(ctx context.Context, tx database.Store, user database.User, params RoleParams)
| 218 | } |
| 219 | |
| 220 | func (s AGPLIDPSync) syncSiteWideRoles(ctx context.Context, tx database.Store, user database.User, params RoleParams) error { |
| 221 | // Apply site wide roles to a user. |
| 222 | // ignored is the list of roles that are not valid Coder roles and will |
| 223 | // be skipped. |
| 224 | ignored := make([]string, 0) |
| 225 | filtered := make([]string, 0, len(params.SiteWideRoles)) |
| 226 | for _, role := range params.SiteWideRoles { |
| 227 | // Because we are only syncing site wide roles, we intentionally will always |
| 228 | // omit 'OrganizationID' from the RoleIdentifier. |
| 229 | // TODO: If custom site wide roles are introduced, this needs to use the |
| 230 | // database to verify the role exists. |
| 231 | if _, err := rbac.RoleByName(rbac.RoleIdentifier{Name: role}); err == nil { |
| 232 | filtered = append(filtered, role) |
| 233 | } else { |
| 234 | ignored = append(ignored, role) |
| 235 | } |
| 236 | } |
| 237 | if len(ignored) > 0 { |
| 238 | s.Logger.Debug(ctx, "OIDC roles ignored in assignment", |
| 239 | slog.F("ignored", ignored), |
| 240 | slog.F("assigned", filtered), |
| 241 | slog.F("user_id", user.ID), |
| 242 | slog.F("username", user.Username), |
| 243 | ) |
| 244 | } |
| 245 | |
| 246 | filtered = slice.Unique(filtered) |
| 247 | slices.Sort(filtered) |
| 248 | |
| 249 | existing := slice.Unique(user.RBACRoles) |
| 250 | slices.Sort(existing) |
| 251 | if !slices.Equal(existing, filtered) { |
| 252 | _, err := tx.UpdateUserRoles(ctx, database.UpdateUserRolesParams{ |
| 253 | GrantedRoles: filtered, |
| 254 | ID: user.ID, |
| 255 | }) |
| 256 | if err != nil { |
| 257 | return xerrors.Errorf("set site wide roles: %w", err) |
| 258 | } |
| 259 | } |
| 260 | return nil |
| 261 | } |
| 262 | |
| 263 | func (AGPLIDPSync) RolesFromClaim(field string, claims jwt.MapClaims) ([]string, error) { |
| 264 | rolesRow, ok := claims[field] |
no test coverage detected