fix: P1-02 OAuth context propagation and P1-16 AuthProvider double-check

P1-02: OAuth ExchangeCode and GetUserInfo now accept context parameter
       to properly propagate request context to HTTP calls
P1-16: AuthProvider isAuthenticated now uses single source of truth
       (effectiveUser !== null) instead of double-checking both
       React state and module-level function
This commit is contained in:
2026-04-18 19:40:54 +08:00
parent e1e423008e
commit 61c19e54ac
5 changed files with 19 additions and 21 deletions

View File

@@ -63,10 +63,10 @@ type OAuthManager interface {
GetAuthURL(provider OAuthProvider, state string) (string, error)
// ExchangeCode 换取访问令牌
ExchangeCode(provider OAuthProvider, code string) (*OAuthToken, error)
ExchangeCode(ctx context.Context, provider OAuthProvider, code string) (*OAuthToken, error)
// GetUserInfo 获取用户信息
GetUserInfo(provider OAuthProvider, token *OAuthToken) (*OAuthUser, error)
GetUserInfo(ctx context.Context, provider OAuthProvider, token *OAuthToken) (*OAuthUser, error)
// ValidateToken 验证令牌
ValidateToken(token string) (bool, error)
@@ -203,14 +203,12 @@ func (m *DefaultOAuthManager) GetAuthURL(provider OAuthProvider, state string) (
}
// ExchangeCode 换取访问令牌(使用真实 provider 实现)
func (m *DefaultOAuthManager) ExchangeCode(provider OAuthProvider, code string) (*OAuthToken, error) {
func (m *DefaultOAuthManager) ExchangeCode(ctx context.Context, provider OAuthProvider, code string) (*OAuthToken, error) {
entry, ok := m.entries[provider]
if !ok {
return nil, ErrOAuthProviderNotSupported
}
ctx := context.Background()
switch provider {
case OAuthProviderGoogle:
if entry.google != nil {
@@ -302,14 +300,12 @@ func (m *DefaultOAuthManager) ExchangeCode(provider OAuthProvider, code string)
}
// GetUserInfo 获取用户信息(使用真实 provider 实现)
func (m *DefaultOAuthManager) GetUserInfo(provider OAuthProvider, token *OAuthToken) (*OAuthUser, error) {
func (m *DefaultOAuthManager) GetUserInfo(ctx context.Context, provider OAuthProvider, token *OAuthToken) (*OAuthUser, error) {
entry, ok := m.entries[provider]
if !ok {
return nil, ErrOAuthProviderNotSupported
}
ctx := context.Background()
switch provider {
case OAuthProviderGoogle:
if entry.google != nil {
@@ -448,8 +444,9 @@ func (m *DefaultOAuthManager) ValidateToken(token string) (bool, error) {
}
// 尝试任一 provider 的 userinfo 端点验证
tokenObj := &OAuthToken{AccessToken: token}
ctx := context.Background()
for _, p := range providers {
if _, err := m.GetUserInfo(p.Provider, tokenObj); err == nil {
if _, err := m.GetUserInfo(ctx, p.Provider, tokenObj); err == nil {
return true, nil
}
}
@@ -469,7 +466,8 @@ func (m *DefaultOAuthManager) ValidateTokenWithProvider(provider OAuthProvider,
// 通过 provider 的 userinfo 端点验证 token
tokenObj := &OAuthToken{AccessToken: token}
_, err := m.GetUserInfo(provider, tokenObj)
ctx := context.Background()
_, err := m.GetUserInfo(ctx, provider, tokenObj)
if err != nil {
return false, err
}

View File

@@ -137,7 +137,7 @@ func TestDefaultOAuthManager_ExchangeCode(t *testing.T) {
m := NewOAuthManager()
// Test non-existent provider
_, err := m.ExchangeCode(OAuthProviderGoogle, "test-code")
_, err := m.ExchangeCode(context.Background(), OAuthProviderGoogle, "test-code")
if err != ErrOAuthProviderNotSupported {
t.Errorf("Expected ErrOAuthProviderNotSupported, got %v", err)
}
@@ -148,7 +148,7 @@ func TestDefaultOAuthManager_GetUserInfo(t *testing.T) {
// Test non-existent provider
token := &OAuthToken{AccessToken: "test-token"}
_, err := m.GetUserInfo(OAuthProviderGoogle, token)
_, err := m.GetUserInfo(context.Background(), OAuthProviderGoogle, token)
if err != ErrOAuthProviderNotSupported {
t.Errorf("Expected ErrOAuthProviderNotSupported, got %v", err)
}
@@ -546,7 +546,7 @@ func TestOAuthManager_ExchangeCode_Errors(t *testing.T) {
})
// ExchangeCode should attempt HTTP call and fail
_, err := m.ExchangeCode(OAuthProviderGoogle, "test-code")
_, err := m.ExchangeCode(context.Background(), OAuthProviderGoogle, "test-code")
// We expect an error because there's no mock server
if err == nil {
t.Log("ExchangeCode() unexpectedly succeeded - real network may be available")
@@ -565,7 +565,7 @@ func TestOAuthManager_GetUserInfo_Errors(t *testing.T) {
})
token := &OAuthToken{AccessToken: "test-token"}
_, err := m.GetUserInfo(OAuthProviderGoogle, token)
_, err := m.GetUserInfo(context.Background(), OAuthProviderGoogle, token)
// We expect an error because there's no mock server
if err == nil {
t.Log("GetUserInfo() unexpectedly succeeded - real network may be available")