Skip to content

Commit e2fc37b

Browse files
committed
Add UI for creating role and access role.
1 parent 63453c2 commit e2fc37b

23 files changed

+1411
-2
lines changed

DynamicRoleBasedAuthorization.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleMvc2WebApp", "samples
2121
EndProject
2222
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{DF22D7D8-4CE9-4A0E-9D9B-FB5D6D637089}"
2323
EndProject
24-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamicRoleBasedAuthorization.Tests", "test\DynamicRoleBasedAuthorization.Tests\DynamicRoleBasedAuthorization.Tests.csproj", "{0FC61895-DE38-4526-96EE-C6CB6AA92A3B}"
24+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynamicRoleBasedAuthorization.Tests", "test\DynamicRoleBasedAuthorization.Tests\DynamicRoleBasedAuthorization.Tests.csproj", "{0FC61895-DE38-4526-96EE-C6CB6AA92A3B}"
25+
EndProject
26+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynamicAuthorization.Mvc.Ui", "src\DynamicAuthorization.Mvc.Ui\DynamicAuthorization.Mvc.Ui.csproj", "{4D5C1490-63F8-434A-A730-380AA6441CE9}"
27+
EndProject
28+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleMvcWebAppWithUi", "samples\netcore3.x\SampleMvcWebAppWithUi\SampleMvcWebAppWithUi.csproj", "{043FB17F-5C3F-47B8-B4C0-B7AB1AC12A29}"
2529
EndProject
2630
Global
2731
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -49,6 +53,14 @@ Global
4953
{0FC61895-DE38-4526-96EE-C6CB6AA92A3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
5054
{0FC61895-DE38-4526-96EE-C6CB6AA92A3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
5155
{0FC61895-DE38-4526-96EE-C6CB6AA92A3B}.Release|Any CPU.Build.0 = Release|Any CPU
56+
{4D5C1490-63F8-434A-A730-380AA6441CE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57+
{4D5C1490-63F8-434A-A730-380AA6441CE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
58+
{4D5C1490-63F8-434A-A730-380AA6441CE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
59+
{4D5C1490-63F8-434A-A730-380AA6441CE9}.Release|Any CPU.Build.0 = Release|Any CPU
60+
{043FB17F-5C3F-47B8-B4C0-B7AB1AC12A29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61+
{043FB17F-5C3F-47B8-B4C0-B7AB1AC12A29}.Debug|Any CPU.Build.0 = Debug|Any CPU
62+
{043FB17F-5C3F-47B8-B4C0-B7AB1AC12A29}.Release|Any CPU.ActiveCfg = Release|Any CPU
63+
{043FB17F-5C3F-47B8-B4C0-B7AB1AC12A29}.Release|Any CPU.Build.0 = Release|Any CPU
5264
EndGlobalSection
5365
GlobalSection(SolutionProperties) = preSolution
5466
HideSolutionNode = FALSE
@@ -61,6 +73,8 @@ Global
6173
{11B88EB7-66BE-402A-A4E0-144220EBD8B9} = {BAAF9837-1DB5-4032-AB2A-2901E6EE6EF8}
6274
{A3124728-6766-48A3-BA1A-5CB119924395} = {11B88EB7-66BE-402A-A4E0-144220EBD8B9}
6375
{0FC61895-DE38-4526-96EE-C6CB6AA92A3B} = {DF22D7D8-4CE9-4A0E-9D9B-FB5D6D637089}
76+
{4D5C1490-63F8-434A-A730-380AA6441CE9} = {A7EEBB7E-C64D-4475-93D0-872E080A4E03}
77+
{043FB17F-5C3F-47B8-B4C0-B7AB1AC12A29} = {5FEB9007-1EFA-4814-BC15-DB0370B84E22}
6478
EndGlobalSection
6579
GlobalSection(ExtensibilityGlobals) = postSolution
6680
SolutionGuid = {18C80710-C9E9-488B-9100-1E4BF8B18038}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
using DynamicAuthorization.Mvc.Core;
2+
using DynamicAuthorization.Mvc.Core.Models;
3+
using DynamicAuthorization.Mvc.Ui.Filters;
4+
using DynamicAuthorization.Mvc.Ui.ViewModels;
5+
using Microsoft.AspNetCore.Authorization;
6+
using Microsoft.AspNetCore.Identity;
7+
using Microsoft.AspNetCore.Mvc;
8+
using System;
9+
using System.ComponentModel;
10+
using System.Linq;
11+
using System.Threading.Tasks;
12+
using Microsoft.EntityFrameworkCore;
13+
14+
namespace DynamicAuthorization.Mvc.Ui.Controllers
15+
{
16+
[Authorize, AddResourcesToViewFilter]
17+
[DisplayName("Role Management")]
18+
public class RoleController : Controller
19+
{
20+
private readonly dynamic _roleManager;
21+
private readonly IMvcControllerDiscovery _mvcControllerDiscovery;
22+
private readonly IRoleAccessStore _roleAccessStore;
23+
24+
public RoleController(
25+
IMvcControllerDiscovery mvcControllerDiscovery,
26+
IRoleAccessStore roleAccessStore,
27+
IServiceProvider serviceProvider
28+
)
29+
{
30+
_mvcControllerDiscovery = mvcControllerDiscovery;
31+
_roleAccessStore = roleAccessStore;
32+
_roleManager = serviceProvider.GetService(typeof(RoleManager<>).MakeGenericType(DynamicAuthorizationOptions.RoleType));
33+
}
34+
35+
// GET: Role
36+
[DisplayName("Role List")]
37+
public ActionResult Index()
38+
{
39+
var roles = _roleManager.Roles;
40+
41+
return View(roles);
42+
}
43+
44+
[DisplayName("Create Role")]
45+
// GET: Role/Create
46+
public ActionResult Create()
47+
{
48+
var controllers = _mvcControllerDiscovery.GetControllers();
49+
ViewData["Controllers"] = controllers;
50+
51+
return View();
52+
}
53+
54+
// POST: Role/Create
55+
[HttpPost, ValidateAntiForgeryToken]
56+
public async Task<ActionResult> Create(RoleViewModel viewModel)
57+
{
58+
if (!ModelState.IsValid)
59+
{
60+
ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
61+
return View(viewModel);
62+
}
63+
64+
var role = new IdentityRole { Name = viewModel.Name };
65+
var result = await _roleManager.CreateAsync(role);
66+
67+
if (!result.Succeeded)
68+
{
69+
foreach (var error in result.Errors)
70+
ModelState.AddModelError("", error.Description);
71+
72+
ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
73+
return View(viewModel);
74+
}
75+
76+
if (viewModel.SelectedControllers != null && viewModel.SelectedControllers.Any())
77+
{
78+
foreach (var controller in viewModel.SelectedControllers)
79+
foreach (var action in controller.Actions)
80+
action.ControllerId = controller.Id;
81+
82+
var roleAccess = new RoleAccess
83+
{
84+
Controllers = viewModel.SelectedControllers.ToList(),
85+
RoleId = role.Id
86+
};
87+
await _roleAccessStore.AddRoleAccessAsync(roleAccess);
88+
}
89+
90+
return RedirectToAction(nameof(Index));
91+
}
92+
93+
// GET: Role/Edit/5
94+
[DisplayName("Edit Role")]
95+
public async Task<ActionResult> Edit(string id)
96+
{
97+
ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
98+
var role = await _roleManager.FindByIdAsync(id);
99+
if (role == null)
100+
return NotFound();
101+
102+
var accessList = await _roleAccessStore.GetRoleAccessAsync(role.Id);
103+
var viewModel = new RoleViewModel
104+
{
105+
Name = role.Name,
106+
SelectedControllers = accessList?.Controllers
107+
};
108+
109+
return View(viewModel);
110+
}
111+
112+
// POST: Role/Edit/5
113+
[HttpPost, ValidateAntiForgeryToken]
114+
public async Task<ActionResult> Edit(string id, RoleViewModel viewModel)
115+
{
116+
if (!ModelState.IsValid)
117+
{
118+
ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
119+
return View(viewModel);
120+
}
121+
122+
// Check role exit
123+
var role = await _roleManager.FindByIdAsync(id);
124+
if (role == null)
125+
{
126+
ModelState.AddModelError("", "Role not found");
127+
ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
128+
return View();
129+
}
130+
131+
// Update role if role's name is changed
132+
if (role.Name != viewModel.Name)
133+
{
134+
role.Name = viewModel.Name;
135+
var result = await _roleManager.UpdateAsync(role);
136+
if (!result.Succeeded)
137+
{
138+
foreach (var error in result.Errors)
139+
ModelState.AddModelError("", error.Description);
140+
141+
ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
142+
return View(viewModel);
143+
}
144+
}
145+
146+
// Update role access list
147+
if (viewModel.SelectedControllers != null && viewModel.SelectedControllers.Any())
148+
{
149+
foreach (var controller in viewModel.SelectedControllers)
150+
foreach (var action in controller.Actions)
151+
action.ControllerId = controller.Id;
152+
}
153+
154+
var roleAccess = new RoleAccess
155+
{
156+
Controllers = viewModel.SelectedControllers?.ToList(),
157+
RoleId = role.Id
158+
};
159+
await _roleAccessStore.EditRoleAccessAsync(roleAccess);
160+
161+
return RedirectToAction(nameof(Index));
162+
}
163+
164+
// POST: Role/Delete/5
165+
[HttpDelete("role/{id}")]
166+
public async Task<ActionResult> Delete(string id)
167+
{
168+
var role = await _roleManager.FindByIdAsync(id);
169+
if (role == null)
170+
{
171+
ModelState.AddModelError("Error", "Role not found");
172+
return BadRequest(ModelState);
173+
}
174+
175+
var result = await _roleManager.DeleteAsync(role);
176+
if (!result.Succeeded)
177+
{
178+
foreach (var error in result.Errors)
179+
ModelState.AddModelError("Error", error.Description);
180+
181+
return BadRequest(ModelState);
182+
}
183+
184+
await _roleAccessStore.RemoveRoleAccessAsync(role.Id);
185+
186+
return Ok(new { });
187+
}
188+
}
189+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using DynamicAuthorization.Mvc.Core.Models;
2+
using DynamicAuthorization.Mvc.Ui.Filters;
3+
using DynamicAuthorization.Mvc.Ui.Services;
4+
using DynamicAuthorization.Mvc.Ui.ViewModels;
5+
using Microsoft.AspNetCore.Authorization;
6+
using Microsoft.AspNetCore.Identity;
7+
using Microsoft.AspNetCore.Mvc;
8+
using Microsoft.EntityFrameworkCore.Internal;
9+
using System;
10+
using System.Collections.Generic;
11+
using System.ComponentModel;
12+
using System.Threading.Tasks;
13+
14+
namespace DynamicAuthorization.Mvc.Ui.Controllers
15+
{
16+
[Authorize, AddResourcesToViewFilter]
17+
[DisplayName("User Role Management")]
18+
public class UserRoleController : Controller
19+
{
20+
private readonly dynamic _roleManager;
21+
private readonly dynamic _userManager;
22+
23+
public UserRoleController(IServiceProvider serviceProvider)
24+
{
25+
_roleManager = serviceProvider.GetService(typeof(RoleManager<>).MakeGenericType(DynamicAuthorizationOptions.RoleType));
26+
_userManager = serviceProvider.GetService(typeof(UserManager<>).MakeGenericType(DynamicAuthorizationOptions.UserType));
27+
}
28+
29+
// GET: Access
30+
[DisplayName("User List")]
31+
public async Task<ActionResult> Index([FromServices] IIdentityService identityService)
32+
{
33+
var usersRoles = await identityService.GetUsersRolesAsync();
34+
35+
return View(usersRoles);
36+
}
37+
38+
// GET: Access/Edit
39+
[DisplayName("Edit User Roles")]
40+
public async Task<ActionResult> Edit(string id)
41+
{
42+
var user = await _userManager.FindByIdAsync(id);
43+
if (user == null)
44+
return NotFound();
45+
46+
var userRoles = await _userManager.GetRolesAsync(user);
47+
var userViewModel = new UserRoleViewModel
48+
{
49+
UserId = user.Id,
50+
UserName = user.UserName,
51+
Roles = userRoles
52+
};
53+
54+
var roles = _roleManager.Roles;
55+
ViewData["Roles"] = roles;
56+
57+
return View(userViewModel);
58+
}
59+
60+
// POST: Access/Edit
61+
[HttpPost]
62+
[ValidateAntiForgeryToken]
63+
public async Task<ActionResult> Edit(UserRoleViewModel viewModel)
64+
{
65+
if (!ModelState.IsValid)
66+
{
67+
ViewData["Roles"] = _roleManager.Roles;
68+
return View(viewModel);
69+
}
70+
71+
var user = await _userManager.FindByIdAsync(viewModel.UserId);
72+
var x = user as IdentityUser;
73+
if (user == null)
74+
{
75+
ModelState.AddModelError("", "User not found");
76+
ViewData["Roles"] = _roleManager.Roles;
77+
return View();
78+
}
79+
80+
List<string> userRoles = await _userManager.GetRolesAsync(user);
81+
if (userRoles.Any())
82+
await _userManager.RemoveFromRolesAsync(user, userRoles);
83+
84+
if (viewModel.Roles != null)
85+
await _userManager.AddToRolesAsync(user, viewModel.Roles);
86+
87+
return RedirectToAction("Index");
88+
}
89+
}
90+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Razor">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
6+
<RazorCompileOnBuild>true</RazorCompileOnBuild>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<FrameworkReference Include="Microsoft.AspNetCore.App" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<EmbeddedResource Include="wwwroot\**\*.css" />
15+
<EmbeddedResource Include="wwwroot\**\*.js" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\DynamicAuthorization.Mvc.Core\DynamicAuthorization.Mvc.Core.csproj" />
20+
</ItemGroup>
21+
</Project>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using DynamicAuthorization.Mvc.Core;
2+
using DynamicAuthorization.Mvc.Core.Models;
3+
using DynamicAuthorization.Mvc.Ui.Filters;
4+
using DynamicAuthorization.Mvc.Ui.Services;
5+
using Microsoft.AspNetCore.Mvc.ApplicationParts;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using System;
8+
using System.Linq;
9+
10+
namespace DynamicAuthorization.Mvc.Ui
11+
{
12+
public static class ServiceCollectionExtensions
13+
{
14+
public static IDynamicAuthorizationBuilder AddUi(this IDynamicAuthorizationBuilder builder, IMvcBuilder mvcBuilder)
15+
{
16+
if (builder == null)
17+
throw new ArgumentNullException(nameof(builder));
18+
19+
if (mvcBuilder == null)
20+
throw new ArgumentNullException(nameof(mvcBuilder));
21+
22+
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.StartsWith("DynamicAuthorization.Mvc.Ui")).ToList();
23+
foreach (var assembly in assemblies)
24+
{
25+
if (assembly.FullName.Contains("Views"))
26+
mvcBuilder.PartManager.ApplicationParts.Add(new CompiledRazorAssemblyPart(assembly));
27+
else
28+
{
29+
mvcBuilder.PartManager.ApplicationParts.Add(new AssemblyPart(assembly));
30+
var manifestResourceNames = assembly.GetManifestResourceNames();
31+
}
32+
}
33+
34+
builder.Services.AddScoped<AddResourcesToViewFilter>();
35+
builder.Services.AddScoped(
36+
typeof(IIdentityService),
37+
typeof(IdentityService<,,,>).MakeGenericType(
38+
DynamicAuthorizationOptions.DbContextType,
39+
DynamicAuthorizationOptions.UserType,
40+
DynamicAuthorizationOptions.RoleType,
41+
DynamicAuthorizationOptions.KeyType
42+
));
43+
44+
return builder;
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)