diff --git a/src/Orchard.Web/Orchard.Web.csproj b/src/Orchard.Web/Orchard.Web.csproj index ce925be36..e575d14eb 100644 --- a/src/Orchard.Web/Orchard.Web.csproj +++ b/src/Orchard.Web/Orchard.Web.csproj @@ -157,6 +157,7 @@ + diff --git a/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesModel.cs b/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesModel.cs new file mode 100644 index 000000000..924dee0aa --- /dev/null +++ b/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesModel.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Orchard.Models; + +namespace Orchard.Roles.Models.NoRecord { + public interface IUserRoles { + IList Roles { get; } + } + + public class UserRolesModel : ModelPart, IUserRoles { + public UserRolesModel() { + Roles = new List(); + } + + public IList Roles { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesModelDriver.cs b/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesModelDriver.cs new file mode 100644 index 000000000..36d5583fc --- /dev/null +++ b/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesModelDriver.cs @@ -0,0 +1,91 @@ +using System.Linq; +using Orchard.Data; +using Orchard.Logging; +using Orchard.Models.Driver; +using Orchard.Roles.Models.NoRecord; +using Orchard.Roles.Services; +using Orchard.Roles.ViewModels; +using Orchard.Security; +using Orchard.UI.Models; +using Orchard.UI.Notify; + +namespace Orchard.Roles.Models { + public class UserRolesModelDriver : ModelDriver { + private readonly IRepository _userRolesRepository; + private readonly IRoleService _roleService; + private readonly INotifier _notifier; + + public UserRolesModelDriver(IRepository userRolesRepository, IRoleService roleService, INotifier notifier) { + _userRolesRepository = userRolesRepository; + _roleService = roleService; + _notifier = notifier; + } + + protected override void New(NewModelContext context) { + if (context.ModelType == "user") { + WeldModelPart(context); + } + } + + protected override void Create(CreateModelContext context) { + var userRoles = context.Instance.As(); + if (userRoles != null) { + } + } + + protected override void Load(LoadModelContext context) { + var userRoles = context.Instance.As(); + if (userRoles != null) { + userRoles.Roles = _userRolesRepository.Fetch(x => x.UserId == userRoles.Id) + .Select(x => x.Role.Name).ToList(); + } + } + + protected override void GetEditors(GetModelEditorsContext context) { + var userRoles = context.Instance.As(); + if (userRoles != null) { + var roles = + _roleService.GetRoles().Select( + x => new UserRoleEntry { + RoleId = x.Id, + Name = x.Name, + Granted = userRoles.Roles.Contains(x.Name) + }); + + var viewModel = new UserRolesViewModel { + User = userRoles.As(), + UserRoles = userRoles, + Roles = roles.ToList(), + }; + + context.Editors.Add(ModelEditor.For("UserRoles", viewModel)); + } + } + + protected override void UpdateEditors(UpdateModelContext context) { + var userRoles = context.Instance.As(); + if (userRoles != null) { + var viewModel = new UserRolesViewModel(); + if (context.Updater.TryUpdateModel(viewModel, null, null, null)) { + + var currentUserRoleRecords = _userRolesRepository.Fetch(x => x.UserId == userRoles.Id); + var currentRoleRecords = currentUserRoleRecords.Select(x => x.Role); + var targetRoleRecords = viewModel.Roles.Where(x => x.Granted).Select(x => _roleService.GetRole(x.RoleId)); + + foreach (var addingRole in targetRoleRecords.Where(x => !currentRoleRecords.Contains(x))) { + _notifier.Warning(string.Format("Adding role {0} to user {1}", addingRole.Name, userRoles.As().UserName)); + _userRolesRepository.Create(new UserRolesRecord { UserId = userRoles.Id, Role = addingRole }); + } + + foreach (var removingRole in currentUserRoleRecords.Where(x => !targetRoleRecords.Contains(x.Role))) { + _notifier.Warning(string.Format("Removing role {0} from user {1}", removingRole.Role.Name, userRoles.As().UserName)); + _userRolesRepository.Delete(removingRole); + } + + } + context.Editors.Add(ModelEditor.For("UserRoles", viewModel)); + } + } + } +} + diff --git a/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesRecord.cs b/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesRecord.cs new file mode 100644 index 000000000..742fa95d5 --- /dev/null +++ b/src/Orchard.Web/Packages/Orchard.Roles/Models/UserRolesRecord.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace Orchard.Roles.Models { + public class UserRolesRecord { + public virtual int Id { get; set; } + public virtual int UserId { get; set; } + public virtual RoleRecord Role { get; set; } + } +} diff --git a/src/Orchard.Web/Packages/Orchard.Roles/Orchard.Roles.csproj b/src/Orchard.Web/Packages/Orchard.Roles/Orchard.Roles.csproj index 50db3e7fe..258a250c8 100644 --- a/src/Orchard.Web/Packages/Orchard.Roles/Orchard.Roles.csproj +++ b/src/Orchard.Web/Packages/Orchard.Roles/Orchard.Roles.csproj @@ -65,13 +65,17 @@ + + + + diff --git a/src/Orchard.Web/Packages/Orchard.Roles/ViewModels/UserRolesViewModel.cs b/src/Orchard.Web/Packages/Orchard.Roles/ViewModels/UserRolesViewModel.cs new file mode 100644 index 000000000..399c80fcd --- /dev/null +++ b/src/Orchard.Web/Packages/Orchard.Roles/ViewModels/UserRolesViewModel.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Orchard.Roles.Models.NoRecord; +using Orchard.Security; + +namespace Orchard.Roles.ViewModels { + public class UserRolesViewModel { + public IUser User { get; set; } + public IUserRoles UserRoles { get; set; } + public IList Roles { get; set; } + } + + public class UserRoleEntry { + public int RoleId { get; set; } + public string Name { get; set; } + public bool Granted { get; set; } + } +} diff --git a/src/Orchard.Web/Packages/Orchard.Users/Controllers/AdminController.cs b/src/Orchard.Web/Packages/Orchard.Users/Controllers/AdminController.cs index 7007d4839..03ff64926 100644 --- a/src/Orchard.Web/Packages/Orchard.Users/Controllers/AdminController.cs +++ b/src/Orchard.Web/Packages/Orchard.Users/Controllers/AdminController.cs @@ -3,13 +3,14 @@ using System.Linq; using System.Web.Mvc; using Orchard.Data; using Orchard.Models; +using Orchard.Models.Driver; using Orchard.Security; using Orchard.UI.Notify; using Orchard.Users.Models; using Orchard.Users.ViewModels; namespace Orchard.Users.Controllers { - public class AdminController : Controller { + public class AdminController : Controller, IModelUpdater { private readonly IModelManager _modelManager; private readonly IRepository _userRepository; private readonly INotifier _notifier; @@ -54,12 +55,15 @@ namespace Orchard.Users.Controllers { public ActionResult Edit(int id) { var model = new UserEditViewModel { User = _modelManager.Get(id) }; + model.Editors = _modelManager.GetEditors(model.User); return View(model); } [HttpPost] public ActionResult Edit(int id, FormCollection input) { var model = new UserEditViewModel { User = _modelManager.Get(id) }; + model.Editors = _modelManager.UpdateEditors(model.User, this); + if (!TryUpdateModel(model, input.ToValueProvider())) { return View(model); } @@ -67,6 +71,10 @@ namespace Orchard.Users.Controllers { return RedirectToAction("Edit", new { id }); } + + bool IModelUpdater.TryUpdateModel(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) { + return TryUpdateModel(model, prefix, includeProperties, excludeProperties); + } } } diff --git a/src/Orchard.Web/Packages/Orchard.Users/ViewModels/UserEditViewModel.cs b/src/Orchard.Web/Packages/Orchard.Users/ViewModels/UserEditViewModel.cs index 4347256a9..644db61f7 100644 --- a/src/Orchard.Web/Packages/Orchard.Users/ViewModels/UserEditViewModel.cs +++ b/src/Orchard.Web/Packages/Orchard.Users/ViewModels/UserEditViewModel.cs @@ -1,12 +1,15 @@ +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Web.Mvc; using Orchard.Models; using Orchard.Mvc.ViewModels; +using Orchard.UI.Models; using Orchard.Users.Models; namespace Orchard.Users.ViewModels { public class UserEditViewModel : AdminViewModel { public IModel User { get; set; } + public IEnumerable Editors { get; set; } [HiddenInput(DisplayValue = false)] public int Id { diff --git a/src/Orchard.Web/Packages/Orchard.Users/Views/Admin/EditorTemplates/UserEditViewModel.ascx b/src/Orchard.Web/Packages/Orchard.Users/Views/Admin/EditorTemplates/UserEditViewModel.ascx index f6c02264b..16e5d9328 100644 --- a/src/Orchard.Web/Packages/Orchard.Users/Views/Admin/EditorTemplates/UserEditViewModel.ascx +++ b/src/Orchard.Web/Packages/Orchard.Users/Views/Admin/EditorTemplates/UserEditViewModel.ascx @@ -6,3 +6,7 @@ <%=Html.EditorFor(m=>m.UserName, "inputTextLarge") %> <%=Html.EditorFor(m=>m.Email, "inputTextLarge") %> + +<% foreach(var editor in Model.Editors) { + Html.RenderPartial(editor.PartialName, editor.ViewData); +} %> diff --git a/src/Orchard.Web/Views/Admin/UserRoles.ascx b/src/Orchard.Web/Views/Admin/UserRoles.ascx new file mode 100644 index 000000000..28f52bbbc --- /dev/null +++ b/src/Orchard.Web/Views/Admin/UserRoles.ascx @@ -0,0 +1,16 @@ +<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> +

+ Roles

+
    +<% + var index = 0; foreach (var entry in Model.Roles) {%> +
  1. + + <%= Html.Hidden("Roles[" + index + "].RoleId", entry.RoleId)%> + + +
  2. +<%++index; + } %> +
+ diff --git a/src/Orchard/Models/DefaultModelManager.cs b/src/Orchard/Models/DefaultModelManager.cs index fdb6c6e2d..5ca215a46 100644 --- a/src/Orchard/Models/DefaultModelManager.cs +++ b/src/Orchard/Models/DefaultModelManager.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Web.Mvc; using Orchard.Data; using Orchard.Models.Driver; using Orchard.Models.Records; +using Orchard.UI.Models; namespace Orchard.Models { public class DefaultModelManager : IModelManager { @@ -82,6 +84,22 @@ namespace Orchard.Models { } } + public IEnumerable GetEditors(IModel model) { + var context = new GetModelEditorsContext(model); + foreach (var driver in _drivers) { + driver.GetEditors(context); + } + return context.Editors; + } + + public IEnumerable UpdateEditors(IModel model, IModelUpdater updater) { + var context = new UpdateModelContext(model, updater); + foreach (var driver in _drivers) { + driver.UpdateEditors(context); + } + return context.Editors; + } + private ModelTypeRecord AcquireModelTypeRecord(string modelType) { var modelTypeRecord = _modelTypeRepository.Get(x => x.Name == modelType); if (modelTypeRecord == null) { diff --git a/src/Orchard/Models/Driver/GetModelEditorsContext.cs b/src/Orchard/Models/Driver/GetModelEditorsContext.cs new file mode 100644 index 000000000..0b71477c3 --- /dev/null +++ b/src/Orchard/Models/Driver/GetModelEditorsContext.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Orchard.UI.Models; + +namespace Orchard.Models.Driver { + public class GetModelEditorsContext { + public GetModelEditorsContext(IModel model) { + Instance = model; + Editors= new List(); + } + public IModel Instance { get; set; } + public IList Editors { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard/Models/Driver/IModelDriver.cs b/src/Orchard/Models/Driver/IModelDriver.cs index f43a2c278..c4905eb77 100644 --- a/src/Orchard/Models/Driver/IModelDriver.cs +++ b/src/Orchard/Models/Driver/IModelDriver.cs @@ -3,5 +3,8 @@ void New(NewModelContext context); void Create(CreateModelContext context); void Load(LoadModelContext context); + + void GetEditors(GetModelEditorsContext context); + void UpdateEditors(UpdateModelContext context); } } \ No newline at end of file diff --git a/src/Orchard/Models/Driver/IModelUpdater.cs b/src/Orchard/Models/Driver/IModelUpdater.cs new file mode 100644 index 000000000..acd699a18 --- /dev/null +++ b/src/Orchard/Models/Driver/IModelUpdater.cs @@ -0,0 +1,5 @@ +namespace Orchard.Models.Driver { + public interface IModelUpdater { + bool TryUpdateModel(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class; + } +} \ No newline at end of file diff --git a/src/Orchard/Models/Driver/ModelDriver.cs b/src/Orchard/Models/Driver/ModelDriver.cs index 56c86b7d2..3bba22106 100644 --- a/src/Orchard/Models/Driver/ModelDriver.cs +++ b/src/Orchard/Models/Driver/ModelDriver.cs @@ -12,6 +12,8 @@ namespace Orchard.Models.Driver { void IModelDriver.New(NewModelContext context) {New(context);} void IModelDriver.Create(CreateModelContext context) { Create(context); } void IModelDriver.Load(LoadModelContext context) { Load(context); } + void IModelDriver.GetEditors(GetModelEditorsContext context) { GetEditors(context); } + void IModelDriver.UpdateEditors(UpdateModelContext context) { UpdateEditors(context); } protected virtual void New(NewModelContext context) { } @@ -22,10 +24,22 @@ namespace Orchard.Models.Driver { protected virtual void Create(CreateModelContext context) { } + protected virtual void GetEditors(GetModelEditorsContext context) { + } + + protected virtual void UpdateEditors(UpdateModelContext context) { + } + + /// + /// TODO: move this - make a modelbuilder class or something + /// + /// + /// protected void WeldModelPart(NewModelContext context) where TPart : class,IModel,new() { var newPart = new TPart(); newPart.Weld(context.Instance); context.Instance = newPart; } + } } \ No newline at end of file diff --git a/src/Orchard/Models/Driver/UpdateModelContext.cs b/src/Orchard/Models/Driver/UpdateModelContext.cs new file mode 100644 index 000000000..7e7fc0b62 --- /dev/null +++ b/src/Orchard/Models/Driver/UpdateModelContext.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Web.Mvc; +using Orchard.UI.Models; + +namespace Orchard.Models.Driver { + public class UpdateModelContext : GetModelEditorsContext { + public UpdateModelContext(IModel model, IModelUpdater updater) : base(model) { + Updater = updater; + } + + public IModelUpdater Updater { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard/Models/IModelManager.cs b/src/Orchard/Models/IModelManager.cs index af793d2ff..501961dcf 100644 --- a/src/Orchard/Models/IModelManager.cs +++ b/src/Orchard/Models/IModelManager.cs @@ -1,7 +1,14 @@ +using System.Collections.Generic; +using System.Web.Mvc; +using Orchard.Models.Driver; +using Orchard.UI.Models; + namespace Orchard.Models { public interface IModelManager : IDependency { IModel New(string modelType); IModel Get(int id); void Create(IModel model); + IEnumerable GetEditors(IModel model); + IEnumerable UpdateEditors(IModel model, IModelUpdater updater); } } diff --git a/src/Orchard/Orchard.csproj b/src/Orchard/Orchard.csproj index 636bef404..1bb43c7be 100644 --- a/src/Orchard/Orchard.csproj +++ b/src/Orchard/Orchard.csproj @@ -90,9 +90,9 @@ - - - + + + @@ -103,12 +103,12 @@ - - + + - - + +
@@ -117,7 +117,8 @@ - + + @@ -132,6 +133,7 @@ + @@ -142,6 +144,7 @@ + @@ -159,6 +162,7 @@ + diff --git a/src/Orchard/UI/Models/ModelEditor.cs b/src/Orchard/UI/Models/ModelEditor.cs new file mode 100644 index 000000000..9220f664a --- /dev/null +++ b/src/Orchard/UI/Models/ModelEditor.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.Mvc; + +namespace Orchard.UI.Models { + public class ModelEditor { + public string PartialName { get; set; } + public ViewDataDictionary ViewData { get; set; } + + public static ModelEditor For(string partialName, TModel model) { + return new ModelEditor { + PartialName = partialName, + ViewData = new ViewDataDictionary(model) + }; + } + } +}