feat(api): add OAuth token fields and new provider types support

Add support for OAuth-based authentication with access/refresh tokens
and expiration tracking for API keys. Extend provider groups with
static headers configuration and headers profile options.

Changes include:
- Add AccessToken, RefreshToken, ExpiresAt, AccountID, ProjectID to APIKey model
- Add StaticHeaders and HeadersProfile to ProviderGroup model
- Add TokenRefresh configuration for background token management
- Support new provider types: ClaudeCode, Codex, GeminiCLI, Antigravity
- Update sync service to include new fields in provider snapshots
This commit is contained in:
zenfun
2025-12-28 02:49:54 +08:00
parent cca0802620
commit f0fe9f0dad
8 changed files with 132 additions and 22 deletions

View File

@@ -49,12 +49,20 @@ func (h *Handler) CreateAPIKey(c *gin.Context) {
}
key := model.APIKey{
GroupID: req.GroupID,
APIKey: apiKey,
Weight: normalizeWeight(req.Weight),
Status: status,
AutoBan: autoBan,
BanReason: strings.TrimSpace(req.BanReason),
GroupID: req.GroupID,
APIKey: apiKey,
AccessToken: strings.TrimSpace(req.AccessToken),
RefreshToken: strings.TrimSpace(req.RefreshToken),
AccountID: strings.TrimSpace(req.AccountID),
ProjectID: strings.TrimSpace(req.ProjectID),
Weight: normalizeWeight(req.Weight),
Status: status,
AutoBan: autoBan,
BanReason: strings.TrimSpace(req.BanReason),
}
if !req.ExpiresAt.IsZero() {
tu := req.ExpiresAt.UTC()
key.ExpiresAt = &tu
}
if !req.BanUntil.IsZero() {
tu := req.BanUntil.UTC()
@@ -180,6 +188,22 @@ func (h *Handler) UpdateAPIKey(c *gin.Context) {
if strings.TrimSpace(req.APIKey) != "" {
update["api_key"] = strings.TrimSpace(req.APIKey)
}
if strings.TrimSpace(req.AccessToken) != "" {
update["access_token"] = strings.TrimSpace(req.AccessToken)
}
if strings.TrimSpace(req.RefreshToken) != "" {
update["refresh_token"] = strings.TrimSpace(req.RefreshToken)
}
if !req.ExpiresAt.IsZero() {
tu := req.ExpiresAt.UTC()
update["expires_at"] = &tu
}
if strings.TrimSpace(req.AccountID) != "" {
update["account_id"] = strings.TrimSpace(req.AccountID)
}
if strings.TrimSpace(req.ProjectID) != "" {
update["project_id"] = strings.TrimSpace(req.ProjectID)
}
if req.Weight > 0 {
update["weight"] = normalizeWeight(req.Weight)
}
@@ -199,11 +223,17 @@ func (h *Handler) UpdateAPIKey(c *gin.Context) {
if req.BanUntil.IsZero() && strings.TrimSpace(req.Status) == "active" {
update["ban_until"] = nil
}
if req.GroupID != 0 || strings.TrimSpace(req.APIKey) != "" {
if req.GroupID != 0 || strings.TrimSpace(req.APIKey) != "" || strings.TrimSpace(req.AccessToken) != "" || strings.TrimSpace(req.RefreshToken) != "" {
nextKey := key
if v, ok := update["api_key"].(string); ok {
nextKey.APIKey = v
}
if v, ok := update["access_token"].(string); ok {
nextKey.AccessToken = v
}
if v, ok := update["refresh_token"].(string); ok {
nextKey.RefreshToken = v
}
if req.GroupID != 0 {
nextKey.GroupID = req.GroupID
}