mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-23 19:06:33 +00:00
0e32645bb5
Backend support for optional TOTP-based 2FA on user accounts:
- POST /auth/2fa/setup — generate TOTP secret, return QR code URI
- POST /auth/2fa/verify — verify code and enable 2FA with recovery codes
- POST /auth/2fa/disable — disable 2FA (requires password confirmation)
- POST /auth/2fa/login-verify — complete login with TOTP or recovery code
- Login returns {requires_2fa: true, user_id} when 2FA is enabled,
requiring a second step via /auth/2fa/login-verify
- 8 recovery codes generated on setup for account recovery
- User model extended with totp_secret, totp_enabled, recovery_codes
- Refactored user queries with shared scanUser/userColumns for DRYness
Implements TASK-169 under PLAN-15 (Pad Cloud: Hardening).
87 lines
2.7 KiB
Go
87 lines
2.7 KiB
Go
package models
|
|
|
|
import "time"
|
|
|
|
// Item-level actions (existing)
|
|
var ValidActions = []string{
|
|
"created", "updated", "archived", "restored", "moved", "read", "searched",
|
|
}
|
|
|
|
// Audit action constants for auth/admin events
|
|
const (
|
|
ActionLogin = "login"
|
|
ActionLoginFailed = "login_failed"
|
|
ActionLogout = "logout"
|
|
ActionBootstrap = "bootstrap"
|
|
ActionRegister = "register"
|
|
ActionPasswordChanged = "password_changed"
|
|
ActionPasswordReset = "password_reset"
|
|
ActionTokenCreated = "token_created"
|
|
ActionTokenRevoked = "token_revoked"
|
|
ActionTokenRotated = "token_rotated"
|
|
ActionTOTPEnabled = "totp_enabled"
|
|
ActionTOTPDisabled = "totp_disabled"
|
|
ActionMemberInvited = "member_invited"
|
|
ActionMemberRemoved = "member_removed"
|
|
ActionRoleChanged = "role_changed"
|
|
ActionSettingsChanged = "settings_changed"
|
|
)
|
|
|
|
type Activity struct {
|
|
ID string `json:"id"`
|
|
WorkspaceID string `json:"workspace_id,omitempty"`
|
|
DocumentID string `json:"document_id,omitempty"`
|
|
Action string `json:"action"`
|
|
Actor string `json:"actor"`
|
|
Source string `json:"source"`
|
|
Metadata string `json:"metadata,omitempty"` // JSON
|
|
UserID string `json:"user_id,omitempty"`
|
|
IPAddress string `json:"ip_address,omitempty"`
|
|
UserAgent string `json:"user_agent,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
// Enrichment fields — populated by handlers, not stored in DB
|
|
ItemTitle string `json:"item_title,omitempty"`
|
|
ItemSlug string `json:"item_slug,omitempty"`
|
|
CollectionSlug string `json:"collection_slug,omitempty"`
|
|
ActorName string `json:"actor_name,omitempty"`
|
|
}
|
|
|
|
type ActivityListParams struct {
|
|
Action string
|
|
Actor string
|
|
Source string
|
|
Limit int
|
|
Offset int
|
|
}
|
|
|
|
// AuditLogParams are query parameters for the audit log endpoint.
|
|
type AuditLogParams struct {
|
|
Action string
|
|
Actor string
|
|
WorkspaceID string
|
|
Days int
|
|
Limit int
|
|
Offset int
|
|
}
|
|
|
|
// TimelineEntry represents a single entry in the unified item timeline.
|
|
// It wraps one of: a comment, an activity, or a version.
|
|
type TimelineEntry struct {
|
|
ID string `json:"id"`
|
|
Kind string `json:"kind"` // "comment", "activity", "version"
|
|
CreatedAt time.Time `json:"created_at"`
|
|
Actor string `json:"actor"`
|
|
ActorName string `json:"actor_name,omitempty"`
|
|
Source string `json:"source"`
|
|
Comment *Comment `json:"comment,omitempty"`
|
|
Activity *Activity `json:"activity,omitempty"`
|
|
Version *Version `json:"version,omitempty"`
|
|
}
|
|
|
|
// TimelineResponse is the paginated response from the timeline endpoint.
|
|
type TimelineResponse struct {
|
|
Entries []TimelineEntry `json:"entries"`
|
|
HasMore bool `json:"has_more"`
|
|
}
|