diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2022-06-13 17:37:59 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-13 17:37:59 +0800 |
commit | 1a9821f57a0293db3adc0eab8aff08ca5fa1026c (patch) | |
tree | 3c3d02813eb63c0d0827ef6d9745f6dcdd2636cb /models/issues/issue_watch.go | |
parent | 3708ca8e2849ca7e36e6bd15ec6935a2a2d81e55 (diff) | |
download | gitea-1a9821f57a0293db3adc0eab8aff08ca5fa1026c.tar.gz gitea-1a9821f57a0293db3adc0eab8aff08ca5fa1026c.zip |
Move issues related files into models/issues (#19931)
* Move access and repo permission to models/perm/access
* fix test
* fix git test
* Move functions sequence
* Some improvements per @KN4CK3R and @delvh
* Move issues related code to models/issues
* Move some issues related sub package
* Merge
* Fix test
* Fix test
* Fix test
* Fix test
* Rename some files
Diffstat (limited to 'models/issues/issue_watch.go')
-rw-r--r-- | models/issues/issue_watch.go | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/models/issues/issue_watch.go b/models/issues/issue_watch.go new file mode 100644 index 0000000000..bf907aa8fd --- /dev/null +++ b/models/issues/issue_watch.go @@ -0,0 +1,135 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package issues + +import ( + "context" + + "code.gitea.io/gitea/models/db" + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/timeutil" +) + +// IssueWatch is connection request for receiving issue notification. +type IssueWatch struct { + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` + IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` + IsWatching bool `xorm:"NOT NULL"` + CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL"` +} + +func init() { + db.RegisterModel(new(IssueWatch)) +} + +// IssueWatchList contains IssueWatch +type IssueWatchList []*IssueWatch + +// CreateOrUpdateIssueWatch set watching for a user and issue +func CreateOrUpdateIssueWatch(userID, issueID int64, isWatching bool) error { + iw, exists, err := GetIssueWatch(db.DefaultContext, userID, issueID) + if err != nil { + return err + } + + if !exists { + iw = &IssueWatch{ + UserID: userID, + IssueID: issueID, + IsWatching: isWatching, + } + + if _, err := db.GetEngine(db.DefaultContext).Insert(iw); err != nil { + return err + } + } else { + iw.IsWatching = isWatching + + if _, err := db.GetEngine(db.DefaultContext).ID(iw.ID).Cols("is_watching", "updated_unix").Update(iw); err != nil { + return err + } + } + return nil +} + +// GetIssueWatch returns all IssueWatch objects from db by user and issue +// the current Web-UI need iw object for watchers AND explicit non-watchers +func GetIssueWatch(ctx context.Context, userID, issueID int64) (iw *IssueWatch, exists bool, err error) { + iw = new(IssueWatch) + exists, err = db.GetEngine(ctx). + Where("user_id = ?", userID). + And("issue_id = ?", issueID). + Get(iw) + return +} + +// CheckIssueWatch check if an user is watching an issue +// it takes participants and repo watch into account +func CheckIssueWatch(user *user_model.User, issue *Issue) (bool, error) { + iw, exist, err := GetIssueWatch(db.DefaultContext, user.ID, issue.ID) + if err != nil { + return false, err + } + if exist { + return iw.IsWatching, nil + } + w, err := repo_model.GetWatch(db.DefaultContext, user.ID, issue.RepoID) + if err != nil { + return false, err + } + return repo_model.IsWatchMode(w.Mode) || IsUserParticipantsOfIssue(user, issue), nil +} + +// GetIssueWatchersIDs returns IDs of subscribers or explicit unsubscribers to a given issue id +// but avoids joining with `user` for performance reasons +// User permissions must be verified elsewhere if required +func GetIssueWatchersIDs(ctx context.Context, issueID int64, watching bool) ([]int64, error) { + ids := make([]int64, 0, 64) + return ids, db.GetEngine(ctx).Table("issue_watch"). + Where("issue_id=?", issueID). + And("is_watching = ?", watching). + Select("user_id"). + Find(&ids) +} + +// GetIssueWatchers returns watchers/unwatchers of a given issue +func GetIssueWatchers(ctx context.Context, issueID int64, listOptions db.ListOptions) (IssueWatchList, error) { + sess := db.GetEngine(ctx). + Where("`issue_watch`.issue_id = ?", issueID). + And("`issue_watch`.is_watching = ?", true). + And("`user`.is_active = ?", true). + And("`user`.prohibit_login = ?", false). + Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id") + + if listOptions.Page != 0 { + sess = db.SetSessionPagination(sess, &listOptions) + watches := make([]*IssueWatch, 0, listOptions.PageSize) + return watches, sess.Find(&watches) + } + watches := make([]*IssueWatch, 0, 8) + return watches, sess.Find(&watches) +} + +// CountIssueWatchers count watchers/unwatchers of a given issue +func CountIssueWatchers(ctx context.Context, issueID int64) (int64, error) { + return db.GetEngine(ctx). + Where("`issue_watch`.issue_id = ?", issueID). + And("`issue_watch`.is_watching = ?", true). + And("`user`.is_active = ?", true). + And("`user`.prohibit_login = ?", false). + Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id").Count(new(IssueWatch)) +} + +// RemoveIssueWatchersByRepoID remove issue watchers by repoID +func RemoveIssueWatchersByRepoID(ctx context.Context, userID, repoID int64) error { + _, err := db.GetEngine(ctx). + Join("INNER", "issue", "`issue`.id = `issue_watch`.issue_id AND `issue`.repo_id = ?", repoID). + Where("`issue_watch`.user_id = ?", userID). + Delete(new(IssueWatch)) + return err +} |