Added repo for dealing with DB and Hashing password to register/login endpoints

This commit is contained in:
2025-10-21 18:45:07 +02:00
parent 8469bd3f33
commit 748459c788
7 changed files with 111 additions and 18 deletions

View File

@@ -0,0 +1,10 @@
package repository
import entity "git.ego.freeddns.org/egommerce/api-entities/identity/entity"
type UserRepositoryInterface interface {
GetByID(id string) (*entity.User, error)
Create(user *entity.User) (*entity.User, error)
Update(user *entity.User) (*entity.User, error)
Delete(id int64) (bool, error)
}

View File

@@ -0,0 +1,47 @@
package repository
import (
"context"
"errors"
entity "git.ego.freeddns.org/egommerce/api-entities/identity/entity"
db "git.ego.freeddns.org/egommerce/go-api-pkg/database"
"github.com/jackc/pgx/v5/pgxpool"
)
type UserRepository struct {
db *pgxpool.Pool
}
func NewUserRepository(db *pgxpool.Pool) *UserRepository {
return &UserRepository{db}
}
func (r *UserRepository) GetByID(id string) (*entity.User, error) {
return &entity.User{}, nil
}
func (r *UserRepository) Create(user *entity.User) (string, error) {
var id string
sql := `INSERT INTO identity.users(email, username, password) VALUES($1, $2, $3) LIMIT 1 RETURNING id`
err := r.db.QueryRow(context.Background(), sql, user.Email, user.Username, user.Password).Scan(&id)
if err != nil {
if err = db.IsDuplicatedRow(err); err != nil {
return "", errors.New("username/email is already taken")
}
return "", errors.New("db error: " + err.Error())
}
return id, nil
}
func (r *UserRepository) Update(user *entity.User) (*entity.User, error) {
return &entity.User{}, nil
}
func (r *UserRepository) Delete(id int64) (bool, error) {
return true, nil
}

View File

@@ -2,6 +2,8 @@ package server
import (
dto "git.ego.freeddns.org/egommerce/api-entities/identity/dto"
domain "git.ego.freeddns.org/egommerce/identity-service/domain/repository"
"git.ego.freeddns.org/egommerce/identity-service/internal/service"
"github.com/gofiber/fiber/v2"
@@ -13,7 +15,8 @@ func (s *Server) LoginHandlerFn(c *fiber.Ctx) error {
return s.Error(c, fiber.StatusBadRequest, "Error parsing input")
}
authSrv := service.NewAuthService(s.GetDatabase(), s.GetCache())
repo := domain.NewUserRepository(s.GetDatabase())
authSrv := service.NewAuthService(repo, s.GetDatabase(), s.GetCache())
token, err := authSrv.Login(data.Username, data.Password)
if err != nil {

View File

@@ -2,6 +2,7 @@ package server
import (
dto "git.ego.freeddns.org/egommerce/api-entities/identity/dto"
domain "git.ego.freeddns.org/egommerce/identity-service/domain/repository"
"git.ego.freeddns.org/egommerce/identity-service/internal/service"
"github.com/gofiber/fiber/v2"
@@ -13,7 +14,8 @@ func (s *Server) RefreshHandlerFn(c *fiber.Ctx) error {
return s.Error(c, fiber.StatusBadRequest, "Error parsing input")
}
authSrv := service.NewAuthService(s.GetDatabase(), s.GetCache())
repo := domain.NewUserRepository(s.GetDatabase())
authSrv := service.NewAuthService(repo, s.GetDatabase(), s.GetCache())
token, err := authSrv.RefreshToken(data.AccessToken)
if err != nil {

View File

@@ -2,6 +2,7 @@ package server
import (
dto "git.ego.freeddns.org/egommerce/api-entities/identity/dto"
domain "git.ego.freeddns.org/egommerce/identity-service/domain/repository"
"git.ego.freeddns.org/egommerce/identity-service/internal/service"
"github.com/gofiber/fiber/v2"
@@ -13,7 +14,8 @@ func (s *Server) RegisterHandlerFn(c *fiber.Ctx) error {
return s.Error(c, fiber.StatusBadRequest, "Error parsing input")
}
authSrv := service.NewAuthService(s.GetDatabase(), s.GetCache())
repo := domain.NewUserRepository(s.GetDatabase())
authSrv := service.NewAuthService(repo, s.GetDatabase(), s.GetCache())
id, err := authSrv.Register(data.Email, data.Username, data.Password)
if err != nil {

View File

@@ -5,14 +5,15 @@ import (
"errors"
"fmt"
db "git.ego.freeddns.org/egommerce/identity-service/pkg/database"
entity "git.ego.freeddns.org/egommerce/api-entities/identity/entity"
domain "git.ego.freeddns.org/egommerce/identity-service/domain/repository"
"github.com/go-redis/redis/v8"
"github.com/jackc/pgx/v5/pgxpool"
)
var (
AuthService *Auth
passSrv *PaswordService
ErrLoginIncorrect = errors.New("login incorrect")
ErrUnableToCacheToken = errors.New("unable to save token in cache")
@@ -20,33 +21,40 @@ var (
)
func init() {
passSrv = NewPasswordService()
}
type Auth struct {
repo *domain.UserRepository
db *pgxpool.Pool
cache *redis.Client
}
func NewAuthService(db *pgxpool.Pool, cache *redis.Client) *Auth {
func NewAuthService(repo *domain.UserRepository, db *pgxpool.Pool, cache *redis.Client) *Auth {
return &Auth{
repo: repo,
db: db,
cache: cache,
}
}
func (a *Auth) Login(login, passwd string) (string, error) {
var id string
var id, hashedPasswd string
sql := `SELECT id FROM identity.users WHERE username=$1 AND password=$2 LIMIT 1`
err := a.db.QueryRow(context.Background(), sql, login, passwd).Scan(&id)
sql := `SELECT id, password FROM identity.users WHERE username=$1 LIMIT 1`
err := a.db.QueryRow(context.Background(), sql, login).Scan(&id, &hashedPasswd)
if err != nil {
// if err = db.NoRowsInQuerySet(err); err != nil { // FIXME NoRowsInQuerySet error detect
// if err = database.NoRowsInQuerySet(err); err != nil {
// return "", errors.New("no user found")
// }
return "", ErrLoginIncorrect
}
if err = passSrv.Verify(passwd, hashedPasswd); err != nil {
return "", ErrLoginIncorrect
}
accessToken, _ := jwtSrv.CreateAccessToken(id)
refreshToken, _ := jwtSrv.CreateRefreshToken(id)
if err = a.saveTokensToCache(id, accessToken, refreshToken); err != nil {
@@ -74,16 +82,15 @@ func (a *Auth) RefreshToken(accessToken string) (string, error) {
}
func (a *Auth) Register(email, login, passwd string) (string, error) {
var id string
passwd, _ = passSrv.Hash(passwd)
sql := `INSERT INTO identity.users(email, username, password) VALUES($1, $2, $3) LIMIT 1 RETURNING id`
err := a.db.QueryRow(context.Background(), sql, email, login, passwd).Scan(&id)
id, err := a.repo.Create(&entity.User{
Email: email,
Username: login,
Password: passwd,
})
if err != nil {
if err = db.IsDuplicatedRow(err); err != nil {
return "", errors.New("username/email is already taken")
}
return "", errors.New("Failed to create new user: " + err.Error())
return "", err
}
return id, nil

View File

@@ -0,0 +1,22 @@
package service
import "golang.org/x/crypto/bcrypt"
type PaswordService struct{}
func NewPasswordService() *PaswordService {
return &PaswordService{}
}
func (p *PaswordService) Hash(pass string) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hash), nil
}
func (p *PaswordService) Verify(pass, hashedPass string) error {
return bcrypt.CompareHashAndPassword([]byte(hashedPass), []byte(pass))
}