mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 10:03:33 -06:00
143 lines
3.5 KiB
Go
143 lines
3.5 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana/pkg/kinds/accesspolicy"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore/session"
|
|
"github.com/grafana/grafana/pkg/util"
|
|
)
|
|
|
|
func GetAccessPolicies(ctx context.Context, orgID int64, sql *session.SessionDB, resolver accesscontrol.ScopeAttributeResolverFunc) ([]accesspolicy.Resource, error) {
|
|
type permissionInfo struct {
|
|
RoleUID string
|
|
RoleName string
|
|
Scope string
|
|
Action string
|
|
Created time.Time
|
|
Updated time.Time
|
|
}
|
|
info := &permissionInfo{}
|
|
policies := make([]accesspolicy.Resource, 0)
|
|
current := &accesspolicy.Resource{}
|
|
prevKey := ""
|
|
rows, err := sql.Query(ctx, `SELECT
|
|
role.uid as role_uid,
|
|
role.name as role_name,
|
|
scope,
|
|
action,
|
|
permission.created,
|
|
permission.updated
|
|
FROM permission
|
|
JOIN role ON permission.role_id = role.id
|
|
WHERE org_id=?
|
|
ORDER BY role.id ASC, scope ASC, action ASC`, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
created := time.Now()
|
|
updated := time.Now()
|
|
|
|
for rows.Next() {
|
|
err = rows.Scan(
|
|
&info.RoleUID,
|
|
&info.RoleName,
|
|
&info.Scope,
|
|
&info.Action,
|
|
&info.Created,
|
|
&info.Updated,
|
|
)
|
|
if err != nil {
|
|
return policies, err
|
|
}
|
|
|
|
key := info.RoleUID + "/" + info.Scope
|
|
if key != prevKey {
|
|
created = info.Created
|
|
updated = info.Updated
|
|
if len(current.Spec.Rules) > 0 {
|
|
current.Spec.Rules = accesspolicy.ReduceRules(current.Spec.Rules)
|
|
policies = append(policies, *current)
|
|
}
|
|
scope, err := resolver(ctx, orgID, info.Scope)
|
|
if err != nil {
|
|
return policies, err
|
|
}
|
|
if len(scope) != 3 {
|
|
return policies, fmt.Errorf("expected three part scope")
|
|
}
|
|
|
|
current = &accesspolicy.Resource{
|
|
Metadata: accesspolicy.Metadata{
|
|
CreationTimestamp: created,
|
|
UpdateTimestamp: updated,
|
|
},
|
|
Spec: accesspolicy.Spec{
|
|
Role: accesspolicy.RoleRef{
|
|
Kind: accesspolicy.RoleRefKindRole,
|
|
Name: info.RoleUID,
|
|
Xname: info.RoleName,
|
|
},
|
|
Scope: accesspolicy.ResourceRef{
|
|
Kind: scope[0],
|
|
Name: scope[2],
|
|
},
|
|
Rules: make([]accesspolicy.AccessRule, 0),
|
|
},
|
|
}
|
|
// When the value is not a UID, set the prefix to $ -- an invalid name
|
|
if scope[1] != "uid" {
|
|
current.Spec.Scope.Name = fmt.Sprintf("$%s:%s", scope[1], scope[2])
|
|
}
|
|
|
|
// Skip role+role binding for direct users
|
|
if strings.HasPrefix(info.RoleName, "managed:users:") {
|
|
current.Spec.Role.Kind = accesspolicy.RoleRefKindUser
|
|
current.Spec.Role.Name = "$TODO:" + info.RoleName
|
|
}
|
|
|
|
prevKey = key
|
|
}
|
|
|
|
if info.Created.Before(created) {
|
|
created = info.Created
|
|
current.Metadata.CreationTimestamp = created
|
|
}
|
|
if info.Updated.After(updated) {
|
|
updated = info.Updated
|
|
current.Metadata.UpdateTimestamp = updated
|
|
}
|
|
|
|
action := strings.Split(info.Action, ":")
|
|
if len(action) != 2 {
|
|
return policies, fmt.Errorf("expected two part action")
|
|
}
|
|
parts := strings.SplitN(action[0], ".", 2)
|
|
rule := accesspolicy.AccessRule{
|
|
Verb: action[1],
|
|
Kind: parts[0],
|
|
}
|
|
if len(parts) > 1 {
|
|
rule.Target = util.Pointer(parts[1])
|
|
}
|
|
|
|
// // When the scope is dashboards or teams
|
|
// // ... hymmm ... this would imply permissions
|
|
// if rule.Kind == current.Spec.Scope.Kind {
|
|
// rule.Kind = "*"
|
|
// }
|
|
|
|
current.Spec.Rules = append(current.Spec.Rules, rule)
|
|
}
|
|
if current.Spec.Scope.Name != "" {
|
|
current.Spec.Rules = accesspolicy.ReduceRules(current.Spec.Rules)
|
|
policies = append(policies, *current)
|
|
}
|
|
return policies, err
|
|
}
|