Example #1
0
        public async Task ExecuteAsync(QueryContext context)
        {
            if (context.IsArrayModel())
            {
                var models = context.ToModels <T>() ?? throw new QueryException("models is required", QueryErrorCode.BadRequest);
                var errors = new List <RecordError>(models.Length);
                if (context.Descriptor.Validate)
                {
                    var validationContext = new ValidationContext <T>(context);
                    for (var index = 0; index < models.Length; ++index)
                    {
                        var model            = models[index];
                        var validationResult = await validationContext.ValidateAsync(model, context.CancellationToken);

                        if (validationResult.IsValid)
                        {
                            continue;
                        }

                        errors.Add(new RecordError
                        {
                            ErrorCode        = QueryErrorCode.ValidationError,
                            ErrorDescription = QueryErrorCode.ValidationError.ToString(),
                            At      = index,
                            Details = validationResult.Errors
                        });
                    }

                    if (errors.Count > 0)
                    {
                        context.Fail(errors, QueryErrorCode.ValidationError, QueryErrorCode.ValidationError.ToString());
                        return;
                    }
                }

                if (context.Descriptor.OnlyOwnerCanUpdate)
                {
                    var authContext = new AuthorizationContext <T>(context);
                    await _repo.UpdateRangeAsync(models,
                                                 async (newDto, oldDto, index, continuation, cancellationToken) =>
                    {
                        var authorized = await authContext.AuthorizeAsync(oldDto, context.Descriptor.UpdatePolicy);
                        if (authorized)
                        {
                            return(true);
                        }

                        errors.Add(new RecordError
                        {
                            ErrorCode        = QueryErrorCode.Unauthorized,
                            ErrorDescription = QueryErrorCode.Unauthorized.ToString(),
                            At = index
                        });
                        continuation.Yes = true;

                        return(false);
                    },
                                                 (dto, index, continuation) =>
                    {
                        errors.Add(new RecordError
                        {
                            ErrorCode        = QueryErrorCode.NotFound,
                            ErrorDescription = QueryErrorCode.NotFound.ToString(),
                            At = index
                        });
                        continuation.Yes = true;
                    }, context.CancellationToken);
                }
                else
                {
                    await _repo.UpdateRangeAsync(models,
                                                 (dto, index, continuation) =>
                    {
                        errors.Add(new RecordError
                        {
                            ErrorCode        = QueryErrorCode.NotFound,
                            ErrorDescription = QueryErrorCode.NotFound.ToString(),
                            At = index
                        });
                        continuation.Yes = true;
                    }, context.CancellationToken);
                }

                if (errors.Count > 0)
                {
                    context.Fail(errors, QueryErrorCode.UnauthorizedOrNotFound, "unauthorized or not found to update");
                }
                else
                {
                    context.Succeed(models);
                }
            }
            else
            {
                var model = context.ToModel <T>() ?? throw new QueryException("model is required", QueryErrorCode.BadRequest);
                if (context.Descriptor.Validate)
                {
                    var validationContext = new ValidationContext <T>(context);
                    var validationResult  = await validationContext.ValidateAsync(model, context.CancellationToken);

                    if (!validationResult.IsValid)
                    {
                        context.Fail(validationResult.Errors, QueryErrorCode.ValidationError, QueryErrorCode.ValidationError.ToString());
                        return;
                    }
                }

                if (context.Descriptor.OnlyOwnerCanUpdate)
                {
                    var authContext = new AuthorizationContext <T>(context);
                    await _repo.UpdateAsync(model,
                                            async (newDto, oldDto, cancellationToken) =>
                    {
                        var authorized = await authContext.AuthorizeAsync(oldDto, context.Descriptor.UpdatePolicy);
                        if (authorized)
                        {
                            return(true);
                        }
                        context.Fail(newDto, QueryErrorCode.Unauthorized, "unauthorized");
                        return(false);
                    },
                                            (dto) => context.Fail(dto, QueryErrorCode.NotFound, "not found"),
                                            context.CancellationToken);
                }
                else
                {
                    await _repo.UpdateAsync(model,
                                            (dto) => context.Fail(dto, QueryErrorCode.NotFound, "not found"),
                                            context.CancellationToken);
                }

                if (!context.HasError)
                {
                    context.Succeed(model);
                }
            }
        }