Пример #1
0
 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
 };
Пример #2
0
        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));
        }
Пример #3
0
        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);
        }
Пример #4
0
 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}")) }
 };
Пример #5
0
        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
            });
        }
Пример #6
0
        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"));
            }
        }
Пример #7
0
        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"));
            }
        }