2017-03-31 01:11:58 +03:00
// 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.
2017-03-19 22:54:12 +03:00
package models
2020-01-07 18:41:35 +03:00
import (
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2020-01-07 18:41:35 +03:00
"code.gitea.io/gitea/modules/timeutil"
)
2017-03-19 22:54:12 +03:00
// IssueWatch is connection request for receiving issue notification.
type IssueWatch struct {
2019-08-15 17:46:21 +03:00
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" `
2017-03-19 22:54:12 +03:00
}
2017-03-30 02:31:47 +03:00
2021-09-19 14:49:59 +03:00
func init ( ) {
db . RegisterModel ( new ( IssueWatch ) )
}
2019-11-02 18:27:49 +03:00
// IssueWatchList contains IssueWatch
type IssueWatchList [ ] * IssueWatch
2017-03-30 02:31:47 +03:00
// CreateOrUpdateIssueWatch set watching for a user and issue
func CreateOrUpdateIssueWatch ( userID , issueID int64 , isWatching bool ) error {
2021-09-23 18:45:36 +03:00
iw , exists , err := getIssueWatch ( db . GetEngine ( db . DefaultContext ) , userID , issueID )
2017-03-30 02:31:47 +03:00
if err != nil {
return err
}
if ! exists {
iw = & IssueWatch {
UserID : userID ,
IssueID : issueID ,
IsWatching : isWatching ,
}
2021-09-23 18:45:36 +03:00
if _ , err := db . GetEngine ( db . DefaultContext ) . Insert ( iw ) ; err != nil {
2017-03-30 02:31:47 +03:00
return err
}
} else {
2017-03-30 02:59:28 +03:00
iw . IsWatching = isWatching
2021-09-23 18:45:36 +03:00
if _ , err := db . GetEngine ( db . DefaultContext ) . ID ( iw . ID ) . Cols ( "is_watching" , "updated_unix" ) . Update ( iw ) ; err != nil {
2017-03-30 02:31:47 +03:00
return err
}
}
return nil
}
2020-01-07 18:41:35 +03:00
// GetIssueWatch returns all IssueWatch objects from db by user and issue
// the current Web-UI need iw object for watchers AND explicit non-watchers
2017-03-30 02:31:47 +03:00
func GetIssueWatch ( userID , issueID int64 ) ( iw * IssueWatch , exists bool , err error ) {
2021-09-23 18:45:36 +03:00
return getIssueWatch ( db . GetEngine ( db . DefaultContext ) , userID , issueID )
2017-03-30 02:31:47 +03:00
}
2017-04-01 15:58:20 +03:00
2020-01-07 18:41:35 +03:00
// Return watcher AND explicit non-watcher if entry in db exist
2021-09-19 14:49:59 +03:00
func getIssueWatch ( e db . Engine , userID , issueID int64 ) ( iw * IssueWatch , exists bool , err error ) {
2017-03-30 02:31:47 +03:00
iw = new ( IssueWatch )
exists , err = e .
Where ( "user_id = ?" , userID ) .
And ( "issue_id = ?" , issueID ) .
Get ( iw )
return
}
2017-03-30 02:54:57 +03:00
2020-04-21 16:48:53 +03:00
// CheckIssueWatch check if an user is watching an issue
// it takes participants and repo watch into account
func CheckIssueWatch ( user * User , issue * Issue ) ( bool , error ) {
2021-09-23 18:45:36 +03:00
iw , exist , err := getIssueWatch ( db . GetEngine ( db . DefaultContext ) , user . ID , issue . ID )
2020-04-21 16:48:53 +03:00
if err != nil {
return false , err
}
if exist {
return iw . IsWatching , nil
}
2021-09-23 18:45:36 +03:00
w , err := getWatch ( db . GetEngine ( db . DefaultContext ) , user . ID , issue . RepoID )
2020-04-21 16:48:53 +03:00
if err != nil {
return false , err
}
return isWatchMode ( w . Mode ) || IsUserParticipantsOfIssue ( user , issue ) , nil
}
2020-02-27 13:07:05 +03:00
// GetIssueWatchersIDs returns IDs of subscribers or explicit unsubscribers to a given issue id
2019-11-18 11:08:20 +03:00
// but avoids joining with `user` for performance reasons
// User permissions must be verified elsewhere if required
2020-02-27 13:07:05 +03:00
func GetIssueWatchersIDs ( issueID int64 , watching bool ) ( [ ] int64 , error ) {
2021-09-23 18:45:36 +03:00
return getIssueWatchersIDs ( db . GetEngine ( db . DefaultContext ) , issueID , watching )
2020-02-26 09:32:22 +03:00
}
2021-09-19 14:49:59 +03:00
func getIssueWatchersIDs ( e db . Engine , issueID int64 , watching bool ) ( [ ] int64 , error ) {
2019-11-18 11:08:20 +03:00
ids := make ( [ ] int64 , 0 , 64 )
2020-02-26 09:32:22 +03:00
return ids , e . Table ( "issue_watch" ) .
2019-11-18 11:08:20 +03:00
Where ( "issue_id=?" , issueID ) .
2020-02-26 09:32:22 +03:00
And ( "is_watching = ?" , watching ) .
2019-11-18 11:08:20 +03:00
Select ( "user_id" ) .
Find ( & ids )
}
2017-03-30 03:18:28 +03:00
// GetIssueWatchers returns watchers/unwatchers of a given issue
2020-01-24 22:00:29 +03:00
func GetIssueWatchers ( issueID int64 , listOptions ListOptions ) ( IssueWatchList , error ) {
2021-09-23 18:45:36 +03:00
return getIssueWatchers ( db . GetEngine ( db . DefaultContext ) , issueID , listOptions )
2017-03-30 02:54:57 +03:00
}
2017-04-01 15:58:20 +03:00
2021-09-19 14:49:59 +03:00
func getIssueWatchers ( e db . Engine , issueID int64 , listOptions ListOptions ) ( IssueWatchList , error ) {
2020-01-24 22:00:29 +03:00
sess := e .
2017-09-16 03:18:25 +03:00
Where ( "`issue_watch`.issue_id = ?" , issueID ) .
2019-11-20 17:50:54 +03:00
And ( "`issue_watch`.is_watching = ?" , true ) .
2017-09-16 03:18:25 +03:00
And ( "`user`.is_active = ?" , true ) .
And ( "`user`.prohibit_login = ?" , false ) .
2020-01-24 22:00:29 +03:00
Join ( "INNER" , "`user`" , "`user`.id = `issue_watch`.user_id" )
2020-02-25 01:50:32 +03:00
if listOptions . Page != 0 {
2021-09-14 20:48:27 +03:00
sess = setSessionPagination ( sess , & listOptions )
2020-02-25 01:50:32 +03:00
watches := make ( [ ] * IssueWatch , 0 , listOptions . PageSize )
return watches , sess . Find ( & watches )
2020-01-24 22:00:29 +03:00
}
2020-02-25 01:50:32 +03:00
watches := make ( [ ] * IssueWatch , 0 , 8 )
return watches , sess . Find ( & watches )
2017-03-30 02:54:57 +03:00
}
2018-06-19 22:44:33 +03:00
2021-09-19 14:49:59 +03:00
func removeIssueWatchersByRepoID ( e db . Engine , userID , repoID int64 ) error {
2018-06-19 22:44:33 +03:00
_ , err := e .
Join ( "INNER" , "issue" , "`issue`.id = `issue_watch`.issue_id AND `issue`.repo_id = ?" , repoID ) .
Where ( "`issue_watch`.user_id = ?" , userID ) .
2020-02-26 09:32:22 +03:00
Delete ( new ( IssueWatch ) )
2018-06-19 22:44:33 +03:00
return err
}