bodytrack/api/internal/handlers/users.go

160 lines
3.3 KiB
Go

package handlers
import (
"fmt"
"log"
"net/http"
"time"
"git.vdhsn.com/adam/bodytrack/internal/services"
"github.com/go-chi/chi/v5"
"github.com/go-chi/jwtauth/v5"
)
type UserHandler struct {
Conn services.DB
JWTSessionDuration time.Duration
}
func (u UserHandler) Subscribe(c chi.Router) error {
c.Post("/user/auth", u.login)
// c.PUT("/user", u.register)
c.Group(func(r chi.Router) {
r.Use(services.NewJWTVerifier())
r.Use(jwtauth.Authenticator)
r.Get("/user", u.getProfile)
r.Post("/user", u.updateProfile)
// r.Post("/user/verify", u.verifyEmail)
})
return nil
}
func (u UserHandler) updateProfile(res http.ResponseWriter, req *http.Request) {
fail := APIResp{Payload: "Unauthorized", Status: http.StatusUnauthorized}
userId, err := services.GetUserIDFromClaims(req)
if err != nil {
fail.Write(res)
return
}
type setProfileInput struct {
services.User
Password string `json:"password"`
}
var in setProfileInput
if err := ParseCall(&in, res, req); err != nil {
fail.Payload = "Could not read arguments"
fail.Status = http.StatusUnprocessableEntity
fail.Write(res)
return
}
oUser, err := u.Conn.GetProfileByID(userId)
if err != nil {
log.Println(err)
fail.Write(res)
return
}
if in.Password != "" && !services.PasswordEqual(oUser.PasswordHash, in.Password) {
in.PasswordHash, _ = services.GenerateHashFromPassword(in.Password)
}
update := oUser.Merge(in.User)
if err := u.Conn.UpdateProfile(userId, update); err != nil {
log.Println(err)
fail.Payload = "Could not update profile"
fail.Status = http.StatusOK
fail.Write(res)
return
}
user, err := u.Conn.GetProfileByID(userId)
if err != nil {
log.Println(err)
fail.Write(res)
return
}
APIResp{Success: true, Payload: user}.Write(res)
}
func (u UserHandler) getProfile(res http.ResponseWriter, req *http.Request) {
userId, err := services.GetUserIDFromClaims(req)
fail := APIResp{Payload: "Unauthorized", Status: http.StatusUnauthorized}
if err != nil {
fail.Write(res)
return
}
user, err := u.Conn.GetProfileByID(userId)
if err != nil {
log.Println(err)
fail.Write(res)
return
}
APIResp{Success: true, Payload: user}.Write(res)
}
func (u UserHandler) login(res http.ResponseWriter, req *http.Request) {
type loginRequest struct {
Email string `json:"email"`
Password string `json:"password"`
}
var lr loginRequest
if err := ParseCall(&lr, res, req); err != nil {
return
}
fail := APIResp{Payload: "Email or password incorrect", Status: http.StatusUnauthorized}
if lr.Email == "" || lr.Password == "" {
fail.Write(res)
return
}
profile, err := u.Conn.GetProfileByEmail(lr.Email)
if err != nil {
log.Println(err)
fail.Write(res)
return
}
if services.PasswordEqual(profile.PasswordHash, lr.Password) {
duration := u.JWTSessionDuration
if duration == 0 {
duration = time.Hour * 24 * 10
}
token := services.GenerateJWT(profile)
res.Header().Set("Authorization", fmt.Sprintf("Bearer %s", token))
http.SetCookie(res, &http.Cookie{
Name: "jwt",
Value: token,
Path: "/v1/api/",
Expires: time.Now().Add(duration),
})
APIResp{
Success: true,
Payload: struct {
Profile services.User `json:"profile"`
Token string `json:"token"`
}{Profile: profile, Token: token},
}.Write(res)
return
}
fail.Write(res)
}