2017-04-09 06:55:07 +08:00
package sqlstore
import (
2017-12-15 00:22:45 +08:00
"bytes"
2021-03-17 23:06:10 +08:00
"context"
2017-04-09 06:55:07 +08:00
"fmt"
2020-11-24 19:10:32 +08:00
"strings"
2017-04-09 06:55:07 +08:00
"time"
2019-08-13 02:03:48 +08:00
"github.com/grafana/grafana/pkg/models"
2022-01-27 23:16:44 +08:00
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
2017-04-09 06:55:07 +08:00
)
2022-01-24 18:52:35 +08:00
type TeamStore interface {
UpdateTeam ( ctx context . Context , cmd * models . UpdateTeamCommand ) error
DeleteTeam ( ctx context . Context , cmd * models . DeleteTeamCommand ) error
SearchTeams ( ctx context . Context , query * models . SearchTeamsQuery ) error
GetTeamById ( ctx context . Context , query * models . GetTeamByIdQuery ) error
UpdateTeamMember ( ctx context . Context , cmd * models . UpdateTeamMemberCommand ) error
RemoveTeamMember ( ctx context . Context , cmd * models . RemoveTeamMemberCommand ) error
GetTeamMembers ( ctx context . Context , cmd * models . GetTeamMembersQuery ) error
2022-02-10 00:46:37 +08:00
GetUserTeamMemberships ( ctx context . Context , orgID , userID int64 , external bool ) ( [ ] * models . TeamMemberDTO , error )
2022-01-24 18:52:35 +08:00
}
2020-11-24 19:10:32 +08:00
func getFilteredUsers ( signedInUser * models . SignedInUser , hiddenUsers map [ string ] struct { } ) [ ] string {
filteredUsers := make ( [ ] string , 0 , len ( hiddenUsers ) )
if signedInUser == nil || signedInUser . IsGrafanaAdmin {
return filteredUsers
}
for u := range hiddenUsers {
if u == signedInUser . Login {
continue
}
filteredUsers = append ( filteredUsers , u )
}
return filteredUsers
}
func getTeamMemberCount ( filteredUsers [ ] string ) string {
if len ( filteredUsers ) > 0 {
2021-03-17 23:06:10 +08:00
return ` ( SELECT COUNT ( * ) FROM team_member
2020-11-24 19:10:32 +08:00
INNER JOIN ` + dialect.Quote("user") + ` ON team_member . user_id = ` + dialect.Quote("user") + ` . id
WHERE team_member . team_id = team . id AND ` + dialect.Quote("user") + ` . login NOT IN ( ? ` +
strings . Repeat ( ",?" , len ( filteredUsers ) - 1 ) + ")" +
` ) AS member_count `
}
return "(SELECT COUNT(*) FROM team_member WHERE team_member.team_id = team.id) AS member_count "
}
func getTeamSelectSQLBase ( filteredUsers [ ] string ) string {
2018-07-12 02:23:07 +08:00
return ` SELECT
team . id as id ,
team . org_id ,
team . name as name ,
2020-11-24 19:10:32 +08:00
team . email as email , ` +
getTeamMemberCount ( filteredUsers ) +
` FROM team as team `
2018-07-12 02:23:07 +08:00
}
2022-02-16 01:09:03 +08:00
func getTeamSelectWithPermissionsSQLBase ( filteredUsers [ ] string ) string {
return ` SELECT
team . id AS id ,
team . org_id ,
team . name AS name ,
team . email AS email ,
team_member . permission , ` +
getTeamMemberCount ( filteredUsers ) +
` FROM team AS team
INNER JOIN team_member ON team . id = team_member . team_id AND team_member . user_id = ? `
}
2021-03-17 23:06:10 +08:00
func ( ss * SQLStore ) CreateTeam ( name , email string , orgID int64 ) ( models . Team , error ) {
team := models . Team {
Name : name ,
Email : email ,
OrgId : orgID ,
Created : time . Now ( ) ,
Updated : time . Now ( ) ,
}
err := ss . WithTransactionalDbSession ( context . Background ( ) , func ( sess * DBSession ) error {
if isNameTaken , err := isTeamNameTaken ( orgID , name , 0 , sess ) ; err != nil {
2017-04-09 06:55:07 +08:00
return err
} else if isNameTaken {
2019-08-13 02:03:48 +08:00
return models . ErrTeamNameTaken
2017-04-09 06:55:07 +08:00
}
2017-12-08 23:25:45 +08:00
_ , err := sess . Insert ( & team )
2017-04-09 06:55:07 +08:00
return err
} )
2021-03-17 23:06:10 +08:00
return team , err
2017-04-09 06:55:07 +08:00
}
2022-01-24 18:52:35 +08:00
func ( ss * SQLStore ) UpdateTeam ( ctx context . Context , cmd * models . UpdateTeamCommand ) error {
2022-01-26 03:30:08 +08:00
return ss . WithTransactionalDbSession ( ctx , func ( sess * DBSession ) error {
2018-02-10 00:26:15 +08:00
if isNameTaken , err := isTeamNameTaken ( cmd . OrgId , cmd . Name , cmd . Id , sess ) ; err != nil {
2017-04-18 21:01:05 +08:00
return err
} else if isNameTaken {
2019-08-13 02:03:48 +08:00
return models . ErrTeamNameTaken
2017-04-18 21:01:05 +08:00
}
2019-08-13 02:03:48 +08:00
team := models . Team {
2017-04-18 21:01:05 +08:00
Name : cmd . Name ,
2017-12-21 04:20:12 +08:00
Email : cmd . Email ,
2017-04-18 21:01:05 +08:00
Updated : time . Now ( ) ,
}
2017-12-21 04:20:12 +08:00
sess . MustCols ( "email" )
2018-09-16 18:37:08 +08:00
affectedRows , err := sess . ID ( cmd . Id ) . Update ( & team )
2017-04-18 21:01:05 +08:00
if err != nil {
return err
}
if affectedRows == 0 {
2019-08-13 02:03:48 +08:00
return models . ErrTeamNotFound
2017-04-18 21:01:05 +08:00
}
return nil
} )
}
2018-02-16 18:45:53 +08:00
// DeleteTeam will delete a team, its member and any permissions connected to the team
2022-01-24 18:52:35 +08:00
func ( ss * SQLStore ) DeleteTeam ( ctx context . Context , cmd * models . DeleteTeamCommand ) error {
2022-01-26 03:30:08 +08:00
return ss . WithTransactionalDbSession ( ctx , func ( sess * DBSession ) error {
2019-03-11 22:48:05 +08:00
if _ , err := teamExists ( cmd . OrgId , cmd . Id , sess ) ; err != nil {
2017-04-09 06:55:07 +08:00
return err
}
deletes := [ ] string {
2018-02-10 00:26:15 +08:00
"DELETE FROM team_member WHERE org_id=? and team_id = ?" ,
"DELETE FROM team WHERE org_id=? and id = ?" ,
"DELETE FROM dashboard_acl WHERE org_id=? and team_id = ?" ,
2022-01-27 23:16:44 +08:00
"DELETE FROM team_role WHERE org_id=? and team_id = ?" ,
2017-04-09 06:55:07 +08:00
}
for _ , sql := range deletes {
2018-02-10 00:26:15 +08:00
_ , err := sess . Exec ( sql , cmd . OrgId , cmd . Id )
2017-04-09 06:55:07 +08:00
if err != nil {
return err
}
}
2022-01-27 23:16:44 +08:00
_ , err := sess . Exec ( "DELETE FROM permission WHERE scope=?" , ac . Scope ( "teams" , "id" , fmt . Sprint ( cmd . Id ) ) )
return err
2017-04-09 06:55:07 +08:00
} )
}
2021-03-17 23:06:10 +08:00
func teamExists ( orgID int64 , teamID int64 , sess * DBSession ) ( bool , error ) {
if res , err := sess . Query ( "SELECT 1 from team WHERE org_id=? and id=?" , orgID , teamID ) ; err != nil {
2018-02-16 18:45:53 +08:00
return false , err
} else if len ( res ) != 1 {
2019-08-13 02:03:48 +08:00
return false , models . ErrTeamNotFound
2018-02-16 18:45:53 +08:00
}
return true , nil
}
2018-02-10 00:26:15 +08:00
func isTeamNameTaken ( orgId int64 , name string , existingId int64 , sess * DBSession ) ( bool , error ) {
2019-08-13 02:03:48 +08:00
var team models . Team
2018-02-10 00:26:15 +08:00
exists , err := sess . Where ( "org_id=? and name=?" , orgId , name ) . Get ( & team )
2017-04-09 06:55:07 +08:00
if err != nil {
return false , nil
}
2017-12-08 23:25:45 +08:00
if exists && existingId != team . Id {
2017-04-09 06:55:07 +08:00
return true , nil
}
return false , nil
}
2022-01-24 18:52:35 +08:00
func ( ss * SQLStore ) SearchTeams ( ctx context . Context , query * models . SearchTeamsQuery ) error {
2022-04-21 03:11:37 +08:00
return ss . WithDbSession ( ctx , func ( sess * DBSession ) error {
query . Result = models . SearchTeamQueryResult {
Teams : make ( [ ] * models . TeamDTO , 0 ) ,
}
queryWithWildcards := "%" + query . Query + "%"
2017-04-10 07:24:16 +08:00
2022-04-21 03:11:37 +08:00
var sql bytes . Buffer
params := make ( [ ] interface { } , 0 )
2017-12-15 00:22:45 +08:00
2022-04-21 03:11:37 +08:00
filteredUsers := getFilteredUsers ( query . SignedInUser , query . HiddenUsers )
for _ , user := range filteredUsers {
params = append ( params , user )
}
2022-02-09 20:44:38 +08:00
2022-04-21 03:11:37 +08:00
if query . UserIdFilter == models . FilterIgnoreUser {
sql . WriteString ( getTeamSelectSQLBase ( filteredUsers ) )
} else {
sql . WriteString ( getTeamSelectWithPermissionsSQLBase ( filteredUsers ) )
params = append ( params , query . UserIdFilter )
}
2017-12-15 00:22:45 +08:00
2022-04-21 03:11:37 +08:00
sql . WriteString ( ` WHERE team.org_id = ? ` )
params = append ( params , query . OrgId )
2017-06-24 02:55:53 +08:00
2022-04-21 03:11:37 +08:00
if query . Query != "" {
sql . WriteString ( ` and team.name ` + ss . Dialect . LikeStr ( ) + ` ? ` )
params = append ( params , queryWithWildcards )
}
2017-12-15 00:22:45 +08:00
2022-04-21 03:11:37 +08:00
if query . Name != "" {
sql . WriteString ( ` and team.name = ? ` )
params = append ( params , query . Name )
}
2017-06-24 02:55:53 +08:00
2022-04-21 03:11:37 +08:00
var (
acFilter ac . SQLFilter
err error
)
2022-05-05 23:31:14 +08:00
if ! ac . IsDisabled ( ss . Cfg ) {
2022-04-21 03:11:37 +08:00
acFilter , err = ac . Filter ( query . SignedInUser , "team.id" , "teams:id:" , ac . ActionTeamsRead )
if err != nil {
return err
}
sql . WriteString ( ` and ` + acFilter . Where )
params = append ( params , acFilter . Args ... )
2022-02-09 23:17:31 +08:00
}
2022-04-21 03:11:37 +08:00
sql . WriteString ( ` order by team.name asc ` )
2017-12-15 00:22:45 +08:00
2022-04-21 03:11:37 +08:00
if query . Limit != 0 {
offset := query . Limit * ( query . Page - 1 )
sql . WriteString ( ss . Dialect . LimitOffset ( int64 ( query . Limit ) , int64 ( offset ) ) )
}
2017-12-15 00:22:45 +08:00
2022-04-21 03:11:37 +08:00
if err := sess . SQL ( sql . String ( ) , params ... ) . Find ( & query . Result . Teams ) ; err != nil {
return err
}
2017-04-10 07:24:16 +08:00
2022-04-21 03:11:37 +08:00
team := models . Team { }
countSess := sess . Table ( "team" )
countSess . Where ( "team.org_id=?" , query . OrgId )
2022-02-09 20:44:38 +08:00
2022-04-21 03:11:37 +08:00
if query . Query != "" {
countSess . Where ( ` name ` + dialect . LikeStr ( ) + ` ? ` , queryWithWildcards )
}
2017-12-15 00:22:45 +08:00
2022-04-21 03:11:37 +08:00
if query . Name != "" {
countSess . Where ( "name=?" , query . Name )
}
2017-12-15 00:22:45 +08:00
2022-04-21 03:11:37 +08:00
// If we're not retrieving all results, then only search for teams that this user has access to
if query . UserIdFilter != models . FilterIgnoreUser {
countSess .
Where ( `
2022-02-09 20:44:38 +08:00
team . id IN (
SELECT
team_id
FROM team_member
WHERE team_member . user_id = ?
) ` , query . UserIdFilter )
2022-04-21 03:11:37 +08:00
}
2022-02-09 20:44:38 +08:00
2022-04-21 03:11:37 +08:00
// Only count teams user can see
2022-05-05 23:31:14 +08:00
if ! ac . IsDisabled ( ss . Cfg ) {
2022-04-21 03:11:37 +08:00
countSess . Where ( acFilter . Where , acFilter . Args ... )
}
2022-02-09 23:17:31 +08:00
2022-04-21 03:11:37 +08:00
count , err := countSess . Count ( & team )
query . Result . TotalCount = count
2017-04-10 07:24:16 +08:00
2022-04-21 03:11:37 +08:00
return err
} )
2017-04-09 06:55:07 +08:00
}
2022-01-24 18:52:35 +08:00
func ( ss * SQLStore ) GetTeamById ( ctx context . Context , query * models . GetTeamByIdQuery ) error {
2022-04-21 03:11:37 +08:00
return ss . WithDbSession ( ctx , func ( sess * DBSession ) error {
var sql bytes . Buffer
params := make ( [ ] interface { } , 0 )
2020-11-24 19:10:32 +08:00
2022-04-21 03:11:37 +08:00
filteredUsers := getFilteredUsers ( query . SignedInUser , query . HiddenUsers )
sql . WriteString ( getTeamSelectSQLBase ( filteredUsers ) )
for _ , user := range filteredUsers {
params = append ( params , user )
}
2018-07-12 02:23:07 +08:00
2022-04-21 03:11:37 +08:00
if query . UserIdFilter != models . FilterIgnoreUser {
sql . WriteString ( ` INNER JOIN team_member ON team.id = team_member.team_id AND team_member.user_id = ? ` )
params = append ( params , query . UserIdFilter )
}
2022-02-09 20:44:38 +08:00
2022-04-21 03:11:37 +08:00
sql . WriteString ( ` WHERE team.org_id = ? and team.id = ? ` )
params = append ( params , query . OrgId , query . Id )
2018-07-12 02:23:07 +08:00
2022-04-21 03:11:37 +08:00
var team models . TeamDTO
exists , err := sess . SQL ( sql . String ( ) , params ... ) . Get ( & team )
2018-07-12 02:23:07 +08:00
2022-04-21 03:11:37 +08:00
if err != nil {
return err
}
2017-04-09 06:55:07 +08:00
2022-04-21 03:11:37 +08:00
if ! exists {
return models . ErrTeamNotFound
}
2017-04-09 06:55:07 +08:00
2022-04-21 03:11:37 +08:00
query . Result = & team
return nil
} )
2017-04-09 06:55:07 +08:00
}
2018-02-16 18:45:53 +08:00
// GetTeamsByUser is used by the Guardian when checking a users' permissions
2022-01-26 03:30:08 +08:00
func ( ss * SQLStore ) GetTeamsByUser ( ctx context . Context , query * models . GetTeamsByUserQuery ) error {
return ss . WithDbSession ( ctx , func ( sess * DBSession ) error {
query . Result = make ( [ ] * models . TeamDTO , 0 )
2018-07-12 02:23:07 +08:00
2022-01-26 03:30:08 +08:00
var sql bytes . Buffer
2017-05-22 16:33:17 +08:00
2022-01-26 03:30:08 +08:00
sql . WriteString ( getTeamSelectSQLBase ( [ ] string { } ) )
sql . WriteString ( ` INNER JOIN team_member on team.id = team_member.team_id ` )
sql . WriteString ( ` WHERE team.org_id = ? and team_member.user_id = ? ` )
2017-05-22 16:33:17 +08:00
2022-01-26 03:30:08 +08:00
err := sess . SQL ( sql . String ( ) , query . OrgId , query . UserId ) . Find ( & query . Result )
return err
} )
2017-05-22 16:33:17 +08:00
}
2018-02-16 18:45:53 +08:00
// AddTeamMember adds a user to a team
2021-03-17 23:06:10 +08:00
func ( ss * SQLStore ) AddTeamMember ( userID , orgID , teamID int64 , isExternal bool , permission models . PermissionType ) error {
return ss . WithTransactionalDbSession ( context . Background ( ) , func ( sess * DBSession ) error {
2022-01-26 22:48:41 +08:00
if isMember , err := isTeamMember ( sess , orgID , teamID , userID ) ; err != nil {
2017-04-09 06:55:07 +08:00
return err
2022-01-26 22:48:41 +08:00
} else if isMember {
2019-08-13 02:03:48 +08:00
return models . ErrTeamMemberAlreadyAdded
2017-04-09 06:55:07 +08:00
}
2022-01-26 22:48:41 +08:00
return addTeamMember ( sess , orgID , teamID , userID , isExternal , permission )
2017-04-09 06:55:07 +08:00
} )
}
2019-08-13 02:03:48 +08:00
func getTeamMember ( sess * DBSession , orgId int64 , teamId int64 , userId int64 ) ( models . TeamMember , error ) {
2020-11-11 13:21:08 +08:00
rawSQL := ` SELECT * FROM team_member WHERE org_id=? and team_id=? and user_id=? `
2019-08-13 02:03:48 +08:00
var member models . TeamMember
2020-11-11 13:21:08 +08:00
exists , err := sess . SQL ( rawSQL , orgId , teamId , userId ) . Get ( & member )
2019-03-14 16:37:56 +08:00
if err != nil {
return member , err
}
if ! exists {
2019-08-13 02:03:48 +08:00
return member , models . ErrTeamMemberNotFound
2019-03-14 16:37:56 +08:00
}
return member , nil
}
2019-03-06 22:37:37 +08:00
// UpdateTeamMember updates a team member
2022-01-24 18:52:35 +08:00
func ( ss * SQLStore ) UpdateTeamMember ( ctx context . Context , cmd * models . UpdateTeamMemberCommand ) error {
2022-04-26 01:07:11 +08:00
return ss . WithTransactionalDbSession ( ctx , func ( sess * DBSession ) error {
2022-01-26 22:48:41 +08:00
return updateTeamMember ( sess , cmd . OrgId , cmd . TeamId , cmd . UserId , cmd . Permission )
} )
}
2019-03-06 22:37:37 +08:00
2022-01-26 22:48:41 +08:00
func ( ss * SQLStore ) IsTeamMember ( orgId int64 , teamId int64 , userId int64 ) ( bool , error ) {
var isMember bool
2019-03-13 17:11:53 +08:00
2022-01-26 22:48:41 +08:00
err := ss . WithTransactionalDbSession ( context . Background ( ) , func ( sess * DBSession ) error {
var err error
isMember , err = isTeamMember ( sess , orgId , teamId , userId )
return err
} )
2019-03-13 14:18:57 +08:00
2022-01-26 22:48:41 +08:00
return isMember , err
}
2019-03-06 22:37:37 +08:00
2022-01-26 22:48:41 +08:00
func isTeamMember ( sess * DBSession , orgId int64 , teamId int64 , userId int64 ) ( bool , error ) {
if res , err := sess . Query ( "SELECT 1 FROM team_member WHERE org_id=? and team_id=? and user_id=?" , orgId , teamId , userId ) ; err != nil {
return false , err
} else if len ( res ) != 1 {
return false , nil
}
return true , nil
}
// AddOrUpdateTeamMemberHook is called from team resource permission service
// it adds user to a team or updates user permissions in a team within the given transaction session
func AddOrUpdateTeamMemberHook ( sess * DBSession , userID , orgID , teamID int64 , isExternal bool , permission models . PermissionType ) error {
isMember , err := isTeamMember ( sess , orgID , teamID , userID )
if err != nil {
2019-03-06 22:37:37 +08:00
return err
2022-01-26 22:48:41 +08:00
}
if isMember {
err = updateTeamMember ( sess , orgID , teamID , userID , permission )
} else {
err = addTeamMember ( sess , orgID , teamID , userID , isExternal , permission )
}
return err
2019-03-06 22:37:37 +08:00
}
2022-01-26 22:48:41 +08:00
func addTeamMember ( sess * DBSession , orgID , teamID , userID int64 , isExternal bool , permission models . PermissionType ) error {
if _ , err := teamExists ( orgID , teamID , sess ) ; err != nil {
return err
}
2018-02-16 18:45:53 +08:00
2022-01-26 22:48:41 +08:00
entity := models . TeamMember {
OrgId : orgID ,
TeamId : teamID ,
UserId : userID ,
External : isExternal ,
Created : time . Now ( ) ,
Updated : time . Now ( ) ,
Permission : permission ,
}
_ , err := sess . Insert ( & entity )
return err
}
2019-03-12 23:59:39 +08:00
2022-01-26 22:48:41 +08:00
func updateTeamMember ( sess * DBSession , orgID , teamID , userID int64 , permission models . PermissionType ) error {
member , err := getTeamMember ( sess , orgID , teamID , userID )
if err != nil {
return err
}
if permission != models . PERMISSION_ADMIN {
permission = 0 // make sure we don't get invalid permission levels in store
// protect the last team admin
_ , err := isLastAdmin ( sess , orgID , teamID , userID )
2017-04-09 06:55:07 +08:00
if err != nil {
return err
}
2022-01-26 22:48:41 +08:00
}
2017-04-09 06:55:07 +08:00
2022-01-26 22:48:41 +08:00
member . Permission = permission
_ , err = sess . Cols ( "permission" ) . Where ( "org_id=? and team_id=? and user_id=?" , orgID , teamID , userID ) . Update ( member )
return err
}
// RemoveTeamMember removes a member from a team
func ( ss * SQLStore ) RemoveTeamMember ( ctx context . Context , cmd * models . RemoveTeamMemberCommand ) error {
2022-04-26 01:07:11 +08:00
return ss . WithTransactionalDbSession ( ctx , func ( sess * DBSession ) error {
2022-01-26 22:48:41 +08:00
return removeTeamMember ( sess , cmd )
2017-04-09 06:55:07 +08:00
} )
}
2022-01-26 22:48:41 +08:00
// RemoveTeamMemberHook is called from team resource permission service
// it removes a member from a team within the given transaction session
func RemoveTeamMemberHook ( sess * DBSession , cmd * models . RemoveTeamMemberCommand ) error {
return removeTeamMember ( sess , cmd )
}
func removeTeamMember ( sess * DBSession , cmd * models . RemoveTeamMemberCommand ) error {
if _ , err := teamExists ( cmd . OrgId , cmd . TeamId , sess ) ; err != nil {
return err
}
_ , err := isLastAdmin ( sess , cmd . OrgId , cmd . TeamId , cmd . UserId )
if err != nil {
return err
}
var rawSQL = "DELETE FROM team_member WHERE org_id=? and team_id=? and user_id=?"
res , err := sess . Exec ( rawSQL , cmd . OrgId , cmd . TeamId , cmd . UserId )
if err != nil {
return err
}
rows , err := res . RowsAffected ( )
if rows == 0 {
return models . ErrTeamMemberNotFound
}
return err
}
2019-03-12 23:59:39 +08:00
func isLastAdmin ( sess * DBSession , orgId int64 , teamId int64 , userId int64 ) ( bool , error ) {
2020-11-11 13:21:08 +08:00
rawSQL := "SELECT user_id FROM team_member WHERE org_id=? and team_id=? and permission=?"
2019-03-12 23:59:39 +08:00
userIds := [ ] * int64 { }
2020-11-11 13:21:08 +08:00
err := sess . SQL ( rawSQL , orgId , teamId , models . PERMISSION_ADMIN ) . Find ( & userIds )
2019-03-12 23:59:39 +08:00
if err != nil {
return false , err
}
isAdmin := false
for _ , adminId := range userIds {
if userId == * adminId {
isAdmin = true
break
}
}
if isAdmin && len ( userIds ) == 1 {
2019-08-13 02:03:48 +08:00
return true , models . ErrLastTeamAdmin
2019-03-12 23:59:39 +08:00
}
return false , err
}
2022-02-10 00:46:37 +08:00
// GetUserTeamMemberships return a list of memberships to teams granted to a user
// If external is specified, only memberships provided by an external auth provider will be listed
// This function doesn't perform any accesscontrol filtering.
func ( ss * SQLStore ) GetUserTeamMemberships ( ctx context . Context , orgID , userID int64 , external bool ) ( [ ] * models . TeamMemberDTO , error ) {
query := & models . GetTeamMembersQuery {
OrgId : orgID ,
UserId : userID ,
External : external ,
Result : [ ] * models . TeamMemberDTO { } ,
}
err := ss . getTeamMembers ( ctx , query , nil )
return query . Result , err
}
// GetTeamMembers return a list of members for the specified team filtered based on the user's permissions
2022-01-24 18:52:35 +08:00
func ( ss * SQLStore ) GetTeamMembers ( ctx context . Context , query * models . GetTeamMembersQuery ) error {
2022-02-10 00:46:37 +08:00
acFilter := & ac . SQLFilter { }
var err error
// With accesscontrol we filter out users based on the SignedInUser's permissions
// Note we assume that checking SignedInUser is allowed to see team members for this team has already been performed
// If the signed in user is not set no member will be returned
2022-05-05 23:31:14 +08:00
if ! ac . IsDisabled ( ss . Cfg ) {
2022-04-21 03:11:37 +08:00
sqlID := fmt . Sprintf ( "%s.%s" , ss . engine . Dialect ( ) . Quote ( "user" ) , ss . engine . Dialect ( ) . Quote ( "id" ) )
2022-03-22 00:58:18 +08:00
* acFilter , err = ac . Filter ( query . SignedInUser , sqlID , "users:id:" , ac . ActionOrgUsersRead )
2022-02-10 00:46:37 +08:00
if err != nil {
return err
}
}
return ss . getTeamMembers ( ctx , query , acFilter )
}
// getTeamMembers return a list of members for the specified team
func ( ss * SQLStore ) getTeamMembers ( ctx context . Context , query * models . GetTeamMembersQuery , acUserFilter * ac . SQLFilter ) error {
2022-04-21 03:11:37 +08:00
return ss . WithDbSession ( ctx , func ( dbSess * DBSession ) error {
query . Result = make ( [ ] * models . TeamMemberDTO , 0 )
sess := dbSess . Table ( "team_member" )
sess . Join ( "INNER" , ss . Dialect . Quote ( "user" ) ,
fmt . Sprintf ( "team_member.user_id=%s.%s" , ss . Dialect . Quote ( "user" ) , ss . Dialect . Quote ( "id" ) ) ,
)
2022-05-24 14:52:39 +08:00
// explicitly check for serviceaccounts
sess . Where ( fmt . Sprintf ( "%s.is_service_account=?" , ss . Dialect . Quote ( "user" ) ) , ss . Dialect . BooleanStr ( false ) )
2022-04-21 03:11:37 +08:00
if acUserFilter != nil {
sess . Where ( acUserFilter . Where , acUserFilter . Args ... )
}
2019-07-03 21:52:10 +08:00
2022-04-21 03:11:37 +08:00
// Join with only most recent auth module
authJoinCondition := ` (
2019-07-03 21:52:10 +08:00
SELECT id from user_auth
WHERE user_auth . user_id = team_member . user_id
ORDER BY user_auth . created DESC `
2022-04-21 03:11:37 +08:00
authJoinCondition = "user_auth.id=" + authJoinCondition + ss . Dialect . Limit ( 1 ) + ")"
sess . Join ( "LEFT" , "user_auth" , authJoinCondition )
2019-07-03 21:52:10 +08:00
2022-04-21 03:11:37 +08:00
if query . OrgId != 0 {
sess . Where ( "team_member.org_id=?" , query . OrgId )
}
if query . TeamId != 0 {
sess . Where ( "team_member.team_id=?" , query . TeamId )
}
if query . UserId != 0 {
sess . Where ( "team_member.user_id=?" , query . UserId )
}
if query . External {
sess . Where ( "team_member.external=?" , ss . Dialect . BooleanStr ( true ) )
}
sess . Cols (
"team_member.org_id" ,
"team_member.team_id" ,
"team_member.user_id" ,
"user.email" ,
"user.name" ,
"user.login" ,
"team_member.external" ,
"team_member.permission" ,
"user_auth.auth_module" ,
)
sess . Asc ( "user.login" , "user.email" )
err := sess . Find ( & query . Result )
return err
} )
2017-04-09 06:55:07 +08:00
}
2019-08-13 02:03:48 +08:00
2022-04-21 03:11:37 +08:00
func ( ss * SQLStore ) IsAdminOfTeams ( ctx context . Context , query * models . IsAdminOfTeamsQuery ) error {
return ss . WithDbSession ( ctx , func ( sess * DBSession ) error {
builder := & SQLBuilder { }
builder . Write ( "SELECT COUNT(team.id) AS count FROM team INNER JOIN team_member ON team_member.team_id = team.id WHERE team.org_id = ? AND team_member.user_id = ? AND team_member.permission = ?" , query . SignedInUser . OrgId , query . SignedInUser . UserId , models . PERMISSION_ADMIN )
2019-08-13 02:03:48 +08:00
2022-04-21 03:11:37 +08:00
type teamCount struct {
Count int64
}
2019-08-13 02:03:48 +08:00
2022-04-21 03:11:37 +08:00
resp := make ( [ ] * teamCount , 0 )
if err := sess . SQL ( builder . GetSQLString ( ) , builder . params ... ) . Find ( & resp ) ; err != nil {
return err
}
2019-08-13 02:03:48 +08:00
2022-04-21 03:11:37 +08:00
query . Result = len ( resp ) > 0 && resp [ 0 ] . Count > 0
2019-08-13 02:03:48 +08:00
2022-04-21 03:11:37 +08:00
return nil
} )
2019-08-13 02:03:48 +08:00
}