Files
user-system/internal/service/auth_capabilities.go

100 lines
2.7 KiB
Go

package service
import (
"context"
"errors"
"log"
"github.com/user-management-system/internal/auth"
"github.com/user-management-system/internal/domain"
"gorm.io/gorm"
)
const adminRoleCode = "admin"
type AuthCapabilities struct {
Password bool `json:"password"`
EmailActivation bool `json:"email_activation"`
EmailCode bool `json:"email_code"`
SMSCode bool `json:"sms_code"`
PasswordReset bool `json:"password_reset"`
AdminBootstrapRequired bool `json:"admin_bootstrap_required"`
OAuthProviders []auth.OAuthProviderInfo `json:"oauth_providers"`
}
func (s *AuthService) SupportsEmailActivation() bool {
return s != nil && s.emailActivationSvc != nil
}
func (s *AuthService) SupportsEmailCodeLogin() bool {
return s != nil && s.emailCodeSvc != nil
}
func (s *AuthService) SupportsSMSCodeLogin() bool {
return s != nil && s.smsCodeSvc != nil
}
func (s *AuthService) GetAuthCapabilities(ctx context.Context) AuthCapabilities {
if ctx == nil {
ctx = context.Background()
}
return AuthCapabilities{
Password: true,
EmailActivation: s.SupportsEmailActivation(),
EmailCode: s.SupportsEmailCodeLogin(),
SMSCode: s.SupportsSMSCodeLogin(),
AdminBootstrapRequired: s.IsAdminBootstrapRequired(ctx),
OAuthProviders: s.GetEnabledOAuthProviders(),
}
}
func (s *AuthService) IsAdminBootstrapRequired(ctx context.Context) bool {
if s == nil || s.userRepo == nil || s.roleRepo == nil || s.userRoleRepo == nil {
return false
}
if ctx == nil {
ctx = context.Background()
}
adminRole, err := s.roleRepo.GetByCode(ctx, adminRoleCode)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return true
}
log.Printf("auth: resolve auth capabilities failed while loading admin role: %v", err)
return false
}
userIDs, err := s.userRoleRepo.GetUserIDByRoleID(ctx, adminRole.ID)
if err != nil {
log.Printf("auth: resolve auth capabilities failed while loading admin users: role_id=%d err=%v", adminRole.ID, err)
return false
}
if len(userIDs) == 0 {
return true
}
hadUnexpectedLookupError := false
for _, userID := range userIDs {
user, err := s.userRepo.GetByID(ctx, userID)
if err != nil {
if isUserNotFoundError(err) {
continue
}
hadUnexpectedLookupError = true
log.Printf("auth: resolve auth capabilities failed while loading admin user: user_id=%d err=%v", userID, err)
continue
}
if user != nil && user.Status == domain.UserStatusActive {
return false
}
}
if hadUnexpectedLookupError {
return false
}
return true
}