Documentation
¶
Index ¶
- Variables
- func SMTPConfigFromIntegrationMeta() map[string]string
- type AcceptInvitationWithRefreshTokenInput
- type AcceptInvitationWithRefreshTokenResult
- type AuthService
- func (s *AuthService) AcceptInvitationWithRefreshToken(ctx context.Context, input AcceptInvitationWithRefreshTokenInput) (*AcceptInvitationWithRefreshTokenResult, error)
- func (s *AuthService) ChangePassword(ctx context.Context, userID string, input ChangePasswordInput) error
- func (s *AuthService) CreateFirstTeam(ctx context.Context, input CreateFirstTeamInput) (*CreateFirstTeamResult, error)
- func (s *AuthService) ExchangeToken(ctx context.Context, input ExchangeTokenInput) (*ExchangeTokenResult, error)
- func (s *AuthService) ForgotPassword(ctx context.Context, input ForgotPasswordInput) (*ForgotPasswordResult, error)
- func (s *AuthService) GenerateWSToken(ctx context.Context, userID, tenantID string) (string, error)
- func (s *AuthService) Login(ctx context.Context, input LoginInput) (*LoginResult, error)
- func (s *AuthService) Logout(ctx context.Context, sessionID string) error
- func (s *AuthService) RefreshToken(ctx context.Context, input RefreshTokenInput) (*RefreshTokenResult, error)
- func (s *AuthService) Register(ctx context.Context, input RegisterInput) (*RegisterResult, error)
- func (s *AuthService) ResetPassword(ctx context.Context, input ResetPasswordInput) error
- func (s *AuthService) SetRoleService(roleService *accesscontrol.RoleService)
- func (s *AuthService) SetSMTPChecker(checker SMTPAvailabilityCheck)
- func (s *AuthService) ValidateAccessToken(tokenString string) (*jwt.Claims, error)
- func (s *AuthService) VerifyEmail(ctx context.Context, token string) error
- type AuthorizationURLInput
- type AuthorizationURLResult
- type CallbackInput
- type CallbackResult
- type ChangePasswordInput
- type CreateFirstTeamInput
- type CreateFirstTeamResult
- type CreateProviderInput
- type EmailService
- func (s *EmailService) HasSystemSMTP() bool
- func (s *EmailService) HasTenantSMTP(ctx context.Context, tenantID string) bool
- func (s *EmailService) IsConfigured() bool
- func (s *EmailService) SendMemberReactivatedEmail(ctx context.Context, ...) error
- func (s *EmailService) SendMemberSuspendedEmail(ctx context.Context, ...) error
- func (s *EmailService) SendPasswordChangedEmail(ctx context.Context, userEmail, userName, ipAddress string) error
- func (s *EmailService) SendPasswordResetEmail(ctx context.Context, userEmail, userName, token string, ...) error
- func (s *EmailService) SendTeamInvitationEmail(ctx context.Context, recipientEmail, inviterName, teamName, token string, ...) error
- func (s *EmailService) SendVerificationEmail(ctx context.Context, userEmail, userName, token string, ...) error
- func (s *EmailService) SendWelcomeEmail(ctx context.Context, userEmail, userName string) error
- func (s *EmailService) SetTenantSMTPResolver(resolver TenantSMTPResolver)
- type ExchangeTokenInput
- type ExchangeTokenResult
- type ForgotPasswordInput
- type ForgotPasswordResult
- type IntegrationSMTPResolver
- type LoginInput
- type LoginResult
- type OAuthProvider
- type OAuthService
- type OAuthUserInfo
- type ProviderInfo
- type RefreshTokenInput
- type RefreshTokenResult
- type RegisterInput
- type RegisterResult
- type ResetPasswordInput
- type SMTPAvailabilityCheck
- type SSOAuthorizeInput
- type SSOAuthorizeResult
- type SSOCallbackInput
- type SSOCallbackResult
- type SSOProviderInfo
- type SSOService
- func (s *SSOService) CreateProvider(ctx context.Context, input CreateProviderInput) (*identityproviderdom.IdentityProvider, error)
- func (s *SSOService) DeleteProvider(ctx context.Context, tenantID, id string) error
- func (s *SSOService) GenerateAuthorizeURL(ctx context.Context, input SSOAuthorizeInput) (*SSOAuthorizeResult, error)
- func (s *SSOService) GetProvider(ctx context.Context, tenantID, id string) (*identityproviderdom.IdentityProvider, error)
- func (s *SSOService) GetProvidersForTenant(ctx context.Context, orgSlug string) ([]SSOProviderInfo, error)
- func (s *SSOService) HandleCallback(ctx context.Context, input SSOCallbackInput) (*SSOCallbackResult, error)
- func (s *SSOService) ListProviders(ctx context.Context, tenantID string) ([]*identityproviderdom.IdentityProvider, error)
- func (s *SSOService) SetTenantMemberRepo(repo TenantMemberCreator)
- func (s *SSOService) UpdateProvider(ctx context.Context, input UpdateProviderInput) (*identityproviderdom.IdentityProvider, error)
- type SSOUserInfo
- type SessionInfo
- type SessionResult
- type SessionService
- func (s *SessionService) CleanupExpiredSessions(ctx context.Context) (int64, int64, error)
- func (s *SessionService) CountActiveSessions(ctx context.Context, userID string) (int, error)
- func (s *SessionService) GetSessionByAccessToken(ctx context.Context, accessToken string) (*sessiondom.Session, error)
- func (s *SessionService) ListUserSessions(ctx context.Context, userID string, currentSessionID string) ([]SessionInfo, error)
- func (s *SessionService) RevokeAllSessions(ctx context.Context, userID, exceptSessionID string) error
- func (s *SessionService) RevokeSession(ctx context.Context, userID, sessionID string) error
- func (s *SessionService) SetPermissionServices(cacheSvc *accesscontrol.PermissionCacheService, ...)
- func (s *SessionService) UpdateSessionActivity(ctx context.Context, sessionID string) error
- func (s *SessionService) ValidateSession(ctx context.Context, sessionID string) (*sessiondom.Session, error)
- type SettingsStorageResolver
- type TenantMemberCreator
- type TenantMembershipInfo
- type TenantMembershipProvider
- type TenantSMTPResolver
- type UpdateProviderInput
- type WSTicketClaims
- type WSTicketService
- type WSTicketStore
Constants ¶
This section is empty.
Variables ¶
var ( ErrOAuthDisabled = errors.New("OAuth is disabled") ErrProviderDisabled = errors.New("OAuth provider is disabled") ErrInvalidProvider = errors.New("invalid OAuth provider") ErrInvalidState = errors.New("invalid OAuth state") ErrOAuthExchangeFailed = errors.New("failed to exchange OAuth code") ErrOAuthUserInfoFailed = errors.New("failed to get user info from OAuth provider") )
OAuth errors.
var ( ErrInvalidCredentials = errors.New("invalid email or password") ErrAccountLocked = errors.New("account is locked due to too many failed attempts") ErrAccountSuspended = errors.New("account is suspended") ErrEmailNotVerified = errors.New("email is not verified") ErrRegistrationDisabled = errors.New("registration is disabled") ErrEmailAlreadyExists = errors.New("email already exists") ErrInvalidResetToken = errors.New("invalid or expired reset token") ErrInvalidVerificationToken = errors.New("invalid or expired verification token") ErrPasswordMismatch = errors.New("current password is incorrect") ErrSessionLimitReached = errors.New("maximum number of active sessions reached") ErrTenantAccessDenied = errors.New("user does not have access to this tenant") ErrTenantRequired = errors.New("tenant_id is required") )
AuthService errors.
var ( ErrSSOTenantNotFound = errors.New("tenant not found") ErrSSONoActiveProviders = errors.New("no active SSO providers for this tenant") ErrSSOProviderNotFound = errors.New("SSO provider not configured for this tenant") ErrSSOProviderInactive = errors.New("SSO provider is not active") ErrSSOInvalidState = errors.New("invalid SSO state token") ErrSSOExchangeFailed = errors.New("failed to exchange authorization code") ErrSSOUserInfoFailed = errors.New("failed to get user info from SSO provider") ErrSSODomainNotAllowed = errors.New("email domain not allowed for this SSO provider") ErrSSODecryptionFailed = errors.New("failed to decrypt client secret") ErrSSOProviderUnsupported = errors.New("unsupported SSO provider type") ErrSSOInvalidRedirectURI = errors.New("invalid redirect URI") ErrSSOInvalidDefaultRole = errors.New("invalid default role") ErrSSONoEmail = errors.New("SSO provider did not return an email address") )
SSO errors.
var ErrTicketNotFound = errors.New("ws ticket not found")
ErrTicketNotFound is returned by RedeemTicket when the ticket is missing, already consumed, or expired. Callers MUST treat all three the same (do not echo distinct error messages to the client — that would be an enumeration oracle).
Functions ¶
func SMTPConfigFromIntegrationMeta ¶
SMTPConfigFromIntegrationMeta extracts SMTP config fields for creating an email integration. Used by the UI when creating/editing an email notification integration.
Types ¶
type AcceptInvitationWithRefreshTokenInput ¶
type AcceptInvitationWithRefreshTokenInput struct {
RefreshToken string `json:"refresh_token" validate:"required"`
InvitationToken string `json:"invitation_token" validate:"required"`
}
AcceptInvitationWithRefreshTokenInput represents the input for accepting an invitation.
type AcceptInvitationWithRefreshTokenResult ¶
type AcceptInvitationWithRefreshTokenResult struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"` // Rotated refresh token
ExpiresAt time.Time `json:"expires_at"`
Tenant TenantMembershipInfo `json:"tenant"`
Role string `json:"role"`
}
AcceptInvitationWithRefreshTokenResult represents the result of accepting an invitation.
type AuthService ¶
type AuthService struct {
// contains filtered or unexported fields
}
AuthService handles authentication operations.
func NewAuthService ¶
func NewAuthService( userRepo userdom.Repository, sessionRepo sessiondom.Repository, refreshTokenRepo sessiondom.RefreshTokenRepository, tenantRepo tenantdom.Repository, auditService *auditapp.AuditService, cfg config.AuthConfig, log *logger.Logger, ) *AuthService
NewAuthService creates a new AuthService.
func (*AuthService) AcceptInvitationWithRefreshToken ¶
func (s *AuthService) AcceptInvitationWithRefreshToken(ctx context.Context, input AcceptInvitationWithRefreshTokenInput) (*AcceptInvitationWithRefreshTokenResult, error)
AcceptInvitationWithRefreshToken accepts an invitation using a refresh token. This endpoint is for users who were invited but don't have a tenant yet, so they only have a refresh token (no access token).
func (*AuthService) ChangePassword ¶
func (s *AuthService) ChangePassword(ctx context.Context, userID string, input ChangePasswordInput) error
ChangePassword changes a user's password (requires authentication).
func (*AuthService) CreateFirstTeam ¶
func (s *AuthService) CreateFirstTeam(ctx context.Context, input CreateFirstTeamInput) (*CreateFirstTeamResult, error)
CreateFirstTeam creates the first team for a user who has no tenants. This endpoint uses refresh_token for authentication since user has no access_token yet.
func (*AuthService) ExchangeToken ¶
func (s *AuthService) ExchangeToken(ctx context.Context, input ExchangeTokenInput) (*ExchangeTokenResult, error)
ExchangeToken exchanges a global refresh token for a tenant-scoped access token. This is the main method for getting access tokens after login.
func (*AuthService) ForgotPassword ¶
func (s *AuthService) ForgotPassword(ctx context.Context, input ForgotPasswordInput) (*ForgotPasswordResult, error)
ForgotPassword initiates a password reset.
func (*AuthService) GenerateWSToken ¶
GenerateWSToken generates a short-lived token for WebSocket authentication. This is needed because WebSocket connections cannot use httpOnly cookies when the connection is cross-origin (different port in development). The token is valid for 30 seconds - just enough time to establish the connection.
func (*AuthService) Login ¶
func (s *AuthService) Login(ctx context.Context, input LoginInput) (*LoginResult, error)
Login authenticates a user and creates a session. Returns a global refresh token and list of tenant memberships. Client should call ExchangeToken to get a tenant-scoped access token.
func (*AuthService) Logout ¶
func (s *AuthService) Logout(ctx context.Context, sessionID string) error
Logout revokes a session.
func (*AuthService) RefreshToken ¶
func (s *AuthService) RefreshToken(ctx context.Context, input RefreshTokenInput) (*RefreshTokenResult, error)
RefreshToken rotates the refresh token and issues new tenant-scoped access token. This implements token rotation for security while providing tenant-scoped access.
func (*AuthService) Register ¶
func (s *AuthService) Register(ctx context.Context, input RegisterInput) (*RegisterResult, error)
Register creates a new local user account. Security note: To prevent email enumeration attacks, this method returns a success result even if the email already exists. The caller should always display a generic "check your email" message regardless of the result.
func (*AuthService) ResetPassword ¶
func (s *AuthService) ResetPassword(ctx context.Context, input ResetPasswordInput) error
ResetPassword resets a user's password using the reset token.
func (*AuthService) SetRoleService ¶
func (s *AuthService) SetRoleService(roleService *accesscontrol.RoleService)
SetRoleService sets the role service for database-driven permissions. When set, the auth service will fetch permissions from the database instead of using hardcoded role-permission mappings.
func (*AuthService) SetSMTPChecker ¶
func (s *AuthService) SetSMTPChecker(checker SMTPAvailabilityCheck)
SetSMTPChecker injects the SMTP availability checker used for smart email verification (auto mode). If not set, the service falls back to the global RequireEmailVerification flag from config.
func (*AuthService) ValidateAccessToken ¶
func (s *AuthService) ValidateAccessToken(tokenString string) (*jwt.Claims, error)
ValidateAccessToken validates an access token and returns the claims.
func (*AuthService) VerifyEmail ¶
func (s *AuthService) VerifyEmail(ctx context.Context, token string) error
VerifyEmail verifies a user's email with the verification token.
type AuthorizationURLInput ¶
type AuthorizationURLInput struct {
Provider OAuthProvider
RedirectURI string // Frontend callback URL
FinalRedirect string // Where to redirect after successful auth
}
AuthorizationURLInput represents input for getting authorization URL.
type AuthorizationURLResult ¶
type AuthorizationURLResult struct {
AuthorizationURL string `json:"authorization_url"`
State string `json:"state"`
}
AuthorizationURLResult represents the result of getting authorization URL.
type CallbackInput ¶
type CallbackInput struct {
Provider OAuthProvider
Code string
State string
RedirectURI string
}
CallbackInput represents the OAuth callback input.
type CallbackResult ¶
type CallbackResult struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int64 `json:"expires_in"`
TokenType string `json:"token_type"`
User *userdom.User `json:"user"`
}
CallbackResult represents the OAuth callback result.
type ChangePasswordInput ¶
type ChangePasswordInput struct {
CurrentPassword string `json:"current_password" validate:"required"`
NewPassword string `json:"new_password" validate:"required,min=8,max=128"`
}
ChangePasswordInput represents the input for changing password.
type CreateFirstTeamInput ¶
type CreateFirstTeamInput struct {
RefreshToken string `json:"refresh_token" validate:"required"`
TeamName string `json:"team_name" validate:"required,min=2,max=100"`
TeamSlug string `json:"team_slug" validate:"required,min=3,max=50"`
}
CreateFirstTeamInput represents the input for creating first team.
type CreateFirstTeamResult ¶
type CreateFirstTeamResult struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"` // Rotated refresh token
ExpiresAt time.Time `json:"expires_at"`
Tenant TenantMembershipInfo `json:"tenant"`
}
CreateFirstTeamResult represents the result of creating first team.
type CreateProviderInput ¶
type CreateProviderInput struct {
TenantID string
Provider string
DisplayName string
ClientID string
ClientSecret string // Plaintext - will be encrypted
IssuerURL string
TenantIdentifier string
Scopes []string
AllowedDomains []string
AutoProvision bool
DefaultRole string
CreatedBy string
}
CreateProviderInput is the input for creating an identity provider config.
type EmailService ¶
type EmailService struct {
// contains filtered or unexported fields
}
EmailService handles sending emails for various application events. Supports per-tenant SMTP via TenantSMTPResolver: if a tenant has a custom email integration configured, it uses that SMTP server instead of the system default.
func NewEmailService ¶
func NewEmailService(sender emaildom.Sender, cfg config.SMTPConfig, appName string, log *logger.Logger) *EmailService
NewEmailService creates a new EmailService.
func (*EmailService) HasSystemSMTP ¶
func (s *EmailService) HasSystemSMTP() bool
HasSystemSMTP implements SMTPAvailabilityCheck. Returns true if the system-wide SMTP sender is configured.
func (*EmailService) HasTenantSMTP ¶
func (s *EmailService) HasTenantSMTP(ctx context.Context, tenantID string) bool
HasTenantSMTP implements SMTPAvailabilityCheck. Returns true if the given tenant has a custom SMTP integration configured. tenantID may be empty for self-registration without tenant context.
func (*EmailService) IsConfigured ¶
func (s *EmailService) IsConfigured() bool
IsConfigured returns true if email service is properly configured.
func (*EmailService) SendMemberReactivatedEmail ¶
func (s *EmailService) SendMemberReactivatedEmail( ctx context.Context, recipientEmail, recipientName, teamName, actorName, tenantID string, ) error
SendMemberReactivatedEmail notifies a user that their access has been restored. Same best-effort semantics as SendMemberSuspendedEmail.
func (*EmailService) SendMemberSuspendedEmail ¶
func (s *EmailService) SendMemberSuspendedEmail( ctx context.Context, recipientEmail, recipientName, teamName, actorName, tenantID string, ) error
SendMemberSuspendedEmail notifies a user that their tenant access has been suspended. Uses per-tenant SMTP if configured. Best-effort: returns nil and logs a warning if email is not configured for the tenant — the suspend operation should succeed even when the user can't be notified.
func (*EmailService) SendPasswordChangedEmail ¶
func (s *EmailService) SendPasswordChangedEmail(ctx context.Context, userEmail, userName, ipAddress string) error
SendPasswordChangedEmail sends a notification that the password was changed.
func (*EmailService) SendPasswordResetEmail ¶
func (s *EmailService) SendPasswordResetEmail(ctx context.Context, userEmail, userName, token string, expiresIn time.Duration, ipAddress string) error
SendPasswordResetEmail sends a password reset link to a user.
func (*EmailService) SendTeamInvitationEmail ¶
func (s *EmailService) SendTeamInvitationEmail(ctx context.Context, recipientEmail, inviterName, teamName, token string, expiresIn time.Duration, tenantID ...string) error
SendTeamInvitationEmail sends a team invitation email. Uses per-tenant SMTP if configured, otherwise falls back to system SMTP.
func (*EmailService) SendVerificationEmail ¶
func (s *EmailService) SendVerificationEmail(ctx context.Context, userEmail, userName, token string, expiresIn time.Duration) error
SendVerificationEmail sends an email verification link to a user.
func (*EmailService) SendWelcomeEmail ¶
func (s *EmailService) SendWelcomeEmail(ctx context.Context, userEmail, userName string) error
SendWelcomeEmail sends a welcome email to a new user.
func (*EmailService) SetTenantSMTPResolver ¶
func (s *EmailService) SetTenantSMTPResolver(resolver TenantSMTPResolver)
SetTenantSMTPResolver sets the per-tenant SMTP resolver.
type ExchangeTokenInput ¶
type ExchangeTokenInput struct {
RefreshToken string `json:"refresh_token" validate:"required"`
TenantID string `json:"tenant_id" validate:"required"`
}
ExchangeTokenInput represents the input for token exchange.
type ExchangeTokenResult ¶
type ExchangeTokenResult struct {
AccessToken string
TenantID string
TenantSlug string
Role string
ExpiresAt time.Time
}
ExchangeTokenResult represents the result of token exchange.
type ForgotPasswordInput ¶
type ForgotPasswordInput struct {
Email string `json:"email" validate:"required,email"`
}
ForgotPasswordInput represents the input for password reset request.
type ForgotPasswordResult ¶
type ForgotPasswordResult struct {
Token string // Reset token (should be sent via email in production)
}
ForgotPasswordResult represents the result of password reset request.
type IntegrationSMTPResolver ¶
type IntegrationSMTPResolver struct {
// contains filtered or unexported fields
}
IntegrationSMTPResolver resolves per-tenant SMTP config from notification integrations. When a tenant creates an email integration (category=notification, provider=email), the SMTP settings are stored encrypted in the integration's config/credentials.
func NewIntegrationSMTPResolver ¶
func NewIntegrationSMTPResolver(repo integration.Repository, log *logger.Logger) *IntegrationSMTPResolver
NewIntegrationSMTPResolver creates a new resolver.
func (*IntegrationSMTPResolver) GetTenantSMTPConfig ¶
func (r *IntegrationSMTPResolver) GetTenantSMTPConfig(ctx context.Context, tenantID string) (*emaildom.Config, error)
GetTenantSMTPConfig looks up the tenant's email integration and returns SMTP config. Returns nil if no email integration is configured for this tenant.
type LoginInput ¶
type LoginInput struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
IPAddress string `json:"-"`
UserAgent string `json:"-"`
}
LoginInput represents the input for login.
type LoginResult ¶
type LoginResult struct {
User *userdom.User
RefreshToken string // Global refresh token (no tenant context)
ExpiresAt time.Time
SessionID string
Tenants []TenantMembershipInfo // Active tenants user can access
// SuspendedTenants lists tenants where this user has a suspended
// membership. The user has zero access to these tenants — the field
// exists purely so the UI can show "your access to {name} is
// suspended" instead of bouncing the user to /onboarding/create-team
// when they have no active memberships.
SuspendedTenants []TenantMembershipInfo
}
LoginResult represents the result of login. Returns a global refresh token and list of tenant memberships. Client must call ExchangeToken to get a tenant-scoped access token.
type OAuthProvider ¶
type OAuthProvider string
OAuthProvider represents a supported OAuth provider.
const ( OAuthProviderGoogle OAuthProvider = "google" OAuthProviderGitHub OAuthProvider = "github" OAuthProviderMicrosoft OAuthProvider = "microsoft" )
func (OAuthProvider) IsValid ¶
func (p OAuthProvider) IsValid() bool
IsValid checks if the provider is valid.
func (OAuthProvider) ToAuthProvider ¶
func (p OAuthProvider) ToAuthProvider() userdom.AuthProvider
ToAuthProvider converts OAuthProvider to userdom.AuthProvider.
type OAuthService ¶
type OAuthService struct {
// contains filtered or unexported fields
}
OAuthService handles OAuth authentication.
func NewOAuthService ¶
func NewOAuthService( userRepo userdom.Repository, sessionRepo sessiondom.Repository, refreshTokenRepo sessiondom.RefreshTokenRepository, oauthCfg config.OAuthConfig, authCfg config.AuthConfig, log *logger.Logger, ) *OAuthService
NewOAuthService creates a new OAuthService.
func (*OAuthService) GetAuthorizationURL ¶
func (s *OAuthService) GetAuthorizationURL(ctx context.Context, input AuthorizationURLInput) (*AuthorizationURLResult, error)
GetAuthorizationURL returns the OAuth authorization URL for the specified provider.
func (*OAuthService) GetAvailableProviders ¶
func (s *OAuthService) GetAvailableProviders() []ProviderInfo
GetAvailableProviders returns a list of available OAuth providers.
func (*OAuthService) HandleCallback ¶
func (s *OAuthService) HandleCallback(ctx context.Context, input CallbackInput) (*CallbackResult, error)
HandleCallback handles the OAuth callback.
type OAuthUserInfo ¶
OAuthUserInfo represents user information from OAuth provider.
type ProviderInfo ¶
type ProviderInfo struct {
ID string `json:"id"`
Name string `json:"name"`
Enabled bool `json:"enabled"`
}
ProviderInfo represents information about an OAuth provider.
type RefreshTokenInput ¶
type RefreshTokenInput struct {
RefreshToken string `json:"refresh_token" validate:"required"`
TenantID string `json:"tenant_id" validate:"required"`
IPAddress string `json:"-"`
UserAgent string `json:"-"`
}
RefreshTokenInput represents the input for token refresh. Requires tenant_id to generate tenant-scoped access token.
type RefreshTokenResult ¶
type RefreshTokenResult struct {
AccessToken string // Tenant-scoped access token
RefreshToken string // New global refresh token (rotated)
TenantID string // Tenant ID the access token is scoped to
TenantSlug string // Tenant slug
Role string // User's role in this tenant
ExpiresAt time.Time // Access token expiration
RefreshExpiresAt time.Time // Refresh token expiration (for cookie)
}
RefreshTokenResult represents the result of token refresh. Returns a new global refresh token and tenant-scoped access token.
type RegisterInput ¶
type RegisterInput struct {
Email string `json:"email" validate:"required,email,max=255"`
Password string `json:"password" validate:"required,min=8,max=128"`
Name string `json:"name" validate:"required,max=255"`
// InvitationToken is optional: when a user registers via an
// invitation link, the client passes the token here so the register
// flow can resolve the target tenant and apply that tenant's email
// verification rule (instead of the platform default). The token
// itself is NOT consumed here — invitation acceptance still happens
// in a separate POST /invitations/{token}/accept call.
InvitationToken string `json:"invitation_token,omitempty"`
}
RegisterInput represents the input for user registration.
type RegisterResult ¶
type RegisterResult struct {
User *userdom.User
VerificationToken string // Only returned if email verification is required
RequiresVerification bool
EmailExisted bool // Set to true if email already exists (for anti-enumeration)
}
RegisterResult represents the result of registration.
type ResetPasswordInput ¶
type ResetPasswordInput struct {
Token string `json:"token" validate:"required"`
NewPassword string `json:"new_password" validate:"required,min=8,max=128"`
}
ResetPasswordInput represents the input for password reset.
type SMTPAvailabilityCheck ¶
type SMTPAvailabilityCheck interface {
// HasSystemSMTP returns true if the platform has system-wide SMTP configured.
HasSystemSMTP() bool
// HasTenantSMTP returns true if the given tenant has a custom SMTP integration.
// tenantID may be empty for self-registration (no tenant context yet).
HasTenantSMTP(ctx context.Context, tenantID string) bool
}
SMTPAvailabilityCheck reports whether outbound email is available, either via the system SMTP config or for a specific tenant. Used by smart email verification to skip verification when no email channel exists.
type SSOAuthorizeInput ¶
type SSOAuthorizeInput struct {
OrgSlug string
Provider string
RedirectURI string // Frontend callback URL
}
SSOAuthorizeInput is the input for generating an SSO authorization URL.
type SSOAuthorizeResult ¶
type SSOAuthorizeResult struct {
AuthorizationURL string `json:"authorization_url"`
State string `json:"state"`
}
SSOAuthorizeResult is the result of generating an SSO authorization URL.
type SSOCallbackInput ¶
SSOCallbackInput is the input for handling an SSO callback.
type SSOCallbackResult ¶
type SSOCallbackResult struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int64 `json:"expires_in"`
TokenType string `json:"token_type"`
User *userdom.User `json:"user"`
TenantID string `json:"tenant_id"`
TenantSlug string `json:"tenant_slug"`
}
SSOCallbackResult is the result of a successful SSO callback.
type SSOProviderInfo ¶
type SSOProviderInfo struct {
ID string `json:"id"`
Provider string `json:"provider"`
DisplayName string `json:"display_name"`
}
SSOProviderInfo represents a public SSO provider for a tenant.
type SSOService ¶
type SSOService struct {
// contains filtered or unexported fields
}
SSOService handles per-tenant SSO authentication.
func NewSSOService ¶
func NewSSOService( ipRepo identityproviderdom.Repository, tenantRepo tenantdom.Repository, userRepo userdom.Repository, sessionRepo sessiondom.Repository, refreshTokenRepo sessiondom.RefreshTokenRepository, encryptor crypto.Encryptor, authCfg config.AuthConfig, log *logger.Logger, ) *SSOService
NewSSOService creates a new SSOService.
func (*SSOService) CreateProvider ¶
func (s *SSOService) CreateProvider(ctx context.Context, input CreateProviderInput) (*identityproviderdom.IdentityProvider, error)
CreateProvider creates a new identity provider configuration for a tenant.
func (*SSOService) DeleteProvider ¶
func (s *SSOService) DeleteProvider(ctx context.Context, tenantID, id string) error
DeleteProvider deletes an identity provider configuration.
func (*SSOService) GenerateAuthorizeURL ¶
func (s *SSOService) GenerateAuthorizeURL(ctx context.Context, input SSOAuthorizeInput) (*SSOAuthorizeResult, error)
GenerateAuthorizeURL builds the OAuth authorization URL for a tenant's SSO provider.
func (*SSOService) GetProvider ¶
func (s *SSOService) GetProvider(ctx context.Context, tenantID, id string) (*identityproviderdom.IdentityProvider, error)
GetProvider retrieves a provider configuration by ID.
func (*SSOService) GetProvidersForTenant ¶
func (s *SSOService) GetProvidersForTenant(ctx context.Context, orgSlug string) ([]SSOProviderInfo, error)
GetProvidersForTenant returns active SSO providers for a tenant identified by slug.
func (*SSOService) HandleCallback ¶
func (s *SSOService) HandleCallback(ctx context.Context, input SSOCallbackInput) (*SSOCallbackResult, error)
HandleCallback handles the SSO OAuth callback.
func (*SSOService) ListProviders ¶
func (s *SSOService) ListProviders(ctx context.Context, tenantID string) ([]*identityproviderdom.IdentityProvider, error)
ListProviders lists all identity provider configurations for a tenant.
func (*SSOService) SetTenantMemberRepo ¶
func (s *SSOService) SetTenantMemberRepo(repo TenantMemberCreator)
SetTenantMemberRepo sets the tenant membership creator for auto-provisioning.
func (*SSOService) UpdateProvider ¶
func (s *SSOService) UpdateProvider(ctx context.Context, input UpdateProviderInput) (*identityproviderdom.IdentityProvider, error)
UpdateProvider updates an identity provider configuration.
type SSOUserInfo ¶
SSOUserInfo represents user info from SSO provider.
type SessionInfo ¶
type SessionInfo struct {
ID string `json:"id"`
IPAddress string `json:"ip_address,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
LastActivityAt string `json:"last_activity_at"`
CreatedAt string `json:"created_at"`
IsCurrent bool `json:"is_current"`
}
SessionInfo represents session information returned to the user.
type SessionResult ¶
SessionResult represents session creation result.
type SessionService ¶
type SessionService struct {
// contains filtered or unexported fields
}
SessionService handles session management operations.
func NewSessionService ¶
func NewSessionService( sessionRepo sessiondom.Repository, refreshTokenRepo sessiondom.RefreshTokenRepository, log *logger.Logger, ) *SessionService
NewSessionService creates a new SessionService.
func (*SessionService) CleanupExpiredSessions ¶
CleanupExpiredSessions removes expired sessions and tokens. This should be called periodically (e.g., by a cron job).
func (*SessionService) CountActiveSessions ¶
CountActiveSessions returns the count of active sessions for a user.
func (*SessionService) GetSessionByAccessToken ¶
func (s *SessionService) GetSessionByAccessToken(ctx context.Context, accessToken string) (*sessiondom.Session, error)
GetSessionByAccessToken retrieves a session by its access token.
func (*SessionService) ListUserSessions ¶
func (s *SessionService) ListUserSessions(ctx context.Context, userID string, currentSessionID string) ([]SessionInfo, error)
ListUserSessions returns all active sessions for a user.
func (*SessionService) RevokeAllSessions ¶
func (s *SessionService) RevokeAllSessions(ctx context.Context, userID, exceptSessionID string) error
RevokeAllSessions revokes all sessions for a user except the current one.
func (*SessionService) RevokeSession ¶
func (s *SessionService) RevokeSession(ctx context.Context, userID, sessionID string) error
RevokeSession revokes a specific session for a user.
func (*SessionService) SetPermissionServices ¶
func (s *SessionService) SetPermissionServices( cacheSvc *accesscontrol.PermissionCacheService, versionSvc *accesscontrol.PermissionVersionService, tenantRepo TenantMembershipProvider, )
SetPermissionServices sets the permission cache and version services. This enables cache invalidation when sessions are revoked.
func (*SessionService) UpdateSessionActivity ¶
func (s *SessionService) UpdateSessionActivity(ctx context.Context, sessionID string) error
UpdateSessionActivity updates the last activity time for a session.
func (*SessionService) ValidateSession ¶
func (s *SessionService) ValidateSession(ctx context.Context, sessionID string) (*sessiondom.Session, error)
ValidateSession checks if a session is valid.
type SettingsStorageResolver ¶
type SettingsStorageResolver struct {
// contains filtered or unexported fields
}
SettingsStorageResolver resolves per-tenant storage config from the settings table.
func NewSettingsStorageResolver ¶
func NewSettingsStorageResolver(db *sql.DB, enc crypto.Encryptor, log *logger.Logger) *SettingsStorageResolver
NewSettingsStorageResolver creates a new resolver.
func (*SettingsStorageResolver) GetTenantStorageConfig ¶
func (r *SettingsStorageResolver) GetTenantStorageConfig(ctx context.Context, tenantID string) (*attachment.StorageConfig, error)
GetTenantStorageConfig reads the storage_config setting for a tenant. Returns nil if not configured (tenant uses default provider).
func (*SettingsStorageResolver) SaveTenantStorageConfig ¶
func (r *SettingsStorageResolver) SaveTenantStorageConfig(ctx context.Context, tenantID string, cfg attachment.StorageConfig) error
SaveTenantStorageConfig upserts the storage config for a tenant.
type TenantMemberCreator ¶
type TenantMemberCreator interface {
CreateMembership(ctx context.Context, m *tenantdom.Membership) error
}
TenantMemberCreator creates tenant memberships for auto-provisioned users.
type TenantMembershipInfo ¶
type TenantMembershipInfo struct {
TenantID string `json:"tenant_id"`
TenantSlug string `json:"tenant_slug"`
TenantName string `json:"tenant_name"`
Role string `json:"role"`
}
TenantMembershipInfo represents a tenant membership for API responses.
type TenantMembershipProvider ¶
type TenantMembershipProvider interface {
GetUserTenantIDs(ctx context.Context, userID shared.ID) ([]string, error)
}
TenantMembershipProvider provides tenant membership information. Used to get all tenants a user belongs to for cache invalidation.
type TenantSMTPResolver ¶
type TenantSMTPResolver interface {
GetTenantSMTPConfig(ctx context.Context, tenantID string) (*emaildom.Config, error)
}
TenantSMTPResolver resolves per-tenant SMTP configuration from integrations. Returns nil if tenant has no custom SMTP config (fallback to system default).
type UpdateProviderInput ¶
type UpdateProviderInput struct {
ID string
TenantID string // For authorization check
DisplayName *string
ClientID *string
ClientSecret *string // Plaintext - will be encrypted if provided
IssuerURL *string
TenantIdentifier *string
Scopes []string
AllowedDomains []string
AutoProvision *bool
DefaultRole *string
IsActive *bool
}
UpdateProviderInput is the input for updating an identity provider config.
type WSTicketClaims ¶
type WSTicketClaims struct {
UserID string `json:"user_id"`
TenantID string `json:"tenant_id"`
IssuedAt int64 `json:"iat"`
}
WSTicketClaims is the payload persisted under each ticket. It is the minimum required to authenticate a WS upgrade as the issuing user/tenant.
type WSTicketService ¶
type WSTicketService struct {
// contains filtered or unexported fields
}
WSTicketService issues and redeems single-use WebSocket tickets.
func NewWSTicketService ¶
func NewWSTicketService(store WSTicketStore, ttl time.Duration, log *logger.Logger) *WSTicketService
NewWSTicketService constructs the service. ttl defaults to 30s when zero.
func (*WSTicketService) IssueTicket ¶
IssueTicket mints a new opaque ticket and stores the caller's identity under it. The returned string is what the client passes as ?ticket= on the WebSocket upgrade.
func (*WSTicketService) RedeemTicket ¶
func (s *WSTicketService) RedeemTicket(ctx context.Context, ticket string) (*WSTicketClaims, error)
RedeemTicket atomically looks up and consumes a ticket. On success returns the claims it was issued with. ticket must be the raw opaque string returned from IssueTicket.
func (*WSTicketService) TTLSeconds ¶
func (s *WSTicketService) TTLSeconds() int
TTLSeconds returns the configured TTL in seconds for HTTP responses.
type WSTicketStore ¶
type WSTicketStore interface {
// Set stores value at key with TTL. Must overwrite existing keys
// (the random ticket space is large enough that collisions are
// negligible, and overwrite is safer than failing silently).
Set(ctx context.Context, key, value string, ttl time.Duration) error
// GetDel atomically reads and deletes a key, returning the stored value.
// Returns ("", false, nil) when the key does not exist.
GetDel(ctx context.Context, key string) (string, bool, error)
}
WSTicketStore is the minimal Redis surface the ticket service needs. Keeping this narrow makes testing easy and prevents coupling to the full Redis client surface.