package server import ( "errors" "fmt" "github.com/go-playground/validator/v10" "github.com/goccy/go-json" "madsky.ru/go-tracker/internal/model/auth" "madsky.ru/go-tracker/internal/model/user" "madsky.ru/go-tracker/internal/server/helpers" "madsky.ru/go-tracker/internal/server/response" "net/http" "strings" "time" ) const TTL = 12 var validate *validator.Validate func (app *Application) login(w http.ResponseWriter, r *http.Request) { dec := json.NewDecoder(r.Body) dec.DisallowUnknownFields() var loginDto auth.LoginDTO if err := dec.Decode(&loginDto); err != nil { response.Error(w, err, http.StatusBadRequest) return } validate = validator.New(validator.WithRequiredStructEnabled()) err := validate.Struct(loginDto) if err != nil { var validateErrs validator.ValidationErrors errorsMessages := make([]string, 0) if errors.As(err, &validateErrs) { for _, e := range validateErrs { errorsMessages = append(errorsMessages, fmt.Sprintf("%s is %s", e.Field(), e.Tag())) } } response.Error(w, errors.New(strings.Join(errorsMessages, ",")), http.StatusBadRequest) return } u, err := app.Storage.User.FindByEmail(app.Ctx, loginDto.Email) if err != nil { response.Error(w, errors.New("user does not exist"), http.StatusBadRequest) return } if !helpers.VerifyHashString(loginDto.Password, u.PasswordHash) { response.Error(w, errors.New("wrong password"), http.StatusBadRequest) return } expires := time.Now().Add(time.Hour * TTL) token, err := helpers.CreateToken(u.ID, u.Role, expires) if err != nil { response.Error(w, err, http.StatusInternalServerError) return } data := make(map[string]string) data["token"] = token data["exp"] = expires.UTC().Format(time.RFC3339) cookie := &http.Cookie{ Name: "token", Path: "/", Value: token, Expires: expires, HttpOnly: true, } http.SetCookie(w, cookie) response.WriteJSON(w, nil, http.StatusCreated, data) } func (app *Application) register(w http.ResponseWriter, r *http.Request) { dec := json.NewDecoder(r.Body) dec.DisallowUnknownFields() var registerDto auth.RegisterDTO if err := dec.Decode(®isterDto); err != nil { response.Error(w, err, http.StatusBadRequest) return } validate = validator.New(validator.WithRequiredStructEnabled()) err := validate.Struct(registerDto) if err != nil { var validateErrs validator.ValidationErrors errorsMessages := make([]string, 0) if errors.As(err, &validateErrs) { for _, e := range validateErrs { errorsMessages = append(errorsMessages, fmt.Sprintf("%s is %s", e.Field(), e.Tag())) } } response.Error(w, errors.New(strings.Join(errorsMessages, ",")), http.StatusBadRequest) return } isEmpty, err := app.Storage.User.IsEmpty(app.Ctx) if err != nil { response.Error(w, err, http.StatusBadRequest) return } var newUser user.User passwordHash, err := helpers.CreateHashString(registerDto.Password) if err != nil { response.Error(w, err, http.StatusBadRequest) return } newUser.Email = registerDto.Email newUser.Name = registerDto.Name newUser.PasswordHash = passwordHash if isEmpty { newUser.Role = "admin" } else { newUser.Role = "user" } res, err := app.Storage.User.Create(app.Ctx, &newUser) if err != nil { response.Error(w, err, http.StatusBadRequest) return } response.WriteJSON(w, nil, http.StatusOK, response.ToUserResponseDto(res)) } func (app *Application) logout(w http.ResponseWriter, _ *http.Request) { cookie := &http.Cookie{ Name: "token", Value: "", Path: "/", MaxAge: -1, } http.SetCookie(w, cookie) response.WriteJSON(w, nil, http.StatusCreated, 1) }