fix(profile): stabilize binding compatibility and frontend checks

This commit is contained in:
IanShaw027
2026-04-22 14:57:47 +08:00
parent 1aab084ecb
commit ca4e38aa01
30 changed files with 1072 additions and 97 deletions

View File

@@ -249,7 +249,7 @@ func (h *UserHandler) UnbindIdentity(c *gin.Context) {
return
}
updatedUser, err := h.userService.UnbindUserAuthProvider(
updatedUser, unbound, err := h.userService.UnbindUserAuthProviderWithResult(
c.Request.Context(),
subject.UserID,
c.Param("provider"),
@@ -258,7 +258,7 @@ func (h *UserHandler) UnbindIdentity(c *gin.Context) {
response.ErrorFrom(c, err)
return
}
if h.authService != nil {
if unbound && h.authService != nil {
if err := h.authService.RevokeAllUserTokens(c.Request.Context(), subject.UserID); err != nil {
response.ErrorFrom(c, err)
return
@@ -512,7 +512,7 @@ func inferUserProfileSources(user *service.User, identities service.UserIdentity
var avatarSource *userProfileSourceContext
avatarValue := strings.TrimSpace(user.AvatarURL)
for _, summary := range thirdParty {
if avatarValue != "" && avatarValue == strings.TrimSpace(summary.DisplayName) {
if avatarValue != "" && avatarValue == strings.TrimSpace(summary.AvatarURL) {
avatarSource = buildUserProfileSourceContext(summary.Provider)
break
}

View File

@@ -636,6 +636,50 @@ func TestUserHandlerUnbindIdentityRevokesAllUserSessionsWhenAuthServiceConfigure
require.Equal(t, int64(5), repo.user.TokenVersion)
}
func TestUserHandlerUnbindIdentityDoesNotRevokeSessionsWhenNothingWasUnbound(t *testing.T) {
gin.SetMode(gin.TestMode)
repo := &userHandlerRepoStub{
user: &service.User{
ID: 24,
Email: "identity@example.com",
Username: "identity-user",
Role: service.RoleUser,
Status: service.StatusActive,
TokenVersion: 4,
},
identities: []service.UserAuthIdentityRecord{
{
ProviderType: "email",
ProviderKey: "email",
ProviderSubject: "identity@example.com",
},
},
}
refreshTokenCache := &userHandlerRefreshTokenCacheStub{}
cfg := &config.Config{
JWT: config.JWTConfig{
Secret: "test-secret",
ExpireHour: 1,
},
}
authService := service.NewAuthService(nil, repo, nil, refreshTokenCache, cfg, nil, nil, nil, nil, nil, nil)
handler := NewUserHandler(service.NewUserService(repo, nil, nil, nil), authService, nil, nil)
recorder := httptest.NewRecorder()
c, _ := gin.CreateTestContext(recorder)
c.Request = httptest.NewRequest(http.MethodDelete, "/api/v1/user/account-bindings/linuxdo", nil)
c.Set(string(middleware2.ContextKeyUser), middleware2.AuthSubject{UserID: 24})
c.Params = gin.Params{{Key: "provider", Value: "linuxdo"}}
handler.UnbindIdentity(c)
require.Equal(t, http.StatusOK, recorder.Code)
require.Empty(t, repo.unbound)
require.Empty(t, refreshTokenCache.revokedUserIDs)
require.Equal(t, int64(4), repo.user.TokenVersion)
}
func TestUserHandlerBindEmailIdentityRejectsWrongCurrentPasswordForBoundEmail(t *testing.T) {
gin.SetMode(gin.TestMode)
@@ -728,7 +772,7 @@ func TestUserHandlerStartIdentityBindingReturnsAuthorizeURL(t *testing.T) {
require.Equal(t, "wechat", resp.Data.Provider)
require.Equal(t, "GET", resp.Data.Method)
require.True(t, resp.Data.UseBrowserRedirect)
require.Contains(t, resp.Data.AuthorizeURL, "/api/v1/auth/oauth/wechat/start")
require.Contains(t, resp.Data.AuthorizeURL, "/api/v1/auth/oauth/wechat/bind/start")
require.Contains(t, resp.Data.AuthorizeURL, "intent=bind_current_user")
require.Contains(t, resp.Data.AuthorizeURL, "redirect=%2Fsettings%2Fprofile")
}