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> { public QueryRoles(IRoleCache cache) { Cache = cache; } private IRoleCache Cache { get; } protected override async Task?> OnInvoke() { return await (from dc in Cache select dc).AsEntities(); } } internal sealed class SelectRole : ServiceFunction, IRole?> { public SelectRole(IRoleCache cache) { Cache = cache; } private IRoleCache Cache { get; } protected override async Task OnInvoke() { return await (from dc in Cache where dc.Id == Arguments.Id select dc).AsEntity(); } } internal sealed class SelectRoleByName : ServiceFunction { public SelectRoleByName(IRoleCache cache) { Cache = cache; } private IRoleCache Cache { get; } protected override async Task OnInvoke() { return await (from dc in Cache where string.Equals(dc.Name, Arguments.Name, StringComparison.OrdinalIgnoreCase) select dc).AsEntity(); } } internal sealed class LookupRoles : ServiceFunction, ImmutableList?> { public LookupRoles(IRoleCache cache) { Cache = cache; } private IRoleCache Cache { get; } protected override async Task?> 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(); } } internal sealed class InsertRole : ServiceFunction { 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 OnInvoke() { if (await RoleService.Select(new NameArgs { Name = Arguments.Name }) is not null) throw ValidationExceptions.ValueExists(nameof(Arguments.Name), Arguments.Name); if (Arguments.AsEntity(State.New) is not Role entity) throw EntityExceptions.EntityCastException(Arguments.GetType(), typeof(Role)); Entity = await Storage.Open().Update(entity); return Entity.Id; } protected override async Task OnCommitted() { await Cache.Refresh(Entity.Id); await Events.Enqueue(this, RoleService, nameof(IServiceNotifications.Inserted), Result); } protected override async Task OnRolledBack() { await Cache.Refresh(Result); } } internal sealed class DeleteRole : ServiceAction> { 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().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 { 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().Update(await Load(), Arguments, async () => { await Cache.Refresh(Arguments.Id); return await Load(); }); await Cache.Refresh(Arguments.Id); } private async Task 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); } }