[split-required] [guardrail-change] Enforce 500 LOC budget across all services
Install LOC guardrails (check-loc.sh, architecture.md, pre-commit hook) and split all 44 files exceeding 500 LOC into domain-focused modules: - consent-service (Go): models, handlers, services, database splits - backend-core (Python): security_api, rbac_api, pdf_service, auth splits - admin-core (TypeScript): 5 page.tsx + sidebar extractions - pitch-deck (TypeScript): 6 slides, 3 UI components, engine.ts splits - voice-service (Python): enhanced_task_orchestrator split Result: 0 violations, 36 exempted (pipeline, tests, pure-data files). Go build verified clean. No behavior changes — pure structural splits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
103
consent-service/internal/models/oauth.go
Normal file
103
consent-service/internal/models/oauth.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// OAuthClient represents a registered OAuth 2.0 client application
|
||||
type OAuthClient struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
ClientID string `json:"client_id" db:"client_id"`
|
||||
ClientSecret string `json:"-" db:"client_secret"` // Never expose in JSON
|
||||
Name string `json:"name" db:"name"`
|
||||
Description *string `json:"description,omitempty" db:"description"`
|
||||
RedirectURIs []string `json:"redirect_uris" db:"redirect_uris"` // JSON array
|
||||
Scopes []string `json:"scopes" db:"scopes"` // Allowed scopes
|
||||
GrantTypes []string `json:"grant_types" db:"grant_types"` // authorization_code, refresh_token
|
||||
IsPublic bool `json:"is_public" db:"is_public"` // Public clients (SPAs) don't have secret
|
||||
IsActive bool `json:"is_active" db:"is_active"`
|
||||
CreatedBy *uuid.UUID `json:"created_by,omitempty" db:"created_by"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
// OAuthAuthorizationCode represents an authorization code for the OAuth flow
|
||||
type OAuthAuthorizationCode struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
Code string `json:"-" db:"code"` // Hashed
|
||||
ClientID string `json:"client_id" db:"client_id"`
|
||||
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
||||
RedirectURI string `json:"redirect_uri" db:"redirect_uri"`
|
||||
Scopes []string `json:"scopes" db:"scopes"`
|
||||
CodeChallenge *string `json:"-" db:"code_challenge"` // For PKCE
|
||||
CodeChallengeMethod *string `json:"-" db:"code_challenge_method"` // S256 or plain
|
||||
ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
|
||||
UsedAt *time.Time `json:"used_at,omitempty" db:"used_at"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
}
|
||||
|
||||
// OAuthAccessToken represents an OAuth access token
|
||||
type OAuthAccessToken struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
TokenHash string `json:"-" db:"token_hash"`
|
||||
ClientID string `json:"client_id" db:"client_id"`
|
||||
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
||||
Scopes []string `json:"scopes" db:"scopes"`
|
||||
ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
|
||||
RevokedAt *time.Time `json:"revoked_at,omitempty" db:"revoked_at"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
}
|
||||
|
||||
// OAuthRefreshToken represents an OAuth refresh token
|
||||
type OAuthRefreshToken struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
TokenHash string `json:"-" db:"token_hash"`
|
||||
AccessTokenID uuid.UUID `json:"access_token_id" db:"access_token_id"`
|
||||
ClientID string `json:"client_id" db:"client_id"`
|
||||
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
||||
Scopes []string `json:"scopes" db:"scopes"`
|
||||
ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
|
||||
RevokedAt *time.Time `json:"revoked_at,omitempty" db:"revoked_at"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
}
|
||||
|
||||
// OAuthAuthorizeRequest for the authorization endpoint
|
||||
type OAuthAuthorizeRequest struct {
|
||||
ResponseType string `form:"response_type" binding:"required"` // Must be "code"
|
||||
ClientID string `form:"client_id" binding:"required"`
|
||||
RedirectURI string `form:"redirect_uri" binding:"required"`
|
||||
Scope string `form:"scope"` // Space-separated scopes
|
||||
State string `form:"state" binding:"required"` // CSRF protection
|
||||
CodeChallenge string `form:"code_challenge"` // PKCE
|
||||
CodeChallengeMethod string `form:"code_challenge_method"` // S256 (recommended) or plain
|
||||
}
|
||||
|
||||
// OAuthTokenRequest for the token endpoint
|
||||
type OAuthTokenRequest struct {
|
||||
GrantType string `form:"grant_type" binding:"required"` // authorization_code or refresh_token
|
||||
Code string `form:"code"` // For authorization_code grant
|
||||
RedirectURI string `form:"redirect_uri"` // For authorization_code grant
|
||||
ClientID string `form:"client_id" binding:"required"`
|
||||
ClientSecret string `form:"client_secret"` // For confidential clients
|
||||
CodeVerifier string `form:"code_verifier"` // For PKCE
|
||||
RefreshToken string `form:"refresh_token"` // For refresh_token grant
|
||||
Scope string `form:"scope"` // For refresh_token grant (optional)
|
||||
}
|
||||
|
||||
// OAuthTokenResponse for successful token requests
|
||||
type OAuthTokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"` // Always "Bearer"
|
||||
ExpiresIn int `json:"expires_in"` // Seconds until expiration
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
Scope string `json:"scope,omitempty"`
|
||||
}
|
||||
|
||||
// OAuthErrorResponse for OAuth errors (RFC 6749)
|
||||
type OAuthErrorResponse struct {
|
||||
Error string `json:"error"`
|
||||
ErrorDescription string `json:"error_description,omitempty"`
|
||||
ErrorURI string `json:"error_uri,omitempty"`
|
||||
}
|
||||
Reference in New Issue
Block a user