Extracting some permissions from SiteOwner

ManageUsers, ManageRoles, AssignRoles and SiteSettings are
new permission which makes it possible to have Administrators roles
without the need of SiteOwner.

Typical scenario:
"super" account is SiteOwner
"admin" account is Administrator without SiteOwner, but with ManageUsers,
ManageRoles and SiteSettings but NOT AssignRoles
This commit is contained in:
Sebastien Ros
2014-03-13 14:25:54 -07:00
parent e753678c1f
commit 6e17c7c6f5
14 changed files with 142 additions and 49 deletions

View File

@@ -225,6 +225,7 @@
<Compile Include="Scheduling\Services\ScheduledTaskExecutor.cs" />
<Compile Include="Scheduling\Models\Task.cs" />
<Compile Include="Settings\Commands\SiteSettingsCommands.cs" />
<Compile Include="Settings\Permissions.cs" />
<Compile Include="Settings\ResourceManifest.cs" />
<Compile Include="Settings\Migrations.cs" />
<Compile Include="Settings\Drivers\SiteSettingsPartDriver.cs" />

View File

@@ -21,7 +21,7 @@ namespace Orchard.Core.Settings {
builder.AddImageSet("settings")
.Add(T("Settings"), "99",
menu => menu.Add(T("General"), "0", item => item.Action("Index", "Admin", new { area = "Settings", groupInfoId = "Index" })
.Permission(StandardPermissions.SiteOwner)), new [] {"collapsed"});
.Permission(Permissions.ManageSettings)), new [] {"collapsed"});
var site = _siteService.GetSiteSettings();
if (site == null)
@@ -31,7 +31,7 @@ namespace Orchard.Core.Settings {
GroupInfo info = groupInfo;
builder.Add(T("Settings"),
menu => menu.Add(info.Name, info.Position, item => item.Action("Index", "Admin", new { area = "Settings", groupInfoId = info.Id })
.Permission(StandardPermissions.SiteOwner)));
.Permission(Permissions.ManageSettings)));
}
}
}

View File

@@ -1,13 +1,10 @@
using System;
using System.Globalization;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Settings.ViewModels;
using Orchard.Localization;
using Orchard.ContentManagement;
using Orchard.Localization.Services;
using Orchard.Security;
using Orchard.Settings;
using Orchard.UI.Notify;
@@ -31,7 +28,7 @@ namespace Orchard.Core.Settings.Controllers {
public Localizer T { get; set; }
public ActionResult Index(string groupInfoId) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage settings")))
if (!Services.Authorizer.Authorize(Permissions.ManageSettings, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
dynamic model;
@@ -57,7 +54,7 @@ namespace Orchard.Core.Settings.Controllers {
[HttpPost, ActionName("Index")]
public ActionResult IndexPOST(string groupInfoId) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage settings")))
if (!Services.Authorizer.Authorize(Permissions.ManageSettings, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
var site = _siteService.GetSiteSettings();
@@ -91,7 +88,7 @@ namespace Orchard.Core.Settings.Controllers {
public ActionResult Culture() {
//todo: class and/or method attributes for our auth?
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage settings")))
if (!Services.Authorizer.Authorize(Permissions.ManageSettings, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
var model = new SiteCulturesViewModel {
@@ -107,7 +104,7 @@ namespace Orchard.Core.Settings.Controllers {
[HttpPost]
public ActionResult AddCulture(string systemCultureName, string cultureName) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage settings")))
if (!Services.Authorizer.Authorize(Permissions.ManageSettings, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
cultureName = string.IsNullOrWhiteSpace(cultureName) ? systemCultureName : cultureName;
@@ -120,7 +117,7 @@ namespace Orchard.Core.Settings.Controllers {
[HttpPost]
public ActionResult DeleteCulture(string cultureName) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage settings")))
if (!Services.Authorizer.Authorize(Permissions.ManageSettings, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
_cultureManager.DeleteCulture(cultureName);

View File

@@ -21,18 +21,21 @@ namespace Orchard.Core.Settings.Drivers {
private readonly ICalendarManager _calendarProvider;
private readonly IMembershipService _membershipService;
private readonly INotifier _notifier;
private readonly IAuthorizer _authorizer;
public SiteSettingsPartDriver(
ISiteService siteService,
ICultureManager cultureManager,
ICalendarManager calendarProvider,
IMembershipService membershipService,
INotifier notifier) {
INotifier notifier,
IAuthorizer authorizer) {
_siteService = siteService;
_cultureManager = cultureManager;
_calendarProvider = calendarProvider;
_membershipService = membershipService;
_notifier = notifier;
_authorizer = authorizer;
T = NullLocalizer.Instance;
Logger = NullLogger.Instance;
@@ -67,21 +70,27 @@ namespace Orchard.Core.Settings.Drivers {
};
var previousBaseUrl = model.Site.BaseUrl;
var previousSuperUser = model.Site.SuperUser;
updater.TryUpdateModel(model, Prefix, null, null);
// ensures the super user is fully empty
if (String.IsNullOrEmpty(model.SuperUser)) {
model.SuperUser = String.Empty;
}
// otherwise the super user must be a valid user, to prevent an external account to impersonate as this name
//the user management module ensures the super user can't be deleted, but it can be disabled
else {
if (_membershipService.GetUser(model.SuperUser) == null) {
updater.AddModelError("SuperUser", T("The user {0} was not found", model.SuperUser));
// only a user with SiteOwner permission can change the site owner
if (_authorizer.Authorize(StandardPermissions.SiteOwner)) {
// ensures the super user is fully empty
if (String.IsNullOrEmpty(model.SuperUser)) {
model.SuperUser = String.Empty;
}
// otherwise the super user must be a valid user, to prevent an external account to impersonate as this name
//the user management module ensures the super user can't be deleted, but it can be disabled
else {
if (_membershipService.GetUser(model.SuperUser) == null) {
updater.AddModelError("SuperUser", T("The user {0} was not found", model.SuperUser));
}
}
}
else {
model.Site.SuperUser = previousSuperUser;
}
// ensure the base url is absolute if provided
if (!String.IsNullOrWhiteSpace(model.Site.BaseUrl)) {

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using Orchard.Environment.Extensions.Models;
using Orchard.Security.Permissions;
namespace Orchard.Core.Settings {
public class Permissions : IPermissionProvider {
public static readonly Permission ManageSettings = new Permission { Description = "Manage Settings", Name = "ManageSettings" };
public virtual Feature Feature { get; set; }
public IEnumerable<Permission> GetPermissions() {
return new[] {
ManageSettings
};
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] {ManageSettings}
},
};
}
}
}

View File

@@ -45,12 +45,14 @@
@Html.EditorFor(x => x.PageTitleSeparator)
@Html.ValidationMessage("PageTitleSeparator", "*")
</div>
<div>
<label for="SuperUser">@T("Super user")</label>
@Html.EditorFor(x=>x.SuperUser)
@Html.ValidationMessage("SuperUser", "*")
<span class="hint">@T("Enter an existing account name, or nothing if you don't want a Super user account")</span>
</div>
@if (AuthorizedFor(Orchard.Security.StandardPermissions.SiteOwner)) {
<div>
<label for="SuperUser">@T("Super user")</label>
@Html.EditorFor(x => x.SuperUser)
@Html.ValidationMessage("SuperUser", "*")
<span class="hint">@T("Enter an existing account name, or nothing if you don't want a Super user account")</span>
</div>
}
<div>
<label for="SiteDebugMode">@T("Resource Debug Mode")</label>
@Html.DropDownList("ResourceDebugMode", resourceDebugMode)

View File

@@ -36,7 +36,7 @@ namespace Orchard.Roles.Controllers {
public ILogger Logger { get; set; }
public ActionResult Index() {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage roles")))
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var model = new RolesIndexViewModel { Rows = _roleService.GetRoles().OrderBy(r => r.Name).ToList() };
@@ -46,7 +46,7 @@ namespace Orchard.Roles.Controllers {
[HttpPost, ActionName("Index")]
public ActionResult IndexPOST() {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage roles")))
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
foreach (string key in Request.Form.Keys) {
@@ -59,7 +59,7 @@ namespace Orchard.Roles.Controllers {
}
public ActionResult Create() {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage roles")))
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var model = new RoleCreateViewModel { FeaturePermissions = _roleService.GetInstalledPermissions() };
@@ -68,7 +68,7 @@ namespace Orchard.Roles.Controllers {
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST() {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage roles")))
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var viewModel = new RoleCreateViewModel();
@@ -100,7 +100,7 @@ namespace Orchard.Roles.Controllers {
}
public ActionResult Edit(int id) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage roles")))
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var role = _roleService.GetRole(id);
@@ -126,7 +126,7 @@ namespace Orchard.Roles.Controllers {
[HttpPost, ActionName("Edit")]
[FormValueRequired("submit.Save")]
public ActionResult EditSavePOST(int id) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage roles")))
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var viewModel = new RoleEditViewModel();
@@ -167,7 +167,7 @@ namespace Orchard.Roles.Controllers {
[HttpPost]
public ActionResult Delete(int id, string returnUrl) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage roles")))
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
_roleService.DeleteRole(id);

View File

@@ -45,7 +45,7 @@ namespace Orchard.Roles.Drivers {
protected override DriverResult Editor(UserRolesPart userRolesPart, dynamic shapeHelper) {
// don't show editor without apply roles permission
if (!_authorizationService.TryCheckAccess(StandardPermissions.SiteOwner, _authenticationService.GetAuthenticatedUser(), userRolesPart))
if (!_authorizationService.TryCheckAccess(Permissions.AssignRoles, _authenticationService.GetAuthenticatedUser(), userRolesPart))
return null;
return ContentShape("Parts_Roles_UserRoles_Edit",
@@ -65,7 +65,7 @@ namespace Orchard.Roles.Drivers {
protected override DriverResult Editor(UserRolesPart userRolesPart, IUpdateModel updater, dynamic shapeHelper) {
// don't apply editor without apply roles permission
if (!_authorizationService.TryCheckAccess(StandardPermissions.SiteOwner, _authenticationService.GetAuthenticatedUser(), userRolesPart))
if (!_authorizationService.TryCheckAccess(Permissions.AssignRoles, _authenticationService.GetAuthenticatedUser(), userRolesPart))
return null;
var model = BuildEditorViewModel(userRolesPart);

View File

@@ -88,6 +88,7 @@
<Compile Include="Handlers\UserRolesPartHandler.cs" />
<Compile Include="Models\RolesPermissionsRecord.cs" />
<Compile Include="Models\UserRolesPartRecord.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\IRoleService.cs" />
<Compile Include="Services\RolesBasedAuthorizationService.cs" />

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using Orchard.Environment.Extensions.Models;
using Orchard.Security.Permissions;
namespace Orchard.Roles {
public class Permissions : IPermissionProvider {
public static readonly Permission ManageRoles = new Permission { Description = "Managing Roles", Name = "ManageRoles" };
public static readonly Permission AssignRoles = new Permission { Description = "Assign Roles", Name = "AssignRoles", ImpliedBy = new [] { ManageRoles } };
public virtual Feature Feature { get; set; }
public IEnumerable<Permission> GetPermissions() {
return new[] {
ManageRoles, AssignRoles
};
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] {ManageRoles, AssignRoles}
},
};
}
}
}

View File

@@ -10,9 +10,9 @@ namespace Orchard.Users {
public void GetNavigation(NavigationBuilder builder) {
builder.AddImageSet("users")
.Add(T("Users"), "11",
menu => menu.Action("Index", "Admin", new { area = "Orchard.Users" }).Permission(StandardPermissions.SiteOwner)
menu => menu.Action("Index", "Admin", new { area = "Orchard.Users" })
.Add(T("Users"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Users" })
.LocalNav().Permission(StandardPermissions.SiteOwner)));
.LocalNav().Permission(Permissions.ManageUsers)));
}
}
}

View File

@@ -50,7 +50,7 @@ namespace Orchard.Users.Controllers {
public Localizer T { get; set; }
public ActionResult Index(UserIndexOptions options, PagerParameters pagerParameters) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to list users")))
return new HttpUnauthorizedResult();
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
@@ -115,7 +115,7 @@ namespace Orchard.Users.Controllers {
[HttpPost]
[FormValueRequired("submit.BulkEdit")]
public ActionResult Index(FormCollection input) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
var viewModel = new UsersIndexViewModel {Users = new List<UserEntry>(), Options = new UserIndexOptions()};
@@ -151,7 +151,7 @@ namespace Orchard.Users.Controllers {
}
public ActionResult Create() {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
var user = Services.ContentManager.New<IUser>("User");
@@ -165,7 +165,7 @@ namespace Orchard.Users.Controllers {
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST(UserCreateViewModel createModel) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
if (!string.IsNullOrEmpty(createModel.UserName)) {
@@ -209,7 +209,7 @@ namespace Orchard.Users.Controllers {
}
public ActionResult Edit(int id) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
var user = Services.ContentManager.Get<UserPart>(id);
@@ -223,7 +223,7 @@ namespace Orchard.Users.Controllers {
[HttpPost, ActionName("Edit")]
public ActionResult EditPOST(int id) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
var user = Services.ContentManager.Get<UserPart>(id, VersionOptions.DraftRequired);
@@ -268,7 +268,7 @@ namespace Orchard.Users.Controllers {
[HttpPost]
public ActionResult Delete(int id) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
var user = Services.ContentManager.Get<IUser>(id);
@@ -290,7 +290,7 @@ namespace Orchard.Users.Controllers {
}
public ActionResult SendChallengeEmail(int id) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
var user = Services.ContentManager.Get<IUser>(id);
@@ -310,7 +310,7 @@ namespace Orchard.Users.Controllers {
}
public ActionResult Approve(int id) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
var user = Services.ContentManager.Get<IUser>(id);
@@ -327,7 +327,7 @@ namespace Orchard.Users.Controllers {
}
public ActionResult Moderate(int id) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
var user = Services.ContentManager.Get<IUser>(id);

View File

@@ -85,6 +85,7 @@
<Compile Include="Handlers\UserPartHandler.cs" />
<Compile Include="Models\UserPartRecord.cs" />
<Compile Include="Models\UserStatus.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\AuthenticationRedirectionFilter.cs" />
<Compile Include="Services\IUserService.cs" />

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using Orchard.Environment.Extensions.Models;
using Orchard.Security.Permissions;
namespace Orchard.Users {
public class Permissions : IPermissionProvider {
public static readonly Permission ManageUsers = new Permission { Description = "Managing Users", Name = "ManageUsers" };
public virtual Feature Feature { get; set; }
public IEnumerable<Permission> GetPermissions() {
return new[] {
ManageUsers,
};
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] {ManageUsers}
},
};
}
}
}