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.

131 lines
3.6 KiB

7 years ago
  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/modules/timeutil"
  7. )
  8. // IssueWatch is connection request for receiving issue notification.
  9. type IssueWatch struct {
  10. ID int64 `xorm:"pk autoincr"`
  11. UserID int64 `xorm:"UNIQUE(watch) NOT NULL"`
  12. IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"`
  13. IsWatching bool `xorm:"NOT NULL"`
  14. CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
  15. UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL"`
  16. }
  17. // IssueWatchList contains IssueWatch
  18. type IssueWatchList []*IssueWatch
  19. // CreateOrUpdateIssueWatch set watching for a user and issue
  20. func CreateOrUpdateIssueWatch(userID, issueID int64, isWatching bool) error {
  21. iw, exists, err := getIssueWatch(x, userID, issueID)
  22. if err != nil {
  23. return err
  24. }
  25. if !exists {
  26. iw = &IssueWatch{
  27. UserID: userID,
  28. IssueID: issueID,
  29. IsWatching: isWatching,
  30. }
  31. if _, err := x.Insert(iw); err != nil {
  32. return err
  33. }
  34. } else {
  35. iw.IsWatching = isWatching
  36. if _, err := x.ID(iw.ID).Cols("is_watching", "updated_unix").Update(iw); err != nil {
  37. return err
  38. }
  39. }
  40. return nil
  41. }
  42. // GetIssueWatch returns all IssueWatch objects from db by user and issue
  43. // the current Web-UI need iw object for watchers AND explicit non-watchers
  44. func GetIssueWatch(userID, issueID int64) (iw *IssueWatch, exists bool, err error) {
  45. return getIssueWatch(x, userID, issueID)
  46. }
  47. // Return watcher AND explicit non-watcher if entry in db exist
  48. func getIssueWatch(e Engine, userID, issueID int64) (iw *IssueWatch, exists bool, err error) {
  49. iw = new(IssueWatch)
  50. exists, err = e.
  51. Where("user_id = ?", userID).
  52. And("issue_id = ?", issueID).
  53. Get(iw)
  54. return
  55. }
  56. // GetIssueWatchersIDs returns IDs of subscribers to a given issue id
  57. // but avoids joining with `user` for performance reasons
  58. // User permissions must be verified elsewhere if required
  59. func GetIssueWatchersIDs(issueID int64) ([]int64, error) {
  60. ids := make([]int64, 0, 64)
  61. return ids, x.Table("issue_watch").
  62. Where("issue_id=?", issueID).
  63. And("is_watching = ?", true).
  64. Select("user_id").
  65. Find(&ids)
  66. }
  67. // GetIssueWatchers returns watchers/unwatchers of a given issue
  68. func GetIssueWatchers(issueID int64) (IssueWatchList, error) {
  69. return getIssueWatchers(x, issueID)
  70. }
  71. func getIssueWatchers(e Engine, issueID int64) (watches IssueWatchList, err error) {
  72. err = e.
  73. Where("`issue_watch`.issue_id = ?", issueID).
  74. And("`issue_watch`.is_watching = ?", true).
  75. And("`user`.is_active = ?", true).
  76. And("`user`.prohibit_login = ?", false).
  77. Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id").
  78. Find(&watches)
  79. return
  80. }
  81. func removeIssueWatchersByRepoID(e Engine, userID int64, repoID int64) error {
  82. iw := &IssueWatch{
  83. IsWatching: false,
  84. }
  85. _, err := e.
  86. Join("INNER", "issue", "`issue`.id = `issue_watch`.issue_id AND `issue`.repo_id = ?", repoID).
  87. Cols("is_watching", "updated_unix").
  88. Where("`issue_watch`.user_id = ?", userID).
  89. Update(iw)
  90. return err
  91. }
  92. // LoadWatchUsers return watching users
  93. func (iwl IssueWatchList) LoadWatchUsers() (users UserList, err error) {
  94. return iwl.loadWatchUsers(x)
  95. }
  96. func (iwl IssueWatchList) loadWatchUsers(e Engine) (users UserList, err error) {
  97. if len(iwl) == 0 {
  98. return []*User{}, nil
  99. }
  100. var userIDs = make([]int64, 0, len(iwl))
  101. for _, iw := range iwl {
  102. if iw.IsWatching {
  103. userIDs = append(userIDs, iw.UserID)
  104. }
  105. }
  106. if len(userIDs) == 0 {
  107. return []*User{}, nil
  108. }
  109. err = e.In("id", userIDs).Find(&users)
  110. return
  111. }