Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestOpenAIOAuthService_ValidateCodexPersonalAccessToken(t *testing.T) {
|
||||
var gotAuthorization string
|
||||
var gotOriginator string
|
||||
var gotUserAgent string
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gotAuthorization = r.Header.Get("authorization")
|
||||
gotOriginator = r.Header.Get("originator")
|
||||
gotUserAgent = r.Header.Get("user-agent")
|
||||
w.Header().Set("content-type", "application/json")
|
||||
_, _ = w.Write([]byte(`{
|
||||
"email":"user@example.com",
|
||||
"chatgpt_user_id":"user-123",
|
||||
"chatgpt_account_id":"acct-123",
|
||||
"chatgpt_plan_type":"plus",
|
||||
"chatgpt_account_is_fedramp":true
|
||||
}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
originalURL := openAICodexPATWhoamiURL
|
||||
openAICodexPATWhoamiURL = server.URL
|
||||
defer func() { openAICodexPATWhoamiURL = originalURL }()
|
||||
|
||||
svc := NewOpenAIOAuthService(nil, nil)
|
||||
defer svc.Stop()
|
||||
|
||||
info, err := svc.ValidateCodexPersonalAccessToken(context.Background(), " at-test-token ", "")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "Bearer at-test-token", gotAuthorization)
|
||||
require.Equal(t, openai.CodexDefaultOriginator, gotOriginator)
|
||||
require.Equal(t, CodexCanonicalUserAgent(), gotUserAgent)
|
||||
require.Equal(t, OpenAIAuthModePersonalAccessToken, info.AuthMode)
|
||||
require.Equal(t, "user@example.com", info.Email)
|
||||
require.Equal(t, "user-123", info.ChatGPTUserID)
|
||||
require.Equal(t, "acct-123", info.ChatGPTAccountID)
|
||||
require.Equal(t, "plus", info.PlanType)
|
||||
require.True(t, info.ChatGPTAccountFedRAMP)
|
||||
require.Zero(t, info.ExpiresAt)
|
||||
require.Empty(t, info.RefreshToken)
|
||||
}
|
||||
|
||||
func TestOpenAIOAuthService_ValidateCodexPersonalAccessTokenRequiresATPrefix(t *testing.T) {
|
||||
svc := NewOpenAIOAuthService(nil, nil)
|
||||
defer svc.Stop()
|
||||
|
||||
_, err := svc.ValidateCodexPersonalAccessToken(context.Background(), "eyJ.jwt", "")
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "at-")
|
||||
}
|
||||
|
||||
func TestOpenAIOAuthService_BuildAccountCredentialsForPAT(t *testing.T) {
|
||||
svc := NewOpenAIOAuthService(nil, nil)
|
||||
defer svc.Stop()
|
||||
|
||||
credentials := svc.BuildAccountCredentials(&OpenAITokenInfo{
|
||||
AccessToken: "at-test-token",
|
||||
AuthMode: OpenAIAuthModePersonalAccessToken,
|
||||
Email: "user@example.com",
|
||||
ChatGPTAccountID: "acct-123",
|
||||
ChatGPTUserID: "user-123",
|
||||
ChatGPTAccountFedRAMP: true,
|
||||
PlanType: "plus",
|
||||
})
|
||||
|
||||
require.Equal(t, "at-test-token", credentials["access_token"])
|
||||
require.Equal(t, OpenAIAuthModePersonalAccessToken, credentials["auth_mode"])
|
||||
require.Equal(t, "personal_access_token", credentials["openai_auth_mode"])
|
||||
require.Equal(t, "Bearer", credentials["token_type"])
|
||||
require.Equal(t, true, credentials["chatgpt_account_is_fedramp"])
|
||||
require.NotContains(t, credentials, "expires_at")
|
||||
require.NotContains(t, credentials, "refresh_token")
|
||||
require.NotContains(t, credentials, "id_token")
|
||||
}
|
||||
|
||||
func TestNormalizeOpenAIPersonalAccessTokenCredentialsRemovesOAuthFields(t *testing.T) {
|
||||
account := &Account{
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeOAuth,
|
||||
Credentials: map[string]any{
|
||||
"auth_mode": "personal_access_token",
|
||||
},
|
||||
}
|
||||
credentials := map[string]any{
|
||||
"access_token": "at-test-token",
|
||||
"refresh_token": "stale-refresh-token",
|
||||
"id_token": "stale-id-token",
|
||||
"expires_at": "2026-01-01T00:00:00Z",
|
||||
"expires_in": 3600,
|
||||
"client_id": "stale-client",
|
||||
"model_mapping": map[string]any{"gpt-5": "gpt-5-codex"},
|
||||
"chatgpt_account_is_fedramp": true,
|
||||
"subscription_expires_at": "2026-12-31T00:00:00Z",
|
||||
"openai_usage_channel_fields": []any{"custom"},
|
||||
}
|
||||
|
||||
got := NormalizeOpenAIPersonalAccessTokenCredentials(account, nil, credentials)
|
||||
|
||||
require.Equal(t, "at-test-token", got["access_token"])
|
||||
require.Equal(t, OpenAIAuthModePersonalAccessToken, got["auth_mode"])
|
||||
require.Equal(t, "personal_access_token", got["openai_auth_mode"])
|
||||
require.Equal(t, "Bearer", got["token_type"])
|
||||
require.NotContains(t, got, "refresh_token")
|
||||
require.NotContains(t, got, "id_token")
|
||||
require.NotContains(t, got, "expires_at")
|
||||
require.NotContains(t, got, "expires_in")
|
||||
require.NotContains(t, got, "client_id")
|
||||
require.Equal(t, map[string]any{"gpt-5": "gpt-5-codex"}, got["model_mapping"])
|
||||
require.Equal(t, true, got["chatgpt_account_is_fedramp"])
|
||||
require.Equal(t, "2026-12-31T00:00:00Z", got["subscription_expires_at"])
|
||||
require.Equal(t, []any{"custom"}, got["openai_usage_channel_fields"])
|
||||
}
|
||||
Reference in New Issue
Block a user