Expand will expand built in roles, and fetch custom roles from the database. If a custom role is defined, but does not exist, the role will be omitted on the response. This means deleted roles are silently dropped.
(ctx context.Context, db database.Store, names []rbac.RoleIdentifier)
| 44 | // If a custom role is defined, but does not exist, the role will be omitted on |
| 45 | // the response. This means deleted roles are silently dropped. |
| 46 | func Expand(ctx context.Context, db database.Store, names []rbac.RoleIdentifier) (rbac.Roles, error) { |
| 47 | if len(names) == 0 { |
| 48 | // That was easy |
| 49 | return []rbac.Role{}, nil |
| 50 | } |
| 51 | |
| 52 | cache := roleCache(ctx) |
| 53 | lookup := make([]rbac.RoleIdentifier, 0) |
| 54 | roles := make([]rbac.Role, 0, len(names)) |
| 55 | |
| 56 | for _, name := range names { |
| 57 | // Remove any built in roles |
| 58 | expanded, err := rbac.RoleByName(name) |
| 59 | if err == nil { |
| 60 | roles = append(roles, expanded) |
| 61 | continue |
| 62 | } |
| 63 | |
| 64 | // Check custom role cache |
| 65 | customRole, ok := cache.Load(name.String()) |
| 66 | if ok { |
| 67 | roles = append(roles, customRole) |
| 68 | continue |
| 69 | } |
| 70 | |
| 71 | // Defer custom role lookup |
| 72 | lookup = append(lookup, name) |
| 73 | } |
| 74 | |
| 75 | if len(lookup) > 0 { |
| 76 | lookupArgs := make([]database.NameOrganizationPair, 0, len(lookup)) |
| 77 | for _, name := range lookup { |
| 78 | lookupArgs = append(lookupArgs, database.NameOrganizationPair{ |
| 79 | Name: name.Name, |
| 80 | OrganizationID: name.OrganizationID, |
| 81 | }) |
| 82 | } |
| 83 | |
| 84 | // If some roles are missing from the database, they are omitted from |
| 85 | // the expansion. These roles are no-ops. Should we raise some kind of |
| 86 | // warning when this happens? |
| 87 | dbroles, err := db.CustomRoles(ctx, database.CustomRolesParams{ |
| 88 | LookupRoles: lookupArgs, |
| 89 | ExcludeOrgRoles: false, |
| 90 | OrganizationID: uuid.Nil, |
| 91 | IncludeSystemRoles: true, |
| 92 | }) |
| 93 | if err != nil { |
| 94 | return nil, xerrors.Errorf("fetch custom roles: %w", err) |
| 95 | } |
| 96 | |
| 97 | // convert dbroles -> roles |
| 98 | for _, dbrole := range dbroles { |
| 99 | converted, err := ConvertDBRole(dbrole) |
| 100 | if err != nil { |
| 101 | return nil, xerrors.Errorf("convert db role %q: %w", dbrole.Name, err) |
| 102 | } |
| 103 | roles = append(roles, converted) |