Files
mixtape/Finch/Identity/FinchRoleStore(TRole).cs
T
2026-04-07 14:23:29 +02:00

170 lines
4.2 KiB
C#

using Microsoft.AspNetCore.Identity;
using System.Security.Claims;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Finch.Identity;
namespace Finch.Identity;
public class FinchRoleStore<TRole> :
IRoleStore<TRole>,
IRoleClaimStore<TRole>
where TRole : FinchIdentityRole, new()
{
protected IdentityErrorDescriber ErrorDescriber { get; private set; }
protected virtual IFinchIdentityStoreDbProvider Db { get; set; }
public FinchRoleStore(IFinchIdentityStoreDbProvider db, IdentityErrorDescriber describer = null)
{
Db = db;
ErrorDescriber = describer ?? new IdentityErrorDescriber();
}
private IdentityResult Fail(Result<TRole> result)
{
IdentityError[] errors = new IdentityError[result.Errors.Count];
int index = 0;
foreach (ResultError error in result.Errors)
{
string message = error.Message + "(key: " + error.Property + ")";
errors[index++] = new() { Code = "finch/raven/500", Description = message };
}
return IdentityResult.Failed(errors);
}
/// <inheritdoc/>
public async Task<IdentityResult> CreateAsync(TRole role, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
try
{
Result<TRole> result = await Db.Create(role);
if (!result.IsSuccess)
{
return Fail(result);
}
}
catch (Exception ex)
{
return IdentityResult.Failed(new IdentityError { Description = ex.Message });
}
return IdentityResult.Success;
}
/// <inheritdoc/>
public async Task<IdentityResult> UpdateAsync(TRole role, CancellationToken cancellationToken)
{
Result<TRole> result = await Db.Update(role);
if (!result.IsSuccess)
{
return Fail(result);
}
return IdentityResult.Success;
}
/// <inheritdoc/>
public async Task<IdentityResult> DeleteAsync(TRole role, CancellationToken cancellationToken)
{
Result<TRole> result = await Db.Delete(role);
if (!result.IsSuccess)
{
return Fail(result);
}
return IdentityResult.Success;
}
/// <inheritdoc/>
public Task<string> GetRoleIdAsync(TRole role, CancellationToken cancellationToken) => Task.FromResult(role.Id);
/// <inheritdoc/>
public Task<string> GetRoleNameAsync(TRole role, CancellationToken cancellationToken) => Task.FromResult(role.Name);
/// <inheritdoc/>
public Task SetRoleNameAsync(TRole role, string roleName, CancellationToken cancellationToken)
{
role.Name = roleName;
return Task.CompletedTask;
}
/// <inheritdoc/>
public Task<string> GetNormalizedRoleNameAsync(TRole role, CancellationToken cancellationToken)
=> Task.FromResult(role.Name);
/// <inheritdoc/>
public Task SetNormalizedRoleNameAsync(TRole role, string normalizedName, CancellationToken cancellationToken) =>
SetRoleNameAsync(role, normalizedName, cancellationToken);
/// <inheritdoc/>
public async Task<TRole> FindByIdAsync(string roleId, CancellationToken cancellationToken)
{
// TODO index
return await Db.Load<TRole>(roleId);
}
/// <inheritdoc/>
public async Task<TRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
{
// TODO index
return await Db.Find<TRole>(x => x.Name == normalizedRoleName, cancellationToken);
}
/// <inheritdoc/>
public void Dispose()
{
}
/*
* ****************************************************
* CLAIM
* ****************************************************
*/
/// <inheritdoc/>
public Task AddClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default)
{
role.Claims.Add(new(claim));
return Task.CompletedTask;
}
/// <inheritdoc/>
public Task<IList<Claim>> GetClaimsAsync(TRole role, CancellationToken cancellationToken = default) =>
Task.FromResult((IList<Claim>)role.Claims.Select(claim => claim.ToClaim()).ToList());
/// <inheritdoc/>
public Task RemoveClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default)
{
UserClaim userClaim = new(claim);
role.Claims = role.Claims.Except(new List<UserClaim>() { userClaim }, new UserClaimComparer()).ToList();
return Task.CompletedTask;
}
}