diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp.EShop.Orders.Application.csproj b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp.EShop.Orders.Application.csproj index c55a2f15..02950336 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp.EShop.Orders.Application.csproj +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp.EShop.Orders.Application.csproj @@ -11,7 +11,7 @@ - + diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/EShopOrdersApplicationModule.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/EShopOrdersApplicationModule.cs index 444cd40d..6bc4e6eb 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/EShopOrdersApplicationModule.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/EShopOrdersApplicationModule.cs @@ -1,4 +1,5 @@ using EasyAbp.EShop.Products; +using EasyAbp.EShop.Stores; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; @@ -10,6 +11,7 @@ namespace EasyAbp.EShop.Orders typeof(EShopOrdersDomainModule), typeof(EShopOrdersApplicationContractsModule), typeof(EShopProductsApplicationContractsModule), + typeof(EShopStoresDomainSharedModule), typeof(AbpDddApplicationModule), typeof(AbpAutoMapperModule) )] diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs index c73e949b..b08c4e95 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs @@ -67,15 +67,7 @@ namespace EasyAbp.EShop.Orders.Orders { if (input.CustomerUserId != CurrentUser.GetId()) { - if (input.StoreId.HasValue) - { - await CheckMultiStorePolicyAsync(input.StoreId.Value, GetListPolicyName); - } - else - { - throw new AbpAuthorizationException("Authorization failed! Given policy has not granted: " + - GetListPolicyName); - } + await CheckMultiStorePolicyAsync(input.StoreId, GetListPolicyName); } return await base.GetListAsync(input); @@ -146,7 +138,7 @@ namespace EasyAbp.EShop.Orders.Orders if (order.CustomerUserId != CurrentUser.GetId()) { - await AuthorizationService.CheckStoreOwnerAsync(order.StoreId, OrdersPermissions.Orders.Manage); + await CheckMultiStorePolicyAsync(order.StoreId, OrdersPermissions.Orders.Manage); } return MapToGetOutputDto(order); @@ -159,7 +151,7 @@ namespace EasyAbp.EShop.Orders.Orders if (order.CustomerUserId != CurrentUser.GetId()) { - await AuthorizationService.CheckStoreOwnerAsync(order.StoreId, OrdersPermissions.Orders.Manage); + await CheckMultiStorePolicyAsync(order.StoreId, OrdersPermissions.Orders.Manage); } order = await _orderManager.CompleteAsync(order); diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp.EShop.Products.Application.csproj b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp.EShop.Products.Application.csproj index 99b3a948..a80318c7 100644 --- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp.EShop.Products.Application.csproj +++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp.EShop.Products.Application.csproj @@ -11,7 +11,7 @@ - + diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/EShopProductsApplicationModule.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/EShopProductsApplicationModule.cs index 69403614..8bd0ba3e 100644 --- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/EShopProductsApplicationModule.cs +++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/EShopProductsApplicationModule.cs @@ -1,4 +1,5 @@ using EasyAbp.Abp.Trees; +using EasyAbp.EShop.Stores; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; @@ -9,6 +10,7 @@ namespace EasyAbp.EShop.Products [DependsOn( typeof(EShopProductsDomainModule), typeof(EShopProductsApplicationContractsModule), + typeof(EShopStoresDomainSharedModule), typeof(AbpDddApplicationModule), typeof(AbpAutoMapperModule), typeof(AbpTreesApplicationModule) diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs index 8244fc94..c894261f 100644 --- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs +++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs @@ -52,7 +52,9 @@ namespace EasyAbp.EShop.Products.ProductInventories throw new AbpValidationException("StoreId should not be null."); } - await AuthorizationService.CheckStoreOwnerAsync(input.StoreId.Value, ProductsPermissions.ProductInventory.Update); + await AuthorizationService.CheckMultiStorePolicyAsync(input.StoreId.Value, + ProductsPermissions.ProductInventory.CrossStore, + ProductsPermissions.ProductInventory.Update); await _productStoreRepository.GetAsync(input.ProductId, input.StoreId.Value); } @@ -76,7 +78,8 @@ namespace EasyAbp.EShop.Products.ProductInventories { if (changedInventory >= 0) { - if (!await _productInventoryProvider.TryIncreaseInventoryAsync(productInventory, changedInventory, false)) + if (!await _productInventoryProvider.TryIncreaseInventoryAsync(productInventory, changedInventory, + false)) { throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId, productInventory.Inventory, changedInventory); @@ -84,7 +87,8 @@ namespace EasyAbp.EShop.Products.ProductInventories } else { - if (!await _productInventoryProvider.TryReduceInventoryAsync(productInventory, -changedInventory, false)) + if (!await _productInventoryProvider.TryReduceInventoryAsync(productInventory, -changedInventory, false) + ) { throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId, productInventory.Inventory, changedInventory); diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs index e9defd0e..29aafe1f 100644 --- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs +++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs @@ -14,7 +14,8 @@ using Volo.Abp.Domain.Entities; namespace EasyAbp.EShop.Products.Products { - public class ProductAppService : CrudAppService, + public class ProductAppService : CrudAppService, IProductAppService { protected override string CreatePolicyName { get; set; } = ProductsPermissions.Products.Create; @@ -110,9 +111,11 @@ namespace EasyAbp.EShop.Products.Products var usedAttributeOptionIds = new HashSet(); - foreach (var serializedAttributeOptionIds in product.ProductSkus.Select(sku => sku.SerializedAttributeOptionIds)) + foreach (var serializedAttributeOptionIds in product.ProductSkus.Select(sku => + sku.SerializedAttributeOptionIds)) { - foreach (var attributeOptionId in await _attributeOptionIdsSerializer.DeserializeAsync(serializedAttributeOptionIds)) + foreach (var attributeOptionId in await _attributeOptionIdsSerializer.DeserializeAsync( + serializedAttributeOptionIds)) { usedAttributeOptionIds.Add(attributeOptionId); } @@ -120,7 +123,8 @@ namespace EasyAbp.EShop.Products.Products foreach (var attributeDto in input.ProductAttributes) { - var attribute = product.ProductAttributes.FirstOrDefault(a => a.DisplayName == attributeDto.DisplayName); + var attribute = + product.ProductAttributes.FirstOrDefault(a => a.DisplayName == attributeDto.DisplayName); if (attribute == null) { @@ -137,7 +141,8 @@ namespace EasyAbp.EShop.Products.Products foreach (var optionDto in attributeDto.ProductAttributeOptions) { - var option = attribute.ProductAttributeOptions.FirstOrDefault(o => o.DisplayName == optionDto.DisplayName); + var option = + attribute.ProductAttributeOptions.FirstOrDefault(o => o.DisplayName == optionDto.DisplayName); if (option == null) { @@ -203,7 +208,7 @@ namespace EasyAbp.EShop.Products.Products await LoadDtoInventoryDataAsync(product, dto, storeId); await LoadDtoPriceAsync(product, dto, storeId); - await LoadDtosProductTypeUniqueNameAsync(new[] { dto }); + await LoadDtosProductTypeUniqueNameAsync(new[] {dto}); return dto; } @@ -240,7 +245,10 @@ namespace EasyAbp.EShop.Products.Products { await CheckGetListPolicyAsync(); - var isCurrentUserStoreAdmin = await AuthorizationService.IsStoreOwnerGrantedAsync(input.StoreId, ProductsPermissions.Products.Default); + var isCurrentUserStoreAdmin = + await AuthorizationService.IsMultiStoreGrantedAsync(input.StoreId, + ProductsPermissions.Products.CrossStore, + ProductsPermissions.Products.Default); if (input.ShowHidden && !isCurrentUserStoreAdmin) { @@ -279,7 +287,8 @@ namespace EasyAbp.EShop.Products.Products return new PagedResultDto(totalCount, items); } - protected virtual async Task LoadDtoInventoryDataAsync(Product product, ProductDto productDto, Guid storeId) + protected virtual async Task LoadDtoInventoryDataAsync(Product product, ProductDto productDto, + Guid storeId) { var inventoryDataDict = await _productInventoryProvider.GetInventoryDataDictionaryAsync(product, storeId); @@ -354,7 +363,8 @@ namespace EasyAbp.EShop.Products.Products return ObjectMapper.Map(product); } - public async Task UpdateSkuAsync(Guid productId, Guid productSkuId, Guid storeId, UpdateProductSkuDto input) + public async Task UpdateSkuAsync(Guid productId, Guid productSkuId, Guid storeId, + UpdateProductSkuDto input) { await CheckUpdatePolicyAsync(); diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml.cs index 4c3023fe..4e009fba 100644 --- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml.cs +++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml.cs @@ -35,7 +35,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product { var storeOwners = await _storeOwnerAppService.GetListAsync(new GetStoreOwnerListDto { - OwnerId = CurrentUser.Id.Value, + OwnerUserId = CurrentUser.Id.Value, }); StoreId = storeOwners.Items.FirstOrDefault()?.StoreId; diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/EShopStoresApplicationContractsModule.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/EShopStoresApplicationContractsModule.cs index fb1a51e8..8f80802a 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/EShopStoresApplicationContractsModule.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/EShopStoresApplicationContractsModule.cs @@ -1,10 +1,6 @@ -using EasyAbp.EShop.Stores.Permissions; -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Application; -using Volo.Abp.Modularity; -using Volo.Abp.VirtualFileSystem; +using Volo.Abp.Application; using Volo.Abp.Authorization; +using Volo.Abp.Modularity; namespace EasyAbp.EShop.Stores { @@ -15,9 +11,5 @@ namespace EasyAbp.EShop.Stores )] public class EShopStoresApplicationContractsModule : AbpModule { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - } } } diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Permissions/StoreOwnerAuthorizationExtensions.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Permissions/StoreOwnerAuthorizationExtensions.cs deleted file mode 100644 index 36f2b450..00000000 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Permissions/StoreOwnerAuthorizationExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using System; -using System.Threading.Tasks; - -namespace EasyAbp.EShop.Stores.Permissions -{ - public static class StoreOwnerAuthorizationExtensions - { - public static Task IsStoreOwnerGrantedAsync(this IAuthorizationService authorizationService, - Guid storeId, string policyName = null, object resource = null) - { - return authorizationService.IsGrantedAsync(resource, - new StorePermissionAuthorizationRequirement(storeId, policyName)); - } - - public static Task CheckStoreOwnerAsync(this IAuthorizationService authorizationService, - Guid storeId, string policyName = null, object resource = null) - { - return authorizationService.CheckAsync(resource, - new StorePermissionAuthorizationRequirement(storeId, policyName)); - } - } -} diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/GetStoreOwnerListDto.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/GetStoreOwnerListDto.cs index 7272053f..6395204a 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/GetStoreOwnerListDto.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/GetStoreOwnerListDto.cs @@ -8,6 +8,6 @@ namespace EasyAbp.EShop.Stores.StoreOwners.Dtos { public Guid? StoreId { get; set; } - public Guid? OwnerId { get; set; } + public Guid? OwnerUserId { get; set; } } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/StoreOwnerDto.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/StoreOwnerDto.cs index d2f0bce0..ec66d309 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/StoreOwnerDto.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/StoreOwnerDto.cs @@ -11,6 +11,6 @@ namespace EasyAbp.EShop.Stores.StoreOwners.Dtos public Guid StoreId { get; set; } [Required] - public Guid OwnerId { get; set; } + public Guid OwnerUserId { get; set; } } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerDuplicatedException.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerDuplicatedException.cs index 1aec6071..0dca6466 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerDuplicatedException.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerDuplicatedException.cs @@ -5,8 +5,8 @@ namespace EasyAbp.EShop.Stores.StoreOwners { public class StoreOwnerDuplicatedException : BusinessException { - public StoreOwnerDuplicatedException(Guid storeId, Guid ownerId) : base( - message: $"Owner {ownerId} is duplicate for the store {storeId}") + public StoreOwnerDuplicatedException(Guid storeId, Guid ownerUserId) : base( + message: $"Owner {ownerUserId} is duplicate for the store {storeId}") { } } diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp.EShop.Stores.Application.Shared.csproj b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp.EShop.Stores.Application.Shared.csproj new file mode 100644 index 00000000..5218cb1b --- /dev/null +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp.EShop.Stores.Application.Shared.csproj @@ -0,0 +1,16 @@ + + + + + + netstandard2.0 + + + + + + + + + + diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/EShopStoresApplicationSharedModule.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/EShopStoresApplicationSharedModule.cs new file mode 100644 index 00000000..9d183e76 --- /dev/null +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/EShopStoresApplicationSharedModule.cs @@ -0,0 +1,22 @@ +using EasyAbp.EShop.Stores.Permissions; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Application; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Stores +{ + [DependsOn( + typeof(EShopStoresDomainSharedModule), + typeof(AbpDddApplicationModule), + typeof(AbpAutoMapperModule) + )] + public class EShopStoresApplicationSharedModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSingleton(); + } + } +} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Permissions/BasicStorePermissionAuthorizationHandler.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Permissions/BasicStorePermissionAuthorizationHandler.cs similarity index 100% rename from modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Permissions/BasicStorePermissionAuthorizationHandler.cs rename to modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Permissions/BasicStorePermissionAuthorizationHandler.cs diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Permissions/StoreOwnerAuthorizationExtensions.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Permissions/StoreOwnerAuthorizationExtensions.cs new file mode 100644 index 00000000..b918ec75 --- /dev/null +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Permissions/StoreOwnerAuthorizationExtensions.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.Authorization; +using System; +using System.Threading.Tasks; +using Volo.Abp.Authorization; + +namespace EasyAbp.EShop.Stores.Permissions +{ + public static class StoreOwnerAuthorizationExtensions + { + public static Task IsStoreOwnerGrantedAsync(this IAuthorizationService authorizationService, + Guid storeId, string policyName = null, object resource = null) + { + return authorizationService.IsGrantedAsync(resource, + new StorePermissionAuthorizationRequirement(storeId, policyName)); + } + + public static async Task IsMultiStoreGrantedAsync(this IAuthorizationService authorizationService, + Guid? storeId, string crossStorePolicyName, string policyName, object resource = null) + { + if (storeId.HasValue + && await authorizationService.IsStoreOwnerGrantedAsync(storeId.Value, policyName)) + { + return true; + } + + return await authorizationService.IsGrantedAsync(resource, crossStorePolicyName) + && await authorizationService.IsGrantedAsync(resource, policyName); + } + + public static async Task CheckMultiStorePolicyAsync(this IAuthorizationService authorizationService, + Guid? storeId, string crossStorePolicyName, string policyName, object resource = null) + { + if (storeId.HasValue + && await authorizationService.IsStoreOwnerGrantedAsync(storeId.Value, policyName)) + { + return; + } + + await authorizationService.CheckAsync(resource, crossStorePolicyName); + await authorizationService.CheckAsync(resource, policyName); + } + + public static Task CheckStoreOwnerAsync(this IAuthorizationService authorizationService, + Guid storeId, string policyName = null, object resource = null) + { + return authorizationService.CheckAsync(resource, + new StorePermissionAuthorizationRequirement(storeId, policyName)); + } + } +} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Permissions/StorePermissionAuthorizationRequirement.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Permissions/StorePermissionAuthorizationRequirement.cs similarity index 100% rename from modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Permissions/StorePermissionAuthorizationRequirement.cs rename to modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Permissions/StorePermissionAuthorizationRequirement.cs diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyCrudAppService.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyCrudAppService.cs new file mode 100644 index 00000000..44745c2d --- /dev/null +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyCrudAppService.cs @@ -0,0 +1,125 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Stores.Permissions; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Repositories; + +namespace EasyAbp.EShop.Stores.Stores +{ + public abstract class MultiStoreAbstractKeyCrudAppService + : MultiStoreAbstractKeyCrudAppService + where TEntity : class, IEntity, IMultiStore + where TEntityDto : IMultiStore + { + protected MultiStoreAbstractKeyCrudAppService(IRepository repository) + : base(repository) + { + } + } + + public abstract class MultiStoreAbstractKeyCrudAppService + : MultiStoreAbstractKeyCrudAppService + where TEntity : class, IEntity, IMultiStore + where TEntityDto : IMultiStore + { + protected MultiStoreAbstractKeyCrudAppService(IRepository repository) + : base(repository) + { + } + } + + public abstract class MultiStoreAbstractKeyCrudAppService + : MultiStoreAbstractKeyCrudAppService + where TEntity : class, IEntity, IMultiStore + where TCreateInput : IMultiStore + { + protected MultiStoreAbstractKeyCrudAppService(IRepository repository) + : base(repository) + { + } + } + + public abstract class MultiStoreAbstractKeyCrudAppService + : MultiStoreAbstractKeyCrudAppService + where TEntity : class, IEntity, IMultiStore + where TCreateInput : IMultiStore + { + protected MultiStoreAbstractKeyCrudAppService(IRepository repository) + : base(repository) + { + } + } + + public abstract class MultiStoreAbstractKeyCrudAppService + : AbstractKeyCrudAppService + where TEntity : class, IEntity, IMultiStore + where TCreateInput : IMultiStore + { + protected virtual string CrossStorePolicyName { get; set; } + + protected MultiStoreAbstractKeyCrudAppService(IRepository repository) + : base(repository) + { + } + + public override async Task GetAsync(TKey id) + { + var entity = await GetEntityByIdAsync(id); + + await CheckMultiStorePolicyAsync(entity.StoreId, GetPolicyName); + + return MapToGetOutputDto(entity); + } + + public override async Task CreateAsync(TCreateInput input) + { + await CheckMultiStorePolicyAsync(input.StoreId, CreatePolicyName); + + var entity = MapToEntity(input); + + TryToSetTenantId(entity); + + await Repository.InsertAsync(entity, autoSave: true); + + return MapToGetOutputDto(entity); + } + + public override async Task UpdateAsync(TKey id, TUpdateInput input) + { + var entity = await GetEntityByIdAsync(id); + await CheckMultiStorePolicyAsync(entity.StoreId, UpdatePolicyName); + + MapToEntity(input, entity); + await Repository.UpdateAsync(entity, autoSave: true); + + return MapToGetOutputDto(entity); + } + + public override async Task DeleteAsync(TKey id) + { + var entity = await GetEntityByIdAsync(id); + await CheckMultiStorePolicyAsync(entity.StoreId, DeletePolicyName); + + await DeleteByIdAsync(id); + } + + + protected virtual async Task CheckMultiStorePolicyAsync(Guid? storeId, string policyName) + { + if (storeId.HasValue + && await AuthorizationService.IsStoreOwnerGrantedAsync(storeId.Value, policyName)) + { + return; + } + + await CheckPolicyAsync(CrossStorePolicyName); + await CheckPolicyAsync(policyName); + } + } +} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyReadOnlyAppService.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyReadOnlyAppService.cs new file mode 100644 index 00000000..ea0e2a5b --- /dev/null +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyReadOnlyAppService.cs @@ -0,0 +1,65 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Stores.Permissions; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Repositories; + +namespace EasyAbp.EShop.Stores.Stores +{ + public abstract class MultiStoreAbstractKeyReadOnlyAppService + : MultiStoreAbstractKeyReadOnlyAppService + where TEntity : class, IEntity, IMultiStore + { + protected MultiStoreAbstractKeyReadOnlyAppService(IReadOnlyRepository repository) + : base(repository) + { + } + } + + public abstract class MultiStoreAbstractKeyReadOnlyAppService + : MultiStoreAbstractKeyReadOnlyAppService + where TEntity : class, IEntity, IMultiStore + { + protected MultiStoreAbstractKeyReadOnlyAppService(IReadOnlyRepository repository) + : base(repository) + { + } + } + + public abstract class MultiStoreAbstractKeyReadOnlyAppService + : AbstractKeyReadOnlyAppService + where TEntity : class, IEntity, IMultiStore + { + protected virtual string CrossStorePolicyName { get; set; } + + protected MultiStoreAbstractKeyReadOnlyAppService(IReadOnlyRepository repository) + : base(repository) + { + } + + public override async Task GetAsync(TKey id) + { + var entity = await GetEntityByIdAsync(id); + + await CheckMultiStorePolicyAsync(entity.StoreId, GetPolicyName); + + return MapToGetOutputDto(entity); + } + + protected virtual async Task CheckMultiStorePolicyAsync(Guid? storeId, string policyName) + { + if (storeId.HasValue + && await AuthorizationService.IsStoreOwnerGrantedAsync(storeId.Value, policyName)) + { + return; + } + + await CheckPolicyAsync(CrossStorePolicyName); + await CheckPolicyAsync(policyName); + } + } +} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreCrudAppService.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreCrudAppService.cs similarity index 84% rename from modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreCrudAppService.cs rename to modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreCrudAppService.cs index bbf4f448..352579f3 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreCrudAppService.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreCrudAppService.cs @@ -52,22 +52,10 @@ namespace EasyAbp.EShop.Stores.Stores : base(repository) { } - - protected override Task MapToGetListOutputDtoAsync(TEntity entity) - { - return base.MapToGetOutputDtoAsync(entity); - } - - protected override TEntityDto MapToGetListOutputDto(TEntity entity) - { - return MapToGetOutputDto(entity); - } } - - public abstract class MultiStoreCrudAppService - : MultiStoreAbstractKeyCrudAppService + + public abstract class MultiStoreCrudAppService + : MultiStoreAbstractKeyCrudAppService where TEntity : class, IEntity, IMultiStore where TGetOutputDto : IEntityDto where TGetListOutputDto : IEntityDto @@ -103,9 +91,9 @@ namespace EasyAbp.EShop.Stores.Stores protected override IQueryable ApplyDefaultSorting(IQueryable query) { - if (typeof(TEntity).IsAssignableTo()) + if (typeof(TEntity).IsAssignableTo()) { - return query.OrderByDescending(e => ((IHasCreationTime) e).CreationTime); + return query.OrderByDescending(e => ((ICreationAuditedObject)e).CreationTime); } else { diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreReadOnlyAppService.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreReadOnlyAppService.cs similarity index 95% rename from modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreReadOnlyAppService.cs rename to modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreReadOnlyAppService.cs index 02688eb7..cb9bef3c 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreReadOnlyAppService.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/EasyAbp/EShop/Stores/Stores/MultiStoreReadOnlyAppService.cs @@ -36,7 +36,7 @@ namespace EasyAbp.EShop.Stores.Stores where TGetOutputDto : IEntityDto where TGetListOutputDto : IEntityDto { - protected new IReadOnlyRepository Repository { get; } + protected IReadOnlyRepository Repository { get; } protected MultiStoreReadOnlyAppService(IReadOnlyRepository repository) : base(repository) @@ -53,7 +53,7 @@ namespace EasyAbp.EShop.Stores.Stores { if (typeof(TEntity).IsAssignableTo()) { - return query.OrderByDescending(e => ((ICreationAuditedObject) e).CreationTime); + return query.OrderByDescending(e => ((ICreationAuditedObject)e).CreationTime); } else { diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/FodyWeavers.xml b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/FodyWeavers.xsd b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Shared/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp.EShop.Stores.Application.csproj b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp.EShop.Stores.Application.csproj index 0daef21b..e8fe6281 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp.EShop.Stores.Application.csproj +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp.EShop.Stores.Application.csproj @@ -11,6 +11,7 @@ + diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerAppService.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerAppService.cs index ad2024e4..904bdc34 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerAppService.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerAppService.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using EasyAbp.EShop.Stores.Permissions; using EasyAbp.EShop.Stores.StoreOwners.Dtos; using EasyAbp.EShop.Stores.Stores; +using Volo.Abp.Application.Dtos; namespace EasyAbp.EShop.Stores.StoreOwners { @@ -18,34 +19,37 @@ namespace EasyAbp.EShop.Stores.StoreOwners protected override string CrossStorePolicyName { get; set; } = StoresPermissions.Stores.CrossStore; private readonly IStoreOwnerRepository _repository; + private readonly IStoreOwnerStore _storeOwnerStore; - public StoreOwnerAppService(IStoreOwnerRepository repository) : base(repository) + public StoreOwnerAppService(IStoreOwnerRepository repository, + IStoreOwnerStore storeOwnerStore) : base(repository) { _repository = repository; + _storeOwnerStore = storeOwnerStore; } public override async Task CreateAsync(StoreOwnerDto input) { - if (await _repository.IsExistAsync(input.StoreId, input.OwnerId)) + if (await _repository.IsExistAsync(input.StoreId, input.OwnerUserId)) { - throw new StoreOwnerDuplicatedException(input.StoreId, input.OwnerId); + throw new StoreOwnerDuplicatedException(input.StoreId, input.OwnerUserId); } return await base.CreateAsync(input); } - + protected override IQueryable CreateFilteredQuery(GetStoreOwnerListDto input) { var queryable = Repository.AsQueryable(); - if (input.StoreId.HasValue) + if (input.OwnerUserId.HasValue) { - queryable = queryable.Where(x => x.StoreId == input.StoreId); + queryable = queryable.Where(x => x.OwnerUserId == input.OwnerUserId); } - if (input.OwnerId.HasValue) + if (input.StoreId.HasValue) { - queryable = queryable.Where(x => x.OwnerId == input.OwnerId); + queryable = queryable.Where(x => x.StoreId == input.StoreId); } return queryable; diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyCrudAppService.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyCrudAppService.cs deleted file mode 100644 index cc16d491..00000000 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyCrudAppService.cs +++ /dev/null @@ -1,211 +0,0 @@ -using System; -using System.Threading.Tasks; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Application.Services; -using Volo.Abp.Domain.Entities; -using Volo.Abp.Domain.Repositories; -using Volo.Abp.MultiTenancy; -using Volo.Abp.ObjectMapping; - -namespace EasyAbp.EShop.Stores.Stores -{ - public abstract class MultiStoreAbstractKeyCrudAppService - : MultiStoreAbstractKeyCrudAppService - where TEntity : class, IEntity, IMultiStore - where TEntityDto : IMultiStore - { - protected MultiStoreAbstractKeyCrudAppService(IRepository repository) - : base(repository) - { - } - } - - public abstract class MultiStoreAbstractKeyCrudAppService - : MultiStoreAbstractKeyCrudAppService - where TEntity : class, IEntity, IMultiStore - where TEntityDto : IMultiStore - { - protected MultiStoreAbstractKeyCrudAppService(IRepository repository) - : base(repository) - { - } - } - - public abstract class MultiStoreAbstractKeyCrudAppService - : MultiStoreAbstractKeyCrudAppService - where TEntity : class, IEntity, IMultiStore - where TCreateInput : IMultiStore - { - protected MultiStoreAbstractKeyCrudAppService(IRepository repository) - : base(repository) - { - } - } - - public abstract class MultiStoreAbstractKeyCrudAppService - : MultiStoreAbstractKeyCrudAppService - where TEntity : class, IEntity, IMultiStore - where TCreateInput : IMultiStore - { - protected MultiStoreAbstractKeyCrudAppService(IRepository repository) - : base(repository) - { - } - - protected override Task MapToGetListOutputDtoAsync(TEntity entity) - { - return MapToGetOutputDtoAsync(entity); - } - - protected override TEntityDto MapToGetListOutputDto(TEntity entity) - { - return MapToGetOutputDto(entity); - } - } - - public abstract class MultiStoreAbstractKeyCrudAppService - : MultiStoreAbstractKeyReadOnlyAppService, - ICrudAppService - where TEntity : class, IEntity, IMultiStore - where TCreateInput : IMultiStore - { - protected IRepository Repository { get; } - - protected virtual string CreatePolicyName { get; set; } - - protected virtual string UpdatePolicyName { get; set; } - - protected virtual string DeletePolicyName { get; set; } - - protected MultiStoreAbstractKeyCrudAppService(IRepository repository) - : base(repository) - { - Repository = repository; - } - - public virtual async Task CreateAsync(TCreateInput input) - { - await CheckMultiStorePolicyAsync(input.StoreId, CreatePolicyName); - - var entity = await MapToEntityAsync(input); - - TryToSetTenantId(entity); - - await Repository.InsertAsync(entity, autoSave: true); - - return await MapToGetOutputDtoAsync(entity); - } - - public virtual async Task UpdateAsync(TKey id, TUpdateInput input) - { - var entity = await GetEntityByIdAsync(id); - await CheckMultiStorePolicyAsync(entity.StoreId, UpdatePolicyName); - //TODO: Check if input has id different than given id and normalize if it's default value, throw ex otherwise - await MapToEntityAsync(input, entity); - await Repository.UpdateAsync(entity, autoSave: true); - - return await MapToGetOutputDtoAsync(entity); - } - - public virtual async Task DeleteAsync(TKey id) - { - var entity = await GetEntityByIdAsync(id); - await CheckMultiStorePolicyAsync(entity.StoreId, DeletePolicyName); - - await DeleteByIdAsync(id); - } - - protected abstract Task DeleteByIdAsync(TKey id); - - /// - /// Maps to to create a new entity. - /// It uses by default. - /// It can be overriden for custom mapping. - /// Overriding this has higher priority than overriding the - /// - protected virtual Task MapToEntityAsync(TCreateInput createInput) - { - return Task.FromResult(MapToEntity(createInput)); - } - - /// - /// Maps to to create a new entity. - /// It uses by default. - /// It can be overriden for custom mapping. - /// - protected virtual TEntity MapToEntity(TCreateInput createInput) - { - var entity = ObjectMapper.Map(createInput); - SetIdForGuids(entity); - return entity; - } - - /// - /// Sets Id value for the entity if is . - /// It's used while creating a new entity. - /// - protected virtual void SetIdForGuids(TEntity entity) - { - if (entity is IEntity entityWithGuidId && entityWithGuidId.Id == Guid.Empty) - { - EntityHelper.TrySetId( - entityWithGuidId, - () => GuidGenerator.Create(), - true - ); - } - } - - /// - /// Maps to to update the entity. - /// It uses by default. - /// It can be overriden for custom mapping. - /// Overriding this has higher priority than overriding the - /// - protected virtual Task MapToEntityAsync(TUpdateInput updateInput, TEntity entity) - { - MapToEntity(updateInput, entity); - return Task.CompletedTask; - } - - /// - /// Maps to to update the entity. - /// It uses by default. - /// It can be overriden for custom mapping. - /// - protected virtual void MapToEntity(TUpdateInput updateInput, TEntity entity) - { - ObjectMapper.Map(updateInput, entity); - } - - protected virtual void TryToSetTenantId(TEntity entity) - { - if (entity is IMultiTenant && HasTenantIdProperty(entity)) - { - var tenantId = CurrentTenant.Id; - - if (!tenantId.HasValue) - { - return; - } - - var propertyInfo = entity.GetType().GetProperty(nameof(IMultiTenant.TenantId)); - - if (propertyInfo == null || propertyInfo.GetSetMethod(true) == null) - { - return; - } - - propertyInfo.SetValue(entity, tenantId); - } - } - - protected virtual bool HasTenantIdProperty(TEntity entity) - { - return entity.GetType().GetProperty(nameof(IMultiTenant.TenantId)) != null; - } - } -} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyReadOnlyAppService.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyReadOnlyAppService.cs deleted file mode 100644 index c1b1f2e1..00000000 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/MultiStoreAbstractKeyReadOnlyAppService.cs +++ /dev/null @@ -1,236 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Dynamic.Core; -using System.Threading.Tasks; -using EasyAbp.EShop.Stores.Permissions; -using Volo.Abp; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Application.Services; -using Volo.Abp.Auditing; -using Volo.Abp.Domain.Entities; -using Volo.Abp.Domain.Repositories; -using Volo.Abp.ObjectMapping; - -namespace EasyAbp.EShop.Stores.Stores -{ - public abstract class MultiStoreAbstractKeyReadOnlyAppService - : MultiStoreAbstractKeyReadOnlyAppService - where TEntity : class, IEntity, IMultiStore - { - protected MultiStoreAbstractKeyReadOnlyAppService(IReadOnlyRepository repository) - : base(repository) - { - - } - } - - public abstract class MultiStoreAbstractKeyReadOnlyAppService - : MultiStoreAbstractKeyReadOnlyAppService - where TEntity : class, IEntity, IMultiStore - { - protected MultiStoreAbstractKeyReadOnlyAppService(IReadOnlyRepository repository) - : base(repository) - { - } - } - - public abstract class MultiStoreAbstractKeyReadOnlyAppService - : ApplicationService - , IReadOnlyAppService - where TEntity : class, IEntity, IMultiStore - { - protected IReadOnlyRepository ReadOnlyRepository { get; } - - protected virtual string GetPolicyName { get; set; } - - protected virtual string GetListPolicyName { get; set; } - - protected virtual string CrossStorePolicyName { get; set; } - - protected MultiStoreAbstractKeyReadOnlyAppService(IReadOnlyRepository repository) - { - ReadOnlyRepository = repository; - } - - public virtual async Task GetAsync(TKey id) - { - var entity = await GetEntityByIdAsync(id); - - await CheckMultiStorePolicyAsync(entity.StoreId, GetPolicyName); - - return await MapToGetOutputDtoAsync(entity); - } - - public virtual async Task> GetListAsync(TGetListInput input) - { - await CheckGetListPolicyAsync(); - - var query = CreateFilteredQuery(input); - - var totalCount = await AsyncExecuter.CountAsync(query); - - query = ApplySorting(query, input); - query = ApplyPaging(query, input); - - var entities = await AsyncExecuter.ToListAsync(query); - var entityDtos = await MapToGetListOutputDtosAsync(entities); - - return new PagedResultDto( - totalCount, - entityDtos - ); - } - - protected virtual async Task CheckGetListPolicyAsync() - { - await CheckPolicyAsync(GetListPolicyName); - } - - protected abstract Task GetEntityByIdAsync(TKey id); - - protected virtual async Task CheckMultiStorePolicyAsync(Guid storeId, string policyName) - { - if (!await AuthorizationService.IsStoreOwnerGrantedAsync(storeId, policyName)) - { - await CheckPolicyAsync(CrossStorePolicyName); - await CheckPolicyAsync(policyName); - } - } - - /// - /// Should apply sorting if needed. - /// - /// The query. - /// The input. - protected virtual IQueryable ApplySorting(IQueryable query, TGetListInput input) - { - //Try to sort query if available - if (input is ISortedResultRequest sortInput) - { - if (!sortInput.Sorting.IsNullOrWhiteSpace()) - { - return query.OrderBy(sortInput.Sorting); - } - } - - //IQueryable.Task requires sorting, so we should sort if Take will be used. - if (input is ILimitedResultRequest) - { - return ApplyDefaultSorting(query); - } - - //No sorting - return query; - } - - /// - /// Applies sorting if no sorting specified but a limited result requested. - /// - /// The query. - protected virtual IQueryable ApplyDefaultSorting(IQueryable query) - { - if (typeof(TEntity).IsAssignableTo()) - { - return query.OrderByDescending(e => ((IHasCreationTime) e).CreationTime); - } - - throw new AbpException( - "No sorting specified but this query requires sorting. Override the ApplyDefaultSorting method for your application service derived from AbstractKeyReadOnlyAppService!"); - } - - /// - /// Should apply paging if needed. - /// - /// The query. - /// The input. - protected virtual IQueryable ApplyPaging(IQueryable query, TGetListInput input) - { - //Try to use paging if available - if (input is IPagedResultRequest pagedInput) - { - return query.PageBy(pagedInput); - } - - //Try to limit query result if available - if (input is ILimitedResultRequest limitedInput) - { - return query.Take(limitedInput.MaxResultCount); - } - - //No paging - return query; - } - - /// - /// This method should create based on given input. - /// It should filter query if needed, but should not do sorting or paging. - /// Sorting should be done in and paging should be done in - /// methods. - /// - /// The input. - protected virtual IQueryable CreateFilteredQuery(TGetListInput input) - { - return ReadOnlyRepository; - } - - /// - /// Maps to . - /// It internally calls the by default. - /// It can be overriden for custom mapping. - /// Overriding this has higher priority than overriding the - /// - protected virtual Task MapToGetOutputDtoAsync(TEntity entity) - { - return Task.FromResult(MapToGetOutputDto(entity)); - } - - /// - /// Maps to . - /// It uses by default. - /// It can be overriden for custom mapping. - /// - protected virtual TGetOutputDto MapToGetOutputDto(TEntity entity) - { - return ObjectMapper.Map(entity); - } - - /// - /// Maps a list of to objects. - /// It uses method for each item in the list. - /// - protected virtual async Task> MapToGetListOutputDtosAsync(List entities) - { - var dtos = new List(); - - foreach (var entity in entities) - { - dtos.Add(await MapToGetListOutputDtoAsync(entity)); - } - - return dtos; - } - - /// - /// Maps to . - /// It internally calls the by default. - /// It can be overriden for custom mapping. - /// Overriding this has higher priority than overriding the - /// - protected virtual Task MapToGetListOutputDtoAsync(TEntity entity) - { - return Task.FromResult(MapToGetListOutputDto(entity)); - } - - /// - /// Maps to . - /// It uses by default. - /// It can be overriden for custom mapping. - /// - protected virtual TGetListOutputDto MapToGetListOutputDto(TEntity entity) - { - return ObjectMapper.Map(entity); - } - } -} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/IStoreOwnerRepository.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/IStoreOwnerRepository.cs index 61dd6e4b..bf03fb61 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/IStoreOwnerRepository.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/IStoreOwnerRepository.cs @@ -10,8 +10,8 @@ namespace EasyAbp.EShop.Stores.StoreOwners { Task> GetListByStoreIdAsync(Guid storeId, CancellationToken cancellationToken = default); - Task> GetListByOwnerIdAsync(Guid ownerId, CancellationToken cancellationToken = default); + Task> GetListByOwnerUserIdAsync(Guid ownerUserId, CancellationToken cancellationToken = default); - Task IsExistAsync(Guid storeId, Guid ownerId, CancellationToken cancellationToken = default); + Task IsExistAsync(Guid storeId, Guid ownerUserId, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/StoreOwner.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/StoreOwner.cs index c8e89ac1..4506a855 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/StoreOwner.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/StoreOwner.cs @@ -11,16 +11,16 @@ namespace EasyAbp.EShop.Stores.StoreOwners public virtual Guid StoreId { get; protected set; } - public virtual Guid OwnerId { get; protected set; } + public virtual Guid OwnerUserId { get; protected set; } protected StoreOwner() { } - public StoreOwner(Guid id, Guid storeId, Guid ownerId, Guid? tenantId = null) : base(id) + public StoreOwner(Guid id, Guid storeId, Guid ownerUserId, Guid? tenantId = null) : base(id) { StoreId = storeId; - OwnerId = ownerId; + OwnerUserId = ownerUserId; TenantId = tenantId; } } diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerStore.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerStore.cs index bed38fcb..a0145604 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerStore.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerStore.cs @@ -60,10 +60,10 @@ namespace EasyAbp.EShop.Stores.StoreOwners var cacheItems = new Dictionary(); foreach (var storeOwner in storeOwners) { - cacheItems.Add(CalculateCacheKey(storeOwner.StoreId, storeOwner.OwnerId), + cacheItems.Add(CalculateCacheKey(storeOwner.StoreId, storeOwner.OwnerUserId), new StoreOwnerCacheItem(true)); - if (storeOwner.StoreId == storeId && storeOwner.OwnerId == userId) + if (storeOwner.OwnerUserId == userId && storeOwner.StoreId == storeId) { currentCacheItem.IsOwner = true; } diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/EntityFrameworkCore/StoresDbContextModelCreatingExtensions.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/EntityFrameworkCore/StoresDbContextModelCreatingExtensions.cs index 20e50c5d..021ebec3 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/EntityFrameworkCore/StoresDbContextModelCreatingExtensions.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/EntityFrameworkCore/StoresDbContextModelCreatingExtensions.cs @@ -45,7 +45,7 @@ namespace EasyAbp.EShop.Stores.EntityFrameworkCore builder.Entity(b => { b.ToTable(options.TablePrefix + "Stores", options.Schema); - b.ConfigureByConvention(); + b.ConfigureByConvention(); /* Configure more properties here */ }); @@ -55,9 +55,9 @@ namespace EasyAbp.EShop.Stores.EntityFrameworkCore b.ConfigureByConvention(); /* Configure more properties here */ - b.HasIndex(x => new {x.StoreId, x.OwnerId}) + b.HasIndex(x => new {x.OwnerUserId, x.StoreId}) .IsUnique(); }); } } -} +} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerRepository.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerRepository.cs index 22c096f8..40b60de5 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerRepository.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerRepository.cs @@ -22,16 +22,16 @@ namespace EasyAbp.EShop.Stores.StoreOwners return await GetQueryable().Where(pc => pc.StoreId == storeId).ToListAsync(cancellationToken); } - public async Task> GetListByOwnerIdAsync(Guid ownerId, + public async Task> GetListByOwnerUserIdAsync(Guid ownerUserId, CancellationToken cancellationToken = default) { - return await GetQueryable().Where(pc => pc.OwnerId == ownerId).ToListAsync(cancellationToken); + return await GetQueryable().Where(pc => pc.OwnerUserId == ownerUserId).ToListAsync(cancellationToken); } - public async Task IsExistAsync(Guid storeId, Guid ownerId, CancellationToken cancellationToken = default) + public async Task IsExistAsync(Guid storeId, Guid ownerUserId, CancellationToken cancellationToken = default) { var storeOwner = await GetQueryable().FirstOrDefaultAsync( - x => x.StoreId == storeId && x.OwnerId == ownerId, + x => x.OwnerUserId == ownerUserId && x.StoreId == storeId, cancellationToken: cancellationToken); return storeOwner != null; diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/EasyAbp.EShop.Stores.Web.csproj b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/EasyAbp.EShop.Stores.Web.csproj index 01386386..b530c1fb 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/EasyAbp.EShop.Stores.Web.csproj +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/EasyAbp.EShop.Stores.Web.csproj @@ -24,7 +24,7 @@ - + @@ -32,44 +32,10 @@ - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - - - CreateModal.cshtml - - - EditModal.cshtml - - - Index.cshtml - - - CreateModal.cshtml - - - EditModal.cshtml - - - Index.cshtml - - - diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/Index.js b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/Index.js index b4930ca6..92ab847f 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/Index.js +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/Index.js @@ -58,7 +58,7 @@ $(function () { } }, { - data: "ownerId", + data: "ownerUserId", render: function (data, type, row, meta) { var currentCell = $("#StoreOwnerTable").DataTable().cells({"row":meta.row, "column":meta.col}).nodes(0); userService.get(data).then( diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/ViewModels/CreateStoreOwnerViewModel.cs b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/ViewModels/CreateStoreOwnerViewModel.cs index 70a202a0..7de5a3b2 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/ViewModels/CreateStoreOwnerViewModel.cs +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/ViewModels/CreateStoreOwnerViewModel.cs @@ -12,6 +12,6 @@ namespace EasyAbp.EShop.Stores.Web.Pages.EShop.Stores.StoreOwners.StoreOwner.Vie [Required] - public Guid OwnerId { get; set; } + public Guid MultiStoreCrudAppService { get; set; } } } \ No newline at end of file