package auth import ( "errors" "github.com/google/uuid" log "github.com/sirupsen/logrus" "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.newSession(userUuid) } func (s *Service) Refresh(refreshUuid string) (shared.AuthData, error) { var err error tokenData, err := s.repo.readRefreshToken(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 time.Now().After(tokenData.Expires) { _ = s.repo.invalidateRefreshToken(refreshUuid) return shared.AuthData{}, errors.New("token expired") } err = s.repo.invalidateRefreshToken(refreshUuid) if err != nil { return shared.AuthData{}, err } return s.updateSession(tokenData.UserUuid, tokenData.SessionUuid) } func (s *Service) Logout(refreshUuid string) error { return s.repo.invalidateRefreshToken(refreshUuid) } func (s *Service) newSession(userUuid string) (shared.AuthData, error) { newSession := uuid.NewString() log.WithFields(log.Fields{ "user uuid": userUuid, "new session uuid": newSession, }).Debug("Auth provider | New session") return s.createSession(userUuid, newSession) } func (s *Service) updateSession(userUuid, sessionUuid string) (shared.AuthData, error) { log.WithFields(log.Fields{ "user uuid": userUuid, "current session uuid": sessionUuid, }).Debug("Auth provider | Refresh session") return s.createSession(userUuid, sessionUuid) } func (s *Service) createSession(userUuid, sessionUuid string) (shared.AuthData, error) { accessToken, err := s.jwtProvider.CreateAccessToken(userUuid, sessionUuid) if err != nil { return shared.AuthData{}, err } refreshUuid := uuid.NewString() expires := time.Now().UTC().Add(s.jwtProvider.RefreshExpires()) refreshCookie := s.jwtProvider.CreateRefreshToken(refreshUuid, expires) err = s.repo.createRefreshToken(&Session{ Expires: expires, UserUuid: userUuid, RefreshUuid: refreshUuid, SessionUuid: sessionUuid, }) return shared.AuthData{ AccessToken: accessToken, RefreshCookie: refreshCookie, }, nil } func (s *Service) GetCurrentSession(sessionUuid string) (shared.CurrentSession, error) { cs, err := s.repo.getCurrentSession(sessionUuid) if err != nil { return shared.CurrentSession{}, err } resp := shared.CurrentSession{ Uuid: cs.SessionUuid, Expires: cs.Expires, } return resp, nil }