]> source.dussan.org Git - gitea.git/commitdiff
Only show Followers that current user can access (#20220) (#20253)
authorzeripath <art27@cantab.net>
Wed, 6 Jul 2022 01:47:16 +0000 (02:47 +0100)
committerGitHub <noreply@github.com>
Wed, 6 Jul 2022 01:47:16 +0000 (09:47 +0800)
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>
models/user/user.go
routers/api/v1/user/follower.go
routers/web/user/profile.go

index e375f3de0a5980791db1c3491b53888a4989a6aa..7e7657070a682628700aa524a6e164162794d2b5 100644 (file)
@@ -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})))
+}
index 1eacb89db2bfece3fe95daac87151f3a31e9d074..d648d50d694943c18589bb3a1c8e74aaba060e33 100644 (file)
@@ -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)
 }
 
index 40fc44ed14a97d8982dce0b6924a2c2183e3b95a..5366a4c2cb622a2ffdf4a133c56ccb4c25cad82c 100644 (file)
@@ -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,