Skip to content

Commit

Permalink
Add a way to Remove User from a Role (Issue OrchardCMS#14632)
Browse files Browse the repository at this point in the history
  • Loading branch information
elaurentin committed Nov 12, 2023
1 parent 19a90c4 commit eb04287
Show file tree
Hide file tree
Showing 22 changed files with 251 additions and 256 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
@using OrchardCore.Workflows.Helpers
@using OrchardCore.Roles.Workflows.Activities
@using OrchardCore.Roles.Workflows.ViewModels
@model ActivityViewModel<RemoveUserRoleTask>
@model ActivityViewModel<GetUsersByRoleTask>
<header>
<h4><i class="fa-solid fa-user" aria-hidden="true"></i>@Model.Activity.GetTitleOrDefault(() => T["Remove user from role"])</h4>
<h4><i class="fa-solid fa-user" aria-hidden="true"></i>@Model.Activity.GetTitleOrDefault(() => T["Get users in roles"])</h4>
</header>
<em>@T["{0} from role {1}", Model.Activity.UserName, Model.Activity.RoleName]</em>
<em>@T["Get users in roles {0} to {1}", string.Join(",", Model.Activity.Roles), Model.Activity.OutputKeyName]</em>
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
@using OrchardCore.Roles.Workflows.ViewModels
@model SelectUsersInRoleTaskViewModel
@model GetUsersByRoleTaskViewModel

<div class="mb-3" asp-validation-class-for="OutputKeyName">
<label asp-for="OutputKeyName">@T["OutputKeyName"]</label>
<input type="text" asp-for="OutputKeyName" class="form-control code" />
<span asp-validation-for="OutputKeyName"></span>
<span class="hint">@T["The Output Key Name to save list. With Liquid support."]</span>
<span class="hint">@T["The designated key name for storing the users' list in the workflow output. This key enables later access to the list within the workflow.With Liquid support."]</span>
</div>

<div class="mb-3" asp-validation-class-for="Roles">
<label asp-for="Roles">@T["Roles"]</label>
@await Component.InvokeAsync("SelectRoles", new { selectedRoles = Model.Roles, htmlName = Html.NameFor(m => m.Roles), except = new[] { "Anonymous", "Authenticated" } })
<span asp-validation-for="Roles"></span>
<span class="hint">@T["The Roles to search for. With Liquid support."]</span>
<span class="hint">@T["Choose the roles used to identify users during list generation."]</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h4 class="card-title"><i class="fa-solid fa-user" aria-hidden="true"></i>@T["Get users in roles"]</h4>
<p>@T["Get users in roles."]</p>

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
@using OrchardCore.Workflows.Helpers
@using OrchardCore.Roles.Workflows.Activities
@using OrchardCore.Roles.Workflows.ViewModels
@model ActivityViewModel<SelectUsersInRoleTask>
@model ActivityViewModel<UnassignUserRoleTask>
<header>
<h4><i class="fa-solid fa-user" aria-hidden="true"></i>@Model.Activity.GetTitleOrDefault(() => T["Select users in roles"])</h4>
<h4><i class="fa-solid fa-user" aria-hidden="true"></i>@Model.Activity.GetTitleOrDefault(() => T["Unassign user from roles"])</h4>
</header>
<em>@T["Stores users of roles {0} to {1}", string.Join(",", Model.Activity.Roles), Model.Activity.OutputKeyName]</em>
<em>@T["Unassign {0} from roles {1}", Model.Activity.UserName, string.Join(",", Model.Activity.Roles)]</em>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@using OrchardCore.Roles.Workflows.ViewModels
@model UnassignUserRoleTaskViewModel

<div class="mb-3" asp-validation-class-for="UserName">
<label asp-for="UserName">@T["UserName"]</label>
<input type="text" asp-for="UserName" class="form-control code" />
<span asp-validation-for="UserName"></span>
<span class="hint">@T["The User to update. With Liquid support."]</span>
</div>

<div class="mb-3" asp-validation-class-for="Roles">
<label asp-for="Roles">@T["Roles"]</label>
@await Component.InvokeAsync("SelectRoles", new { selectedRoles = Model.Roles, htmlName = Html.NameFor(m => m.Roles), except = new[] { "Anonymous", "Authenticated" } })
<span asp-validation-for="Roles"></span>
<span class="hint">@T["The Roles to remove."]</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h4 class="card-title"><i class="fa-solid fa-user" aria-hidden="true"></i>@T["Unassign user from roles"]</h4>
<p>@T["Unassign a user from roles."]</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization;
using OrchardCore.Users;
using OrchardCore.Users.Models;
using OrchardCore.Workflows.Abstractions.Models;
using OrchardCore.Workflows.Activities;
using OrchardCore.Workflows.Models;
using OrchardCore.Workflows.Services;

namespace OrchardCore.Roles.Workflows.Activities;

public class GetUsersByRoleTask : TaskActivity
{
private readonly UserManager<IUser> _userManager;
private readonly IWorkflowExpressionEvaluator _expressionEvaluator;
protected readonly IStringLocalizer S;

public GetUsersByRoleTask(UserManager<IUser> userManager, IWorkflowExpressionEvaluator expressionvaluator, IStringLocalizer<GetUsersByRoleTask> localizer)
{
_userManager = userManager;
_expressionEvaluator = expressionvaluator;
S = localizer;
}

public override string Name => nameof(GetUsersByRoleTask);

public override LocalizedString DisplayText => S["Get Users by Role Task"];

public override LocalizedString Category => S["User"];

public WorkflowExpression<string> OutputKeyName
{
get => GetProperty(() => new WorkflowExpression<string>());
set => SetProperty(value);
}

public IEnumerable<string> Roles
{
get => GetProperty(() => new List<string>());
set => SetProperty(value);
}

public override IEnumerable<Outcome> GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
{
return Outcomes(S["Done"], S["Failed"]);
}

public override async Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
{
var propKeyName = await _expressionEvaluator.EvaluateAsync(OutputKeyName, workflowContext, null);

if (!string.IsNullOrEmpty(propKeyName))
{
if (Roles.Any())
{
HashSet<IUser> usersInRole = new HashSet<IUser>();
foreach (var role in Roles)
{
usersInRole.UnionWith(await _userManager.GetUsersInRoleAsync(role));
}
if (usersInRole.Any())
{
workflowContext.Output[propKeyName] = usersInRole.Select(u => (u as User).UserId).ToArray();
return Outcomes("Done");
}
}
}
return Outcomes("Failed");
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization;
using OrchardCore.Users;
using OrchardCore.Users.Models;
using OrchardCore.Users.Services;
using OrchardCore.Workflows.Abstractions.Models;
using OrchardCore.Workflows.Activities;
using OrchardCore.Workflows.Models;
using OrchardCore.Workflows.Services;

namespace OrchardCore.Roles.Workflows.Activities;

public class UnassignUserRoleTask : TaskActivity
{
private readonly UserManager<IUser> _userManager;
private readonly IUserService _userService;
private readonly IWorkflowExpressionEvaluator _expressionEvaluator;
protected readonly IStringLocalizer S;

public UnassignUserRoleTask(UserManager<IUser> userManager, IUserService userService, IWorkflowExpressionEvaluator expressionvaluator, IStringLocalizer<UnassignUserRoleTask> localizer)
{
_userManager = userManager;
_userService = userService;
_expressionEvaluator = expressionvaluator;
S = localizer;
}

public override string Name => nameof(UnassignUserRoleTask);

public override LocalizedString DisplayText => S["Unassign User Role Task"];

public override LocalizedString Category => S["User"];

public WorkflowExpression<string> UserName
{
get => GetProperty(() => new WorkflowExpression<string>());
set => SetProperty(value);
}

public IEnumerable<string> Roles
{
get => GetProperty(() => new List<string>());
set => SetProperty(value);
}

public override IEnumerable<Outcome> GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
{
return Outcomes(S["Done"], S["Failed"]);
}

public override async Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
{
var userName = await _expressionEvaluator.EvaluateAsync(UserName, workflowContext, null);

var usr = await _userService.GetUserAsync(userName);

if (usr is User user)
{
if (Roles.Any())
{
foreach(var role in Roles)
{
if (user.RoleNames.Contains(role))
{
await _userManager.RemoveFromRoleAsync(user, role);
}
}
return Outcomes("Done");
}
}
return Outcomes("Failed");
}
}
Loading

0 comments on commit eb04287

Please sign in to comment.