Skip to content

Commit

Permalink
Makes IUser extensible (#1054)
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Payne authored and sebastienros committed Oct 3, 2017
1 parent 6127d0a commit e3161ea
Show file tree
Hide file tree
Showing 16 changed files with 357 additions and 252 deletions.
172 changes: 33 additions & 139 deletions src/OrchardCore.Modules/OrchardCore.Users/Controllers/AdminController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
Expand All @@ -9,6 +7,7 @@
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Localization;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.DisplayManagement.Notify;
using OrchardCore.Navigation;
using OrchardCore.Security;
Expand All @@ -22,21 +21,19 @@

namespace OrchardCore.Users.Controllers
{
public class AdminController : Controller
public class AdminController : Controller, IUpdateModel
{
private readonly UserManager<IUser> _userManager;
private readonly ISession _session;
private readonly IAuthorizationService _authorizationService;
private readonly IStringLocalizer T;
private readonly IHtmlLocalizer TH;
private readonly ISiteService _siteService;
private readonly dynamic New;
private readonly RoleManager<IRole> _roleManager;
private readonly IRoleProvider _roleProvider;
private readonly IDisplayManager<User> _userDisplayManager;
private readonly INotifier _notifier;
private readonly IUserService _userService;

public AdminController(
IDisplayManager<User> userDisplayManager,
IAuthorizationService authorizationService,
ISession session,
UserManager<IUser> userManager,
Expand All @@ -50,17 +47,14 @@ public class AdminController : Controller
IUserService userService
)
{
_userDisplayManager = userDisplayManager;
_notifier = notifier;
_roleProvider = roleProvider;
_roleManager = roleManager;
New = shapeFactory;
_siteService = siteService;
T = stringLocalizer;
TH = htmlLocalizer;
_authorizationService = authorizationService;
_session = session;
_userManager = userManager;
_userService = userService;
}
public async Task<ActionResult> Index(UserIndexOptions options, PagerParameters pagerParameters)
{
Expand Down Expand Up @@ -148,38 +142,30 @@ public async Task<IActionResult> Create()
return Unauthorized();
}

var roleNames = await GetRoleNamesAsync();
var roles = roleNames.Select(x => new RoleViewModel { Role = x }).ToArray();
var shape = await _userDisplayManager.BuildEditorAsync(new User(), this);

var model = new CreateUserViewModel
{
Roles = roles
};

return View(model);
return View(shape);
}

[HttpPost]
public async Task<IActionResult> Create(CreateUserViewModel model)
[ActionName(nameof(Create))]
public async Task<IActionResult> CreatePost()
{
CleanViewModel(model);

if (ModelState.IsValid)
if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageUsers))
{
var roleNames = model.Roles.Where(x => x.IsSelected).Select(x => x.Role).ToArray();
var user = await _userService.CreateUserAsync(model.UserName, model.Email, roleNames, model.Password, (key, message) => ModelState.AddModelError(key, message));

if (user != null)
{
_notifier.Success(TH["User created successfully"]);
return RedirectToAction(nameof(Index));
}
return Unauthorized();
}

var shape = await _userDisplayManager.UpdateEditorAsync(new User(), this);

_session.Cancel();
if (!ModelState.IsValid)
{
return View(shape);
}

// If we got this far, something failed, redisplay form
return View(model);
_notifier.Success(TH["User created successfully"]);

return RedirectToAction(nameof(Index));
}

public async Task<IActionResult> Edit(string id)
Expand All @@ -190,115 +176,41 @@ public async Task<IActionResult> Edit(string id)
}

var currentUser = await _userManager.FindByIdAsync(id);

if (currentUser == null)
if (!(currentUser is User))
{
return NotFound();
}

var roleNames = await GetRoleNamesAsync();
var userRoleNames = await _userManager.GetRolesAsync(currentUser);
var roles = roleNames.Select(x => new RoleViewModel { Role = x, IsSelected = userRoleNames.Contains(x, StringComparer.OrdinalIgnoreCase) }).ToArray();

var model = new EditUserViewModel
{
Id = id,
Email = await _userManager.GetEmailAsync(currentUser),
UserName = await _userManager.GetUserNameAsync(currentUser),
Roles = roles
};
var shape = await _userDisplayManager.BuildEditorAsync((User) currentUser, this);

return View(model);
return View(shape);
}

[HttpPost]
public async Task<IActionResult> Edit(EditUserViewModel model)
[ActionName(nameof(Edit))]
public async Task<IActionResult> EditPost(string id)
{
if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageUsers))
{
return Unauthorized();
}

CleanViewModel(model);

var currentUser = await _userManager.FindByIdAsync(model.Id.ToString());

var currentUser = await _userManager.FindByIdAsync(id);
if (currentUser == null)
{
return NotFound();
}

if (ModelState.IsValid)
{
var userWithSameName = await _userManager.FindByNameAsync(model.UserName);
if (userWithSameName != null)
{
var userWithSameNameId = await _userManager.GetUserIdAsync(userWithSameName);
if (userWithSameNameId != model.Id)
{
ModelState.AddModelError(string.Empty, T["The user name is already used."]);
}
}

var userWithSameEmail = await _userManager.FindByEmailAsync(model.Email);
if (userWithSameEmail != null)
{
var userWithSameEmailId = await _userManager.GetUserIdAsync(userWithSameEmail);
if (userWithSameEmailId != model.Id)
{
ModelState.AddModelError(string.Empty, T["The email is already used."]);
}
}
}
var shape = await _userDisplayManager.UpdateEditorAsync((User) currentUser, this);

if (ModelState.IsValid)
if (!ModelState.IsValid)
{
var roleNames = model.Roles.Where(x => x.IsSelected).Select(x => x.Role).ToList();
await _userManager.SetUserNameAsync(currentUser, model.UserName);
await _userManager.SetEmailAsync(currentUser, model.Email);

// Remove roles in two steps to prevent an iteration on a modified collection
var rolesToRemove = new List<string>();
foreach (var role in await _userManager.GetRolesAsync(currentUser))
{
if (!roleNames.Contains(role))
{
rolesToRemove.Add(role);
}
}

foreach(var role in rolesToRemove)
{
await _userManager.RemoveFromRoleAsync(currentUser, role);
}

// Add new roles
foreach (var role in roleNames)
{
if (!await _userManager.IsInRoleAsync(currentUser, role))
{
await _userManager.AddToRoleAsync(currentUser, role);
}
}

var result = await _userManager.UpdateAsync(currentUser);

if (result.Succeeded)
{
_notifier.Success(TH["User updated successfully"]);
return RedirectToAction(nameof(Index));
}

_session.Cancel();

foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
return View(shape);
}

// If we got this far, something failed, redisplay form
return View(model);
_notifier.Success(TH["User updated successfully"]);

return RedirectToAction(nameof(Index));
}

[HttpPost]
Expand All @@ -311,7 +223,7 @@ public async Task<IActionResult> Delete(string id)

var currentUser = await _userManager.FindByIdAsync(id);

if (currentUser == null)
if (!(currentUser is User))
{
return NotFound();
}
Expand All @@ -336,23 +248,5 @@ public async Task<IActionResult> Delete(string id)

return RedirectToAction(nameof(Index));
}

public async Task<IEnumerable<string>> GetRoleNamesAsync()
{
var roleNames = await _roleProvider.GetRoleNamesAsync();
return roleNames.Except(new[] { "Anonymous", "Authenticated" }, StringComparer.OrdinalIgnoreCase);
}

public void CleanViewModel(CreateUserViewModel model)
{
model.UserName = model.UserName?.Trim();
model.Email = model.Email?.Trim();
}

public void CleanViewModel(EditUserViewModel model)
{
model.UserName = model.UserName?.Trim();
model.Email = model.Email?.Trim();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Threading.Tasks;
using OrchardCore.DisplayManagement.Handlers;
using OrchardCore.DisplayManagement.Views;
using OrchardCore.Users.Models;

namespace OrchardCore.Users.Drivers
{
public class UserButtonsDisplayDriver : DisplayDriver<User>
{
public override IDisplayResult Edit(User user)
{
return Shape("UserSaveButtons_Edit").Location("Actions");
}

public override Task<IDisplayResult> UpdateAsync(User user, UpdateEditorContext context)
{
return Task.FromResult(Edit(user));
}
}
}

0 comments on commit e3161ea

Please sign in to comment.