feat(PROJ-29): Tenant-Quotas & Usage-Limits vollständig implementiert
- storage/quota.go: SQL-Bug gefixt (emails.size → size_bytes, email_refs JOIN)
- tenantstore/quota.go: GetUsage nutzt jetzt email_refs JOIN für korrekte Tenant-Isolation
- smtpd: ErrQuotaExceeded → SMTP 452 statt 554 (MTA-retry statt permanent reject)
- admin_handlers: handleCreateUser prüft max_users-Quota → HTTP 402 bei Überschreitung
- quota_handlers: handleGetTenantUsage gibt jetzt warnings-Feld mit soft-limit-Prozenten zurück
- server.go: spec-konforme Alias-Route GET /api/admin/tenants/{id}/usage registriert
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -48,14 +48,17 @@ func (s *Store) GetQuota(ctx context.Context, tenantID int64) (TenantQuota, erro
|
||||
}
|
||||
|
||||
// GetUsage returns the current resource usage for a tenant.
|
||||
// Email count and storage bytes are aggregated via email_refs (tenant-aware dedup).
|
||||
func (s *Store) GetUsage(ctx context.Context, tenantID int64) (*TenantUsage, error) {
|
||||
u := &TenantUsage{}
|
||||
|
||||
// Email count and storage bytes from emails table
|
||||
// Email count and storage bytes via email_refs JOIN emails (correct tenant isolation).
|
||||
// size_bytes is the column name in the emails table (not size).
|
||||
err := s.pool.QueryRow(ctx, `
|
||||
SELECT COUNT(*), COALESCE(SUM(size), 0)
|
||||
FROM emails
|
||||
WHERE tenant_id = $1
|
||||
SELECT COUNT(r.id), COALESCE(SUM(e.size_bytes), 0)
|
||||
FROM email_refs r
|
||||
JOIN emails e ON e.id = r.email_id
|
||||
WHERE r.tenant_id = $1
|
||||
`, tenantID).Scan(&u.EmailCount, &u.StorageBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tenantstore: get usage emails: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user