Merge remote-tracking branch 'upstream/main'
# Conflicts: # backend/internal/server/api_contract_test.go # backend/internal/service/setting_service.go # deploy/docker-compose.yml # frontend/src/components/layout/AppSidebar.vue # frontend/src/views/admin/SettingsView.vue
This commit is contained in:
@@ -50,14 +50,138 @@ func TestAPIContracts(t *testing.T) {
|
||||
"data": {
|
||||
"id": 1,
|
||||
"email": "alice@example.com",
|
||||
"email_bound": true,
|
||||
"username": "alice",
|
||||
"role": "user",
|
||||
"balance": 12.5,
|
||||
"concurrency": 5,
|
||||
"rpm_limit": 0,
|
||||
"status": "active",
|
||||
"allowed_groups": null,
|
||||
"created_at": "2025-01-02T03:04:05Z",
|
||||
"updated_at": "2025-01-02T03:04:05Z",
|
||||
"balance_notify_enabled": false,
|
||||
"balance_notify_threshold_type": "",
|
||||
"balance_notify_threshold": null,
|
||||
"balance_notify_extra_emails": null,
|
||||
"total_recharged": 0,
|
||||
"linuxdo_bound": false,
|
||||
"oidc_bound": false,
|
||||
"wechat_bound": false,
|
||||
"identities": {
|
||||
"email": {
|
||||
"provider": "email",
|
||||
"provider_key": "email",
|
||||
"bound": true,
|
||||
"bound_count": 1,
|
||||
"can_bind": false,
|
||||
"can_unbind": false,
|
||||
"display_name": "alice@example.com",
|
||||
"subject_hint": "a***e@example.com",
|
||||
"note_key": "profile.authBindings.notes.emailManagedFromProfile",
|
||||
"note": "Primary account email is managed from the profile form."
|
||||
},
|
||||
"linuxdo": {
|
||||
"provider": "linuxdo",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/linuxdo/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
},
|
||||
"oidc": {
|
||||
"provider": "oidc",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/oidc/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
},
|
||||
"wechat": {
|
||||
"provider": "wechat",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/wechat/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
}
|
||||
},
|
||||
"identity_bindings": {
|
||||
"email": {
|
||||
"provider": "email",
|
||||
"provider_key": "email",
|
||||
"bound": true,
|
||||
"bound_count": 1,
|
||||
"can_bind": false,
|
||||
"can_unbind": false,
|
||||
"display_name": "alice@example.com",
|
||||
"subject_hint": "a***e@example.com",
|
||||
"note_key": "profile.authBindings.notes.emailManagedFromProfile",
|
||||
"note": "Primary account email is managed from the profile form."
|
||||
},
|
||||
"linuxdo": {
|
||||
"provider": "linuxdo",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/linuxdo/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
},
|
||||
"oidc": {
|
||||
"provider": "oidc",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/oidc/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
},
|
||||
"wechat": {
|
||||
"provider": "wechat",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/wechat/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
}
|
||||
},
|
||||
"auth_bindings": {
|
||||
"email": {
|
||||
"provider": "email",
|
||||
"provider_key": "email",
|
||||
"bound": true,
|
||||
"bound_count": 1,
|
||||
"can_bind": false,
|
||||
"can_unbind": false,
|
||||
"display_name": "alice@example.com",
|
||||
"subject_hint": "a***e@example.com",
|
||||
"note_key": "profile.authBindings.notes.emailManagedFromProfile",
|
||||
"note": "Primary account email is managed from the profile form."
|
||||
},
|
||||
"linuxdo": {
|
||||
"provider": "linuxdo",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/linuxdo/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
},
|
||||
"oidc": {
|
||||
"provider": "oidc",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/oidc/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
},
|
||||
"wechat": {
|
||||
"provider": "wechat",
|
||||
"bound": false,
|
||||
"bound_count": 0,
|
||||
"can_bind": true,
|
||||
"can_unbind": false,
|
||||
"bind_start_path": "/api/v1/auth/oauth/wechat/bind/start?intent=bind_current_user&redirect=%2Fsettings%2Fprofile"
|
||||
}
|
||||
},
|
||||
"run_mode": "standard"
|
||||
}
|
||||
}`,
|
||||
@@ -204,18 +328,13 @@ func TestAPIContracts(t *testing.T) {
|
||||
"image_price_1k": null,
|
||||
"image_price_2k": null,
|
||||
"image_price_4k": null,
|
||||
"sora_image_price_360": null,
|
||||
"sora_image_price_540": null,
|
||||
"sora_storage_quota_bytes": 0,
|
||||
"sora_video_price_per_request": null,
|
||||
"sora_video_price_per_request_hd": null,
|
||||
"claude_code_only": false,
|
||||
"claude_code_only": false,
|
||||
"allow_messages_dispatch": false,
|
||||
"fallback_group_id": null,
|
||||
"fallback_group_id_on_invalid_request": null,
|
||||
"allow_messages_dispatch": false,
|
||||
"require_oauth_only": false,
|
||||
"require_privacy_set": false,
|
||||
"rpm_limit": 0,
|
||||
"created_at": "2025-01-02T03:04:05Z",
|
||||
"updated_at": "2025-01-02T03:04:05Z"
|
||||
}
|
||||
@@ -467,6 +586,28 @@ func TestAPIContracts(t *testing.T) {
|
||||
service.SettingKeyTurnstileSiteKey: "site-key",
|
||||
service.SettingKeyTurnstileSecretKey: "secret-key",
|
||||
|
||||
service.SettingKeyOIDCConnectEnabled: "false",
|
||||
service.SettingKeyOIDCConnectProviderName: "OIDC",
|
||||
service.SettingKeyOIDCConnectClientID: "",
|
||||
service.SettingKeyOIDCConnectIssuerURL: "",
|
||||
service.SettingKeyOIDCConnectDiscoveryURL: "",
|
||||
service.SettingKeyOIDCConnectAuthorizeURL: "",
|
||||
service.SettingKeyOIDCConnectTokenURL: "",
|
||||
service.SettingKeyOIDCConnectUserInfoURL: "",
|
||||
service.SettingKeyOIDCConnectJWKSURL: "",
|
||||
service.SettingKeyOIDCConnectScopes: "openid email profile",
|
||||
service.SettingKeyOIDCConnectRedirectURL: "",
|
||||
service.SettingKeyOIDCConnectFrontendRedirectURL: "/auth/oidc/callback",
|
||||
service.SettingKeyOIDCConnectTokenAuthMethod: "client_secret_post",
|
||||
service.SettingKeyOIDCConnectUsePKCE: "true",
|
||||
service.SettingKeyOIDCConnectValidateIDToken: "true",
|
||||
service.SettingKeyOIDCConnectAllowedSigningAlgs: "RS256,ES256,PS256",
|
||||
service.SettingKeyOIDCConnectClockSkewSeconds: "120",
|
||||
service.SettingKeyOIDCConnectRequireEmailVerified: "false",
|
||||
service.SettingKeyOIDCConnectUserInfoEmailPath: "",
|
||||
service.SettingKeyOIDCConnectUserInfoIDPath: "",
|
||||
service.SettingKeyOIDCConnectUserInfoUsernamePath: "",
|
||||
|
||||
service.SettingKeySiteName: "TianShuAPI",
|
||||
service.SettingKeySiteLogo: "",
|
||||
service.SettingKeySiteSubtitle: "Subtitle",
|
||||
@@ -474,13 +615,20 @@ func TestAPIContracts(t *testing.T) {
|
||||
service.SettingKeyContactInfo: "support",
|
||||
service.SettingKeyDocURL: "https://docs.example.com",
|
||||
|
||||
service.SettingKeyDefaultConcurrency: "5",
|
||||
service.SettingKeyDefaultBalance: "1.25",
|
||||
service.SettingKeyDefaultConcurrency: "5",
|
||||
service.SettingKeyDefaultBalance: "1.25",
|
||||
service.SettingKeyTableDefaultPageSize: "20",
|
||||
service.SettingKeyTablePageSizeOptions: "[10,20,50,100]",
|
||||
|
||||
service.SettingKeyOpsMonitoringEnabled: "false",
|
||||
service.SettingKeyOpsRealtimeMonitoringEnabled: "true",
|
||||
service.SettingKeyOpsQueryModeDefault: "auto",
|
||||
service.SettingKeyOpsMetricsIntervalSeconds: "60",
|
||||
service.SettingKeyOpsMonitoringEnabled: "false",
|
||||
service.SettingKeyOpsRealtimeMonitoringEnabled: "true",
|
||||
service.SettingKeyOpsQueryModeDefault: "auto",
|
||||
service.SettingKeyOpsMetricsIntervalSeconds: "60",
|
||||
service.SettingPaymentVisibleMethodAlipaySource: service.VisibleMethodSourceEasyPayAlipay,
|
||||
service.SettingPaymentVisibleMethodWxpaySource: service.VisibleMethodSourceOfficialWechat,
|
||||
service.SettingPaymentVisibleMethodAlipayEnabled: "true",
|
||||
service.SettingPaymentVisibleMethodWxpayEnabled: "false",
|
||||
"openai_advanced_scheduler_enabled": "true",
|
||||
})
|
||||
},
|
||||
method: http.MethodGet,
|
||||
@@ -508,10 +656,32 @@ func TestAPIContracts(t *testing.T) {
|
||||
"turnstile_enabled": true,
|
||||
"turnstile_site_key": "site-key",
|
||||
"turnstile_secret_key_configured": true,
|
||||
"linuxdo_connect_enabled": false,
|
||||
"linuxdo_connect_enabled": false,
|
||||
"linuxdo_connect_client_id": "",
|
||||
"linuxdo_connect_client_secret_configured": false,
|
||||
"linuxdo_connect_redirect_url": "",
|
||||
"oidc_connect_enabled": false,
|
||||
"oidc_connect_provider_name": "OIDC",
|
||||
"oidc_connect_client_id": "",
|
||||
"oidc_connect_client_secret_configured": false,
|
||||
"oidc_connect_issuer_url": "",
|
||||
"oidc_connect_discovery_url": "",
|
||||
"oidc_connect_authorize_url": "",
|
||||
"oidc_connect_token_url": "",
|
||||
"oidc_connect_userinfo_url": "",
|
||||
"oidc_connect_jwks_url": "",
|
||||
"oidc_connect_scopes": "openid email profile",
|
||||
"oidc_connect_redirect_url": "",
|
||||
"oidc_connect_frontend_redirect_url": "/auth/oidc/callback",
|
||||
"oidc_connect_token_auth_method": "client_secret_post",
|
||||
"oidc_connect_use_pkce": true,
|
||||
"oidc_connect_validate_id_token": true,
|
||||
"oidc_connect_allowed_signing_algs": "RS256,ES256,PS256",
|
||||
"oidc_connect_clock_skew_seconds": 120,
|
||||
"oidc_connect_require_email_verified": false,
|
||||
"oidc_connect_userinfo_email_path": "",
|
||||
"oidc_connect_userinfo_id_path": "",
|
||||
"oidc_connect_userinfo_username_path": "",
|
||||
"ops_monitoring_enabled": false,
|
||||
"ops_realtime_monitoring_enabled": true,
|
||||
"ops_query_mode_default": "auto",
|
||||
@@ -522,8 +692,34 @@ func TestAPIContracts(t *testing.T) {
|
||||
"api_base_url": "https://api.example.com",
|
||||
"contact_info": "support",
|
||||
"doc_url": "https://docs.example.com",
|
||||
"auth_source_default_email_balance": 0,
|
||||
"auth_source_default_email_concurrency": 5,
|
||||
"auth_source_default_email_subscriptions": [],
|
||||
"auth_source_default_email_grant_on_signup": false,
|
||||
"auth_source_default_email_grant_on_first_bind": false,
|
||||
"auth_source_default_linuxdo_balance": 0,
|
||||
"auth_source_default_linuxdo_concurrency": 5,
|
||||
"auth_source_default_linuxdo_subscriptions": [],
|
||||
"auth_source_default_linuxdo_grant_on_signup": false,
|
||||
"auth_source_default_linuxdo_grant_on_first_bind": false,
|
||||
"auth_source_default_oidc_balance": 0,
|
||||
"auth_source_default_oidc_concurrency": 5,
|
||||
"auth_source_default_oidc_subscriptions": [],
|
||||
"auth_source_default_oidc_grant_on_signup": false,
|
||||
"auth_source_default_oidc_grant_on_first_bind": false,
|
||||
"auth_source_default_wechat_balance": 0,
|
||||
"auth_source_default_wechat_concurrency": 5,
|
||||
"auth_source_default_wechat_subscriptions": [],
|
||||
"auth_source_default_wechat_grant_on_signup": false,
|
||||
"auth_source_default_wechat_grant_on_first_bind": false,
|
||||
"force_email_on_third_party_signup": false,
|
||||
"default_concurrency": 5,
|
||||
"default_balance": 1.25,
|
||||
"affiliate_rebate_rate": 20,
|
||||
"affiliate_rebate_freeze_hours": 0,
|
||||
"affiliate_rebate_duration_days": 0,
|
||||
"affiliate_rebate_per_invitee_cap": 0,
|
||||
"default_user_rpm_limit": 0,
|
||||
"default_subscriptions": [],
|
||||
"enable_model_fallback": false,
|
||||
"fallback_model_anthropic": "claude-3-5-sonnet-20241022",
|
||||
@@ -532,20 +728,274 @@ func TestAPIContracts(t *testing.T) {
|
||||
"fallback_model_openai": "gpt-4o",
|
||||
"enable_identity_patch": true,
|
||||
"identity_patch_prompt": "",
|
||||
"sora_client_enabled": false,
|
||||
"invitation_code_enabled": false,
|
||||
"home_content": "",
|
||||
"hide_ccs_import_button": false,
|
||||
"purchase_subscription_enabled": false,
|
||||
"purchase_subscription_url": "",
|
||||
"table_default_page_size": 20,
|
||||
"table_page_size_options": [10, 20, 50, 100],
|
||||
"min_claude_code_version": "",
|
||||
"max_claude_code_version": "",
|
||||
"allow_ungrouped_key_scheduling": false,
|
||||
"backend_mode_enabled": false,
|
||||
"enable_cch_signing": false,
|
||||
"enable_fingerprint_unification": true,
|
||||
"enable_metadata_passthrough": false,
|
||||
"web_search_emulation_enabled": false,
|
||||
"payment_visible_method_alipay_source": "easypay_alipay",
|
||||
"payment_visible_method_wxpay_source": "official_wxpay",
|
||||
"payment_visible_method_alipay_enabled": true,
|
||||
"payment_visible_method_wxpay_enabled": false,
|
||||
"openai_advanced_scheduler_enabled": true,
|
||||
"custom_menu_items": [],
|
||||
"custom_endpoints": [],
|
||||
"payment_enabled": false,
|
||||
"payment_min_amount": 0,
|
||||
"payment_max_amount": 0,
|
||||
"payment_daily_limit": 0,
|
||||
"payment_order_timeout_minutes": 0,
|
||||
"payment_max_pending_orders": 0,
|
||||
"payment_balance_disabled": false,
|
||||
"payment_balance_recharge_multiplier": 0,
|
||||
"payment_recharge_fee_rate": 0,
|
||||
"payment_load_balance_strategy": "",
|
||||
"payment_product_name_prefix": "",
|
||||
"payment_product_name_suffix": "",
|
||||
"payment_help_image_url": "",
|
||||
"payment_help_text": "",
|
||||
"payment_enabled_types": null,
|
||||
"payment_cancel_rate_limit_enabled": false,
|
||||
"payment_cancel_rate_limit_max": 0,
|
||||
"payment_cancel_rate_limit_window": 0,
|
||||
"payment_cancel_rate_limit_unit": "",
|
||||
"payment_cancel_rate_limit_window_mode": "",
|
||||
"balance_low_notify_enabled": false,
|
||||
"account_quota_notify_enabled": false,
|
||||
"balance_low_notify_threshold": 0,
|
||||
"balance_low_notify_recharge_url": "",
|
||||
"account_quota_notify_emails": [],
|
||||
"channel_monitor_enabled": true,
|
||||
"channel_monitor_default_interval_seconds": 60,
|
||||
"available_channels_enabled": false,
|
||||
"affiliate_enabled": false,
|
||||
"wechat_connect_enabled": false,
|
||||
"wechat_connect_app_id": "",
|
||||
"wechat_connect_app_secret_configured": false,
|
||||
"wechat_connect_mode": "open",
|
||||
"wechat_connect_open_enabled": false,
|
||||
"wechat_connect_open_app_id": "",
|
||||
"wechat_connect_open_app_secret_configured": false,
|
||||
"wechat_connect_mp_enabled": false,
|
||||
"wechat_connect_mp_app_id": "",
|
||||
"wechat_connect_mp_app_secret_configured": false,
|
||||
"wechat_connect_mobile_enabled": false,
|
||||
"wechat_connect_mobile_app_id": "",
|
||||
"wechat_connect_mobile_app_secret_configured": false,
|
||||
"wechat_connect_redirect_url": "",
|
||||
"wechat_connect_frontend_redirect_url": "/auth/wechat/callback",
|
||||
"wechat_connect_scopes": "snsapi_login"
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "GET /api/v1/admin/settings falls back to config oauth defaults",
|
||||
setup: func(t *testing.T, deps *contractDeps) {
|
||||
t.Helper()
|
||||
deps.cfg.OIDC = config.OIDCConnectConfig{
|
||||
Enabled: true,
|
||||
ProviderName: "ConfigOIDC",
|
||||
ClientID: "oidc-config-client",
|
||||
ClientSecret: "oidc-config-secret",
|
||||
IssuerURL: "https://issuer.example.com",
|
||||
RedirectURL: "https://api.example.com/api/v1/auth/oauth/oidc/callback",
|
||||
FrontendRedirectURL: "/auth/oidc/callback",
|
||||
Scopes: "openid email profile",
|
||||
TokenAuthMethod: "client_secret_post",
|
||||
UsePKCE: true,
|
||||
ValidateIDToken: true,
|
||||
AllowedSigningAlgs: "RS256,ES256,PS256",
|
||||
ClockSkewSeconds: 120,
|
||||
}
|
||||
deps.cfg.WeChat = config.WeChatConnectConfig{
|
||||
Enabled: true,
|
||||
OpenEnabled: true,
|
||||
OpenAppID: "wx-open-config",
|
||||
OpenAppSecret: "wx-open-secret",
|
||||
Mode: "open",
|
||||
Scopes: "snsapi_login",
|
||||
FrontendRedirectURL: "/auth/wechat/callback",
|
||||
}
|
||||
deps.settingRepo.SetAll(map[string]string{
|
||||
service.SettingKeyRegistrationEnabled: "true",
|
||||
service.SettingKeyEmailVerifyEnabled: "false",
|
||||
service.SettingKeyRegistrationEmailSuffixWhitelist: "[]",
|
||||
})
|
||||
},
|
||||
method: http.MethodGet,
|
||||
path: "/api/v1/admin/settings",
|
||||
wantStatus: http.StatusOK,
|
||||
wantJSON: `{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"registration_enabled": true,
|
||||
"email_verify_enabled": false,
|
||||
"registration_email_suffix_whitelist": [],
|
||||
"promo_code_enabled": true,
|
||||
"password_reset_enabled": false,
|
||||
"frontend_url": "",
|
||||
"invitation_code_enabled": false,
|
||||
"totp_enabled": false,
|
||||
"totp_encryption_key_configured": false,
|
||||
"smtp_host": "",
|
||||
"smtp_port": 587,
|
||||
"smtp_username": "",
|
||||
"smtp_password_configured": false,
|
||||
"smtp_from_email": "",
|
||||
"smtp_from_name": "",
|
||||
"smtp_use_tls": false,
|
||||
"turnstile_enabled": false,
|
||||
"turnstile_site_key": "",
|
||||
"turnstile_secret_key_configured": false,
|
||||
"linuxdo_connect_enabled": false,
|
||||
"linuxdo_connect_client_id": "",
|
||||
"linuxdo_connect_client_secret_configured": false,
|
||||
"linuxdo_connect_redirect_url": "",
|
||||
"oidc_connect_enabled": true,
|
||||
"oidc_connect_provider_name": "ConfigOIDC",
|
||||
"oidc_connect_client_id": "oidc-config-client",
|
||||
"oidc_connect_client_secret_configured": true,
|
||||
"oidc_connect_issuer_url": "https://issuer.example.com",
|
||||
"oidc_connect_discovery_url": "",
|
||||
"oidc_connect_authorize_url": "",
|
||||
"oidc_connect_token_url": "",
|
||||
"oidc_connect_userinfo_url": "",
|
||||
"oidc_connect_jwks_url": "",
|
||||
"oidc_connect_scopes": "openid email profile",
|
||||
"oidc_connect_redirect_url": "https://api.example.com/api/v1/auth/oauth/oidc/callback",
|
||||
"oidc_connect_frontend_redirect_url": "/auth/oidc/callback",
|
||||
"oidc_connect_token_auth_method": "client_secret_post",
|
||||
"oidc_connect_use_pkce": true,
|
||||
"oidc_connect_validate_id_token": true,
|
||||
"oidc_connect_allowed_signing_algs": "RS256,ES256,PS256",
|
||||
"oidc_connect_clock_skew_seconds": 120,
|
||||
"oidc_connect_require_email_verified": false,
|
||||
"oidc_connect_userinfo_email_path": "",
|
||||
"oidc_connect_userinfo_id_path": "",
|
||||
"oidc_connect_userinfo_username_path": "",
|
||||
"site_name": "Sub2API",
|
||||
"site_logo": "",
|
||||
"site_subtitle": "Subscription to API Conversion Platform",
|
||||
"api_base_url": "",
|
||||
"contact_info": "",
|
||||
"doc_url": "",
|
||||
"home_content": "",
|
||||
"hide_ccs_import_button": false,
|
||||
"purchase_subscription_enabled": false,
|
||||
"purchase_subscription_url": "",
|
||||
"table_default_page_size": 20,
|
||||
"table_page_size_options": [10, 20, 50],
|
||||
"custom_menu_items": [],
|
||||
"custom_endpoints": [],
|
||||
"default_concurrency": 0,
|
||||
"default_balance": 0,
|
||||
"affiliate_rebate_rate": 20,
|
||||
"affiliate_rebate_freeze_hours": 0,
|
||||
"affiliate_rebate_duration_days": 0,
|
||||
"affiliate_rebate_per_invitee_cap": 0,
|
||||
"default_user_rpm_limit": 0,
|
||||
"default_subscriptions": [],
|
||||
"enable_model_fallback": false,
|
||||
"fallback_model_anthropic": "claude-3-5-sonnet-20241022",
|
||||
"fallback_model_openai": "gpt-4o",
|
||||
"fallback_model_gemini": "gemini-2.5-pro",
|
||||
"fallback_model_antigravity": "gemini-2.5-pro",
|
||||
"enable_identity_patch": true,
|
||||
"identity_patch_prompt": "",
|
||||
"ops_monitoring_enabled": false,
|
||||
"ops_realtime_monitoring_enabled": true,
|
||||
"ops_query_mode_default": "auto",
|
||||
"ops_metrics_interval_seconds": 60,
|
||||
"min_claude_code_version": "",
|
||||
"max_claude_code_version": "",
|
||||
"allow_ungrouped_key_scheduling": false,
|
||||
"backend_mode_enabled": false,
|
||||
"enable_fingerprint_unification": true,
|
||||
"enable_metadata_passthrough": false,
|
||||
"custom_menu_items": [],
|
||||
"custom_endpoints": []
|
||||
"enable_cch_signing": false,
|
||||
"web_search_emulation_enabled": false,
|
||||
"payment_visible_method_alipay_source": "",
|
||||
"payment_visible_method_wxpay_source": "",
|
||||
"payment_visible_method_alipay_enabled": false,
|
||||
"payment_visible_method_wxpay_enabled": false,
|
||||
"openai_advanced_scheduler_enabled": false,
|
||||
"payment_enabled": false,
|
||||
"payment_min_amount": 0,
|
||||
"payment_max_amount": 0,
|
||||
"payment_daily_limit": 0,
|
||||
"payment_order_timeout_minutes": 0,
|
||||
"payment_max_pending_orders": 0,
|
||||
"payment_enabled_types": null,
|
||||
"payment_balance_disabled": false,
|
||||
"payment_balance_recharge_multiplier": 0,
|
||||
"payment_recharge_fee_rate": 0,
|
||||
"payment_load_balance_strategy": "",
|
||||
"payment_product_name_prefix": "",
|
||||
"payment_product_name_suffix": "",
|
||||
"payment_help_image_url": "",
|
||||
"payment_help_text": "",
|
||||
"payment_cancel_rate_limit_enabled": false,
|
||||
"payment_cancel_rate_limit_max": 0,
|
||||
"payment_cancel_rate_limit_window": 0,
|
||||
"payment_cancel_rate_limit_unit": "",
|
||||
"payment_cancel_rate_limit_window_mode": "",
|
||||
"balance_low_notify_enabled": false,
|
||||
"account_quota_notify_enabled": false,
|
||||
"balance_low_notify_threshold": 0,
|
||||
"balance_low_notify_recharge_url": "",
|
||||
"account_quota_notify_emails": [],
|
||||
"channel_monitor_enabled": true,
|
||||
"channel_monitor_default_interval_seconds": 60,
|
||||
"available_channels_enabled": false,
|
||||
"affiliate_enabled": false,
|
||||
"wechat_connect_enabled": true,
|
||||
"wechat_connect_app_id": "wx-open-config",
|
||||
"wechat_connect_app_secret_configured": true,
|
||||
"wechat_connect_mode": "open",
|
||||
"wechat_connect_open_enabled": true,
|
||||
"wechat_connect_open_app_id": "wx-open-config",
|
||||
"wechat_connect_open_app_secret_configured": true,
|
||||
"wechat_connect_mp_enabled": false,
|
||||
"wechat_connect_mp_app_id": "wx-open-config",
|
||||
"wechat_connect_mp_app_secret_configured": true,
|
||||
"wechat_connect_mobile_enabled": false,
|
||||
"wechat_connect_mobile_app_id": "wx-open-config",
|
||||
"wechat_connect_mobile_app_secret_configured": true,
|
||||
"wechat_connect_redirect_url": "",
|
||||
"wechat_connect_frontend_redirect_url": "/auth/wechat/callback",
|
||||
"wechat_connect_scopes": "snsapi_login",
|
||||
"auth_source_default_email_balance": 0,
|
||||
"auth_source_default_email_concurrency": 5,
|
||||
"auth_source_default_email_subscriptions": [],
|
||||
"auth_source_default_email_grant_on_signup": false,
|
||||
"auth_source_default_email_grant_on_first_bind": false,
|
||||
"auth_source_default_linuxdo_balance": 0,
|
||||
"auth_source_default_linuxdo_concurrency": 5,
|
||||
"auth_source_default_linuxdo_subscriptions": [],
|
||||
"auth_source_default_linuxdo_grant_on_signup": false,
|
||||
"auth_source_default_linuxdo_grant_on_first_bind": false,
|
||||
"auth_source_default_oidc_balance": 0,
|
||||
"auth_source_default_oidc_concurrency": 5,
|
||||
"auth_source_default_oidc_subscriptions": [],
|
||||
"auth_source_default_oidc_grant_on_signup": false,
|
||||
"auth_source_default_oidc_grant_on_first_bind": false,
|
||||
"auth_source_default_wechat_balance": 0,
|
||||
"auth_source_default_wechat_concurrency": 5,
|
||||
"auth_source_default_wechat_subscriptions": [],
|
||||
"auth_source_default_wechat_grant_on_signup": false,
|
||||
"auth_source_default_wechat_grant_on_first_bind": false,
|
||||
"force_email_on_third_party_signup": false
|
||||
}
|
||||
}`,
|
||||
},
|
||||
@@ -592,6 +1042,7 @@ func TestAPIContracts(t *testing.T) {
|
||||
type contractDeps struct {
|
||||
now time.Time
|
||||
router http.Handler
|
||||
cfg *config.Config
|
||||
apiKeyRepo *stubApiKeyRepo
|
||||
groupRepo *stubGroupRepo
|
||||
userSubRepo *stubUserSubscriptionRepo
|
||||
@@ -638,7 +1089,7 @@ func newContractDeps(t *testing.T) *contractDeps {
|
||||
RunMode: config.RunModeStandard,
|
||||
}
|
||||
|
||||
userService := service.NewUserService(userRepo, nil, nil)
|
||||
userService := service.NewUserService(userRepo, nil, nil, nil)
|
||||
apiKeyService := service.NewAPIKeyService(apiKeyRepo, userRepo, groupRepo, userSubRepo, nil, apiKeyCache, cfg)
|
||||
|
||||
usageRepo := newStubUsageLogRepo()
|
||||
@@ -653,11 +1104,11 @@ func newContractDeps(t *testing.T) *contractDeps {
|
||||
settingRepo := newStubSettingRepo()
|
||||
settingService := service.NewSettingService(settingRepo, cfg)
|
||||
|
||||
adminService := service.NewAdminService(userRepo, groupRepo, &accountRepo, nil, proxyRepo, apiKeyRepo, redeemRepo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
adminService := service.NewAdminService(userRepo, groupRepo, &accountRepo, proxyRepo, apiKeyRepo, redeemRepo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
authHandler := handler.NewAuthHandler(cfg, nil, userService, settingService, nil, redeemService, nil)
|
||||
apiKeyHandler := handler.NewAPIKeyHandler(apiKeyService)
|
||||
usageHandler := handler.NewUsageHandler(usageService, apiKeyService)
|
||||
adminSettingHandler := adminhandler.NewSettingHandler(settingService, nil, nil, nil, nil)
|
||||
adminSettingHandler := adminhandler.NewSettingHandler(settingService, nil, nil, nil, nil, nil)
|
||||
adminAccountHandler := adminhandler.NewAccountHandler(adminService, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
|
||||
jwtAuth := func(c *gin.Context) {
|
||||
@@ -712,6 +1163,7 @@ func newContractDeps(t *testing.T) *contractDeps {
|
||||
return &contractDeps{
|
||||
now: now,
|
||||
router: r,
|
||||
cfg: cfg,
|
||||
apiKeyRepo: apiKeyRepo,
|
||||
groupRepo: groupRepo,
|
||||
userSubRepo: userSubRepo,
|
||||
@@ -785,6 +1237,18 @@ func (r *stubUserRepo) Delete(ctx context.Context, id int64) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) GetUserAvatar(ctx context.Context, userID int64) (*service.UserAvatar, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) UpsertUserAvatar(ctx context.Context, userID int64, input service.UpsertUserAvatarInput) (*service.UserAvatar, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) DeleteUserAvatar(ctx context.Context, userID int64) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) List(ctx context.Context, params pagination.PaginationParams) ([]service.User, *pagination.PaginationResult, error) {
|
||||
return nil, nil, errors.New("not implemented")
|
||||
}
|
||||
@@ -821,6 +1285,26 @@ func (r *stubUserRepo) AddGroupToAllowedGroups(ctx context.Context, userID int64
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) ListUserAuthIdentities(ctx context.Context, userID int64) ([]service.UserAuthIdentityRecord, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) UnbindUserAuthProvider(context.Context, int64, string) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) GetLatestUsedAtByUserIDs(ctx context.Context, userIDs []int64) (map[int64]*time.Time, error) {
|
||||
return map[int64]*time.Time{}, nil
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) GetLatestUsedAtByUserID(ctx context.Context, userID int64) (*time.Time, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) UpdateUserLastActiveAt(ctx context.Context, userID int64, activeAt time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *stubUserRepo) UpdateTotpSecret(ctx context.Context, userID int64, encryptedSecret *string) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user