|
|
|
@ -32,7 +32,7 @@ type store interface { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type xormStore struct { |
|
|
|
|
db db.DB |
|
|
|
|
db db.ReplDB |
|
|
|
|
cfg *setting.Cfg |
|
|
|
|
deletes []string |
|
|
|
|
} |
|
|
|
@ -85,7 +85,7 @@ func (ss *xormStore) Create(name, email string, orgID int64) (team.Team, error) |
|
|
|
|
Created: time.Now(), |
|
|
|
|
Updated: time.Now(), |
|
|
|
|
} |
|
|
|
|
err := ss.db.WithTransactionalDbSession(context.Background(), func(sess *db.Session) error { |
|
|
|
|
err := ss.db.DB().WithTransactionalDbSession(context.Background(), func(sess *db.Session) error { |
|
|
|
|
if isNameTaken, err := isTeamNameTaken(orgID, name, 0, sess); err != nil { |
|
|
|
|
return err |
|
|
|
|
} else if isNameTaken { |
|
|
|
@ -99,7 +99,7 @@ func (ss *xormStore) Create(name, email string, orgID int64) (team.Team, error) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (ss *xormStore) Update(ctx context.Context, cmd *team.UpdateTeamCommand) error { |
|
|
|
|
return ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
return ss.db.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
if isNameTaken, err := isTeamNameTaken(cmd.OrgID, cmd.Name, cmd.ID, sess); err != nil { |
|
|
|
|
return err |
|
|
|
|
} else if isNameTaken { |
|
|
|
@ -130,7 +130,7 @@ func (ss *xormStore) Update(ctx context.Context, cmd *team.UpdateTeamCommand) er |
|
|
|
|
|
|
|
|
|
// DeleteTeam will delete a team, its member and any permissions connected to the team
|
|
|
|
|
func (ss *xormStore) Delete(ctx context.Context, cmd *team.DeleteTeamCommand) error { |
|
|
|
|
return ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
return ss.db.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
if _, err := teamExists(cmd.OrgID, cmd.ID, sess); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
@ -181,7 +181,7 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( |
|
|
|
|
queryResult := team.SearchTeamQueryResult{ |
|
|
|
|
Teams: make([]*team.TeamDTO, 0), |
|
|
|
|
} |
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
queryWithWildcards := "%" + query.Query + "%" |
|
|
|
|
|
|
|
|
|
var sql bytes.Buffer |
|
|
|
@ -192,12 +192,12 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( |
|
|
|
|
params = append(params, user) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sql.WriteString(getTeamSelectSQLBase(ss.db, filteredUsers)) |
|
|
|
|
sql.WriteString(getTeamSelectSQLBase(ss.db.ReadReplica(), filteredUsers)) |
|
|
|
|
sql.WriteString(` WHERE team.org_id = ?`) |
|
|
|
|
params = append(params, query.OrgID) |
|
|
|
|
|
|
|
|
|
if query.Query != "" { |
|
|
|
|
sql.WriteString(` and team.name ` + ss.db.GetDialect().LikeStr() + ` ?`) |
|
|
|
|
sql.WriteString(` and team.name ` + ss.db.ReadReplica().GetDialect().LikeStr() + ` ?`) |
|
|
|
|
params = append(params, queryWithWildcards) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -234,7 +234,7 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( |
|
|
|
|
|
|
|
|
|
if query.Limit != 0 { |
|
|
|
|
offset := query.Limit * (query.Page - 1) |
|
|
|
|
sql.WriteString(ss.db.GetDialect().LimitOffset(int64(query.Limit), int64(offset))) |
|
|
|
|
sql.WriteString(ss.db.ReadReplica().GetDialect().LimitOffset(int64(query.Limit), int64(offset))) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err := sess.SQL(sql.String(), params...).Find(&queryResult.Teams); err != nil { |
|
|
|
@ -246,7 +246,7 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( |
|
|
|
|
countSess.Where("team.org_id=?", query.OrgID) |
|
|
|
|
|
|
|
|
|
if query.Query != "" { |
|
|
|
|
countSess.Where(`name `+ss.db.GetDialect().LikeStr()+` ?`, queryWithWildcards) |
|
|
|
|
countSess.Where(`name `+ss.db.ReadReplica().GetDialect().LikeStr()+` ?`, queryWithWildcards) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if query.Name != "" { |
|
|
|
@ -269,12 +269,12 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( |
|
|
|
|
|
|
|
|
|
func (ss *xormStore) GetByID(ctx context.Context, query *team.GetTeamByIDQuery) (*team.TeamDTO, error) { |
|
|
|
|
var queryResult *team.TeamDTO |
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
var sql bytes.Buffer |
|
|
|
|
params := make([]any, 0) |
|
|
|
|
|
|
|
|
|
filteredUsers := getFilteredUsers(query.SignedInUser, query.HiddenUsers) |
|
|
|
|
sql.WriteString(getTeamSelectSQLBase(ss.db, filteredUsers)) |
|
|
|
|
sql.WriteString(getTeamSelectSQLBase(ss.db.ReadReplica(), filteredUsers)) |
|
|
|
|
for _, user := range filteredUsers { |
|
|
|
|
params = append(params, user) |
|
|
|
|
} |
|
|
|
@ -305,12 +305,12 @@ func (ss *xormStore) GetByID(ctx context.Context, query *team.GetTeamByIDQuery) |
|
|
|
|
// GetTeamsByUser is used by the Guardian when checking a users' permissions
|
|
|
|
|
func (ss *xormStore) GetByUser(ctx context.Context, query *team.GetTeamsByUserQuery) ([]*team.TeamDTO, error) { |
|
|
|
|
queryResult := make([]*team.TeamDTO, 0) |
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
var sql bytes.Buffer |
|
|
|
|
var params []any |
|
|
|
|
params = append(params, query.OrgID, query.UserID) |
|
|
|
|
|
|
|
|
|
sql.WriteString(getTeamSelectSQLBase(ss.db, []string{})) |
|
|
|
|
sql.WriteString(getTeamSelectSQLBase(ss.db.ReadReplica(), []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 = ?`) |
|
|
|
|
|
|
|
|
@ -334,7 +334,7 @@ func (ss *xormStore) GetByUser(ctx context.Context, query *team.GetTeamsByUserQu |
|
|
|
|
func (ss *xormStore) GetIDsByUser(ctx context.Context, query *team.GetTeamIDsByUserQuery) ([]int64, error) { |
|
|
|
|
queryResult := make([]int64, 0) |
|
|
|
|
|
|
|
|
|
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
return sess.SQL(`SELECT tm.team_id |
|
|
|
|
FROM team_member as tm |
|
|
|
|
WHERE tm.user_id=? AND tm.org_id=?;`, query.UserID, query.OrgID).Find(&queryResult) |
|
|
|
@ -364,7 +364,7 @@ func getTeamMember(sess *db.Session, orgId int64, teamId int64, userId int64) (t |
|
|
|
|
func (ss *xormStore) IsMember(orgId int64, teamId int64, userId int64) (bool, error) { |
|
|
|
|
var isMember bool |
|
|
|
|
|
|
|
|
|
err := ss.db.WithDbSession(context.Background(), func(sess *db.Session) error { |
|
|
|
|
err := ss.db.ReadReplica().WithDbSession(context.Background(), func(sess *db.Session) error { |
|
|
|
|
var err error |
|
|
|
|
isMember, err = isTeamMember(sess, orgId, teamId, userId) |
|
|
|
|
return err |
|
|
|
@ -461,7 +461,7 @@ func removeTeamMember(sess *db.Session, cmd *team.RemoveTeamMemberCommand) error |
|
|
|
|
// RemoveUsersMemberships removes all the team membership entries for the given user.
|
|
|
|
|
// Only used when removing a user from a Grafana instance.
|
|
|
|
|
func (ss *xormStore) RemoveUsersMemberships(ctx context.Context, userID int64) error { |
|
|
|
|
return ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
return ss.db.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { |
|
|
|
|
var rawSQL = "DELETE FROM team_member WHERE user_id = ?" |
|
|
|
|
_, err := sess.Exec(rawSQL, userID) |
|
|
|
|
return err |
|
|
|
@ -489,7 +489,7 @@ func (ss *xormStore) GetMembers(ctx context.Context, query *team.GetTeamMembersQ |
|
|
|
|
// 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
|
|
|
|
|
sqlID := fmt.Sprintf("%s.%s", ss.db.GetDialect().Quote("user"), ss.db.GetDialect().Quote("id")) |
|
|
|
|
sqlID := fmt.Sprintf("%s.%s", ss.db.ReadReplica().GetDialect().Quote("user"), ss.db.ReadReplica().GetDialect().Quote("id")) |
|
|
|
|
*acFilter, err = ac.Filter(query.SignedInUser, sqlID, "users:id:", ac.ActionOrgUsersRead) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
@ -501,15 +501,16 @@ func (ss *xormStore) GetMembers(ctx context.Context, query *team.GetTeamMembersQ |
|
|
|
|
// getTeamMembers return a list of members for the specified team
|
|
|
|
|
func (ss *xormStore) getTeamMembers(ctx context.Context, query *team.GetTeamMembersQuery, acUserFilter *ac.SQLFilter) ([]*team.TeamMemberDTO, error) { |
|
|
|
|
queryResult := make([]*team.TeamMemberDTO, 0) |
|
|
|
|
err := ss.db.WithDbSession(ctx, func(dbSess *db.Session) error { |
|
|
|
|
err := ss.db.ReadReplica().WithDbSession(ctx, func(dbSess *db.Session) error { |
|
|
|
|
dialect := ss.db.ReadReplica().GetDialect() |
|
|
|
|
sess := dbSess.Table("team_member") |
|
|
|
|
sess.Join("INNER", ss.db.GetDialect().Quote("user"), |
|
|
|
|
fmt.Sprintf("team_member.user_id=%s.%s", ss.db.GetDialect().Quote("user"), ss.db.GetDialect().Quote("id")), |
|
|
|
|
sess.Join("INNER", dialect.Quote("user"), |
|
|
|
|
fmt.Sprintf("team_member.user_id=%s.%s", dialect.Quote("user"), dialect.Quote("id")), |
|
|
|
|
) |
|
|
|
|
sess.Join("INNER", "team", "team.id=team_member.team_id") |
|
|
|
|
|
|
|
|
|
// explicitly check for serviceaccounts
|
|
|
|
|
sess.Where(fmt.Sprintf("%s.is_service_account=?", ss.db.GetDialect().Quote("user")), ss.db.GetDialect().BooleanStr(false)) |
|
|
|
|
sess.Where(fmt.Sprintf("%s.is_service_account=?", dialect.Quote("user")), dialect.BooleanStr(false)) |
|
|
|
|
|
|
|
|
|
if acUserFilter != nil { |
|
|
|
|
sess.Where(acUserFilter.Where, acUserFilter.Args...) |
|
|
|
@ -521,7 +522,7 @@ func (ss *xormStore) getTeamMembers(ctx context.Context, query *team.GetTeamMemb |
|
|
|
|
FROM user_auth |
|
|
|
|
WHERE user_auth.user_id = team_member.user_id |
|
|
|
|
ORDER BY user_auth.created DESC ` + |
|
|
|
|
ss.db.GetDialect().Limit(1) + ")" |
|
|
|
|
dialect.Limit(1) + ")" |
|
|
|
|
sess.Join("LEFT", "user_auth", authJoinCondition) |
|
|
|
|
|
|
|
|
|
if query.OrgID != 0 { |
|
|
|
@ -537,7 +538,7 @@ func (ss *xormStore) getTeamMembers(ctx context.Context, query *team.GetTeamMemb |
|
|
|
|
sess.Where("team_member.user_id=?", query.UserID) |
|
|
|
|
} |
|
|
|
|
if query.External { |
|
|
|
|
sess.Where("team_member.external=?", ss.db.GetDialect().BooleanStr(true)) |
|
|
|
|
sess.Where("team_member.external=?", dialect.BooleanStr(true)) |
|
|
|
|
} |
|
|
|
|
sess.Cols( |
|
|
|
|
"team_member.org_id", |
|
|
|
|