2014-06-25 08:44:48 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2019-02-18 19:00:27 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2014-06-25 08:44:48 +04:00
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
2014-06-27 11:37:01 +04:00
import (
2015-02-23 10:15:53 +03:00
"fmt"
2014-06-27 11:37:01 +04:00
"strings"
2015-09-07 20:58:23 +03:00
2018-01-08 10:48:37 +03:00
"code.gitea.io/gitea/modules/log"
2019-08-24 15:28:59 +03:00
"code.gitea.io/gitea/modules/setting"
2020-10-14 16:07:51 +03:00
"code.gitea.io/gitea/modules/storage"
2019-02-18 19:00:27 +03:00
"code.gitea.io/gitea/modules/structs"
2020-08-11 23:05:34 +03:00
"code.gitea.io/gitea/modules/util"
2018-01-08 10:48:37 +03:00
2019-06-23 18:22:43 +03:00
"xorm.io/builder"
2019-10-17 12:26:49 +03:00
"xorm.io/xorm"
2014-06-27 11:37:01 +04:00
)
2014-12-13 04:30:32 +03:00
// IsOwnedBy returns true if given user is in the owner team.
2017-12-21 10:43:26 +03:00
func ( org * User ) IsOwnedBy ( uid int64 ) ( bool , error ) {
2016-07-23 20:08:22 +03:00
return IsOrganizationOwner ( org . ID , uid )
2014-06-30 00:30:41 +04:00
}
// IsOrgMember returns true if given user is member of organization.
2017-12-21 10:43:26 +03:00
func ( org * User ) IsOrgMember ( uid int64 ) ( bool , error ) {
return IsOrganizationMember ( org . ID , uid )
2014-06-30 00:30:41 +04:00
}
2019-11-20 14:27:49 +03:00
// CanCreateOrgRepo returns true if given user can create repo in organization
func ( org * User ) CanCreateOrgRepo ( uid int64 ) ( bool , error ) {
return CanCreateOrgRepo ( org . ID , uid )
}
2015-02-13 08:58:46 +03:00
func ( org * User ) getTeam ( e Engine , name string ) ( * Team , error ) {
2016-07-23 20:08:22 +03:00
return getTeam ( e , org . ID , name )
2015-02-13 08:58:46 +03:00
}
2014-08-16 12:21:17 +04:00
// GetTeam returns named team of organization.
func ( org * User ) GetTeam ( name string ) ( * Team , error ) {
2015-02-13 08:58:46 +03:00
return org . getTeam ( x , name )
}
func ( org * User ) getOwnerTeam ( e Engine ) ( * Team , error ) {
2016-11-28 04:30:08 +03:00
return org . getTeam ( e , ownerTeamName )
2014-08-16 12:21:17 +04:00
}
2014-06-28 08:40:07 +04:00
// GetOwnerTeam returns owner team of organization.
func ( org * User ) GetOwnerTeam ( ) ( * Team , error ) {
2015-02-13 08:58:46 +03:00
return org . getOwnerTeam ( x )
}
func ( org * User ) getTeams ( e Engine ) error {
2019-11-06 12:37:14 +03:00
if org . Teams != nil {
return nil
}
2016-11-10 18:16:32 +03:00
return e .
Where ( "org_id=?" , org . ID ) .
2016-11-28 04:30:08 +03:00
OrderBy ( "CASE WHEN name LIKE '" + ownerTeamName + "' THEN '' ELSE name END" ) .
2016-11-10 18:16:32 +03:00
Find ( & org . Teams )
2014-06-28 08:40:07 +04:00
}
2020-01-24 22:00:29 +03:00
// GetTeams returns paginated teams that belong to organization.
func ( org * User ) GetTeams ( opts * SearchTeamOptions ) error {
if opts . Page != 0 {
return org . getTeams ( opts . getPaginatedSession ( ) )
}
2015-02-13 08:58:46 +03:00
return org . getTeams ( x )
2014-06-28 23:43:25 +04:00
}
// GetMembers returns all members of organization.
2019-12-06 08:34:54 +03:00
func ( org * User ) GetMembers ( ) ( err error ) {
2020-01-24 22:00:29 +03:00
org . Members , org . MembersIsPublic , err = FindOrgMembers ( & FindOrgMembersOpts {
2019-12-06 08:34:54 +03:00
OrgID : org . ID ,
} )
return
}
2021-07-08 14:38:13 +03:00
// FindOrgMembersOpts represensts find org members conditions
2019-12-06 08:34:54 +03:00
type FindOrgMembersOpts struct {
2020-01-24 22:00:29 +03:00
ListOptions
2019-12-06 08:34:54 +03:00
OrgID int64
PublicOnly bool
}
// CountOrgMembers counts the organization's members
func CountOrgMembers ( opts FindOrgMembersOpts ) ( int64 , error ) {
sess := x . Where ( "org_id=?" , opts . OrgID )
if opts . PublicOnly {
sess . And ( "is_public = ?" , true )
}
return sess . Count ( new ( OrgUser ) )
}
// FindOrgMembers loads organization members according conditions
2020-01-24 22:00:29 +03:00
func FindOrgMembers ( opts * FindOrgMembersOpts ) ( UserList , map [ int64 ] bool , error ) {
ous , err := GetOrgUsersByOrgID ( opts )
2014-06-28 23:43:25 +04:00
if err != nil {
2019-12-06 08:34:54 +03:00
return nil , nil , err
2014-06-28 23:43:25 +04:00
}
2021-03-14 21:52:12 +03:00
ids := make ( [ ] int64 , len ( ous ) )
idsIsPublic := make ( map [ int64 ] bool , len ( ous ) )
2014-06-28 23:43:25 +04:00
for i , ou := range ous {
2016-11-26 03:20:18 +03:00
ids [ i ] = ou . UID
2019-08-02 19:06:28 +03:00
idsIsPublic [ ou . UID ] = ou . IsPublic
2014-06-28 23:43:25 +04:00
}
2019-12-06 08:34:54 +03:00
users , err := GetUsersByIDs ( ids )
if err != nil {
return nil , nil , err
}
return users , idsIsPublic , nil
2014-06-28 23:43:25 +04:00
}
2014-08-15 14:29:41 +04:00
// AddMember adds new member to organization.
func ( org * User ) AddMember ( uid int64 ) error {
2016-07-23 20:08:22 +03:00
return AddOrgUser ( org . ID , uid )
2014-08-15 14:29:41 +04:00
}
// RemoveMember removes member from organization.
func ( org * User ) RemoveMember ( uid int64 ) error {
2016-07-23 20:08:22 +03:00
return RemoveOrgUser ( org . ID , uid )
2014-08-15 14:29:41 +04:00
}
2015-03-01 05:44:09 +03:00
func ( org * User ) removeOrgRepo ( e Engine , repoID int64 ) error {
2016-07-23 20:08:22 +03:00
return removeOrgRepo ( e , org . ID , repoID )
2015-03-01 05:44:09 +03:00
}
// RemoveOrgRepo removes all team-repository relations of organization.
func ( org * User ) RemoveOrgRepo ( repoID int64 ) error {
return org . removeOrgRepo ( x , repoID )
}
2014-06-27 11:37:01 +04:00
// CreateOrganization creates record of a new organization.
2015-03-27 00:11:47 +03:00
func CreateOrganization ( org , owner * User ) ( err error ) {
2016-12-31 05:33:30 +03:00
if ! owner . CanCreateOrganization ( ) {
return ErrUserNotAllowedCreateOrg { }
}
2016-07-23 13:58:18 +03:00
if err = IsUsableUsername ( org . Name ) ; err != nil {
2015-03-27 00:11:47 +03:00
return err
2014-06-27 11:37:01 +04:00
}
2015-02-23 02:24:49 +03:00
isExist , err := IsUserExist ( 0 , org . Name )
2014-06-27 11:37:01 +04:00
if err != nil {
2015-03-27 00:11:47 +03:00
return err
2014-06-27 11:37:01 +04:00
} else if isExist {
2015-03-27 00:11:47 +03:00
return ErrUserAlreadyExist { org . Name }
2014-06-27 11:37:01 +04:00
}
org . LowerName = strings . ToLower ( org . Name )
2016-12-20 15:32:02 +03:00
if org . Rands , err = GetUserSalt ( ) ; err != nil {
return err
}
if org . Salt , err = GetUserSalt ( ) ; err != nil {
return err
}
2015-09-06 17:08:14 +03:00
org . UseCustomAvatar = true
2015-12-11 23:48:02 +03:00
org . MaxRepoCreation = - 1
2014-06-27 11:37:01 +04:00
org . NumTeams = 1
org . NumMembers = 1
2017-01-24 19:16:36 +03:00
org . Type = UserTypeOrganization
2014-06-27 11:37:01 +04:00
sess := x . NewSession ( )
2017-06-21 03:57:05 +03:00
defer sess . Close ( )
2014-06-27 11:37:01 +04:00
if err = sess . Begin ( ) ; err != nil {
2015-03-27 00:11:47 +03:00
return err
2014-06-27 11:37:01 +04:00
}
2021-01-24 18:23:05 +03:00
if err = deleteUserRedirect ( sess , org . Name ) ; err != nil {
return err
}
2014-06-27 11:37:01 +04:00
if _ , err = sess . Insert ( org ) ; err != nil {
2015-03-27 00:11:47 +03:00
return fmt . Errorf ( "insert organization: %v" , err )
2014-07-05 06:43:39 +04:00
}
2017-03-08 18:05:15 +03:00
if err = org . generateRandomAvatar ( sess ) ; err != nil {
return fmt . Errorf ( "generate random avatar: %v" , err )
}
2015-09-06 17:08:14 +03:00
// Add initial creator to organization and owner team.
if _ , err = sess . Insert ( & OrgUser {
2018-01-08 10:48:37 +03:00
UID : owner . ID ,
OrgID : org . ID ,
2015-09-06 17:08:14 +03:00
} ) ; err != nil {
return fmt . Errorf ( "insert org-user relation: %v" , err )
}
2014-07-05 06:43:39 +04:00
2014-06-27 11:37:01 +04:00
// Create default owner team.
t := & Team {
2019-11-06 12:37:14 +03:00
OrgID : org . ID ,
LowerName : strings . ToLower ( ownerTeamName ) ,
Name : ownerTeamName ,
Authorize : AccessModeOwner ,
NumMembers : 1 ,
IncludesAllRepositories : true ,
2019-11-20 14:27:49 +03:00
CanCreateOrgRepo : true ,
2014-06-27 11:37:01 +04:00
}
if _ , err = sess . Insert ( t ) ; err != nil {
2015-03-27 00:11:47 +03:00
return fmt . Errorf ( "insert owner team: %v" , err )
2014-06-27 11:37:01 +04:00
}
2018-06-21 19:00:13 +03:00
// insert units for team
2021-03-14 21:52:12 +03:00
units := make ( [ ] TeamUnit , 0 , len ( AllRepoUnitTypes ) )
2019-05-30 18:09:05 +03:00
for _ , tp := range AllRepoUnitTypes {
2018-06-21 19:00:13 +03:00
units = append ( units , TeamUnit {
OrgID : org . ID ,
TeamID : t . ID ,
Type : tp ,
} )
}
if _ , err = sess . Insert ( & units ) ; err != nil {
2019-06-12 22:41:28 +03:00
if err := sess . Rollback ( ) ; err != nil {
log . Error ( "CreateOrganization: sess.Rollback: %v" , err )
}
2018-06-21 19:00:13 +03:00
return err
}
2015-09-06 17:08:14 +03:00
if _ , err = sess . Insert ( & TeamUser {
2016-11-28 04:30:08 +03:00
UID : owner . ID ,
2016-07-23 20:08:22 +03:00
OrgID : org . ID ,
2015-02-23 10:15:53 +03:00
TeamID : t . ID ,
2015-09-06 17:08:14 +03:00
} ) ; err != nil {
2015-03-27 00:11:47 +03:00
return fmt . Errorf ( "insert team-user relation: %v" , err )
2015-02-23 10:15:53 +03:00
}
2015-03-27 00:11:47 +03:00
return sess . Commit ( )
2014-06-27 11:37:01 +04:00
}
2014-12-13 04:30:32 +03:00
// GetOrgByName returns organization by given name.
func GetOrgByName ( name string ) ( * User , error ) {
if len ( name ) == 0 {
2017-07-06 16:30:19 +03:00
return nil , ErrOrgNotExist { 0 , name }
2014-12-13 04:30:32 +03:00
}
u := & User {
LowerName : strings . ToLower ( name ) ,
2016-11-07 19:53:22 +03:00
Type : UserTypeOrganization ,
2014-12-13 04:30:32 +03:00
}
has , err := x . Get ( u )
if err != nil {
return nil , err
} else if ! has {
2017-07-06 16:30:19 +03:00
return nil , ErrOrgNotExist { 0 , name }
2014-12-13 04:30:32 +03:00
}
return u , nil
}
2014-08-28 18:29:00 +04:00
// CountOrganizations returns number of organizations.
func CountOrganizations ( ) int64 {
2016-11-10 18:16:32 +03:00
count , _ := x .
Where ( "type=1" ) .
Count ( new ( User ) )
2014-08-28 18:29:00 +04:00
return count
}
2014-06-28 08:40:07 +04:00
// DeleteOrganization completely and permanently deletes everything of organization.
func DeleteOrganization ( org * User ) ( err error ) {
2020-02-04 17:27:18 +03:00
if ! org . IsOrganization ( ) {
return fmt . Errorf ( "%s is a user not an organization" , org . Name )
}
2014-06-28 08:40:07 +04:00
sess := x . NewSession ( )
2016-12-27 05:02:14 +03:00
defer sess . Close ( )
2014-06-28 08:40:07 +04:00
if err = sess . Begin ( ) ; err != nil {
return err
}
2017-01-11 16:10:43 +03:00
if err = deleteOrg ( sess , org ) ; err != nil {
if IsErrUserOwnRepos ( err ) {
return err
} else if err != nil {
return fmt . Errorf ( "deleteOrg: %v" , err )
}
}
2017-09-19 11:08:30 +03:00
return sess . Commit ( )
2017-01-11 16:10:43 +03:00
}
func deleteOrg ( e * xorm . Session , u * User ) error {
// Check ownership of repository.
count , err := getRepositoryCount ( e , u )
if err != nil {
return fmt . Errorf ( "GetRepositoryCount: %v" , err )
} else if count > 0 {
return ErrUserOwnRepos { UID : u . ID }
}
if err := deleteBeans ( e ,
& Team { OrgID : u . ID } ,
& OrgUser { OrgID : u . ID } ,
& TeamUser { OrgID : u . ID } ,
2018-06-21 19:00:13 +03:00
& TeamUnit { OrgID : u . ID } ,
2015-09-06 15:54:08 +03:00
) ; err != nil {
return fmt . Errorf ( "deleteBeans: %v" , err )
2014-06-28 08:40:07 +04:00
}
2015-09-06 15:54:08 +03:00
2017-10-05 07:43:04 +03:00
if _ , err = e . ID ( u . ID ) . Delete ( new ( User ) ) ; err != nil {
2017-01-11 16:10:43 +03:00
return fmt . Errorf ( "Delete: %v" , err )
2014-06-28 08:40:07 +04:00
}
2015-09-06 15:54:08 +03:00
2017-01-11 16:10:43 +03:00
// FIXME: system notice
// Note: There are something just cannot be roll back,
// so just keep error logs of those operations.
path := UserPath ( u . Name )
2020-08-11 23:05:34 +03:00
if err := util . RemoveAll ( path ) ; err != nil {
2017-01-29 23:13:57 +03:00
return fmt . Errorf ( "Failed to RemoveAll %s: %v" , path , err )
2017-01-11 16:10:43 +03:00
}
2017-03-06 11:07:18 +03:00
if len ( u . Avatar ) > 0 {
2020-10-14 16:07:51 +03:00
avatarPath := u . CustomAvatarRelativePath ( )
if err := storage . Avatars . Delete ( avatarPath ) ; err != nil {
return fmt . Errorf ( "Failed to remove %s: %v" , avatarPath , err )
2017-01-11 16:10:43 +03:00
}
2016-12-27 05:02:14 +03:00
}
2017-01-11 16:10:43 +03:00
return nil
2014-06-28 08:40:07 +04:00
}
2014-06-25 08:44:48 +04:00
// ________ ____ ___
// \_____ \_______ ____ | | \______ ___________
// / | \_ __ \/ ___\| | / ___// __ \_ __ \
// / | \ | \/ /_/ > | /\___ \\ ___/| | \/
// \_______ /__| \___ /|______//____ >\___ >__|
// \/ /_____/ \/ \/
// OrgUser represents an organization-user relation.
type OrgUser struct {
2015-02-23 10:15:53 +03:00
ID int64 ` xorm:"pk autoincr" `
2016-11-26 03:20:18 +03:00
UID int64 ` xorm:"INDEX UNIQUE(s)" `
2015-02-23 10:15:53 +03:00
OrgID int64 ` xorm:"INDEX UNIQUE(s)" `
2017-01-06 18:14:33 +03:00
IsPublic bool ` xorm:"INDEX" `
2018-01-08 10:48:37 +03:00
}
func isOrganizationOwner ( e Engine , orgID , uid int64 ) ( bool , error ) {
2019-08-02 19:06:28 +03:00
ownerTeam , err := getOwnerTeam ( e , orgID )
if err != nil {
2019-09-23 23:08:03 +03:00
if IsErrTeamNotExist ( err ) {
2019-08-02 19:06:28 +03:00
log . Error ( "Organization does not have owner team: %d" , orgID )
return false , nil
}
2018-01-08 10:48:37 +03:00
return false , err
}
return isTeamMember ( e , orgID , ownerTeam . ID , uid )
2014-06-25 08:44:48 +04:00
}
2014-06-30 00:30:41 +04:00
// IsOrganizationOwner returns true if given user is in the owner team.
2017-12-21 10:43:26 +03:00
func IsOrganizationOwner ( orgID , uid int64 ) ( bool , error ) {
2018-01-08 10:48:37 +03:00
return isOrganizationOwner ( x , orgID , uid )
2014-06-30 00:30:41 +04:00
}
// IsOrganizationMember returns true if given user is member of organization.
2017-12-21 10:43:26 +03:00
func IsOrganizationMember ( orgID , uid int64 ) ( bool , error ) {
2019-01-14 05:29:58 +03:00
return isOrganizationMember ( x , orgID , uid )
}
func isOrganizationMember ( e Engine , orgID , uid int64 ) ( bool , error ) {
return e .
2016-11-10 18:16:32 +03:00
Where ( "uid=?" , uid ) .
2016-11-26 03:20:18 +03:00
And ( "org_id=?" , orgID ) .
2017-12-21 10:43:26 +03:00
Table ( "org_user" ) .
Exist ( )
2014-06-30 00:30:41 +04:00
}
2014-12-07 04:22:48 +03:00
// IsPublicMembership returns true if given user public his/her membership.
2017-12-21 10:43:26 +03:00
func IsPublicMembership ( orgID , uid int64 ) ( bool , error ) {
return x .
2016-11-10 18:16:32 +03:00
Where ( "uid=?" , uid ) .
2016-11-26 03:20:18 +03:00
And ( "org_id=?" , orgID ) .
2016-11-10 18:16:32 +03:00
And ( "is_public=?" , true ) .
2017-12-21 10:43:26 +03:00
Table ( "org_user" ) .
Exist ( )
2014-08-15 14:29:41 +04:00
}
2019-11-20 14:27:49 +03:00
// CanCreateOrgRepo returns true if user can create repo in organization
func CanCreateOrgRepo ( orgID , uid int64 ) ( bool , error ) {
if owner , err := IsOrganizationOwner ( orgID , uid ) ; owner || err != nil {
return owner , err
}
return x .
Where ( builder . Eq { "team.can_create_org_repo" : true } ) .
Join ( "INNER" , "team_user" , "team_user.team_id = team.id" ) .
And ( "team_user.uid = ?" , uid ) .
And ( "team_user.org_id = ?" , orgID ) .
Exist ( new ( Team ) )
}
2021-03-01 03:47:30 +03:00
// GetUsersWhoCanCreateOrgRepo returns users which are able to create repo in organization
func GetUsersWhoCanCreateOrgRepo ( orgID int64 ) ( [ ] * User , error ) {
return getUsersWhoCanCreateOrgRepo ( x , orgID )
}
func getUsersWhoCanCreateOrgRepo ( e Engine , orgID int64 ) ( [ ] * User , error ) {
users := make ( [ ] * User , 0 , 10 )
return users , x .
Join ( "INNER" , "`team_user`" , "`team_user`.uid=`user`.id" ) .
Join ( "INNER" , "`team`" , "`team`.id=`team_user`.team_id" ) .
Where ( builder . Eq { "team.can_create_org_repo" : true } . Or ( builder . Eq { "team.authorize" : AccessModeOwner } ) ) .
And ( "team_user.org_id = ?" , orgID ) . Asc ( "`user`.name" ) . Find ( & users )
}
2016-02-20 02:10:03 +03:00
func getOrgsByUserID ( sess * xorm . Session , userID int64 , showAll bool ) ( [ ] * User , error ) {
2016-01-31 00:51:11 +03:00
orgs := make ( [ ] * User , 0 , 10 )
2016-02-20 02:10:03 +03:00
if ! showAll {
sess . And ( "`org_user`.is_public=?" , true )
}
2016-11-10 11:10:35 +03:00
return orgs , sess .
And ( "`org_user`.uid=?" , userID ) .
Join ( "INNER" , "`org_user`" , "`org_user`.org_id=`user`.id" ) .
Asc ( "`user`.name" ) .
Find ( & orgs )
2016-01-31 00:51:11 +03:00
}
2016-02-15 04:36:03 +03:00
// GetOrgsByUserID returns a list of organizations that the given user ID
// has joined.
2016-02-20 02:10:03 +03:00
func GetOrgsByUserID ( userID int64 , showAll bool ) ( [ ] * User , error ) {
2017-01-27 19:11:41 +03:00
sess := x . NewSession ( )
defer sess . Close ( )
return getOrgsByUserID ( sess , userID , showAll )
2016-01-31 00:51:11 +03:00
}
2021-06-14 15:18:09 +03:00
// queryUserOrgIDs returns a condition to return user's organization id
func queryUserOrgIDs ( uid int64 ) * builder . Builder {
return builder . Select ( "team.org_id" ) .
From ( "team_user" ) . InnerJoin ( "team" , "team.id = team_user.team_id" ) .
Where ( builder . Eq { "team_user.uid" : uid } )
}
// MinimalOrg represents a simple orgnization with only needed columns
type MinimalOrg = User
// GetUserOrgsList returns one user's all orgs list
func GetUserOrgsList ( uid int64 ) ( [ ] * MinimalOrg , error ) {
var orgs = make ( [ ] * MinimalOrg , 0 , 20 )
return orgs , x . Select ( "id, name, full_name, visibility, avatar, avatar_email, use_custom_avatar" ) .
Table ( "user" ) .
In ( "id" , queryUserOrgIDs ( uid ) ) .
Find ( & orgs )
}
2015-09-07 20:58:23 +03:00
func getOwnedOrgsByUserID ( sess * xorm . Session , userID int64 ) ( [ ] * User , error ) {
orgs := make ( [ ] * User , 0 , 10 )
2016-11-10 11:10:35 +03:00
return orgs , sess .
2018-01-08 10:48:37 +03:00
Join ( "INNER" , "`team_user`" , "`team_user`.org_id=`user`.id" ) .
Join ( "INNER" , "`team`" , "`team`.id=`team_user`.team_id" ) .
Where ( "`team_user`.uid=?" , userID ) .
And ( "`team`.authorize=?" , AccessModeOwner ) .
2016-11-10 11:10:35 +03:00
Asc ( "`user`.name" ) .
Find ( & orgs )
2015-09-07 20:58:23 +03:00
}
2021-06-26 22:53:14 +03:00
// HasOrgOrUserVisible tells if the given user can see the given org or user
func HasOrgOrUserVisible ( org , user * User ) bool {
return hasOrgOrUserVisible ( x , org , user )
2019-04-25 21:59:10 +03:00
}
2021-06-26 22:53:14 +03:00
func hasOrgOrUserVisible ( e Engine , orgOrUser , user * User ) bool {
2019-02-18 19:00:27 +03:00
// Not SignedUser
if user == nil {
2021-06-26 22:53:14 +03:00
return orgOrUser . Visibility == structs . VisibleTypePublic
2019-02-18 19:00:27 +03:00
}
2021-06-26 22:53:14 +03:00
if user . IsAdmin || orgOrUser . ID == user . ID {
2019-02-18 19:00:27 +03:00
return true
}
2021-06-26 22:53:14 +03:00
if ( orgOrUser . Visibility == structs . VisibleTypePrivate || user . IsRestricted ) && ! orgOrUser . hasMemberWithUserID ( e , user . ID ) {
2019-02-18 19:00:27 +03:00
return false
}
return true
}
// HasOrgsVisible tells if the given user can see at least one of the orgs provided
func HasOrgsVisible ( orgs [ ] * User , user * User ) bool {
if len ( orgs ) == 0 {
return false
}
for _ , org := range orgs {
2021-06-26 22:53:14 +03:00
if HasOrgOrUserVisible ( org , user ) {
2019-02-18 19:00:27 +03:00
return true
}
}
return false
}
2015-09-07 20:58:23 +03:00
// GetOwnedOrgsByUserID returns a list of organizations are owned by given user ID.
func GetOwnedOrgsByUserID ( userID int64 ) ( [ ] * User , error ) {
sess := x . NewSession ( )
2017-01-27 19:11:41 +03:00
defer sess . Close ( )
2015-09-07 20:58:23 +03:00
return getOwnedOrgsByUserID ( sess , userID )
}
2016-11-26 03:20:18 +03:00
// GetOwnedOrgsByUserIDDesc returns a list of organizations are owned by
2016-01-31 00:51:11 +03:00
// given user ID, ordered descending by the given condition.
2015-09-07 20:58:23 +03:00
func GetOwnedOrgsByUserIDDesc ( userID int64 , desc string ) ( [ ] * User , error ) {
2017-01-27 19:11:41 +03:00
return getOwnedOrgsByUserID ( x . Desc ( desc ) , userID )
2015-09-07 20:58:23 +03:00
}
2019-11-20 14:27:49 +03:00
// GetOrgsCanCreateRepoByUserID returns a list of organizations where given user ID
// are allowed to create repos.
func GetOrgsCanCreateRepoByUserID ( userID int64 ) ( [ ] * User , error ) {
orgs := make ( [ ] * User , 0 , 10 )
2020-05-07 16:24:59 +03:00
return orgs , x . Where ( builder . In ( "id" , builder . Select ( "`user`.id" ) . From ( "`user`" ) .
Join ( "INNER" , "`team_user`" , "`team_user`.org_id = `user`.id" ) .
Join ( "INNER" , "`team`" , "`team`.id = `team_user`.team_id" ) .
Where ( builder . Eq { "`team_user`.uid" : userID } ) .
And ( builder . Eq { "`team`.authorize" : AccessModeOwner } . Or ( builder . Eq { "`team`.can_create_org_repo" : true } ) ) ) ) .
2020-10-16 01:15:55 +03:00
Asc ( "`user`.name" ) .
Find ( & orgs )
2019-11-20 14:27:49 +03:00
}
2015-12-17 10:28:47 +03:00
// GetOrgUsersByUserID returns all organization-user relations by user ID.
2020-01-24 22:00:29 +03:00
func GetOrgUsersByUserID ( uid int64 , opts * SearchOrganizationsOptions ) ( [ ] * OrgUser , error ) {
2014-06-25 08:44:48 +04:00
ous := make ( [ ] * OrgUser , 0 , 10 )
2016-11-10 11:10:35 +03:00
sess := x .
2018-07-20 05:10:17 +03:00
Join ( "LEFT" , "`user`" , "`org_user`.org_id=`user`.id" ) .
2016-11-11 19:55:06 +03:00
Where ( "`org_user`.uid=?" , uid )
2020-01-24 22:00:29 +03:00
if ! opts . All {
2015-12-17 10:28:47 +03:00
// Only show public organizations
sess . And ( "is_public=?" , true )
}
2020-01-24 22:00:29 +03:00
if opts . PageSize != 0 {
sess = opts . setSessionPagination ( sess )
}
2016-11-10 11:10:35 +03:00
err := sess .
Asc ( "`user`.name" ) .
Find ( & ous )
2014-06-25 08:44:48 +04:00
return ous , err
}
2016-07-15 19:36:39 +03:00
// GetOrgUsersByOrgID returns all organization-user relations by organization ID.
2020-01-24 22:00:29 +03:00
func GetOrgUsersByOrgID ( opts * FindOrgMembersOpts ) ( [ ] * OrgUser , error ) {
return getOrgUsersByOrgID ( x , opts )
2019-01-05 00:51:27 +03:00
}
2020-01-24 22:00:29 +03:00
func getOrgUsersByOrgID ( e Engine , opts * FindOrgMembersOpts ) ( [ ] * OrgUser , error ) {
sess := e . Where ( "org_id=?" , opts . OrgID )
if opts . PublicOnly {
2019-12-06 08:34:54 +03:00
sess . And ( "is_public = ?" , true )
}
2020-01-24 22:00:29 +03:00
if opts . ListOptions . PageSize > 0 {
sess = opts . setSessionPagination ( sess )
ous := make ( [ ] * OrgUser , 0 , opts . PageSize )
return ous , sess . Find ( & ous )
2019-12-06 08:34:54 +03:00
}
2020-01-24 22:00:29 +03:00
var ous [ ] * OrgUser
return ous , sess . Find ( & ous )
2014-06-25 13:14:36 +04:00
}
2014-08-15 14:29:41 +04:00
// ChangeOrgUserStatus changes public or private membership status.
2016-07-24 09:32:46 +03:00
func ChangeOrgUserStatus ( orgID , uid int64 , public bool ) error {
2014-08-15 14:29:41 +04:00
ou := new ( OrgUser )
2016-11-10 18:16:32 +03:00
has , err := x .
Where ( "uid=?" , uid ) .
And ( "org_id=?" , orgID ) .
Get ( ou )
2014-08-15 14:29:41 +04:00
if err != nil {
return err
} else if ! has {
return nil
}
ou . IsPublic = public
2017-10-05 07:43:04 +03:00
_ , err = x . ID ( ou . ID ) . Cols ( "is_public" ) . Update ( ou )
2014-08-15 14:29:41 +04:00
return err
}
// AddOrgUser adds new user to given organization.
2016-07-24 09:32:46 +03:00
func AddOrgUser ( orgID , uid int64 ) error {
2017-12-21 10:43:26 +03:00
isAlreadyMember , err := IsOrganizationMember ( orgID , uid )
if err != nil || isAlreadyMember {
return err
2014-08-15 14:29:41 +04:00
}
sess := x . NewSession ( )
defer sess . Close ( )
if err := sess . Begin ( ) ; err != nil {
return err
}
2014-08-24 17:09:05 +04:00
ou := & OrgUser {
2019-08-24 15:28:59 +03:00
UID : uid ,
OrgID : orgID ,
IsPublic : setting . Service . DefaultOrgMemberVisible ,
2014-08-24 17:09:05 +04:00
}
2014-08-15 14:29:41 +04:00
if _ , err := sess . Insert ( ou ) ; err != nil {
2019-06-12 22:41:28 +03:00
if err := sess . Rollback ( ) ; err != nil {
log . Error ( "AddOrgUser: sess.Rollback: %v" , err )
}
2014-08-15 14:29:41 +04:00
return err
2016-07-24 09:32:46 +03:00
} else if _ , err = sess . Exec ( "UPDATE `user` SET num_members = num_members + 1 WHERE id = ?" , orgID ) ; err != nil {
2019-06-12 22:41:28 +03:00
if err := sess . Rollback ( ) ; err != nil {
log . Error ( "AddOrgUser: sess.Rollback: %v" , err )
}
2014-08-15 14:29:41 +04:00
return err
}
return sess . Commit ( )
}
2018-02-23 11:42:02 +03:00
func removeOrgUser ( sess * xorm . Session , orgID , userID int64 ) error {
2014-08-15 14:29:41 +04:00
ou := new ( OrgUser )
2018-07-27 02:41:36 +03:00
has , err := sess .
2016-11-10 18:16:32 +03:00
Where ( "uid=?" , userID ) .
And ( "org_id=?" , orgID ) .
Get ( ou )
2014-08-15 14:29:41 +04:00
if err != nil {
2015-03-18 04:51:39 +03:00
return fmt . Errorf ( "get org-user: %v" , err )
2014-08-15 14:29:41 +04:00
} else if ! has {
return nil
}
2018-10-29 16:48:37 +03:00
org , err := getUserByID ( sess , orgID )
2014-08-24 17:09:05 +04:00
if err != nil {
2016-07-24 09:32:46 +03:00
return fmt . Errorf ( "GetUserByID [%d]: %v" , orgID , err )
2014-08-24 17:09:05 +04:00
}
2016-07-24 09:32:46 +03:00
2014-08-16 12:21:17 +04:00
// Check if the user to delete is the last member in owner team.
2018-10-29 16:48:37 +03:00
if isOwner , err := isOrganizationOwner ( sess , orgID , userID ) ; err != nil {
2017-12-21 10:43:26 +03:00
return err
} else if isOwner {
2018-10-29 16:48:37 +03:00
t , err := org . getOwnerTeam ( sess )
2014-08-16 12:21:17 +04:00
if err != nil {
return err
}
if t . NumMembers == 1 {
2018-10-29 16:48:37 +03:00
if err := t . getMembers ( sess ) ; err != nil {
2017-12-13 01:26:31 +03:00
return err
}
if t . Members [ 0 ] . ID == userID {
return ErrLastOrgOwner { UID : userID }
}
2014-08-16 12:21:17 +04:00
}
}
2017-10-05 07:43:04 +03:00
if _ , err := sess . ID ( ou . ID ) . Delete ( ou ) ; err != nil {
2014-08-15 14:29:41 +04:00
return err
2016-07-24 09:32:46 +03:00
} else if _ , err = sess . Exec ( "UPDATE `user` SET num_members=num_members-1 WHERE id=?" , orgID ) ; err != nil {
2014-08-15 14:29:41 +04:00
return err
}
2016-07-24 09:32:46 +03:00
// Delete all repository accesses and unwatch them.
2018-10-29 16:48:37 +03:00
env , err := org . accessibleReposEnv ( sess , userID )
2017-01-25 18:41:38 +03:00
if err != nil {
return fmt . Errorf ( "AccessibleReposEnv: %v" , err )
}
repoIDs , err := env . RepoIDs ( 1 , org . NumRepos )
if err != nil {
2017-01-24 19:16:36 +03:00
return fmt . Errorf ( "GetUserRepositories [%d]: %v" , userID , err )
2017-01-25 18:41:38 +03:00
}
for _ , repoID := range repoIDs {
2017-01-24 19:16:36 +03:00
if err = watchRepo ( sess , userID , repoID , false ) ; err != nil {
2014-08-27 12:39:36 +04:00
return err
2014-08-24 17:09:05 +04:00
}
}
2016-08-10 21:06:51 +03:00
if len ( repoIDs ) > 0 {
2016-11-10 18:16:32 +03:00
if _ , err = sess .
2017-01-24 19:16:36 +03:00
Where ( "user_id = ?" , userID ) .
2016-11-10 18:16:32 +03:00
In ( "repo_id" , repoIDs ) .
Delete ( new ( Access ) ) ; err != nil {
2016-08-10 21:06:51 +03:00
return err
}
2016-07-24 09:32:46 +03:00
}
2014-08-24 17:09:05 +04:00
// Delete member in his/her teams.
2019-01-17 03:39:50 +03:00
teams , err := getUserOrgTeams ( sess , org . ID , userID )
2014-08-24 17:09:05 +04:00
if err != nil {
return err
}
2015-03-18 04:51:39 +03:00
for _ , t := range teams {
2017-02-24 09:25:09 +03:00
if err = removeTeamMember ( sess , t , userID ) ; err != nil {
2014-08-24 17:09:05 +04:00
return err
}
}
2018-02-23 11:42:02 +03:00
return nil
}
// RemoveOrgUser removes user from given organization.
func RemoveOrgUser ( orgID , userID int64 ) error {
sess := x . NewSession ( )
defer sess . Close ( )
if err := sess . Begin ( ) ; err != nil {
return err
}
if err := removeOrgUser ( sess , orgID , userID ) ; err != nil {
return err
}
2014-08-15 14:29:41 +04:00
return sess . Commit ( )
}
2015-03-01 05:44:09 +03:00
func removeOrgRepo ( e Engine , orgID , repoID int64 ) error {
2017-02-04 19:00:07 +03:00
teamRepos := make ( [ ] * TeamRepo , 0 , 10 )
if err := e . Find ( & teamRepos , & TeamRepo { OrgID : orgID , RepoID : repoID } ) ; err != nil {
return err
}
if len ( teamRepos ) == 0 {
return nil
}
if _ , err := e . Delete ( & TeamRepo {
2015-03-01 05:44:09 +03:00
OrgID : orgID ,
RepoID : repoID ,
2017-02-04 19:00:07 +03:00
} ) ; err != nil {
return err
}
teamIDs := make ( [ ] int64 , len ( teamRepos ) )
for i , teamRepo := range teamRepos {
2017-06-03 04:06:10 +03:00
teamIDs [ i ] = teamRepo . TeamID
2017-02-04 19:00:07 +03:00
}
2017-06-01 03:41:14 +03:00
_ , err := e . Decr ( "num_repos" ) . In ( "id" , teamIDs ) . Update ( new ( Team ) )
2015-03-01 05:44:09 +03:00
return err
}
2016-07-24 13:09:45 +03:00
func ( org * User ) getUserTeams ( e Engine , userID int64 , cols ... string ) ( [ ] * Team , error ) {
teams := make ( [ ] * Team , 0 , org . NumTeams )
2016-11-10 11:10:35 +03:00
return teams , e .
Where ( "`team_user`.org_id = ?" , org . ID ) .
Join ( "INNER" , "team_user" , "`team_user`.team_id = team.id" ) .
2018-07-20 05:10:17 +03:00
Join ( "INNER" , "`user`" , "`user`.id=team_user.uid" ) .
2016-11-10 11:10:35 +03:00
And ( "`team_user`.uid = ?" , userID ) .
Asc ( "`user`.name" ) .
Cols ( cols ... ) .
2016-11-10 18:16:32 +03:00
Find ( & teams )
2016-07-24 13:09:45 +03:00
}
2017-02-14 06:46:46 +03:00
func ( org * User ) getUserTeamIDs ( e Engine , userID int64 ) ( [ ] int64 , error ) {
teamIDs := make ( [ ] int64 , 0 , org . NumTeams )
return teamIDs , e .
Table ( "team" ) .
Cols ( "team.id" ) .
Where ( "`team_user`.org_id = ?" , org . ID ) .
Join ( "INNER" , "team_user" , "`team_user`.team_id = team.id" ) .
And ( "`team_user`.uid = ?" , userID ) .
Find ( & teamIDs )
}
2020-06-22 18:21:11 +03:00
// TeamsWithAccessToRepo returns all teams that have given access level to the repository.
2017-09-14 11:16:22 +03:00
func ( org * User ) TeamsWithAccessToRepo ( repoID int64 , mode AccessMode ) ( [ ] * Team , error ) {
return GetTeamsWithAccessToRepo ( org . ID , repoID , mode )
}
2016-11-27 14:59:12 +03:00
// GetUserTeamIDs returns of all team IDs of the organization that user is member of.
2016-07-24 09:32:46 +03:00
func ( org * User ) GetUserTeamIDs ( userID int64 ) ( [ ] int64 , error ) {
2017-02-14 06:46:46 +03:00
return org . getUserTeamIDs ( x , userID )
2016-07-24 09:32:46 +03:00
}
2016-11-26 03:20:18 +03:00
// GetUserTeams returns all teams that belong to user,
2016-07-24 13:09:45 +03:00
// and that the user has joined.
func ( org * User ) GetUserTeams ( userID int64 ) ( [ ] * Team , error ) {
return org . getUserTeams ( x , userID )
}
2017-01-25 18:41:38 +03:00
// AccessibleReposEnvironment operations involving the repositories that are
// accessible to a particular user
type AccessibleReposEnvironment interface {
CountRepos ( ) ( int64 , error )
RepoIDs ( page , pageSize int ) ( [ ] int64 , error )
Repos ( page , pageSize int ) ( [ ] * Repository , error )
MirrorRepos ( ) ( [ ] * Repository , error )
2019-02-08 19:45:43 +03:00
AddKeyword ( keyword string )
2019-04-24 21:20:22 +03:00
SetSort ( SearchOrderBy )
2017-01-25 18:41:38 +03:00
}
2016-12-29 11:53:33 +03:00
2017-01-25 18:41:38 +03:00
type accessibleReposEnv struct {
org * User
2020-01-13 20:33:46 +03:00
user * User
2020-12-27 22:58:03 +03:00
team * Team
2017-01-25 18:41:38 +03:00
teamIDs [ ] int64
2018-10-29 16:48:37 +03:00
e Engine
2019-02-08 19:45:43 +03:00
keyword string
2019-04-24 21:20:22 +03:00
orderBy SearchOrderBy
2017-01-25 18:41:38 +03:00
}
2021-01-13 07:19:17 +03:00
// AccessibleReposEnv builds an AccessibleReposEnvironment for the repositories in `org`
2017-01-25 18:41:38 +03:00
// that are accessible to the specified user.
func ( org * User ) AccessibleReposEnv ( userID int64 ) ( AccessibleReposEnvironment , error ) {
2018-10-29 16:48:37 +03:00
return org . accessibleReposEnv ( x , userID )
}
func ( org * User ) accessibleReposEnv ( e Engine , userID int64 ) ( AccessibleReposEnvironment , error ) {
2020-01-13 20:33:46 +03:00
var user * User
if userID > 0 {
u , err := getUserByID ( e , userID )
if err != nil {
return nil , err
}
user = u
}
2018-10-29 16:48:37 +03:00
teamIDs , err := org . getUserTeamIDs ( e , userID )
2016-07-24 09:32:46 +03:00
if err != nil {
2017-01-25 18:41:38 +03:00
return nil , err
2016-01-31 21:13:39 +03:00
}
2018-10-29 16:48:37 +03:00
return & accessibleReposEnv {
org : org ,
2020-01-13 20:33:46 +03:00
user : user ,
2018-10-29 16:48:37 +03:00
teamIDs : teamIDs ,
e : e ,
2019-04-24 21:20:22 +03:00
orderBy : SearchOrderByRecentUpdated ,
2018-10-29 16:48:37 +03:00
} , nil
2017-01-25 18:41:38 +03:00
}
2016-12-29 11:53:33 +03:00
2020-12-27 22:58:03 +03:00
// AccessibleTeamReposEnv an AccessibleReposEnvironment for the repositories in `org`
// that are accessible to the specified team.
func ( org * User ) AccessibleTeamReposEnv ( team * Team ) AccessibleReposEnvironment {
return & accessibleReposEnv {
org : org ,
team : team ,
e : x ,
orderBy : SearchOrderByRecentUpdated ,
}
}
2017-01-25 18:41:38 +03:00
func ( env * accessibleReposEnv ) cond ( ) builder . Cond {
2021-03-14 21:52:12 +03:00
cond := builder . NewCond ( )
2020-12-27 22:58:03 +03:00
if env . team != nil {
cond = cond . And ( builder . Eq { "team_repo.team_id" : env . team . ID } )
} else {
if env . user == nil || ! env . user . IsRestricted {
cond = cond . Or ( builder . Eq {
"`repository`.owner_id" : env . org . ID ,
"`repository`.is_private" : false ,
} )
}
if len ( env . teamIDs ) > 0 {
cond = cond . Or ( builder . In ( "team_repo.team_id" , env . teamIDs ) )
}
2017-01-25 18:41:38 +03:00
}
2019-02-08 19:45:43 +03:00
if env . keyword != "" {
cond = cond . And ( builder . Like { "`repository`.lower_name" , strings . ToLower ( env . keyword ) } )
}
2017-01-25 18:41:38 +03:00
return cond
}
2016-01-31 21:13:39 +03:00
2017-01-25 18:41:38 +03:00
func ( env * accessibleReposEnv ) CountRepos ( ) ( int64 , error ) {
2018-10-29 16:48:37 +03:00
repoCount , err := env . e .
2017-01-25 18:41:38 +03:00
Join ( "INNER" , "team_repo" , "`team_repo`.repo_id=`repository`.id" ) .
Where ( env . cond ( ) ) .
2017-01-24 19:16:36 +03:00
Distinct ( "`repository`.id" ) .
2017-01-25 18:41:38 +03:00
Count ( & Repository { } )
if err != nil {
return 0 , fmt . Errorf ( "count user repositories in organization: %v" , err )
}
return repoCount , nil
}
func ( env * accessibleReposEnv ) RepoIDs ( page , pageSize int ) ( [ ] int64 , error ) {
2016-07-24 09:32:46 +03:00
if page <= 0 {
page = 1
}
2017-01-14 17:32:36 +03:00
2017-01-25 18:41:38 +03:00
repoIDs := make ( [ ] int64 , 0 , pageSize )
2018-10-29 16:48:37 +03:00
return repoIDs , env . e .
2017-01-25 18:41:38 +03:00
Table ( "repository" ) .
2016-11-10 18:16:32 +03:00
Join ( "INNER" , "team_repo" , "`team_repo`.repo_id=`repository`.id" ) .
2017-01-25 18:41:38 +03:00
Where ( env . cond ( ) ) .
2019-04-24 21:20:22 +03:00
GroupBy ( "`repository`.id,`repository`." + strings . Fields ( string ( env . orderBy ) ) [ 0 ] ) .
OrderBy ( string ( env . orderBy ) ) .
2016-11-10 18:16:32 +03:00
Limit ( pageSize , ( page - 1 ) * pageSize ) .
2017-01-25 18:41:38 +03:00
Cols ( "`repository`.id" ) .
Find ( & repoIDs )
}
2016-07-24 09:32:46 +03:00
2017-01-25 18:41:38 +03:00
func ( env * accessibleReposEnv ) Repos ( page , pageSize int ) ( [ ] * Repository , error ) {
repoIDs , err := env . RepoIDs ( page , pageSize )
2016-07-24 09:32:46 +03:00
if err != nil {
2017-01-25 18:41:38 +03:00
return nil , fmt . Errorf ( "GetUserRepositoryIDs: %v" , err )
2016-01-31 13:46:04 +03:00
}
2017-01-25 18:41:38 +03:00
repos := make ( [ ] * Repository , 0 , len ( repoIDs ) )
2018-10-21 00:25:14 +03:00
if len ( repoIDs ) == 0 {
2017-02-14 18:37:44 +03:00
return repos , nil
}
2018-10-29 16:48:37 +03:00
return repos , env . e .
2017-02-14 18:37:44 +03:00
In ( "`repository`.id" , repoIDs ) .
2019-04-24 21:20:22 +03:00
OrderBy ( string ( env . orderBy ) ) .
2017-01-25 18:41:38 +03:00
Find ( & repos )
2016-07-24 09:32:46 +03:00
}
2017-04-07 04:47:25 +03:00
func ( env * accessibleReposEnv ) MirrorRepoIDs ( ) ( [ ] int64 , error ) {
repoIDs := make ( [ ] int64 , 0 , 10 )
2018-10-29 16:48:37 +03:00
return repoIDs , env . e .
2017-04-07 04:47:25 +03:00
Table ( "repository" ) .
2016-11-10 18:16:32 +03:00
Join ( "INNER" , "team_repo" , "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?" , true ) .
2017-01-25 18:41:38 +03:00
Where ( env . cond ( ) ) .
2017-09-15 09:14:06 +03:00
GroupBy ( "`repository`.id, `repository`.updated_unix" ) .
2019-04-24 21:20:22 +03:00
OrderBy ( string ( env . orderBy ) ) .
2017-04-07 04:47:25 +03:00
Cols ( "`repository`.id" ) .
Find ( & repoIDs )
}
func ( env * accessibleReposEnv ) MirrorRepos ( ) ( [ ] * Repository , error ) {
repoIDs , err := env . MirrorRepoIDs ( )
if err != nil {
return nil , fmt . Errorf ( "MirrorRepoIDs: %v" , err )
}
repos := make ( [ ] * Repository , 0 , len ( repoIDs ) )
2018-10-21 00:25:14 +03:00
if len ( repoIDs ) == 0 {
2017-04-07 04:47:25 +03:00
return repos , nil
}
2018-10-29 16:48:37 +03:00
return repos , env . e .
2017-04-07 04:47:25 +03:00
In ( "`repository`.id" , repoIDs ) .
2016-11-10 18:16:32 +03:00
Find ( & repos )
2016-01-31 13:46:04 +03:00
}
2019-02-08 19:45:43 +03:00
func ( env * accessibleReposEnv ) AddKeyword ( keyword string ) {
env . keyword = keyword
}
2019-04-24 21:20:22 +03:00
func ( env * accessibleReposEnv ) SetSort ( orderBy SearchOrderBy ) {
env . orderBy = orderBy
}