VirtoCommerce/vc-module-catalog

only product resource owner can save it

six006 opened this issue · 2 comments

Can't find any solution for product resource authorize,I want to only product creator can save the product.

src\VirtoCommerce.CatalogModule.Web\Authorization\CatalogAuthorizationHandler.cs

        /// <summary>
        /// Create/Update the specified products.
        /// </summary>
        /// <param name="products">The products.</param>
        [HttpPost]
        [Route("batch")]
        public async Task<ActionResult> SaveProducts([FromBody] CatalogProduct[] products)
        {
            var authorizationResult = await _authorizationService.AuthorizeAsync(User, products, new CatalogAuthorizationRequirement(ModuleConstants.Security.Permissions.Update));
            if (!authorizationResult.Succeeded)
            {
                return Unauthorized();
            }

            await InnerSaveProducts(products);
            return Ok();
        }

But can't find a solution in CatalogAuthorizationHandler.cs
src\VirtoCommerce.CatalogModule.Web\Authorization\CatalogAuthorizationHandler.cs

 public sealed class CatalogAuthorizationHandler : PermissionAuthorizationHandlerBase<CatalogAuthorizationRequirement>
    {
        private readonly MvcNewtonsoftJsonOptions _jsonOptions;
        public CatalogAuthorizationHandler(IOptions<MvcNewtonsoftJsonOptions> jsonOptions)
        {
            _jsonOptions = jsonOptions.Value;
        }

        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, CatalogAuthorizationRequirement requirement)
        {
            await base.HandleRequirementAsync(context, requirement);

            if (!context.HasSucceeded)
            {
                var userPermission = context.User.FindPermission(requirement.Permission, _jsonOptions.SerializerSettings);
                if (userPermission != null)
                {
                    var allowedCatalogIds = userPermission.AssignedScopes.OfType<SelectedCatalogScope>()
                                                          .Select(x => x.CatalogId)
                                                          .Distinct()
                                                          .ToArray();

                    if (context.Resource is CatalogSearchCriteria catalogSearchCriteria)
                    {
                        catalogSearchCriteria.CatalogIds = allowedCatalogIds;
                        context.Succeed(requirement);
                    }
                    else if (context.Resource is CatalogListEntrySearchCriteria listEntrySearchCriteria)
                    {
                        listEntrySearchCriteria.CatalogIds = allowedCatalogIds;
                        context.Succeed(requirement);
                    }
                    else if (context.Resource is Catalog catalog && !catalog.IsTransient())
                    {
                        if (allowedCatalogIds.Contains(catalog.Id))
                        {
                            context.Succeed(requirement);
                        }
                    }
                    else if (context.Resource is IEnumerable<IHasCatalogId> hasCatalogIds)
                    {
                        var catalogIds = hasCatalogIds.Select(x => x.CatalogId).Distinct().ToList();
                        if (catalogIds.Intersect(allowedCatalogIds).Count() == catalogIds.Count)
                        {
                            context.Succeed(requirement);
                        }
                    }
                    else if (context.Resource is IHasCatalogId hasCatalogId)
                    {
                        if (allowedCatalogIds.Contains(hasCatalogId.CatalogId))
                        {
                            context.Succeed(requirement);
                        }
                    }
                    else if (context.Resource is ProductExportDataQuery dataQuery)
                    {
                        if (dataQuery.CatalogIds.IsNullOrEmpty())
                        {
                            dataQuery.CatalogIds = allowedCatalogIds;
                        }
                        else
                        {
                            dataQuery.CatalogIds = dataQuery.CatalogIds.Intersect(allowedCatalogIds).ToArray();
                        }
                        context.Succeed(requirement);
                    }
                    else if (context.Resource is PropertyDictionaryItemSearchCriteria propertyDictionaryItemSearchCriteria)
                    {
                        if (propertyDictionaryItemSearchCriteria.CatalogIds.IsNullOrEmpty())
                        {
                            propertyDictionaryItemSearchCriteria.CatalogIds = allowedCatalogIds;
                        }
                        else
                        {
                            propertyDictionaryItemSearchCriteria.CatalogIds = propertyDictionaryItemSearchCriteria.CatalogIds.Intersect(allowedCatalogIds).ToArray();
                        }
                        context.Succeed(requirement);
                    }
                }
            }
        }
    }

Hi, @six006! We bring you a test solution for your problem. You can look at it here https://github.com/VirtoCommerce/vc-module-catalog/tree/howto/479 (commit d8109fd).

Feel free to reopen this ticket, if this solution not fully covers your requirements.