Authorization works with roles properly. Added authorization examples to Sample project.

This commit is contained in:
JudahGabriel
2017-09-06 11:49:33 -05:00
parent ea3a6cbdd3
commit 6fc83d4ea3
9 changed files with 87 additions and 19 deletions
+10 -1
View File
@@ -21,7 +21,7 @@ namespace RavenDB.Identity
public virtual bool LockoutEnabled { get; set; }
public virtual DateTimeOffset? LockoutEndDate { get; set; }
public virtual bool TwoFactorAuthEnabled { get; set; }
public virtual List<string> Roles { get; private set; }
public virtual IReadOnlyList<string> Roles { get; private set; }
public virtual List<IdentityUserClaim> Claims { get; private set; }
public virtual List<UserLoginInfo> Logins { get; private set; }
@@ -38,6 +38,15 @@ namespace RavenDB.Identity
this.Id = userId;
this.UserName = userName;
}
/// <summary>
/// Gets the mutable roles list. This shouldn't be modified by user code; roles should be changed via UserManager instead.
/// </summary>
/// <returns></returns>
internal List<string> GetRolesList()
{
return (List<string>)this.Roles;
}
}
public sealed class IdentityUserLogin
+2 -2
View File
@@ -242,7 +242,7 @@ namespace RavenDB.Identity
throw new ArgumentNullException(nameof(role));
}
role.Name = roleName;
return Task.FromResult(0);
return Task.CompletedTask;
}
/// <summary>
@@ -268,7 +268,7 @@ namespace RavenDB.Identity
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return AsyncSession.LoadAsync<TRole>($"IdentityRoles/{normalizedName}");
return AsyncSession.LoadAsync<TRole>($"IdentityRoles/{normalizedName.ToLower()}");
}
/// <summary>
@@ -97,7 +97,7 @@ namespace RavenDB.Identity
services.AddIdentity<TUser, IdentityRole>()
.AddDefaultTokenProviders();
}
services.AddScoped<Microsoft.AspNetCore.Identity.IUserStore<TUser>, UserStore<TUser>>();
services.AddScoped<Microsoft.AspNetCore.Identity.IRoleStore<IdentityRole>, RoleStore<IdentityRole>>();
+46 -13
View File
@@ -250,18 +250,16 @@ namespace RavenDB.Identity
return Task.CompletedTask;
}
public Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken)
public async Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken)
{
ThrowIfNullDisposedCancelled(user, cancellationToken);
var indexOfClaim = user.Claims.FindIndex(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value);
if (indexOfClaim != -1)
{
user.Claims.RemoveAt(indexOfClaim);
this.AddClaimsAsync(user, new[] { newClaim }, cancellationToken);
await this.AddClaimsAsync(user, new[] { newClaim }, cancellationToken);
}
return Task.CompletedTask;
}
public Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken)
@@ -289,31 +287,65 @@ namespace RavenDB.Identity
#region IUserRoleStore implementation
public Task AddToRoleAsync(TUser user, string roleName, CancellationToken cancellationToken)
/// <summary>
/// Adds the user to the specified role.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="roleName">The name of the role.</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task AddToRoleAsync(TUser user, string roleName, CancellationToken cancellationToken)
{
ThrowIfNullDisposedCancelled(user, cancellationToken);
if (!user.Roles.Contains(roleName, StringComparer.OrdinalIgnoreCase))
var roleNameLowered = roleName.ToLower();
if (!user.Roles.Contains(roleNameLowered, StringComparer.OrdinalIgnoreCase))
{
user.Roles.Add(roleName);
user.GetRolesList().Add(roleNameLowered);
}
return Task.CompletedTask;
// See if we have an IdentityRole with that.
var roleId = "IdentityRoles/" + roleNameLowered;
var existingRoleOrNull = await this.DbSession.LoadAsync<IdentityRole>(roleId, cancellationToken);
if (existingRoleOrNull == null)
{
ThrowIfDisposedOrCancelled(cancellationToken);
existingRoleOrNull = new IdentityRole(roleNameLowered);
await this.DbSession.StoreAsync(existingRoleOrNull, roleId, cancellationToken);
}
if (!existingRoleOrNull.Users.Contains(user.Id, StringComparer.OrdinalIgnoreCase))
{
existingRoleOrNull.Users.Add(user.Id);
}
}
public Task RemoveFromRoleAsync(TUser user, string roleName, CancellationToken cancellationToken)
/// <summary>
/// Removes the user from the specified role.
/// </summary>
/// <param name="user"></param>
/// <param name="roleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task RemoveFromRoleAsync(TUser user, string roleName, CancellationToken cancellationToken)
{
ThrowIfNullDisposedCancelled(user, cancellationToken);
user.Roles.RemoveAll(r => string.Equals(r, roleName, StringComparison.OrdinalIgnoreCase));
return Task.CompletedTask;
user.GetRolesList().RemoveAll(r => string.Equals(r, roleName, StringComparison.OrdinalIgnoreCase));
var roleId = "IdentityRoles/" + roleName.ToLower();
var roleOrNull = await DbSession.LoadAsync<IdentityRole>(roleId, cancellationToken);
if (roleOrNull != null)
{
roleOrNull.Users.Remove(user.Id);
}
}
public Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken)
{
ThrowIfNullDisposedCancelled(user, cancellationToken);
return Task.FromResult<IList<string>>(user.Roles);
return Task.FromResult<IList<string>>(new List<string>(user.Roles));
}
public Task<bool> IsInRoleAsync(TUser user, string roleName, CancellationToken cancellationToken)
@@ -336,6 +368,7 @@ namespace RavenDB.Identity
return DbSession.Query<TUser>()
.Where(u => u.Roles.Contains(roleName))
.Take(1024)
.ToListAsync();
}
+20 -1
View File
@@ -6,14 +6,19 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Sample.Models;
using Raven.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
namespace Sample.Controllers
{
public class HomeController : RavenController
{
public HomeController(IAsyncDocumentSession dbSession)
private UserManager<AppUser> userManager;
public HomeController(IAsyncDocumentSession dbSession, UserManager<AppUser> userManager)
: base(dbSession)
{
this.userManager = userManager;
}
public async Task<IActionResult> Index()
@@ -27,6 +32,20 @@ namespace Sample.Controllers
return View();
}
// Require that the user be logged in.
[Authorize]
public IActionResult Auth()
{
return View();
}
// Require that the user be in the Admin role.
[Authorize(Roles = "Admin")]
public IActionResult AuthAdmin()
{
return View();
}
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
+4 -1
View File
@@ -9,7 +9,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.0" PrivateAssets="All" />
<PackageReference Include="RavenDB.Identity" Version="2.0.2" />
</ItemGroup>
<ItemGroup>
@@ -18,4 +17,8 @@
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RavenDB.Identity\RavenDB.Identity.csproj" />
</ItemGroup>
</Project>
+2
View File
@@ -32,6 +32,8 @@ namespace Sample
.AddRavenDbAsyncSession() // Create a RavenDB IAsyncDocumentSession for each request.
.AddRavenDbIdentity<AppUser>(); // Use Raven for users and roles.
// You can change the login path if need be.
// services.ConfigureApplicationCookie(options => options.LoginPath = "/my/login/path");
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
+1
View File
@@ -0,0 +1 @@
<h1>Hi, this is a page you can access only if you're signed in.</h1>
+1
View File
@@ -0,0 +1 @@
<h1>Hi, this is a page you can access only if you're an admin.</h1>