Skip to content

Commit

Permalink
Only show Followers that current user can access (go-gitea#20220) (go…
Browse files Browse the repository at this point in the history
…-gitea#20253)

Backport go-gitea#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>
  • Loading branch information
zeripath authored Jul 6, 2022
1 parent 6162fb0 commit b42df31
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 18 deletions.
59 changes: 50 additions & 9 deletions models/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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})))
}
8 changes: 4 additions & 4 deletions routers/api/v1/user/follower.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down Expand Up @@ -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)
}

Expand Down
11 changes: 6 additions & 5 deletions routers/web/user/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
Expand All @@ -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,
})
Expand All @@ -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,
Expand Down

0 comments on commit b42df31

Please sign in to comment.