grafana/pkg/services/accesscontrol/database/database.go
Karl Persson e844b263c7
Access control: Load permissions from memory and database (#42080)
* Load permission from both in memory and from database
Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
2022-01-28 16:11:18 +01:00

113 lines
2.5 KiB
Go

package database
import (
"context"
"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
permission.id,
permission.role_id,
permission.action,
permission.scope,
permission.updated,
permission.created
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)
}
}
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
}