// Copyright (c) 2025 Nikolai Papin // // This file is part of Easywish // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . package services import ( "easywish/internal/database" errs "easywish/internal/errors" "easywish/internal/models" "easywish/internal/utils" "easywish/internal/utils/enums" "go.uber.org/zap" ) type AuthService interface { RegistrationBegin(request models.RegistrationBeginRequest) (bool, error) RegistrationComplete(request models.RegistrationBeginRequest) (*models.RegistrationCompleteResponse, error) Login(request models.LoginRequest) (*models.LoginResponse, error) Refresh(request models.RefreshRequest) (*models.RefreshResponse, error) } type authServiceImpl struct { log *zap.Logger dbctx database.DbContext } func NewAuthService(_log *zap.Logger, _dbctx database.DbContext) AuthService { return &authServiceImpl{log: _log, dbctx: _dbctx} } func (a *authServiceImpl) RegistrationBegin(request models.RegistrationBeginRequest) (bool, error) { var user database.User var generatedCode string helper, db, _ := database.NewDbHelperTransaction(a.dbctx) defer helper.Rollback() var err error if user, err = db.TXQueries.CreateUser(db.CTX, request.Username); err != nil { // TODO: validation a.log.Error("Failed to add user to database", zap.Error(err)) return false, errs.ErrServerError } a.log.Info("Registraion of a new user", zap.String("username", user.Username), zap.Int64("id", user.ID)) if _, err = db.TXQueries.CreateLoginInformation(db.CTX, database.CreateLoginInformationParams{ UserID: user.ID, Email: request.Email, Password: request.Password, // Hashed in database }); err != nil { a.log.Error("Failed to add login information for user to database", zap.Error(err)) return false, errs.ErrServerError } if generatedCode, err = utils.GenerateSecure6DigitNumber(); err != nil { a.log.Error("Failed to generate a registration code", zap.Error(err)) return false, errs.ErrServerError } if _, err = db.TXQueries.CreateConfirmationCode(db.CTX, database.CreateConfirmationCodeParams{ UserID: user.ID, CodeType: int32(enums.RegistrationCodeType), Code: generatedCode, // Hashed in database }); err != nil { a.log.Error("Failed to add registration code to database", zap.Error(err)) return false, errs.ErrServerError } a.log.Info("Registered a new user", zap.String("username", user.Username)) helper.Commit() a.log.Debug("Declated registration code for a new user", zap.String("username", user.Username), zap.String("code", generatedCode)) // TODO: Send verification email return true, nil } func (a *authServiceImpl) RegistrationComplete(request models.RegistrationBeginRequest) (*models.RegistrationCompleteResponse, error) { return nil, errs.ErrNotImplemented } func (a *authServiceImpl) Login(request models.LoginRequest) (*models.LoginResponse, error) { conn, ctx, err := utils.GetDbConn() if err != nil { return nil, err } defer conn.Close(ctx) queries := database.New(conn) user, err := queries.GetUserByLoginCredentials(ctx, database.GetUserByLoginCredentialsParams{ Username: request.Username, Password: request.Password, }) if err != nil { return nil, errs.ErrUnauthorized } accessToken, refreshToken, err := utils.GenerateTokens(user.Username) return &models.LoginResponse{Tokens: models.Tokens{AccessToken: accessToken, RefreshToken: refreshToken}}, nil } func (a *authServiceImpl) Refresh(request models.RefreshRequest) (*models.RefreshResponse, error) { return nil, errs.ErrNotImplemented }