Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Recipe Roles permission behavior #17254

Merged
merged 4 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions src/OrchardCore.Modules/OrchardCore.Roles/Recipes/RolesStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,33 @@ protected override async Task HandleAsync(RecipeExecutionContext context)
if (role is Role r)
{
r.RoleDescription = roleEntry.Description;
r.RoleClaims.RemoveAll(c => c.ClaimType == Permission.ClaimType);

if (roleEntry.PermissionBehavior == PermissionBehavior.Replace)
{
// At this point, we know we are replacing permissions.
// Remove all existing permission so we can add the replacements later.
r.RoleClaims.RemoveAll(c => c.ClaimType == Permission.ClaimType);
}

if (!await _systemRoleNameProvider.IsAdminRoleAsync(roleName))
{
r.RoleClaims.AddRange(roleEntry.Permissions.Select(RoleClaim.Create));
if (roleEntry.PermissionBehavior == PermissionBehavior.Remove)
{
// Materialize this list to prevent an exception.
var permissions = r.RoleClaims.Where(c => c.ClaimType == Permission.ClaimType && roleEntry.Permissions.Contains(c.ClaimValue)).ToArray();

foreach (var permission in permissions)
{
r.RoleClaims.Remove(permission);
}
}
else
{
var permissions = roleEntry.Permissions.Select(RoleClaim.Create)
.Where(newClaim => !r.RoleClaims.Exists(existingClaim => existingClaim.ClaimType == newClaim.ClaimType && existingClaim.ClaimValue == newClaim.ClaimValue));

r.RoleClaims.AddRange(permissions);
}
}
}

Expand Down Expand Up @@ -83,4 +105,13 @@ public sealed class RolesStepRoleModel
public string Description { get; set; }

public string[] Permissions { get; set; }

public PermissionBehavior PermissionBehavior { get; set; }
}

public enum PermissionBehavior
{
Replace,
Add,
Remove,
}
51 changes: 42 additions & 9 deletions src/docs/reference/modules/Roles/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,50 @@ A sample of a roles configuration step:

```json
{
"name": "roles",
"Roles": [
"steps": [
{
"Name": "Journalist",
"Description" "Journalist Role",
"Permissions": ["PublishContent", "EditContent"]
},
"name": "roles",
"Roles": [
{
"Name": "Journalist",
"Description" "Journalist Role",
"PermissionBehavior": "Replace",
"Permissions": ["PublishContent", "EditContent"]
},
{
"Name": "Subscriber",
"Description" "Subscriber Role",
"PermissionBehavior": "Replace",
"Permissions": []
}
]
}
]
}
```

As of version 3.0, the `Roles` recipe includes the ability to define specific permission behaviors, giving you greater control over how permissions are managed within a role. The following behaviors are available:

- **Replace**: This behavior removes all existing permissions associated with the role and replaces them with the new permissions from the `Permissions` collection. This is the default behavior.
- **Add**: This behavior adds the new permission(s) from the `Permissions` collection to the role, but only if they do not already exist. Existing permissions are left unchanged.
- **Remove**: This behavior removes the specified permission(s) from the role’s existing permissions based on the `Permissions` collection.

### Example: Adding a New Permission to a Role

For instance, to add the "CanChat" permission to the `Subscriber` role, use the following configuration:

```json
{
"steps": [
{
"Name": "Subscriber",
"Description" "Subscriber Role",
"Permissions": []
"name": "roles",
"Roles": [
{
"Name": "Subscriber",
"PermissionBehavior": "Add",
"Permissions": ["CanChat"]
}
]
}
]
}
Expand Down
14 changes: 13 additions & 1 deletion src/docs/releases/3.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,21 @@ This change is designed to simplify your integration process and make it easier

## Change Log

### Roles Module

#### Permission Behavior Added to Roles Recipe Step

The `Roles` recipe now includes the ability to define specific permission behaviors, allowing you to control how permissions are managed within a role. The following behaviors are available:

- **Replace**: This behavior removes all existing permissions associated with the role and replaces them with the new permissions from the `Permissions` collection. This is the default behavior.
- **Add**: This behavior adds the new permission(s) from the `Permissions` collection to the role, but only if they do not already exist. It does not affect the existing permissions.
- **Remove**: This behavior removes the specified permission(s) in the `Permissions` collection from the role’s existing permissions.

For more info about the new `PermissionBehavior`, check out the [documentation](../reference/modules/Roles/README.md).

### ReCaptcha

### New ReCaptcha Shape
#### New ReCaptcha Shape

A new `ReCaptcha` shape has been introduced, enabling you to render the ReCaptcha challenge using a customizable shape. For more details, please refer to the [documentation](../reference/modules/ReCaptcha/README.md).

Expand Down
Loading