feat(PROJ-33): IMAP UID-Stabilität + Shared/Personal-Modus
Backend: - storage: uid BIGSERIAL Migration, MailWithUID, GetMailsWithUID, GetMailsByRecipient - tenantstore: imap_mode Spalte, GetIMAPMode, SetIMAPMode - imapserver: stable UIDs aus DB, personal/shared Modus, userEmail in session - api: GET/PUT /api/admin/settings/imap-mode (domain_admin only, double opt-in) Frontend: - IMAPSettingsTab: Modus-Anzeige + Toggle mit Double-Opt-In Dialog - Admin-Panel: IMAP-Tab für domain_admin Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,7 @@ ALTER TABLE users ADD COLUMN IF NOT EXISTS tenant_id BIGINT REFERENCES tenants(i
|
||||
ALTER TABLE audit_log ADD COLUMN IF NOT EXISTS tenant_id BIGINT REFERENCES tenants(id);
|
||||
ALTER TABLE tenants ADD COLUMN IF NOT EXISTS logo_data BYTEA;
|
||||
ALTER TABLE tenants ADD COLUMN IF NOT EXISTS logo_content_type VARCHAR(100) NOT NULL DEFAULT '';
|
||||
ALTER TABLE tenants ADD COLUMN IF NOT EXISTS imap_mode TEXT NOT NULL DEFAULT 'personal';
|
||||
`
|
||||
|
||||
// New connects to PostgreSQL and initialises the tenant schema.
|
||||
@@ -326,3 +327,24 @@ func (s *Store) getDomain(ctx context.Context, id int64) (*TenantDomain, error)
|
||||
}
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
// ── IMAP Mode ─────────────────────────────────────────────────────────────
|
||||
|
||||
// GetIMAPMode returns the imap_mode for a tenant ("personal" or "shared").
|
||||
func (s *Store) GetIMAPMode(ctx context.Context, tenantID int64) (string, error) {
|
||||
var mode string
|
||||
err := s.pool.QueryRow(ctx, `SELECT imap_mode FROM tenants WHERE id = $1`, tenantID).Scan(&mode)
|
||||
if err != nil {
|
||||
return "personal", nil // safe default
|
||||
}
|
||||
return mode, nil
|
||||
}
|
||||
|
||||
// SetIMAPMode updates the imap_mode for a tenant. Valid values: "personal", "shared".
|
||||
func (s *Store) SetIMAPMode(ctx context.Context, tenantID int64, mode string) error {
|
||||
if mode != "personal" && mode != "shared" {
|
||||
return fmt.Errorf("tenantstore: invalid imap_mode %q", mode)
|
||||
}
|
||||
_, err := s.pool.Exec(ctx, `UPDATE tenants SET imap_mode = $1 WHERE id = $2`, mode, tenantID)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user