mirror of
https://github.com/EZ-Api/ez-api.git
synced 2026-01-13 17:47:51 +00:00
Add `POST /admin/masters/{id}/keys` allowing admins to issue child keys
on behalf of a master. Introduce an `issued_by` field in the Key model
to audit whether a key was issued by the master or an admin.
Refactor master service to use typed errors for consistent HTTP status
mapping and ensure validation logic (active status, group check) is
shared.
66 lines
3.3 KiB
Go
66 lines
3.3 KiB
Go
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Admin is not a database model. It's configured via environment variables.
|
|
|
|
// Master represents a tenant account.
|
|
type Master struct {
|
|
gorm.Model
|
|
Name string `gorm:"size:255" json:"name"`
|
|
MasterKey string `gorm:"size:255" json:"-"` // bcrypt hash of master key
|
|
MasterKeyDigest string `gorm:"size:64;uniqueIndex" json:"-"` // sha256 digest for lookup
|
|
Group string `gorm:"size:100;default:'default'" json:"group"` // routing group
|
|
Epoch int64 `gorm:"default:1" json:"epoch"` // used for revocation/rotation
|
|
Status string `gorm:"size:50;default:'active'" json:"status"` // active, suspended
|
|
MaxChildKeys int `gorm:"default:5" json:"max_child_keys"`
|
|
GlobalQPS int `gorm:"default:3" json:"global_qps"`
|
|
}
|
|
|
|
// Key represents a child access token issued by a Master.
|
|
type Key struct {
|
|
gorm.Model
|
|
MasterID uint `gorm:"not null;index" json:"master_id"`
|
|
KeySecret string `gorm:"size:255;column:key_secret" json:"-"` // bcrypt hash of child key
|
|
TokenHash string `gorm:"size:64;uniqueIndex" json:"token_hash"` // sha256 digest of child key
|
|
Group string `gorm:"size:100;default:'default'" json:"group"` // routing group
|
|
Scopes string `gorm:"size:1024" json:"scopes"` // Comma-separated scopes
|
|
IssuedAtEpoch int64 `gorm:"not null" json:"issued_at_epoch"` // copy of master epoch at issuance
|
|
Status string `gorm:"size:50;default:'active'" json:"status"` // active, suspended
|
|
IssuedBy string `gorm:"size:20;default:'master'" json:"issued_by"`
|
|
}
|
|
|
|
// Provider remains the same.
|
|
type Provider struct {
|
|
gorm.Model
|
|
Name string `gorm:"not null" json:"name"`
|
|
Type string `gorm:"not null" json:"type"` // openai, anthropic, etc.
|
|
BaseURL string `json:"base_url"`
|
|
APIKey string `json:"api_key"`
|
|
GoogleProject string `gorm:"size:128" json:"google_project,omitempty"`
|
|
GoogleLocation string `gorm:"size:64" json:"google_location,omitempty"`
|
|
Group string `gorm:"default:'default'" json:"group"` // routing group/tier
|
|
Models string `json:"models"` // comma-separated list of supported models (e.g. "gpt-4,gpt-3.5-turbo")
|
|
Status string `gorm:"size:50;default:'active'" json:"status"` // active, auto_disabled, manual_disabled
|
|
AutoBan bool `gorm:"default:true" json:"auto_ban"` // whether DP-triggered disable is allowed
|
|
BanReason string `gorm:"size:255" json:"ban_reason"` // reason for current disable
|
|
BanUntil *time.Time `json:"ban_until"` // optional TTL for disable
|
|
}
|
|
|
|
// Model remains the same.
|
|
type Model struct {
|
|
gorm.Model
|
|
Name string `gorm:"uniqueIndex;not null" json:"name"`
|
|
ContextWindow int `json:"context_window"`
|
|
CostPerToken float64 `json:"cost_per_token"`
|
|
SupportsVision bool `json:"supports_vision"`
|
|
SupportsFunctions bool `json:"supports_functions"`
|
|
SupportsToolChoice bool `json:"supports_tool_choice"`
|
|
SupportsFIM bool `json:"supports_fim"`
|
|
MaxOutputTokens int `json:"max_output_tokens"`
|
|
}
|