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) }