All checks were successful
ci/woodpecker/push/build Pipeline was successful
Signed-off-by: Nikolai Rodionov <allanger@badhouseplants.net>
104 lines
2.6 KiB
Go
104 lines
2.6 KiB
Go
package controllers
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"time"
|
|
|
|
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/hash"
|
|
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/logger"
|
|
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/repository"
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
var (
|
|
ErrEmailUsed = errors.New("email is already used")
|
|
ErrUserNotFound = errors.New("user not found")
|
|
ErrWrongPassword = errors.New("wrong password")
|
|
)
|
|
|
|
type AccountController struct {
|
|
DB *sql.DB
|
|
Redis *redis.Client
|
|
DevMode bool
|
|
HashCost int16
|
|
AccessTokenTTL time.Duration
|
|
RefreshTokenTTL time.Duration
|
|
JWTSecret []byte
|
|
}
|
|
|
|
type JWT struct {
|
|
RefreshToken string
|
|
AccessToken string
|
|
}
|
|
|
|
type AccountParams struct{}
|
|
|
|
type AccountData struct {
|
|
Password string
|
|
Email string
|
|
UUID string
|
|
}
|
|
|
|
// Create a new account
|
|
func (c *AccountController) Create(ctx context.Context, data *AccountData) (string, error) {
|
|
log := logger.FromContext(ctx).WithValues("email", data.Email)
|
|
log.V(2).Info("Creating a user")
|
|
data.UUID = uuid.New().String()
|
|
|
|
passwordHash, err := hash.HashPassword(data.Password, int(c.HashCost))
|
|
if err != nil {
|
|
log.Error(err, "Couldn't crate the password hash")
|
|
return "", ErrServerError
|
|
}
|
|
|
|
queryData := &repository.AccountData{
|
|
UUID: data.UUID,
|
|
Email: data.Email,
|
|
PasswordHash: passwordHash,
|
|
}
|
|
|
|
if err := repository.CreateAccount(ctx, c.DB, queryData); err != nil {
|
|
if errors.Is(err, repository.ErrAlreadyExists) {
|
|
return "", ErrEmailUsed
|
|
}
|
|
log.Error(err, "Couldn't create a user")
|
|
return "", ErrServerError
|
|
}
|
|
|
|
return data.UUID, nil
|
|
}
|
|
|
|
// Login into an existing account (check password and email)
|
|
func (c *AccountController) Login(ctx context.Context, email, password string) (string, error) {
|
|
log := logger.FromContext(ctx).WithValues("email", email)
|
|
log.V(2).Info("Trying to verify user login")
|
|
|
|
passwordHash, err := repository.GetPasswordHashForEmail(ctx, c.DB, email)
|
|
if err != nil {
|
|
if errors.Is(err, repository.ErrNotFound) {
|
|
return "", ErrUserNotFound
|
|
}
|
|
log.Error(err, "Couldn't get the password hash")
|
|
return "", ErrServerError
|
|
}
|
|
|
|
if err := hash.CheckPasswordHash(password, passwordHash); err != nil {
|
|
return "", ErrWrongPassword
|
|
}
|
|
|
|
uuid, err := repository.GetUUIDForEmail(ctx, c.DB, email)
|
|
if err != nil {
|
|
if errors.Is(err, repository.ErrNotFound) {
|
|
return "", ErrUserNotFound
|
|
}
|
|
log.Error(err, "Couldn't get tha password hash")
|
|
return "", ErrServerError
|
|
}
|
|
|
|
return uuid, nil
|
|
}
|