fix(client+server): OAuth login path now surfaces user identity in desktop TitleBar
Root cause of the recurring "I don't see the logged-in user info in the desktop client" complaint: the credentials-login path builds an mcpAuth record with email / displayName / role from the mcp-server /api/auth/login response and the TitleBar UserPill renders fine. But the OAuth-login path (the typical browser-redirect flow) only received an sk- API key in the callback query string — no user fields. So: status.user == null UserPill: if (!user) return null → blank space where the user pill should be. Fix on backend (heicode_oauth.go HeicodeOAuthAuthorize): - After issuing the sk- token, load the authenticated user from the session and embed email / name / role (root|admin|user) / channel_id / user_id as query params on the redirect URI. Fix on client (cc-haha/src/server/api/heicode-auth.ts handleOAuthCallback): - Read those query params (pickUserFromQuery), build an mcpAuth record (buildMcpAuthFromOAuthQuery), and pass it through loginAndActivate the same way the credentials path does. The accessToken slot holds the sk- key as a placeholder — OAuth flow doesn't deliver a refreshable JWT pair, and this mcpAuth exists purely to surface identity on the TitleBar. After this, OAuth-route users see the same gradient-avatar pill with their email / name / role badge that credentials-route users already see. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -85,6 +85,38 @@ func HeicodeOAuthAuthorize(c *gin.Context) {
|
||||
if providerID != "" {
|
||||
q.Set("provider_id", providerID)
|
||||
}
|
||||
|
||||
// Include the authenticated user's identity so the desktop client can
|
||||
// display it in the title bar / settings without making a separate
|
||||
// /api/user/self call (that endpoint requires a session cookie which the
|
||||
// desktop client doesn't have). This is the missing piece that left the
|
||||
// UserPill empty for OAuth-route logins.
|
||||
var user model.User
|
||||
if dbErr := model.DB.First(&user, userID).Error; dbErr == nil {
|
||||
if email := strings.TrimSpace(user.Email); email != "" {
|
||||
q.Set("email", email)
|
||||
}
|
||||
display := strings.TrimSpace(user.DisplayName)
|
||||
if display == "" {
|
||||
display = strings.TrimSpace(user.Username)
|
||||
}
|
||||
if display != "" {
|
||||
q.Set("name", display)
|
||||
}
|
||||
switch {
|
||||
case user.Role >= 100:
|
||||
q.Set("role", "root")
|
||||
case user.Role >= 10:
|
||||
q.Set("role", "admin")
|
||||
default:
|
||||
q.Set("role", "user")
|
||||
}
|
||||
if g := strings.TrimSpace(user.Group); g != "" {
|
||||
q.Set("channel_id", g)
|
||||
}
|
||||
q.Set("user_id", fmt.Sprintf("%d", userID))
|
||||
}
|
||||
|
||||
parsed.RawQuery = q.Encode()
|
||||
c.Redirect(http.StatusFound, parsed.String())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user