package auth import ( "errors" "github.com/google/uuid" "gorm.io/gorm" "merch-parser-api/internal/interfaces" "merch-parser-api/internal/shared" "time" ) type Service struct { repo Repository jwtProvider interfaces.JWTProvider } func newService(repo Repository, jwtProvider interfaces.JWTProvider) *Service { return &Service{ repo: repo, jwtProvider: jwtProvider, } } func (s *Service) Login(userUuid string) (shared.AuthData, error) { return s.generateTokens(userUuid) } func (s *Service) Refresh(userUuid string, refreshUuid string) (shared.AuthData, error) { var err error tokenData, err := s.repo.ReadRefreshToken(userUuid, refreshUuid) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return shared.AuthData{}, errors.New("refresh token is not valid or doesn't exist") } return shared.AuthData{}, err } if tokenData.Expires < time.Now().UTC().Unix() { return shared.AuthData{}, errors.New("token expired") } err = s.repo.InvalidateRefreshToken(userUuid, refreshUuid) if err != nil { return shared.AuthData{}, err } return s.generateTokens(userUuid) } func (s *Service) Logout(userUuid string, refreshUuid string) error { return s.repo.InvalidateRefreshToken(userUuid, refreshUuid) } func (s *Service) generateTokens(userUuid string) (shared.AuthData, error) { accessToken, err := s.jwtProvider.CreateAccessToken(userUuid) if err != nil { return shared.AuthData{}, err } refreshTokenUuid := uuid.NewString() refreshToken, exp, err := s.jwtProvider.CreateRefreshToken(userUuid, refreshTokenUuid) if err != nil { return shared.AuthData{}, err } err = s.repo.CreateRefreshToken(&RefreshToken{ Expires: exp, UserUuid: userUuid, TokenUuid: refreshTokenUuid, }) return shared.AuthData{ AccessToken: accessToken, RefreshToken: refreshToken, }, nil }