Documentation
¶
Index ¶
- Constants
- Variables
- func Can(role OrganizationRole, permission string) bool
- func DetectStoreFromSubscriptionID(subscriptionID *string) string
- func GenerateSCIMToken() (string, error)
- func GetPermissions(role OrganizationRole) []string
- func IsWritePermission(permission string) bool
- func StoreDisplayName(store string) string
- type ActivityType
- type AddTeamUserRequest
- type AuthResponse
- type BillingCycle
- type BillingInfo
- type CancelSubscriptionRequest
- type ChangeMasterPasswordRequest
- type Collection
- type CollectionDTO
- type CollectionTeam
- type CollectionTeamDTO
- type CollectionUser
- type CollectionUserDTO
- type CreateActivityRequest
- type CreateCollectionRequest
- type CreateExcludedDomainRequest
- type CreateInvitationRequest
- type CreateItemShareRequest
- type CreateOrganizationFolderRequest
- type CreateOrganizationItemRequest
- type CreateOrganizationRequest
- type CreateSCIMTokenRequest
- type CreateSSOConnectionRequest
- type CreateSubscriptionRequest
- type CreateTeamRequest
- type CreateUserByAdminRequest
- type Credentials
- type DeleteWithOrganizationsRequest
- type ErrValidation
- type ExcludedDomain
- type ExcludedDomainDTO
- type FieldType
- type GrantCollectionAccessRequest
- type Invitation
- type InviteUserToOrgRequest
- type InvoiceDTO
- type InvoiceStatus
- type Item
- type ItemMetadata
- type ItemShare
- type ItemShareDTO
- type ItemType
- type KdfConfig
- type KdfType
- type MoveItemToCollectionRequest
- type OIDCConfig
- type OIDCConfigDTO
- type Organization
- type OrganizationDTO
- type OrganizationFolder
- type OrganizationFolderDTO
- type OrganizationItem
- type OrganizationItemDTO
- type OrganizationPlan
- type OrganizationRole
- type OrganizationStatus
- type OrganizationUser
- type OrganizationUserDTO
- type OrganizationUserStatus
- type OwnershipCheckResult
- type PaymentProvider
- type Permission
- type Plan
- type PlanChangePreview
- type PlanChangeResult
- type PlanDTO
- type PlanFeatures
- type PreLoginRequest
- type PreLoginResponse
- type Preference
- type PreferenceDTO
- type ResendVerificationRequest
- type Role
- type SAMLConfig
- type SAMLConfigDTO
- type SCIMEmail
- type SCIMError
- type SCIMGroup
- type SCIMGroupRef
- type SCIMListResponse
- type SCIMMemberRef
- type SCIMMeta
- type SCIMName
- type SCIMPatchOp
- type SCIMPatchOpItem
- type SCIMToken
- type SCIMTokenCreatedDTO
- type SCIMTokenDTO
- type SCIMUser
- type SSOCallbackResult
- type SSOConnection
- type SSOConnectionDTO
- type SSOConnectionStatus
- type SSOInitiateRequest
- type SSOProtocol
- type SSOState
- type SeatChangePreview
- type SharePersonalItemRequest
- type SignUpRequest
- type SoleOwnerOrganization
- type Subscription
- type SubscriptionDTO
- type SubscriptionState
- type Team
- type TeamDTO
- type TeamUser
- type TeamUserDTO
- type Token
- type TokenClaims
- type TokenDetails
- type TransferOwnershipRequest
- type UpdateCollectionRequest
- type UpdateOrgUserRoleRequest
- type UpdateOrganizationFolderRequest
- type UpdateOrganizationItemRequest
- type UpdateOrganizationRequest
- type UpdateSSOConnectionRequest
- type UpdateSubscriptionRequest
- type UpdateTeamRequest
- type UpdateTeamUserRequest
- type UpdateUserAppearancePreferencesRequest
- type UpdateUserNotificationPreferencesRequest
- type UpdateUserRequest
- type UpsertPreferenceRequest
- type UpsertPreferencesRequest
- type User
- type UserActivity
- type UserActivityDTO
- type UserAppearancePreferences
- type UserAppearancePreferencesDTO
- type UserAuthDTO
- type UserBillingInfo
- type UserDTO
- type UserNotificationPreferences
- type UserNotificationPreferencesDTO
- type UserSubscription
- func (s *UserSubscription) CanWrite() bool
- func (s *UserSubscription) IsActive() bool
- func (s *UserSubscription) IsCanceled() bool
- func (s *UserSubscription) IsExpired() bool
- func (s *UserSubscription) IsInGracePeriod() bool
- func (s *UserSubscription) ShouldExpire() bool
- func (UserSubscription) TableName() string
- type UserSubscriptionDTO
- type VerificationCode
- type VerificationCodeRequest
- type VerificationCodeResponse
- type VerifyEmailRequest
- type VerifyEmailResponse
- type WebhookEvent
- type WebhookPayload
Constants ¶
const ( PBKDF2MinIterations = 600000 // Minimum (security) PBKDF2DefaultIterations = 600000 // Default (balanced) PBKDF2MaxIterations = 2000000 // Maximum (high security) )
PBKDF2 defaults (OWASP 2023 recommendations)
const ( Argon2DefaultIterations = 3 // Time cost Argon2DefaultMemory = 64 // 64 MB Argon2DefaultParallelism = 4 // 4 threads Argon2MinIterations = 2 Argon2MaxIterations = 10 Argon2MinMemory = 16 // 16 MB Argon2MaxMemory = 1024 // 1 GB Argon2MinParallelism = 1 Argon2MaxParallelism = 16 )
Argon2id defaults (industry standard)
const ( // Users permissions PermissionUsersRead = "users.read" PermissionUsersCreate = "users.create" PermissionUsersUpdate = "users.update" PermissionUsersDelete = "users.delete" // Logins permissions PermissionLoginsRead = "logins.read" PermissionLoginsCreate = "logins.create" PermissionLoginsUpdate = "logins.update" PermissionLoginsDelete = "logins.delete" // Credit Cards permissions PermissionCreditCardsRead = "credit_cards.read" PermissionCreditCardsCreate = "credit_cards.create" PermissionCreditCardsUpdate = "credit_cards.update" PermissionCreditCardsDelete = "credit_cards.delete" // Bank Accounts permissions PermissionBankAccountsRead = "bank_accounts.read" PermissionBankAccountsCreate = "bank_accounts.create" PermissionBankAccountsUpdate = "bank_accounts.update" PermissionBankAccountsDelete = "bank_accounts.delete" // Notes permissions PermissionNotesRead = "notes.read" PermissionNotesCreate = "notes.create" PermissionNotesUpdate = "notes.update" PermissionNotesDelete = "notes.delete" // Emails permissions PermissionEmailsRead = "emails.read" PermissionEmailsCreate = "emails.create" PermissionEmailsUpdate = "emails.update" PermissionEmailsDelete = "emails.delete" )
Permission name constants
const ( // Organization permissions PermOrgView = "org:view" PermOrgUpdate = "org:update" PermOrgDelete = "org:delete" PermOrgTransferOwnership = "org:transfer_ownership" PermOrgManageSettings = "org:manage_settings" // Member permissions PermMemberView = "member:view" PermMemberInvite = "member:invite" PermMemberRemove = "member:remove" PermMemberUpdateRole = "member:update_role" // Billing permissions PermBillingView = "billing:view" PermBillingUpdate = "billing:update" PermBillingCancel = "billing:cancel" PermBillingDownloadInvoice = "billing:download_invoice" // Collection permissions PermCollectionCreate = "collection:create" PermCollectionView = "collection:view" PermCollectionUpdate = "collection:update" PermCollectionDelete = "collection:delete" // Item permissions PermItemCreate = "item:create" PermItemView = "item:view" PermItemUpdate = "item:update" PermItemDelete = "item:delete" PermItemExport = "item:export" // Activity/Audit permissions PermActivityView = "activity:view" PermActivityExport = "activity:export" // Security permissions PermSecurityRotateKeys = "security:rotate_keys" PermSecurityRevokeSessions = "security:revoke_sessions" )
Permission constants
const ( SCIMSchemaUser = "urn:ietf:params:scim:schemas:core:2.0:User" SCIMSchemaGroup = "urn:ietf:params:scim:schemas:core:2.0:Group" SCIMSchemaListResponse = "urn:ietf:params:scim:api:messages:2.0:ListResponse" SCIMSchemaError = "urn:ietf:params:scim:api:messages:2.0:Error" SCIMSchemaPatchOp = "urn:ietf:params:scim:api:messages:2.0:PatchOp" SCIMSchemaServiceConfig = "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig" SCIMSchemaResourceType = "urn:ietf:params:scim:schemas:core:2.0:ResourceType" SCIMSchemaSchema = "urn:ietf:params:scim:schemas:core:2.0:Schema" )
SCIM 2.0 schema URNs
Variables ¶
var PermissionMatrix = map[OrganizationRole][]string{ OrgRoleOwner: { PermOrgView, PermOrgUpdate, PermOrgDelete, PermOrgTransferOwnership, PermOrgManageSettings, PermMemberView, PermMemberInvite, PermMemberRemove, PermMemberUpdateRole, PermBillingView, PermBillingUpdate, PermBillingCancel, PermBillingDownloadInvoice, PermCollectionCreate, PermCollectionView, PermCollectionUpdate, PermCollectionDelete, PermItemCreate, PermItemView, PermItemUpdate, PermItemDelete, PermItemShare, PermItemExport, PermActivityView, PermActivityExport, PermSecurityRotateKeys, PermSecurityRevokeSessions, }, OrgRoleAdmin: { PermOrgView, PermOrgUpdate, PermMemberView, PermMemberInvite, PermMemberRemove, PermCollectionCreate, PermCollectionView, PermCollectionUpdate, PermCollectionDelete, PermItemCreate, PermItemView, PermItemUpdate, PermItemDelete, PermItemShare, PermItemExport, PermActivityView, PermSecurityRevokeSessions, }, OrgRoleManager: { PermOrgView, PermMemberView, PermCollectionView, PermCollectionUpdate, PermItemCreate, PermItemView, PermItemUpdate, PermItemDelete, PermItemShare, }, OrgRoleMember: { PermCollectionView, PermItemCreate, PermItemView, PermItemUpdate, PermItemDelete, }, OrgRoleBilling: { PermOrgView, PermBillingView, PermBillingUpdate, PermBillingDownloadInvoice, }, "read_only": { PermOrgView, PermCollectionView, PermItemView, }, }
PermissionMatrix defines permissions for each role
Functions ¶
func Can ¶
func Can(role OrganizationRole, permission string) bool
Can checks if a role has a specific permission
func DetectStoreFromSubscriptionID ¶
DetectStoreFromSubscriptionID extracts the store name from a RevenueCat subscription ID. Returns empty string for non-RevenueCat subscriptions. RevenueCat format: "rc_{STORE}_{transaction_id}" e.g. "rc_PLAY_STORE_abc123"
func GenerateSCIMToken ¶
GenerateSCIMToken creates a cryptographically secure random token string
func GetPermissions ¶
func GetPermissions(role OrganizationRole) []string
GetPermissions returns all permissions for a role
func IsWritePermission ¶
IsWritePermission checks if a permission is a write operation
func StoreDisplayName ¶
StoreDisplayName returns a user-friendly name for the store
Types ¶
type ActivityType ¶
type ActivityType string
ActivityType represents the type of user activity
const ( ActivityTypeSignIn ActivityType = "signin" ActivityTypeSignOut ActivityType = "signout" ActivityTypePasswordChange ActivityType = "password_change" ActivityTypeEmailVerified ActivityType = "email_verified" ActivityTypeAccountCreated ActivityType = "account_created" ActivityTypeVaultUnlock ActivityType = "vault_unlock" ActivityTypeVaultLock ActivityType = "vault_lock" ActivityTypeItemCreated ActivityType = "item_created" ActivityTypeItemUpdated ActivityType = "item_updated" ActivityTypeItemDeleted ActivityType = "item_deleted" ActivityTypeFailedSignIn ActivityType = "failed_signin" // Admin / Audit activities (admin-only visibility in UI) ActivityTypeAdminUserCreated ActivityType = "admin_user_created" ActivityTypeAdminUserUpdated ActivityType = "admin_user_updated" ActivityTypeAdminUserDeleted ActivityType = "admin_user_deleted" // Billing & Subscription Activities ActivityTypeCheckoutCreated ActivityType = "checkout_created" ActivityTypeSubscriptionCreated ActivityType = "subscription_created" ActivityTypeSubscriptionUpdated ActivityType = "subscription_updated" ActivityTypeSubscriptionCanceled ActivityType = "subscription_canceled" ActivityTypeSubscriptionReactivated ActivityType = "subscription_reactivated" ActivityTypeInvoicePaid ActivityType = "invoice_paid" ActivityTypeInvoicePaymentFailed ActivityType = "invoice_payment_failed" ActivityTypeOrganizationUpgraded ActivityType = "organization_upgraded" ActivityTypeOrganizationDowngraded ActivityType = "organization_downgraded" )
type AddTeamUserRequest ¶
type AddTeamUserRequest struct {
OrganizationUserID uint `json:"organization_user_id" validate:"required"`
IsManager bool `json:"is_manager"`
}
AddTeamUserRequest for adding users to team
type AuthResponse ¶
type AuthResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
Type string `json:"type"` // "Bearer"
AccessTokenExpiresAt int64 `json:"access_token_expires_at,omitempty"` // unix seconds
RefreshTokenExpiresAt int64 `json:"refresh_token_expires_at,omitempty"` // unix seconds
ProtectedUserKey string `json:"protected_user_key"`
KdfConfig *KdfConfig `json:"kdf_config"`
User *UserAuthDTO `json:"user"`
}
AuthResponse represents the authentication response
type BillingCycle ¶
type BillingCycle string
BillingCycle represents billing period
const ( BillingCycleMonthly BillingCycle = "monthly" BillingCycleYearly BillingCycle = "yearly" )
type BillingInfo ¶
type BillingInfo struct {
Organization *OrganizationDTO `json:"organization"`
Subscription *SubscriptionDTO `json:"subscription,omitempty"`
// Current usage
CurrentUsers int `json:"current_users"`
CurrentCollections int `json:"current_collections"`
CurrentItems int `json:"current_items"`
// Invoices
Invoices []*InvoiceDTO `json:"invoices,omitempty"`
}
BillingInfo contains billing and subscription information
type CancelSubscriptionRequest ¶
type CancelSubscriptionRequest struct {
Immediate bool `json:"immediate"` // Cancel immediately or at period end
}
CancelSubscriptionRequest for API requests
type ChangeMasterPasswordRequest ¶
type ChangeMasterPasswordRequest struct {
// NOTE: This endpoint is authenticated (JWT). The server will use the
// authenticated user (context) and ignore any client-provided email.
Email string `json:"email,omitempty"`
OldMasterPasswordHash string `json:"old_master_password_hash" validate:"required"`
NewMasterPasswordHash string `json:"new_master_password_hash" validate:"required"`
NewProtectedUserKey string `json:"new_protected_user_key" validate:"required"`
// Optional: rotate KDF settings and salt
NewKdfConfig *KdfConfig `json:"new_kdf_config,omitempty"`
NewKdfSalt string `json:"new_kdf_salt,omitempty"`
}
ChangeMasterPasswordRequest represents master password change request
type Collection ¶
type Collection struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty" gorm:"index"`
OrganizationID uint `json:"organization_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
// Collection details
Name string `json:"name" gorm:"type:varchar(255);not null"`
Description string `json:"description,omitempty" gorm:"type:text"`
// System defaults
IsDefault bool `json:"is_default" gorm:"not null;default:false"`
// Access control
IsPrivate bool `json:"is_private" gorm:"default:false"` // Only assigned users can access
// External ID for LDAP/AD sync
ExternalID *string `json:"external_id,omitempty" gorm:"type:varchar(255);index"`
// Stats (runtime calculated, not stored in DB)
ItemCount *int `json:"item_count,omitempty" gorm:"-"`
UserCount *int `json:"user_count,omitempty" gorm:"-"`
TeamCount *int `json:"team_count,omitempty" gorm:"-"`
// Associations
Organization *Organization `json:"organization,omitempty" gorm:"foreignKey:OrganizationID"`
UserAccess []CollectionUser `json:"user_access,omitempty" gorm:"foreignKey:CollectionID"`
TeamAccess []CollectionTeam `json:"team_access,omitempty" gorm:"foreignKey:CollectionID"`
Items []OrganizationItem `json:"items,omitempty" gorm:"foreignKey:CollectionID"`
}
Collection represents a shared folder at organization level
func (Collection) TableName ¶
func (Collection) TableName() string
TableName specifies the table name
type CollectionDTO ¶
type CollectionDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
OrganizationID uint `json:"organization_id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
IsPrivate bool `json:"is_private"`
ExternalID *string `json:"external_id,omitempty"`
IsDefault bool `json:"is_default"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Stats (optional)
ItemCount *int `json:"item_count,omitempty"`
UserCount *int `json:"user_count,omitempty"`
TeamCount *int `json:"team_count,omitempty"`
}
CollectionDTO for API responses
func ToCollectionDTO ¶
func ToCollectionDTO(c *Collection) *CollectionDTO
ToCollectionDTO converts Collection to DTO
type CollectionTeam ¶
type CollectionTeam struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CollectionID uint `json:"collection_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
TeamID uint `json:"team_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
// Permissions
CanRead bool `json:"can_read" gorm:"default:true"`
CanWrite bool `json:"can_write" gorm:"default:false"`
CanAdmin bool `json:"can_admin" gorm:"default:false"`
HidePasswords bool `json:"hide_passwords" gorm:"default:false"`
// Associations
Collection *Collection `json:"collection,omitempty" gorm:"foreignKey:CollectionID"`
Team *Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
}
CollectionTeam represents team permissions for a collection
func (CollectionTeam) TableName ¶
func (CollectionTeam) TableName() string
TableName specifies the table name
type CollectionTeamDTO ¶
type CollectionTeamDTO struct {
ID uint `json:"id"`
CollectionID uint `json:"collection_id"`
TeamID uint `json:"team_id"`
TeamName string `json:"team_name"`
CanRead bool `json:"can_read"`
CanWrite bool `json:"can_write"`
CanAdmin bool `json:"can_admin"`
HidePasswords bool `json:"hide_passwords"`
CreatedAt time.Time `json:"created_at"`
}
CollectionTeamDTO for API responses
func ToCollectionTeamDTO ¶
func ToCollectionTeamDTO(ct *CollectionTeam) *CollectionTeamDTO
ToCollectionTeamDTO converts CollectionTeam to DTO
type CollectionUser ¶
type CollectionUser struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CollectionID uint `json:"collection_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
OrganizationUserID uint `json:"organization_user_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
// Permissions
CanRead bool `json:"can_read" gorm:"default:true"`
CanWrite bool `json:"can_write" gorm:"default:false"`
CanAdmin bool `json:"can_admin" gorm:"default:false"`
HidePasswords bool `json:"hide_passwords" gorm:"default:false"` // Can view metadata but not passwords
// Associations
Collection *Collection `json:"collection,omitempty" gorm:"foreignKey:CollectionID"`
OrganizationUser *OrganizationUser `json:"organization_user,omitempty" gorm:"foreignKey:OrganizationUserID"`
}
CollectionUser represents user permissions for a collection
func (CollectionUser) TableName ¶
func (CollectionUser) TableName() string
TableName specifies the table name
type CollectionUserDTO ¶
type CollectionUserDTO struct {
ID uint `json:"id"`
CollectionID uint `json:"collection_id"`
OrganizationUserID uint `json:"organization_user_id"`
UserID uint `json:"user_id"`
UserEmail string `json:"user_email"`
UserName string `json:"user_name"`
CanRead bool `json:"can_read"`
CanWrite bool `json:"can_write"`
CanAdmin bool `json:"can_admin"`
HidePasswords bool `json:"hide_passwords"`
CreatedAt time.Time `json:"created_at"`
}
CollectionUserDTO for API responses
func ToCollectionUserDTO ¶
func ToCollectionUserDTO(cu *CollectionUser) *CollectionUserDTO
ToCollectionUserDTO converts CollectionUser to DTO
type CreateActivityRequest ¶
type CreateActivityRequest struct {
UserID uint
ActivityType ActivityType
IPAddress string
UserAgent string
Details string
}
CreateActivityRequest for logging activity
type CreateCollectionRequest ¶
type CreateCollectionRequest struct {
Name string `json:"name" validate:"required,max=255"`
Description string `json:"description,omitempty" validate:"max=1000"`
IsPrivate bool `json:"is_private"`
ExternalID *string `json:"external_id,omitempty"`
}
CreateCollectionRequest for API requests
type CreateExcludedDomainRequest ¶
type CreateExcludedDomainRequest struct {
Domain string `json:"domain" validate:"required"`
}
CreateExcludedDomainRequest for API requests
type CreateInvitationRequest ¶
type CreateInvitationRequest struct {
Email string `json:"email" validate:"required,email"`
RoleID uint `json:"role_id" validate:"required"`
Description *string `json:"description,omitempty"` // Optional personal note
// Organization invitation fields (optional)
OrganizationID *uint `json:"organization_id,omitempty"`
OrgRole *string `json:"org_role,omitempty"`
EncryptedOrgKey *string `json:"encrypted_org_key,omitempty"`
AccessAll *bool `json:"access_all,omitempty"`
}
CreateInvitationRequest represents invitation creation request
func (*CreateInvitationRequest) Validate ¶
func (r *CreateInvitationRequest) Validate() error
Validate validates the invitation request
type CreateItemShareRequest ¶
type CreateItemShareRequest struct {
}
CreateItemShareRequest for API requests
type CreateOrganizationFolderRequest ¶
type CreateOrganizationFolderRequest struct {
Name string `json:"name" validate:"required,max=255"`
}
type CreateOrganizationItemRequest ¶
type CreateOrganizationItemRequest struct {
CollectionID *uint `json:"collection_id,omitempty"`
ItemType ItemType `json:"item_type" validate:"required"`
Data string `json:"data" validate:"required"` // Encrypted with Org Key
Metadata ItemMetadata `json:"metadata" validate:"required"`
IsFavorite bool `json:"is_favorite"`
FolderID *uint `json:"folder_id,omitempty"`
Reprompt bool `json:"reprompt"`
AutoFill *bool `json:"auto_fill,omitempty"`
AutoLogin *bool `json:"auto_login,omitempty"`
}
CreateOrganizationItemRequest for API requests
type CreateOrganizationRequest ¶
type CreateOrganizationRequest struct {
Name string `json:"name" validate:"required,max=255"`
BillingEmail string `json:"billing_email" validate:"required,email"`
Plan string `json:"plan" validate:"omitempty,oneof=free business enterprise"`
EncryptedOrgKey string `json:"encrypted_org_key" validate:"required"` // Owner's copy of org key
}
CreateOrganizationRequest for API requests
type CreateSCIMTokenRequest ¶
type CreateSCIMTokenRequest struct {
Label string `json:"label" binding:"required,max=255"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
}
CreateSCIMTokenRequest for generating a new SCIM token
type CreateSSOConnectionRequest ¶
type CreateSSOConnectionRequest struct {
Protocol SSOProtocol `json:"protocol" binding:"required,oneof=saml oidc"`
Name string `json:"name" binding:"required,max=255"`
Domain string `json:"domain" binding:"required,max=255"`
SAMLConfig *SAMLConfig `json:"saml_config,omitempty"`
OIDCConfig *OIDCConfig `json:"oidc_config,omitempty"`
AutoProvision *bool `json:"auto_provision,omitempty"`
DefaultRole OrganizationRole `json:"default_role,omitempty"`
JITProvisioning *bool `json:"jit_provisioning,omitempty"`
}
CreateSSOConnectionRequest for creating a new SSO connection
type CreateSubscriptionRequest ¶
type CreateSubscriptionRequest struct {
PlanCode string `json:"plan_code" validate:"required"`
}
CreateSubscriptionRequest for API requests
type CreateTeamRequest ¶
type CreateTeamRequest struct {
Name string `json:"name" validate:"required,max=255"`
Description string `json:"description,omitempty" validate:"max=1000"`
AccessAllCollections bool `json:"access_all_collections"`
ExternalID *string `json:"external_id,omitempty"`
}
CreateTeamRequest for API requests
type CreateUserByAdminRequest ¶
type CreateUserByAdminRequest struct {
Name string `json:"name" validate:"required,max=100"`
Email string `json:"email" validate:"required,email"`
MasterPasswordHash string `json:"master_password_hash" validate:"required"` // HKDF(masterKey, info="auth")
ProtectedUserKey string `json:"protected_user_key" validate:"required"` // EncString: "2.iv|ct|mac"
EncryptedOrgKey string `json:"encrypted_org_key" validate:"required"` // Organization key encrypted with User Key
KdfConfig *KdfConfig `json:"kdf_config" validate:"required"`
KdfSalt string `json:"kdf_salt" validate:"required"` // hex-encoded random salt
RoleID *uint `json:"role_id,omitempty"`
}
CreateUserByAdminRequest represents admin-created user request (zero-knowledge)
func (*CreateUserByAdminRequest) Validate ¶
func (r *CreateUserByAdminRequest) Validate() error
Validate validates the create user request
type Credentials ¶
type Credentials struct {
Email string `json:"email" validate:"required,email"`
MasterPasswordHash string `json:"master_password_hash" validate:"required"`
// Optional device identifier to keep a stable session per app/device.
// Example: Vault can persist this in localStorage to avoid orphan sessions after tab close.
DeviceID string `json:"device_id,omitempty"`
// Optional app identifier (used with device_id). Expected: vault|extension|mobile|desktop
App string `json:"app,omitempty"`
// Optional login override:
// when true and free-plan device limit is hit, revoke all active sessions and continue login.
LogoutOtherDevices bool `json:"logout_other_devices,omitempty"`
}
Credentials represents user login credentials
type DeleteWithOrganizationsRequest ¶
type DeleteWithOrganizationsRequest struct {
OrganizationIDs []uint `json:"organization_ids" binding:"required"`
}
DeleteWithOrganizationsRequest represents a request to delete user with their organizations
type ErrValidation ¶
ErrValidation represents a validation error
func (ErrValidation) Error ¶
func (e ErrValidation) Error() string
type ExcludedDomain ¶
type ExcludedDomain struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;type:varchar(100);" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
UserID uint `json:"user_id" gorm:"not null;index"`
Domain string `json:"domain" gorm:"type:varchar(255);not null"`
}
ExcludedDomain represents a domain where Passwall is disabled for a specific user
func (ExcludedDomain) TableName ¶
func (ExcludedDomain) TableName() string
type ExcludedDomainDTO ¶
type ExcludedDomainDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
Domain string `json:"domain"`
CreatedAt time.Time `json:"created_at"`
}
ExcludedDomainDTO for API responses
func ToExcludedDomainDTO ¶
func ToExcludedDomainDTO(ed *ExcludedDomain) *ExcludedDomainDTO
func ToExcludedDomainDTOs ¶
func ToExcludedDomainDTOs(eds []*ExcludedDomain) []*ExcludedDomainDTO
type GrantCollectionAccessRequest ¶
type GrantCollectionAccessRequest struct {
CanRead bool `json:"can_read"`
CanWrite bool `json:"can_write"`
CanAdmin bool `json:"can_admin"`
HidePasswords bool `json:"hide_passwords"`
}
GrantCollectionAccessRequest for granting access to users/teams
type Invitation ¶
type Invitation struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// NOTE: Email is NOT unique because a user can have multiple invitations
// (e.g. multiple organization invites). Code remains unique.
Email string `json:"email" gorm:"type:varchar(255);index;not null"`
Code string `json:"code" gorm:"type:varchar(64);uniqueIndex;not null"`
RoleID uint `json:"role_id" gorm:"not null"`
CreatedBy uint `json:"created_by" gorm:"not null"` // Admin user ID
ExpiresAt time.Time `json:"expires_at" gorm:"not null"`
UsedAt *time.Time `json:"used_at,omitempty"`
// Organization invitation fields (optional)
OrganizationID *uint `json:"organization_id,omitempty" gorm:"index"`
OrgRole *string `json:"org_role,omitempty" gorm:"type:varchar(50)"`
EncryptedOrgKey *string `json:"encrypted_org_key,omitempty" gorm:"type:text"`
AccessAll bool `json:"access_all" gorm:"default:false"`
}
Invitation represents a user invitation
func (*Invitation) IsExpired ¶
func (i *Invitation) IsExpired() bool
IsExpired checks if invitation is expired
func (*Invitation) IsUsed ¶
func (i *Invitation) IsUsed() bool
IsUsed checks if invitation is already used
func (Invitation) TableName ¶
func (Invitation) TableName() string
TableName specifies the table name for Invitation
type InviteUserToOrgRequest ¶
type InviteUserToOrgRequest struct {
Email string `json:"email" binding:"required,email"`
Role OrganizationRole `json:"role" binding:"required,oneof=owner admin manager member"`
EncryptedOrgKey string `json:"encrypted_org_key" binding:"required"` // Org key wrapped for invitee
AccessAll bool `json:"access_all"`
Collections []uint `json:"collections,omitempty"` // Collection IDs to grant access
}
InviteUserToOrgRequest for inviting users
type InvoiceDTO ¶
type InvoiceDTO struct {
ID uint `json:"id,omitempty"` // Not used (no DB)
UUID string `json:"uuid,omitempty"` // Not used (no DB)
SubscriptionID uint `json:"subscription_id,omitempty"` // Not used (no DB)
Status InvoiceStatus `json:"status"`
AmountCents int `json:"amount_cents"`
AmountDisplay string `json:"amount_display"`
Currency string `json:"currency"`
IssuedAt time.Time `json:"issued_at"`
PaidAt *time.Time `json:"paid_at,omitempty"`
DueDate *time.Time `json:"due_date,omitempty"`
StripeInvoiceID *string `json:"stripe_invoice_id,omitempty"`
InvoicePDFURL *string `json:"invoice_pdf_url,omitempty"`
HostedInvoiceURL *string `json:"hosted_invoice_url,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"` // Not used (no DB)
}
InvoiceDTO represents invoice data fetched from Stripe (no DB table) Invoices are fetched directly from Stripe API, not stored in database
type InvoiceStatus ¶
type InvoiceStatus string
InvoiceStatus represents the status of an invoice (from Stripe)
const ( InvoiceStatusDraft InvoiceStatus = "draft" InvoiceStatusOpen InvoiceStatus = "open" InvoiceStatusPaid InvoiceStatus = "paid" InvoiceStatusVoid InvoiceStatus = "void" InvoiceStatusUncollectible InvoiceStatus = "uncollectible" )
func (InvoiceStatus) String ¶
func (i InvoiceStatus) String() string
String returns the string representation of InvoiceStatus
type Item ¶
type Item struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;uniqueIndex" json:"uuid"`
SupportID int64 `gorm:"uniqueIndex;not null" json:"support_id"` // Human-readable ID for support
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty" gorm:"index"`
// Sync
Revision int64 `json:"revision" gorm:"not null;default:0"`
SyncVersion int `json:"sync_version" gorm:"not null;default:1"`
ItemType ItemType `json:"item_type" gorm:"not null"`
Data string `json:"data" gorm:"type:text;not null"` // Encrypted JSON
// Optional: encrypted item key (for per-item key envelope encryption)
ItemKeyEnc *string `json:"item_key_enc,omitempty" gorm:"type:text"`
Metadata ItemMetadata `json:"metadata" gorm:"type:jsonb;not null"`
// User preferences
IsFavorite bool `json:"is_favorite" gorm:"default:false"`
FolderID *uint `json:"folder_id,omitempty"`
Reprompt bool `json:"reprompt" gorm:"default:false"`
// Browser extension features (Password items only)
AutoFill bool `json:"auto_fill" gorm:"default:true"` // Enable auto-fill
AutoLogin bool `json:"auto_login" gorm:"default:false"` // Enable auto-submit
ArchivedAt *time.Time `json:"archived_at,omitempty"`
}
Item - Universal vault item entity
func (*Item) FormatSupportID ¶
FormatSupportID formats support ID for display Example: 1855215206460051939 → "1855 2152 0646 0051 939"
type ItemMetadata ¶
type ItemMetadata struct {
Name string `json:"name"` // Required: display name
URIHint string `json:"uri_hint,omitempty"` // For passwords: domain for autofill
Brand string `json:"brand,omitempty"` // For cards: Visa, Mastercard, etc.
Category string `json:"category,omitempty"` // Custom category
Tags []string `json:"tags,omitempty"` // User tags for organization
IconHint string `json:"icon_hint,omitempty"` // For UI (favicon URL hint)
}
ItemMetadata - Searchable metadata (NOT encrypted)
func (*ItemMetadata) Scan ¶
func (m *ItemMetadata) Scan(value interface{}) error
Scan implements sql.Scanner for ItemMetadata (JSONB)
func (ItemMetadata) Value ¶
func (m ItemMetadata) Value() (interface{}, error)
Value implements driver.Valuer for ItemMetadata (JSONB)
type ItemShare ¶
type ItemShare struct {
// Item reference (organization item)
// Share target (either user or team)
// Permissions
EncryptedKey string `json:"-" gorm:"type:text;not null"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
// Associations
}
ItemShare represents a direct share of an organization item to another user/team
type ItemType ¶
type ItemType int16
ItemType - Enum for vault item types
const ( ItemTypePassword ItemType = 1 ItemTypeSecureNote ItemType = 2 ItemTypeCard ItemType = 3 ItemTypeBankAccount ItemType = 4 ItemTypeEmail ItemType = 5 ItemTypeServer ItemType = 6 ItemTypeIdentity ItemType = 7 ItemTypeSSHKey ItemType = 8 ItemTypeAddress ItemType = 9 // Address/Location ItemTypeCustom ItemType = 99 // User-defined )
type KdfConfig ¶
type KdfConfig struct {
Type KdfType `json:"kdf_type"`
Iterations int `json:"kdf_iterations"`
Memory *int `json:"kdf_memory,omitempty"` // For Argon2id (MB)
Parallelism *int `json:"kdf_parallelism,omitempty"` // For Argon2id (threads)
Salt string `json:"kdf_salt,omitempty"` // hex-encoded random salt
}
KdfConfig represents KDF (Key Derivation Function) configuration
func NewArgon2KdfConfig ¶
func NewArgon2KdfConfig() *KdfConfig
NewArgon2KdfConfig returns default Argon2id configuration
func NewDefaultKdfConfig ¶
func NewDefaultKdfConfig() *KdfConfig
NewDefaultKdfConfig returns default PBKDF2 configuration
func (*KdfConfig) ValidateForPrelogin ¶
ValidateForPrelogin validates KDF config against downgrade attacks Server should never allow iterations below minimum
type MoveItemToCollectionRequest ¶
type MoveItemToCollectionRequest struct {
CollectionID *uint `json:"collection_id"` // NULL to move to org-wide
}
MoveItemToCollectionRequest for moving items between collections
type OIDCConfig ¶
type OIDCConfig struct {
Issuer string `json:"issuer"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
AuthURL string `json:"auth_url,omitempty"`
TokenURL string `json:"token_url,omitempty"`
UserInfoURL string `json:"user_info_url,omitempty"`
JwksURI string `json:"jwks_uri,omitempty"`
Scopes []string `json:"scopes,omitempty"`
UseDiscovery bool `json:"use_discovery"`
PKCEEnabled bool `json:"pkce_enabled"`
EmailClaim string `json:"email_claim,omitempty"`
NameClaim string `json:"name_claim,omitempty"`
GroupsClaim string `json:"groups_claim,omitempty"`
}
OIDCConfig holds OIDC-specific IdP configuration
func (*OIDCConfig) Scan ¶
func (c *OIDCConfig) Scan(value interface{}) error
Scan implements sql.Scanner
type OIDCConfigDTO ¶
type OIDCConfigDTO struct {
Issuer string `json:"issuer"`
ClientID string `json:"client_id"`
AuthURL string `json:"auth_url,omitempty"`
TokenURL string `json:"token_url,omitempty"`
Scopes []string `json:"scopes,omitempty"`
UseDiscovery bool `json:"use_discovery"`
PKCEEnabled bool `json:"pkce_enabled"`
}
OIDCConfigDTO strips the client secret
type Organization ¶
type Organization struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Organization info
Name string `json:"name" gorm:"type:varchar(255);not null"`
BillingEmail string `json:"billing_email" gorm:"type:varchar(255);not null"`
// System defaults
// IsDefault is a legacy concept kept for backward compatibility.
// Do not use it for default-org resolution; use users.default_organization_id instead.
IsDefault bool `json:"is_default" gorm:"not null;default:false"`
// Personal Vault model (new)
IsPersonal bool `json:"is_personal" gorm:"not null;default:false"`
PersonalOwnerUserID *uint `json:"personal_owner_user_id,omitempty" gorm:"index"`
// Creator snapshot (denormalized).
// Users can be hard-deleted, so we keep immutable creator identity fields here.
CreatedByUserID *uint `json:"created_by_user_id,omitempty" gorm:"index"`
CreatedByUserEmail *string `json:"created_by_user_email,omitempty" gorm:"type:varchar(255)"`
CreatedByUserName *string `json:"created_by_user_name,omitempty" gorm:"type:varchar(255)"`
// Encryption
// Organization symmetric key (AES-256) encrypted with owner's User Key
EncryptedOrgKey string `json:"-" gorm:"type:text;not null"`
// RSA key pair for organization (optional, for advanced key management)
OrgPublicKey *string `json:"-" gorm:"type:text"` // RSA-2048 public key (PEM)
OrgPrivateKeyEnc *string `json:"-" gorm:"type:text"` // RSA private key encrypted with recovery key
KeyRotationCounter int `json:"key_rotation_counter" gorm:"default:0"`
// Status
Status OrganizationStatus `json:"status" gorm:"type:varchar(20);not null;default:'active'"`
IsActive bool `json:"is_active" gorm:"default:true"`
SuspendedAt *time.Time `json:"suspended_at,omitempty"`
DeletedAt *time.Time `json:"deleted_at,omitempty" gorm:"index"`
ScheduledDeletionAt *time.Time `json:"scheduled_deletion_at,omitempty"`
// Billing & Stripe Integration
StripeCustomerID *string `json:"stripe_customer_id,omitempty" gorm:"type:varchar(255);index"`
// Stats (runtime calculated, not stored in DB)
MemberCount *int `json:"member_count,omitempty" gorm:"-"`
TeamCount *int `json:"team_count,omitempty" gorm:"-"`
CollectionCount *int `json:"collection_count,omitempty" gorm:"-"`
ItemCount *int `json:"item_count,omitempty" gorm:"-"`
// Associations (not loaded by default)
Members []OrganizationUser `json:"members,omitempty" gorm:"foreignKey:OrganizationID"`
Teams []Team `json:"teams,omitempty" gorm:"foreignKey:OrganizationID"`
Collections []Collection `json:"collections,omitempty" gorm:"foreignKey:OrganizationID"`
}
Organization represents a team/company organization
func (Organization) TableName ¶
func (Organization) TableName() string
TableName specifies the table name
type OrganizationDTO ¶
type OrganizationDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
Name string `json:"name"`
BillingEmail string `json:"billing_email"`
IsDefault bool `json:"is_default"`
CreatedByUserID *uint `json:"created_by_user_id,omitempty"`
CreatedByUserEmail *string `json:"created_by_user_email,omitempty"`
CreatedByUserName *string `json:"created_by_user_name,omitempty"`
Plan OrganizationPlan `json:"plan"`
MaxUsers int `json:"max_users"`
MaxCollections int `json:"max_collections"`
Status OrganizationStatus `json:"status"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Subscription (optional)
Subscription *SubscriptionDTO `json:"subscription,omitempty"`
// Stats (optional)
MemberCount *int `json:"member_count,omitempty"`
TeamCount *int `json:"team_count,omitempty"`
CollectionCount *int `json:"collection_count,omitempty"`
ItemCount *int `json:"item_count,omitempty"`
// Encrypted org key (safe to send - user's own copy, encrypted with their User Key)
EncryptedOrgKey string `json:"encrypted_org_key,omitempty"`
}
OrganizationDTO for API responses
func ToOrganizationDTO ¶
func ToOrganizationDTO(org *Organization) *OrganizationDTO
ToOrganizationDTO converts Organization to DTO
func ToOrganizationDTOWithSubscription ¶
func ToOrganizationDTOWithSubscription(org *Organization, sub *Subscription) *OrganizationDTO
ToOrganizationDTOWithSubscription converts Organization to DTO and derives plan/limits from the provided subscription (source of truth).
type OrganizationFolder ¶
type OrganizationFolder struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;type:varchar(100);" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
OrganizationID uint `json:"organization_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
CreatedByUserID uint `json:"created_by_user_id" gorm:"not null;index"`
Name string `json:"name" gorm:"type:varchar(255);not null"`
}
OrganizationFolder represents a folder for organization vault items
func (OrganizationFolder) TableName ¶
func (OrganizationFolder) TableName() string
type OrganizationFolderDTO ¶
type OrganizationFolderDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
}
func ToOrganizationFolderDTO ¶
func ToOrganizationFolderDTO(f *OrganizationFolder) *OrganizationFolderDTO
func ToOrganizationFolderDTOs ¶
func ToOrganizationFolderDTOs(folders []*OrganizationFolder) []*OrganizationFolderDTO
type OrganizationItem ¶
type OrganizationItem struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null" json:"uuid"`
SupportID int64 `gorm:"not null" json:"support_id"` // Human-readable ID for support
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty" gorm:"index"`
// Organization and collection
OrganizationID uint `json:"organization_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
CollectionID *uint `json:"collection_id,omitempty" gorm:"index;constraint:OnDelete:SET NULL"` // NULL means org-wide item
// Sync
Revision int64 `json:"revision" gorm:"not null;default:0"`
SyncVersion int `json:"sync_version" gorm:"not null;default:1"`
// Item type and data
ItemType ItemType `json:"item_type" gorm:"not null"`
Data string `json:"data" gorm:"type:text;not null"` // Encrypted with Org Key
Metadata ItemMetadata `json:"metadata" gorm:"type:jsonb;not null"`
// User preferences
IsFavorite bool `json:"is_favorite" gorm:"default:false"`
FolderID *uint `json:"folder_id,omitempty"` // Organization folder (future feature)
Reprompt bool `json:"reprompt" gorm:"default:false"`
// Browser extension features (Password items only)
AutoFill bool `json:"auto_fill" gorm:"default:true"`
AutoLogin bool `json:"auto_login" gorm:"default:false"`
ArchivedAt *time.Time `json:"archived_at,omitempty"`
// Creator info
CreatedByUserID uint `json:"created_by_user_id" gorm:"not null;index"`
// Associations
Organization *Organization `json:"organization,omitempty" gorm:"foreignKey:OrganizationID"`
Collection *Collection `json:"collection,omitempty" gorm:"foreignKey:CollectionID"`
CreatedBy *User `json:"created_by,omitempty" gorm:"foreignKey:CreatedByUserID"`
}
OrganizationItem represents a vault item shared within an organization Unlike personal items (in user schemas), org items are in the public schema and encrypted with the organization key instead of user key
func (*OrganizationItem) FormatSupportID ¶
func (oi *OrganizationItem) FormatSupportID() string
FormatSupportID formats support ID for display
func (*OrganizationItem) IsArchived ¶
func (oi *OrganizationItem) IsArchived() bool
IsArchived checks if item is archived
func (*OrganizationItem) IsDeleted ¶
func (oi *OrganizationItem) IsDeleted() bool
IsDeleted checks if item is soft deleted
func (OrganizationItem) TableName ¶
func (OrganizationItem) TableName() string
TableName specifies the table name
type OrganizationItemDTO ¶
type OrganizationItemDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
SupportID int64 `json:"support_id"`
SupportIDFormatted string `json:"support_id_formatted"`
OrganizationID uint `json:"organization_id"`
CollectionID *uint `json:"collection_id,omitempty"`
ItemType ItemType `json:"item_type"`
Data string `json:"data"` // Still encrypted
Metadata ItemMetadata `json:"metadata"`
IsFavorite bool `json:"is_favorite"`
FolderID *uint `json:"folder_id,omitempty"`
Reprompt bool `json:"reprompt"`
AutoFill bool `json:"auto_fill"`
AutoLogin bool `json:"auto_login"`
Revision int64 `json:"revision"`
SyncVersion int `json:"sync_version"`
CreatedByUserID uint `json:"created_by_user_id"`
CreatedByUserEmail string `json:"created_by_user_email,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ArchivedAt *time.Time `json:"archived_at,omitempty"`
}
OrganizationItemDTO for API responses
func ToOrganizationItemDTO ¶
func ToOrganizationItemDTO(oi *OrganizationItem) *OrganizationItemDTO
ToOrganizationItemDTO converts OrganizationItem to DTO
type OrganizationPlan ¶
type OrganizationPlan string
OrganizationPlan represents the subscription plan "family" at the product level.
NOTE: This is a presentation/UX concept. Source-of-truth entitlements MUST come from subscriptions + plans.
const ( PlanFree OrganizationPlan = "free" PlanPremium OrganizationPlan = "premium" // Premium plan does NOT use organizations PlanFamily OrganizationPlan = "family" PlanTeam OrganizationPlan = "team" PlanBusiness OrganizationPlan = "business" PlanEnterprise OrganizationPlan = "enterprise" )
type OrganizationRole ¶
type OrganizationRole string
OrganizationRole represents a user's role in an organization
const ( OrgRoleOwner OrganizationRole = "owner" // Full control, billing, delete org OrgRoleAdmin OrganizationRole = "admin" // Manage users, collections, all items OrgRoleManager OrganizationRole = "manager" // Manage specific teams/collections OrgRoleMember OrganizationRole = "member" // Access assigned collections only OrgRoleBilling OrganizationRole = "billing" // Billing management only )
type OrganizationStatus ¶
type OrganizationStatus string
OrganizationStatus represents the status of an organization
const ( OrgStatusActive OrganizationStatus = "active" OrgStatusSuspended OrganizationStatus = "suspended" OrgStatusScheduledForDeletion OrganizationStatus = "scheduled_for_deletion" OrgStatusDeleted OrganizationStatus = "deleted" )
type OrganizationUser ¶
type OrganizationUser struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
OrganizationID uint `json:"organization_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
UserID uint `json:"user_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
// Role in organization
Role OrganizationRole `json:"role" gorm:"type:varchar(20);not null;default:'member'"`
// Organization key wrapped for this user
// Encrypted with user's RSA public key (or User Key if RSA not available)
EncryptedOrgKey string `json:"-" gorm:"type:text;not null"`
// Permissions
AccessAll bool `json:"access_all" gorm:"default:false"` // Access all collections
Permissions string `json:"permissions,omitempty" gorm:"type:text"`
// Status
Status OrganizationUserStatus `json:"status" gorm:"type:varchar(20);default:'invited'"`
InvitedAt *time.Time `json:"invited_at,omitempty"`
AcceptedAt *time.Time `json:"accepted_at,omitempty"`
// External ID for LDAP/AD sync
ExternalID *string `json:"external_id,omitempty" gorm:"type:varchar(255);index"`
// Associations
Organization *Organization `json:"organization,omitempty" gorm:"foreignKey:OrganizationID"`
User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}
OrganizationUser represents a user's membership in an organization
func (*OrganizationUser) CanManageCollections ¶
func (ou *OrganizationUser) CanManageCollections() bool
CanManageCollections checks if the user can manage collections
func (*OrganizationUser) CanManageUsers ¶
func (ou *OrganizationUser) CanManageUsers() bool
CanManageUsers checks if the user can manage other users
func (*OrganizationUser) IsAdmin ¶
func (ou *OrganizationUser) IsAdmin() bool
IsAdmin checks if the user is an admin or owner
func (*OrganizationUser) IsOwner ¶
func (ou *OrganizationUser) IsOwner() bool
IsOwner checks if the user is an owner
func (OrganizationUser) TableName ¶
func (OrganizationUser) TableName() string
TableName specifies the table name
type OrganizationUserDTO ¶
type OrganizationUserDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
OrganizationID uint `json:"organization_id"`
UserID uint `json:"user_id"`
UserEmail string `json:"user_email"`
UserName string `json:"user_name"`
Role OrganizationRole `json:"role"`
AccessAll bool `json:"access_all"`
Status OrganizationUserStatus `json:"status"`
InvitedAt *time.Time `json:"invited_at,omitempty"`
AcceptedAt *time.Time `json:"accepted_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
OrganizationUserDTO for API responses
func ToOrganizationUserDTO ¶
func ToOrganizationUserDTO(ou *OrganizationUser) *OrganizationUserDTO
ToOrganizationUserDTO converts OrganizationUser to DTO
type OrganizationUserStatus ¶
type OrganizationUserStatus string
OrganizationUserStatus represents the status of a user's membership
const ( OrgUserStatusInvited OrganizationUserStatus = "invited" OrgUserStatusAccepted OrganizationUserStatus = "accepted" OrgUserStatusConfirmed OrganizationUserStatus = "confirmed" OrgUserStatusSuspended OrganizationUserStatus = "suspended" )
type OwnershipCheckResult ¶
type OwnershipCheckResult struct {
IsSoleOwner bool `json:"is_sole_owner"`
Organizations []SoleOwnerOrganization `json:"organizations"`
}
OwnershipCheckResult represents organizations where user is sole owner
type PaymentProvider ¶
type PaymentProvider string
PaymentProvider represents the payment provider for a subscription
const ( PaymentProviderStripe PaymentProvider = "stripe" PaymentProviderRevenueCat PaymentProvider = "revenuecat" PaymentProviderManual PaymentProvider = "manual" PaymentProviderNone PaymentProvider = "none" )
func DetectPaymentProvider ¶
func DetectPaymentProvider(subscriptionID *string) PaymentProvider
DetectPaymentProvider determines the payment provider from a subscription ID. RevenueCat subscriptions use the format "rc_{store}_{transaction_id}". Empty or nil subscription IDs indicate a manual/admin grant.
func (PaymentProvider) IsManagedExternally ¶
func (p PaymentProvider) IsManagedExternally() bool
IsManagedExternally returns true if the subscription is managed by an external store (App Store / Play Store via RevenueCat). These subscriptions can only be canceled/modified from the respective store — not from our API.
func (PaymentProvider) IsRevenueCat ¶
func (p PaymentProvider) IsRevenueCat() bool
IsRevenueCat returns true if the provider is RevenueCat (mobile in-app purchase)
func (PaymentProvider) IsStripe ¶
func (p PaymentProvider) IsStripe() bool
IsStripe returns true if the provider is Stripe (web payment)
func (PaymentProvider) String ¶
func (p PaymentProvider) String() string
type Permission ¶
type Permission struct {
ID uint `gorm:"primary_key" json:"id"`
Name string `json:"name" gorm:"type:varchar(100);uniqueIndex;not null"`
DisplayName string `json:"display_name" gorm:"type:varchar(100);not null"`
Description string `json:"description" gorm:"type:text"`
Resource string `json:"resource" gorm:"type:varchar(50);not null"` // e.g., "users", "logins"
Action string `json:"action" gorm:"type:varchar(50);not null"` // e.g., "read", "create", "update", "delete"
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Permission represents a specific action/access right
func (Permission) TableName ¶
func (Permission) TableName() string
TableName specifies the table name for Permission
type Plan ¶
type Plan struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Code string `json:"code" gorm:"type:varchar(50);uniqueIndex;not null"`
Name string `json:"name" gorm:"type:varchar(100);not null"`
BillingCycle BillingCycle `json:"billing_cycle" gorm:"type:varchar(20);not null"`
PriceCents int `json:"price_cents" gorm:"not null"`
Currency string `json:"currency" gorm:"type:varchar(3);not null;default:'USD'"`
TrialDays int `json:"trial_days" gorm:"not null;default:0"`
// Limits (null = unlimited)
MaxUsers *int `json:"max_users,omitempty"`
MaxCollections *int `json:"max_collections,omitempty"`
MaxItems *int `json:"max_items,omitempty"`
// Feature flags
Features PlanFeatures `json:"features" gorm:"type:jsonb;not null"`
// Status
IsActive bool `json:"is_active" gorm:"default:true"`
// Stripe integration
StripeProductID *string `json:"stripe_product_id,omitempty" gorm:"type:varchar(255)"`
StripePriceID *string `json:"stripe_price_id,omitempty" gorm:"type:varchar(255)"`
}
Plan represents a subscription plan
func (*Plan) GetPriceDisplay ¶
GetPriceDisplay returns formatted price for display (e.g., "$5.99")
func (*Plan) IsUnlimitedCollections ¶
IsUnlimitedCollections checks if plan allows unlimited collections
func (*Plan) IsUnlimitedItems ¶
IsUnlimitedItems checks if plan allows unlimited items
func (*Plan) IsUnlimitedUsers ¶
IsUnlimitedUsers checks if plan allows unlimited users
type PlanChangePreview ¶
type PlanChangePreview struct {
CurrentPlan string `json:"current_plan"`
NewPlan string `json:"new_plan"`
ProratedAmount int64 `json:"prorated_amount"` // cents
Currency string `json:"currency"`
NextBillingDate string `json:"next_billing_date"`
NextBillingAmount int64 `json:"next_billing_amount"`
ImmediateCharge bool `json:"immediate_charge"` // true if user will be charged now
}
PlanChangePreview shows the cost impact of switching to a different plan.
type PlanChangeResult ¶
PlanChangeResult represents the result of an inline plan change.
type PlanDTO ¶
type PlanDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
Code string `json:"code"`
Name string `json:"name"`
BillingCycle BillingCycle `json:"billing_cycle"`
PriceCents int `json:"price_cents"`
PriceDisplay string `json:"price_display"`
Currency string `json:"currency"`
TrialDays int `json:"trial_days"`
MaxUsers *int `json:"max_users,omitempty"`
MaxCollections *int `json:"max_collections,omitempty"`
MaxItems *int `json:"max_items,omitempty"`
Features PlanFeatures `json:"features"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
PlanDTO for API responses
type PlanFeatures ¶
type PlanFeatures struct {
Items *int `json:"items"` // Max items (null = unlimited)
Sharing bool `json:"sharing"` // Item sharing enabled
Teams bool `json:"teams"` // Team management enabled
Audit bool `json:"audit"` // Audit logs enabled
SSO bool `json:"sso"` // Single Sign-On enabled
APIAccess bool `json:"api_access"` // API access enabled
PrioritySupport bool `json:"priority_support"` // Priority support enabled
}
PlanFeatures represents feature flags for a plan
func (*PlanFeatures) Scan ¶
func (f *PlanFeatures) Scan(value interface{}) error
Scan implements sql.Scanner for PlanFeatures (JSONB)
type PreLoginRequest ¶
type PreLoginRequest struct {
Email string `json:"email" validate:"required,email"`
}
PreLoginRequest represents prelogin request
type PreLoginResponse ¶
type PreLoginResponse struct {
KdfType KdfType `json:"kdf_type"`
KdfIterations int `json:"kdf_iterations"`
KdfMemory *int `json:"kdf_memory,omitempty"`
KdfParallelism *int `json:"kdf_parallelism,omitempty"`
KdfSalt string `json:"kdf_salt"` // hex-encoded salt for master key derivation
}
PreLoginResponse represents prelogin response (KDF config for client)
type Preference ¶
type Preference struct {
ID uint `json:"id" gorm:"primaryKey"`
OwnerType string `` /* 153-byte string literal not displayed */
OwnerID uint `` /* 134-byte string literal not displayed */
Section string `` /* 150-byte string literal not displayed */
Key string `json:"key" gorm:"type:varchar(64);not null;uniqueIndex:uq_preferences_owner_section_key,priority:4"`
// Value is stored as text; interpretation depends on Type.
// Type can be: string | number | boolean | json
Value string `json:"value" gorm:"type:text;not null;default:''"`
Type string `json:"type" gorm:"type:varchar(16);not null;default:'string'"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Preference stores a single preference value for a scoped owner (user/org). One row represents one setting: (owner_type, owner_id, section, key) → (type, value).
func (Preference) TableName ¶
func (Preference) TableName() string
type PreferenceDTO ¶
type PreferenceDTO struct {
Section string `json:"section"`
Key string `json:"key"`
Type string `json:"type"`
Value string `json:"value"`
}
func ToPreferenceDTO ¶
func ToPreferenceDTO(p *Preference) *PreferenceDTO
type ResendVerificationRequest ¶
type ResendVerificationRequest struct {
Email string `json:"email" binding:"required,email"`
}
ResendVerificationRequest represents resend verification email request
type Role ¶
type Role struct {
ID uint `gorm:"primary_key" json:"id"`
Name string `json:"name" gorm:"type:varchar(50);uniqueIndex;not null"`
DisplayName string `json:"display_name" gorm:"type:varchar(100);not null"`
Description string `json:"description" gorm:"type:text"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Permissions []Permission `gorm:"many2many:role_permissions;" json:"permissions,omitempty"`
}
Role represents a user role in the system
type SAMLConfig ¶
type SAMLConfig struct {
EntityID string `json:"entity_id"`
SSOURL string `json:"sso_url"`
SLOURL string `json:"slo_url,omitempty"`
Certificate string `json:"certificate"`
SignAuthnRequests bool `json:"sign_authn_requests"`
WantAssertionSigned bool `json:"want_assertion_signed"`
NameIDFormat string `json:"name_id_format,omitempty"`
}
SAMLConfig holds SAML-specific IdP configuration
func (*SAMLConfig) Scan ¶
func (c *SAMLConfig) Scan(value interface{}) error
Scan implements sql.Scanner
type SAMLConfigDTO ¶
type SAMLConfigDTO struct {
EntityID string `json:"entity_id"`
SSOURL string `json:"sso_url"`
SLOURL string `json:"slo_url,omitempty"`
HasCertificate bool `json:"has_certificate"`
SignAuthnRequests bool `json:"sign_authn_requests"`
WantAssertionSigned bool `json:"want_assertion_signed"`
NameIDFormat string `json:"name_id_format,omitempty"`
}
SAMLConfigDTO strips the certificate body for list views
type SCIMEmail ¶
type SCIMEmail struct {
Value string `json:"value"`
Type string `json:"type,omitempty"`
Primary bool `json:"primary,omitempty"`
}
SCIMEmail represents an email in the SCIM schema
type SCIMError ¶
type SCIMError struct {
Schemas []string `json:"schemas"`
Detail string `json:"detail"`
Status string `json:"status"`
ScimType string `json:"scimType,omitempty"`
}
SCIMError represents a SCIM 2.0 error response
type SCIMGroup ¶
type SCIMGroup struct {
Schemas []string `json:"schemas"`
ID string `json:"id"`
ExternalID string `json:"externalId,omitempty"`
DisplayName string `json:"displayName"`
Members []SCIMMemberRef `json:"members,omitempty"`
Meta *SCIMMeta `json:"meta,omitempty"`
}
SCIMGroup represents a SCIM 2.0 Group resource
type SCIMGroupRef ¶
type SCIMGroupRef struct {
Value string `json:"value"`
Display string `json:"display,omitempty"`
Ref string `json:"$ref,omitempty"`
}
SCIMGroupRef is a reference to a group the user belongs to
type SCIMListResponse ¶
type SCIMListResponse struct {
Schemas []string `json:"schemas"`
TotalResults int `json:"totalResults"`
StartIndex int `json:"startIndex"`
ItemsPerPage int `json:"itemsPerPage"`
Resources interface{} `json:"Resources"`
}
SCIMListResponse wraps a SCIM list with pagination envelope
type SCIMMemberRef ¶
type SCIMMemberRef struct {
Value string `json:"value"`
Display string `json:"display,omitempty"`
Ref string `json:"$ref,omitempty"`
}
SCIMMemberRef is a reference to a group member
type SCIMMeta ¶
type SCIMMeta struct {
ResourceType string `json:"resourceType"`
Created string `json:"created,omitempty"`
LastModified string `json:"lastModified,omitempty"`
Location string `json:"location,omitempty"`
}
SCIMMeta holds resource metadata per SCIM spec
type SCIMName ¶
type SCIMName struct {
Formatted string `json:"formatted,omitempty"`
FamilyName string `json:"familyName,omitempty"`
GivenName string `json:"givenName,omitempty"`
}
SCIMName represents the name component of a SCIM user
type SCIMPatchOp ¶
type SCIMPatchOp struct {
Schemas []string `json:"schemas"`
Operations []SCIMPatchOpItem `json:"Operations"`
}
SCIMPatchOp represents a SCIM PATCH operation (RFC 7644 §3.5.2)
type SCIMPatchOpItem ¶
type SCIMPatchOpItem struct {
Op string `json:"op"`
Path string `json:"path,omitempty"`
Value interface{} `json:"value,omitempty"`
}
SCIMPatchOpItem is a single patch operation
type SCIMToken ¶
type SCIMToken struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null;uniqueIndex" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
OrganizationID uint `json:"organization_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
Label string `json:"label" gorm:"type:varchar(255);not null"`
// Token value (hashed for storage, plain text returned only on creation)
TokenHash string `json:"-" gorm:"type:varchar(512);not null;uniqueIndex"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
IsActive bool `json:"is_active" gorm:"not null;default:true"`
// Associations
Organization *Organization `json:"organization,omitempty" gorm:"foreignKey:OrganizationID"`
}
SCIMToken represents an API bearer token used by IdP directory sync (SCIM 2.0)
type SCIMTokenCreatedDTO ¶
type SCIMTokenCreatedDTO struct {
SCIMTokenDTO
Token string `json:"token"`
}
SCIMTokenCreatedDTO includes the plain-text token (returned only on creation)
type SCIMTokenDTO ¶
type SCIMTokenDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
OrganizationID uint `json:"organization_id"`
Label string `json:"label"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
}
SCIMTokenDTO for API responses
func ToSCIMTokenDTO ¶
func ToSCIMTokenDTO(t *SCIMToken) *SCIMTokenDTO
ToSCIMTokenDTO converts SCIMToken to DTO
type SCIMUser ¶
type SCIMUser struct {
Schemas []string `json:"schemas"`
ID string `json:"id"`
ExternalID string `json:"externalId,omitempty"`
UserName string `json:"userName"`
Name *SCIMName `json:"name,omitempty"`
Emails []SCIMEmail `json:"emails,omitempty"`
Active bool `json:"active"`
Groups []SCIMGroupRef `json:"groups,omitempty"`
Meta *SCIMMeta `json:"meta,omitempty"`
}
SCIMUser represents a SCIM 2.0 User resource
type SSOCallbackResult ¶
type SSOCallbackResult struct {
User *User `json:"user"`
Organization *Organization `json:"organization"`
IsNewUser bool `json:"is_new_user"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
}
SSOCallbackResult returned after successful SSO authentication
type SSOConnection ¶
type SSOConnection struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null;uniqueIndex" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
OrganizationID uint `json:"organization_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
Protocol SSOProtocol `json:"protocol" gorm:"type:varchar(10);not null"`
// Display
Name string `json:"name" gorm:"type:varchar(255);not null"`
Domain string `json:"domain" gorm:"type:varchar(255);not null;uniqueIndex"`
// Protocol-specific configuration (stored as JSONB)
SAMLConfig *SAMLConfig `json:"saml_config,omitempty" gorm:"type:jsonb"`
OIDCConfig *OIDCConfig `json:"oidc_config,omitempty" gorm:"type:jsonb"`
// SP (Passwall) metadata — generated at creation, read-only for admin
SPEntityID string `json:"sp_entity_id" gorm:"type:varchar(512)"`
SPAcsURL string `json:"sp_acs_url" gorm:"type:varchar(512)"`
SPMetadata string `json:"-" gorm:"type:text"`
// Behaviour
AutoProvision bool `json:"auto_provision" gorm:"default:true"`
DefaultRole OrganizationRole `json:"default_role" gorm:"type:varchar(20);default:'member'"`
JITProvisioning bool `json:"jit_provisioning" gorm:"default:true"`
Status SSOConnectionStatus `json:"status" gorm:"type:varchar(20);not null;default:'draft'"`
// Associations
Organization *Organization `json:"organization,omitempty" gorm:"foreignKey:OrganizationID"`
}
SSOConnection represents an SSO provider configuration for an organization
func (*SSOConnection) IsActive ¶
func (s *SSOConnection) IsActive() bool
IsActive returns true if connection is active
func (*SSOConnection) IsOIDC ¶
func (s *SSOConnection) IsOIDC() bool
IsOIDC returns true if protocol is OIDC
func (*SSOConnection) IsSAML ¶
func (s *SSOConnection) IsSAML() bool
IsSAML returns true if protocol is SAML
func (SSOConnection) TableName ¶
func (SSOConnection) TableName() string
TableName specifies the table name
type SSOConnectionDTO ¶
type SSOConnectionDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
OrganizationID uint `json:"organization_id"`
Protocol SSOProtocol `json:"protocol"`
Name string `json:"name"`
Domain string `json:"domain"`
SPEntityID string `json:"sp_entity_id"`
SPAcsURL string `json:"sp_acs_url"`
AutoProvision bool `json:"auto_provision"`
DefaultRole OrganizationRole `json:"default_role"`
JITProvisioning bool `json:"jit_provisioning"`
Status SSOConnectionStatus `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Protocol-specific (admin-visible only)
SAMLConfig *SAMLConfigDTO `json:"saml_config,omitempty"`
OIDCConfig *OIDCConfigDTO `json:"oidc_config,omitempty"`
}
SSOConnectionDTO for API responses (sensitive fields stripped)
func ToSSOConnectionDTO ¶
func ToSSOConnectionDTO(conn *SSOConnection) *SSOConnectionDTO
ToSSOConnectionDTO converts SSOConnection to DTO
type SSOConnectionStatus ¶
type SSOConnectionStatus string
SSOConnectionStatus represents the status of an SSO connection
const ( SSOStatusDraft SSOConnectionStatus = "draft" SSOStatusActive SSOConnectionStatus = "active" SSOStatusInactive SSOConnectionStatus = "inactive" )
type SSOInitiateRequest ¶
type SSOInitiateRequest struct {
Domain string `json:"domain" binding:"required"`
RedirectURL string `json:"redirect_url,omitempty"`
}
SSOInitiateRequest for starting SSO login
type SSOProtocol ¶
type SSOProtocol string
SSOProtocol represents the SSO protocol type
const ( SSOProtocolSAML SSOProtocol = "saml" SSOProtocolOIDC SSOProtocol = "oidc" )
type SSOState ¶
type SSOState struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
State string `json:"state" gorm:"type:varchar(512);not null;uniqueIndex"`
ConnectionID uint `json:"connection_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
OrganizationID uint `json:"organization_id" gorm:"not null;index"`
RedirectURL string `json:"redirect_url" gorm:"type:varchar(2048)"`
CodeVerifier string `json:"-" gorm:"type:varchar(512)"`
Nonce string `json:"-" gorm:"type:varchar(512)"`
ExpiresAt time.Time `json:"expires_at" gorm:"not null;index"`
}
SSOState stores transient SSO authentication state (CSRF protection)
type SeatChangePreview ¶
type SeatChangePreview struct {
CurrentSeats int `json:"current_seats"`
RequestedSeats int `json:"requested_seats"`
ProratedAmount int64 `json:"prorated_amount"` // cents – positive means charge, negative means credit
Currency string `json:"currency"` // e.g. "usd"
NextBillingDate string `json:"next_billing_date"` // ISO-8601
NextBillingAmount int64 `json:"next_billing_amount"` // cents – full amount at next renewal
}
SeatChangePreview shows the cost impact of changing seat count before the user confirms. This uses Stripe's upcoming invoice preview so the amount matches exactly what will be charged.
type SharePersonalItemRequest ¶
type SharePersonalItemRequest struct {
}
SharePersonalItemRequest for sharing a personal item to organization
type SignUpRequest ¶
type SignUpRequest struct {
Name string `json:"name" validate:"max=100"`
Email string `json:"email" validate:"required,email"`
MasterPasswordHash string `json:"master_password_hash" validate:"required"` // HKDF(masterKey, info="auth")
ProtectedUserKey string `json:"protected_user_key" validate:"required"` // EncString: "2.iv|ct|mac"
KdfConfig *KdfConfig `json:"kdf_config" validate:"required"`
KdfSalt string `json:"kdf_salt" validate:"required"` // hex-encoded random salt from client
EncryptedOrgKey string `json:"encrypted_org_key" validate:"required"` // Organization key encrypted with User Key
}
SignUpRequest represents a user registration request
func (*SignUpRequest) Validate ¶
func (r *SignUpRequest) Validate() error
Validate validates the signup request
type SoleOwnerOrganization ¶
type SoleOwnerOrganization struct {
ID uint `json:"id"`
Name string `json:"name"`
MemberCount int `json:"member_count"`
CanTransfer bool `json:"can_transfer"` // True if there are other members to transfer to
}
SoleOwnerOrganization represents an organization where user is the sole owner
type Subscription ¶
type Subscription struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
OrganizationID uint `json:"organization_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
PlanID uint `json:"plan_id" gorm:"not null;index"`
State SubscriptionState `json:"state" gorm:"type:varchar(20);not null;default:'draft'"`
// Lifecycle timestamps
StartedAt *time.Time `json:"started_at,omitempty"`
RenewAt *time.Time `json:"renew_at,omitempty"`
CancelAt *time.Time `json:"cancel_at,omitempty"`
EndedAt *time.Time `json:"ended_at,omitempty"`
GracePeriodEndsAt *time.Time `json:"grace_period_ends_at,omitempty"`
TrialEndsAt *time.Time `json:"trial_ends_at,omitempty"`
// Stripe integration
StripeSubscriptionID *string `json:"stripe_subscription_id,omitempty" gorm:"type:varchar(255);uniqueIndex"`
// Seat-based billing (quantity-based Stripe subscriptions)
// Null means "not seat-based / unknown". When set, it becomes the effective user limit.
SeatsPurchased *int `json:"seats_purchased,omitempty" gorm:"index"`
// Associations
Organization *Organization `json:"organization,omitempty" gorm:"foreignKey:OrganizationID"`
Plan *Plan `json:"plan,omitempty" gorm:"foreignKey:PlanID"`
}
Subscription represents an organization's subscription to a plan
func (*Subscription) CanWrite ¶
func (s *Subscription) CanWrite() bool
CanWrite checks if subscription allows write operations
func (*Subscription) IsActive ¶
func (s *Subscription) IsActive() bool
IsActive checks if subscription allows full access
func (*Subscription) IsCanceled ¶
func (s *Subscription) IsCanceled() bool
IsCanceled checks if subscription is canceled
func (*Subscription) IsExpired ¶
func (s *Subscription) IsExpired() bool
IsExpired checks if subscription has expired
func (*Subscription) IsInGracePeriod ¶
func (s *Subscription) IsInGracePeriod() bool
IsInGracePeriod checks if subscription is in grace period after payment failure
func (*Subscription) ShouldExpire ¶
func (s *Subscription) ShouldExpire() bool
ShouldExpire checks if subscription should be expired (grace period ended or cancel period ended)
func (Subscription) TableName ¶
func (Subscription) TableName() string
TableName specifies the table name
type SubscriptionDTO ¶
type SubscriptionDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
OrganizationID uint `json:"organization_id"`
Plan *PlanDTO `json:"plan,omitempty"`
State SubscriptionState `json:"state"`
StartedAt *time.Time `json:"started_at,omitempty"`
RenewAt *time.Time `json:"renew_at,omitempty"`
CancelAt *time.Time `json:"cancel_at,omitempty"`
EndedAt *time.Time `json:"ended_at,omitempty"`
GracePeriodEndsAt *time.Time `json:"grace_period_ends_at,omitempty"`
TrialEndsAt *time.Time `json:"trial_ends_at,omitempty"`
StripeSubscriptionID *string `json:"stripe_subscription_id,omitempty"`
SeatsPurchased *int `json:"seats_purchased,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
SubscriptionDTO for API responses
func ToSubscriptionDTO ¶
func ToSubscriptionDTO(s *Subscription) *SubscriptionDTO
ToSubscriptionDTO converts Subscription to DTO
type SubscriptionState ¶
type SubscriptionState string
SubscriptionState represents the state of a subscription
const ( SubStateDraft SubscriptionState = "draft" SubStateTrialing SubscriptionState = "trialing" SubStateActive SubscriptionState = "active" SubStatePastDue SubscriptionState = "past_due" SubStateCanceled SubscriptionState = "canceled" SubStateExpired SubscriptionState = "expired" )
func (SubscriptionState) String ¶
func (s SubscriptionState) String() string
String returns the string representation of SubscriptionState
type Team ¶
type Team struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
OrganizationID uint `json:"organization_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
// Team details
Name string `json:"name" gorm:"type:varchar(255);not null"`
Description string `json:"description,omitempty" gorm:"type:text"`
// System defaults
IsDefault bool `json:"is_default" gorm:"not null;default:false"`
// Access control
AccessAllCollections bool `json:"access_all_collections" gorm:"default:false"`
// External ID for LDAP/AD sync
ExternalID *string `json:"external_id,omitempty" gorm:"type:varchar(255);index"`
// Associations
Organization *Organization `json:"organization,omitempty" gorm:"foreignKey:OrganizationID"`
Members []TeamUser `json:"members,omitempty" gorm:"foreignKey:TeamID"`
}
Team represents a group of users within an organization
type TeamDTO ¶
type TeamDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
OrganizationID uint `json:"organization_id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
AccessAllCollections bool `json:"access_all_collections"`
ExternalID *string `json:"external_id,omitempty"`
IsDefault bool `json:"is_default"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Stats (optional)
MemberCount *int `json:"member_count,omitempty"`
}
TeamDTO for API responses
type TeamUser ¶
type TeamUser struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
TeamID uint `json:"team_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
OrganizationUserID uint `json:"organization_user_id" gorm:"not null;index;constraint:OnDelete:CASCADE"`
// Role in team
IsManager bool `json:"is_manager" gorm:"default:false"`
// Associations
Team *Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
OrganizationUser *OrganizationUser `json:"organization_user,omitempty" gorm:"foreignKey:OrganizationUserID"`
}
TeamUser represents a user's membership in a team
type TeamUserDTO ¶
type TeamUserDTO struct {
ID uint `json:"id"`
TeamID uint `json:"team_id"`
OrganizationUserID uint `json:"organization_user_id"`
UserID uint `json:"user_id"`
UserEmail string `json:"user_email"`
UserName string `json:"user_name"`
IsManager bool `json:"is_manager"`
CreatedAt time.Time `json:"created_at"`
}
TeamUserDTO for API responses
func ToTeamUserDTO ¶
func ToTeamUserDTO(tu *TeamUser) *TeamUserDTO
ToTeamUserDTO converts TeamUser to DTO
type Token ¶
type Token struct {
ID int `gorm:"primary_key" json:"id"`
UserID int `json:"user_id" gorm:"index;not null"`
UUID uuid.UUID `gorm:"type:uuid;type:varchar(100);uniqueIndex;not null" json:"uuid"`
// SessionUUID groups access+refresh tokens belonging to the same login/session.
// This allows multiple concurrent sessions (e.g. vault + extension) without revoking each other.
SessionUUID uuid.UUID `gorm:"type:uuid;index" json:"-"`
// DeviceID is an optional stable identifier for a device/app installation.
// For Vault we currently align DeviceID with SessionUUID to avoid orphan sessions after tab close.
DeviceID uuid.UUID `gorm:"type:uuid;index" json:"-"`
// App identifies the client type: vault|extension|mobile|desktop
App string `gorm:"type:varchar(16);index" json:"-"`
// Kind is either "access" or "refresh" (optional for legacy rows).
Kind string `gorm:"type:varchar(16);index" json:"-"`
Token string `gorm:"type:text;not null" json:"-"`
ExpiryTime time.Time `json:"expiry_time" gorm:"index;not null"`
}
Token represents authentication tokens stored in the database
type TokenClaims ¶
type TokenClaims struct {
UserID uint `json:"user_id"`
Email string `json:"email"`
Schema string `json:"schema"`
Role string `json:"role"`
UUID uuid.UUID `json:"uuid"`
Exp int64 `json:"exp"`
}
TokenClaims represents JWT token claims
type TokenDetails ¶
type TokenDetails struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
AccessTokenExpiresAt int64 `json:"access_token_expires_at,omitempty"` // unix seconds
RefreshTokenExpiresAt int64 `json:"refresh_token_expires_at,omitempty"` // unix seconds
AtExpiresTime time.Time `json:"-"`
RtExpiresTime time.Time `json:"-"`
AtUUID uuid.UUID `json:"-"`
RtUUID uuid.UUID `json:"-"`
SessionUUID uuid.UUID `json:"-"`
}
TokenDetails represents JWT token details
type TransferOwnershipRequest ¶
type TransferOwnershipRequest struct {
UserID uint `json:"user_id" binding:"required"`
OrganizationID uint `json:"organization_id" binding:"required"`
NewOwnerUserID uint `json:"new_owner_user_id" binding:"required"`
}
TransferOwnershipRequest represents a request to transfer organization ownership
type UpdateCollectionRequest ¶
type UpdateCollectionRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,max=255"`
Description *string `json:"description,omitempty" validate:"omitempty,max=1000"`
IsPrivate *bool `json:"is_private,omitempty"`
}
UpdateCollectionRequest for API requests
type UpdateOrgUserRoleRequest ¶
type UpdateOrgUserRoleRequest struct {
Role OrganizationRole `json:"role" binding:"required,oneof=owner admin manager member"`
AccessAll *bool `json:"access_all,omitempty"`
}
UpdateOrgUserRoleRequest for updating user role
type UpdateOrganizationFolderRequest ¶
type UpdateOrganizationFolderRequest struct {
Name string `json:"name" validate:"required,max=255"`
}
type UpdateOrganizationItemRequest ¶
type UpdateOrganizationItemRequest struct {
CollectionID *uint `json:"collection_id,omitempty"`
Data *string `json:"data,omitempty"`
Metadata *ItemMetadata `json:"metadata,omitempty"`
IsFavorite *bool `json:"is_favorite,omitempty"`
FolderID *uint `json:"folder_id,omitempty"`
Reprompt *bool `json:"reprompt,omitempty"`
AutoFill *bool `json:"auto_fill,omitempty"`
AutoLogin *bool `json:"auto_login,omitempty"`
}
UpdateOrganizationItemRequest for API requests
type UpdateOrganizationRequest ¶
type UpdateOrganizationRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,max=255"`
BillingEmail *string `json:"billing_email,omitempty" validate:"omitempty,email"`
}
UpdateOrganizationRequest for API requests
type UpdateSSOConnectionRequest ¶
type UpdateSSOConnectionRequest struct {
Name *string `json:"name,omitempty" binding:"omitempty,max=255"`
Domain *string `json:"domain,omitempty" binding:"omitempty,max=255"`
SAMLConfig *SAMLConfig `json:"saml_config,omitempty"`
OIDCConfig *OIDCConfig `json:"oidc_config,omitempty"`
AutoProvision *bool `json:"auto_provision,omitempty"`
DefaultRole *OrganizationRole `json:"default_role,omitempty"`
JITProvisioning *bool `json:"jit_provisioning,omitempty"`
Status *SSOConnectionStatus `json:"status,omitempty" binding:"omitempty,oneof=draft active inactive"`
}
UpdateSSOConnectionRequest for updating an SSO connection
type UpdateSubscriptionRequest ¶
type UpdateSubscriptionRequest struct {
PlanCode string `json:"plan_code" validate:"required"`
}
UpdateSubscriptionRequest for API requests
type UpdateTeamRequest ¶
type UpdateTeamRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,max=255"`
Description *string `json:"description,omitempty" validate:"omitempty,max=1000"`
AccessAllCollections *bool `json:"access_all_collections,omitempty"`
}
UpdateTeamRequest for API requests
type UpdateTeamUserRequest ¶
type UpdateTeamUserRequest struct {
IsManager bool `json:"is_manager"`
}
UpdateTeamUserRequest for updating team member
type UpdateUserAppearancePreferencesRequest ¶
type UpdateUserAppearancePreferencesRequest struct {
Theme *string `json:"theme"`
Font *string `json:"font"`
}
UpdateUserAppearancePreferencesRequest supports partial updates. (Fields are pointers so "unset" can be distinguished from empty values.)
type UpdateUserNotificationPreferencesRequest ¶
type UpdateUserNotificationPreferencesRequest struct {
CommunicationEmails *bool `json:"communication_emails"`
MarketingEmails *bool `json:"marketing_emails"`
SocialEmails *bool `json:"social_emails"`
SecurityEmails *bool `json:"security_emails"`
}
UpdateUserNotificationPreferencesRequest supports partial updates. (Booleans are pointers so "unset" can be distinguished from false.)
type UpdateUserRequest ¶
type UpdateUserRequest struct {
Name *string `json:"name,omitempty"`
Email *string `json:"email,omitempty"`
RoleID *uint `json:"role_id,omitempty"`
DateOfBirth *string `json:"date_of_birth,omitempty"`
Language *string `json:"language,omitempty"`
}
UpdateUserRequest represents user update request
func (*UpdateUserRequest) ApplyTo ¶
func (r *UpdateUserRequest) ApplyTo(user *User)
ApplyTo applies the update request to a user
func (*UpdateUserRequest) HasUpdates ¶
func (r *UpdateUserRequest) HasUpdates() bool
HasUpdates checks if any field is being updated
type UpsertPreferenceRequest ¶
type UpsertPreferencesRequest ¶
type UpsertPreferencesRequest struct {
Preferences []UpsertPreferenceRequest `json:"preferences"`
}
type User ¶
type User struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;type:varchar(100);" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Name string `json:"name" gorm:"type:varchar(255)"`
Email string `json:"email" gorm:"type:varchar(255);uniqueIndex;not null"`
Schema string `json:"schema" gorm:"type:varchar(255);uniqueIndex;not null"`
// Organization pointers (per user)
PersonalOrganizationID uint `json:"personal_organization_id" gorm:"not null"`
DefaultOrganizationID uint `json:"default_organization_id" gorm:"not null"`
// Modern Zero-Knowledge Encryption Fields
MasterPasswordHash string `json:"-" gorm:"type:varchar(255);not null"` // bcrypt(HKDF(masterKey, info="auth"))
ProtectedUserKey string `json:"-" gorm:"type:text;not null"` // EncString: "2.iv|ct|mac"
// KDF Configuration (per user, configurable)
KdfType KdfType `json:"kdf_type" gorm:"not null;default:0"` // 0=PBKDF2, 1=Argon2id
KdfIterations int `json:"kdf_iterations" gorm:"not null;default:600000"` // Default: 600K
KdfMemory *int `json:"kdf_memory,omitempty"` // For Argon2 (MB)
KdfParallelism *int `json:"kdf_parallelism,omitempty"` // For Argon2 (threads)
KdfSalt string `json:"-" gorm:"type:varchar(64);not null"` // hex-encoded 32 bytes, random per user
// RSA Keys for Organization Sharing (optional, generated when joining first org)
RSAPublicKey *string `json:"rsa_public_key,omitempty" gorm:"type:text"` // RSA-2048 public key (PEM format)
RSAPrivateKeyEnc *string `json:"-" gorm:"type:text"` // RSA private key encrypted with User Key (EncString)
// User metadata
RoleID uint `json:"role_id" gorm:"not null;default:2;constraint:OnUpdate:CASCADE,OnDelete:RESTRICT"`
Role *Role `json:"role,omitempty" gorm:"foreignKey:RoleID"`
IsVerified bool `json:"is_verified" gorm:"default:false"`
IsSystemUser bool `json:"is_system_user" gorm:"default:false;index"` // System users (e.g., super admin) cannot be deleted
Language string `json:"language" gorm:"type:varchar(10);default:'en'"`
// Stripe integration for personal subscriptions
StripeCustomerID *string `json:"-" gorm:"type:varchar(255);index"` // Stripe customer ID for user-level billing
// Stats (runtime calculated, not stored in DB)
ItemCount *int `json:"item_count,omitempty" gorm:"-"`
}
User represents a user account in the system
func (*User) GetKdfConfig ¶
GetKdfConfig extracts KDF config from user
func (*User) GetRoleName ¶
GetRoleName returns the role name with proper null handling
func (*User) HasPermission ¶
HasPermission checks if user has a specific permission (requires Role.Permissions to be loaded)
type UserActivity ¶
type UserActivity struct {
ID uint `gorm:"primary_key" json:"id"`
UserID uint `gorm:"not null;index" json:"user_id"`
ActivityType ActivityType `gorm:"type:varchar(50);not null;index" json:"activity_type"`
IPAddress string `gorm:"type:varchar(45)" json:"ip_address"` // IPv4 or IPv6
UserAgent string `gorm:"type:varchar(500)" json:"user_agent"`
Details string `gorm:"type:text" json:"details,omitempty"` // JSON for additional info
CreatedAt time.Time `gorm:"index" json:"created_at"`
}
UserActivity represents user activity log for audit trail
func (UserActivity) TableName ¶
func (UserActivity) TableName() string
TableName specifies the table name
type UserActivityDTO ¶
type UserActivityDTO struct {
ID uint `json:"id"`
UserID uint `json:"user_id"`
ActivityType ActivityType `json:"activity_type"`
IPAddress string `json:"ip_address"`
UserAgent string `json:"user_agent"`
Details string `json:"details,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
UserActivityDTO for API responses
func ToUserActivityDTO ¶
func ToUserActivityDTO(activity *UserActivity) *UserActivityDTO
ToUserActivityDTO converts UserActivity to DTO
func ToUserActivityDTOs ¶
func ToUserActivityDTOs(activities []*UserActivity) []*UserActivityDTO
ToUserActivityDTOs converts multiple activities to DTOs
type UserAppearancePreferences ¶
type UserAppearancePreferences struct {
UserID uint `json:"user_id" gorm:"primaryKey"`
// Theme can be: dark | light | system
Theme string `json:"theme" gorm:"not null;default:dark"`
// Font is a UI hint (e.g. inter, manrope, system).
Font string `json:"font" gorm:"not null;default:inter"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
UserAppearancePreferences stores per-user UI preferences (theme, font).
This is a 1:1 table keyed by user_id (PK) to keep reads/updates fast.
func (UserAppearancePreferences) TableName ¶
func (UserAppearancePreferences) TableName() string
type UserAppearancePreferencesDTO ¶
UserAppearancePreferencesDTO is the API response shape.
func ToUserAppearancePreferencesDTO ¶
func ToUserAppearancePreferencesDTO(p *UserAppearancePreferences) *UserAppearancePreferencesDTO
type UserAuthDTO ¶
type UserAuthDTO struct {
ID uint `json:"id"`
UUID string `json:"uuid"`
Email string `json:"email"`
Name string `json:"name"`
Schema string `json:"schema"`
Role string `json:"role"`
IsVerified bool `json:"is_verified"`
Language string `json:"language"`
PersonalOrganizationID uint `json:"personal_organization_id"`
DefaultOrganizationID uint `json:"default_organization_id"`
}
UserAuthDTO represents user data in auth responses
type UserBillingInfo ¶
type UserBillingInfo struct {
UserID uint `json:"user_id"`
Email string `json:"email"`
Name string `json:"name"`
IsPro bool `json:"is_pro"` // true if user has active Pro subscription
Subscription *UserSubscriptionDTO `json:"subscription,omitempty"`
CurrentPlan string `json:"current_plan"` // "free" or plan code like "pro-monthly"
CurrentItems int `json:"current_items"`
Invoices []*InvoiceDTO `json:"invoices,omitempty"`
// Payment provider information
Provider PaymentProvider `json:"provider"` // "stripe", "revenuecat", "manual", "none"
Store string `json:"store,omitempty"` // "APP_STORE", "PLAY_STORE", etc. (only for revenuecat)
StoreDisplayName string `json:"store_display_name,omitempty"` // "Apple App Store", "Google Play Store", etc.
ManagedExternally bool `json:"managed_externally"` // true if subscription can only be canceled from external store
CanCancel bool `json:"can_cancel"` // true if subscription can be canceled from our API
CanUpgrade bool `json:"can_upgrade"` // true if plan can be changed from our API
}
UserBillingInfo represents billing information for a user
type UserDTO ¶
type UserDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Name string `json:"name"`
Email string `json:"email"`
Schema string `json:"schema"`
Role string `json:"role"`
IsVerified bool `json:"is_verified"`
IsSystemUser bool `json:"is_system_user"` // System users cannot be deleted
Language string `json:"language"`
ItemCount *int `json:"item_count,omitempty"`
KdfType KdfType `json:"kdf_type"`
KdfIterations int `json:"kdf_iterations"`
}
UserDTO is the data transfer object for User It converts the Role relationship to a simple string for API responses
func ToUserDTOs ¶
ToUserDTOs converts multiple Users to UserDTOs
type UserNotificationPreferences ¶
type UserNotificationPreferences struct {
UserID uint `json:"user_id" gorm:"primaryKey"`
CommunicationEmails bool `json:"communication_emails" gorm:"not null;default:false"`
MarketingEmails bool `json:"marketing_emails" gorm:"not null;default:false"`
SocialEmails bool `json:"social_emails" gorm:"not null;default:false"`
// Security emails are mandatory and should not be disabled.
SecurityEmails bool `json:"security_emails" gorm:"not null;default:true"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
UserNotificationPreferences stores per-user notification delivery preferences.
This is intentionally a 1:1 table keyed by user_id (PK) to keep reads/updates fast and to avoid having to manage separate IDs for a purely user-scoped row.
func (UserNotificationPreferences) TableName ¶
func (UserNotificationPreferences) TableName() string
type UserNotificationPreferencesDTO ¶
type UserNotificationPreferencesDTO struct {
CommunicationEmails bool `json:"communication_emails"`
MarketingEmails bool `json:"marketing_emails"`
SocialEmails bool `json:"social_emails"`
SecurityEmails bool `json:"security_emails"`
}
UserNotificationPreferencesDTO is the API response shape.
func ToUserNotificationPreferencesDTO ¶
func ToUserNotificationPreferencesDTO(p *UserNotificationPreferences) *UserNotificationPreferencesDTO
type UserSubscription ¶
type UserSubscription struct {
ID uint `gorm:"primary_key" json:"id"`
UUID uuid.UUID `gorm:"type:uuid;not null" json:"uuid"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
UserID uint `json:"user_id" gorm:"not null;uniqueIndex;constraint:OnDelete:CASCADE"`
PlanID uint `json:"plan_id" gorm:"not null;index"`
State SubscriptionState `json:"state" gorm:"type:varchar(20);not null;default:'draft'"`
// Lifecycle timestamps
StartedAt *time.Time `json:"started_at,omitempty"`
RenewAt *time.Time `json:"renew_at,omitempty"`
CancelAt *time.Time `json:"cancel_at,omitempty"`
EndedAt *time.Time `json:"ended_at,omitempty"`
GracePeriodEndsAt *time.Time `json:"grace_period_ends_at,omitempty"`
TrialEndsAt *time.Time `json:"trial_ends_at,omitempty"`
// Stripe integration
StripeSubscriptionID *string `json:"stripe_subscription_id,omitempty" gorm:"type:varchar(255);uniqueIndex"`
// Associations
User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Plan *Plan `json:"plan,omitempty" gorm:"foreignKey:PlanID"`
}
UserSubscription represents a user's personal subscription to a plan (e.g., Pro) This is separate from organization subscriptions - every user can have their own subscription.
func (*UserSubscription) CanWrite ¶
func (s *UserSubscription) CanWrite() bool
CanWrite checks if subscription allows write operations
func (*UserSubscription) IsActive ¶
func (s *UserSubscription) IsActive() bool
IsActive checks if subscription allows full access
func (*UserSubscription) IsCanceled ¶
func (s *UserSubscription) IsCanceled() bool
IsCanceled checks if subscription is canceled
func (*UserSubscription) IsExpired ¶
func (s *UserSubscription) IsExpired() bool
IsExpired checks if subscription has expired
func (*UserSubscription) IsInGracePeriod ¶
func (s *UserSubscription) IsInGracePeriod() bool
IsInGracePeriod checks if subscription is in grace period after payment failure
func (*UserSubscription) ShouldExpire ¶
func (s *UserSubscription) ShouldExpire() bool
ShouldExpire checks if subscription should be expired
func (UserSubscription) TableName ¶
func (UserSubscription) TableName() string
TableName specifies the table name
type UserSubscriptionDTO ¶
type UserSubscriptionDTO struct {
ID uint `json:"id"`
UUID uuid.UUID `json:"uuid"`
UserID uint `json:"user_id"`
Plan *PlanDTO `json:"plan,omitempty"`
State SubscriptionState `json:"state"`
StartedAt *time.Time `json:"started_at,omitempty"`
RenewAt *time.Time `json:"renew_at,omitempty"`
CancelAt *time.Time `json:"cancel_at,omitempty"`
EndedAt *time.Time `json:"ended_at,omitempty"`
GracePeriodEndsAt *time.Time `json:"grace_period_ends_at,omitempty"`
TrialEndsAt *time.Time `json:"trial_ends_at,omitempty"`
StripeSubscriptionID *string `json:"stripe_subscription_id,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
UserSubscriptionDTO for API responses
func ToUserSubscriptionDTO ¶
func ToUserSubscriptionDTO(s *UserSubscription) *UserSubscriptionDTO
ToUserSubscriptionDTO converts UserSubscription to DTO
type VerificationCode ¶
type VerificationCode struct {
ID uint `gorm:"primary_key" json:"id"`
Email string `json:"email" gorm:"type:varchar(255);not null;index:idx_verification_code_email"`
Code string `json:"code" gorm:"type:varchar(6);not null;index:idx_verification_code_email"`
ExpiresAt time.Time `json:"expires_at" gorm:"not null;index:idx_verification_code_expires"`
CreatedAt time.Time `json:"created_at"`
}
VerificationCode represents email verification code in database
func (*VerificationCode) IsExpired ¶
func (v *VerificationCode) IsExpired() bool
IsExpired checks if the verification code has expired
func (VerificationCode) TableName ¶
func (VerificationCode) TableName() string
TableName specifies the table name for VerificationCode
type VerificationCodeRequest ¶
type VerificationCodeRequest struct {
Name string `json:"name" binding:"required,max=100"`
Email string `json:"email" binding:"required,email"`
}
VerificationCodeRequest represents a request to send verification code
type VerificationCodeResponse ¶
type VerificationCodeResponse struct {
Message string `json:"message"`
}
VerificationCodeResponse represents verification code response
type VerifyEmailRequest ¶
type VerifyEmailRequest struct {
Email string `json:"email" binding:"required,email"`
Code string `json:"code" binding:"required,len=6"`
}
VerifyEmailRequest represents email verification request
type VerifyEmailResponse ¶
VerifyEmailResponse represents email verification response
type WebhookEvent ¶
type WebhookEvent struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
StripeEventID string `json:"stripe_event_id" gorm:"type:varchar(255);uniqueIndex;not null"`
EventType string `json:"event_type" gorm:"type:varchar(100);not null"`
Payload WebhookPayload `json:"payload" gorm:"type:jsonb;not null"`
ProcessedAt *time.Time `json:"processed_at,omitempty"`
Error *string `json:"error,omitempty" gorm:"type:text"`
}
WebhookEvent represents a Stripe webhook event for idempotency
func (*WebhookEvent) HasError ¶
func (w *WebhookEvent) HasError() bool
HasError checks if webhook processing failed
func (*WebhookEvent) IsProcessed ¶
func (w *WebhookEvent) IsProcessed() bool
IsProcessed checks if webhook event has been processed
func (*WebhookEvent) MarkFailed ¶
func (w *WebhookEvent) MarkFailed(err error)
MarkFailed marks the webhook as failed with an error
func (*WebhookEvent) MarkProcessed ¶
func (w *WebhookEvent) MarkProcessed()
MarkProcessed marks the webhook as successfully processed
func (WebhookEvent) TableName ¶
func (WebhookEvent) TableName() string
TableName specifies the table name
type WebhookPayload ¶
type WebhookPayload json.RawMessage
WebhookPayload represents the webhook payload
func (*WebhookPayload) Scan ¶
func (p *WebhookPayload) Scan(value interface{}) error
Scan implements sql.Scanner for WebhookPayload (JSONB)
Source Files
¶
- auth.go
- billing.go
- collection.go
- excluded_domain.go
- invitation.go
- invoice.go
- item.go
- kdf_config.go
- organization.go
- organization_folder.go
- organization_item.go
- payment_provider.go
- permission.go
- permissions.go
- plan.go
- preference.go
- role.go
- scim.go
- sso.go
- subscription.go
- team.go
- token.go
- user.go
- user_activity.go
- user_appearance_preferences.go
- user_dto.go
- user_notification_preferences.go
- user_subscription.go
- verification_code.go
- webhook_event.go