mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	@@ -22,6 +22,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
			
		||||
	"code.gitea.io/gitea/modules/util"
 | 
			
		||||
 | 
			
		||||
@@ -315,19 +316,21 @@ func (a *Action) GetIssueContent() string {
 | 
			
		||||
 | 
			
		||||
// GetFeedsOptions options for retrieving feeds
 | 
			
		||||
type GetFeedsOptions struct {
 | 
			
		||||
	RequestedUser   *user_model.User // the user we want activity for
 | 
			
		||||
	RequestedTeam   *Team            // the team we want activity for
 | 
			
		||||
	Actor           *user_model.User // the user viewing the activity
 | 
			
		||||
	IncludePrivate  bool             // include private actions
 | 
			
		||||
	OnlyPerformedBy bool             // only actions performed by requested user
 | 
			
		||||
	IncludeDeleted  bool             // include deleted actions
 | 
			
		||||
	Date            string           // the day we want activity for: YYYY-MM-DD
 | 
			
		||||
	db.ListOptions
 | 
			
		||||
	RequestedUser   *user_model.User       // the user we want activity for
 | 
			
		||||
	RequestedTeam   *Team                  // the team we want activity for
 | 
			
		||||
	RequestedRepo   *repo_model.Repository // the repo we want activity for
 | 
			
		||||
	Actor           *user_model.User       // the user viewing the activity
 | 
			
		||||
	IncludePrivate  bool                   // include private actions
 | 
			
		||||
	OnlyPerformedBy bool                   // only actions performed by requested user
 | 
			
		||||
	IncludeDeleted  bool                   // include deleted actions
 | 
			
		||||
	Date            string                 // the day we want activity for: YYYY-MM-DD
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFeeds returns actions according to the provided options
 | 
			
		||||
func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
 | 
			
		||||
	if !activityReadable(opts.RequestedUser, opts.Actor) {
 | 
			
		||||
		return make([]*Action, 0), nil
 | 
			
		||||
	if opts.RequestedUser == nil && opts.RequestedTeam == nil && opts.RequestedRepo == nil {
 | 
			
		||||
		return nil, fmt.Errorf("need at least one of these filters: RequestedUser, RequestedTeam, RequestedRepo")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cond, err := activityQueryCondition(opts)
 | 
			
		||||
@@ -335,9 +338,14 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	actions := make([]*Action, 0, setting.UI.FeedPagingNum)
 | 
			
		||||
	sess := db.GetEngine(db.DefaultContext).Where(cond)
 | 
			
		||||
 | 
			
		||||
	if err := db.GetEngine(db.DefaultContext).Limit(setting.UI.FeedPagingNum).Desc("created_unix").Where(cond).Find(&actions); err != nil {
 | 
			
		||||
	opts.SetDefaultValues()
 | 
			
		||||
	sess = db.SetSessionPagination(sess, &opts)
 | 
			
		||||
 | 
			
		||||
	actions := make([]*Action, 0, opts.PageSize)
 | 
			
		||||
 | 
			
		||||
	if err := sess.Desc("created_unix").Find(&actions); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Find: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -349,41 +357,44 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func activityReadable(user, doer *user_model.User) bool {
 | 
			
		||||
	var doerID int64
 | 
			
		||||
	if doer != nil {
 | 
			
		||||
		doerID = doer.ID
 | 
			
		||||
	}
 | 
			
		||||
	if doer == nil || !doer.IsAdmin {
 | 
			
		||||
		if user.KeepActivityPrivate && doerID != user.ID {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
	return !user.KeepActivityPrivate ||
 | 
			
		||||
		doer != nil && (doer.IsAdmin || user.ID == doer.ID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {
 | 
			
		||||
	cond := builder.NewCond()
 | 
			
		||||
 | 
			
		||||
	var repoIDs []int64
 | 
			
		||||
	var actorID int64
 | 
			
		||||
	if opts.Actor != nil {
 | 
			
		||||
		actorID = opts.Actor.ID
 | 
			
		||||
	if opts.RequestedTeam != nil && opts.RequestedUser == nil {
 | 
			
		||||
		org, err := user_model.GetUserByID(opts.RequestedTeam.OrgID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		opts.RequestedUser = org
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check activity visibility for actor ( similar to activityReadable() )
 | 
			
		||||
	if opts.Actor == nil {
 | 
			
		||||
		cond = cond.And(builder.In("act_user_id",
 | 
			
		||||
			builder.Select("`user`.id").Where(
 | 
			
		||||
				builder.Eq{"keep_activity_private": false, "visibility": structs.VisibleTypePublic},
 | 
			
		||||
			).From("`user`"),
 | 
			
		||||
		))
 | 
			
		||||
	} else if !opts.Actor.IsAdmin {
 | 
			
		||||
		cond = cond.And(builder.In("act_user_id",
 | 
			
		||||
			builder.Select("`user`.id").Where(
 | 
			
		||||
				builder.Eq{"keep_activity_private": false}.
 | 
			
		||||
					And(builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))).
 | 
			
		||||
				Or(builder.Eq{"id": opts.Actor.ID}).From("`user`"),
 | 
			
		||||
		))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check readable repositories by doer/actor
 | 
			
		||||
	if opts.Actor == nil || !opts.Actor.IsAdmin {
 | 
			
		||||
		if opts.RequestedUser.IsOrganization() {
 | 
			
		||||
			env, err := OrgFromUser(opts.RequestedUser).AccessibleReposEnv(actorID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("AccessibleReposEnv: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			if repoIDs, err = env.RepoIDs(1, opts.RequestedUser.NumRepos); err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("GetUserRepositories: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			cond = cond.And(builder.In("repo_id", repoIDs))
 | 
			
		||||
		} else {
 | 
			
		||||
			cond = cond.And(builder.In("repo_id", AccessibleRepoIDsQuery(opts.Actor)))
 | 
			
		||||
		}
 | 
			
		||||
		cond = cond.And(builder.In("repo_id", AccessibleRepoIDsQuery(opts.Actor)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.RequestedRepo != nil {
 | 
			
		||||
		cond = cond.And(builder.Eq{"repo_id": opts.RequestedRepo.ID})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.RequestedTeam != nil {
 | 
			
		||||
@@ -395,11 +406,14 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {
 | 
			
		||||
		cond = cond.And(builder.In("repo_id", teamRepoIDs))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cond = cond.And(builder.Eq{"user_id": opts.RequestedUser.ID})
 | 
			
		||||
	if opts.RequestedUser != nil {
 | 
			
		||||
		cond = cond.And(builder.Eq{"user_id": opts.RequestedUser.ID})
 | 
			
		||||
 | 
			
		||||
	if opts.OnlyPerformedBy {
 | 
			
		||||
		cond = cond.And(builder.Eq{"act_user_id": opts.RequestedUser.ID})
 | 
			
		||||
		if opts.OnlyPerformedBy {
 | 
			
		||||
			cond = cond.And(builder.Eq{"act_user_id": opts.RequestedUser.ID})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !opts.IncludePrivate {
 | 
			
		||||
		cond = cond.And(builder.Eq{"is_private": false})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user