You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

issue_watch.go 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "code.gitea.io/gitea/models/db"
  7. "code.gitea.io/gitea/modules/timeutil"
  8. )
  9. // IssueWatch is connection request for receiving issue notification.
  10. type IssueWatch struct {
  11. ID int64 `xorm:"pk autoincr"`
  12. UserID int64 `xorm:"UNIQUE(watch) NOT NULL"`
  13. IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"`
  14. IsWatching bool `xorm:"NOT NULL"`
  15. CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
  16. UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL"`
  17. }
  18. func init() {
  19. db.RegisterModel(new(IssueWatch))
  20. }
  21. // IssueWatchList contains IssueWatch
  22. type IssueWatchList []*IssueWatch
  23. // CreateOrUpdateIssueWatch set watching for a user and issue
  24. func CreateOrUpdateIssueWatch(userID, issueID int64, isWatching bool) error {
  25. iw, exists, err := getIssueWatch(db.GetEngine(db.DefaultContext), userID, issueID)
  26. if err != nil {
  27. return err
  28. }
  29. if !exists {
  30. iw = &IssueWatch{
  31. UserID: userID,
  32. IssueID: issueID,
  33. IsWatching: isWatching,
  34. }
  35. if _, err := db.GetEngine(db.DefaultContext).Insert(iw); err != nil {
  36. return err
  37. }
  38. } else {
  39. iw.IsWatching = isWatching
  40. if _, err := db.GetEngine(db.DefaultContext).ID(iw.ID).Cols("is_watching", "updated_unix").Update(iw); err != nil {
  41. return err
  42. }
  43. }
  44. return nil
  45. }
  46. // GetIssueWatch returns all IssueWatch objects from db by user and issue
  47. // the current Web-UI need iw object for watchers AND explicit non-watchers
  48. func GetIssueWatch(userID, issueID int64) (iw *IssueWatch, exists bool, err error) {
  49. return getIssueWatch(db.GetEngine(db.DefaultContext), userID, issueID)
  50. }
  51. // Return watcher AND explicit non-watcher if entry in db exist
  52. func getIssueWatch(e db.Engine, userID, issueID int64) (iw *IssueWatch, exists bool, err error) {
  53. iw = new(IssueWatch)
  54. exists, err = e.
  55. Where("user_id = ?", userID).
  56. And("issue_id = ?", issueID).
  57. Get(iw)
  58. return
  59. }
  60. // CheckIssueWatch check if an user is watching an issue
  61. // it takes participants and repo watch into account
  62. func CheckIssueWatch(user *User, issue *Issue) (bool, error) {
  63. iw, exist, err := getIssueWatch(db.GetEngine(db.DefaultContext), user.ID, issue.ID)
  64. if err != nil {
  65. return false, err
  66. }
  67. if exist {
  68. return iw.IsWatching, nil
  69. }
  70. w, err := getWatch(db.GetEngine(db.DefaultContext), user.ID, issue.RepoID)
  71. if err != nil {
  72. return false, err
  73. }
  74. return isWatchMode(w.Mode) || IsUserParticipantsOfIssue(user, issue), nil
  75. }
  76. // GetIssueWatchersIDs returns IDs of subscribers or explicit unsubscribers to a given issue id
  77. // but avoids joining with `user` for performance reasons
  78. // User permissions must be verified elsewhere if required
  79. func GetIssueWatchersIDs(issueID int64, watching bool) ([]int64, error) {
  80. return getIssueWatchersIDs(db.GetEngine(db.DefaultContext), issueID, watching)
  81. }
  82. func getIssueWatchersIDs(e db.Engine, issueID int64, watching bool) ([]int64, error) {
  83. ids := make([]int64, 0, 64)
  84. return ids, e.Table("issue_watch").
  85. Where("issue_id=?", issueID).
  86. And("is_watching = ?", watching).
  87. Select("user_id").
  88. Find(&ids)
  89. }
  90. // GetIssueWatchers returns watchers/unwatchers of a given issue
  91. func GetIssueWatchers(issueID int64, listOptions db.ListOptions) (IssueWatchList, error) {
  92. return getIssueWatchers(db.GetEngine(db.DefaultContext), issueID, listOptions)
  93. }
  94. func getIssueWatchers(e db.Engine, issueID int64, listOptions db.ListOptions) (IssueWatchList, error) {
  95. sess := e.
  96. Where("`issue_watch`.issue_id = ?", issueID).
  97. And("`issue_watch`.is_watching = ?", true).
  98. And("`user`.is_active = ?", true).
  99. And("`user`.prohibit_login = ?", false).
  100. Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id")
  101. if listOptions.Page != 0 {
  102. sess = db.SetSessionPagination(sess, &listOptions)
  103. watches := make([]*IssueWatch, 0, listOptions.PageSize)
  104. return watches, sess.Find(&watches)
  105. }
  106. watches := make([]*IssueWatch, 0, 8)
  107. return watches, sess.Find(&watches)
  108. }
  109. func removeIssueWatchersByRepoID(e db.Engine, userID, repoID int64) error {
  110. _, err := e.
  111. Join("INNER", "issue", "`issue`.id = `issue_watch`.issue_id AND `issue`.repo_id = ?", repoID).
  112. Where("`issue_watch`.user_id = ?", userID).
  113. Delete(new(IssueWatch))
  114. return err
  115. }