From 00c9a3a8c76882c0cd94d1f38c8dcc30f6cffeaf Mon Sep 17 00:00:00 2001 From: renothing Date: Wed, 3 Jul 2019 09:40:57 +0800 Subject: [PATCH] fix wrong email when use gitea as OAuth2 provider when you use gitea as OAuth2 provider, the /api/v1/user should return user primary email as identifier, which is unique in OAuth2 clients. this patch use convert.ToUser replace all u.APIFormat in api requests, return primary email when caller is yourself or admin. --- models/user.go | 8 ++++---- routers/api/v1/admin/user.go | 7 +++---- routers/api/v1/convert/convert.go | 9 +++++++-- routers/api/v1/org/member.go | 3 ++- routers/api/v1/org/team.go | 4 ++-- routers/api/v1/repo/collaborators.go | 3 ++- routers/api/v1/repo/hook.go | 4 ++-- routers/api/v1/repo/star.go | 3 ++- routers/api/v1/repo/subscriber.go | 3 ++- routers/api/v1/user/follower.go | 3 ++- routers/api/v1/user/key.go | 4 ++-- routers/api/v1/user/user.go | 8 ++------ 12 files changed, 32 insertions(+), 27 deletions(-) diff --git a/models/user.go b/models/user.go index aa3e527cd58a..1f684a594045 100644 --- a/models/user.go +++ b/models/user.go @@ -204,9 +204,9 @@ func (u *User) UpdateTheme(themeName string) error { return UpdateUserCols(u, "theme") } -// getEmail returns an noreply email, if the user has set to keep his +// GetEmail returns an noreply email, if the user has set to keep his // email address private, otherwise the primary email address. -func (u *User) getEmail() string { +func (u *User) GetEmail() string { if u.KeepEmailPrivate { return fmt.Sprintf("%s@%s", u.LowerName, setting.Service.NoReplyAddress) } @@ -219,7 +219,7 @@ func (u *User) APIFormat() *api.User { ID: u.ID, UserName: u.Name, FullName: u.FullName, - Email: u.getEmail(), + Email: u.GetEmail(), AvatarURL: u.AvatarLink(), Language: u.Language, IsAdmin: u.IsAdmin, @@ -434,7 +434,7 @@ func (u *User) GetFollowing(page int) ([]*User, error) { func (u *User) NewGitSig() *git.Signature { return &git.Signature{ Name: u.GitName(), - Email: u.getEmail(), + Email: u.GetEmail(), When: time.Now(), } } diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 6dc3b0325b1e..f4b694aa2287 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -91,8 +91,7 @@ func CreateUser(ctx *context.APIContext, form api.CreateUserOption) { if form.SendNotify && setting.MailService != nil { models.SendRegisterNotifyMail(ctx.Context.Context, u) } - - ctx.JSON(201, u.APIFormat()) + ctx.JSON(201, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin)) } // EditUser api for modifying a user's information @@ -181,7 +180,7 @@ func EditUser(ctx *context.APIContext, form api.EditUserOption) { } log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name) - ctx.JSON(200, u.APIFormat()) + ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin)) } // DeleteUser api for deleting a user @@ -326,7 +325,7 @@ func GetAllUsers(ctx *context.APIContext) { results := make([]*api.User, len(users)) for i := range users { - results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) + results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User.IsAdmin) } ctx.JSON(200, &results) diff --git a/routers/api/v1/convert/convert.go b/routers/api/v1/convert/convert.go index f1cb23de4378..d2691f823808 100644 --- a/routers/api/v1/convert/convert.go +++ b/routers/api/v1/convert/convert.go @@ -229,7 +229,7 @@ func ToTeam(team *models.Team) *api.Team { } // ToUser convert models.User to api.User -func ToUser(user *models.User, signed, admin bool) *api.User { +func ToUser(user *models.User, signed, authed bool) *api.User { result := &api.User{ ID: user.ID, UserName: user.Name, @@ -239,7 +239,12 @@ func ToUser(user *models.User, signed, admin bool) *api.User { LastLogin: user.LastLoginUnix.AsTime(), Created: user.CreatedUnix.AsTime(), } - if signed && (!user.KeepEmailPrivate || admin) { + // hide primary email if API caller isn't user itself or an admin + if !signed { + result.Email = "" + } else if user.KeepEmailPrivate && !authed { + result.Email = user.GetEmail() + } else { result.Email = user.Email } return result diff --git a/routers/api/v1/org/member.go b/routers/api/v1/org/member.go index ad60dfbda5a3..4ada2d6ef688 100644 --- a/routers/api/v1/org/member.go +++ b/routers/api/v1/org/member.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/routers/api/v1/convert" "code.gitea.io/gitea/routers/api/v1/user" ) @@ -46,7 +47,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) { apiMembers := make([]*api.User, len(members)) for i, member := range members { - apiMembers[i] = member.APIFormat() + apiMembers[i] = convert.ToUser(member, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) } ctx.JSON(200, apiMembers) } diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 40b6e008b9db..59a000b67096 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -257,7 +257,7 @@ func GetTeamMembers(ctx *context.APIContext) { } members := make([]*api.User, len(team.Members)) for i, member := range team.Members { - members[i] = member.APIFormat() + members[i] = convert.ToUser(member, ctx.IsSigned, ctx.User.IsAdmin) } ctx.JSON(200, members) } @@ -288,7 +288,7 @@ func GetTeamMember(ctx *context.APIContext) { if ctx.Written() { return } - ctx.JSON(200, u.APIFormat()) + ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin)) } // AddTeamMember api for add a member to a team diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go index 98daf2c9d5ca..3ba03e054cf5 100644 --- a/routers/api/v1/repo/collaborators.go +++ b/routers/api/v1/repo/collaborators.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/routers/api/v1/convert" ) // ListCollaborators list a repository's collaborators @@ -42,7 +43,7 @@ func ListCollaborators(ctx *context.APIContext) { } users := make([]*api.User, len(collaborators)) for i, collaborator := range collaborators { - users[i] = collaborator.APIFormat() + users[i] = convert.ToUser(collaborator.User, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) } ctx.JSON(200, users) } diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index b35a10ac3d07..5c71262560bc 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -130,8 +130,8 @@ func TestHook(ctx *context.APIContext) { convert.ToCommit(ctx.Repo.Repository, ctx.Repo.Commit), }, Repo: ctx.Repo.Repository.APIFormat(models.AccessModeNone), - Pusher: ctx.User.APIFormat(), - Sender: ctx.User.APIFormat(), + Pusher: convert.ToUser(ctx.User, ctx.IsSigned, false), + Sender: convert.ToUser(ctx.User, ctx.IsSigned, false), }); err != nil { ctx.Error(500, "PrepareWebhook: ", err) return diff --git a/routers/api/v1/repo/star.go b/routers/api/v1/repo/star.go index 046142252b4a..1b2ef0b027d2 100644 --- a/routers/api/v1/repo/star.go +++ b/routers/api/v1/repo/star.go @@ -8,6 +8,7 @@ import ( "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/routers/api/v1/convert" ) // ListStargazers list a repository's stargazers @@ -38,7 +39,7 @@ func ListStargazers(ctx *context.APIContext) { } users := make([]*api.User, len(stargazers)) for i, stargazer := range stargazers { - users[i] = stargazer.APIFormat() + users[i] = convert.ToUser(stargazer, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) } ctx.JSON(200, users) } diff --git a/routers/api/v1/repo/subscriber.go b/routers/api/v1/repo/subscriber.go index b7d329dc7808..ec0ea6dadab0 100644 --- a/routers/api/v1/repo/subscriber.go +++ b/routers/api/v1/repo/subscriber.go @@ -8,6 +8,7 @@ import ( "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/routers/api/v1/convert" ) // ListSubscribers list a repo's subscribers (i.e. watchers) @@ -38,7 +39,7 @@ func ListSubscribers(ctx *context.APIContext) { } users := make([]*api.User, len(subscribers)) for i, subscriber := range subscribers { - users[i] = subscriber.APIFormat() + users[i] = convert.ToUser(subscriber, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) } ctx.JSON(200, users) } diff --git a/routers/api/v1/user/follower.go b/routers/api/v1/user/follower.go index 453f73137d96..078f30af3ccb 100644 --- a/routers/api/v1/user/follower.go +++ b/routers/api/v1/user/follower.go @@ -9,12 +9,13 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/routers/api/v1/convert" ) func responseAPIUsers(ctx *context.APIContext, users []*models.User) { apiUsers := make([]*api.User, len(users)) for i := range users { - apiUsers[i] = users[i].APIFormat() + apiUsers[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) } ctx.JSON(200, &apiUsers) } diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index 286f9ae4c349..e3d7aa4b3e10 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -22,13 +22,13 @@ func appendPrivateInformation(apiKey *api.PublicKey, key *models.PublicKey, defa apiKey.KeyType = "user" if defaultUser.ID == key.OwnerID { - apiKey.Owner = defaultUser.APIFormat() + apiKey.Owner = convert.ToUser(defaultUser, true, true) } else { user, err := models.GetUserByID(key.OwnerID) if err != nil { return apiKey, err } - apiKey.Owner = user.APIFormat() + apiKey.Owner = convert.ToUser(user, true, true) } } else { apiKey.KeyType = "unknown" diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 8d05a671850a..fc3b7a816036 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -104,11 +104,7 @@ func GetInfo(ctx *context.APIContext) { return } - // Hide user e-mail when API caller isn't signed in. - if !ctx.IsSigned { - u.Email = "" - } - ctx.JSON(200, u.APIFormat()) + ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.ID == u.ID || ctx.User.IsAdmin)) } // GetAuthenticatedUser get current user's information @@ -121,7 +117,7 @@ func GetAuthenticatedUser(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/User" - ctx.JSON(200, ctx.User.APIFormat()) + ctx.JSON(200, convert.ToUser(ctx.User, ctx.IsSigned, ctx.User != nil)) } // GetUserHeatmapData is the handler to get a users heatmap