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 (
2021-11-18 20:42:27 +03:00
"context"
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
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2022-03-29 09:29:02 +03:00
"code.gitea.io/gitea/models/organization"
2022-05-11 13:09:36 +03:00
access_model "code.gitea.io/gitea/models/perm/access"
2021-12-10 04:27:50 +03:00
repo_model "code.gitea.io/gitea/models/repo"
2021-11-11 10:03:30 +03:00
user_model "code.gitea.io/gitea/models/user"
2018-01-08 10:48:37 +03:00
2019-06-23 18:22:43 +03:00
"xorm.io/builder"
2014-06-27 11:37:01 +04:00
)
2021-06-14 15:18:09 +03:00
// MinimalOrg represents a simple orgnization with only needed columns
2022-03-29 09:29:02 +03:00
type MinimalOrg = organization . Organization
2021-06-14 15:18:09 +03:00
// GetUserOrgsList returns one user's all orgs list
2021-11-24 12:49:20 +03:00
func GetUserOrgsList ( user * user_model . User ) ( [ ] * MinimalOrg , error ) {
schema , err := db . TableInfo ( new ( user_model . User ) )
2021-09-01 08:31:42 +03:00
if err != nil {
return nil , err
}
outputCols := [ ] string {
"id" ,
"name" ,
"full_name" ,
"visibility" ,
"avatar" ,
"avatar_email" ,
"use_custom_avatar" ,
}
groupByCols := & strings . Builder { }
for _ , col := range outputCols {
fmt . Fprintf ( groupByCols , "`%s`.%s," , schema . Name , col )
}
groupByStr := groupByCols . String ( )
groupByStr = groupByStr [ 0 : len ( groupByStr ) - 1 ]
2021-11-21 18:41:00 +03:00
sess := db . GetEngine ( db . DefaultContext )
sess = sess . Select ( groupByStr + ", count(distinct repo_id) as org_count" ) .
2021-06-14 15:18:09 +03:00
Table ( "user" ) .
2021-09-01 08:31:42 +03:00
Join ( "INNER" , "team" , "`team`.org_id = `user`.id" ) .
Join ( "INNER" , "team_user" , "`team`.id = `team_user`.team_id" ) .
Join ( "LEFT" , builder .
Select ( "id as repo_id, owner_id as repo_owner_id" ) .
From ( "repository" ) .
Where ( accessibleRepositoryCondition ( user ) ) , "`repository`.repo_owner_id = `team`.org_id" ) .
Where ( "`team_user`.uid = ?" , user . ID ) .
GroupBy ( groupByStr )
type OrgCount struct {
2022-03-29 09:29:02 +03:00
organization . Organization ` xorm:"extends" `
OrgCount int
2021-09-01 08:31:42 +03:00
}
orgCounts := make ( [ ] * OrgCount , 0 , 10 )
if err := sess .
Asc ( "`user`.name" ) .
Find ( & orgCounts ) ; err != nil {
return nil , err
}
orgs := make ( [ ] * MinimalOrg , len ( orgCounts ) )
for i , orgCount := range orgCounts {
2021-11-19 14:41:40 +03:00
orgCount . Organization . NumRepos = orgCount . OrgCount
orgs [ i ] = & orgCount . Organization
2021-09-01 08:31:42 +03:00
}
return orgs , nil
2021-06-14 15:18:09 +03:00
}
2021-11-19 14:41:40 +03:00
func removeOrgUser ( ctx context . Context , orgID , userID int64 ) error {
2022-03-29 09:29:02 +03:00
ou := new ( organization . OrgUser )
2014-08-15 14:29:41 +04:00
2021-11-19 14:41:40 +03:00
sess := db . GetEngine ( ctx )
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
}
2022-03-29 09:29:02 +03:00
org , err := organization . GetOrgByIDCtx ( ctx , 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.
2022-03-29 09:29:02 +03:00
if isOwner , err := organization . IsOrganizationOwner ( ctx , orgID , userID ) ; err != nil {
2017-12-21 10:43:26 +03:00
return err
} else if isOwner {
2022-03-29 09:29:02 +03:00
t , err := organization . GetOwnerTeam ( ctx , org . ID )
2014-08-16 12:21:17 +04:00
if err != nil {
return err
}
if t . NumMembers == 1 {
2022-03-29 09:29:02 +03:00
if err := t . GetMembersCtx ( ctx ) ; err != nil {
2017-12-13 01:26:31 +03:00
return err
}
if t . Members [ 0 ] . ID == userID {
2022-03-29 09:29:02 +03:00
return organization . ErrLastOrgOwner { UID : userID }
2017-12-13 01:26:31 +03:00
}
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.
2022-03-29 09:29:02 +03:00
env , err := organization . AccessibleReposEnv ( ctx , org , 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 {
2021-12-12 18:48:20 +03:00
if err = repo_model . WatchRepoCtx ( ctx , 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 ) .
2022-05-11 13:09:36 +03:00
Delete ( new ( access_model . 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.
2022-03-29 09:29:02 +03:00
teams , err := organization . GetUserOrgTeams ( ctx , 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 {
2021-11-19 14:41:40 +03:00
if err = removeTeamMember ( ctx , 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 {
2021-11-19 14:41:40 +03:00
ctx , committer , err := db . TxContext ( )
if err != nil {
2018-02-23 11:42:02 +03:00
return err
}
2021-11-19 14:41:40 +03:00
defer committer . Close ( )
if err := removeOrgUser ( ctx , orgID , userID ) ; err != nil {
2018-02-23 11:42:02 +03:00
return err
}
2021-11-19 14:41:40 +03:00
return committer . Commit ( )
2014-08-15 14:29:41 +04:00
}