aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2022-07-06 02:47:16 +0100
committerGitHub <noreply@github.com>2022-07-06 09:47:16 +0800
commitb42df3105d6d94fbc758daff81a5f39d4416ed42 (patch)
tree1962b27bc63a004835b33970a0a55198c82039cd
parent6162fb0a1923b03ca10e5dc0b6cb5c33a40f66a5 (diff)
downloadgitea-b42df3105d6d94fbc758daff81a5f39d4416ed42.tar.gz
gitea-b42df3105d6d94fbc758daff81a5f39d4416ed42.zip
Only show Followers that current user can access (#20220) (#20253)
Backport #20220 Users who are following or being followed by a user should only be displayed if the viewing user can see them. Signed-off-by: Andrew Thornton <art27@cantab.net>
-rw-r--r--models/user/user.go59
-rw-r--r--routers/api/v1/user/follower.go8
-rw-r--r--routers/web/user/profile.go11
3 files changed, 60 insertions, 18 deletions
diff --git a/models/user/user.go b/models/user/user.go
index e375f3de0a..7e7657070a 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -316,37 +316,45 @@ func (u *User) GenerateEmailActivateCode(email string) string {
}
// GetUserFollowers returns range of user's followers.
-func GetUserFollowers(u *User, listOptions db.ListOptions) ([]*User, error) {
- sess := db.GetEngine(db.DefaultContext).
+func GetUserFollowers(ctx context.Context, u, viewer *User, listOptions db.ListOptions) ([]*User, int64, error) {
+ sess := db.GetEngine(ctx).
+ Select("`user`.*").
+ Join("LEFT", "follow", "`user`.id=follow.user_id").
Where("follow.follow_id=?", u.ID).
- Join("LEFT", "follow", "`user`.id=follow.user_id")
+ And(isUserVisibleToViewerCond(viewer))
if listOptions.Page != 0 {
sess = db.SetSessionPagination(sess, &listOptions)
users := make([]*User, 0, listOptions.PageSize)
- return users, sess.Find(&users)
+ count, err := sess.FindAndCount(&users)
+ return users, count, err
}
users := make([]*User, 0, 8)
- return users, sess.Find(&users)
+ count, err := sess.FindAndCount(&users)
+ return users, count, err
}
// GetUserFollowing returns range of user's following.
-func GetUserFollowing(u *User, listOptions db.ListOptions) ([]*User, error) {
+func GetUserFollowing(ctx context.Context, u, viewer *User, listOptions db.ListOptions) ([]*User, int64, error) {
sess := db.GetEngine(db.DefaultContext).
+ Select("`user`.*").
+ Join("LEFT", "follow", "`user`.id=follow.follow_id").
Where("follow.user_id=?", u.ID).
- Join("LEFT", "follow", "`user`.id=follow.follow_id")
+ And(isUserVisibleToViewerCond(viewer))
if listOptions.Page != 0 {
sess = db.SetSessionPagination(sess, &listOptions)
users := make([]*User, 0, listOptions.PageSize)
- return users, sess.Find(&users)
+ count, err := sess.FindAndCount(&users)
+ return users, count, err
}
users := make([]*User, 0, 8)
- return users, sess.Find(&users)
+ count, err := sess.FindAndCount(&users)
+ return users, count, err
}
// NewGitSig generates and returns the signature of given user.
@@ -1231,3 +1239,36 @@ func GetAdminUser() (*User, error) {
return &admin, nil
}
+
+func isUserVisibleToViewerCond(viewer *User) builder.Cond {
+ if viewer != nil && viewer.IsAdmin {
+ return builder.NewCond()
+ }
+
+ if viewer == nil || viewer.IsRestricted {
+ return builder.Eq{
+ "`user`.visibility": structs.VisibleTypePublic,
+ }
+ }
+
+ return builder.Neq{
+ "`user`.visibility": structs.VisibleTypePrivate,
+ }.Or(
+ builder.In("`user`.id",
+ builder.
+ Select("`follow`.user_id").
+ From("follow").
+ Where(builder.Eq{"`follow`.follow_id": viewer.ID})),
+ builder.In("`user`.id",
+ builder.
+ Select("`team_user`.uid").
+ From("team_user").
+ Join("INNER", "`team_user` AS t2", "`team_user`.id = `t2`.id").
+ Where(builder.Eq{"`t2`.uid": viewer.ID})),
+ builder.In("`user`.id",
+ builder.
+ Select("`team_user`.uid").
+ From("team_user").
+ Join("INNER", "`team_user` AS t2", "`team_user`.org_id = `t2`.org_id").
+ Where(builder.Eq{"`t2`.uid": viewer.ID})))
+}
diff --git a/routers/api/v1/user/follower.go b/routers/api/v1/user/follower.go
index 1eacb89db2..d648d50d69 100644
--- a/routers/api/v1/user/follower.go
+++ b/routers/api/v1/user/follower.go
@@ -24,13 +24,13 @@ func responseAPIUsers(ctx *context.APIContext, users []*user_model.User) {
}
func listUserFollowers(ctx *context.APIContext, u *user_model.User) {
- users, err := user_model.GetUserFollowers(u, utils.GetListOptions(ctx))
+ users, count, err := user_model.GetUserFollowers(ctx, u, ctx.User, utils.GetListOptions(ctx))
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetUserFollowers", err)
return
}
- ctx.SetTotalCountHeader(int64(u.NumFollowers))
+ ctx.SetTotalCountHeader(count)
responseAPIUsers(ctx, users)
}
@@ -90,13 +90,13 @@ func ListFollowers(ctx *context.APIContext) {
}
func listUserFollowing(ctx *context.APIContext, u *user_model.User) {
- users, err := user_model.GetUserFollowing(u, utils.GetListOptions(ctx))
+ users, count, err := user_model.GetUserFollowing(ctx, u, ctx.User, utils.GetListOptions(ctx))
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetUserFollowing", err)
return
}
- ctx.SetTotalCountHeader(int64(u.NumFollowing))
+ ctx.SetTotalCountHeader(count)
responseAPIUsers(ctx, users)
}
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index 40fc44ed14..5366a4c2cb 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -234,7 +234,7 @@ func Profile(ctx *context.Context) {
ctx.Data["Keyword"] = keyword
switch tab {
case "followers":
- items, err := user_model.GetUserFollowers(ctxUser, db.ListOptions{
+ items, count, err := user_model.GetUserFollowers(ctx, ctxUser, ctx.User, db.ListOptions{
PageSize: setting.UI.User.RepoPagingNum,
Page: page,
})
@@ -244,9 +244,9 @@ func Profile(ctx *context.Context) {
}
ctx.Data["Cards"] = items
- total = ctxUser.NumFollowers
+ total = int(count)
case "following":
- items, err := user_model.GetUserFollowing(ctxUser, db.ListOptions{
+ items, count, err := user_model.GetUserFollowing(ctx, ctxUser, ctx.User, db.ListOptions{
PageSize: setting.UI.User.RepoPagingNum,
Page: page,
})
@@ -256,9 +256,10 @@ func Profile(ctx *context.Context) {
}
ctx.Data["Cards"] = items
- total = ctxUser.NumFollowing
+ total = int(count)
case "activity":
- ctx.Data["Feeds"] = feed.RetrieveFeeds(ctx, models.GetFeedsOptions{RequestedUser: ctxUser,
+ ctx.Data["Feeds"] = feed.RetrieveFeeds(ctx, models.GetFeedsOptions{
+ RequestedUser: ctxUser,
Actor: ctx.User,
IncludePrivate: showPrivate,
OnlyPerformedBy: true,