admin

package
v0.0.0-...-b140ed9 Latest Latest
Warning

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

Go to latest
Published: May 11, 2026 License: MIT Imports: 48 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// KeyTypeAdmin is the key type for admin API keys (/admin/* routes).
	KeyTypeAdmin = "admin"
	// KeyTypeApp is the key type for per-application API keys.
	KeyTypeApp = "app"
)
View Source
const ExportActivityLogsMaxRows = 10_000

ExportActivityLogsMaxRows is the hard cap for admin GUI log exports.

View Source
const ExportUsersMaxRows = 10_000

ExportUsersMaxRows is the hard cap for user export operations.

Variables

This section is empty.

Functions

func GenerateApiKey

func GenerateApiKey(keyType string) (rawKey, keyHash, keyPrefix, keySuffix string, err error)

GenerateApiKey creates a new random API key for the given type. Returns (rawKey, hash, prefix, suffix). The rawKey should be shown to the user once and never stored.

func HashApiKey

func HashApiKey(rawKey string) string

HashApiKey computes the SHA-256 hex digest of a raw API key.

Types

type AccountRepository

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

AccountRepository handles database operations for admin accounts

func NewAccountRepository

func NewAccountRepository(pool *pgxpool.Pool) *AccountRepository

NewAccountRepository creates a new AccountRepository backed by pgx/SQLC.

func (*AccountRepository) ClearBackupEmail

func (r *AccountRepository) ClearBackupEmail(id string) error

ClearBackupEmail removes the backup email from an admin account.

func (*AccountRepository) Count

func (r *AccountRepository) Count() (int64, error)

Count returns the total number of admin accounts

func (*AccountRepository) Create

func (r *AccountRepository) Create(account *models.AdminAccount) error

Create stores a new admin account in the database. The account pointer is updated with the generated ID and timestamps.

func (*AccountRepository) DeleteByID

func (r *AccountRepository) DeleteByID(id string) error

DeleteByID removes an admin account by ID

func (*AccountRepository) Disable2FA

func (r *AccountRepository) Disable2FA(id string) error

Disable2FA deactivates two-factor authentication for an admin account, clearing all 2FA-related fields.

func (*AccountRepository) Enable2FA

func (r *AccountRepository) Enable2FA(id, method, secret string, recoveryCodes []byte) error

Enable2FA activates two-factor authentication for an admin account. It sets the method, secret, and recovery codes in a single update.

func (*AccountRepository) GetByEmail

func (r *AccountRepository) GetByEmail(email string) (*models.AdminAccount, error)

GetByEmail retrieves an admin account by email address.

func (*AccountRepository) GetByID

func (r *AccountRepository) GetByID(id string) (*models.AdminAccount, error)

GetByID retrieves an admin account by ID

func (*AccountRepository) GetByUsername

func (r *AccountRepository) GetByUsername(username string) (*models.AdminAccount, error)

GetByUsername retrieves an admin account by username

func (*AccountRepository) GetByUsernameOrEmail

func (r *AccountRepository) GetByUsernameOrEmail(identifier string) (*models.AdminAccount, error)

GetByUsernameOrEmail retrieves an admin account by username or email. This allows admins to log in using either their username or email address.

func (*AccountRepository) ListAll

func (r *AccountRepository) ListAll() ([]models.AdminAccount, error)

ListAll retrieves all admin accounts ordered by creation date

func (*AccountRepository) SetBackupEmail

func (r *AccountRepository) SetBackupEmail(id, backupEmail string) error

SetBackupEmail sets (or updates) the backup email for an admin account. It marks backup_email_verified = false since the new address hasn't been confirmed.

func (*AccountRepository) UpdateEmail

func (r *AccountRepository) UpdateEmail(id, email string) error

UpdateEmail sets the email address for an admin account

func (*AccountRepository) UpdateLastLogin

func (r *AccountRepository) UpdateLastLogin(id string) error

UpdateLastLogin sets the LastLoginAt timestamp for an admin account

func (*AccountRepository) UpdateMagicLinkEnabled

func (r *AccountRepository) UpdateMagicLinkEnabled(id string, enabled bool) error

UpdateMagicLinkEnabled sets the magic_link_enabled flag for an admin account.

func (*AccountRepository) UpdatePassword

func (r *AccountRepository) UpdatePassword(id, passwordHash string) error

UpdatePassword updates the password hash for an admin account

func (*AccountRepository) UpdateRecoveryCodes

func (r *AccountRepository) UpdateRecoveryCodes(id string, codes []byte) error

UpdateRecoveryCodes replaces the recovery codes for an admin account.

type AccountService

type AccountService struct {
	Repo         *AccountRepository
	EmailService *emailpkg.Service
	SessionTTL   time.Duration
}

AccountService handles admin authentication and session management

func NewAccountService

func NewAccountService(repo *AccountRepository, emailService *emailpkg.Service, sessionTTL time.Duration) *AccountService

NewAccountService creates a new AccountService

func (*AccountService) Authenticate

func (s *AccountService) Authenticate(username, password string) (*models.AdminAccount, error)

Authenticate validates admin credentials and updates the last login timestamp. Returns the admin account on success, or an error on failure.

func (*AccountService) ChangePassword

func (s *AccountService) ChangePassword(adminID, currentPassword, newPassword string) error

ChangePassword updates the admin's password after verifying the current one.

func (*AccountService) Consume2FATempSession

func (s *AccountService) Consume2FATempSession(tempToken string) (*models.AdminAccount, error)

Consume2FATempSession validates and then deletes a temporary 2FA session. Used after successful 2FA verification to prevent replay.

func (*AccountService) Create2FATempSession

func (s *AccountService) Create2FATempSession(adminID string) (string, error)

Create2FATempSession stores a temporary session token for an admin who has passed password authentication but still needs to complete 2FA verification. Returns the temp token.

func (*AccountService) CreateSession

func (s *AccountService) CreateSession(adminID string) (string, error)

CreateSession generates a secure session token and stores it in Redis. Returns the session ID that should be set as a cookie value.

func (*AccountService) Disable2FA

func (s *AccountService) Disable2FA(adminID, password string) error

Disable2FA disables two-factor authentication for an admin after password verification.

func (*AccountService) EnableEmail2FA

func (s *AccountService) EnableEmail2FA(adminID string) ([]string, error)

EnableEmail2FA enables email-based 2FA for an admin account. Requires that the admin has an email address set. Returns the recovery codes (shown once to the user).

func (*AccountService) EnableTOTP

func (s *AccountService) EnableTOTP(adminID string) ([]string, error)

EnableTOTP finalizes TOTP-based 2FA for an admin. It persists the secret from Redis to the database, generates recovery codes, and cleans up the temp secret. Returns the recovery codes (shown once to the user).

func (*AccountService) GenerateAndSendEmail2FACode

func (s *AccountService) GenerateAndSendEmail2FACode(adminID string) error

GenerateAndSendEmail2FACode generates a 6-digit code, stores it in Redis, and sends it to the admin's email address. Used during login verification.

func (*AccountService) GenerateCSRFToken

func (s *AccountService) GenerateCSRFToken(sessionID string) (string, error)

GenerateCSRFToken returns the existing CSRF token for the session if one exists, or creates and stores a new one. This ensures a stable token per session so that HTMX GET requests (which also pass through the middleware) don't invalidate the token held in the page's <meta> tag.

func (*AccountService) GenerateTOTPSecret

func (s *AccountService) GenerateTOTPSecret(adminID, username string) (*TwoFASetupResponse, error)

GenerateTOTPSecret creates a new TOTP secret for an admin and stores it temporarily in Redis (10-minute TTL). Returns the secret and QR code data.

func (*AccountService) Logout

func (s *AccountService) Logout(sessionID string) error

Logout removes a session from Redis.

func (*AccountService) RegenerateRecoveryCodes

func (s *AccountService) RegenerateRecoveryCodes(adminID, password string) ([]string, error)

RegenerateRecoveryCodes generates a new set of 8 recovery codes after password verification. Returns the new codes (shown once to the user).

func (*AccountService) UpdateEmail

func (s *AccountService) UpdateEmail(adminID, email string) error

UpdateEmail updates the email address for an admin account.

func (*AccountService) Validate2FATempSession

func (s *AccountService) Validate2FATempSession(tempToken string) (*models.AdminAccount, error)

Validate2FATempSession validates a temporary 2FA session and returns the admin account.

func (*AccountService) ValidateCSRFToken

func (s *AccountService) ValidateCSRFToken(sessionID, token string) bool

ValidateCSRFToken checks if the provided CSRF token matches the one stored for the session.

func (*AccountService) ValidateSession

func (s *AccountService) ValidateSession(sessionID string) (*models.AdminAccount, error)

ValidateSession checks if a session is valid and returns the associated admin account.

func (*AccountService) VerifyEmail2FACode

func (s *AccountService) VerifyEmail2FACode(adminID, code string) error

VerifyEmail2FACode validates a 6-digit email code for an admin.

func (*AccountService) VerifyRecoveryCode

func (s *AccountService) VerifyRecoveryCode(adminID, recoveryCode string) error

VerifyRecoveryCode validates and consumes a single-use recovery code.

func (*AccountService) VerifyTOTPCode

func (s *AccountService) VerifyTOTPCode(adminID, code string) error

VerifyTOTPCode validates a TOTP code for an admin with TOTP-based 2FA enabled.

func (*AccountService) VerifyTOTPSetup

func (s *AccountService) VerifyTOTPSetup(adminID, code string) error

VerifyTOTPSetup validates a TOTP code against the temporary secret stored in Redis. This is called during initial 2FA setup to confirm the user has correctly configured their app.

type ActivityLogDetail

type ActivityLogDetail struct {
	ID        uuid.UUID  `json:"id"`
	AppID     uuid.UUID  `json:"app_id"`
	AppName   string     `json:"app_name"`
	UserID    uuid.UUID  `json:"user_id"`
	UserEmail string     `json:"user_email"`
	EventType string     `json:"event_type"`
	Severity  string     `json:"severity"`
	IPAddress string     `json:"ip_address"`
	UserAgent string     `json:"user_agent"`
	Details   string     `json:"details"`
	IsAnomaly bool       `json:"is_anomaly"`
	ExpiresAt *time.Time `json:"expires_at"`
	Timestamp time.Time  `json:"timestamp"`
}

ActivityLogDetail represents a full activity log view for the admin GUI detail panel.

type ActivityLogExportItem

type ActivityLogExportItem struct {
	ActivityLogListItem
	UserAgent string `json:"user_agent"`
}

ActivityLogExportItem extends ActivityLogListItem with extra fields useful for compliance exports.

type ActivityLogListItem

type ActivityLogListItem struct {
	ID        uuid.UUID `json:"id"`
	AppID     uuid.UUID `json:"app_id"`
	AppName   string    `json:"app_name"`
	UserID    uuid.UUID `json:"user_id"`
	UserEmail string    `json:"user_email"`
	EventType string    `json:"event_type"`
	Severity  string    `json:"severity"`
	IPAddress string    `json:"ip_address"`
	IsAnomaly bool      `json:"is_anomaly"`
	Timestamp time.Time `json:"timestamp"`
}

ActivityLogListItem represents an activity log row in the admin GUI list view.

type ApiKeyListItem

type ApiKeyListItem struct {
	ID         uuid.UUID  `json:"id"`
	KeyType    string     `json:"key_type"`
	Name       string     `json:"name"`
	KeyPrefix  string     `json:"key_prefix"`
	KeySuffix  string     `json:"key_suffix"`
	Scopes     string     `json:"scopes"`
	AppID      *uuid.UUID `json:"app_id"`
	AppName    string     `json:"app_name"`
	TenantName string     `json:"tenant_name"`
	ExpiresAt  *time.Time `json:"expires_at"`
	LastUsedAt *time.Time `json:"last_used_at"`
	IsRevoked  bool       `json:"is_revoked"`
	CreatedAt  time.Time  `json:"created_at"`
}

ApiKeyListItem represents an API key row in the admin GUI list view.

type ApiKeyNotificationService

type ApiKeyNotificationService struct {
	AdminEmail string
	// contains filtered or unexported fields
}

ApiKeyNotificationService sends expiry-warning emails for API keys that are about to expire. It runs as an in-process background goroutine, checking once per day (same pattern as internal/log/cleanup.go).

Notifications are sent:

  • 7 days before expiry (deduplicated via notified_7_days_at column)
  • 1 day before expiry (deduplicated via notified_1_day_at column)

The recipient is the system admin email configured via the ADMIN_EMAIL environment variable. If the variable is empty, notifications are skipped.

func NewApiKeyNotificationService

func NewApiKeyNotificationService(repo *Repository, emailSvc *email.Service, adminEmail string) *ApiKeyNotificationService

NewApiKeyNotificationService creates the service but does not start it.

func (*ApiKeyNotificationService) Shutdown

func (s *ApiKeyNotificationService) Shutdown()

Shutdown stops the background worker.

func (*ApiKeyNotificationService) Start

func (s *ApiKeyNotificationService) Start()

Start launches the background worker goroutine.

type ApiKeyUsagePoint

type ApiKeyUsagePoint struct {
	PeriodDate   time.Time `json:"period_date"`
	RequestCount int64     `json:"request_count"`
}

ApiKeyUsagePoint is a single data point for usage analytics (one day).

type AppCustomizationSettings

type AppCustomizationSettings struct {
	// Login Page Branding
	LoginLogoURL        string
	LoginPrimaryColor   string
	LoginSecondaryColor string
	LoginDisplayName    string
	// Password Policy
	PwMinLength     int
	PwMaxLength     int
	PwRequireUpper  bool
	PwRequireLower  bool
	PwRequireDigit  bool
	PwRequireSymbol bool
	PwHistoryCount  int
	PwMaxAgeDays    int
	// Token TTL overrides (0 = use global defaults)
	AccessTokenTTLMinutes int
	RefreshTokenTTLHours  int
	// Email Action Link Paths (empty = use system defaults)
	ResetPasswordPath string
	MagicLinkPath     string
	VerifyEmailPath   string
}

AppCustomizationSettings holds per-application branding, password policy, token TTL, and email link path fields.

type AppListItem

type AppListItem struct {
	ID                  uuid.UUID
	TenantID            uuid.UUID
	Name                string
	Description         string
	TenantName          string
	OAuthConfigCount    int64
	TwoFAEnabled        bool
	TwoFARequired       bool
	Passkey2FAEnabled   bool
	PasskeyLoginEnabled bool
	MagicLinkEnabled    bool
	CreatedAt           time.Time
	UpdatedAt           time.Time
}

AppListItem holds an application with its tenant name and OAuth config count for list views.

type AppWithTenant

type AppWithTenant struct {
	ID         uuid.UUID
	Name       string
	TenantName string
}

AppWithTenant holds an application ID, name, and its tenant name for dropdown selects.

type BruteForceAppSettings

type BruteForceAppSettings struct {
	LockoutEnabled   *bool
	LockoutThreshold *int
	LockoutDurations *string
	LockoutWindow    *string
	LockoutTierTTL   *string
	DelayEnabled     *bool
	DelayStartAfter  *int
	DelayMaxSeconds  *int
	DelayTierTTL     *string
	CaptchaEnabled   *bool
	CaptchaSiteKey   *string
	CaptchaSecretKey *string // empty string in form = keep existing; nil = clear override
	CaptchaThreshold *int
}

BruteForceAppSettings holds per-application brute-force override values. Nil pointers mean "clear override, use global default".

type DashboardService

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

DashboardService provides aggregated data for the admin dashboard.

func NewDashboardService

func NewDashboardService(pool *pgxpool.Pool) *DashboardService

NewDashboardService creates a new DashboardService.

func (*DashboardService) GetRecentActivity

func (s *DashboardService) GetRecentActivity(limit int) ([]models.ActivityLog, error)

GetRecentActivity returns the most recent activity log entries.

func (*DashboardService) GetStats

func (s *DashboardService) GetStats() (*DashboardStats, error)

GetStats returns aggregate counts for the dashboard stat cards.

type DashboardStats

type DashboardStats struct {
	TotalUsers         int64
	ActiveUsers        int64
	InactiveUsers      int64
	TotalTenants       int64
	TotalApps          int64
	RecentEventsCount  int64 // activity logs in last 24 hours
	ActiveSessions     int64 // active user sessions across all apps
	TrustedDeviceCount int64 // active (non-expired) trusted devices
	VerifiedPhoneCount int64 // users with phone_verified = true
}

DashboardStats holds aggregate counts for the admin dashboard.

type GUIHandler

type GUIHandler struct {
	AccountService    *AccountService
	DashboardService  *DashboardService
	Repo              *Repository
	SettingsService   *SettingsService
	EmailService      *email.Service
	RBACService       *rbac.Service
	PasskeyService    *passkeypkg.Service
	IPRuleRepo        *geoip.IPRuleRepository        // IP rule repository (nil = IP rules disabled)
	IPRuleEvaluator   *geoip.IPRuleEvaluator         // IP rule evaluator for cache invalidation (nil = disabled)
	GeoIPService      *geoip.Service                 // GeoIP service for IP lookups (nil = disabled)
	BruteForceService *bruteforce.Service            // Brute-force protection service for account unlock (nil = disabled)
	WebhookService    *webhook.Service               // Webhook management service (nil = webhooks disabled)
	OIDCService       *oidcpkg.Service               // OIDC provider service (nil = OIDC disabled)
	TrustedDeviceRepo *twofa.TrustedDeviceRepository // Trusted device repository (nil = feature disabled)
	HealthHandler     *healthpkg.Handler             // System health + metrics (nil = monitoring disabled)
	AdminSessionTTL   time.Duration                  // Admin session cookie TTL
	AdminBaseURL      string                         // Base URL for admin links (e.g. magic link emails)
	AccessTokenTTL    time.Duration                  // Access token TTL (used for session status display)
	BasePath          string                         // URL path prefix for admin GUI (e.g. "/gui")
}

GUIHandler serves HTML pages for the Admin GUI. Separate from Handler (which serves the JSON admin API).

func NewGUIHandler

func NewGUIHandler(accountService *AccountService, dashboardService *DashboardService, repo *Repository, settingsService *SettingsService, emailService *email.Service, rbacService *rbac.Service, passkeyService *passkeypkg.Service) *GUIHandler

NewGUIHandler creates a new GUIHandler

func (*GUIHandler) ApiKeyCreate

func (h *GUIHandler) ApiKeyCreate(c *gin.Context)

ApiKeyCreate handles creating a new API key. POST /gui/api-keys

func (*GUIHandler) ApiKeyCreateForm

func (h *GUIHandler) ApiKeyCreateForm(c *gin.Context)

ApiKeyCreateForm returns the API key creation form HTML fragment. GET /gui/api-keys/new

func (*GUIHandler) ApiKeyDelete

func (h *GUIHandler) ApiKeyDelete(c *gin.Context)

ApiKeyDelete handles permanently deleting an API key. DELETE /gui/api-keys/:id

func (*GUIHandler) ApiKeyDeleteConfirm

func (h *GUIHandler) ApiKeyDeleteConfirm(c *gin.Context)

ApiKeyDeleteConfirm returns the delete confirmation modal body. GET /gui/api-keys/:id/delete

func (*GUIHandler) ApiKeyEditForm

func (h *GUIHandler) ApiKeyEditForm(c *gin.Context)

ApiKeyEditForm returns the edit form partial for an existing API key. GET /gui/api-keys/:id/edit

func (*GUIHandler) ApiKeyFormCancel

func (h *GUIHandler) ApiKeyFormCancel(c *gin.Context)

ApiKeyFormCancel clears the API key form. GET /gui/api-keys/form-cancel

func (*GUIHandler) ApiKeyList

func (h *GUIHandler) ApiKeyList(c *gin.Context)

ApiKeyList returns the paginated API key list partial (HTMX fragment). GET /gui/api-keys/list

func (*GUIHandler) ApiKeyRevoke

func (h *GUIHandler) ApiKeyRevoke(c *gin.Context)

ApiKeyRevoke handles revoking an API key. PUT /gui/api-keys/:id/revoke

func (*GUIHandler) ApiKeyRevokeConfirm

func (h *GUIHandler) ApiKeyRevokeConfirm(c *gin.Context)

ApiKeyRevokeConfirm returns the revoke confirmation modal body. GET /gui/api-keys/:id/revoke

func (*GUIHandler) ApiKeyUpdate

func (h *GUIHandler) ApiKeyUpdate(c *gin.Context)

ApiKeyUpdate handles updating name, description, and scopes for an existing API key. PUT /gui/api-keys/:id

func (*GUIHandler) ApiKeyUsagePage

func (h *GUIHandler) ApiKeyUsagePage(c *gin.Context)

ApiKeyUsagePage renders the full usage analytics page for a single API key. GET /gui/api-keys/:id/usage

func (*GUIHandler) ApiKeysPage

func (h *GUIHandler) ApiKeysPage(c *gin.Context)

ApiKeysPage renders the API Keys management page. GET /gui/api-keys

func (*GUIHandler) AppCreate

func (h *GUIHandler) AppCreate(c *gin.Context)

AppCreate handles creating a new application. POST /gui/applications

func (*GUIHandler) AppCreateForm

func (h *GUIHandler) AppCreateForm(c *gin.Context)

AppCreateForm returns the empty create form HTML fragment for HTMX. GET /gui/applications/new

func (*GUIHandler) AppDelete

func (h *GUIHandler) AppDelete(c *gin.Context)

AppDelete handles deleting an application. DELETE /gui/applications/:id

func (*GUIHandler) AppDeleteConfirm

func (h *GUIHandler) AppDeleteConfirm(c *gin.Context)

AppDeleteConfirm returns the delete confirmation modal body for HTMX. GET /gui/applications/:id/delete

func (*GUIHandler) AppEditForm

func (h *GUIHandler) AppEditForm(c *gin.Context)

AppEditForm returns the pre-filled edit form HTML fragment for HTMX. GET /gui/applications/:id/edit

func (*GUIHandler) AppFormCancel

func (h *GUIHandler) AppFormCancel(c *gin.Context)

AppFormCancel returns an empty response to clear the form container. GET /gui/applications/form-cancel

func (*GUIHandler) AppList

func (h *GUIHandler) AppList(c *gin.Context)

AppList returns the application table HTML fragment for HTMX. GET /gui/applications/list

func (*GUIHandler) AppPage

func (h *GUIHandler) AppPage(c *gin.Context)

AppPage renders the application management page. GET /gui/applications

func (*GUIHandler) AppUpdate

func (h *GUIHandler) AppUpdate(c *gin.Context)

AppUpdate handles updating an application. PUT /gui/applications/:id

func (*GUIHandler) Dashboard

func (h *GUIHandler) Dashboard(c *gin.Context)

Dashboard renders the main dashboard page. GET /gui/

func (*GUIHandler) DashboardActivity

func (h *GUIHandler) DashboardActivity(c *gin.Context)

DashboardActivity returns the recent activity table HTML fragment for HTMX. GET /gui/dashboard/activity

func (*GUIHandler) DashboardStats

func (h *GUIHandler) DashboardStats(c *gin.Context)

DashboardStats returns the stats cards HTML fragment for HTMX. GET /gui/dashboard/stats

func (*GUIHandler) EmailServerCreate

func (h *GUIHandler) EmailServerCreate(c *gin.Context)

EmailServerCreate handles creating a new email server config. POST /gui/email-servers

func (*GUIHandler) EmailServerCreateForm

func (h *GUIHandler) EmailServerCreateForm(c *gin.Context)

EmailServerCreateForm returns the empty create form for email server config. GET /gui/email-servers/new

func (*GUIHandler) EmailServerDelete

func (h *GUIHandler) EmailServerDelete(c *gin.Context)

EmailServerDelete handles deleting an email server config. DELETE /gui/email-servers/:id

func (*GUIHandler) EmailServerDeleteConfirm

func (h *GUIHandler) EmailServerDeleteConfirm(c *gin.Context)

EmailServerDeleteConfirm returns the delete confirmation modal body. GET /gui/email-servers/:id/delete

func (*GUIHandler) EmailServerEditForm

func (h *GUIHandler) EmailServerEditForm(c *gin.Context)

EmailServerEditForm returns the pre-filled edit form for an email server config. GET /gui/email-servers/:id/edit

func (*GUIHandler) EmailServerFormCancel

func (h *GUIHandler) EmailServerFormCancel(c *gin.Context)

EmailServerFormCancel clears the form container. GET /gui/email-servers/form-cancel

func (*GUIHandler) EmailServerList

func (h *GUIHandler) EmailServerList(c *gin.Context)

EmailServerList returns the email server config list partial (HTMX fragment). GET /gui/email-servers/list

func (*GUIHandler) EmailServerSendTest

func (h *GUIHandler) EmailServerSendTest(c *gin.Context)

EmailServerSendTest sends a test email for a given SMTP config. POST /gui/email-servers/:id/test

func (*GUIHandler) EmailServerUpdate

func (h *GUIHandler) EmailServerUpdate(c *gin.Context)

EmailServerUpdate handles updating an email server config. PUT /gui/email-servers/:id

func (*GUIHandler) EmailServersPage

func (h *GUIHandler) EmailServersPage(c *gin.Context)

EmailServersPage renders the email server config management page. GET /gui/email-servers

func (*GUIHandler) EmailTemplateCreate

func (h *GUIHandler) EmailTemplateCreate(c *gin.Context)

EmailTemplateCreate handles creating a new email template. POST /gui/email-templates

func (*GUIHandler) EmailTemplateCreateForm

func (h *GUIHandler) EmailTemplateCreateForm(c *gin.Context)

EmailTemplateCreateForm returns the empty create form. GET /gui/email-templates/new

func (*GUIHandler) EmailTemplateDelete

func (h *GUIHandler) EmailTemplateDelete(c *gin.Context)

EmailTemplateDelete handles deleting an email template. DELETE /gui/email-templates/:id

func (*GUIHandler) EmailTemplateDeleteConfirm

func (h *GUIHandler) EmailTemplateDeleteConfirm(c *gin.Context)

EmailTemplateDeleteConfirm returns the delete confirmation modal body. GET /gui/email-templates/:id/delete

func (*GUIHandler) EmailTemplateEditForm

func (h *GUIHandler) EmailTemplateEditForm(c *gin.Context)

EmailTemplateEditForm returns the pre-filled edit form for an email template. GET /gui/email-templates/:id/edit

func (*GUIHandler) EmailTemplateEditorWindow

func (h *GUIHandler) EmailTemplateEditorWindow(c *gin.Context)

EmailTemplateEditorWindow renders a standalone editor window with split editor/preview. POST /gui/email-templates/editor-window

func (*GUIHandler) EmailTemplateFormCancel

func (h *GUIHandler) EmailTemplateFormCancel(c *gin.Context)

EmailTemplateFormCancel clears the form container. Also clears the preview container via HTMX out-of-band swap. GET /gui/email-templates/form-cancel

func (*GUIHandler) EmailTemplateList

func (h *GUIHandler) EmailTemplateList(c *gin.Context)

EmailTemplateList returns the email template list partial (HTMX fragment). GET /gui/email-templates/list

func (*GUIHandler) EmailTemplatePreview

func (h *GUIHandler) EmailTemplatePreview(c *gin.Context)

EmailTemplatePreview renders a preview of the template. POST /gui/email-templates/preview

func (*GUIHandler) EmailTemplateReset

func (h *GUIHandler) EmailTemplateReset(c *gin.Context)

EmailTemplateReset resets a template's content to the built-in hardcoded default. POST /gui/email-templates/:id/reset

func (*GUIHandler) EmailTemplateResetConfirm

func (h *GUIHandler) EmailTemplateResetConfirm(c *gin.Context)

EmailTemplateResetConfirm returns the reset confirmation modal body. GET /gui/email-templates/:id/reset

func (*GUIHandler) EmailTemplateUpdate

func (h *GUIHandler) EmailTemplateUpdate(c *gin.Context)

EmailTemplateUpdate handles updating an email template. PUT /gui/email-templates/:id

func (*GUIHandler) EmailTemplatesPage

func (h *GUIHandler) EmailTemplatesPage(c *gin.Context)

EmailTemplatesPage renders the email templates management page. GET /gui/email-templates

func (*GUIHandler) EmailTypeCreate

func (h *GUIHandler) EmailTypeCreate(c *gin.Context)

EmailTypeCreate handles creating a new custom email type. POST /gui/email-types

func (*GUIHandler) EmailTypeCreateForm

func (h *GUIHandler) EmailTypeCreateForm(c *gin.Context)

EmailTypeCreateForm returns the empty create form for email types. GET /gui/email-types/new

func (*GUIHandler) EmailTypeDelete

func (h *GUIHandler) EmailTypeDelete(c *gin.Context)

EmailTypeDelete handles deleting a custom email type. DELETE /gui/email-types/:id

func (*GUIHandler) EmailTypeDeleteConfirm

func (h *GUIHandler) EmailTypeDeleteConfirm(c *gin.Context)

EmailTypeDeleteConfirm returns the delete confirmation modal body. GET /gui/email-types/:id/delete

func (*GUIHandler) EmailTypeEditForm

func (h *GUIHandler) EmailTypeEditForm(c *gin.Context)

EmailTypeEditForm returns the pre-filled edit form for an email type. GET /gui/email-types/:id/edit

func (*GUIHandler) EmailTypeFormCancel

func (h *GUIHandler) EmailTypeFormCancel(c *gin.Context)

EmailTypeFormCancel clears the email type form container. GET /gui/email-types/form-cancel

func (*GUIHandler) EmailTypeList

func (h *GUIHandler) EmailTypeList(c *gin.Context)

EmailTypeList returns the email type list partial (HTMX fragment). GET /gui/email-types/list

func (*GUIHandler) EmailTypeUpdate

func (h *GUIHandler) EmailTypeUpdate(c *gin.Context)

EmailTypeUpdate handles updating an email type. PUT /gui/email-types/:id

func (*GUIHandler) EmailTypesPage

func (h *GUIHandler) EmailTypesPage(c *gin.Context)

EmailTypesPage renders the email types management page. GET /gui/email-types

func (*GUIHandler) EmailVariablesList

func (h *GUIHandler) EmailVariablesList(c *gin.Context)

EmailVariablesList returns the list of well-known email template variables as JSON. GET /gui/email-variables

func (*GUIHandler) IPRuleCheckAccess

func (h *GUIHandler) IPRuleCheckAccess(c *gin.Context)

IPRuleCheckAccess checks IP access for testing purposes (HTMX partial). POST /gui/ip-rules/check

func (*GUIHandler) IPRuleCreate

func (h *GUIHandler) IPRuleCreate(c *gin.Context)

IPRuleCreate handles IP rule creation. POST /gui/ip-rules

func (*GUIHandler) IPRuleCreateForm

func (h *GUIHandler) IPRuleCreateForm(c *gin.Context)

IPRuleCreateForm renders the IP rule create form (HTMX partial). GET /gui/ip-rules/new

func (*GUIHandler) IPRuleDelete

func (h *GUIHandler) IPRuleDelete(c *gin.Context)

IPRuleDelete handles IP rule deletion. DELETE /gui/ip-rules/:id

func (*GUIHandler) IPRuleDeleteConfirm

func (h *GUIHandler) IPRuleDeleteConfirm(c *gin.Context)

IPRuleDeleteConfirm renders the IP rule delete confirmation (HTMX partial). GET /gui/ip-rules/:id/delete

func (*GUIHandler) IPRuleEditForm

func (h *GUIHandler) IPRuleEditForm(c *gin.Context)

IPRuleEditForm renders the IP rule edit form (HTMX partial). GET /gui/ip-rules/:id/edit

func (*GUIHandler) IPRuleFormCancel

func (h *GUIHandler) IPRuleFormCancel(c *gin.Context)

IPRuleFormCancel handles IP rule form cancellation (HTMX partial). GET /gui/ip-rules/form-cancel

func (*GUIHandler) IPRuleList

func (h *GUIHandler) IPRuleList(c *gin.Context)

IPRuleList renders the IP rules list (HTMX partial). GET /gui/ip-rules/list

func (*GUIHandler) IPRulePage

func (h *GUIHandler) IPRulePage(c *gin.Context)

IPRulePage renders the IP Rules management page. GET /gui/ip-rules

func (*GUIHandler) IPRuleUpdate

func (h *GUIHandler) IPRuleUpdate(c *gin.Context)

IPRuleUpdate handles IP rule update. PUT /gui/ip-rules/:id

func (*GUIHandler) LogDetail

func (h *GUIHandler) LogDetail(c *gin.Context)

LogDetail returns the activity log detail partial (HTMX fragment). GET /gui/logs/:id

func (*GUIHandler) LogExport

func (h *GUIHandler) LogExport(c *gin.Context)

LogExport streams activity logs as a downloadable CSV or JSON file. GET /gui/logs/export

func (*GUIHandler) LogList

func (h *GUIHandler) LogList(c *gin.Context)

LogList returns the paginated activity log list partial (HTMX fragment). GET /gui/logs/list

func (*GUIHandler) LoginPage

func (h *GUIHandler) LoginPage(c *gin.Context)

LoginPage renders the login form. GET /gui/login

func (*GUIHandler) LoginSubmit

func (h *GUIHandler) LoginSubmit(c *gin.Context)

LoginSubmit handles login form submission. If the admin has 2FA enabled, it creates a temporary session and redirects to the 2FA verification page instead of creating a full session. POST /gui/login

func (*GUIHandler) Logout

func (h *GUIHandler) Logout(c *gin.Context)

Logout destroys the admin session and redirects to login. GET /gui/logout

func (*GUIHandler) LogsPage

func (h *GUIHandler) LogsPage(c *gin.Context)

LogsPage renders the activity logs viewer page. GET /gui/logs

func (*GUIHandler) MagicLinkLoginRequest

func (h *GUIHandler) MagicLinkLoginRequest(c *gin.Context)

MagicLinkLoginRequest handles the magic link login request from the login page. It looks up the admin by email, checks if magic link is enabled, generates a token, sends the email, and returns a generic success message (to prevent email enumeration). POST /gui/magic-link-login

func (*GUIHandler) MagicLinkLoginVerify

func (h *GUIHandler) MagicLinkLoginVerify(c *gin.Context)

MagicLinkLoginVerify handles the magic link verification callback. On success, creates a full admin session (bypassing 2FA like passkey login) and redirects. GET /gui/magic-link-login/verify

func (*GUIHandler) MonitoringHealth

func (h *GUIHandler) MonitoringHealth(c *gin.Context)

MonitoringHealth returns the health check status partial for HTMX polling. GET /gui/monitoring/health

func (*GUIHandler) MonitoringMetrics

func (h *GUIHandler) MonitoringMetrics(c *gin.Context)

MonitoringMetrics returns the Prometheus metrics summary partial for HTMX polling. GET /gui/monitoring/metrics

func (*GUIHandler) MonitoringPage

func (h *GUIHandler) MonitoringPage(c *gin.Context)

MonitoringPage renders the system health monitoring page. GET /gui/monitoring

func (*GUIHandler) MyAccount2FADisable

func (h *GUIHandler) MyAccount2FADisable(c *gin.Context)

MyAccount2FADisable disables 2FA for the admin (requires password). POST /gui/my-account/2fa/disable

func (*GUIHandler) MyAccount2FAEnableEmail

func (h *GUIHandler) MyAccount2FAEnableEmail(c *gin.Context)

MyAccount2FAEnableEmail enables email-based 2FA. POST /gui/my-account/2fa/enable-email

func (*GUIHandler) MyAccount2FAGenerateTOTP

func (h *GUIHandler) MyAccount2FAGenerateTOTP(c *gin.Context)

MyAccount2FAGenerateTOTP generates a TOTP secret and returns the QR code partial. POST /gui/my-account/2fa/generate

func (*GUIHandler) MyAccount2FARegenerateCodes

func (h *GUIHandler) MyAccount2FARegenerateCodes(c *gin.Context)

MyAccount2FARegenerateCodes regenerates recovery codes (requires password). POST /gui/my-account/2fa/regenerate-codes

func (*GUIHandler) MyAccount2FAStatus

func (h *GUIHandler) MyAccount2FAStatus(c *gin.Context)

MyAccount2FAStatus returns the current 2FA status as an HTMX partial. GET /gui/my-account/2fa/status

func (*GUIHandler) MyAccount2FAVerifyTOTP

func (h *GUIHandler) MyAccount2FAVerifyTOTP(c *gin.Context)

MyAccount2FAVerifyTOTP verifies the TOTP code during setup. POST /gui/my-account/2fa/verify-totp

func (*GUIHandler) MyAccountBackupEmailStatus

func (h *GUIHandler) MyAccountBackupEmailStatus(c *gin.Context)

MyAccountBackupEmailStatus returns the current backup email status as an HTML partial. GET /gui/my-account/backup-email/status

func (*GUIHandler) MyAccountChangePassword

func (h *GUIHandler) MyAccountChangePassword(c *gin.Context)

MyAccountChangePassword handles password changes. POST /gui/my-account/password

func (*GUIHandler) MyAccountMagicLinkStatus

func (h *GUIHandler) MyAccountMagicLinkStatus(c *gin.Context)

MyAccountMagicLinkStatus returns the current magic link status as an HTMX partial. GET /gui/my-account/magic-link/status

func (*GUIHandler) MyAccountMagicLinkToggle

func (h *GUIHandler) MyAccountMagicLinkToggle(c *gin.Context)

MyAccountMagicLinkToggle enables or disables magic link login for the current admin. POST /gui/my-account/magic-link/toggle

func (*GUIHandler) MyAccountPage

func (h *GUIHandler) MyAccountPage(c *gin.Context)

MyAccountPage renders the "My Account" page with 2FA settings. GET /gui/my-account

func (*GUIHandler) MyAccountPasskeyBeginRegister

func (h *GUIHandler) MyAccountPasskeyBeginRegister(c *gin.Context)

MyAccountPasskeyBeginRegister starts the WebAuthn registration ceremony for the admin. POST /gui/my-account/passkeys/register/begin

func (*GUIHandler) MyAccountPasskeyDelete

func (h *GUIHandler) MyAccountPasskeyDelete(c *gin.Context)

MyAccountPasskeyDelete deletes a passkey for the current admin. DELETE /gui/my-account/passkeys/:id

func (*GUIHandler) MyAccountPasskeyFinishRegister

func (h *GUIHandler) MyAccountPasskeyFinishRegister(c *gin.Context)

MyAccountPasskeyFinishRegister completes the WebAuthn registration ceremony for the admin. POST /gui/my-account/passkeys/register/finish

func (*GUIHandler) MyAccountPasskeyRename

func (h *GUIHandler) MyAccountPasskeyRename(c *gin.Context)

MyAccountPasskeyRename renames a passkey for the current admin. POST /gui/my-account/passkeys/:id/rename

func (*GUIHandler) MyAccountPasskeyStatus

func (h *GUIHandler) MyAccountPasskeyStatus(c *gin.Context)

MyAccountPasskeyStatus returns the current passkey status as an HTMX partial. GET /gui/my-account/passkeys/status

func (*GUIHandler) MyAccountRemoveBackupEmail

func (h *GUIHandler) MyAccountRemoveBackupEmail(c *gin.Context)

MyAccountRemoveBackupEmail removes the backup email from the admin account. DELETE /gui/my-account/backup-email

func (*GUIHandler) MyAccountRevokeTrustedDevice

func (h *GUIHandler) MyAccountRevokeTrustedDevice(c *gin.Context)

MyAccountRevokeTrustedDevice revokes one of the admin's own trusted devices. DELETE /gui/my-account/trusted-devices/:device_id

func (*GUIHandler) MyAccountSetBackupEmail

func (h *GUIHandler) MyAccountSetBackupEmail(c *gin.Context)

MyAccountSetBackupEmail sets (or updates) the backup email for the admin account. POST /gui/my-account/backup-email

func (*GUIHandler) MyAccountTrustedDevices

func (h *GUIHandler) MyAccountTrustedDevices(c *gin.Context)

MyAccountTrustedDevices lists the trusted devices belonging to the logged-in admin across all apps (the admin may also be a regular user in some apps). GET /gui/my-account/trusted-devices

func (*GUIHandler) MyAccountUpdateEmail

func (h *GUIHandler) MyAccountUpdateEmail(c *gin.Context)

MyAccountUpdateEmail updates the admin's email address. POST /gui/my-account/email

func (*GUIHandler) OAuthCreate

func (h *GUIHandler) OAuthCreate(c *gin.Context)

OAuthCreate handles creating a new OAuth config. POST /gui/oauth

func (*GUIHandler) OAuthCreateForm

func (h *GUIHandler) OAuthCreateForm(c *gin.Context)

OAuthCreateForm returns the empty create form HTML fragment for HTMX. GET /gui/oauth/new

func (*GUIHandler) OAuthDelete

func (h *GUIHandler) OAuthDelete(c *gin.Context)

OAuthDelete handles deleting an OAuth config. DELETE /gui/oauth/:id

func (*GUIHandler) OAuthDeleteConfirm

func (h *GUIHandler) OAuthDeleteConfirm(c *gin.Context)

OAuthDeleteConfirm returns the delete confirmation modal body for HTMX. GET /gui/oauth/:id/delete

func (*GUIHandler) OAuthEditForm

func (h *GUIHandler) OAuthEditForm(c *gin.Context)

OAuthEditForm returns the pre-filled edit form HTML fragment for HTMX. GET /gui/oauth/:id/edit

func (*GUIHandler) OAuthFormCancel

func (h *GUIHandler) OAuthFormCancel(c *gin.Context)

OAuthFormCancel returns an empty response to clear the form container. GET /gui/oauth/form-cancel

func (*GUIHandler) OAuthList

func (h *GUIHandler) OAuthList(c *gin.Context)

OAuthList returns the OAuth config table HTML fragment for HTMX. GET /gui/oauth/list

func (*GUIHandler) OAuthPage

func (h *GUIHandler) OAuthPage(c *gin.Context)

OAuthPage renders the OAuth config management page. GET /gui/oauth

func (*GUIHandler) OAuthToggleEnabled

func (h *GUIHandler) OAuthToggleEnabled(c *gin.Context)

OAuthToggleEnabled toggles the IsEnabled flag for an OAuth config. PUT /gui/oauth/:id/toggle

func (*GUIHandler) OAuthUpdate

func (h *GUIHandler) OAuthUpdate(c *gin.Context)

OAuthUpdate handles updating an OAuth config. PUT /gui/oauth/:id

func (*GUIHandler) OIDCClientCreate

func (h *GUIHandler) OIDCClientCreate(c *gin.Context)

OIDCClientCreate handles creating a new OIDC client. POST /gui/oidc-clients

func (*GUIHandler) OIDCClientCreateForm

func (h *GUIHandler) OIDCClientCreateForm(c *gin.Context)

OIDCClientCreateForm returns the empty create form HTML fragment for HTMX. GET /gui/oidc-clients/new

func (*GUIHandler) OIDCClientDelete

func (h *GUIHandler) OIDCClientDelete(c *gin.Context)

OIDCClientDelete handles deleting an OIDC client. DELETE /gui/oidc-clients/:id

func (*GUIHandler) OIDCClientDeleteConfirm

func (h *GUIHandler) OIDCClientDeleteConfirm(c *gin.Context)

OIDCClientDeleteConfirm returns the delete confirmation modal body for HTMX. GET /gui/oidc-clients/:id/delete

func (*GUIHandler) OIDCClientEditForm

func (h *GUIHandler) OIDCClientEditForm(c *gin.Context)

OIDCClientEditForm returns the pre-filled edit form HTML fragment for HTMX. GET /gui/oidc-clients/:id/edit

func (*GUIHandler) OIDCClientFormCancel

func (h *GUIHandler) OIDCClientFormCancel(c *gin.Context)

OIDCClientFormCancel returns an empty response to clear the form container. GET /gui/oidc-clients/form-cancel

func (*GUIHandler) OIDCClientList

func (h *GUIHandler) OIDCClientList(c *gin.Context)

OIDCClientList returns the OIDC client table HTML fragment for HTMX. GET /gui/oidc-clients/list

func (*GUIHandler) OIDCClientRotateSecret

func (h *GUIHandler) OIDCClientRotateSecret(c *gin.Context)

OIDCClientRotateSecret rotates the client secret and returns the new secret partial. POST /gui/oidc-clients/:id/rotate-secret

func (*GUIHandler) OIDCClientUpdate

func (h *GUIHandler) OIDCClientUpdate(c *gin.Context)

OIDCClientUpdate handles updating an OIDC client. PUT /gui/oidc-clients/:id

func (*GUIHandler) OIDCClientsPage

func (h *GUIHandler) OIDCClientsPage(c *gin.Context)

OIDCClientsPage renders the full OIDC clients admin page. GET /gui/oidc-clients

func (*GUIHandler) PasskeyDelete

func (h *GUIHandler) PasskeyDelete(c *gin.Context)

PasskeyDelete handles deleting a WebAuthn passkey credential. DELETE /gui/users/passkeys/:id

func (*GUIHandler) PasskeyDeleteConfirm

func (h *GUIHandler) PasskeyDeleteConfirm(c *gin.Context)

PasskeyDeleteConfirm returns a confirmation dialog partial for deleting a passkey. GET /gui/users/passkeys/:id/delete

func (*GUIHandler) PasskeyLoginBegin

func (h *GUIHandler) PasskeyLoginBegin(c *gin.Context)

PasskeyLoginBegin starts the WebAuthn discoverable login ceremony for admin passkey login. POST /gui/passkey-login/begin

func (*GUIHandler) PasskeyLoginFinish

func (h *GUIHandler) PasskeyLoginFinish(c *gin.Context)

PasskeyLoginFinish completes the WebAuthn discoverable login ceremony for admin passkey login. On success, creates a full admin session (bypassing 2FA) and sets the session cookie. POST /gui/passkey-login/finish

func (*GUIHandler) PermissionCreate

func (h *GUIHandler) PermissionCreate(c *gin.Context)

PermissionCreate handles creating a new permission. POST /gui/permissions

func (*GUIHandler) PermissionCreateForm

func (h *GUIHandler) PermissionCreateForm(c *gin.Context)

PermissionCreateForm returns the empty create form HTML fragment for HTMX. GET /gui/permissions/new

func (*GUIHandler) PermissionFormCancel

func (h *GUIHandler) PermissionFormCancel(c *gin.Context)

PermissionFormCancel clears the permission form container. GET /gui/permissions/form-cancel

func (*GUIHandler) PermissionList

func (h *GUIHandler) PermissionList(c *gin.Context)

PermissionList returns the permission table HTML fragment for HTMX. GET /gui/permissions/list

func (*GUIHandler) PermissionsPage

func (h *GUIHandler) PermissionsPage(c *gin.Context)

PermissionsPage renders the permissions management page. GET /gui/permissions

func (*GUIHandler) RoleCreate

func (h *GUIHandler) RoleCreate(c *gin.Context)

RoleCreate handles creating a new role. POST /gui/roles

func (*GUIHandler) RoleCreateForm

func (h *GUIHandler) RoleCreateForm(c *gin.Context)

RoleCreateForm returns the empty create form HTML fragment for HTMX. GET /gui/roles/new

func (*GUIHandler) RoleDelete

func (h *GUIHandler) RoleDelete(c *gin.Context)

RoleDelete handles deleting a role and returns a refreshed role list. DELETE /gui/roles/:id

func (*GUIHandler) RoleDeleteConfirm

func (h *GUIHandler) RoleDeleteConfirm(c *gin.Context)

RoleDeleteConfirm returns the delete confirmation modal body for HTMX. GET /gui/roles/:id/delete

func (*GUIHandler) RoleEditForm

func (h *GUIHandler) RoleEditForm(c *gin.Context)

RoleEditForm returns the pre-filled edit form HTML fragment for HTMX. GET /gui/roles/:id/edit

func (*GUIHandler) RoleFormCancel

func (h *GUIHandler) RoleFormCancel(c *gin.Context)

RoleFormCancel clears the role form container. GET /gui/roles/form-cancel

func (*GUIHandler) RoleList

func (h *GUIHandler) RoleList(c *gin.Context)

RoleList returns the role table HTML fragment for HTMX. GET /gui/roles/list?app_id=X

func (*GUIHandler) RolePermissions

func (h *GUIHandler) RolePermissions(c *gin.Context)

RolePermissions returns the permissions checkbox modal body for HTMX. GET /gui/roles/:id/permissions

func (*GUIHandler) RolePermissionsUpdate

func (h *GUIHandler) RolePermissionsUpdate(c *gin.Context)

RolePermissionsUpdate saves the selected permissions for a role. PUT /gui/roles/:id/permissions

func (*GUIHandler) RoleUpdate

func (h *GUIHandler) RoleUpdate(c *gin.Context)

RoleUpdate handles updating a role. PUT /gui/roles/:id

func (*GUIHandler) RolesPage

func (h *GUIHandler) RolesPage(c *gin.Context)

RolesPage renders the roles management page. GET /gui/roles

func (*GUIHandler) SessionDetail

func (h *GUIHandler) SessionDetail(c *gin.Context)

SessionDetail returns the session detail partial (HTMX fragment). GET /gui/sessions/:app_id/:session_id/detail

func (*GUIHandler) SessionGroupAddApp

func (h *GUIHandler) SessionGroupAddApp(c *gin.Context)

SessionGroupAddApp adds an application to a session group. POST /gui/session-groups/:id/apps

func (*GUIHandler) SessionGroupApps

func (h *GUIHandler) SessionGroupApps(c *gin.Context)

SessionGroupApps returns the apps management partial for a session group. GET /gui/session-groups/:id/apps

func (*GUIHandler) SessionGroupCreate

func (h *GUIHandler) SessionGroupCreate(c *gin.Context)

SessionGroupCreate handles creating a new session group. POST /gui/session-groups

func (*GUIHandler) SessionGroupCreateForm

func (h *GUIHandler) SessionGroupCreateForm(c *gin.Context)

SessionGroupCreateForm returns the empty create form HTML fragment for HTMX. GET /gui/session-groups/new

func (*GUIHandler) SessionGroupDelete

func (h *GUIHandler) SessionGroupDelete(c *gin.Context)

SessionGroupDelete handles deleting a session group. DELETE /gui/session-groups/:id

func (*GUIHandler) SessionGroupDeleteConfirm

func (h *GUIHandler) SessionGroupDeleteConfirm(c *gin.Context)

SessionGroupDeleteConfirm returns the delete confirmation modal body for HTMX. GET /gui/session-groups/:id/delete

func (*GUIHandler) SessionGroupEditForm

func (h *GUIHandler) SessionGroupEditForm(c *gin.Context)

SessionGroupEditForm returns the pre-filled edit form HTML fragment for HTMX. GET /gui/session-groups/:id/edit

func (*GUIHandler) SessionGroupFormCancel

func (h *GUIHandler) SessionGroupFormCancel(c *gin.Context)

SessionGroupFormCancel returns an empty response to clear the form container. GET /gui/session-groups/form-cancel

func (*GUIHandler) SessionGroupList

func (h *GUIHandler) SessionGroupList(c *gin.Context)

SessionGroupList returns the session group table HTML fragment for HTMX. GET /gui/session-groups/list

func (*GUIHandler) SessionGroupPage

func (h *GUIHandler) SessionGroupPage(c *gin.Context)

SessionGroupPage renders the session group management page. GET /gui/session-groups

func (*GUIHandler) SessionGroupRemoveApp

func (h *GUIHandler) SessionGroupRemoveApp(c *gin.Context)

SessionGroupRemoveApp removes an application from a session group. DELETE /gui/session-groups/:id/apps/:app_id

func (*GUIHandler) SessionGroupUpdate

func (h *GUIHandler) SessionGroupUpdate(c *gin.Context)

SessionGroupUpdate handles updating a session group. PUT /gui/session-groups/:id

func (*GUIHandler) SessionList

func (h *GUIHandler) SessionList(c *gin.Context)

SessionList returns the paginated session list partial (HTMX fragment). GET /gui/sessions/list

func (*GUIHandler) SessionRevoke

func (h *GUIHandler) SessionRevoke(c *gin.Context)

SessionRevoke deletes a single session (HTMX action). DELETE /gui/sessions/:app_id/:session_id

func (*GUIHandler) SessionRevokeAllForUser

func (h *GUIHandler) SessionRevokeAllForUser(c *gin.Context)

SessionRevokeAllForUser revokes all sessions for a specific user (HTMX action). DELETE /gui/sessions/revoke-all-user

func (*GUIHandler) SessionsPage

func (h *GUIHandler) SessionsPage(c *gin.Context)

SessionsPage renders the session management page. GET /gui/sessions

func (*GUIHandler) SettingReset

func (h *GUIHandler) SettingReset(c *gin.Context)

SettingReset removes the DB override for a setting (reverts to env/default). DELETE /gui/settings/:key

func (*GUIHandler) SettingUpdate

func (h *GUIHandler) SettingUpdate(c *gin.Context)

SettingUpdate saves a new value for a single setting. PUT /gui/settings/:key

func (*GUIHandler) SettingsInfo

func (h *GUIHandler) SettingsInfo(c *gin.Context)

SettingsInfo returns the system info partial. GET /gui/settings/info

func (*GUIHandler) SettingsPage

func (h *GUIHandler) SettingsPage(c *gin.Context)

SettingsPage renders the system settings page with accordion categories. GET /gui/settings

func (*GUIHandler) SettingsSection

func (h *GUIHandler) SettingsSection(c *gin.Context)

SettingsSection returns the settings rows for a single category. GET /gui/settings/section/:category

func (h *GUIHandler) SocialAccountUnlink(c *gin.Context)

SocialAccountUnlink handles deleting (unlinking) a social account from a user. DELETE /gui/users/social-accounts/:id

func (*GUIHandler) SocialAccountUnlinkConfirm

func (h *GUIHandler) SocialAccountUnlinkConfirm(c *gin.Context)

SocialAccountUnlinkConfirm returns a confirmation dialog partial for unlinking a social account. GET /gui/users/social-accounts/:id/unlink

func (*GUIHandler) TenantCreate

func (h *GUIHandler) TenantCreate(c *gin.Context)

TenantCreate handles creating a new tenant. POST /gui/tenants

func (*GUIHandler) TenantCreateForm

func (h *GUIHandler) TenantCreateForm(c *gin.Context)

TenantCreateForm returns the empty create form HTML fragment for HTMX. GET /gui/tenants/new

func (*GUIHandler) TenantDelete

func (h *GUIHandler) TenantDelete(c *gin.Context)

TenantDelete handles deleting a tenant. DELETE /gui/tenants/:id

func (*GUIHandler) TenantDeleteConfirm

func (h *GUIHandler) TenantDeleteConfirm(c *gin.Context)

TenantDeleteConfirm returns the delete confirmation modal body for HTMX. GET /gui/tenants/:id/delete

func (*GUIHandler) TenantEditForm

func (h *GUIHandler) TenantEditForm(c *gin.Context)

TenantEditForm returns the pre-filled edit form HTML fragment for HTMX. GET /gui/tenants/:id/edit

func (*GUIHandler) TenantFormCancel

func (h *GUIHandler) TenantFormCancel(c *gin.Context)

TenantFormCancel returns an empty response to clear the form container. GET /gui/tenants/form-cancel

func (*GUIHandler) TenantList

func (h *GUIHandler) TenantList(c *gin.Context)

TenantList returns the tenant table HTML fragment for HTMX. GET /gui/tenants/list

func (*GUIHandler) TenantPage

func (h *GUIHandler) TenantPage(c *gin.Context)

TenantPage renders the tenant management page. GET /gui/tenants

func (*GUIHandler) TenantUpdate

func (h *GUIHandler) TenantUpdate(c *gin.Context)

TenantUpdate handles updating a tenant. PUT /gui/tenants/:id

func (*GUIHandler) TwoFAResendEmail

func (h *GUIHandler) TwoFAResendEmail(c *gin.Context)

TwoFAResendEmail resends the 2FA email code during login verification. POST /gui/2fa-resend-email

func (*GUIHandler) TwoFAVerifyPage

func (h *GUIHandler) TwoFAVerifyPage(c *gin.Context)

TwoFAVerifyPage renders the 2FA verification form during login. The admin has already authenticated with password and received a temp token. GET /gui/2fa-verify

func (*GUIHandler) TwoFAVerifySubmit

func (h *GUIHandler) TwoFAVerifySubmit(c *gin.Context)

TwoFAVerifySubmit handles 2FA code submission during login. On success, creates a full session and redirects to the dashboard. POST /gui/2fa-verify

func (*GUIHandler) UserDetail

func (h *GUIHandler) UserDetail(c *gin.Context)

UserDetail returns the user detail partial (HTMX fragment)

func (*GUIHandler) UserExport

func (h *GUIHandler) UserExport(c *gin.Context)

UserExport streams all users as a downloadable CSV or JSON file. GET /gui/users/export?format=csv|json&app_id=&search=

func (*GUIHandler) UserImport

func (h *GUIHandler) UserImport(c *gin.Context)

UserImport processes an uploaded CSV or JSON file and bulk-creates users. POST /gui/users/import (multipart/form-data)

func (*GUIHandler) UserImportModal

func (h *GUIHandler) UserImportModal(c *gin.Context)

UserImportModal returns the import modal partial for the Users page. GET /gui/users/import/modal

func (*GUIHandler) UserList

func (h *GUIHandler) UserList(c *gin.Context)

UserList returns the paginated user list partial (HTMX fragment)

func (*GUIHandler) UserPage

func (h *GUIHandler) UserPage(c *gin.Context)

UserPage renders the user management page with app filter dropdown

func (*GUIHandler) UserRevokeAllTrustedDevices

func (h *GUIHandler) UserRevokeAllTrustedDevices(c *gin.Context)

UserRevokeAllTrustedDevices revokes all trusted devices for a user across all apps (admin action). DELETE /gui/users/:id/trusted-devices

func (*GUIHandler) UserRevokeTrustedDevice

func (h *GUIHandler) UserRevokeTrustedDevice(c *gin.Context)

UserRevokeTrustedDevice revokes a single trusted device for a user (admin action). DELETE /gui/users/:id/trusted-devices/:device_id

func (*GUIHandler) UserRoleCreate

func (h *GUIHandler) UserRoleCreate(c *gin.Context)

UserRoleCreate handles assigning a role to a user. POST /gui/user-roles

func (*GUIHandler) UserRoleCreateForm

func (h *GUIHandler) UserRoleCreateForm(c *gin.Context)

UserRoleCreateForm returns the assign role form HTML fragment for HTMX. GET /gui/user-roles/new

func (*GUIHandler) UserRoleFormCancel

func (h *GUIHandler) UserRoleFormCancel(c *gin.Context)

UserRoleFormCancel clears the user-role form container. GET /gui/user-roles/form-cancel

func (*GUIHandler) UserRoleList

func (h *GUIHandler) UserRoleList(c *gin.Context)

UserRoleList returns the user-role table HTML fragment for HTMX. GET /gui/user-roles/list?app_id=X&page=N

func (*GUIHandler) UserRoleRevoke

func (h *GUIHandler) UserRoleRevoke(c *gin.Context)

UserRoleRevoke handles revoking a role from a user and returns a refreshed list. DELETE /gui/user-roles?user_id=X&role_id=X&app_id=X

func (*GUIHandler) UserRoleRevokeConfirm

func (h *GUIHandler) UserRoleRevokeConfirm(c *gin.Context)

UserRoleRevokeConfirm returns the revoke confirmation modal body for HTMX. GET /gui/user-roles/revoke?user_id=X&role_id=X&app_id=X&user_email=X&role_name=X

func (*GUIHandler) UserRoleRolesForApp

func (h *GUIHandler) UserRoleRolesForApp(c *gin.Context)

UserRoleRolesForApp returns HTML <option> elements for the roles in an app. GET /gui/user-roles/roles-for-app?app_id=X

func (*GUIHandler) UserRoleSearchUsers

func (h *GUIHandler) UserRoleSearchUsers(c *gin.Context)

UserRoleSearchUsers returns a list of matching users as clickable HTML items. GET /gui/user-roles/search-users?app_id=X&q=term

func (*GUIHandler) UserRoleUpdate

func (h *GUIHandler) UserRoleUpdate(c *gin.Context)

UserRoleUpdate handles changing a user's role assignment. PUT /gui/user-roles Atomically revokes the old role and assigns the new one.

func (*GUIHandler) UserRolesPage

func (h *GUIHandler) UserRolesPage(c *gin.Context)

UserRolesPage renders the user-roles management page. GET /gui/user-roles

func (*GUIHandler) UserSessions

func (h *GUIHandler) UserSessions(c *gin.Context)

UserSessions returns the user sessions partial for the user detail page. GET /gui/users/:id/sessions

func (*GUIHandler) UserToggleActive

func (h *GUIHandler) UserToggleActive(c *gin.Context)

UserToggleActive toggles a user's IsActive flag and revokes tokens on deactivation (HTMX fragment)

func (*GUIHandler) UserUnlock

func (h *GUIHandler) UserUnlock(c *gin.Context)

UserUnlock unlocks a locked user account (HTMX fragment). Clears DB lockout fields and resets all Redis brute-force counters. PUT /gui/users/:id/unlock

func (*GUIHandler) WebhookCreate

func (h *GUIHandler) WebhookCreate(c *gin.Context)

WebhookCreate handles creating a new webhook endpoint. POST /gui/webhooks

func (*GUIHandler) WebhookCreateForm

func (h *GUIHandler) WebhookCreateForm(c *gin.Context)

WebhookCreateForm returns the webhook creation form HTML fragment. GET /gui/webhooks/new

func (*GUIHandler) WebhookDelete

func (h *GUIHandler) WebhookDelete(c *gin.Context)

WebhookDelete deletes a webhook endpoint. DELETE /gui/webhooks/:id

func (*GUIHandler) WebhookDeleteConfirm

func (h *GUIHandler) WebhookDeleteConfirm(c *gin.Context)

WebhookDeleteConfirm renders the delete confirmation fragment. GET /gui/webhooks/:id/delete

func (*GUIHandler) WebhookDeliveries

func (h *GUIHandler) WebhookDeliveries(c *gin.Context)

WebhookDeliveries renders the delivery log page for a webhook endpoint. GET /gui/webhooks/:id/deliveries

func (*GUIHandler) WebhookFormCancel

func (h *GUIHandler) WebhookFormCancel(c *gin.Context)

WebhookFormCancel returns an empty fragment to collapse the form. GET /gui/webhooks/form-cancel

func (*GUIHandler) WebhookList

func (h *GUIHandler) WebhookList(c *gin.Context)

WebhookList returns the paginated webhook endpoints list partial (HTMX fragment). GET /gui/webhooks/list

func (*GUIHandler) WebhookPage

func (h *GUIHandler) WebhookPage(c *gin.Context)

WebhookPage renders the webhooks management page. GET /gui/webhooks

func (*GUIHandler) WebhookToggle

func (h *GUIHandler) WebhookToggle(c *gin.Context)

WebhookToggle toggles the active state of a webhook endpoint. PUT /gui/webhooks/:id/toggle

type Handler

type Handler struct {
	Repo              *Repository
	EmailService      *email.Service
	IPRuleRepo        *geoip.IPRuleRepository        // IP rule repository (nil = IP rules disabled)
	IPRuleEvaluator   *geoip.IPRuleEvaluator         // IP rule evaluator for cache invalidation (nil = disabled)
	TrustedDeviceRepo *twofa.TrustedDeviceRepository // Optional: trusted device management (nil = disabled)
	GeoIPService      *geoip.Service                 // GeoIP service for IP access checks (nil = disabled)
}

func NewHandler

func NewHandler(r *Repository, emailService *email.Service) *Handler

func (*Handler) AdminListTrustedDevices

func (h *Handler) AdminListTrustedDevices(c *gin.Context)

AdminListTrustedDevices lists all trusted devices for a given user. @Summary List trusted devices for a user @Description Returns all trusted devices registered by a specific user across all apps @Tags Admin @Produce json @Param id path string true "User UUID" @Success 200 {object} dto.TrustedDevicesListResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/users/{id}/trusted-devices [get]

func (*Handler) AdminRevokeAllTrustedDevices

func (h *Handler) AdminRevokeAllTrustedDevices(c *gin.Context)

AdminRevokeAllTrustedDevices revokes all trusted devices for a user. @Summary Revoke all trusted devices for a user @Description Removes all trusted devices for a user, forcing full 2FA on all devices @Tags Admin @Produce json @Param id path string true "User UUID" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/users/{id}/trusted-devices [delete]

func (*Handler) AdminRevokeTrustedDevice

func (h *Handler) AdminRevokeTrustedDevice(c *gin.Context)

AdminRevokeTrustedDevice revokes a single trusted device for a user. @Summary Revoke a trusted device @Description Removes a specific trusted device, forcing the user to re-authenticate with 2FA on that device @Tags Admin @Produce json @Param id path string true "User UUID" @Param device_id path string true "Trusted Device UUID" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/users/{id}/trusted-devices/{device_id} [delete]

func (*Handler) CheckIPAccess

func (h *Handler) CheckIPAccess(c *gin.Context)

CheckIPAccess checks whether an IP address is allowed to access an application @Summary Check IP access @Description Evaluate whether a specific IP address is allowed to access an application based on its IP rules @Tags Admin - IP Rules @Accept json @Produce json @Param id path string true "Application ID" @Param request body dto.IPAccessCheckRequest true "IP address to check" @Success 200 {object} dto.IPAccessCheckResponse @Failure 400 {object} dto.ErrorResponse @Failure 503 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/ip-rules/check [post]

func (*Handler) CreateApp

func (h *Handler) CreateApp(c *gin.Context)

CreateApp creates a new application for a tenant @Summary Create a new application @Description Register a new application under a specific tenant @Tags Admin @Accept json @Produce json @Param app body dto.CreateAppRequest true "Application Creation Data" @Success 201 {object} dto.AppResponse @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps [post]

func (*Handler) CreateEmailServerConfig

func (h *Handler) CreateEmailServerConfig(c *gin.Context)

CreateEmailServerConfig creates a new SMTP config @Summary Create SMTP config @Description Create a new SMTP server configuration for an application @Tags Admin - Email Servers @Accept json @Produce json @Param app_id query string true "Application ID" @Param config body dto.EmailServerConfigRequest true "SMTP Config" @Success 201 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-servers [post]

func (*Handler) CreateEmailType

func (h *Handler) CreateEmailType(c *gin.Context)

CreateEmailType creates a new custom email type @Summary Create a custom email type @Description Register a new custom email type for use in templates @Tags Admin - Email @Accept json @Produce json @Param emailType body dto.CreateEmailTypeRequest true "Email Type Data" @Success 201 {object} dto.EmailTypeResponse @Failure 400 {object} dto.ErrorResponse @Failure 409 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-types [post]

func (*Handler) CreateIPRule

func (h *Handler) CreateIPRule(c *gin.Context)

CreateIPRule creates a new IP rule for an application @Summary Create an IP rule @Description Add a new IP access rule (allow or block) for a specific application @Tags Admin - IP Rules @Accept json @Produce json @Param id path string true "Application ID" @Param request body dto.IPRuleCreateRequest true "IP rule data" @Success 201 {object} dto.IPRuleResponse @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/ip-rules [post]

func (*Handler) CreateTenant

func (h *Handler) CreateTenant(c *gin.Context)

CreateTenant creates a new tenant @Summary Create a new tenant @Description Register a new tenant organization in the system @Tags Admin @Accept json @Produce json @Param tenant body dto.CreateTenantRequest true "Tenant Creation Data" @Success 201 {object} dto.TenantResponse @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/tenants [post]

func (*Handler) DeleteEmailServerConfig

func (h *Handler) DeleteEmailServerConfig(c *gin.Context)

DeleteEmailServerConfig removes all SMTP configs for an app (legacy app-scoped) @Summary Delete SMTP configs for application @Description Remove all SMTP server configurations for an application (falls back to global) @Tags Admin - Email @Produce json @Param id path string true "Application ID" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/email-config [delete]

func (*Handler) DeleteEmailServerConfigByID

func (h *Handler) DeleteEmailServerConfigByID(c *gin.Context)

DeleteEmailServerConfigByID removes a single SMTP config by its ID @Summary Delete SMTP config by ID @Description Remove a specific SMTP server configuration by its ID @Tags Admin - Email Servers @Produce json @Param id path string true "Config ID" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-servers/{id} [delete]

func (*Handler) DeleteEmailTemplate

func (h *Handler) DeleteEmailTemplate(c *gin.Context)

DeleteEmailTemplate removes an email template @Summary Delete email template @Description Remove an email template by ID @Tags Admin - Email @Produce json @Param id path string true "Template ID" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-templates/{id} [delete]

func (*Handler) DeleteEmailType

func (h *Handler) DeleteEmailType(c *gin.Context)

DeleteEmailType deletes a custom email type @Summary Delete a custom email type @Description Delete a custom email type (system types cannot be deleted) @Tags Admin - Email @Produce json @Param id path string true "Email Type ID" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-types/{id} [delete]

func (*Handler) DeleteIPRule

func (h *Handler) DeleteIPRule(c *gin.Context)

DeleteIPRule deletes an IP rule @Summary Delete an IP rule @Description Remove an IP access rule by its ID @Tags Admin - IP Rules @Produce json @Param id path string true "Application ID" @Param rule_id path string true "IP Rule ID" @Success 200 {object} dto.MessageResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/ip-rules/{rule_id} [delete]

func (*Handler) ExportUsers

func (h *Handler) ExportUsers(c *gin.Context)

ExportUsers streams all users as a downloadable CSV or JSON file.

@Summary Export users as CSV or JSON (Admin) @Description Export all users as CSV or JSON (max 10,000 rows). Optionally filter by app_id or search term. @Description Use the X-Export-Truncated response header to detect if the result was capped at 10,000 rows. @Tags Users @Security AdminApiKey @Produce json @Produce text/csv @Param format query string false "Export format: csv or json (default: csv)" Enums(csv, json) @Param app_id query string false "Filter by application UUID" @Param search query string false "Filter by email or name (case-insensitive)" @Success 200 {object} dto.UserExportResponse "JSON export" @Success 200 {string} string "CSV export" @Failure 400 {object} dto.ErrorResponse @Failure 401 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Router /admin/users/export [get]

func (*Handler) GetAppDetails

func (h *Handler) GetAppDetails(c *gin.Context)

GetAppDetails retrieves app details including OAuth configs @Summary Get application details @Description Retrieve details of a specific application including OAuth configurations @Tags Admin @Accept json @Produce json @Param id path string true "Application ID" @Success 200 {object} dto.AppResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id} [get]

func (*Handler) GetAppLoginConfig

func (h *Handler) GetAppLoginConfig(c *gin.Context)

GetAppLoginConfig returns the public login configuration for an application. It exposes only which social providers are enabled and whether OIDC/SSO is available. No secrets are included. No authentication is required. @Summary Get public login configuration for an app @Description Returns enabled social providers and OIDC availability for the login/register UI @Tags Public @Produce json @Param app_id path string true "Application UUID" @Success 200 {object} dto.AppLoginConfigResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Router /app-config/{app_id} [get]

func (*Handler) GetEmailServerConfig

func (h *Handler) GetEmailServerConfig(c *gin.Context)

GetEmailServerConfig returns the default SMTP config for an app @Summary Get default SMTP config for application @Description Retrieve the default SMTP server configuration for an application @Tags Admin - Email @Produce json @Param id path string true "Application ID" @Success 200 {object} dto.EmailServerConfigResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/email-config [get]

func (*Handler) GetEmailServerConfigByID

func (h *Handler) GetEmailServerConfigByID(c *gin.Context)

GetEmailServerConfigByID returns a single SMTP config by its ID @Summary Get SMTP config by ID @Description Retrieve a specific SMTP server configuration by its ID @Tags Admin - Email Servers @Produce json @Param id path string true "Config ID" @Success 200 {object} dto.EmailServerConfigResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-servers/{id} [get]

func (*Handler) GetEmailTemplate

func (h *Handler) GetEmailTemplate(c *gin.Context)

GetEmailTemplate returns a single template by ID @Summary Get email template @Description Retrieve a specific email template by ID @Tags Admin - Email @Produce json @Param id path string true "Template ID" @Success 200 {object} dto.EmailTemplateResponse @Failure 404 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-templates/{id} [get]

func (*Handler) GetEmailType

func (h *Handler) GetEmailType(c *gin.Context)

GetEmailType returns a single email type by code @Summary Get email type by code @Description Retrieve a specific email type by its code @Tags Admin - Email @Produce json @Param code path string true "Email Type Code" @Success 200 {object} dto.EmailTypeResponse @Failure 404 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-types/{code} [get]

func (*Handler) GetIPRule

func (h *Handler) GetIPRule(c *gin.Context)

GetIPRule retrieves a specific IP rule by ID @Summary Get an IP rule @Description Retrieve a specific IP access rule by its ID @Tags Admin - IP Rules @Produce json @Param id path string true "Application ID" @Param rule_id path string true "IP Rule ID" @Success 200 {object} dto.IPRuleResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/ip-rules/{rule_id} [get]

func (*Handler) ImportUsers

func (h *Handler) ImportUsers(c *gin.Context)

ImportUsers bulk-creates users from an uploaded CSV or JSON file.

@Summary Bulk import users from CSV or JSON (Admin) @Description Upload a CSV or JSON file to bulk-create users under a specific application. @Description The app_id query parameter is required. Duplicate emails are skipped and reported. @Description Imported users have no password — they must use the password reset flow to set one. @Description CSV expected columns: email (required), name, first_name, last_name, locale (all optional). @Description JSON: top-level array or {"users":[...]} object, same fields. @Tags Users @Security AdminApiKey @Accept multipart/form-data @Produce json @Param app_id query string true "Target application UUID" @Param file formData file true "CSV or JSON file to import" @Success 200 {object} dto.UserImportResult @Failure 400 {object} dto.ErrorResponse @Failure 401 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Router /admin/users/import [post]

func (*Handler) ListAllEmailServerConfigs

func (h *Handler) ListAllEmailServerConfigs(c *gin.Context)

ListAllEmailServerConfigs returns all SMTP configs across all apps @Summary List all SMTP configs @Description Retrieve all SMTP server configurations across all applications @Tags Admin - Email Servers @Produce json @Success 200 {array} dto.EmailServerConfigResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-servers [get]

func (*Handler) ListEmailServerConfigsByApp

func (h *Handler) ListEmailServerConfigsByApp(c *gin.Context)

ListEmailServerConfigsByApp returns all SMTP configs for a specific app @Summary List SMTP configs for application @Description Retrieve all SMTP server configurations for a specific application @Tags Admin - Email Servers @Produce json @Param id path string true "Application ID" @Success 200 {array} dto.EmailServerConfigResponse @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/email-servers [get]

func (*Handler) ListEmailTemplates

func (h *Handler) ListEmailTemplates(c *gin.Context)

ListEmailTemplates returns all templates for an app or global defaults @Summary List email templates @Description Retrieve email templates for a specific app or global defaults @Tags Admin - Email @Produce json @Param app_id query string false "Application ID (omit for global defaults)" @Success 200 {array} dto.EmailTemplateResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-templates [get]

func (*Handler) ListEmailTypes

func (h *Handler) ListEmailTypes(c *gin.Context)

ListEmailTypes returns all email types @Summary List all email types @Description Retrieve all registered email types @Tags Admin - Email @Produce json @Success 200 {array} dto.EmailTypeResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-types [get]

func (*Handler) ListIPRules

func (h *Handler) ListIPRules(c *gin.Context)

ListIPRules lists all IP rules for an application @Summary List IP rules for an application @Description Retrieve all IP access rules (allow/block) for a specific application @Tags Admin - IP Rules @Produce json @Param id path string true "Application ID" @Param include_inactive query bool false "Include inactive rules" default(false) @Success 200 {object} dto.IPRuleListResponse @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/ip-rules [get]

func (*Handler) ListTenants

func (h *Handler) ListTenants(c *gin.Context)

ListTenants lists all tenants with pagination @Summary List all tenants @Description Retrieve a paginated list of all tenants @Tags Admin @Accept json @Produce json @Param page query int false "Page number" default(1) @Param page_size query int false "Page size" default(10) @Success 200 {object} map[string]interface{} @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/tenants [get]

func (*Handler) ListWellKnownVariables

func (h *Handler) ListWellKnownVariables(c *gin.Context)

ListWellKnownVariables returns the list of all variables the system can auto-resolve. @Summary List well-known email template variables @Description Returns all variables that the system can automatically resolve from user profiles, app settings, or that must be passed explicitly. Use this as a reference when adding variables to email types. @Tags Admin - Email @Produce json @Success 200 {array} dto.EmailTypeVariableResponse @Security AdminApiKey @Router /admin/email-variables [get]

func (*Handler) PreviewEmailTemplate

func (h *Handler) PreviewEmailTemplate(c *gin.Context)

PreviewEmailTemplate renders a template with sample data @Summary Preview email template @Description Render a template with sample variables for preview @Tags Admin - Email @Accept json @Produce json @Param preview body dto.EmailPreviewRequest true "Preview Data" @Success 200 {object} dto.EmailPreviewResponse @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-templates/preview [post]

func (*Handler) SaveEmailServerConfig

func (h *Handler) SaveEmailServerConfig(c *gin.Context)

SaveEmailServerConfig creates or updates SMTP config for an app (legacy app-scoped) @Summary Save SMTP config for application @Description Create or update an SMTP server configuration for an application @Tags Admin - Email @Accept json @Produce json @Param id path string true "Application ID" @Param config body dto.EmailServerConfigRequest true "SMTP Config" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/email-config [put]

func (*Handler) SaveEmailTemplate

func (h *Handler) SaveEmailTemplate(c *gin.Context)

SaveEmailTemplate creates or updates an email template @Summary Save email template @Description Create or update an email template for a specific app or as global default @Tags Admin - Email @Accept json @Produce json @Param app_id query string false "Application ID (omit for global default)" @Param email_type_id query string true "Email Type ID" @Param template body dto.EmailTemplateRequest true "Template Data" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-templates [post]

func (*Handler) SendCustomEmail

func (h *Handler) SendCustomEmail(c *gin.Context)

SendCustomEmail sends an email of a specific type to a recipient @Summary Send an email @Description Send an email of the specified type using app's SMTP config and templates @Tags Admin - Email @Accept json @Produce json @Param id path string true "Application ID" @Param request body dto.SendEmailRequest true "Send Email Data" @Success 200 {object} dto.SendEmailResponse @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/send-email [post]

func (*Handler) SendTestEmail

func (h *Handler) SendTestEmail(c *gin.Context)

SendTestEmail sends a test email using an app's default SMTP configuration @Summary Send test email (app-scoped) @Description Send a test email to verify the default SMTP configuration for an application @Tags Admin - Email @Accept json @Produce json @Param id path string true "Application ID" @Param request body dto.EmailTestRequest true "Test Email Data" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/email-test [post]

func (*Handler) SendTestEmailByConfigID

func (h *Handler) SendTestEmailByConfigID(c *gin.Context)

SendTestEmailByConfigID sends a test email using a specific SMTP config @Summary Send test email by config ID @Description Send a test email to verify a specific SMTP configuration @Tags Admin - Email Servers @Accept json @Produce json @Param id path string true "Config ID" @Param request body dto.EmailTestRequest true "Test Email Data" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-servers/{id}/test [post]

func (*Handler) UpdateEmailServerConfigByID

func (h *Handler) UpdateEmailServerConfigByID(c *gin.Context)

UpdateEmailServerConfigByID updates an existing SMTP config by ID @Summary Update SMTP config @Description Update an existing SMTP server configuration by its ID @Tags Admin - Email Servers @Accept json @Produce json @Param id path string true "Config ID" @Param config body dto.EmailServerConfigRequest true "SMTP Config" @Success 200 {object} map[string]string @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-servers/{id} [put]

func (*Handler) UpdateEmailType

func (h *Handler) UpdateEmailType(c *gin.Context)

UpdateEmailType updates an existing email type @Summary Update an email type @Description Update an existing email type's name, description, subject, or variables @Tags Admin - Email @Accept json @Produce json @Param id path string true "Email Type ID" @Param emailType body dto.UpdateEmailTypeRequest true "Email Type Update Data" @Success 200 {object} dto.EmailTypeResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/email-types/{id} [put]

func (*Handler) UpdateIPRule

func (h *Handler) UpdateIPRule(c *gin.Context)

UpdateIPRule updates an existing IP rule @Summary Update an IP rule @Description Update an existing IP access rule by its ID @Tags Admin - IP Rules @Accept json @Produce json @Param id path string true "Application ID" @Param rule_id path string true "IP Rule ID" @Param request body dto.IPRuleUpdateRequest true "Updated IP rule data" @Success 200 {object} dto.IPRuleResponse @Failure 400 {object} dto.ErrorResponse @Failure 404 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/ip-rules/{rule_id} [put]

func (*Handler) UpsertOAuthConfig

func (h *Handler) UpsertOAuthConfig(c *gin.Context)

UpsertOAuthConfig creates or updates OAuth configuration for an app @Summary Set OAuth configuration @Description Configure OAuth provider credentials (Google, GitHub, etc.) for an application @Tags Admin @Accept json @Produce json @Param id path string true "Application ID" @Param config body dto.UpsertOAuthConfigRequest true "OAuth Config Data" @Success 200 {object} dto.OAuthConfigResponse @Failure 400 {object} dto.ErrorResponse @Failure 500 {object} dto.ErrorResponse @Security AdminApiKey @Router /admin/apps/{id}/oauth-config [post]

type MyAccountData

type MyAccountData struct {
	Email              string
	TwoFAEnabled       bool
	TwoFAMethod        string
	RecoveryCodesCount int
}

MyAccountData holds data for the My Account page template.

type MyAccountMagicLinkData

type MyAccountMagicLinkData struct {
	MagicLinkEnabled bool
}

MyAccountMagicLinkData holds data for the admin magic link status template.

type MyAccountPasskeyData

type MyAccountPasskeyData struct {
	Passkeys []models.WebAuthnCredential
}

MyAccountPasskeyData holds passkey list data for the admin passkey status template.

type OAuthConfigListItem

type OAuthConfigListItem struct {
	ID          uuid.UUID
	AppID       uuid.UUID
	AppName     string
	TenantName  string
	Provider    string
	ClientID    string
	RedirectURL string
	IsEnabled   bool
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

OAuthConfigListItem holds an OAuth config with app and tenant names for list views.

type OIDCClientListItem

type OIDCClientListItem struct {
	ID                string
	AppID             string
	Name              string
	Description       string
	ClientID          string
	AllowedGrantTypes string
	AllowedScopes     string
	IsConfidential    bool
	IsActive          bool
	CreatedAtStr      string
	CreatedAtFull     string
}

OIDCClientListItem is the view model for the OIDC client list partial.

type Repository

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

func NewRepository

func NewRepository(pool *pgxpool.Pool) *Repository

func (*Repository) AddAppToSessionGroup

func (r *Repository) AddAppToSessionGroup(groupID, appID string) error

AddAppToSessionGroup adds an application to a session group.

func (*Repository) CountApps

func (r *Repository) CountApps() (int64, error)

func (*Repository) CountSocialAccountsByUserID

func (r *Repository) CountSocialAccountsByUserID(userID string) (int64, error)

CountSocialAccountsByUserID returns the number of social accounts linked to a user.

func (*Repository) CountTenants

func (r *Repository) CountTenants() (int64, error)

func (*Repository) CountUsersByStatus

func (r *Repository) CountUsersByStatus() (*UserStatusCounts, error)

CountUsersByStatus returns the count of active and inactive users.

func (*Repository) CreateApiKey

func (r *Repository) CreateApiKey(apiKey *models.ApiKey) error

CreateApiKey inserts a new API key record.

func (*Repository) CreateApp

func (r *Repository) CreateApp(app *models.Application) error

func (*Repository) CreateSessionGroup

func (r *Repository) CreateSessionGroup(sg *models.SessionGroup) error

CreateSessionGroup inserts a new session group.

func (*Repository) CreateTenant

func (r *Repository) CreateTenant(tenant *models.Tenant) error

func (*Repository) DeleteApiKey

func (r *Repository) DeleteApiKey(id string) error

DeleteApiKey permanently deletes an API key by ID.

func (*Repository) DeleteApp

func (r *Repository) DeleteApp(id string) error

func (*Repository) DeleteOAuthConfig

func (r *Repository) DeleteOAuthConfig(id string) error

DeleteOAuthConfig deletes an OAuth config by ID.

func (*Repository) DeleteSessionGroup

func (r *Repository) DeleteSessionGroup(id string) error

DeleteSessionGroup deletes a session group and its app memberships.

func (*Repository) DeleteSocialAccount

func (r *Repository) DeleteSocialAccount(id string) error

DeleteSocialAccount permanently removes a social account by ID.

func (*Repository) DeleteTenant

func (r *Repository) DeleteTenant(id string) error

func (*Repository) DeleteWebAuthnCredential

func (r *Repository) DeleteWebAuthnCredential(id string) error

DeleteWebAuthnCredential permanently removes a WebAuthn credential by ID.

func (*Repository) ExportActivityLogs

func (r *Repository) ExportActivityLogs(eventType, severity, appID, search, startDate, endDate string) ([]ActivityLogExportItem, bool, error)

ExportActivityLogs returns up to ExportActivityLogsMaxRows activity log rows including UserAgent.

func (*Repository) ExportUsers

func (r *Repository) ExportUsers(appID, search string) ([]UserExportItem, bool, error)

ExportUsers returns up to ExportUsersMaxRows user rows.

func (*Repository) FindActiveKeyByHash

func (r *Repository) FindActiveKeyByHash(keyHash string) (*models.ApiKey, error)

FindActiveKeyByHash looks up an active (non-revoked, non-expired) API key by its SHA-256 hash. Returns nil, nil if no matching key is found.

func (*Repository) GetActivityLogDetail

func (r *Repository) GetActivityLogDetail(id string) (*ActivityLogDetail, error)

GetActivityLogDetail returns a full activity log detail view with user email and app name.

func (*Repository) GetApiKeyByID

func (r *Repository) GetApiKeyByID(id string) (*models.ApiKey, error)

GetApiKeyByID returns a single API key by ID.

func (*Repository) GetApiKeyTotalUsage

func (r *Repository) GetApiKeyTotalUsage(keyID uuid.UUID) (int64, error)

GetApiKeyTotalUsage returns the lifetime total request count for a key.

func (*Repository) GetApiKeyUsageSummary

func (r *Repository) GetApiKeyUsageSummary(keyID uuid.UUID, days int) ([]ApiKeyUsagePoint, error)

GetApiKeyUsageSummary returns daily usage data for a key over the last `days` days.

func (*Repository) GetAppByID

func (r *Repository) GetAppByID(id string) (*models.Application, error)

func (*Repository) GetAppNamesByIDs

func (r *Repository) GetAppNamesByIDs(appIDs []string) (map[string]string, error)

GetAppNamesByIDs returns a map of appID -> appName for the given application IDs.

func (*Repository) GetAppsInSessionGroup

func (r *Repository) GetAppsInSessionGroup(groupID string) ([]string, error)

GetAppsInSessionGroup returns all app IDs (as strings) that belong to the given group.

func (*Repository) GetAppsInSessionGroupWithDetails

func (r *Repository) GetAppsInSessionGroupWithDetails(groupID string) ([]SessionGroupAppDetail, error)

GetAppsInSessionGroupWithDetails returns apps in a session group with their names and tenant names.

func (*Repository) GetEnabledOAuthProviders

func (r *Repository) GetEnabledOAuthProviders(appID string) ([]string, error)

GetEnabledOAuthProviders returns the provider names (e.g. "google", "github") that are configured and enabled for the given app. Used by the public /app-config endpoint.

func (*Repository) GetFirstActiveOIDCClientLoginTheme

func (r *Repository) GetFirstActiveOIDCClientLoginTheme(appID string) (string, error)

GetFirstActiveOIDCClientLoginTheme returns the login_theme of the first active OIDC client for the given app, or an empty string if none exists.

func (*Repository) GetKeysExpiringWithin

func (r *Repository) GetKeysExpiringWithin(days int) ([]models.ApiKey, error)

GetKeysExpiringWithin returns all active (non-revoked) API keys expiring within `days` days.

func (*Repository) GetOAuthConfigByID

func (r *Repository) GetOAuthConfigByID(id string) (*models.OAuthProviderConfig, error)

GetOAuthConfigByID returns a single OAuth config by ID.

func (*Repository) GetPeersForApp

func (r *Repository) GetPeersForApp(appID string) ([]sso.SSOPeerInfo, error)

GetPeersForApp returns all peer applications (excluding the requesting app) in the same session group, with their app_id and frontend_url as origin.

func (*Repository) GetSessionGroupByID

func (r *Repository) GetSessionGroupByID(id string) (*models.SessionGroup, error)

GetSessionGroupByID returns a session group by its UUID string.

func (*Repository) GetSessionGroupForApp

func (r *Repository) GetSessionGroupForApp(appID string) (*models.SessionGroup, error)

GetSessionGroupForApp returns the session group that the given appID belongs to. Returns (nil, nil) when the app is not in any group.

func (*Repository) GetSocialAccountByID

func (r *Repository) GetSocialAccountByID(id string) (*models.SocialAccount, error)

GetSocialAccountByID returns a single social account by primary key.

func (*Repository) GetTenantByID

func (r *Repository) GetTenantByID(id string) (*models.Tenant, error)

func (*Repository) GetUserDetailByID

func (r *Repository) GetUserDetailByID(id string) (*UserDetail, error)

GetUserDetailByID returns a full user detail view with social accounts, app name, and tenant name.

func (*Repository) GetUserEmailsByIDs

func (r *Repository) GetUserEmailsByIDs(userIDs []string) (map[string]string, error)

GetUserEmailsByIDs returns a map of userID -> email for the given user IDs.

func (*Repository) GetUserIDByEmailAndApp

func (r *Repository) GetUserIDByEmailAndApp(appID, email string) (string, error)

GetUserIDByEmailAndApp returns the user ID (as a string) for the given email within the given application. Returns ("", nil) when no matching user exists.

func (*Repository) GetUsersByEmailsAndApp

func (r *Repository) GetUsersByEmailsAndApp(emails []string, appID uuid.UUID) ([]sqlcgen.AdminGetUsersByEmailsAndAppRow, error)

GetUsersByEmailsAndApp returns a slice of {ID, Email} for users matching the given emails in the app. Used for post-import activity log correlation.

func (*Repository) GetWebAuthnCredentialByID

func (r *Repository) GetWebAuthnCredentialByID(id string) (*models.WebAuthnCredential, error)

GetWebAuthnCredentialByID returns a single WebAuthn credential by primary key.

func (*Repository) HasActiveOIDCClients

func (r *Repository) HasActiveOIDCClients(appID string) (bool, error)

HasActiveOIDCClients returns true if at least one active OIDC client exists for the given app. Used by the public /app-config endpoint.

func (*Repository) ImportUsers

func (r *Repository) ImportUsers(appID string, rows []dto.UserImportRow) (dto.UserImportResult, error)

ImportUsers bulk-creates users from the provided rows under the given appID.

func (*Repository) IncrementDailyUsage

func (r *Repository) IncrementDailyUsage(keyID uuid.UUID)

IncrementDailyUsage upserts a daily usage row for the given API key, incrementing the count by 1.

func (*Repository) ListActivityLogs

func (r *Repository) ListActivityLogs(page, pageSize int, eventType, severity, appID, search, startDate, endDate string) ([]ActivityLogListItem, int64, error)

ListActivityLogs returns a paginated list of activity logs with user email and app name.

func (*Repository) ListAllAppsWithTenantName

func (r *Repository) ListAllAppsWithTenantName() ([]AppWithTenant, error)

ListAllAppsWithTenantName returns all applications with their tenant name, ordered by tenant then app name. Used for populating dropdown selects in forms and filters.

func (*Repository) ListAllTenants

func (r *Repository) ListAllTenants() ([]models.Tenant, error)

ListAllTenants returns all tenants (ID and Name only), ordered by name. Used for populating dropdown selects in forms and filters.

func (*Repository) ListApiKeys

func (r *Repository) ListApiKeys(page, pageSize int, keyType string) ([]ApiKeyListItem, int64, error)

ListApiKeys returns a paginated list of API keys with optional type filter.

func (*Repository) ListAppsByTenant

func (r *Repository) ListAppsByTenant(tenantID string) ([]models.Application, error)

func (*Repository) ListAppsWithDetails

func (r *Repository) ListAppsWithDetails(page, pageSize int, tenantID string) ([]AppListItem, int64, error)

ListAppsWithDetails returns paginated applications with tenant name and OAuth config count. If tenantID is non-empty, results are filtered to that tenant.

func (*Repository) ListDistinctEventTypes

func (r *Repository) ListDistinctEventTypes() ([]string, error)

ListDistinctEventTypes returns all distinct event types currently in the activity_logs table.

func (*Repository) ListDistinctSeverities

func (r *Repository) ListDistinctSeverities() ([]string, error)

ListDistinctSeverities returns all distinct severity levels currently in the activity_logs table.

func (*Repository) ListOAuthConfigsWithDetails

func (r *Repository) ListOAuthConfigsWithDetails(page, pageSize int, appID string) ([]OAuthConfigListItem, int64, error)

ListOAuthConfigsWithDetails returns paginated OAuth configs with app and tenant names. If appID is non-empty, results are filtered to that application.

func (*Repository) ListSessionGroups

func (r *Repository) ListSessionGroups(page, pageSize int) ([]SessionGroupListItem, int64, error)

ListSessionGroups returns paginated session groups with tenant name and app count.

func (*Repository) ListTenants

func (r *Repository) ListTenants(page, pageSize int) ([]models.Tenant, int64, error)

func (*Repository) ListTenantsWithAppCount

func (r *Repository) ListTenantsWithAppCount(page, pageSize int) ([]TenantListItem, int64, error)

ListTenantsWithAppCount returns paginated tenants with their application counts.

func (*Repository) ListUsersWithDetails

func (r *Repository) ListUsersWithDetails(page, pageSize int, appID, search string) ([]UserListItem, int64, error)

ListUsersWithDetails returns a paginated list of users with app/tenant info and social account counts. Supports optional filtering by appID and text search on email/name.

func (*Repository) MarkApiKeyNotified1Day

func (r *Repository) MarkApiKeyNotified1Day(id uuid.UUID) error

MarkApiKeyNotified1Day sets the notified_1_day_at timestamp to now.

func (*Repository) MarkApiKeyNotified7Days

func (r *Repository) MarkApiKeyNotified7Days(id uuid.UUID) error

MarkApiKeyNotified7Days sets the notified_7_days_at timestamp to now.

func (*Repository) RemoveAppFromSessionGroup

func (r *Repository) RemoveAppFromSessionGroup(groupID, appID string) error

RemoveAppFromSessionGroup removes an application from a session group.

func (*Repository) RevokeApiKey

func (r *Repository) RevokeApiKey(id string) error

RevokeApiKey sets the is_revoked flag to true for an API key.

func (*Repository) SeedDefaultRolesForApp

func (r *Repository) SeedDefaultRolesForApp(appID uuid.UUID) error

SeedDefaultRolesForApp creates the default system roles (admin, member, viewer) for an application and assigns them the standard permissions. Should be called after creating a new application.

func (*Repository) ToggleOAuthConfigEnabled

func (r *Repository) ToggleOAuthConfigEnabled(id string) (*models.OAuthProviderConfig, error)

ToggleOAuthConfigEnabled flips the IsEnabled flag for an OAuth config.

func (*Repository) ToggleUserActive

func (r *Repository) ToggleUserActive(id string) (isActive bool, appID string, err error)

ToggleUserActive toggles the is_active flag for a user and returns the new value along with the user's app_id.

func (*Repository) UnlockUser

func (r *Repository) UnlockUser(id string) (email string, appID string, err error)

UnlockUser clears the lockout fields for a user and returns the user's email and app_id.

func (*Repository) UpdateApiKeyLastUsed

func (r *Repository) UpdateApiKeyLastUsed(id uuid.UUID)

UpdateApiKeyLastUsed sets the last_used_at timestamp to now.

func (*Repository) UpdateApiKeyScopes

func (r *Repository) UpdateApiKeyScopes(id string, name, description, scopes string) error

UpdateApiKeyScopes updates the name, description, and scopes for an existing key.

func (*Repository) UpdateApp

func (r *Repository) UpdateApp(id string, name string, description string, frontendURL string, twoFAIssuerName string, twoFAEnabled bool, twoFARequired bool, passkey2FAEnabled bool, passkeyLoginEnabled bool, magicLinkEnabled bool, oidcEnabled bool, bf BruteForceAppSettings, custom AppCustomizationSettings) error

func (*Repository) UpdateAppSMSTrustedDevice

func (r *Repository) UpdateAppSMSTrustedDevice(id string, sms2FAEnabled bool, trustedDeviceEnabled bool, trustedDeviceMaxDays int) error

UpdateAppSMSTrustedDevice updates the SMS and trusted device settings for an application.

func (*Repository) UpdateOAuthConfigByID

func (r *Repository) UpdateOAuthConfigByID(id string, clientID string, clientSecret string, redirectURL string, isEnabled bool) error

UpdateOAuthConfigByID updates an OAuth config by primary key. If clientSecret is empty, the existing secret is preserved.

func (*Repository) UpdateSessionGroup

func (r *Repository) UpdateSessionGroup(id, name, description string, globalLogout bool) error

UpdateSessionGroup updates the mutable fields of a session group.

func (*Repository) UpdateTenant

func (r *Repository) UpdateTenant(id string, name string) error

func (*Repository) UpsertOAuthConfig

func (r *Repository) UpsertOAuthConfig(config *models.OAuthProviderConfig) error

type ResolvedSetting

type ResolvedSetting struct {
	Definition SettingDefinition
	Value      string        // Resolved value (masked if sensitive + env source)
	RawValue   string        // Actual value (for editing; empty if sensitive + env)
	Source     SettingSource // Where the value came from
	DBValue    *string       // Value stored in DB (nil if not in DB)
}

ResolvedSetting holds a setting definition with its resolved value and source.

type SessionGroupAppDetail

type SessionGroupAppDetail struct {
	AppID      uuid.UUID
	AppName    string
	TenantName string
}

SessionGroupAppDetail holds an app's membership info within a session group.

type SessionGroupListItem

type SessionGroupListItem struct {
	ID           uuid.UUID
	TenantID     uuid.UUID
	TenantName   string
	Name         string
	Description  string
	GlobalLogout bool
	AppCount     int64
	CreatedAt    time.Time
}

SessionGroupListItem holds a session group with tenant name and app count for list views.

type SettingDefinition

type SettingDefinition struct {
	Key             string // Setting key (matches env var name)
	EnvVar          string // Environment variable name (usually same as Key)
	Category        string // Category slug for grouping
	Type            SettingType
	DefaultValue    string        // Default as string
	Label           string        // Human-readable label
	Description     string        // Help text
	Sensitive       bool          // If true, value is masked in display
	RequiresRestart bool          // If true, changes need app restart
	UIHint          SettingUIHint // Optional rendering hint for the GUI
}

SettingDefinition describes a known system setting.

func GetSettingDefinition

func GetSettingDefinition(key string) *SettingDefinition

GetSettingDefinition returns the definition for a given key, or nil if not found.

type SettingSource

type SettingSource string

SettingSource indicates where a resolved setting value came from.

const (
	SourceEnv     SettingSource = "env"
	SourceDB      SettingSource = "db"
	SourceDefault SettingSource = "default"
)

type SettingType

type SettingType string

SettingType defines the expected value type for a setting.

const (
	SettingTypeString   SettingType = "string"
	SettingTypeInt      SettingType = "int"
	SettingTypeBool     SettingType = "bool"
	SettingTypeFloat    SettingType = "float"
	SettingTypeDuration SettingType = "duration"
)

type SettingUIHint

type SettingUIHint string

SettingUIHint controls how the admin GUI renders the value input for a setting.

const (
	// UIHintDefault renders a plain text input (or bool select / password input).
	UIHintDefault SettingUIHint = ""
	// UIHintTagList renders an interactive tag-chip widget for comma-separated values.
	UIHintTagList SettingUIHint = "tag_list"
)

type SettingsCategory

type SettingsCategory struct {
	Slug     string // URL-safe identifier
	Label    string // Human-readable name
	Icon     string // Bootstrap icon class
	Settings []ResolvedSetting
}

SettingsCategory groups resolved settings under a category.

type SettingsRepository

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

SettingsRepository handles CRUD operations for the system_settings table.

func NewSettingsRepository

func NewSettingsRepository(pool *pgxpool.Pool) *SettingsRepository

NewSettingsRepository creates a new SettingsRepository backed by pgx/SQLC.

func (*SettingsRepository) DeleteSetting

func (r *SettingsRepository) DeleteSetting(key string) error

DeleteSetting removes a setting from the database (reverts to default behavior).

func (*SettingsRepository) GetAllSettings

func (r *SettingsRepository) GetAllSettings() ([]models.SystemSetting, error)

GetAllSettings returns all system settings from the database.

func (*SettingsRepository) GetSettingByKey

func (r *SettingsRepository) GetSettingByKey(key string) (*models.SystemSetting, error)

GetSettingByKey returns a single setting by its key. Returns nil, nil if the key is not found in the database.

func (*SettingsRepository) GetSettingsByCategory

func (r *SettingsRepository) GetSettingsByCategory(category string) ([]models.SystemSetting, error)

GetSettingsByCategory returns all settings for a given category.

func (*SettingsRepository) UpsertSetting

func (r *SettingsRepository) UpsertSetting(key, value, category string) error

UpsertSetting inserts or updates a setting by key. Uses PostgreSQL ON CONFLICT DO UPDATE (upsert).

type SettingsService

type SettingsService struct {
	RedisAddr string
	Port      string
	GinMode   string
	// contains filtered or unexported fields
}

SettingsService handles settings resolution and management.

func NewSettingsService

func NewSettingsService(repo *SettingsRepository, pool *pgxpool.Pool, redisAddr, port, ginMode string) *SettingsService

NewSettingsService creates a new SettingsService.

func (*SettingsService) GetResolvedValue

func (s *SettingsService) GetResolvedValue(key string) string

GetResolvedValue resolves a single setting by key using the standard priority: env > DB > default. Returns empty string if the key is unknown. This is safe to call concurrently and does not load the entire registry.

func (*SettingsService) GetSystemInfo

func (s *SettingsService) GetSystemInfo() SystemInfo

GetSystemInfo returns read-only system information.

func (*SettingsService) ResetSetting

func (s *SettingsService) ResetSetting(key string) error

ResetSetting removes the DB override for a setting, reverting to env var or default.

func (*SettingsService) ResolveAllByCategory

func (s *SettingsService) ResolveAllByCategory() ([]SettingsCategory, error)

ResolveAllByCategory returns all settings grouped by category with resolved values.

func (*SettingsService) ResolveCategorySettings

func (s *SettingsService) ResolveCategorySettings(categorySlug string) (*SettingsCategory, error)

ResolveCategorySettings returns resolved settings for a single category.

func (*SettingsService) UpdateSetting

func (s *SettingsService) UpdateSetting(key, value string) error

UpdateSetting validates and persists a setting value.

type SystemInfo

type SystemInfo struct {
	GoVersion   string
	GOOS        string
	GOARCH      string
	NumCPU      int
	DBHost      string
	DBPort      string
	DBName      string
	DBStatus    string // "Connected" or error message
	RedisAddr   string
	RedisStatus string // "Connected" or error message
	Uptime      string
	StartTime   time.Time
	ServerPort  string
	GinMode     string
}

SystemInfo holds read-only system information for display.

type TenantListItem

type TenantListItem struct {
	ID        uuid.UUID
	Name      string
	AppCount  int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

TenantListItem holds a tenant with its app count for list views.

type TwoFASetupResponse

type TwoFASetupResponse struct {
	Secret     string `json:"secret"` // #nosec G101 -- TOTP secret for setup, not a hardcoded credential
	QRCodeData []byte `json:"qr_code_data"`
}

TwoFASetupResponse contains the TOTP secret and QR code for setup.

type UserDetail

type UserDetail struct {
	ID                  uuid.UUID                   `json:"id"`
	Email               string                      `json:"email"`
	Name                string                      `json:"name"`
	FirstName           string                      `json:"first_name"`
	LastName            string                      `json:"last_name"`
	ProfilePicture      string                      `json:"profile_picture"`
	Locale              string                      `json:"locale"`
	AppID               uuid.UUID                   `json:"app_id"`
	AppName             string                      `json:"app_name"`
	TenantName          string                      `json:"tenant_name"`
	IsActive            bool                        `json:"is_active"`
	EmailVerified       bool                        `json:"email_verified"`
	TwoFAEnabled        bool                        `json:"two_fa_enabled"`
	HasPassword         bool                        `json:"has_password"`
	BackupEmail         string                      `json:"backup_email"`
	BackupEmailVerified bool                        `json:"backup_email_verified"`
	PhoneNumber         string                      `json:"phone_number"`
	PhoneVerified       bool                        `json:"phone_verified"`
	LockedAt            *time.Time                  `json:"locked_at"`
	LockReason          string                      `json:"lock_reason"`
	LockExpiresAt       *time.Time                  `json:"lock_expires_at"`
	CreatedAt           time.Time                   `json:"created_at"`
	UpdatedAt           time.Time                   `json:"updated_at"`
	SocialAccounts      []models.SocialAccount      `json:"social_accounts"`
	WebAuthnCredentials []models.WebAuthnCredential `json:"webauthn_credentials"`
	TrustedDevices      []models.TrustedDevice      `json:"trusted_devices"`
}

UserDetail represents a full user view with social accounts for the admin GUI detail panel

type UserExportItem

type UserExportItem struct {
	ID              uuid.UUID `json:"id"`
	AppID           uuid.UUID `json:"app_id"`
	Email           string    `json:"email"`
	Name            string    `json:"name"`
	FirstName       string    `json:"first_name"`
	LastName        string    `json:"last_name"`
	Locale          string    `json:"locale"`
	EmailVerified   bool      `json:"email_verified"`
	IsActive        bool      `json:"is_active"`
	TwoFAEnabled    bool      `json:"two_fa_enabled"`
	TwoFAMethod     string    `json:"two_fa_method"`
	SocialProviders string    `json:"social_providers"` // STRING_AGG result, comma-separated
	CreatedAt       time.Time `json:"created_at"`
	UpdatedAt       time.Time `json:"updated_at"`
}

UserExportItem is a flat projection used for user export queries.

type UserListItem

type UserListItem struct {
	ID                 uuid.UUID  `json:"id"`
	Email              string     `json:"email"`
	Name               string     `json:"name"`
	AppID              uuid.UUID  `json:"app_id"`
	AppName            string     `json:"app_name"`
	TenantName         string     `json:"tenant_name"`
	IsActive           bool       `json:"is_active"`
	EmailVerified      bool       `json:"email_verified"`
	TwoFAEnabled       bool       `json:"two_fa_enabled"`
	HasPassword        bool       `json:"has_password"`
	SocialAccountCount int        `json:"social_account_count"`
	LockedAt           *time.Time `json:"locked_at"`
	LockExpiresAt      *time.Time `json:"lock_expires_at"`
	CreatedAt          time.Time  `json:"created_at"`
}

UserListItem represents a user row in the admin GUI list view

type UserStatusCounts

type UserStatusCounts struct {
	ActiveUsers   int64 `json:"active_users"`
	InactiveUsers int64 `json:"inactive_users"`
}

UserStatusCounts holds active/inactive user counts for dashboard display

Jump to

Keyboard shortcuts

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