mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Roles: Fixing and DRYing IsInRoleActivity and RoleCondition to be able handle "Anonymous" and "Authenticated" + code styling, fixes #6948
This commit is contained in:
parent
bbd0d9bb16
commit
83ba470cd2
src/Orchard.Web/Modules/Orchard.Roles
Activities
Conditions
Constants
Extensions
Migrations.csOrchard.Roles.csprojServices
Views/EditorTemplates/Parts
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Security;
|
||||
using Orchard.Roles.Models;
|
||||
using Orchard.Workflows.Models;
|
||||
using Orchard.Workflows.Services;
|
||||
|
||||
@ -28,7 +28,7 @@ namespace Orchard.Roles.Activities {
|
||||
}
|
||||
|
||||
public override LocalizedString Description {
|
||||
get { return T("Whether the current user is in a specific role."); }
|
||||
get { return T("Whether the current user is in a specific role."); }
|
||||
}
|
||||
|
||||
public override string Form {
|
||||
@ -36,7 +36,7 @@ namespace Orchard.Roles.Activities {
|
||||
}
|
||||
|
||||
public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext) {
|
||||
return new[] {T("Yes"), T("No")};
|
||||
return new[] { T("Yes"), T("No") };
|
||||
}
|
||||
|
||||
public override bool CanExecute(WorkflowContext workflowContext, ActivityContext activityContext) {
|
||||
@ -44,51 +44,16 @@ namespace Orchard.Roles.Activities {
|
||||
}
|
||||
|
||||
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext) {
|
||||
|
||||
if (UserIsInRole(activityContext)) {
|
||||
yield return T("Yes");
|
||||
}
|
||||
else {
|
||||
yield return T("No");
|
||||
}
|
||||
yield return _workContextAccessor.GetContext().CurrentUser.UserIsInRole(GetRoles(activityContext)) ? T("Yes") : T("No");
|
||||
}
|
||||
|
||||
private bool UserIsInRole(ActivityContext context) {
|
||||
|
||||
// checking if user is in an accepted role
|
||||
var workContext = _workContextAccessor.GetContext();
|
||||
var user = workContext.CurrentUser;
|
||||
var roles = GetRoles(context);
|
||||
|
||||
return UserIsInRole(user, roles);
|
||||
}
|
||||
|
||||
public static bool UserIsInRole(IUser user, IEnumerable<string> roles) {
|
||||
bool isInRole = false;
|
||||
|
||||
if (user == null) {
|
||||
isInRole = roles.Contains("Anonymous");
|
||||
}
|
||||
else {
|
||||
dynamic dynUser = user.ContentItem;
|
||||
|
||||
if (dynUser.UserRolesPart != null) {
|
||||
IEnumerable<string> userRoles = dynUser.UserRolesPart.Roles;
|
||||
isInRole = userRoles.Any(roles.Contains);
|
||||
}
|
||||
}
|
||||
|
||||
return isInRole;
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetRoles(ActivityContext context) {
|
||||
string roles = context.GetState<string>("Roles");
|
||||
|
||||
if (String.IsNullOrEmpty(roles)) {
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
return roles.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();
|
||||
return string.IsNullOrEmpty(roles) ?
|
||||
Enumerable.Empty<string>() :
|
||||
roles.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
using Orchard.ContentManagement;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Orchard.Events;
|
||||
using Orchard.Roles.Models;
|
||||
using Orchard.Security;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Orchard.Roles.Conditions {
|
||||
public interface IConditionProvider : IEventHandler {
|
||||
@ -18,19 +17,14 @@ namespace Orchard.Roles.Conditions {
|
||||
}
|
||||
|
||||
public void Evaluate(dynamic evaluationContext) {
|
||||
if (!String.Equals(evaluationContext.FunctionName, "role", StringComparison.OrdinalIgnoreCase)) {
|
||||
if (!string.Equals(evaluationContext.FunctionName, "role", StringComparison.OrdinalIgnoreCase)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var user = _authenticationService.GetAuthenticatedUser();
|
||||
if (user == null) {
|
||||
evaluationContext.Result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var roles = ((object[])evaluationContext.Arguments).Cast<string>();
|
||||
var userRoles = user.As<IUserRoles>();
|
||||
evaluationContext.Result = userRoles != null && userRoles.Roles.Intersect(roles).Any();
|
||||
|
||||
evaluationContext.Result = user.UserIsInRole(roles);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Roles.Constants {
|
||||
public static class SystemRoles {
|
||||
public const string Anonymous = nameof(Anonymous);
|
||||
public const string Authenticated = nameof(Authenticated);
|
||||
|
||||
public static IEnumerable<string> GetSystemRoles() {
|
||||
return new List<string> { Anonymous, Authenticated };
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Roles.Constants;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.Roles.Models {
|
||||
public static class UserRolesExtensions {
|
||||
/// <summary>
|
||||
/// Determines whether the given User has any of the provided list of Roles.
|
||||
/// </summary>
|
||||
/// <param name="user">The User to examine.</param>
|
||||
/// <param name="roles">The list of Roles to compare to User's Roles with.</param>
|
||||
/// <returns>True if the User has any of the provided Roles.</returns>
|
||||
public static bool UserIsInRole(this IUser user, IEnumerable<string> roles) {
|
||||
return UserIsInRole(user.As<UserRolesPart>(), roles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given User has any of the provided list of Roles.
|
||||
/// </summary>
|
||||
/// <param name="user">The User to examine.</param>
|
||||
/// <param name="roles">The list of Roles to compare to User's Roles with.</param>
|
||||
/// <returns>True if the User has any of the provided Roles.</returns>
|
||||
public static bool UserIsInRole(this UserRolesPart userRolesPart, IEnumerable<string> roles) {
|
||||
if (!roles?.Any() ?? false) return false;
|
||||
|
||||
return userRolesPart == null ?
|
||||
roles.Contains(SystemRoles.Anonymous) :
|
||||
roles.Contains(SystemRoles.Authenticated) || userRolesPart.Roles.Any(roles.Contains);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of Roles the User has, including the ones
|
||||
/// that are not assignable (Anonymous or Authenticated).
|
||||
/// </summary>
|
||||
/// <param name="user">The User whose Roles are to be retrieved.</param>
|
||||
/// <returns>The User's list of Roles.</returns>
|
||||
public static IEnumerable<string> GetRuntimeUserRoles(this IUser user) {
|
||||
return GetRuntimeUserRoles(user.As<UserRolesPart>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of Roles the User has, including the ones
|
||||
/// that are not assignable (Anonymous or Authenticated).
|
||||
/// </summary>
|
||||
/// <param name="user">The UserRolesPart of the User whose Roles are to be retrieved.</param>
|
||||
/// <returns>The User's list of Roles.</returns>
|
||||
public static IEnumerable<string> GetRuntimeUserRoles(this UserRolesPart userRolesPart) {
|
||||
var roles = new List<string>();
|
||||
|
||||
if (userRolesPart == null) roles.Add(SystemRoles.Anonymous);
|
||||
else {
|
||||
roles.Add(SystemRoles.Authenticated);
|
||||
roles.AddRange(userRolesPart.Roles);
|
||||
}
|
||||
|
||||
return roles;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ using Orchard.Data.Migration;
|
||||
using Orchard.Roles.Models;
|
||||
using Orchard.Roles.Services;
|
||||
using Orchard.Security;
|
||||
using Orchard.Roles.Constants;
|
||||
using ContentsPermissions = Orchard.Core.Contents.Permissions;
|
||||
|
||||
namespace Orchard.Roles {
|
||||
public class RolesDataMigration : DataMigrationImpl {
|
||||
@ -58,32 +60,32 @@ namespace Orchard.Roles {
|
||||
public int UpdateFrom1() {
|
||||
|
||||
// creates default permissions for Orchard v1.4 instances and earlier
|
||||
_roleService.CreatePermissionForRole("Anonymous", Orchard.Core.Contents.Permissions.ViewContent.Name);
|
||||
_roleService.CreatePermissionForRole("Authenticated", Orchard.Core.Contents.Permissions.ViewContent.Name);
|
||||
_roleService.CreatePermissionForRole(SystemRoles.Anonymous, ContentsPermissions.ViewContent.Name);
|
||||
_roleService.CreatePermissionForRole(SystemRoles.Authenticated, ContentsPermissions.ViewContent.Name);
|
||||
|
||||
return 2;
|
||||
}
|
||||
public int UpdateFrom2() {
|
||||
//Assigns the "Create Permission" to all roles able to create contents
|
||||
var contentEditPermissions = new[] {
|
||||
Core.Contents.Permissions.EditContent,
|
||||
Core.Contents.Permissions.EditOwnContent
|
||||
ContentsPermissions.EditContent,
|
||||
ContentsPermissions.EditOwnContent
|
||||
};
|
||||
|
||||
var dynamicPermissions = new Orchard.Core.Contents.DynamicPermissions(_contentDefinitionManager);
|
||||
var dynamicPermissions = new DynamicPermissions(_contentDefinitionManager);
|
||||
var securableTypes = _contentDefinitionManager.ListTypeDefinitions()
|
||||
.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Securable);
|
||||
var permissionTemplates = Core.Contents.DynamicPermissions.PermissionTemplates;
|
||||
var permissionTemplates = DynamicPermissions.PermissionTemplates;
|
||||
List<object> dynContentPermissions = new List<object>();
|
||||
|
||||
foreach (var typeDefinition in securableTypes) {
|
||||
dynContentPermissions.Add(new {
|
||||
Permission = DynamicPermissions.CreateDynamicPermission(permissionTemplates[Core.Contents.Permissions.EditContent.Name], typeDefinition),
|
||||
CreatePermission = DynamicPermissions.CreateDynamicPermission(permissionTemplates[Core.Contents.Permissions.CreateContent.Name], typeDefinition)
|
||||
Permission = DynamicPermissions.CreateDynamicPermission(permissionTemplates[ContentsPermissions.EditContent.Name], typeDefinition),
|
||||
CreatePermission = DynamicPermissions.CreateDynamicPermission(permissionTemplates[ContentsPermissions.CreateContent.Name], typeDefinition)
|
||||
});
|
||||
dynContentPermissions.Add(new {
|
||||
Permission = DynamicPermissions.CreateDynamicPermission(permissionTemplates[Core.Contents.Permissions.EditOwnContent.Name], typeDefinition),
|
||||
CreatePermission = DynamicPermissions.CreateDynamicPermission(permissionTemplates[Core.Contents.Permissions.CreateContent.Name], typeDefinition)
|
||||
Permission = DynamicPermissions.CreateDynamicPermission(permissionTemplates[ContentsPermissions.EditOwnContent.Name], typeDefinition),
|
||||
CreatePermission = DynamicPermissions.CreateDynamicPermission(permissionTemplates[ContentsPermissions.CreateContent.Name], typeDefinition)
|
||||
});
|
||||
}
|
||||
var roles = _roleService.GetRoles();
|
||||
@ -91,13 +93,13 @@ namespace Orchard.Roles {
|
||||
var existingPermissionsNames = role.RolesPermissions.Select(x => x.Permission.Name).ToList();
|
||||
var checkForDynamicPermissions = true;
|
||||
var updateRole = false;
|
||||
if (existingPermissionsNames.Any(x => x == Core.Contents.Permissions.CreateContent.Name)) {
|
||||
if (existingPermissionsNames.Any(x => x == ContentsPermissions.CreateContent.Name)) {
|
||||
continue; // Skipping this role cause it already has the Create content permission
|
||||
}
|
||||
var simulation = UserSimulation.Create(role.Name);
|
||||
foreach (var contentEditPermission in contentEditPermissions) {
|
||||
if (_authorizationService.TryCheckAccess(contentEditPermission, simulation, null)) {
|
||||
existingPermissionsNames.Add(Core.Contents.Permissions.CreateContent.Name);
|
||||
existingPermissionsNames.Add(ContentsPermissions.CreateContent.Name);
|
||||
checkForDynamicPermissions = false;
|
||||
updateRole = true;
|
||||
break;
|
||||
|
@ -102,6 +102,7 @@
|
||||
<Compile Include="Activities\UserTaskActivity.cs" />
|
||||
<Compile Include="AdminMenu.cs" />
|
||||
<Compile Include="Commands\RoleCommands.cs" />
|
||||
<Compile Include="Constants\SystemRoles.cs" />
|
||||
<Compile Include="Controllers\AdminController.cs" />
|
||||
<Compile Include="Drivers\UserTaskDriver.cs" />
|
||||
<Compile Include="Events\IRoleEventHandler.cs" />
|
||||
@ -115,6 +116,7 @@
|
||||
<Compile Include="Events\UserAddedContext.cs" />
|
||||
<Compile Include="Events\UserRemovedContext.cs" />
|
||||
<Compile Include="Events\UserRoleContext.cs" />
|
||||
<Compile Include="Extensions\UserRolesExtensions.cs" />
|
||||
<Compile Include="Forms\SelectRolesForms.cs" />
|
||||
<Compile Include="Forms\UserTaskForms.cs" />
|
||||
<Compile Include="Recipes\Builders\RolesStep.cs" />
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Roles.Constants;
|
||||
using Orchard.Roles.Models;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
@ -13,8 +14,6 @@ namespace Orchard.Roles.Services {
|
||||
private readonly IRoleService _roleService;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
private readonly IAuthorizationServiceEventHandler _authorizationServiceEventHandler;
|
||||
private static readonly string[] AnonymousRole = new[] { "Anonymous" };
|
||||
private static readonly string[] AuthenticatedRole = new[] { "Authenticated" };
|
||||
|
||||
public RolesBasedAuthorizationService(IRoleService roleService, IWorkContextAccessor workContextAccessor, IAuthorizationServiceEventHandler authorizationServiceEventHandler) {
|
||||
_roleService = roleService;
|
||||
@ -57,22 +56,22 @@ namespace Orchard.Roles.Services {
|
||||
var grantingNames = PermissionNames(context.Permission, Enumerable.Empty<string>()).Distinct().ToArray();
|
||||
|
||||
// determine what set of roles should be examined by the access check
|
||||
IEnumerable<string> rolesToExamine;
|
||||
var rolesToExamine = new List<string>();
|
||||
if (context.User == null) {
|
||||
rolesToExamine = AnonymousRole;
|
||||
rolesToExamine.Add(SystemRoles.Anonymous);
|
||||
}
|
||||
else if (context.User.Has<IUserRoles>()) {
|
||||
// the current user is not null, so get his roles and add "Authenticated" to it
|
||||
rolesToExamine = context.User.As<IUserRoles>().Roles;
|
||||
rolesToExamine = context.User.As<IUserRoles>().Roles.ToList();
|
||||
|
||||
// when it is a simulated anonymous user in the admin
|
||||
if (!rolesToExamine.Contains(AnonymousRole[0])) {
|
||||
rolesToExamine = rolesToExamine.Concat(AuthenticatedRole);
|
||||
if (!rolesToExamine.Contains(SystemRoles.Anonymous)) {
|
||||
rolesToExamine.Add(SystemRoles.Authenticated);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the user is not null and has no specific role, then it's just "Authenticated"
|
||||
rolesToExamine = AuthenticatedRole;
|
||||
rolesToExamine.Add(SystemRoles.Authenticated);
|
||||
}
|
||||
|
||||
foreach (var role in rolesToExamine) {
|
||||
|
@ -1,26 +1,31 @@
|
||||
@using Orchard.Roles.Constants
|
||||
@using Orchard.Roles.ViewModels
|
||||
@using System.Linq
|
||||
|
||||
@model UserRolesViewModel
|
||||
@using Orchard.Roles.ViewModels;
|
||||
|
||||
<fieldset>
|
||||
<legend>@T("Roles")</legend>
|
||||
|
||||
@if (Model.Roles.Count > 0) {
|
||||
var index = 0;
|
||||
foreach (var entry in Model.Roles) {
|
||||
if (string.Equals(entry.Name, "Authenticated", StringComparison.OrdinalIgnoreCase) || string.Equals(entry.Name, "Anonymous", StringComparison.OrdinalIgnoreCase)) {
|
||||
if (SystemRoles.GetSystemRoles().Contains(entry.Name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@Html.Hidden("Roles[" + index + "].RoleId", entry.RoleId)
|
||||
@Html.Hidden("Roles[" + index + "].Name", entry.Name)
|
||||
|
||||
<div>
|
||||
@Html.CheckBox("Roles[" + index + "].Granted", entry.Granted)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Roles[index].Granted)">@entry.Name</label>
|
||||
</div>
|
||||
<div>
|
||||
@Html.CheckBox("Roles[" + index + "].Granted", entry.Granted)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Roles[index].Granted)">@entry.Name</label>
|
||||
</div>
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
<p>@T("There are no roles.")</p>
|
||||
<p>@T("There are no roles.")</p>
|
||||
}
|
||||
</fieldset>
|
||||
|
Loading…
Reference in New Issue
Block a user