summaryrefslogtreecommitdiffstats
path: root/models/issues/issue_watch.go
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2022-06-13 17:37:59 +0800
committerGitHub <noreply@github.com>2022-06-13 17:37:59 +0800
commit1a9821f57a0293db3adc0eab8aff08ca5fa1026c (patch)
tree3c3d02813eb63c0d0827ef6d9745f6dcdd2636cb /models/issues/issue_watch.go
parent3708ca8e2849ca7e36e6bd15ec6935a2a2d81e55 (diff)
downloadgitea-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.go135
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
+}