Add ContextUser to http request context (#18798)

This PR adds a middleware which sets a ContextUser (like GetUserByParams before) in a single place which can be used by other methods. For routes which represent a repo or org the respective middlewares set the field too.

Also fix a bug in modules/context/org.go during refactoring.
This commit is contained in:
KN4CK3R 2022-03-26 10:04:22 +01:00 committed by GitHub
parent f36701c702
commit 59b867dc2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 247 additions and 323 deletions

View file

@ -8,7 +8,6 @@ package user
import (
"fmt"
"net/http"
"path"
"strings"
"code.gitea.io/gitea/models"
@ -24,121 +23,51 @@ import (
"code.gitea.io/gitea/routers/web/org"
)
// GetUserByName get user by name
func GetUserByName(ctx *context.Context, name string) *user_model.User {
user, err := user_model.GetUserByName(name)
if err != nil {
if user_model.IsErrUserNotExist(err) {
if redirectUserID, err := user_model.LookupUserRedirect(name); err == nil {
context.RedirectToUser(ctx, name, redirectUserID)
} else {
ctx.NotFound("GetUserByName", err)
}
} else {
ctx.ServerError("GetUserByName", err)
}
return nil
}
return user
}
// GetUserByParams returns user whose name is presented in URL paramenter.
func GetUserByParams(ctx *context.Context) *user_model.User {
return GetUserByName(ctx, ctx.Params(":username"))
}
// Profile render user's profile page
func Profile(ctx *context.Context) {
uname := ctx.Params(":username")
// Special handle for FireFox requests favicon.ico.
if uname == "favicon.ico" {
ctx.ServeFile(path.Join(setting.StaticRootPath, "public/img/favicon.png"))
if strings.Contains(ctx.Req.Header.Get("Accept"), "application/rss+xml") {
feed.ShowUserFeedRSS(ctx)
return
}
if strings.Contains(ctx.Req.Header.Get("Accept"), "application/atom+xml") {
feed.ShowUserFeedAtom(ctx)
return
}
if strings.HasSuffix(uname, ".png") {
ctx.Error(http.StatusNotFound)
return
}
isShowKeys := false
if strings.HasSuffix(uname, ".keys") {
isShowKeys = true
uname = strings.TrimSuffix(uname, ".keys")
}
isShowGPG := false
if strings.HasSuffix(uname, ".gpg") {
isShowGPG = true
uname = strings.TrimSuffix(uname, ".gpg")
}
isShowFeed, uname, showFeedType := feed.GetFeedType(uname, ctx.Req)
ctxUser := GetUserByName(ctx, uname)
if ctx.Written() {
return
}
if ctxUser.IsOrganization() {
// Show Org RSS feed
if isShowFeed {
feed.ShowUserFeed(ctx, ctxUser, showFeedType)
return
}
if ctx.ContextUser.IsOrganization() {
org.Home(ctx)
return
}
// check view permissions
if !models.IsUserVisibleToViewer(ctxUser, ctx.Doer) {
ctx.NotFound("user", fmt.Errorf(uname))
return
}
// Show SSH keys.
if isShowKeys {
ShowSSHKeys(ctx, ctxUser.ID)
return
}
// Show GPG keys.
if isShowGPG {
ShowGPGKeys(ctx, ctxUser.ID)
return
}
// Show User RSS feed
if isShowFeed {
feed.ShowUserFeed(ctx, ctxUser, showFeedType)
if !models.IsUserVisibleToViewer(ctx.ContextUser, ctx.Doer) {
ctx.NotFound("user", fmt.Errorf(ctx.ContextUser.Name))
return
}
// advertise feed via meta tag
ctx.Data["FeedURL"] = ctxUser.HTMLURL()
ctx.Data["FeedURL"] = ctx.ContextUser.HTMLURL()
// Show OpenID URIs
openIDs, err := user_model.GetUserOpenIDs(ctxUser.ID)
openIDs, err := user_model.GetUserOpenIDs(ctx.ContextUser.ID)
if err != nil {
ctx.ServerError("GetUserOpenIDs", err)
return
}
var isFollowing bool
if ctx.Doer != nil && ctxUser != nil {
isFollowing = user_model.IsFollowing(ctx.Doer.ID, ctxUser.ID)
if ctx.Doer != nil {
isFollowing = user_model.IsFollowing(ctx.Doer.ID, ctx.ContextUser.ID)
}
ctx.Data["Title"] = ctxUser.DisplayName()
ctx.Data["Title"] = ctx.ContextUser.DisplayName()
ctx.Data["PageIsUserProfile"] = true
ctx.Data["Owner"] = ctxUser
ctx.Data["Owner"] = ctx.ContextUser
ctx.Data["OpenIDs"] = openIDs
ctx.Data["IsFollowing"] = isFollowing
if setting.Service.EnableUserHeatmap {
data, err := models.GetUserHeatmapDataByUser(ctxUser, ctx.Doer)
data, err := models.GetUserHeatmapDataByUser(ctx.ContextUser, ctx.Doer)
if err != nil {
ctx.ServerError("GetUserHeatmapDataByUser", err)
return
@ -146,13 +75,13 @@ func Profile(ctx *context.Context) {
ctx.Data["HeatmapData"] = data
}
if len(ctxUser.Description) != 0 {
if len(ctx.ContextUser.Description) != 0 {
content, err := markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: map[string]string{"mode": "document"},
GitRepo: ctx.Repo.GitRepo,
Ctx: ctx,
}, ctxUser.Description)
}, ctx.ContextUser.Description)
if err != nil {
ctx.ServerError("RenderString", err)
return
@ -160,10 +89,10 @@ func Profile(ctx *context.Context) {
ctx.Data["RenderedDescription"] = content
}
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctxUser.ID)
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
orgs, err := models.FindOrgs(models.FindOrgOptions{
UserID: ctxUser.ID,
UserID: ctx.ContextUser.ID,
IncludePrivate: showPrivate,
})
if err != nil {
@ -226,7 +155,7 @@ func Profile(ctx *context.Context) {
switch tab {
case "followers":
items, err := user_model.GetUserFollowers(ctxUser, db.ListOptions{
items, err := user_model.GetUserFollowers(ctx.ContextUser, db.ListOptions{
PageSize: setting.UI.User.RepoPagingNum,
Page: page,
})
@ -236,9 +165,9 @@ func Profile(ctx *context.Context) {
}
ctx.Data["Cards"] = items
total = ctxUser.NumFollowers
total = ctx.ContextUser.NumFollowers
case "following":
items, err := user_model.GetUserFollowing(ctxUser, db.ListOptions{
items, err := user_model.GetUserFollowing(ctx.ContextUser, db.ListOptions{
PageSize: setting.UI.User.RepoPagingNum,
Page: page,
})
@ -248,10 +177,10 @@ func Profile(ctx *context.Context) {
}
ctx.Data["Cards"] = items
total = ctxUser.NumFollowing
total = ctx.ContextUser.NumFollowing
case "activity":
ctx.Data["Feeds"], err = models.GetFeeds(ctx, models.GetFeedsOptions{
RequestedUser: ctxUser,
RequestedUser: ctx.ContextUser,
Actor: ctx.Doer,
IncludePrivate: showPrivate,
OnlyPerformedBy: true,
@ -273,7 +202,7 @@ func Profile(ctx *context.Context) {
Keyword: keyword,
OrderBy: orderBy,
Private: ctx.IsSigned,
StarredByID: ctxUser.ID,
StarredByID: ctx.ContextUser.ID,
Collaborate: util.OptionalBoolFalse,
TopicOnly: topicOnly,
Language: language,
@ -305,7 +234,7 @@ func Profile(ctx *context.Context) {
Keyword: keyword,
OrderBy: orderBy,
Private: ctx.IsSigned,
WatchedByID: ctxUser.ID,
WatchedByID: ctx.ContextUser.ID,
Collaborate: util.OptionalBoolFalse,
TopicOnly: topicOnly,
Language: language,
@ -325,7 +254,7 @@ func Profile(ctx *context.Context) {
},
Actor: ctx.Doer,
Keyword: keyword,
OwnerID: ctxUser.ID,
OwnerID: ctx.ContextUser.ID,
OrderBy: orderBy,
Private: ctx.IsSigned,
Collaborate: util.OptionalBoolFalse,
@ -350,24 +279,19 @@ func Profile(ctx *context.Context) {
}
ctx.Data["Page"] = pager
ctx.Data["ShowUserEmail"] = len(ctxUser.Email) > 0 && ctx.IsSigned && (!ctxUser.KeepEmailPrivate || ctxUser.ID == ctx.Doer.ID)
ctx.Data["ShowUserEmail"] = len(ctx.ContextUser.Email) > 0 && ctx.IsSigned && (!ctx.ContextUser.KeepEmailPrivate || ctx.ContextUser.ID == ctx.Doer.ID)
ctx.HTML(http.StatusOK, tplProfile)
}
// Action response for follow/unfollow user request
func Action(ctx *context.Context) {
u := GetUserByParams(ctx)
if ctx.Written() {
return
}
var err error
switch ctx.FormString("action") {
case "follow":
err = user_model.FollowUser(ctx.Doer.ID, u.ID)
err = user_model.FollowUser(ctx.Doer.ID, ctx.ContextUser.ID)
case "unfollow":
err = user_model.UnfollowUser(ctx.Doer.ID, u.ID)
err = user_model.UnfollowUser(ctx.Doer.ID, ctx.ContextUser.ID)
}
if err != nil {
@ -375,5 +299,5 @@ func Action(ctx *context.Context) {
return
}
// FIXME: We should check this URL and make sure that it's a valid Gitea URL
ctx.RedirectToFirst(ctx.FormString("redirect_to"), u.HomeLink())
ctx.RedirectToFirst(ctx.FormString("redirect_to"), ctx.ContextUser.HomeLink())
}