auth

package
v0.6.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 3, 2026 License: AGPL-3.0 Imports: 22 Imported by: 0

Documentation

Overview

Package auth provides OIDC authentication and session management.

Package auth provides authentication and authorization for Keldris.

Package auth provides authentication and authorization for Keldris.

Package auth provides email verification for non-OIDC users.

Index

Constants

View Source
const (
	// RegistrationCodeLength is the length of generated registration codes.
	RegistrationCodeLength = 8
	// RegistrationCodeExpiration is how long registration codes are valid.
	RegistrationCodeExpiration = 10 * time.Minute
	// RegistrationCodeChars is the character set for registration codes.
	// Using uppercase letters and digits, excluding ambiguous characters (0, O, I, L, 1).
	RegistrationCodeChars = "ABCDEFGHJKMNPQRSTUVWXYZ23456789"
)
View Source
const (
	// APIKeyPrefix is the prefix for all Keldris API keys.
	APIKeyPrefix = "kld_"
	// APIKeyLength is the expected length of the hex portion of the API key.
	APIKeyLength = 64 // 32 bytes = 64 hex chars
)
View Source
const (
	// TokenExpiryDuration is the duration before a reset token expires.
	TokenExpiryDuration = 1 * time.Hour
	// TokenLength is the length of the reset token in bytes (before hex encoding).
	TokenLength = 32
	// MaxResetAttemptsPerEmail is the maximum number of reset requests per email per window.
	MaxResetAttemptsPerEmail = 3
	// MaxResetAttemptsPerIP is the maximum number of reset requests per IP per window.
	MaxResetAttemptsPerIP = 5
	// RateLimitWindow is the duration of the rate limit window.
	RateLimitWindow = 15 * time.Minute
)
View Source
const (
	// SessionName is the name of the session cookie.
	SessionName = "keldris_session"
	// StateKey is the session key for OIDC state.
	StateKey = "oidc_state"
	// UserIDKey is the session key for the authenticated user ID.
	UserIDKey = "user_id"
	// OIDCSubjectKey is the session key for the OIDC subject.
	OIDCSubjectKey = "oidc_subject"
	// EmailKey is the session key for the user's email.
	EmailKey = "email"
	// NameKey is the session key for the user's name.
	NameKey = "name"
	// AuthenticatedAtKey is the session key for when the user authenticated.
	AuthenticatedAtKey = "authenticated_at"
	// CurrentOrgIDKey is the session key for the currently selected organization.
	CurrentOrgIDKey = "current_org_id"
	// CurrentOrgRoleKey is the session key for the user's role in the current org.
	CurrentOrgRoleKey = "current_org_role"
	// LastActivityKey is the session key for the last activity timestamp.
	LastActivityKey = "last_activity"
	// SessionRecordIDKey is the session key for the database session record ID.
	SessionRecordIDKey = "session_record_id"
	// IsSuperuserKey is the session key for superuser status.
	IsSuperuserKey = "is_superuser"
	// ImpersonatingKey is the session key for impersonation state.
	ImpersonatingKey = "impersonating"
	// ImpersonatingUserIDKey is the session key for the user being impersonated.
	ImpersonatingUserIDKey = "impersonating_user_id"
	// OriginalUserIDKey is the session key for the original superuser ID during impersonation.
	OriginalUserIDKey = "original_user_id"
	// OriginalUserEmailKey is the session key for the original user email during impersonation.
	OriginalUserEmailKey = "original_user_email"
	// ImpersonationLogIDKey is the session key for the impersonation log ID.
	ImpersonationLogIDKey = "impersonation_log_id"
)

Variables

View Source
var (
	ErrPasswordTooShort       = errors.New("password is too short")
	ErrPasswordNoUppercase    = errors.New("password must contain at least one uppercase letter")
	ErrPasswordNoLowercase    = errors.New("password must contain at least one lowercase letter")
	ErrPasswordNoNumber       = errors.New("password must contain at least one number")
	ErrPasswordNoSpecial      = errors.New("password must contain at least one special character")
	ErrPasswordInHistory      = errors.New("password has been used recently")
	ErrPasswordMismatch       = errors.New("current password is incorrect")
	ErrPasswordExpired        = errors.New("password has expired")
	ErrPasswordChangeRequired = errors.New("password change is required")
)

Common password validation errors.

View Source
var (
	ErrResetTokenExpired  = errors.New("reset token has expired")
	ErrResetTokenUsed     = errors.New("reset token has already been used")
	ErrResetTokenInvalid  = errors.New("invalid reset token")
	ErrResetRateLimited   = errors.New("too many password reset requests")
	ErrUserNoPasswordAuth = errors.New("user does not have password authentication")
	ErrUserOIDCOnly       = errors.New("user uses OIDC authentication only")
)

Common password reset errors.

View Source
var (
	ErrTokenExpired        = errors.New("verification token has expired")
	ErrTokenAlreadyUsed    = errors.New("verification token has already been used")
	ErrTokenNotFound       = errors.New("verification token not found")
	ErrUserAlreadyVerified = errors.New("user email is already verified")
	ErrUserNotFound        = errors.New("user not found")
)

Common errors for email verification.

View Source
var ErrCannotRevokeSelf = fmt.Errorf("cannot revoke own superuser privileges")

ErrCannotRevokeSelf is returned when a superuser tries to revoke their own privileges.

View Source
var ErrLastSuperuser = fmt.Errorf("cannot remove the last superuser")

ErrLastSuperuser is returned when attempting to remove the last superuser.

View Source
var ErrNotMember = fmt.Errorf("not a member of this organization")

ErrNotMember is returned when a user is not a member of the organization.

View Source
var ErrNotSuperuser = fmt.Errorf("superuser privileges required")

ErrNotSuperuser is returned when a user is not a superuser.

View Source
var ErrPermissionDenied = fmt.Errorf("permission denied")

ErrPermissionDenied is returned when a user lacks required permissions.

Functions

func BuildVerificationURL

func BuildVerificationURL(baseURL, token string) string

BuildVerificationURL builds the verification URL for an email.

func CompareAPIKeyHash

func CompareAPIKeyHash(apiKey, storedHash string) bool

CompareAPIKeyHash compares an API key with a stored hash using constant-time comparison.

func DefaultPasswordPolicy

func DefaultPasswordPolicy() *models.PasswordPolicy

DefaultPasswordPolicy returns a default password policy for organizations without one.

func ExtractBearerToken

func ExtractBearerToken(authHeader string) string

ExtractBearerToken extracts the token from an Authorization header value. Returns empty string if the header is not a valid Bearer token.

func GenerateState

func GenerateState() (string, error)

GenerateState generates a cryptographically secure random state parameter.

func HasRolePermission

func HasRolePermission(role models.OrgRole, perm Permission) bool

HasRolePermission checks if a role has the given permission.

func HashAPIKey

func HashAPIKey(key string) string

HashAPIKey creates a SHA-256 hash of an API key for storage/comparison.

func HashPassword

func HashPassword(password string) (string, error)

HashPassword creates a bcrypt hash of the password.

func HashToken

func HashToken(token string) string

HashToken hashes a raw token for comparison.

func IsValidAPIKeyFormat

func IsValidAPIKeyFormat(apiKey string) bool

IsValidAPIKeyFormat checks if the API key has the correct format.

func VerifyPassword

func VerifyPassword(password, hash string) error

VerifyPassword compares a password with its hash.

Types

type APIKeyValidator

type APIKeyValidator struct {
	// contains filtered or unexported fields
}

APIKeyValidator validates API keys and retrieves associated agents.

func NewAPIKeyValidator

func NewAPIKeyValidator(store AgentStore, logger zerolog.Logger) *APIKeyValidator

NewAPIKeyValidator creates a new API key validator.

func (*APIKeyValidator) ValidateAPIKey

func (v *APIKeyValidator) ValidateAPIKey(ctx context.Context, apiKey string) (*models.Agent, error)

ValidateAPIKey validates an API key and returns the associated agent. Returns nil if the key is invalid or not found.

type AgentMFA

type AgentMFA struct {
	// contains filtered or unexported fields
}

AgentMFA handles agent registration code generation and verification.

func NewAgentMFA

func NewAgentMFA(store RegistrationCodeStore, logger zerolog.Logger) *AgentMFA

NewAgentMFA creates a new AgentMFA instance.

func (*AgentMFA) CleanupExpiredCodes

func (m *AgentMFA) CleanupExpiredCodes(ctx context.Context) error

CleanupExpiredCodes removes expired registration codes from the database.

func (*AgentMFA) GenerateCode

func (m *AgentMFA) GenerateCode(ctx context.Context, orgID, userID uuid.UUID, hostname *string) (*models.RegistrationCode, error)

GenerateCode generates a new registration code for an organization.

func (*AgentMFA) GetPendingCodes

func (m *AgentMFA) GetPendingCodes(ctx context.Context, orgID uuid.UUID) ([]*models.RegistrationCode, error)

GetPendingCodes returns all pending (unused, unexpired) registration codes for an organization.

func (*AgentMFA) MarkCodeUsed

func (m *AgentMFA) MarkCodeUsed(ctx context.Context, codeID, agentID uuid.UUID) error

MarkCodeUsed marks a registration code as used by an agent.

func (*AgentMFA) VerifyCode

func (m *AgentMFA) VerifyCode(ctx context.Context, orgID uuid.UUID, code string) (*models.RegistrationCode, error)

VerifyCode verifies a registration code and returns it if valid.

type AgentStore

type AgentStore interface {
	GetAgentByAPIKeyHash(ctx context.Context, hash string) (*models.Agent, error)
}

AgentStore defines the interface for agent lookup operations.

type EmailVerificationToken

type EmailVerificationToken struct {
	ID        uuid.UUID  `json:"id"`
	UserID    uuid.UUID  `json:"user_id"`
	TokenHash string     `json:"-"` // Never expose token hash
	ExpiresAt time.Time  `json:"expires_at"`
	UsedAt    *time.Time `json:"used_at,omitempty"`
	CreatedAt time.Time  `json:"created_at"`
}

EmailVerificationToken represents a verification token for email verification.

func NewEmailVerificationToken

func NewEmailVerificationToken(userID uuid.UUID, expiresIn time.Duration) (*EmailVerificationToken, string, error)

NewEmailVerificationToken creates a new verification token for a user.

func (*EmailVerificationToken) IsExpired

func (t *EmailVerificationToken) IsExpired() bool

IsExpired returns true if the token has expired.

func (*EmailVerificationToken) IsUsed

func (t *EmailVerificationToken) IsUsed() bool

IsUsed returns true if the token has been used.

type GroupSync

type GroupSync struct {
	// contains filtered or unexported fields
}

GroupSync handles OIDC group synchronization to Keldris roles.

func NewGroupSync

func NewGroupSync(store GroupSyncStore, logger zerolog.Logger) *GroupSync

NewGroupSync creates a new GroupSync instance.

func (*GroupSync) ExtractGroupsFromToken

func (gs *GroupSync) ExtractGroupsFromToken(ctx context.Context, oidc *OIDC, token *oauth2.Token) ([]string, error)

ExtractGroupsFromToken extracts groups from an OIDC token. Different OIDC providers use different claim names for groups.

func (*GroupSync) SyncUserGroups

func (gs *GroupSync) SyncUserGroups(ctx context.Context, userID uuid.UUID, groups []string) (*models.GroupSyncResult, error)

SyncUserGroups syncs a user's OIDC groups to Keldris memberships. This should be called during login after extracting groups from the token.

type GroupSyncStore

type GroupSyncStore interface {
	// Group mapping operations
	GetSSOGroupMappingsByGroupNames(ctx context.Context, groupNames []string) ([]*models.SSOGroupMapping, error)
	GetSSOGroupMappingsByOrgID(ctx context.Context, orgID uuid.UUID) ([]*models.SSOGroupMapping, error)

	// User SSO groups operations
	GetUserSSOGroups(ctx context.Context, userID uuid.UUID) (*models.UserSSOGroups, error)
	UpsertUserSSOGroups(ctx context.Context, userID uuid.UUID, groups []string) error

	// Membership operations
	GetMembershipsByUserID(ctx context.Context, userID uuid.UUID) ([]*models.OrgMembership, error)
	GetMembershipByUserAndOrg(ctx context.Context, userID, orgID uuid.UUID) (*models.OrgMembership, error)
	CreateMembership(ctx context.Context, m *models.OrgMembership) error
	UpdateMembershipRole(ctx context.Context, membershipID uuid.UUID, role models.OrgRole) error

	// Organization operations
	GetOrganizationByID(ctx context.Context, id uuid.UUID) (*models.Organization, error)
	GetOrganizationSSOSettings(ctx context.Context, orgID uuid.UUID) (defaultRole *string, autoCreateOrgs bool, err error)
}

GroupSyncStore defines the interface for group sync persistence operations.

type IDTokenClaims

type IDTokenClaims struct {
	Subject string `json:"sub"`
	Email   string `json:"email"`
	Name    string `json:"name"`
}

IDTokenClaims holds the standard claims from an ID token.

type MembershipStore

type MembershipStore interface {
	GetMembershipByUserAndOrg(ctx context.Context, userID, orgID uuid.UUID) (*models.OrgMembership, error)
	GetMembershipsByUserID(ctx context.Context, userID uuid.UUID) ([]*models.OrgMembership, error)
}

MembershipStore defines the interface for fetching membership data.

type OIDC

type OIDC struct {
	// contains filtered or unexported fields
}

OIDC wraps the OIDC provider and OAuth2 configuration.

func NewOIDC

func NewOIDC(ctx context.Context, cfg OIDCConfig, logger zerolog.Logger) (*OIDC, error)

NewOIDC creates a new OIDC provider instance.

func (*OIDC) AuthorizationURL

func (o *OIDC) AuthorizationURL(state string) string

AuthorizationURL returns the URL to redirect users for authentication.

func (*OIDC) Exchange

func (o *OIDC) Exchange(ctx context.Context, code string) (*oauth2.Token, error)

Exchange exchanges an authorization code for tokens.

func (*OIDC) HealthCheck

func (o *OIDC) HealthCheck(ctx context.Context) error

HealthCheck verifies that the OIDC provider is reachable by fetching its discovery document.

func (*OIDC) UserInfo

func (o *OIDC) UserInfo(ctx context.Context, token *oauth2.Token) (*oidc.UserInfo, error)

UserInfo fetches user information from the OIDC provider.

func (*OIDC) VerifyIDToken

func (o *OIDC) VerifyIDToken(ctx context.Context, token *oauth2.Token) (*IDTokenClaims, error)

VerifyIDToken verifies the ID token and extracts claims.

type OIDCConfig

type OIDCConfig struct {
	Issuer       string
	ClientID     string
	ClientSecret string
	RedirectURL  string
	Scopes       []string
}

OIDCConfig holds OIDC provider configuration.

func DefaultOIDCConfig

func DefaultOIDCConfig(issuer, clientID, clientSecret, redirectURL string) OIDCConfig

DefaultOIDCConfig returns an OIDCConfig with standard scopes.

type OIDCProvider

type OIDCProvider struct {
	// contains filtered or unexported fields
}

OIDCProvider is a thread-safe wrapper around an OIDC provider that supports hot-reloading when OIDC settings change at runtime.

func NewOIDCProvider

func NewOIDCProvider(provider *OIDC, logger zerolog.Logger) *OIDCProvider

NewOIDCProvider creates a new OIDCProvider wrapper. The initial provider can be nil (password-only mode).

func (*OIDCProvider) Get

func (p *OIDCProvider) Get() *OIDC

Get returns the current OIDC provider instance (may be nil).

func (*OIDCProvider) HealthCheck

func (p *OIDCProvider) HealthCheck(ctx context.Context) error

HealthCheck delegates to the underlying provider's health check. Returns nil if no provider is configured (OIDC is optional).

func (*OIDCProvider) IsConfigured

func (p *OIDCProvider) IsConfigured() bool

IsConfigured returns true if an OIDC provider is currently loaded.

func (*OIDCProvider) Update

func (p *OIDCProvider) Update(ctx context.Context, cfg OIDCConfig) error

Update creates a new OIDC provider from the given config and swaps it in. If initialization fails, the old provider is kept.

type PasswordPolicyStore

type PasswordPolicyStore interface {
	GetPasswordPolicyByOrgID(ctx context.Context, orgID uuid.UUID) (*models.PasswordPolicy, error)
	GetPasswordHistory(ctx context.Context, userID uuid.UUID, limit int) ([]*models.PasswordHistory, error)
	CreatePasswordHistory(ctx context.Context, history *models.PasswordHistory) error
	CleanupPasswordHistory(ctx context.Context, userID uuid.UUID, keepCount int) error
}

PasswordPolicyStore defines the interface for password policy data access.

type PasswordResetService

type PasswordResetService struct {
	// contains filtered or unexported fields
}

PasswordResetService handles password reset operations.

func NewPasswordResetService

func NewPasswordResetService(store PasswordResetStore, logger zerolog.Logger) *PasswordResetService

NewPasswordResetService creates a new PasswordResetService.

func (*PasswordResetService) CleanupExpiredTokens

func (s *PasswordResetService) CleanupExpiredTokens(ctx context.Context) error

CleanupExpiredTokens removes expired reset tokens and rate limit entries.

func (*PasswordResetService) RequestReset

func (s *PasswordResetService) RequestReset(ctx context.Context, email, ipAddress, userAgent string) (*ResetRequest, error)

RequestReset initiates a password reset for the given email. Returns the reset token and user info for sending the reset email. Always returns success to prevent email enumeration, but only generates a token if the user exists and has password auth.

func (*PasswordResetService) ResetPassword

func (s *PasswordResetService) ResetPassword(ctx context.Context, token, newPassword, ipAddress, userAgent string) error

ResetPassword resets the user's password using a valid token.

func (*PasswordResetService) ValidateToken

func (s *PasswordResetService) ValidateToken(ctx context.Context, token string) (*models.User, error)

ValidateToken validates a password reset token and returns the associated user.

type PasswordResetStore

type PasswordResetStore interface {
	// User methods
	GetUserByEmail(ctx context.Context, email string) (*models.User, error)
	GetUserByID(ctx context.Context, id uuid.UUID) (*models.User, error)
	HasPasswordAuth(ctx context.Context, userID uuid.UUID) (bool, error)

	// Token methods
	CreatePasswordResetToken(ctx context.Context, token *models.PasswordResetToken) error
	GetPasswordResetTokenByHash(ctx context.Context, tokenHash string) (*models.PasswordResetToken, error)
	MarkPasswordResetTokenUsed(ctx context.Context, tokenID uuid.UUID) error
	InvalidateUserResetTokens(ctx context.Context, userID uuid.UUID) error

	// Rate limiting methods
	GetResetRateLimit(ctx context.Context, identifier, identifierType string) (*models.PasswordResetRateLimit, error)
	IncrementResetRateLimit(ctx context.Context, identifier, identifierType string, windowDuration time.Duration) error
	CleanupExpiredRateLimits(ctx context.Context, windowDuration time.Duration) error

	// Password update
	UpdateUserPassword(ctx context.Context, userID uuid.UUID, passwordHash string, expiresAt *time.Time) error
	GetPasswordPolicyByOrgID(ctx context.Context, orgID uuid.UUID) (*models.PasswordPolicy, error)

	// Audit logging
	CreateAuditLog(ctx context.Context, log *models.AuditLog) error
}

PasswordResetStore defines the interface for password reset data access.

type PasswordValidator

type PasswordValidator struct {
	// contains filtered or unexported fields
}

PasswordValidator handles password validation against policies.

func NewPasswordValidator

func NewPasswordValidator(store PasswordPolicyStore) *PasswordValidator

NewPasswordValidator creates a new PasswordValidator.

func (*PasswordValidator) RecordPasswordChange

func (v *PasswordValidator) RecordPasswordChange(ctx context.Context, orgID, userID uuid.UUID, passwordHash string) error

RecordPasswordChange records a password change in history.

func (*PasswordValidator) ValidateAgainstPolicy

func (v *PasswordValidator) ValidateAgainstPolicy(password string, policy *models.PasswordPolicy) *ValidationResult

ValidateAgainstPolicy validates a password against a specific policy.

func (*PasswordValidator) ValidatePassword

func (v *PasswordValidator) ValidatePassword(ctx context.Context, orgID uuid.UUID, password string) (*ValidationResult, error)

ValidatePassword validates a password against the organization's policy.

func (*PasswordValidator) ValidatePasswordWithHistory

func (v *PasswordValidator) ValidatePasswordWithHistory(ctx context.Context, orgID, userID uuid.UUID, password string) (*ValidationResult, error)

ValidatePasswordWithHistory validates a password against policy and history.

type Permission

type Permission string

Permission defines an action that can be performed.

const (
	// Organization permissions
	PermOrgRead   Permission = "org:read"
	PermOrgUpdate Permission = "org:update"
	PermOrgDelete Permission = "org:delete"

	// Member management permissions
	PermMemberRead   Permission = "member:read"
	PermMemberInvite Permission = "member:invite"
	PermMemberUpdate Permission = "member:update"
	PermMemberRemove Permission = "member:remove"

	// User management permissions (admin-level control)
	PermUserRead          Permission = "user:read"
	PermUserInvite        Permission = "user:invite"
	PermUserUpdate        Permission = "user:update"
	PermUserDisable       Permission = "user:disable"
	PermUserDelete        Permission = "user:delete"
	PermUserResetPassword Permission = "user:reset_password"
	PermUserImpersonate   Permission = "user:impersonate"
	PermUserActivityView  Permission = "user:activity_view"

	// Agent permissions
	PermAgentRead   Permission = "agent:read"
	PermAgentCreate Permission = "agent:create"
	PermAgentUpdate Permission = "agent:update"
	PermAgentDelete Permission = "agent:delete"

	// Repository permissions
	PermRepoRead   Permission = "repo:read"
	PermRepoCreate Permission = "repo:create"
	PermRepoUpdate Permission = "repo:update"
	PermRepoDelete Permission = "repo:delete"

	// Schedule permissions
	PermScheduleRead   Permission = "schedule:read"
	PermScheduleCreate Permission = "schedule:create"
	PermScheduleUpdate Permission = "schedule:update"
	PermScheduleDelete Permission = "schedule:delete"
	PermScheduleRun    Permission = "schedule:run"

	// Backup permissions
	PermBackupRead   Permission = "backup:read"
	PermBackupCreate Permission = "backup:create"
)

type RBAC

type RBAC struct {
	// contains filtered or unexported fields
}

RBAC provides role-based access control functionality.

func NewRBAC

func NewRBAC(store MembershipStore) *RBAC

NewRBAC creates a new RBAC instance.

func (*RBAC) CanAssignRole

func (r *RBAC) CanAssignRole(ctx context.Context, actorID, orgID uuid.UUID, targetRole models.OrgRole) (bool, error)

CanAssignRole checks if a user can assign a specific role to another user.

func (*RBAC) CanManageMember

func (r *RBAC) CanManageMember(ctx context.Context, actorID, targetID, orgID uuid.UUID) (bool, error)

CanManageMember checks if a user can manage (update/remove) another member. Owners can manage anyone. Admins can manage members and readonly, but not other admins or owners.

func (*RBAC) GetUserRole

func (r *RBAC) GetUserRole(ctx context.Context, userID, orgID uuid.UUID) (models.OrgRole, error)

GetUserRole returns the user's role in the organization.

func (*RBAC) HasPermission

func (r *RBAC) HasPermission(ctx context.Context, userID, orgID uuid.UUID, perm Permission) (bool, error)

HasPermission checks if the user has the given permission in the organization.

func (*RBAC) RequirePermission

func (r *RBAC) RequirePermission(ctx context.Context, userID, orgID uuid.UUID, perm Permission) error

RequirePermission checks if the user has permission and returns an error if not.

type RegistrationCodeStore

type RegistrationCodeStore interface {
	CreateRegistrationCode(ctx context.Context, code *models.RegistrationCode) error
	GetRegistrationCodeByCode(ctx context.Context, orgID uuid.UUID, code string) (*models.RegistrationCode, error)
	GetPendingRegistrationCodes(ctx context.Context, orgID uuid.UUID) ([]*models.RegistrationCode, error)
	MarkRegistrationCodeUsed(ctx context.Context, codeID, agentID uuid.UUID) error
	DeleteExpiredRegistrationCodes(ctx context.Context) error
}

RegistrationCodeStore defines the interface for registration code persistence.

type ResetRequest

type ResetRequest struct {
	Token     string    // The plain-text token to send to the user
	ExpiresAt time.Time // When the token expires
	UserID    uuid.UUID // The user's ID
	UserEmail string    // The user's email
	UserName  string    // The user's name
}

ResetRequest contains the result of a password reset request.

type SessionConfig

type SessionConfig struct {
	Secret      []byte
	MaxAge      int  // seconds
	IdleTimeout int  // seconds, 0 to disable
	Secure      bool // require HTTPS
	HTTPOnly    bool // prevent JavaScript access
	SameSite    http.SameSite
	CookiePath  string
}

SessionConfig holds session store configuration.

func DefaultSessionConfig

func DefaultSessionConfig(secret []byte, secure bool, maxAge, idleTimeout int) SessionConfig

DefaultSessionConfig returns a SessionConfig with secure defaults. maxAge in seconds (0 or negative uses default 86400). idleTimeout in seconds (0 disables idle timeout, negative uses default 1800).

type SessionStore

type SessionStore struct {
	// contains filtered or unexported fields
}

SessionStore wraps a gorilla/sessions store with helper methods.

func NewSessionStore

func NewSessionStore(cfg SessionConfig, logger zerolog.Logger) (*SessionStore, error)

NewSessionStore creates a new session store.

func (*SessionStore) ClearUser

func (s *SessionStore) ClearUser(r *http.Request, w http.ResponseWriter) error

ClearUser removes user data from the session (logout).

func (*SessionStore) EndImpersonation

func (s *SessionStore) EndImpersonation(r *http.Request, w http.ResponseWriter, originalUser *SessionUser) error

EndImpersonation restores the original superuser session.

func (*SessionStore) Get

func (s *SessionStore) Get(r *http.Request) (*sessions.Session, error)

Get retrieves a session from the request.

func (*SessionStore) GetImpersonationLogID

func (s *SessionStore) GetImpersonationLogID(r *http.Request) (uuid.UUID, error)

GetImpersonationLogID returns the current impersonation log ID if impersonating.

func (*SessionStore) GetOIDCState

func (s *SessionStore) GetOIDCState(r *http.Request, w http.ResponseWriter) (string, error)

GetOIDCState retrieves and clears the OIDC state from the session.

func (*SessionStore) GetOriginalUserID

func (s *SessionStore) GetOriginalUserID(r *http.Request) uuid.UUID

GetOriginalUserID returns the original superuser ID during impersonation.

func (*SessionStore) GetUser

func (s *SessionStore) GetUser(r *http.Request) (*SessionUser, error)

GetUser retrieves the authenticated user from the session.

func (*SessionStore) IsAuthenticated

func (s *SessionStore) IsAuthenticated(r *http.Request) bool

IsAuthenticated checks if the session has a valid authenticated user.

func (*SessionStore) IsImpersonating

func (s *SessionStore) IsImpersonating(r *http.Request) bool

IsImpersonating checks if the current session is in impersonation mode.

func (*SessionStore) Save

func (s *SessionStore) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error

Save saves the session to the response.

func (*SessionStore) SetCurrentOrg

func (s *SessionStore) SetCurrentOrg(r *http.Request, w http.ResponseWriter, orgID uuid.UUID, role string) error

SetCurrentOrg updates the current organization in the session.

func (*SessionStore) SetOIDCState

func (s *SessionStore) SetOIDCState(r *http.Request, w http.ResponseWriter, state string) error

SetOIDCState stores the OIDC state in the session.

func (*SessionStore) SetSuperuserStatus

func (s *SessionStore) SetSuperuserStatus(r *http.Request, w http.ResponseWriter, isSuperuser bool) error

SetSuperuserStatus updates the superuser status in the session.

func (*SessionStore) SetUser

func (s *SessionStore) SetUser(r *http.Request, w http.ResponseWriter, user *SessionUser) error

SetUser stores user data in the session after successful authentication.

func (*SessionStore) StartImpersonation

func (s *SessionStore) StartImpersonation(r *http.Request, w http.ResponseWriter, originalUser *SessionUser, targetUser *SessionUser, logID uuid.UUID) error

StartImpersonation sets up impersonation mode where a superuser acts as another user.

func (*SessionStore) TouchSession

func (s *SessionStore) TouchSession(r *http.Request, w http.ResponseWriter) error

TouchSession updates the last activity timestamp to keep the session alive. Call this on each authenticated request to track idle timeout.

type SessionUser

type SessionUser struct {
	ID              uuid.UUID
	OIDCSubject     string
	Email           string
	Name            string
	AuthenticatedAt time.Time
	CurrentOrgID    uuid.UUID
	CurrentOrgRole  string
	SessionRecordID uuid.UUID
	IsSuperuser     bool
	// Impersonation fields
	Impersonating      bool
	ImpersonatingID    uuid.UUID // The user being impersonated (if any)
	OriginalUserID     uuid.UUID // The original superuser ID (during impersonation)
	OriginalUserEmail  string
	ImpersonationLogID uuid.UUID
}

SessionUser represents the authenticated user data stored in session.

func (*SessionUser) IsImpersonating

func (u *SessionUser) IsImpersonating() bool

IsImpersonating returns true if the user is being impersonated.

type Superuser

type Superuser struct {
	// contains filtered or unexported fields
}

Superuser provides superuser authorization checks.

func NewSuperuser

func NewSuperuser(store SuperuserStore) *Superuser

NewSuperuser creates a new Superuser instance.

func (*Superuser) GetAllOrganizations

func (s *Superuser) GetAllOrganizations(ctx context.Context, userID uuid.UUID) ([]*models.Organization, error)

GetAllOrganizations returns all organizations (superuser only).

func (*Superuser) GetAllUsers

func (s *Superuser) GetAllUsers(ctx context.Context, userID uuid.UUID) ([]*models.User, error)

GetAllUsers returns all users across all organizations (superuser only).

func (*Superuser) GetSystemSetting

func (s *Superuser) GetSystemSetting(ctx context.Context, userID uuid.UUID, key string) (*models.SystemSetting, error)

GetSystemSetting returns a system setting by key (superuser only).

func (*Superuser) GetSystemSettings

func (s *Superuser) GetSystemSettings(ctx context.Context, userID uuid.UUID) ([]*models.SystemSetting, error)

GetSystemSettings returns all system settings (superuser only).

func (*Superuser) GrantSuperuser

func (s *Superuser) GrantSuperuser(ctx context.Context, grantedBy, targetUserID uuid.UUID) error

GrantSuperuser grants superuser privileges to a user.

func (*Superuser) IsSuperuser

func (s *Superuser) IsSuperuser(ctx context.Context, userID uuid.UUID) (bool, error)

IsSuperuser checks if the user with the given ID is a superuser.

func (*Superuser) RequireSuperuser

func (s *Superuser) RequireSuperuser(ctx context.Context, userID uuid.UUID) error

RequireSuperuser checks if the user is a superuser and returns an error if not.

func (*Superuser) RevokeSuperuser

func (s *Superuser) RevokeSuperuser(ctx context.Context, revokedBy, targetUserID uuid.UUID) error

RevokeSuperuser revokes superuser privileges from a user.

func (*Superuser) UpdateSystemSetting

func (s *Superuser) UpdateSystemSetting(ctx context.Context, userID uuid.UUID, key string, value interface{}) error

UpdateSystemSetting updates a system setting (superuser only).

type SuperuserStore

type SuperuserStore interface {
	GetUserByID(ctx context.Context, id uuid.UUID) (*models.User, error)
	GetAllOrganizations(ctx context.Context) ([]*models.Organization, error)
	GetAllUsers(ctx context.Context) ([]*models.User, error)
	SetUserSuperuser(ctx context.Context, userID uuid.UUID, isSuperuser bool) error
	GetSuperusers(ctx context.Context) ([]*models.User, error)
	GetUserByEmail(ctx context.Context, email string) (*models.User, error)
	CreateSuperuserAuditLog(ctx context.Context, log *models.SuperuserAuditLog) error
	GetSuperuserAuditLogs(ctx context.Context, limit, offset int) ([]*models.SuperuserAuditLogWithUser, int, error)
	GetSystemSetting(ctx context.Context, key string) (*models.SystemSetting, error)
	GetSystemSettings(ctx context.Context) ([]*models.SystemSetting, error)
	UpdateSystemSetting(ctx context.Context, key string, value interface{}, updatedBy uuid.UUID) error
}

SuperuserStore defines the interface for superuser-related data operations.

type UserVerificationStatus

type UserVerificationStatus struct {
	UserID        uuid.UUID `json:"user_id"`
	Email         string    `json:"email"`
	IsVerified    bool      `json:"is_verified"`
	IsOIDCUser    bool      `json:"is_oidc_user"`
	RequiresEmail bool      `json:"requires_email"` // True if user needs to verify email
}

GetUserVerificationStatus returns the verification status for a user.

type ValidationResult

type ValidationResult struct {
	Valid    bool     `json:"valid"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
}

ValidationResult contains the result of password validation.

type VerifiableUser

type VerifiableUser interface {
	GetID() uuid.UUID
	GetEmail() string
	IsEmailVerified() bool
	IsOIDCUser() bool
}

VerifiableUser represents a user that can be verified.

type VerificationConfig

type VerificationConfig struct {
	TokenExpiration  time.Duration // How long verification tokens are valid
	ResendCooldown   time.Duration // Minimum time between resend requests
	MaxTokensPerUser int           // Maximum active tokens per user
}

VerificationConfig holds configuration for the verification service.

func DefaultVerificationConfig

func DefaultVerificationConfig() VerificationConfig

DefaultVerificationConfig returns a VerificationConfig with sensible defaults.

type VerificationService

type VerificationService struct {
	// contains filtered or unexported fields
}

VerificationService handles email verification operations.

func NewVerificationService

func NewVerificationService(store VerificationStore, config VerificationConfig, logger zerolog.Logger) *VerificationService

NewVerificationService creates a new verification service.

func (*VerificationService) GenerateToken

func (s *VerificationService) GenerateToken(ctx context.Context, userID uuid.UUID) (string, error)

GenerateToken creates a new verification token for a user. Returns the raw token that should be sent to the user via email.

func (*VerificationService) GetUserVerificationStatus

func (s *VerificationService) GetUserVerificationStatus(ctx context.Context, userID uuid.UUID) (*UserVerificationStatus, error)

GetUserVerificationStatus returns verification status for a user.

func (*VerificationService) ResendVerification

func (s *VerificationService) ResendVerification(ctx context.Context, userID uuid.UUID) (string, error)

ResendVerification generates a new verification token for a user. This can be used when the original token expires or is lost.

func (*VerificationService) VerifyToken

func (s *VerificationService) VerifyToken(ctx context.Context, rawToken string) error

VerifyToken validates a verification token and marks the user's email as verified.

type VerificationStore

type VerificationStore interface {
	CreateEmailVerificationToken(ctx context.Context, token *EmailVerificationToken) error
	GetEmailVerificationTokenByHash(ctx context.Context, tokenHash string) (*EmailVerificationToken, error)
	MarkEmailVerificationTokenUsed(ctx context.Context, tokenID uuid.UUID) error
	GetUserByID(ctx context.Context, userID uuid.UUID) (VerifiableUser, error)
	SetUserEmailVerified(ctx context.Context, userID uuid.UUID) error
	InvalidateUserVerificationTokens(ctx context.Context, userID uuid.UUID) error
}

VerificationStore defines the interface for verification token persistence.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL