public static _ApiEntityType ToEntity <TEntity>(this _EntityType from) where TEntity : _ApiEntityType => from is null ? null : new _ApiEntityType { Description = from.Description, Id = from.Id, Title = from.Title, CreatedAt = from.CreatedAt, CreatedBy = from.CreatedBy.ToApiActor(), IsArchived = from.IsArchived, GeoJson = from.GeoJson, ProjectId = from.ProjectId };
private async Task <_TEntity> BuildUpdatedEntity (_TUpdateCommand command, _TEntity oldEntity) { var newEntity = new _TEntity { CreatedAt = oldEntity.CreatedAt, CreatedBy = oldEntity.CreatedBy, Description = command.Description, Id = oldEntity.Id, IsArchived = command.IsArchived, Title = command.Title, GeoJson = command.GeoJson, ProjectId = oldEntity.ProjectId }; return(await Task.FromResult(newEntity).ConfigureAwait(false)); }
private async Task <ValidationResult> CheckPermissionAsync (_TEntity oldEntity, _TEntity newEntity, Actor currentActor, ActorRole currentProjectRole) { var checkModel = new CheckUpdatePermissionModel <_TEntity> { Actor = currentActor, EntityBeforeUpdate = oldEntity, EntityAfterUpdate = newEntity, NewProjectRole = currentProjectRole, OldProjectRole = currentProjectRole }; var validator = new UpdatePermissionValidator <_TEntity>(); var validatorResult = await validator.ValidateAsync(checkModel) .ConfigureAwait(false); return(validatorResult); }
public static Dictionary <string, object> ToDictionary (this _TEntity from) => from is null ? null : new Dictionary <string, object> { { nameof(from.Id), from.Id }, { nameof(from.Description), from.Description }, { nameof(from.IsArchived), from.IsArchived }, { nameof(from.Title), from.Title }, { nameof(from.ProjectId), from.ProjectId }, { nameof(from.GeoJson), from.GeoJson }, { nameof(from.CreatedAt), from.CreatedAt }, { nameof(from.CreatedBy), String.Join(',', from.CreatedBy .ToDictionary() .Select(x => $"{x.Key}={x.Value}")) } };
private async Task <CreateResult> CheckPermission (_TEntity entity, Actor currentActor, ActorRole currentProjectRole) { var checkModel = new CheckCreatePermissionModel <_TEntity> { Entity = entity, Actor = currentActor, ProjectActorRole = currentProjectRole }; var validator = new CreatePermissionValidator <_TEntity>(); var validatorResult = await validator.ValidateAsync(checkModel) .ConfigureAwait(false); if (!validatorResult.IsValid) { return(ErrorResult(validatorResult.Errors .Select(x => x.ErrorMessage))); } return(new CreateResult { Success = true }); }
public async Task <UpdateResult> Handle(_TUpdateCommand command, CancellationToken cancellationToken) { try { Logger.LogInformation(AppLogEvent.HandleRequest, "Handle Geo Update Command {Command}", command.ToDictionary()); if (command is null || string.IsNullOrWhiteSpace(command.Id)) { Logger.LogWarning(AppLogEvent.HandleArgumentError, "Geo Update Command is empty"); return(ErrorResult("Geo Update Command is empty")); } // Validate Update Command var validator = new GeoUpdateCommandValidator(); var validationResult = await validator .ValidateAsync(command) .ConfigureAwait(false); if (!validationResult.IsValid) { var validationErrors = validationResult.Errors .Select(x => x.ErrorMessage) .ToList(); Logger.LogWarning(AppLogEvent.HandleArgumentError, "Geo Update Command validation error. " + "Command={Command}. Error={Error}.", command.ToDictionary(), validationErrors); return(ErrorResult(validationErrors)); } // Get entity before update var oldEntityResponse = await Mediator .Send(new DbGetEntityByIdRequest <_TEntity>(command.Id)) .ConfigureAwait(false); if (!oldEntityResponse.Success) { Logger.LogWarning(AppLogEvent.HandleErrorResponse, "Get entity for update error. Id={Id}. Error={Error}", command.Id, oldEntityResponse.Errors); return(ErrorResult(oldEntityResponse.Errors)); } var oldEntity = oldEntityResponse.Entity; // Get current actor var currentActorResponse = await Mediator .Send(new DbGetActorByNameRequest (command.CurrentPrincipal?.Identity?.Name)) .ConfigureAwait(false); var currentActor = currentActorResponse.Success ? currentActorResponse.Entity : null; // Build updated entity _TEntity newEntity = await BuildUpdatedEntity (command, oldEntity) .ConfigureAwait(false); // Validate updated entity before update var validatorBeforeSave = new BeforeSaveValidator <_TEntity>(); var validationBeforeSaveResult = await validatorBeforeSave .ValidateAsync(newEntity) .ConfigureAwait(false); if (!validationBeforeSaveResult.IsValid) { Logger.LogWarning(AppLogEvent.RequestValidationError, "Update Geo validation error. Entity={Entity}. " + "Error={Error}.", newEntity.ToDictionary(), validationBeforeSaveResult.Errors); return(ErrorResult(validationBeforeSaveResult.Errors .Select(x => x.ErrorMessage))); } // Get project role of current actor var projectResponse = await Mediator .Send(new DbGetEntityByIdRequest <Project> (oldEntity.ProjectId)) .ConfigureAwait(false); ActorRole currentProjectRole = null; if (projectResponse.Success) { projectResponse.Entity.ProjectActorRoles .TryGetValue(currentActor.Id, out currentProjectRole); } // Check permission to update var permissionValidateResult = await CheckPermissionAsync (oldEntity, newEntity, currentActor, currentProjectRole) .ConfigureAwait(false); if (!permissionValidateResult.IsValid) { Logger.LogWarning(AppLogEvent.SecurityNotPassed, "Current actor has no rights to update entity. " + "Actor={Actor}. " + "CurrentActorProjectRole={CurrentActorProjectRole}. " + "Entity before update={OldEntity}. " + "Entity after update={NewEntity}. Error={Error}.", currentActor.ToDictionary(), currentProjectRole, oldEntity.ToDictionary(), newEntity.ToDictionary(), permissionValidateResult.Errors .Select(x => x.ErrorMessage)); return(ErrorResult(permissionValidateResult.Errors .Select(x => x.ErrorMessage))); } // Save updated entity var updateResult = await Mediator .Send(new DbUpdateCommand <_TEntity>(newEntity)) .ConfigureAwait(false); return(updateResult); } catch (Exception e) { Logger.LogError(AppLogEvent.HandleErrorResponse, e, "Geo update exception"); return(ErrorResult("Geo update exception")); } }
public async Task <CreateResult> Handle(_TCreateCommand command, CancellationToken cancellationToken) { Logger.LogInformation(AppLogEvent.HandleRequest, "Handle Geo Create Command. Command={Command}", command.ToDictionary()); if (command is null) { Logger.LogWarning(AppLogEvent.HandleArgumentError, "Handle Geo Create Command got empty command"); return(ErrorResult("Empty Geo Create Command")); } try { var validator = new CreateCommandValidator <_TCreateCommand>(); var validationResult = await validator.ValidateAsync(command) .ConfigureAwait(false); if (!validationResult.IsValid) { Logger.LogWarning(AppLogEvent.RequestValidationError, "Validation command error. Command={Command}. " + "Error={Error}.", command.ToDictionary(), validationResult.Errors); return(ErrorResult(validationResult.Errors .Select(x => x.ErrorMessage))); } // Get Actor for current user by user name Actor createdBy = null; var currentUserName = command.CurrentPrincipal? .Identity? .Name; var creatorResponse = await Mediator .Send(new DbGetActorByNameRequest(currentUserName)) .ConfigureAwait(false); if (creatorResponse.Success) { createdBy = creatorResponse.Entity; } var entity = new _TEntity() { CreatedAt = DateTime.UtcNow, CreatedBy = createdBy, Description = command.Description, IsArchived = command.IsArchived, Title = command.Title, GeoJson = command.GeoJson, ProjectId = command.ProjectId }; var validatorBeforeSave = new BeforeSaveValidator <_TEntity>(); var validationBeforeSaveResult = await validatorBeforeSave .ValidateAsync(entity).ConfigureAwait(false); if (!validationBeforeSaveResult.IsValid) { Logger.LogWarning(AppLogEvent.RequestNotValid, "Geo validation error. Entity={Entity}. " + "Error={Error}.", entity.ToDictionary(), validationBeforeSaveResult.Errors); return(ErrorResult(validationBeforeSaveResult.Errors .Select(x => x.ErrorMessage))); } // Get project role of current actor var projectResponse = await Mediator .Send(new DbGetEntityByIdRequest <Project>(entity.ProjectId)) .ConfigureAwait(false); ActorRole currentProjectRole = null; if (projectResponse.Success) { projectResponse.Entity.ProjectActorRoles .TryGetValue(createdBy.Id, out currentProjectRole); } var checkPermissionResult = await CheckPermission(entity, createdBy, currentProjectRole) .ConfigureAwait(false); if (!checkPermissionResult.Success) { Logger.LogWarning(AppLogEvent.SecurityNotPassed, "Geo Create permission error. " + "Entity={Entity}. CurrentActor={CurrentActor}." + "CurrentActorProjectRole={CurrentActorProjectRole}." + " Error={Error}.", entity.ToDictionary(), createdBy?.ToDictionary(), currentProjectRole.Name, checkPermissionResult.Errors); return(checkPermissionResult); } return(await Mediator .Send(new DbCreateCommand <_TEntity>(entity)) .ConfigureAwait(false)); } catch (Exception e) { Logger.LogError(AppLogEvent.HandleErrorResponse, e, "Call repository exception"); return(ErrorResult("Not found")); } }