expandRBACScope merges the permissions of all scopes in the list into a single RBAC scope. If the list is empty, it defaults to rbac.ScopeAll for backward compatibility. This method is internal; use ScopeSet() to combine scopes with the API key's allow list for authorization.
()
| 262 | // backward compatibility. This method is internal; use ScopeSet() to combine |
| 263 | // scopes with the API key's allow list for authorization. |
| 264 | func (s APIKeyScopes) expandRBACScope() (rbac.Scope, error) { |
| 265 | // Default to ScopeAll for backward compatibility when no scopes provided. |
| 266 | if len(s) == 0 { |
| 267 | return rbac.Scope{}, xerrors.New("no scopes provided") |
| 268 | } |
| 269 | |
| 270 | var merged rbac.Scope |
| 271 | merged.Role = rbac.Role{ |
| 272 | // Identifier is informational; not used in policy evaluation. |
| 273 | Identifier: rbac.RoleIdentifier{Name: "Scope_Multiple"}, |
| 274 | Site: nil, |
| 275 | User: nil, |
| 276 | ByOrgID: map[string]rbac.OrgPermissions{}, |
| 277 | } |
| 278 | |
| 279 | // Collect allow lists for a union after expanding all scopes. |
| 280 | allowLists := make([][]rbac.AllowListElement, 0, len(s)) |
| 281 | |
| 282 | for _, s := range s { |
| 283 | expanded, err := s.ToRBAC().Expand() |
| 284 | if err != nil { |
| 285 | return rbac.Scope{}, err |
| 286 | } |
| 287 | |
| 288 | // Merge role permissions: union by simple concatenation. |
| 289 | merged.Site = append(merged.Site, expanded.Site...) |
| 290 | for orgID, perms := range expanded.ByOrgID { |
| 291 | orgPerms := merged.ByOrgID[orgID] |
| 292 | orgPerms.Org = append(orgPerms.Org, perms.Org...) |
| 293 | orgPerms.Member = append(orgPerms.Member, perms.Member...) |
| 294 | merged.ByOrgID[orgID] = orgPerms |
| 295 | } |
| 296 | merged.User = append(merged.User, expanded.User...) |
| 297 | |
| 298 | allowLists = append(allowLists, expanded.AllowIDList) |
| 299 | } |
| 300 | |
| 301 | // De-duplicate permissions across Site/Org/User |
| 302 | merged.Site = rbac.DeduplicatePermissions(merged.Site) |
| 303 | merged.User = rbac.DeduplicatePermissions(merged.User) |
| 304 | for orgID, perms := range merged.ByOrgID { |
| 305 | perms.Org = rbac.DeduplicatePermissions(perms.Org) |
| 306 | perms.Member = rbac.DeduplicatePermissions(perms.Member) |
| 307 | merged.ByOrgID[orgID] = perms |
| 308 | } |
| 309 | |
| 310 | union, err := rbac.UnionAllowLists(allowLists...) |
| 311 | if err != nil { |
| 312 | return rbac.Scope{}, err |
| 313 | } |
| 314 | merged.AllowIDList = union |
| 315 | |
| 316 | return merged, nil |
| 317 | } |
| 318 | |
| 319 | // Name returns a human-friendly identifier for tracing/logging. |
| 320 | func (s APIKeyScopes) Name() rbac.RoleIdentifier { |