package authsvc import ( "context" "errors" "time" "github.com/panelhosting/panel/internal/auth" "github.com/panelhosting/panel/internal/models" "github.com/panelhosting/panel/internal/repository" ) type Service struct { users *repository.UserRepository sessions *repository.SessionRepository ttl time.Duration } func NewService(users *repository.UserRepository, sessions *repository.SessionRepository, ttlHours int) *Service { return &Service{ users: users, sessions: sessions, ttl: time.Duration(ttlHours) * time.Hour, } } type LoginInput struct { Username string Password string IP string UserAgent string } type LoginResult struct { Token string User *models.User } func (s *Service) Login(ctx context.Context, in LoginInput) (*LoginResult, error) { user, err := s.users.GetByUsername(ctx, in.Username) if err != nil { if errors.Is(err, repository.ErrUserNotFound) { return nil, auth.ErrInvalidCredentials } return nil, err } if user.Status != models.UserStatusActive { return nil, auth.ErrInvalidCredentials } if err := auth.CheckPassword(user.PasswordHash, in.Password); err != nil { return nil, auth.ErrInvalidCredentials } raw, hash, err := auth.NewSessionToken() if err != nil { return nil, err } expires := time.Now().Add(s.ttl) if err := s.sessions.Create(ctx, user.ID, hash, in.IP, in.UserAgent, expires); err != nil { return nil, err } _ = s.users.UpdateLastLogin(ctx, user.ID) user.PasswordHash = "" return &LoginResult{Token: raw, User: user}, nil } func (s *Service) Logout(ctx context.Context, token string) error { if token == "" { return nil } return s.sessions.DeleteByToken(ctx, auth.HashToken(token)) } func (s *Service) UserByToken(ctx context.Context, token string) (*models.User, error) { if token == "" { return nil, repository.ErrUserNotFound } userID, err := s.sessions.GetUserIDByToken(ctx, auth.HashToken(token)) if err != nil { return nil, err } user, err := s.users.GetByID(ctx, userID) if err != nil { return nil, err } if user.Status != models.UserStatusActive { return nil, repository.ErrUserNotFound } user.PasswordHash = "" return user, nil } func (s *Service) IsAdmin(user *models.User) bool { return user.Role == models.RoleSuperAdmin || user.Role == models.RoleAdmin }