package ents import ( "context" "errors" "atlas9.dev/c/core" "atlas9.dev/c/core/iam" ) var Cap_Entitlements_Write = iam.NewCap("Entitlements_Write") var Cap_Entitlements_Read = iam.NewCap("Entitlements_Read") var ErrQuotaExceeded = errors.New("quota exceeded") // QuotaExceededError carries the name of the specific quota that was exceeded. // errors.Is(err, ErrQuotaExceeded) returns true for any QuotaExceededError. type QuotaExceededError struct{ Name string } func (e *QuotaExceededError) Error() string { return "quota exceeded: " + e.Name } func (e *QuotaExceededError) Unwrap() error { return ErrQuotaExceeded } type Quota struct { Used, Max int } // Ok returns ErrQuotaExceeded if the quota is full or not granted. func (q Quota) Ok() error { if q.Used >= q.Max { return ErrQuotaExceeded } return nil } // Defaults is the baseline granted to every newly provisioned tenant. // Max=0 means no access, so every field must be explicitly set. func Defaults() Entitlements { return Entitlements{ AuditLog: true, Sso: Quota{Max: 1}, Members: Quota{Max: 25}, Roles: Quota{Max: 10}, Groups: Quota{Max: 10}, Invitations: Quota{Max: 25}, TodoLists: Quota{Max: 50}, TodoItems: Quota{Max: 1_000_000}, Bots: Quota{Max: 3}, BotKeys: Quota{Max: 10}, Domains: Quota{Max: 5}, Webhooks: Quota{Max: 10}, Slack: Quota{Max: 5}, } } type Store interface { Get(ctx context.Context, tenant core.ID, out *Entitlements) error Create(ctx context.Context, tenant core.ID, e *Entitlements) error Update(ctx context.Context, tenant core.ID, e *Entitlements) error } type Entitlements struct { Sso Quota Tenants Quota // TODO what controls tenant count if tenants are the root? Members Quota Roles Quota Groups Quota Invitations Quota // TODO should be a rate TodoLists Quota TodoItems Quota AuditLog bool Bots Quota BotKeys Quota Domains Quota Webhooks Quota Slack Quota }