354 lines
10 KiB
Go
354 lines
10 KiB
Go
package db
|
|
|
|
import "time"
|
|
|
|
// ── Tenants & domains ──────────────────────────────────────────────────────────
|
|
|
|
type Tenant struct {
|
|
ID string
|
|
Name string
|
|
DisplayName string
|
|
DigestIntervalMins int
|
|
MaxAccounts int // 0 = unlimited
|
|
QuotaMBPerUser int
|
|
SettingsJSON string // pipeline thresholds, check toggles (parsed by pipeline pkg)
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type Domain struct {
|
|
ID string
|
|
TenantID string
|
|
Domain string
|
|
Active bool
|
|
DKIMSelector string
|
|
DKIMPrivateKeyEnc []byte // AES-256-GCM encrypted PEM
|
|
AcceptAll bool
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// ── Users & auth ──────────────────────────────────────────────────────────────
|
|
|
|
type UserRole string
|
|
|
|
const (
|
|
RoleUser UserRole = "user"
|
|
RoleTenantAdmin UserRole = "tenant_admin"
|
|
RoleGlobalAdmin UserRole = "global_admin"
|
|
)
|
|
|
|
type User struct {
|
|
ID string
|
|
TenantID string
|
|
DomainID string
|
|
Email string
|
|
PasswordHash string
|
|
DisplayName string
|
|
Role UserRole
|
|
Active bool
|
|
MFAEnabled bool
|
|
TOTPSecretEnc []byte // AES-256-GCM encrypted
|
|
PasskeyCredentialsJSON string // JSON array of WebAuthn credentials
|
|
RecoveryEmail string // external address for password-reset delivery (see Phase 12 notes)
|
|
QuotaMB int
|
|
UsedBytes int64
|
|
DigestEnabled bool
|
|
DigestIntervalMins int // 0 = use tenant default
|
|
LastDigestAt *time.Time
|
|
LastLoginAt *time.Time
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type AppPassword struct {
|
|
ID string
|
|
UserID string
|
|
Label string
|
|
PasswordHash string // bcrypt of a 32-char random token
|
|
Scopes string // comma-separated: smtp,imap,caldav,carddav,pop3
|
|
LastUsedAt *time.Time
|
|
ExpiresAt *time.Time // nil = never expires
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type Session struct {
|
|
ID string
|
|
UserID string
|
|
JTI string // JWT ID, for revocation lookups
|
|
UserAgent string
|
|
IP string
|
|
ExpiresAt time.Time
|
|
RevokedAt *time.Time
|
|
}
|
|
|
|
type Alias struct {
|
|
ID string
|
|
TenantID string
|
|
FromAddress string
|
|
ToUserID *string // nil if forwarding externally
|
|
ToExternal *string // nil if local
|
|
Active bool
|
|
}
|
|
|
|
// ── List rules (allow/block, per tenant) ───────────────────────────────────────
|
|
|
|
type ListRuleAction string
|
|
|
|
const (
|
|
ListActionAllow ListRuleAction = "allow"
|
|
ListActionBlock ListRuleAction = "block"
|
|
)
|
|
|
|
type ListRule struct {
|
|
ID string
|
|
TenantID string
|
|
ListType ListRuleAction // allow | block
|
|
MatchType string // email | domain
|
|
Value string
|
|
Note string
|
|
Active bool
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// ── Messages (audit log) & mailbox index ────────────────────────────────────────
|
|
|
|
type MessageVerdict string
|
|
|
|
const (
|
|
VerdictClean MessageVerdict = "clean"
|
|
VerdictFlagged MessageVerdict = "flagged"
|
|
VerdictQuarantine MessageVerdict = "quarantine"
|
|
VerdictBlocked MessageVerdict = "blocked"
|
|
)
|
|
|
|
type Message struct {
|
|
ID string
|
|
TenantID string
|
|
FromAddress string
|
|
ToAddress string
|
|
Subject string
|
|
MessageIDHdr string
|
|
SizeBytes int64
|
|
Verdict MessageVerdict
|
|
TotalScore float64
|
|
SenderIP string
|
|
RelayedAt *time.Time
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type MailboxEntry struct {
|
|
ID string
|
|
UserID string
|
|
Mailbox string // INBOX, Sent, Trash, Junk, custom...
|
|
UID int
|
|
EMLPath string // path to encrypted .eml.enc on disk
|
|
Flags string // \Seen \Flagged \Answered \Deleted \Draft
|
|
SizeBytes int64
|
|
ReceivedAt time.Time
|
|
InternalDate time.Time
|
|
}
|
|
|
|
// ── Outbound queue ───────────────────────────────────────────────────────────
|
|
|
|
type OutboundQueueEntry struct {
|
|
ID string
|
|
UserID string
|
|
FromAddress string
|
|
ToAddress string
|
|
EMLPath string
|
|
Priority int
|
|
Attempts int
|
|
LastError string
|
|
NextAttemptAt time.Time
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// ── Pipeline check results ──────────────────────────────────────────────────────
|
|
|
|
// CheckResult is the outcome of a single pipeline stage (SPF, DKIM, etc.).
|
|
type CheckResult string
|
|
|
|
const (
|
|
CheckPass CheckResult = "pass"
|
|
CheckWarn CheckResult = "warn"
|
|
CheckFail CheckResult = "fail"
|
|
CheckSkipped CheckResult = "skipped"
|
|
CheckError CheckResult = "error"
|
|
)
|
|
|
|
type MessageCheck struct {
|
|
ID string
|
|
MessageID string
|
|
Stage string
|
|
Result CheckResult
|
|
Score float64
|
|
Detail string
|
|
DurationMs int64
|
|
}
|
|
|
|
// ── Quarantine ────────────────────────────────────────────────────────────────
|
|
|
|
type QuarantineStatus string
|
|
|
|
const (
|
|
QuarantineHeld QuarantineStatus = "held"
|
|
QuarantineReleased QuarantineStatus = "released"
|
|
QuarantineDeleted QuarantineStatus = "deleted"
|
|
)
|
|
|
|
type QuarantineEntry struct {
|
|
ID string
|
|
MessageID string
|
|
EMLPath string
|
|
Status QuarantineStatus
|
|
Reason string
|
|
ReleasedBy string
|
|
ReleasedAt *time.Time
|
|
ExpiresAt time.Time
|
|
NotifiedAt *time.Time
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type ReleaseToken struct {
|
|
ID string
|
|
QuarantineID string
|
|
Token string
|
|
Email string
|
|
UsedAt *time.Time
|
|
ExpiresAt time.Time
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// ── Linked accounts (multi-account webmail — Part B of the plan) ──────────────
|
|
|
|
type LinkedAccountProvider string
|
|
|
|
const (
|
|
ProviderGoMail LinkedAccountProvider = "gomail"
|
|
ProviderIMAP LinkedAccountProvider = "imap"
|
|
ProviderGmail LinkedAccountProvider = "gmail" // Phase 10
|
|
ProviderM365 LinkedAccountProvider = "m365" // Phase 10
|
|
)
|
|
|
|
type LinkedAccountAuthType string
|
|
|
|
const (
|
|
AuthTypeSession LinkedAccountAuthType = "session" // gomail local account, already logged in
|
|
AuthTypePassword LinkedAccountAuthType = "password" // generic IMAP/SMTP
|
|
AuthTypeOAuth2 LinkedAccountAuthType = "oauth2" // Phase 10
|
|
)
|
|
|
|
type LinkedAccount struct {
|
|
ID string
|
|
UserID string
|
|
Provider LinkedAccountProvider
|
|
DisplayName string
|
|
EmailAddress string
|
|
AuthType LinkedAccountAuthType
|
|
IMAPHost string
|
|
IMAPPort int
|
|
IMAPTLS string // "starttls" | "implicit" | "off"
|
|
SMTPHost string
|
|
SMTPPort int
|
|
SMTPTLS string
|
|
CredentialEnc []byte // encrypted password or OAuth2 tokens (JSON)
|
|
OAuthExpiresAt *time.Time
|
|
SyncState string
|
|
CacheRetentionDays int // 0 = use instance default
|
|
LastSyncAt *time.Time
|
|
LastSyncError string
|
|
Active bool
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// ── CalDAV / CardDAV ────────────────────────────────────────────────────────────
|
|
|
|
// OwnerType distinguishes a personal (per-user) collection from a shared
|
|
// tenant-wide one — both addressbooks and calendars support both scopes per
|
|
// the plan (tenant addressbook + per-user addressbook, same for calendars).
|
|
type OwnerType string
|
|
|
|
const (
|
|
OwnerUser OwnerType = "user"
|
|
OwnerTenant OwnerType = "tenant"
|
|
)
|
|
|
|
type Addressbook struct {
|
|
ID string
|
|
OwnerType OwnerType
|
|
OwnerID string
|
|
DisplayName string
|
|
Description string
|
|
SyncToken string
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type Contact struct {
|
|
ID string
|
|
AddressbookID string
|
|
UID string
|
|
VCardEnc []byte // AES-256-GCM encrypted vCard text
|
|
ETag string
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
type Calendar struct {
|
|
ID string
|
|
OwnerType OwnerType
|
|
OwnerID string
|
|
DisplayName string
|
|
Description string
|
|
Color string
|
|
Timezone string
|
|
SyncToken string
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type CalendarObject struct {
|
|
ID string
|
|
CalendarID string
|
|
UID string
|
|
ICalEnc []byte // AES-256-GCM encrypted iCal text
|
|
ComponentType string // VEVENT | VTODO | VJOURNAL
|
|
Summary string
|
|
DTStart *time.Time
|
|
DTEnd *time.Time
|
|
ETag string
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// ── ManageSieve ───────────────────────────────────────────────────────────────
|
|
|
|
type SieveScript struct {
|
|
ID string
|
|
UserID string
|
|
Name string
|
|
ScriptText string
|
|
Active bool
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// ── TLS certs (ACME) ────────────────────────────────────────────────────────────
|
|
|
|
type TLSCert struct {
|
|
ID string
|
|
Domain string
|
|
CertPEMEnc []byte
|
|
KeyPEMEnc []byte
|
|
ExpiresAt *time.Time
|
|
ACMEAccountKeyEnc []byte
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// ── MFA ───────────────────────────────────────────────────────────────────────
|
|
|
|
type MFABackupCode struct {
|
|
ID string
|
|
UserID string
|
|
CodeHash string
|
|
UsedAt *time.Time
|
|
CreatedAt time.Time
|
|
}
|