Close profile identity and avatar loop

This commit is contained in:
IanShaw027
2026-04-21 00:11:03 +08:00
parent f73117f9b1
commit 9204145746
14 changed files with 801 additions and 35 deletions

View File

@@ -92,6 +92,12 @@ func (s *userHandlerRepoStub) RemoveGroupFromAllowedGroups(context.Context, int6
func (s *userHandlerRepoStub) AddGroupToAllowedGroups(context.Context, int64, int64) error {
return nil
}
func (s *userHandlerRepoStub) GetLatestUsedAtByUserIDs(context.Context, []int64) (map[int64]*time.Time, error) {
return map[int64]*time.Time{}, nil
}
func (s *userHandlerRepoStub) GetLatestUsedAtByUserID(context.Context, int64) (*time.Time, error) {
return nil, nil
}
func (s *userHandlerRepoStub) RemoveGroupFromUserAllowedGroups(context.Context, int64, int64) error {
return nil
}
@@ -230,6 +236,79 @@ func TestUserHandlerGetProfileReturnsIdentitySummaries(t *testing.T) {
require.Contains(t, resp.Data.Identities.WeChat.BindStartPath, "/api/v1/auth/oauth/wechat/start")
}
func TestUserHandlerGetProfileReturnsLegacyCompatibilityFields(t *testing.T) {
gin.SetMode(gin.TestMode)
verifiedAt := time.Date(2026, 4, 20, 8, 30, 0, 0, time.UTC)
repo := &userHandlerRepoStub{
user: &service.User{
ID: 21,
Email: "legacy-profile@example.com",
Username: "linuxdo-handle",
Role: service.RoleUser,
Status: service.StatusActive,
AvatarURL: "https://cdn.example.com/linuxdo.png",
AvatarSource: "remote_url",
},
identities: []service.UserAuthIdentityRecord{
{
ProviderType: "linuxdo",
ProviderKey: "linuxdo",
ProviderSubject: "linuxdo-subject-21",
VerifiedAt: &verifiedAt,
Metadata: map[string]any{
"username": "linuxdo-handle",
},
},
},
}
handler := NewUserHandler(service.NewUserService(repo, nil, nil, nil), nil, nil)
recorder := httptest.NewRecorder()
c, _ := gin.CreateTestContext(recorder)
c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/user/profile", nil)
c.Set(string(middleware2.ContextKeyUser), middleware2.AuthSubject{UserID: 21})
handler.GetProfile(c)
require.Equal(t, http.StatusOK, recorder.Code)
var resp struct {
Code int `json:"code"`
Data map[string]any `json:"data"`
}
require.NoError(t, json.Unmarshal(recorder.Body.Bytes(), &resp))
require.Equal(t, 0, resp.Code)
require.Equal(t, true, resp.Data["email_bound"])
require.Equal(t, true, resp.Data["linuxdo_bound"])
require.Equal(t, false, resp.Data["oidc_bound"])
require.Equal(t, false, resp.Data["wechat_bound"])
require.Equal(t, "https://cdn.example.com/linuxdo.png", resp.Data["avatar_url"])
authBindings, ok := resp.Data["auth_bindings"].(map[string]any)
require.True(t, ok)
linuxdoBinding, ok := authBindings["linuxdo"].(map[string]any)
require.True(t, ok)
require.Equal(t, true, linuxdoBinding["bound"])
require.Equal(t, "linuxdo", linuxdoBinding["provider"])
identityBindings, ok := resp.Data["identity_bindings"].(map[string]any)
require.True(t, ok)
emailBinding, ok := identityBindings["email"].(map[string]any)
require.True(t, ok)
require.Equal(t, true, emailBinding["bound"])
avatarSource, ok := resp.Data["avatar_source"].(map[string]any)
require.True(t, ok)
require.Equal(t, "linuxdo", avatarSource["provider"])
profileSources, ok := resp.Data["profile_sources"].(map[string]any)
require.True(t, ok)
usernameSource, ok := profileSources["username"].(map[string]any)
require.True(t, ok)
require.Equal(t, "linuxdo", usernameSource["provider"])
}
func TestUserHandlerStartIdentityBindingReturnsAuthorizeURL(t *testing.T) {
gin.SetMode(gin.TestMode)