160 lines
3.3 KiB
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)
|
|
}
|