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")); } }