mirror of https://github.com/abpframework/abp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
331 lines
15 KiB
331 lines
15 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Security.Claims;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using JetBrains.Annotations;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Volo.Abp.Uow;
|
|
using Volo.DependencyInjection;
|
|
|
|
namespace Volo.Abp.Identity
|
|
{
|
|
/// <summary>
|
|
/// Creates a new instance of a persistence store for roles.
|
|
/// </summary>
|
|
public class RoleStore :
|
|
IRoleStore<IdentityRole>,
|
|
IRoleClaimStore<IdentityRole>,
|
|
ITransientDependency
|
|
{
|
|
private readonly IIdentityRoleRepository _roleRepository;
|
|
private readonly IUnitOfWorkManager _unitOfWorkManager;
|
|
|
|
/// <summary>
|
|
/// Constructs a new instance of <see cref="RoleStore"/>.
|
|
/// </summary>
|
|
public RoleStore(
|
|
IIdentityRoleRepository roleRepository,
|
|
IUnitOfWorkManager unitOfWorkManager,
|
|
IdentityErrorDescriber describer = null)
|
|
{
|
|
_roleRepository = roleRepository;
|
|
_unitOfWorkManager = unitOfWorkManager;
|
|
|
|
ErrorDescriber = describer ?? new IdentityErrorDescriber();
|
|
}
|
|
|
|
private bool _disposed; //TODO: Remove!
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="IdentityErrorDescriber"/> for any error that occurred with the current operation.
|
|
/// </summary>
|
|
public IdentityErrorDescriber ErrorDescriber { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a flag indicating if changes should be persisted after CreateAsync, UpdateAsync and DeleteAsync are called.
|
|
/// </summary>
|
|
/// <value>
|
|
/// True if changes should be automatically persisted, otherwise false.
|
|
/// </value>
|
|
public bool AutoSaveChanges { get; set; } = true;
|
|
|
|
/// <summary>Saves the current store.</summary>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
|
protected Task SaveChanges(CancellationToken cancellationToken)
|
|
{
|
|
if (!AutoSaveChanges || _unitOfWorkManager.Current == null)
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
return _unitOfWorkManager.Current.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new role in a store as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role to create in the store.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
|
|
public virtual async Task<IdentityResult> CreateAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
await _roleRepository.InsertAsync(role, cancellationToken: cancellationToken);
|
|
await SaveChanges(cancellationToken);
|
|
|
|
return IdentityResult.Success;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates a role in a store as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role to update in the store.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
|
|
public virtual async Task<IdentityResult> UpdateAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
await _roleRepository.UpdateAsync(role, cancellationToken);
|
|
|
|
try
|
|
{
|
|
await SaveChanges(cancellationToken);
|
|
}
|
|
catch (AbpDbConcurrencyException ex)
|
|
{
|
|
//TODO: Log...?
|
|
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
|
|
}
|
|
|
|
return IdentityResult.Success;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes a role from the store as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role to delete from the store.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
|
|
public virtual async Task<IdentityResult> DeleteAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
try
|
|
{
|
|
await _roleRepository.DeleteAsync(role, cancellationToken);
|
|
await SaveChanges(cancellationToken);
|
|
}
|
|
catch (AbpDbConcurrencyException ex)
|
|
{
|
|
//TODO: Log...
|
|
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
|
|
}
|
|
|
|
return IdentityResult.Success;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the ID for a role from the store as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role whose ID should be returned.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that contains the ID of the role.</returns>
|
|
public Task<string> GetRoleIdAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
return Task.FromResult(role.Id.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the name of a role from the store as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role whose name should be returned.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that contains the name of the role.</returns>
|
|
public Task<string> GetRoleNameAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
return Task.FromResult(role.Name);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the name of a role in the store as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role whose name should be set.</param>
|
|
/// <param name="roleName">The name of the role.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
|
public Task SetRoleNameAsync([NotNull] IdentityRole role, string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
role.Name = roleName;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds the role who has the specified ID as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="id">The role ID to look for.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
|
|
public virtual Task<IdentityRole> FindByIdAsync(string id, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
return _roleRepository.FindAsync(Guid.Parse(id), cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds the role who has the specified normalized name as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="normalizedName">The normalized role name to look for.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
|
|
public virtual Task<IdentityRole> FindByNameAsync([NotNull] string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(normalizedName, nameof(normalizedName));
|
|
|
|
return _roleRepository.FindByNormalizedNameAsync(normalizedName, cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a role's normalized name as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role whose normalized name should be retrieved.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that contains the name of the role.</returns>
|
|
public virtual Task<string> GetNormalizedRoleNameAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
return Task.FromResult(role.NormalizedName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set a role's normalized name as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role whose normalized name should be set.</param>
|
|
/// <param name="normalizedName">The normalized name to set</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
|
public virtual Task SetNormalizedRoleNameAsync([NotNull] IdentityRole role, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
role.NormalizedName = normalizedName;
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Throws if this class has been disposed.
|
|
/// </summary>
|
|
protected void ThrowIfDisposed()
|
|
{
|
|
if (_disposed)
|
|
{
|
|
throw new ObjectDisposedException(GetType().Name);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose the stores
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
_disposed = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the claims associated with the specified <paramref name="role"/> as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="role">The role whose claims should be retrieved.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>A <see cref="Task{TResult}"/> that contains the claims granted to a role.</returns>
|
|
public Task<IList<Claim>> GetClaimsAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
|
|
return Task.FromResult<IList<Claim>>(role.Claims.Select(c => c.ToClaim()).ToList());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the <paramref name="claim"/> given to the specified <paramref name="role"/>.
|
|
/// </summary>
|
|
/// <param name="role">The role to add the claim to.</param>
|
|
/// <param name="claim">The claim to add to the role.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
|
public Task AddClaimAsync([NotNull] IdentityRole role, [NotNull] Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
Check.NotNull(claim, nameof(claim));
|
|
|
|
role.AddClaim(claim);
|
|
|
|
return Task.FromResult(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the <paramref name="claim"/> given from the specified <paramref name="role"/>.
|
|
/// </summary>
|
|
/// <param name="role">The role to remove the claim from.</param>
|
|
/// <param name="claim">The claim to remove from the role.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
|
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
|
public Task RemoveClaimAsync([NotNull] IdentityRole role, [NotNull] Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
ThrowIfDisposed();
|
|
|
|
Check.NotNull(role, nameof(role));
|
|
Check.NotNull(claim, nameof(claim));
|
|
|
|
role.RemoveClaim(claim);
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
}
|