feat(api-key): add independent quota and expiration support
This feature allows API Keys to have their own quota limits and expiration times, independent of the user's balance. Backend: - Add quota, quota_used, expires_at fields to api_key schema - Implement IsExpired() and IsQuotaExhausted() checks in middleware - Add ResetQuota and ClearExpiration API endpoints - Integrate quota billing in gateway handlers (OpenAI, Anthropic, Gemini) - Include quota/expiration fields in auth cache for performance - Expiration check returns 403, quota exhausted returns 429 Frontend: - Add quota and expiration inputs to key create/edit dialog - Add quick-select buttons for expiration (+7, +30, +90 days) - Add reset quota confirmation dialog - Add expires_at column to keys list - Add i18n translations for new features (en/zh) Migration: - Add 045_add_api_key_quota.sql for new columns
This commit is contained in:
@@ -20,6 +20,9 @@ var (
|
||||
{Name: "status", Type: field.TypeString, Size: 20, Default: "active"},
|
||||
{Name: "ip_whitelist", Type: field.TypeJSON, Nullable: true},
|
||||
{Name: "ip_blacklist", Type: field.TypeJSON, Nullable: true},
|
||||
{Name: "quota", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||
{Name: "quota_used", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
|
||||
{Name: "expires_at", Type: field.TypeTime, Nullable: true},
|
||||
{Name: "group_id", Type: field.TypeInt64, Nullable: true},
|
||||
{Name: "user_id", Type: field.TypeInt64},
|
||||
}
|
||||
@@ -31,13 +34,13 @@ var (
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "api_keys_groups_api_keys",
|
||||
Columns: []*schema.Column{APIKeysColumns[9]},
|
||||
Columns: []*schema.Column{APIKeysColumns[12]},
|
||||
RefColumns: []*schema.Column{GroupsColumns[0]},
|
||||
OnDelete: schema.SetNull,
|
||||
},
|
||||
{
|
||||
Symbol: "api_keys_users_api_keys",
|
||||
Columns: []*schema.Column{APIKeysColumns[10]},
|
||||
Columns: []*schema.Column{APIKeysColumns[13]},
|
||||
RefColumns: []*schema.Column{UsersColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
},
|
||||
@@ -46,12 +49,12 @@ var (
|
||||
{
|
||||
Name: "apikey_user_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[10]},
|
||||
Columns: []*schema.Column{APIKeysColumns[13]},
|
||||
},
|
||||
{
|
||||
Name: "apikey_group_id",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[9]},
|
||||
Columns: []*schema.Column{APIKeysColumns[12]},
|
||||
},
|
||||
{
|
||||
Name: "apikey_status",
|
||||
@@ -63,6 +66,16 @@ var (
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[3]},
|
||||
},
|
||||
{
|
||||
Name: "apikey_quota_quota_used",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[9], APIKeysColumns[10]},
|
||||
},
|
||||
{
|
||||
Name: "apikey_expires_at",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{APIKeysColumns[11]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// AccountsColumns holds the columns for the "accounts" table.
|
||||
|
||||
Reference in New Issue
Block a user