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) {%>
+-
+
+ <%= Html.Hidden("Roles[" + index + "].RoleId", entry.RoleId)%>
+
+
+
+<%++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)
+ };
+ }
+ }
+}