|
|
|
@ -1,7 +1,6 @@
|
|
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"net/http"
|
|
|
|
@ -9,14 +8,12 @@ import (
|
|
|
|
|
|
|
|
|
|
"git.vdhsn.com/adam/bodytrack/internal/services"
|
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
|
"github.com/go-chi/jwtauth/v5"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ApiHandler interface {
|
|
|
|
|
Subscribe(chi.Router) error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type UserHandler struct {
|
|
|
|
|
Conn services.DB
|
|
|
|
|
Conn services.DB
|
|
|
|
|
JWTSessionDuration time.Duration
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u UserHandler) Subscribe(c chi.Router) error {
|
|
|
|
@ -24,17 +21,90 @@ func (u UserHandler) Subscribe(c chi.Router) error {
|
|
|
|
|
// c.PUT("/user", u.register)
|
|
|
|
|
|
|
|
|
|
c.Group(func(r chi.Router) {
|
|
|
|
|
r.Use(services.JWTVerifier)
|
|
|
|
|
|
|
|
|
|
// r.Get("/user", u.getProfile)
|
|
|
|
|
// r.Post("/user", u.updateProfile)
|
|
|
|
|
r.Use(services.JWTVerifier)
|
|
|
|
|
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"`
|
|
|
|
@ -46,7 +116,7 @@ func (u UserHandler) login(res http.ResponseWriter, req *http.Request) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fail := APIResp{Payload: "Email or password incorrect"}
|
|
|
|
|
fail := APIResp{Payload: "Email or password incorrect", Status: http.StatusUnauthorized}
|
|
|
|
|
|
|
|
|
|
if lr.Email == "" || lr.Password == "" {
|
|
|
|
|
fail.Write(res)
|
|
|
|
@ -61,13 +131,18 @@ func (u UserHandler) login(res http.ResponseWriter, req *http.Request) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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: "user-auth",
|
|
|
|
|
Name: "jwt",
|
|
|
|
|
Value: token,
|
|
|
|
|
Expires: time.Now().Add(time.Hour * 24 * 10),
|
|
|
|
|
Expires: time.Now().Add(duration),
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
APIResp{
|
|
|
|
@ -82,28 +157,3 @@ func (u UserHandler) login(res http.ResponseWriter, req *http.Request) {
|
|
|
|
|
|
|
|
|
|
fail.Write(res)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type APIResp struct {
|
|
|
|
|
Success bool `json:"success"`
|
|
|
|
|
Payload interface{} `json:"payload"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a APIResp) Write(res http.ResponseWriter) {
|
|
|
|
|
res.Header().Set("Content-Type", "application/json; utf-8")
|
|
|
|
|
enc := json.NewEncoder(res)
|
|
|
|
|
enc.SetIndent("\n", "\t")
|
|
|
|
|
enc.Encode(a)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ParseCall(model interface{}, res http.ResponseWriter, req *http.Request) error {
|
|
|
|
|
defer req.Body.Close()
|
|
|
|
|
decoder := json.NewDecoder(req.Body)
|
|
|
|
|
decoder.DisallowUnknownFields()
|
|
|
|
|
if err := decoder.Decode(&model); err != nil {
|
|
|
|
|
a := APIResp{Success: false, Payload: err.Error()}
|
|
|
|
|
a.Write(res)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|