feat: add challenge to auth service

This commit is contained in:
2025-09-06 17:04:17 +03:30
parent 7e471fd8d9
commit 723d883bc2
7 changed files with 165 additions and 19 deletions
+13
View File
@@ -26,3 +26,16 @@ type UserSession struct {
UpdatedAt time.Time
DeletedAt *time.Time
}
func NewSession(userID, walletID uuid.UUID, ipAddress, agent string, expiresAt time.Time) *UserSession {
return &UserSession{
ID: uuid.New(),
UserID: userID,
WalletID: walletID,
IPaddress: ipAddress,
Agent: agent,
ExpiresAt: expiresAt,
CreatedAt: time.Now().UTC(),
UpdatedAt: time.Now().UTC(),
}
}
+69 -3
View File
@@ -1,12 +1,26 @@
package domain
import (
"backend/pkg/validate/national"
"backend/pkg/validate/phone"
"context"
"errors"
"time"
"net/mail"
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
)
var (
ErrPhoneInvalid = errors.New("phone number is invalid")
ErrUserNotFound = errors.New("user not found")
ErrNationalIDInvalid = errors.New("national ID is invalid")
ErrWalletInvalid = errors.New("wallet address is invalid")
ErrEmailInvalid = errors.New("email is invalid")
)
type UserRepo interface {
Create(ctx context.Context, user *User) error
GetByID(ctx context.Context, id uuid.UUID) (*User, error)
@@ -16,14 +30,66 @@ type UserRepo interface {
}
type User struct {
ID uuid.UUID
PubKey string
Name string
ID uuid.UUID
PubKey string
Name string
//TODO: add Kyc Embedded struct
//TODO: add NFT Embedded struct
LastName string
PhoneNumber string
Email *string
NationalID string
BirthDate *time.Time
LastLogin *time.Time
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
type Challenge struct {
Message uuid.UUID
TimeStamp time.Time
ExpiresAt time.Time
}
func NewUser(pubKey, name, lastName, phoneNumber, email, nationalID string) (*User, error) {
_, err := phone.IsValid(phoneNumber)
if err != nil {
return nil, ErrPhoneInvalid
}
_, err = national.IsValid(nationalID)
if err != nil {
return nil, ErrNationalIDInvalid
}
if !common.IsHexAddress(pubKey) {
return nil, ErrWalletInvalid
}
return &User{
ID: uuid.New(),
PubKey: pubKey,
Name: name,
LastName: lastName,
PhoneNumber: phoneNumber,
NationalID: nationalID,
CreatedAt: time.Now().UTC(),
UpdatedAt: time.Now().UTC(),
}, nil
}
func (u *User) UpdateLastLogin() {
now := time.Now().UTC()
u.LastLogin = &now
u.UpdatedAt = now
}
func (u *User) UpdateInfo(email string) {
addr, err := mail.ParseAddress(email)
if err == nil {
u.Email = &addr.Address
}
u.UpdatedAt = time.Now().UTC()
}
View File
+15 -2
View File
@@ -2,14 +2,21 @@ package types
import (
"backend/internal/domain"
"time"
)
type User struct {
Base
Name string
LastName string
PubKey string
Name string
LastName string
//TODO: add Kyc Embedded struct
//TODO: add NFT Embedded struct
Phone string
NationalID string
LastLogin *time.Time
Email *string
BirthDate *time.Time
}
func CastUserToStorage(u domain.User) *User {
@@ -24,6 +31,9 @@ func CastUserToStorage(u domain.User) *User {
LastName: u.LastName,
Phone: u.PhoneNumber,
NationalID: u.NationalID,
Email: u.Email,
BirthDate: u.BirthDate,
LastLogin: u.LastLogin,
}
}
@@ -34,6 +44,9 @@ func CastUserToDomain(u User) *domain.User {
LastName: u.LastName,
PhoneNumber: u.Phone,
NationalID: u.NationalID,
Email: u.Email,
BirthDate: u.BirthDate,
LastLogin: u.LastLogin,
CreatedAt: u.CreatedAt,
UpdatedAt: u.UpdatedAt,
DeletedAt: u.DeletedAt,
+48
View File
@@ -1 +1,49 @@
package usecase
import (
"backend/internal/domain"
"context"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
)
type AuthService interface {
GenerateChallenge(ctx context.Context, pubKey string) (*domain.Challenge, error)
}
type authService struct {
userRepo *domain.UserRepo
sessionRepo *domain.SessionRepo
challengeExp uint
tokenExp uint
refreshTokenExp uint
}
func NewAuthService(
userRepo *domain.UserRepo,
sessionRepo *domain.SessionRepo,
challengeExp uint,
tokenExp uint,
refreshTokenExp uint) AuthService {
return &authService{
userRepo: userRepo,
sessionRepo: sessionRepo,
challengeExp: challengeExp,
tokenExp: tokenExp,
refreshTokenExp: refreshTokenExp,
}
}
func (s *authService) GenerateChallenge(ctx context.Context, pubKey string) (*domain.Challenge, error) {
if !common.IsHexAddress(pubKey) {
return nil, domain.ErrWalletInvalid
}
challenge := &domain.Challenge{
Message: uuid.New(),
TimeStamp: time.Now().UTC(),
ExpiresAt: time.Now().Add(time.Duration(s.challengeExp) * time.Minute),
}
return challenge, nil
}