2022-03-29 09:29:02 +03:00
// Copyright 2022 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 repo
import (
2022-06-06 11:01:49 +03:00
"context"
2022-03-29 09:29:02 +03:00
"code.gitea.io/gitea/models/db"
2022-06-06 11:01:49 +03:00
"code.gitea.io/gitea/models/perm"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"xorm.io/builder"
2022-03-29 09:29:02 +03:00
)
// GetStarredRepos returns the repos starred by a particular user
func GetStarredRepos ( userID int64 , private bool , listOptions db . ListOptions ) ( [ ] * Repository , error ) {
sess := db . GetEngine ( db . DefaultContext ) . Where ( "star.uid=?" , userID ) .
Join ( "LEFT" , "star" , "`repository`.id=`star`.repo_id" )
if ! private {
sess = sess . And ( "is_private=?" , false )
}
if listOptions . Page != 0 {
sess = db . SetSessionPagination ( sess , & listOptions )
repos := make ( [ ] * Repository , 0 , listOptions . PageSize )
return repos , sess . Find ( & repos )
}
repos := make ( [ ] * Repository , 0 , 10 )
return repos , sess . Find ( & repos )
}
// GetWatchedRepos returns the repos watched by a particular user
func GetWatchedRepos ( userID int64 , private bool , listOptions db . ListOptions ) ( [ ] * Repository , int64 , error ) {
sess := db . GetEngine ( db . DefaultContext ) . Where ( "watch.user_id=?" , userID ) .
And ( "`watch`.mode<>?" , WatchModeDont ) .
Join ( "LEFT" , "watch" , "`repository`.id=`watch`.repo_id" )
if ! private {
sess = sess . And ( "is_private=?" , false )
}
if listOptions . Page != 0 {
sess = db . SetSessionPagination ( sess , & listOptions )
repos := make ( [ ] * Repository , 0 , listOptions . PageSize )
total , err := sess . FindAndCount ( & repos )
return repos , total , err
}
repos := make ( [ ] * Repository , 0 , 10 )
total , err := sess . FindAndCount ( & repos )
return repos , total , err
}
2022-06-06 11:01:49 +03:00
// GetRepoAssignees returns all users that have write access and can be assigned to issues
// of the repository,
func GetRepoAssignees ( ctx context . Context , repo * Repository ) ( _ [ ] * user_model . User , err error ) {
if err = repo . GetOwner ( ctx ) ; err != nil {
return nil , err
}
e := db . GetEngine ( ctx )
userIDs := make ( [ ] int64 , 0 , 10 )
if err = e . Table ( "access" ) .
Where ( "repo_id = ? AND mode >= ?" , repo . ID , perm . AccessModeWrite ) .
Select ( "user_id" ) .
Find ( & userIDs ) ; err != nil {
return nil , err
}
additionalUserIDs := make ( [ ] int64 , 0 , 10 )
if err = e . Table ( "team_user" ) .
Join ( "INNER" , "team_repo" , "`team_repo`.team_id = `team_user`.team_id" ) .
Join ( "INNER" , "team_unit" , "`team_unit`.team_id = `team_user`.team_id" ) .
Where ( "`team_repo`.repo_id = ? AND `team_unit`.access_mode >= ?" , repo . ID , perm . AccessModeWrite ) .
Distinct ( "`team_user`.uid" ) .
Select ( "`team_user`.uid" ) .
Find ( & additionalUserIDs ) ; err != nil {
return nil , err
}
uidMap := map [ int64 ] bool { }
i := 0
for _ , uid := range userIDs {
if uidMap [ uid ] {
continue
}
uidMap [ uid ] = true
userIDs [ i ] = uid
i ++
}
userIDs = userIDs [ : i ]
userIDs = append ( userIDs , additionalUserIDs ... )
for _ , uid := range additionalUserIDs {
if uidMap [ uid ] {
continue
}
userIDs [ i ] = uid
i ++
}
userIDs = userIDs [ : i ]
// Leave a seat for owner itself to append later, but if owner is an organization
// and just waste 1 unit is cheaper than re-allocate memory once.
users := make ( [ ] * user_model . User , 0 , len ( userIDs ) + 1 )
if len ( userIDs ) > 0 {
if err = e . In ( "id" , userIDs ) . Find ( & users ) ; err != nil {
return nil , err
}
}
if ! repo . Owner . IsOrganization ( ) && ! uidMap [ repo . OwnerID ] {
users = append ( users , repo . Owner )
}
return users , nil
}
// GetReviewers get all users can be requested to review:
// * for private repositories this returns all users that have read access or higher to the repository.
// * for public repositories this returns all users that have read access or higher to the repository,
// all repo watchers and all organization members.
// TODO: may be we should have a busy choice for users to block review request to them.
func GetReviewers ( ctx context . Context , repo * Repository , doerID , posterID int64 ) ( [ ] * user_model . User , error ) {
// Get the owner of the repository - this often already pre-cached and if so saves complexity for the following queries
if err := repo . GetOwner ( ctx ) ; err != nil {
return nil , err
}
cond := builder . And ( builder . Neq { "`user`.id" : posterID } )
if repo . IsPrivate || repo . Owner . Visibility == api . VisibleTypePrivate {
// This a private repository:
// Anyone who can read the repository is a requestable reviewer
cond = cond . And ( builder . In ( "`user`.id" ,
builder . Select ( "user_id" ) . From ( "access" ) . Where (
builder . Eq { "repo_id" : repo . ID } .
And ( builder . Gte { "mode" : perm . AccessModeRead } ) ,
) ,
) )
if repo . Owner . Type == user_model . UserTypeIndividual && repo . Owner . ID != posterID {
// as private *user* repos don't generate an entry in the `access` table,
// the owner of a private repo needs to be explicitly added.
cond = cond . Or ( builder . Eq { "`user`.id" : repo . Owner . ID } )
}
} else {
// This is a "public" repository:
// Any user that has read access, is a watcher or organization member can be requested to review
cond = cond . And ( builder . And ( builder . In ( "`user`.id" ,
builder . Select ( "user_id" ) . From ( "access" ) .
Where ( builder . Eq { "repo_id" : repo . ID } .
And ( builder . Gte { "mode" : perm . AccessModeRead } ) ) ,
) . Or ( builder . In ( "`user`.id" ,
builder . Select ( "user_id" ) . From ( "watch" ) .
Where ( builder . Eq { "repo_id" : repo . ID } .
And ( builder . In ( "mode" , WatchModeNormal , WatchModeAuto ) ) ) ,
) . Or ( builder . In ( "`user`.id" ,
builder . Select ( "uid" ) . From ( "org_user" ) .
Where ( builder . Eq { "org_id" : repo . OwnerID } ) ,
) ) ) ) )
}
users := make ( [ ] * user_model . User , 0 , 8 )
return users , db . GetEngine ( ctx ) . Where ( cond ) . OrderBy ( "name" ) . Find ( & users )
}