models

package
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetUserIDFromContext added in v0.14.0

func GetUserIDFromContext(ctx context.Context) string

GetUserIDFromContext extracts user ID from context

func GetUsernameFromContext

func GetUsernameFromContext(ctx context.Context) string

GetUsernameFromContext extracts the username from the user object in context. Returns empty string if user cannot be determined.

func SetUserContext added in v0.14.0

func SetUserContext(ctx context.Context, user *User) context.Context

SetUserContext embeds user object into a standard context

Types

type AccessToken

type AccessToken struct {
	ID              string `gorm:"primaryKey"`
	Token           string `gorm:"uniqueIndex;not null"`
	TokenType       string `gorm:"not null;default:'Bearer'"`
	TokenCategory   string `gorm:"not null;default:'access';index"` // 'access' or 'refresh'
	Status          string `gorm:"not null;default:'active';index"` // 'active', 'disabled', 'revoked'
	UserID          string `gorm:"not null;index"`
	ClientID        string `gorm:"not null;index"`
	Scopes          string `gorm:"not null"` // space-separated scopes
	ExpiresAt       time.Time
	CreatedAt       time.Time
	LastUsedAt      *time.Time `gorm:"index"` // Last time token was used (for refresh tokens)
	ParentTokenID   string     `gorm:"index"` // Links access tokens to their refresh token
	AuthorizationID *uint      `gorm:"index"` // FK → UserAuthorization.ID (nil for device_code grants)
}

func (*AccessToken) IsAccessToken added in v0.11.0

func (t *AccessToken) IsAccessToken() bool

IsAccessToken returns true if token category is 'access'

func (*AccessToken) IsActive

func (t *AccessToken) IsActive() bool

IsActive returns true if token status is 'active'

func (*AccessToken) IsDisabled

func (t *AccessToken) IsDisabled() bool

IsDisabled returns true if token status is 'disabled'

func (*AccessToken) IsExpired

func (t *AccessToken) IsExpired() bool

func (*AccessToken) IsRefreshToken added in v0.11.0

func (t *AccessToken) IsRefreshToken() bool

IsRefreshToken returns true if token category is 'refresh'

func (*AccessToken) IsRevoked

func (t *AccessToken) IsRevoked() bool

IsRevoked returns true if token status is 'revoked'

type AuditDetails

type AuditDetails map[string]any

AuditDetails stores additional event-specific information as JSON

func (*AuditDetails) Scan

func (a *AuditDetails) Scan(value any) error

Scan implements the sql.Scanner interface for database retrieval

func (AuditDetails) Value

func (a AuditDetails) Value() (driver.Value, error)

Value implements the driver.Valuer interface for database storage

type AuditLog

type AuditLog struct {
	ID string `gorm:"primaryKey;type:varchar(36)" json:"id"`

	// Event information
	EventType EventType     `gorm:"type:varchar(50);index;not null" json:"event_type"`
	EventTime time.Time     `gorm:"index;not null"                  json:"event_time"`
	Severity  EventSeverity `gorm:"type:varchar(20);not null"       json:"severity"`

	// Actor information
	ActorUserID   string `gorm:"type:varchar(36);index" json:"actor_user_id"`
	ActorUsername string `gorm:"type:varchar(100)"      json:"actor_username"`
	ActorIP       string `gorm:"type:varchar(45);index" json:"actor_ip"` // Support IPv6

	// Resource information
	ResourceType ResourceType `gorm:"type:varchar(50);index" json:"resource_type"`
	ResourceID   string       `gorm:"type:varchar(36);index" json:"resource_id"`
	ResourceName string       `gorm:"type:varchar(255)"      json:"resource_name"`

	// Operation details
	Action       string       `gorm:"type:varchar(255);not null" json:"action"`
	Details      AuditDetails `gorm:"type:json"                  json:"details"`
	Success      bool         `gorm:"index;not null"             json:"success"`
	ErrorMessage string       `gorm:"type:text"                  json:"error_message,omitempty"`

	// Request metadata
	UserAgent     string `gorm:"type:varchar(500)" json:"user_agent,omitempty"`
	RequestPath   string `gorm:"type:varchar(500)" json:"request_path,omitempty"`
	RequestMethod string `gorm:"type:varchar(10)"  json:"request_method,omitempty"`

	// Timestamps (no UpdatedAt - immutable logs)
	CreatedAt time.Time `gorm:"index;not null" json:"created_at"`
}

AuditLog represents an audit log entry

func (AuditLog) TableName

func (AuditLog) TableName() string

TableName specifies the table name for GORM

type AuthorizationCode

type AuthorizationCode struct {
	ID   uint   `gorm:"primaryKey;autoIncrement"`
	UUID string `gorm:"uniqueIndex;size:36;not null"` // Public UUID for API/UI identification

	// Code storage: SHA256 hash for security, prefix for quick lookup
	CodeHash   string `gorm:"uniqueIndex;not null"`  // SHA256(plainCode)
	CodePrefix string `gorm:"index;not null;size:8"` // First 8 chars for quick lookup

	// Relations (int PK for fast JOIN, string ClientID for OAuth protocol)
	ApplicationID int64  `gorm:"not null;index"` // FK → OAuthApplication.ID
	ClientID      string `gorm:"not null;index"` // Denormalized ClientID UUID (OAuth protocol use)
	UserID        string `gorm:"not null;index"` // FK → User.ID

	RedirectURI string `gorm:"not null"`
	Scopes      string `gorm:"not null"`

	// PKCE (RFC 7636)
	CodeChallenge       string `gorm:"default:''"`     // code_challenge (empty = PKCE not used)
	CodeChallengeMethod string `gorm:"default:'S256'"` // "S256" or "plain"

	// OIDC (OpenID Connect Core 1.0 §3.1.2.1)
	Nonce string `gorm:"default:''"` // nonce from authorization request (empty if not provided)

	ExpiresAt time.Time
	UsedAt    *time.Time // Set immediately upon exchange; prevents replay attacks
	CreatedAt time.Time
}

AuthorizationCode stores OAuth 2.0 authorization codes (RFC 6749). Codes are short-lived (default 10 minutes) and single-use.

func (*AuthorizationCode) IsExpired

func (a *AuthorizationCode) IsExpired() bool

func (*AuthorizationCode) IsUsed

func (a *AuthorizationCode) IsUsed() bool

func (AuthorizationCode) TableName

func (AuthorizationCode) TableName() string

type DeviceCode

type DeviceCode struct {
	ID             int64  `gorm:"primaryKey;autoIncrement"`
	DeviceCode     string `gorm:"-"`                    // Not stored in DB, only for in-memory use
	DeviceCodeHash string `gorm:"uniqueIndex;not null"` // PBKDF2 hash of device code
	DeviceCodeSalt string `gorm:"not null"`             // Random salt for hashing
	DeviceCodeID   string `gorm:"index;not null"`       // Last 8 chars for quick lookup
	UserCode       string `gorm:"uniqueIndex;not null"`
	ClientID       string `gorm:"not null;index"`
	Scopes         string `gorm:"not null"` // space-separated scopes
	ExpiresAt      time.Time
	Interval       int    // polling interval in seconds
	UserID         string // filled after authorization
	Authorized     bool   `gorm:"default:false"`
	AuthorizedAt   time.Time
	CreatedAt      time.Time
	UpdatedAt      time.Time
}

func (*DeviceCode) IsExpired

func (d *DeviceCode) IsExpired() bool

type EventSeverity

type EventSeverity string

EventSeverity represents the severity level of an audit event

const (
	SeverityInfo     EventSeverity = "INFO"
	SeverityWarning  EventSeverity = "WARNING"
	SeverityError    EventSeverity = "ERROR"
	SeverityCritical EventSeverity = "CRITICAL"
)

type EventType

type EventType string

EventType represents the type of audit event

const (
	// Authentication events
	EventAuthenticationSuccess EventType = "AUTHENTICATION_SUCCESS"
	EventAuthenticationFailure EventType = "AUTHENTICATION_FAILURE"
	EventLogout                EventType = "LOGOUT"
	EventOAuthAuthentication   EventType = "OAUTH_AUTHENTICATION"

	// Device authorization events
	EventDeviceCodeGenerated  EventType = "DEVICE_CODE_GENERATED"
	EventDeviceCodeAuthorized EventType = "DEVICE_CODE_AUTHORIZED"

	// Token events
	EventAccessTokenIssued  EventType = "ACCESS_TOKEN_ISSUED"
	EventRefreshTokenIssued EventType = "REFRESH_TOKEN_ISSUED"
	EventIDTokenIssued      EventType = "ID_TOKEN_ISSUED"
	EventTokenRefreshed     EventType = "TOKEN_REFRESHED"
	EventTokenRevoked       EventType = "TOKEN_REVOKED"
	EventTokenDisabled      EventType = "TOKEN_DISABLED"
	EventTokenEnabled       EventType = "TOKEN_ENABLED"

	// Admin operations
	EventClientCreated           EventType = "CLIENT_CREATED"
	EventClientUpdated           EventType = "CLIENT_UPDATED"
	EventClientDeleted           EventType = "CLIENT_DELETED"
	EventClientSecretRegenerated EventType = "CLIENT_SECRET_REGENERATED"

	// Security events
	EventRateLimitExceeded  EventType = "RATE_LIMIT_EXCEEDED"
	EventSuspiciousActivity EventType = "SUSPICIOUS_ACTIVITY"

	// Authorization Code Flow events (RFC 6749)
	EventAuthorizationCodeGenerated EventType = "AUTHORIZATION_CODE_GENERATED"
	EventAuthorizationCodeExchanged EventType = "AUTHORIZATION_CODE_EXCHANGED"
	EventAuthorizationCodeDenied    EventType = "AUTHORIZATION_CODE_DENIED"
	EventUserAuthorizationGranted   EventType = "USER_AUTHORIZATION_GRANTED"
	EventUserAuthorizationRevoked   EventType = "USER_AUTHORIZATION_REVOKED"
	EventClientTokensRevokedAll     EventType = "CLIENT_TOKENS_REVOKED_ALL" //nolint:gosec // G101: false positive, this is a const string describing an event type, not a credential

	// Client Credentials Flow events (RFC 6749 §4.4)
	EventClientCredentialsTokenIssued EventType = "CLIENT_CREDENTIALS_TOKEN_ISSUED" //nolint:gosec // G101: false positive

	// Audit events
	EventTypeAuditLogView     EventType = "AUDIT_LOG_VIEWED"
	EventTypeAuditLogExported EventType = "AUDIT_LOG_EXPORTED"
)

type OAuthApplication

type OAuthApplication struct {
	ID                          int64       `gorm:"primaryKey;autoIncrement"`
	ClientID                    string      `gorm:"uniqueIndex;not null"`
	ClientSecret                string      `gorm:"not null"` // bcrypt hashed secret
	ClientName                  string      `gorm:"not null"`
	Description                 string      `gorm:"type:text"`
	UserID                      string      `gorm:"not null"`
	Scopes                      string      `gorm:"not null"`
	GrantTypes                  string      `gorm:"not null;default:'device_code'"`
	RedirectURIs                StringArray `gorm:"type:json"`
	ClientType                  string      `gorm:"not null;default:'public'"` // "confidential" or "public"
	EnableDeviceFlow            bool        `gorm:"not null;default:true"`
	EnableAuthCodeFlow          bool        `gorm:"not null;default:false"`
	EnableClientCredentialsFlow bool        `gorm:"not null;default:false"` // Client Credentials Grant (RFC 6749 §4.4); confidential clients only
	IsActive                    bool        `gorm:"not null;default:true"`
	CreatedBy                   string
	CreatedAt                   time.Time
	UpdatedAt                   time.Time
}

func (*OAuthApplication) GenerateClientSecret

func (app *OAuthApplication) GenerateClientSecret(ctx context.Context) (string, error)

GenerateClientSecret will generate the client secret and returns the plaintext and saves the hash at the database

func (OAuthApplication) TableName

func (OAuthApplication) TableName() string

TableName overrides the table name used by OAuthApplication to `oauth_applications`

func (*OAuthApplication) ValidateClientSecret

func (app *OAuthApplication) ValidateClientSecret(secret []byte) bool

ValidateClientSecret validates the given secret by the hash saved in database

type OAuthConnection

type OAuthConnection struct {
	ID             string `gorm:"primaryKey"`
	UserID         string `gorm:"not null;uniqueIndex:idx_oauth_user_provider,priority:1"`
	Provider       string `gorm:"not null;uniqueIndex:idx_oauth_provider_user,priority:1;uniqueIndex:idx_oauth_user_provider,priority:2"` // "github", "gitea", "gitlab"
	ProviderUserID string `gorm:"not null;uniqueIndex:idx_oauth_provider_user,priority:2"`                                                // Provider's user ID

	// OAuth metadata (snapshot for audit/reference)
	ProviderUsername string // Provider's username
	ProviderEmail    string // Provider's email (snapshot)
	AvatarURL        string // User avatar URL from provider

	// Token storage (should be encrypted in production)
	AccessToken  string    `gorm:"type:text"` // OAuth access token
	RefreshToken string    `gorm:"type:text"` // OAuth refresh token
	TokenExpiry  time.Time // Token expiration time

	// Activity tracking
	LastUsedAt time.Time

	CreatedAt time.Time
	UpdatedAt time.Time
}

OAuthConnection represents an OAuth provider connection for a user

func (OAuthConnection) TableName

func (OAuthConnection) TableName() string

TableName overrides the table name used by OAuthConnection to `oauth_connections`

type ResourceType

type ResourceType string

ResourceType represents the type of resource being operated on

const (
	ResourceUser          ResourceType = "USER"
	ResourceClient        ResourceType = "CLIENT"
	ResourceToken         ResourceType = "TOKEN"
	ResourceDeviceCode    ResourceType = "DEVICE_CODE"
	ResourceOAuthConfig   ResourceType = "OAUTH_CONFIG"
	ResourceAuthorization ResourceType = "AUTHORIZATION"
)

type StringArray

type StringArray []string

StringArray is a custom type for []string that can be stored as JSON in database

func (StringArray) Join

func (s StringArray) Join(sep string) string

Join returns a string with elements joined by the specified separator

func (*StringArray) Scan

func (s *StringArray) Scan(value any) error

Scan implements sql.Scanner interface

func (StringArray) Value

func (s StringArray) Value() (driver.Value, error)

Value implements driver.Valuer interface

type User

type User struct {
	ID           string `gorm:"primaryKey"`
	Username     string `gorm:"uniqueIndex;not null"`
	Email        string `gorm:"uniqueIndex;not null"` // Email is unique and required
	PasswordHash string // OAuth-only users have empty password
	Role         string `gorm:"not null;default:'user'"` // "admin" or "user"
	FullName     string // User full name
	AvatarURL    string // User avatar URL (from OAuth or manual)

	// External authentication support
	ExternalID string `gorm:"index"`           // External user ID (e.g., from HTTP API)
	AuthSource string `gorm:"default:'local'"` // "local" or "http_api"

	CreatedAt time.Time
	UpdatedAt time.Time
}

func GetUserFromContext added in v0.14.0

func GetUserFromContext(ctx context.Context) *User

GetUserFromContext extracts full user object from context

func (*User) IsAdmin

func (u *User) IsAdmin() bool

IsAdmin returns true if the user has admin role

func (*User) IsExternal

func (u *User) IsExternal() bool

IsExternal returns true if user authenticates via external provider

type UserAuthorization

type UserAuthorization struct {
	ID   uint   `gorm:"primaryKey;autoIncrement"`
	UUID string `gorm:"uniqueIndex;size:36;not null"` // Public UUID for API/UI identification

	// Relations (composite unique index ensures one grant per user+app)
	UserID        string `gorm:"not null;uniqueIndex:idx_user_app"` // FK → User.ID
	ApplicationID int64  `gorm:"not null;uniqueIndex:idx_user_app"` // FK → OAuthApplication.ID
	ClientID      string `gorm:"not null;index"`                    // Denormalized ClientID UUID (for UI display and API responses)

	Scopes    string `gorm:"not null"`
	GrantedAt time.Time
	RevokedAt *time.Time
	IsActive  bool `gorm:"not null;default:true"`

	CreatedAt time.Time
	UpdatedAt time.Time
}

UserAuthorization records a user's consent grant to an OAuth application. There is at most one active record per (UserID, ApplicationID) pair.

func (UserAuthorization) TableName

func (UserAuthorization) TableName() string

Jump to

Keyboard shortcuts

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