Files
grafana/pkg/services/accesscontrol/database/database.go
idafurjes 578ab71ba9 Copy delete user permission to access control service (#51747)
* Copy delete user permission to access control service

* Update pkg/services/accesscontrol/database/database_test.go

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
2022-07-05 18:05:56 +02:00

157 lines
3.7 KiB
Go

package database
import (
"context"
"strconv"
"strings"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/sqlstore"
)
const (
globalOrgID = 0
)
func ProvideService(sqlStore *sqlstore.SQLStore) *AccessControlStore {
return &AccessControlStore{sqlStore}
}
type AccessControlStore struct {
sql *sqlstore.SQLStore
}
func (s *AccessControlStore) GetUserPermissions(ctx context.Context, query accesscontrol.GetUserPermissionsQuery) ([]accesscontrol.Permission, error) {
result := make([]accesscontrol.Permission, 0)
err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
filter, params := userRolesFilter(query.OrgID, query.UserID, query.Roles)
// TODO: optimize this
q := `SELECT DISTINCT
permission.action,
permission.scope
FROM permission
INNER JOIN role ON role.id = permission.role_id
` + filter
if query.Actions != nil {
q += " AND permission.action IN("
if len(query.Actions) > 0 {
q += "?" + strings.Repeat(",?", len(query.Actions)-1)
}
q += ")"
for _, a := range query.Actions {
params = append(params, a)
}
}
q += `
ORDER BY permission.scope
`
if err := sess.SQL(q, params...).Find(&result); err != nil {
return err
}
return nil
})
return result, err
}
func userRolesFilter(orgID, userID int64, roles []string) (string, []interface{}) {
q := `
WHERE role.id IN (
SELECT ur.role_id
FROM user_role AS ur
WHERE ur.user_id = ?
AND (ur.org_id = ? OR ur.org_id = ?)
UNION
SELECT tr.role_id FROM team_role as tr
INNER JOIN team_member as tm ON tm.team_id = tr.team_id
WHERE tm.user_id = ? AND tr.org_id = ?
`
params := []interface{}{userID, orgID, globalOrgID, userID, orgID}
if len(roles) != 0 {
q += `
UNION
SELECT br.role_id FROM builtin_role AS br
WHERE role IN (? ` + strings.Repeat(", ?", len(roles)-1) + `)
`
for _, role := range roles {
params = append(params, role)
}
q += `AND (br.org_id = ? OR br.org_id = ?)`
params = append(params, orgID, globalOrgID)
}
q += `)`
return q, params
}
func deletePermissions(sess *sqlstore.DBSession, ids []int64) error {
if len(ids) == 0 {
return nil
}
rawSQL := "DELETE FROM permission WHERE id IN(?" + strings.Repeat(",?", len(ids)-1) + ")"
args := make([]interface{}, 0, len(ids)+1)
args = append(args, rawSQL)
for _, id := range ids {
args = append(args, id)
}
_, err := sess.Exec(args...)
if err != nil {
return err
}
return nil
}
func (s *AccessControlStore) DeleteUserPermissions(ctx context.Context, userID int64) error {
err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
// Delete user role assignments
if _, err := sess.Exec("DELETE FROM user_role WHERE user_id = ?", userID); err != nil {
return err
}
// Delete permissions that are scoped to user
if _, err := sess.Exec("DELETE FROM permission WHERE scope = ?", accesscontrol.Scope("users", "id", strconv.FormatInt(userID, 10))); err != nil {
return err
}
var roleIDs []int64
if err := sess.SQL("SELECT id FROM role WHERE name = ?", accesscontrol.ManagedUserRoleName(userID)).Find(&roleIDs); err != nil {
return err
}
if len(roleIDs) == 0 {
return nil
}
query := "DELETE FROM permission WHERE role_id IN(? " + strings.Repeat(",?", len(roleIDs)-1) + ")"
args := make([]interface{}, 0, len(roleIDs)+1)
args = append(args, query)
for _, id := range roleIDs {
args = append(args, id)
}
// Delete managed user permissions
if _, err := sess.Exec(args...); err != nil {
return err
}
// Delete managed user roles
if _, err := sess.Exec("DELETE FROM role WHERE name = ?", accesscontrol.ManagedUserRoleName(userID)); err != nil {
return err
}
return nil
})
return err
}