This commit is contained in:
2025-11-12 09:41:52 +03:00
commit 2a8566712a
44 changed files with 2602 additions and 0 deletions

150
internal/server/auth.go Normal file
View File

@@ -0,0 +1,150 @@
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(&registerDto); 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)
}