yao/openapi/user/profile.go
Max 0d83faeeca Add Yao user ID support in OIDC and token generation
- Enhanced the SignIDToken method to include the original Yao user ID in the token claims, improving user identification.
- Updated the MakeOIDCUserInfo function to extract and set the Yao user ID from the user map, ensuring consistency in user information.
- Modified the OIDCUserInfo structure to include a field for Yao user ID, facilitating better integration with Yao-specific features.
- Adjusted the team invitation response to include the inviter's user ID, enhancing the invitation context.
2025-10-14 09:56:29 +08:00

152 lines
4.2 KiB
Go

package user
import (
"context"
"net/http"
"github.com/gin-gonic/gin"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/openapi/oauth"
oauthtypes "github.com/yaoapp/yao/openapi/oauth/types"
"github.com/yaoapp/yao/openapi/response"
)
// User Profile Management Handlers
// GinProfileGet handles GET /profile - Get current user profile
func GinProfileGet(c *gin.Context) {
// Get authorized user info
authInfo := oauth.GetAuthorizedInfo(c)
if authInfo == nil || authInfo.UserID == "" {
errorResp := &response.ErrorResponse{
Code: response.ErrInvalidClient.Code,
ErrorDescription: "User not authenticated",
}
response.RespondWithError(c, response.StatusUnauthorized, errorResp)
return
}
// Get user provider
userProvider, err := oauth.OAuth.GetUserProvider()
if err != nil {
log.Error("Failed to get user provider: %v", err)
errorResp := &response.ErrorResponse{
Code: response.ErrServerError.Code,
ErrorDescription: "Failed to get user provider",
}
response.RespondWithError(c, response.StatusInternalServerError, errorResp)
return
}
// Get user data with scopes
ctx := c.Request.Context()
if ctx == nil {
ctx = context.Background()
}
user, err := userProvider.GetUserWithScopes(ctx, authInfo.UserID)
if err != nil {
log.Error("Failed to get user profile: %v", err)
errorResp := &response.ErrorResponse{
Code: response.ErrServerError.Code,
ErrorDescription: "Failed to retrieve user profile",
}
response.RespondWithError(c, response.StatusInternalServerError, errorResp)
return
}
// Get Yao client config
yaoClientConfig := GetYaoClientConfig()
// Get or create subject
subject, err := oauth.OAuth.Subject(yaoClientConfig.ClientID, authInfo.UserID)
if err != nil {
log.Warn("Failed to get user subject: %s", err.Error())
subject = authInfo.UserID // Fallback to user ID
}
// Prepare OIDC user info (same format as login response)
oidcUserInfo := oauthtypes.MakeOIDCUserInfo(user)
oidcUserInfo.Sub = subject
oidcUserInfo.YaoUserID = authInfo.UserID
// Add team context if available from token
if authInfo.TeamID != "" {
// Get team details
team, err := userProvider.GetTeamByMember(ctx, authInfo.TeamID, authInfo.UserID)
if err == nil && team != nil {
// Add team info to OIDC user info
oidcUserInfo.YaoTeamID = authInfo.TeamID
teamInfo := &oauthtypes.OIDCTeamInfo{}
if teamIDVal := toString(team["team_id"]); teamIDVal != "" {
teamInfo.TeamID = teamIDVal
}
if logo := toString(team["logo"]); logo != "" {
teamInfo.Logo = logo
}
if name := toString(team["name"]); name != "" {
teamInfo.Name = name
}
if description := toString(team["description"]); description != "" {
teamInfo.Description = description
}
if ownerID := toString(team["owner_id"]); ownerID != "" {
teamInfo.OwnerID = ownerID
// Check if user is owner
if ownerID == authInfo.UserID {
isOwner := true
oidcUserInfo.YaoIsOwner = &isOwner
}
}
oidcUserInfo.YaoTeam = teamInfo
// Add tenant_id if available from the team
if tenantID := toString(team["tenant_id"]); tenantID != "" {
oidcUserInfo.YaoTenantID = tenantID
}
}
}
// Add type information
var typeID string
if authInfo.TeamID != "" {
// Team context - try to get team's type first
team, err := userProvider.GetTeamByMember(ctx, authInfo.TeamID, authInfo.UserID)
if err == nil && team != nil {
typeID = toString(team["type_id"])
}
}
// Fallback to user's type if no team type
if typeID == "" {
typeID = toString(user["type_id"])
}
if typeID != "" {
oidcUserInfo.YaoTypeID = typeID
// Get type details
typeInfo, err := userProvider.GetType(ctx, typeID)
if err == nil && typeInfo != nil {
typeDetails := &oauthtypes.OIDCTypeInfo{}
if typeIDVal := toString(typeInfo["type_id"]); typeIDVal != "" {
typeDetails.TypeID = typeIDVal
}
if name := toString(typeInfo["name"]); name != "" {
typeDetails.Name = name
}
if locale := toString(typeInfo["locale"]); locale != "" {
typeDetails.Locale = locale
}
oidcUserInfo.YaoType = typeDetails
}
}
// Convert to map for response
profileData := oidcUserInfo.Map()
// Return user profile
response.RespondWithSuccess(c, http.StatusOK, profileData)
}