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.
Connected.Common/Common/Security/Identity/RoleOps.cs

183 lines
4.7 KiB

2 years ago
using System.Collections.Immutable;
using Connected;
using Connected.Entities;
using Connected.Entities.Storage;
using Connected.Notifications;
using Connected.Notifications.Events;
using Connected.Security.Identity;
using Connected.ServiceModel;
using Connected.Services;
using Connected.Validation;
namespace Common.Security.Identity;
internal sealed class QueryRoles : ServiceFunction<IDto, ImmutableList<IRole>>
{
public QueryRoles(IRoleCache cache)
{
Cache = cache;
}
private IRoleCache Cache { get; }
protected override async Task<ImmutableList<IRole>?> OnInvoke()
{
return await (from dc in Cache
select dc).AsEntities<IRole>();
}
}
internal sealed class SelectRole : ServiceFunction<PrimaryKeyArgs<int>, IRole?>
{
public SelectRole(IRoleCache cache)
{
Cache = cache;
}
private IRoleCache Cache { get; }
protected override async Task<IRole?> OnInvoke()
{
return await (from dc in Cache
where dc.Id == Arguments.Id
select dc).AsEntity();
}
}
internal sealed class SelectRoleByName : ServiceFunction<NameArgs, IRole?>
{
public SelectRoleByName(IRoleCache cache)
{
Cache = cache;
}
private IRoleCache Cache { get; }
protected override async Task<IRole?> OnInvoke()
{
return await (from dc in Cache
where string.Equals(dc.Name, Arguments.Name, StringComparison.OrdinalIgnoreCase)
select dc).AsEntity();
}
}
internal sealed class LookupRoles : ServiceFunction<PrimaryKeyListArgs<int>, ImmutableList<IRole>?>
{
public LookupRoles(IRoleCache cache)
{
Cache = cache;
}
private IRoleCache Cache { get; }
protected override async Task<ImmutableList<IRole>?> OnInvoke()
{
if (Arguments.IdList is null)
return default;
return await (from dc in Cache
where Arguments.IdList.Any(f => f == dc.Id)
select dc).AsEntities<IRole>();
}
}
internal sealed class InsertRole : ServiceFunction<RoleArgs, int>
{
public InsertRole(IRoleService roleService, IRoleCache cache, IStorageProvider storage, IEventService events)
{
RoleService = roleService;
Cache = cache;
Storage = storage;
Events = events;
}
private IStorageProvider Storage { get; }
private IEventService Events { get; }
private IRoleCache Cache { get; }
private IRoleService RoleService { get; }
private IRole? Entity { get; set; }
protected override async Task<int> OnInvoke()
{
if (await RoleService.Select(new NameArgs { Name = Arguments.Name }) is not null)
throw ValidationExceptions.ValueExists(nameof(Arguments.Name), Arguments.Name);
if (Arguments.AsEntity<Role>(State.New) is not Role entity)
throw EntityExceptions.EntityCastException(Arguments.GetType(), typeof(Role));
Entity = await Storage.Open<Role>().Update(entity);
return Entity.Id;
}
protected override async Task OnCommitted()
{
await Cache.Refresh(Entity.Id);
await Events.Enqueue(this, RoleService, nameof(IServiceNotifications<int>.Inserted), Result);
}
protected override async Task OnRolledBack()
{
await Cache.Refresh(Result);
}
}
internal sealed class DeleteRole : ServiceAction<PrimaryKeyArgs<int>>
{
public DeleteRole(IRoleService roleService, IStorageProvider storage, IRoleCache cache, IEventService events)
{
RoleService = roleService;
Storage = storage;
Cache = cache;
Events = events;
}
private IRoleService RoleService { get; }
private IStorageProvider Storage { get; }
private IRoleCache Cache { get; }
private IEventService Events { get; }
protected override async Task OnInvoke()
{
if (await RoleService.Select(Arguments.Id) is IRole existing && existing.Id < 1)
throw new AccessViolationException($"{SR.ErrSysRole} ({existing.Name})");
await Storage.Open<Role>().Update(new Role { Id = Arguments.Id, State = State.Deleted });
}
protected override async Task OnCommitted()
{
await Cache.Remove(Arguments.Id);
await Events.Enqueue(this, RoleService, ServiceEvents.Deleted, Arguments.Id);
}
}
internal sealed class UpdateRole : ServiceAction<RoleUpdateArgs>
{
public UpdateRole(IRoleService roleService, IStorageProvider storage, IRoleCache cache, IEventService events)
{
RoleService = roleService;
Storage = storage;
Cache = cache;
Events = events;
}
private IStorageProvider Storage { get; }
private IRoleCache Cache { get; }
private IEventService Events { get; }
private IRoleService RoleService { get; }
protected override async Task OnInvoke()
{
await Storage.Open<Role>().Update(await Load(), Arguments, async () =>
{
await Cache.Refresh(Arguments.Id);
return await Load();
});
await Cache.Refresh(Arguments.Id);
}
private async Task<Role> Load() => await (from dc in Cache where dc.Id == Arguments.Id select dc).AsEntity();
protected override async Task OnCommitted()
{
await Events.Enqueue(this, RoleService, ServiceEvents.Updated, Arguments.Id);
}
}