From a4def8625d6c982dd06c88b886b9ce6a6d0279de Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 30 Mar 2020 21:10:35 +0800 Subject: [PATCH 01/16] Fix options prefix in document. Resolve #3419 --- docs/en/Authorization.md | 2 +- docs/en/Modules/Docs.md | 2 +- docs/en/UI/AspNetCore/Bundling-Minification.md | 2 +- docs/zh-Hans/Authorization.md | 2 +- docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md | 10 +++++----- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/en/Authorization.md b/docs/en/Authorization.md index 1bceda951f..58d7011080 100644 --- a/docs/en/Authorization.md +++ b/docs/en/Authorization.md @@ -342,7 +342,7 @@ A permission value provider should return one of the following values from the ` Once a provider is defined, it should be added to the `PermissionOptions` as shown below: ```csharp -Configure(options => +Configure(options => { options.ValueProviders.Add(); }); diff --git a/docs/en/Modules/Docs.md b/docs/en/Modules/Docs.md index db752ceb74..bbed28e8fe 100644 --- a/docs/en/Modules/Docs.md +++ b/docs/en/Modules/Docs.md @@ -134,7 +134,7 @@ An ABP module must declare `[DependsOn]` attribute if it has a dependency upon a { public override void ConfigureServices(ServiceConfigurationContext context) { - Configure(options => + Configure(options => { options.DefinitionProviders.Add(); }); diff --git a/docs/en/UI/AspNetCore/Bundling-Minification.md b/docs/en/UI/AspNetCore/Bundling-Minification.md index 5af3f177d5..4216b6d40f 100644 --- a/docs/en/UI/AspNetCore/Bundling-Minification.md +++ b/docs/en/UI/AspNetCore/Bundling-Minification.md @@ -249,7 +249,7 @@ public class MyPrismjsStyleExtension : BundleContributor Then you can configure `BundleContributorOptions` to extend existing `PrismjsStyleBundleContributor`. ````csharp -Configure(options => +Configure(options => { options .Extensions() diff --git a/docs/zh-Hans/Authorization.md b/docs/zh-Hans/Authorization.md index fd3ec72943..69522d87e5 100644 --- a/docs/zh-Hans/Authorization.md +++ b/docs/zh-Hans/Authorization.md @@ -343,7 +343,7 @@ public class SystemAdminPermissionValueProvider : PermissionValueProvider 定义`Provider`后将其添加到 `PermissionOptions`,如下所示: ````csharp -Configure(options => +Configure(options => { options.ValueProviders.Add(); }); diff --git a/docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md b/docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md index c0f999f996..cce92599d6 100644 --- a/docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md +++ b/docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md @@ -115,7 +115,7 @@ public class MyWebModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - Configure(options => + Configure(options => { options .ScriptBundles @@ -153,7 +153,7 @@ public class MyWebExtensionModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - Configure(options => + Configure(options => { options .ScriptBundles @@ -191,7 +191,7 @@ public class MyExtensionGlobalStyleContributor : BundleContributor 然后你可以按照下面的代码使用这个贡献者: ````C# -services.Configure(options => +services.Configure(options => { options .ScriptBundles @@ -251,7 +251,7 @@ public class MyPrismjsStyleExtension : BundleContributor 然后你可以配置 `BundleContributorOptions` 去扩展已存在的 `PrismjsStyleBundleContributor`. ````csharp -Configure(options => +Configure(options => { options .Extensions() @@ -319,7 +319,7 @@ namespace MyCompany.MyProject 例如: ````c# -services.Configure(options => +services.Configure(options => { options .StyleBundles From ab83f4a37a4f6c6ceb21574df7b19d13943a0255 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 30 Mar 2020 21:18:21 +0800 Subject: [PATCH 02/16] Fix options prefix in document. --- docs/en/Authorization.md | 2 +- docs/en/Best-Practices/Entity-Framework-Core-Integration.md | 2 +- docs/en/Best-Practices/MongoDB-Integration.md | 2 +- docs/en/UI/AspNetCore/Bundling-Minification.md | 2 +- docs/zh-Hans/API/Dynamic-CSharp-API-Clients.md | 4 ++-- docs/zh-Hans/Authorization.md | 2 +- docs/zh-Hans/Best-Practices/MongoDB-Integration.md | 2 +- docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/en/Authorization.md b/docs/en/Authorization.md index 58d7011080..888d907b59 100644 --- a/docs/en/Authorization.md +++ b/docs/en/Authorization.md @@ -339,7 +339,7 @@ A permission value provider should return one of the following values from the ` - `PermissionGrantResult.Prohibited` is returned to prohibit the user for the permission. If any of the providers return `Prohibited`, the result will always be `Prohibited`. Doesn't matter what other providers return. - `PermissionGrantResult.Undefined` is returned if this value provider could not decide about the permission value. Return this to let other providers check the permission. -Once a provider is defined, it should be added to the `PermissionOptions` as shown below: +Once a provider is defined, it should be added to the `AbpPermissionOptions` as shown below: ```csharp Configure(options => diff --git a/docs/en/Best-Practices/Entity-Framework-Core-Integration.md b/docs/en/Best-Practices/Entity-Framework-Core-Integration.md index db8117d798..a86a3e272c 100644 --- a/docs/en/Best-Practices/Entity-Framework-Core-Integration.md +++ b/docs/en/Best-Practices/Entity-Framework-Core-Integration.md @@ -107,7 +107,7 @@ public static class IdentityDbContextModelBuilderExtensions ```` * **Do** call `b.ConfigureByConvention();` for each entity mapping (as shown above). -* **Do** create a **configuration options** class by inheriting from the `ModelBuilderConfigurationOptions`. Example: +* **Do** create a **configuration options** class by inheriting from the `AbpModelBuilderConfigurationOptions`. Example: ````C# public class IdentityModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions diff --git a/docs/en/Best-Practices/MongoDB-Integration.md b/docs/en/Best-Practices/MongoDB-Integration.md index 76b6e8561f..d65872ede7 100644 --- a/docs/en/Best-Practices/MongoDB-Integration.md +++ b/docs/en/Best-Practices/MongoDB-Integration.md @@ -90,7 +90,7 @@ public static class AbpIdentityMongoDbContextExtensions } ``` -- **Do** create a **configuration options** class by inheriting from the `MongoModelBuilderConfigurationOptions`. Example: +- **Do** create a **configuration options** class by inheriting from the `AbpMongoModelBuilderConfigurationOptions`. Example: ```c# public class IdentityMongoModelBuilderConfigurationOptions diff --git a/docs/en/UI/AspNetCore/Bundling-Minification.md b/docs/en/UI/AspNetCore/Bundling-Minification.md index 4216b6d40f..9d88a37135 100644 --- a/docs/en/UI/AspNetCore/Bundling-Minification.md +++ b/docs/en/UI/AspNetCore/Bundling-Minification.md @@ -246,7 +246,7 @@ public class MyPrismjsStyleExtension : BundleContributor } ```` -Then you can configure `BundleContributorOptions` to extend existing `PrismjsStyleBundleContributor`. +Then you can configure `AbpBundleContributorOptions` to extend existing `PrismjsStyleBundleContributor`. ````csharp Configure(options => diff --git a/docs/zh-Hans/API/Dynamic-CSharp-API-Clients.md b/docs/zh-Hans/API/Dynamic-CSharp-API-Clients.md index 331e66c18e..eae86d6117 100644 --- a/docs/zh-Hans/API/Dynamic-CSharp-API-Clients.md +++ b/docs/zh-Hans/API/Dynamic-CSharp-API-Clients.md @@ -69,7 +69,7 @@ public class MyClientAppModule : AbpModule } ```` -查看下面的"RemoteServiceOptions"章节获取更多详细配置. +查看下面的"AbpRemoteServiceOptions"章节获取更多详细配置. ## 使用 @@ -104,7 +104,7 @@ public class MyService : ITransientDependency ## 配置 -### RemoteServiceOptions +### AbpRemoteServiceOptions 默认情况下`AbpRemoteServiceOptions`从`appsettings.json`获取.或者,你可以使用`Configure`方法来设置或重写它.如: diff --git a/docs/zh-Hans/Authorization.md b/docs/zh-Hans/Authorization.md index 69522d87e5..9886d07690 100644 --- a/docs/zh-Hans/Authorization.md +++ b/docs/zh-Hans/Authorization.md @@ -340,7 +340,7 @@ public class SystemAdminPermissionValueProvider : PermissionValueProvider * `PermissionGrantResult.Prohibited` 禁止授权用户,任何一个授权值提供程序返回了 `Prohibited`, 那么其他的提供程序返回的值都不再重要. * `PermissionGrantResult.Undefined` 代表当前无法确定是否授予或禁止权限, 返回`UnDefined`由其他权限值提供程序检查权限. -定义`Provider`后将其添加到 `PermissionOptions`,如下所示: +定义`Provider`后将其添加到 `AbpPermissionOptions`,如下所示: ````csharp Configure(options => diff --git a/docs/zh-Hans/Best-Practices/MongoDB-Integration.md b/docs/zh-Hans/Best-Practices/MongoDB-Integration.md index 4c71a58f90..f2188b7805 100644 --- a/docs/zh-Hans/Best-Practices/MongoDB-Integration.md +++ b/docs/zh-Hans/Best-Practices/MongoDB-Integration.md @@ -90,7 +90,7 @@ public static class AbpIdentityMongoDbContextExtensions } ``` -- **推荐** 通过继承 `MongoModelBuilderConfigurationOptions` 来创建 **configuration Options** 类. 示例: +- **推荐** 通过继承 `AbpMongoModelBuilderConfigurationOptions` 来创建 **configuration Options** 类. 示例: ```c# public class IdentityMongoModelBuilderConfigurationOptions diff --git a/docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md b/docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md index cce92599d6..ebb402b273 100644 --- a/docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md +++ b/docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md @@ -248,7 +248,7 @@ public class MyPrismjsStyleExtension : BundleContributor } ```` -然后你可以配置 `BundleContributorOptions` 去扩展已存在的 `PrismjsStyleBundleContributor`. +然后你可以配置 `AbpBundleContributorOptions` 去扩展已存在的 `PrismjsStyleBundleContributor`. ````csharp Configure(options => From 18e511b8cec3338572ccaa1d2699dec94f0f8eab Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 30 Mar 2020 21:23:01 +0800 Subject: [PATCH 03/16] Rename RemoteServiceOptions --- docs/en/API/Dynamic-CSharp-API-Clients.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/API/Dynamic-CSharp-API-Clients.md b/docs/en/API/Dynamic-CSharp-API-Clients.md index 3c3c2ec26c..460623440f 100644 --- a/docs/en/API/Dynamic-CSharp-API-Clients.md +++ b/docs/en/API/Dynamic-CSharp-API-Clients.md @@ -69,7 +69,7 @@ public class MyClientAppModule : AbpModule } ```` -See the "RemoteServiceOptions" section below for more detailed configuration. +See the "AbpRemoteServiceOptions" section below for more detailed configuration. ## Usage @@ -104,7 +104,7 @@ While you can inject `IBookAppService` like above to use the client proxy, you c ## Configuration -### RemoteServiceOptions +### AbpRemoteServiceOptions `AbpRemoteServiceOptions` is automatically set from the `appsettings.json` by default. Alternatively, you can use `Configure` method to set or override it. Example: From ca080777dbce8f68121c585e69c336ec4f47c815 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 30 Mar 2020 21:31:48 +0800 Subject: [PATCH 04/16] Rename MongoModelBuilderConfigurationOptions & ModelBuilderConfigurationOptions. --- docs/en/Best-Practices/Entity-Framework-Core-Integration.md | 2 +- docs/en/Best-Practices/MongoDB-Integration.md | 2 +- .../Best-Practices/Entity-Framework-Core-Integration.md | 4 ++-- docs/zh-Hans/Best-Practices/MongoDB-Integration.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/en/Best-Practices/Entity-Framework-Core-Integration.md b/docs/en/Best-Practices/Entity-Framework-Core-Integration.md index a86a3e272c..f487f9d61d 100644 --- a/docs/en/Best-Practices/Entity-Framework-Core-Integration.md +++ b/docs/en/Best-Practices/Entity-Framework-Core-Integration.md @@ -110,7 +110,7 @@ public static class IdentityDbContextModelBuilderExtensions * **Do** create a **configuration options** class by inheriting from the `AbpModelBuilderConfigurationOptions`. Example: ````C# -public class IdentityModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions +public class IdentityModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions { public IdentityModelBuilderConfigurationOptions() : base(AbpIdentityConsts.DefaultDbTablePrefix, AbpIdentityConsts.DefaultDbSchema) diff --git a/docs/en/Best-Practices/MongoDB-Integration.md b/docs/en/Best-Practices/MongoDB-Integration.md index d65872ede7..74a0e429f1 100644 --- a/docs/en/Best-Practices/MongoDB-Integration.md +++ b/docs/en/Best-Practices/MongoDB-Integration.md @@ -94,7 +94,7 @@ public static class AbpIdentityMongoDbContextExtensions ```c# public class IdentityMongoModelBuilderConfigurationOptions - : MongoModelBuilderConfigurationOptions + : AbpMongoModelBuilderConfigurationOptions { public IdentityMongoModelBuilderConfigurationOptions() : base(AbpIdentityConsts.DefaultDbTablePrefix) diff --git a/docs/zh-Hans/Best-Practices/Entity-Framework-Core-Integration.md b/docs/zh-Hans/Best-Practices/Entity-Framework-Core-Integration.md index c74945ec01..b01f7eab28 100644 --- a/docs/zh-Hans/Best-Practices/Entity-Framework-Core-Integration.md +++ b/docs/zh-Hans/Best-Practices/Entity-Framework-Core-Integration.md @@ -106,10 +106,10 @@ public static class IdentityDbContextModelBuilderExtensions ```` * **推荐** 为每个Enttiy映射调用 `b.ConfigureByConvention();`(如上所示). -* **推荐** 通过继承 `ModelBuilderConfigurationOptions` 来创建 **configuration Options** 类. 例如: +* **推荐** 通过继承 `AbpModelBuilderConfigurationOptions` 来创建 **configuration Options** 类. 例如: ````C# -public class IdentityModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions +public class IdentityModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions { public IdentityModelBuilderConfigurationOptions() : base(AbpIdentityConsts.DefaultDbTablePrefix, AbpIdentityConsts.DefaultDbSchema) diff --git a/docs/zh-Hans/Best-Practices/MongoDB-Integration.md b/docs/zh-Hans/Best-Practices/MongoDB-Integration.md index f2188b7805..b7b033b1fa 100644 --- a/docs/zh-Hans/Best-Practices/MongoDB-Integration.md +++ b/docs/zh-Hans/Best-Practices/MongoDB-Integration.md @@ -1,4 +1,4 @@ -## MongoDB 集成 +## MongoDB 集成 * **推荐** 为每个模块定义一个独立的 `MongoDbContext` 接口与实现类. @@ -94,7 +94,7 @@ public static class AbpIdentityMongoDbContextExtensions ```c# public class IdentityMongoModelBuilderConfigurationOptions - : MongoModelBuilderConfigurationOptions + : AbpMongoModelBuilderConfigurationOptions { public IdentityMongoModelBuilderConfigurationOptions() : base(AbpIdentityConsts.DefaultDbTablePrefix) From 9698e3f7dc11d588143fe5c8f102e108e5983856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 31 Mar 2020 14:47:16 +0300 Subject: [PATCH 05/16] Refactor MappingPropertyDefinitionChecks --- .../AbpAutoMapperExtensibleDtoExtensions.cs | 2 +- ...xtraPropertiesObjectExtendingExtensions.cs | 135 ++++++++++++------ .../ObjectExtensionPropertyInfo.cs | 14 ++ .../AbpObjectExtendingTestModule.cs | 1 + ...opertiesObjectExtendingExtensions_Tests.cs | 4 +- 5 files changed, 107 insertions(+), 49 deletions(-) diff --git a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperExtensibleDtoExtensions.cs b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperExtensibleDtoExtensions.cs index e78e9628c1..664e35e9b0 100644 --- a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperExtensibleDtoExtensions.cs +++ b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperExtensibleDtoExtensions.cs @@ -8,7 +8,7 @@ namespace AutoMapper { public static IMappingExpression MapExtraProperties( this IMappingExpression mappingExpression, - MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both) + MappingPropertyDefinitionChecks? definitionChecks = null) where TDestination : IHasExtraProperties where TSource : IHasExtraProperties { diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs index 25156f298c..6b687fcf81 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using JetBrains.Annotations; using Volo.Abp.Data; @@ -25,7 +24,7 @@ namespace Volo.Abp.ObjectExtending public static void MapExtraPropertiesTo( [NotNull] this TSource source, [NotNull] TDestination destination, - MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both) + MappingPropertyDefinitionChecks? definitionChecks = null) where TSource : IHasExtraProperties where TDestination : IHasExtraProperties { @@ -58,7 +57,7 @@ namespace Volo.Abp.ObjectExtending public static void MapExtraPropertiesTo( [NotNull] Dictionary sourceDictionary, [NotNull] Dictionary destinationDictionary, - MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both) + MappingPropertyDefinitionChecks? definitionChecks = null) where TSource : IHasExtraProperties where TDestination : IHasExtraProperties { @@ -90,7 +89,7 @@ namespace Volo.Abp.ObjectExtending [NotNull] Type destinationType, [NotNull] Dictionary sourceDictionary, [NotNull] Dictionary destinationDictionary, - MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both) + MappingPropertyDefinitionChecks? definitionChecks = null) { Check.AssignableTo(sourceType, nameof(sourceType)); Check.AssignableTo(destinationType, nameof(destinationType)); @@ -98,78 +97,120 @@ namespace Volo.Abp.ObjectExtending Check.NotNull(destinationDictionary, nameof(destinationDictionary)); var sourceObjectExtension = ObjectExtensionManager.Instance.GetOrNull(sourceType); - if (definitionChecks.HasFlag(MappingPropertyDefinitionChecks.Source) && - sourceObjectExtension == null) - { - return; - } - var destinationObjectExtension = ObjectExtensionManager.Instance.GetOrNull(destinationType); - if (definitionChecks.HasFlag(MappingPropertyDefinitionChecks.Destination) && - destinationObjectExtension == null) - { - return; - } - if (definitionChecks == MappingPropertyDefinitionChecks.None) + foreach (var keyValue in sourceDictionary) { - foreach (var keyValue in sourceDictionary) + if (CanMapProperty( + keyValue.Key, + sourceObjectExtension, + destinationObjectExtension, + definitionChecks)) { destinationDictionary[keyValue.Key] = keyValue.Value; } } - else if (definitionChecks == MappingPropertyDefinitionChecks.Source) - { - Debug.Assert(sourceObjectExtension != null, nameof(sourceObjectExtension) + " != null"); + } + + //TODO: Move these methods to a class like ObjectExtensionHelper + + public static bool CanMapProperty( + [NotNull] string propertyName, + MappingPropertyDefinitionChecks? definitionChecks = null) + { + return CanMapProperty( + typeof(TSource), + typeof(TDestination), + propertyName, + definitionChecks + ); + } + + public static bool CanMapProperty( + [NotNull] Type sourceType, + [NotNull] Type destinationType, + [NotNull] string propertyName, + MappingPropertyDefinitionChecks? definitionChecks = null) + { + Check.AssignableTo(sourceType, nameof(sourceType)); + Check.AssignableTo(destinationType, nameof(destinationType)); + Check.NotNull(propertyName, nameof(propertyName)); + + var sourceObjectExtension = ObjectExtensionManager.Instance.GetOrNull(sourceType); + var destinationObjectExtension = ObjectExtensionManager.Instance.GetOrNull(destinationType); + + return CanMapProperty( + propertyName, + sourceObjectExtension, + destinationObjectExtension, + definitionChecks); + } - foreach (var property in sourceObjectExtension.GetProperties()) + private static bool CanMapProperty( + [NotNull] string propertyName, + [CanBeNull] ObjectExtensionInfo sourceObjectExtension, + [CanBeNull] ObjectExtensionInfo destinationObjectExtension, + MappingPropertyDefinitionChecks? definitionChecks = null) + { + Check.NotNull(propertyName, nameof(propertyName)); + + if (definitionChecks != null) + { + if (definitionChecks.Value.HasFlag(MappingPropertyDefinitionChecks.Source)) { - if (!sourceDictionary.ContainsKey(property.Name)) + if (sourceObjectExtension == null) { - continue; + return false; } - destinationDictionary[property.Name] = sourceDictionary[property.Name]; + if (!sourceObjectExtension.HasProperty(propertyName)) + { + return false; + } } - } - else if (definitionChecks == MappingPropertyDefinitionChecks.Destination) - { - Debug.Assert(destinationObjectExtension != null, nameof(destinationObjectExtension) + " != null"); - foreach (var keyValue in sourceDictionary) + if (definitionChecks.Value.HasFlag(MappingPropertyDefinitionChecks.Destination)) { - if (!destinationObjectExtension.HasProperty(keyValue.Key)) + if (destinationObjectExtension == null) { - continue; + return false; } - destinationDictionary[keyValue.Key] = keyValue.Value; + if (!destinationObjectExtension.HasProperty(propertyName)) + { + return false; + } } + + return true; } - else if (definitionChecks == MappingPropertyDefinitionChecks.Both) + else { - Debug.Assert(sourceObjectExtension != null, nameof(sourceObjectExtension) + " != null"); - Debug.Assert(destinationObjectExtension != null, nameof(destinationObjectExtension) + " != null"); + var sourcePropertyDefinition = sourceObjectExtension?.GetPropertyOrNull(propertyName); + var destinationPropertyDefinition = destinationObjectExtension?.GetPropertyOrNull(propertyName); - foreach (var property in sourceObjectExtension.GetProperties()) + if (sourcePropertyDefinition != null) { - if (!sourceDictionary.ContainsKey(property.Name)) + if (destinationPropertyDefinition != null) { - continue; + return true; } - if (!destinationObjectExtension.HasProperty(property.Name)) + if (sourcePropertyDefinition.CheckPairDefinitionOnMapping == false) { - continue; + return true; } - - destinationDictionary[property.Name] = sourceDictionary[property.Name]; } - } - else - { - throw new NotImplementedException(definitionChecks + " was not implemented!"); + else if (destinationPropertyDefinition != null) + { + if (destinationPropertyDefinition.CheckPairDefinitionOnMapping == false) + { + return true; + } + } + + return false; } } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs index af5d0c2ce4..2edae9a3f8 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs @@ -15,6 +15,20 @@ namespace Volo.Abp.ObjectExtending [NotNull] public Type Type { get; } + /// + /// Indicates whether to check the other side of the object mapping + /// if it explicitly defines the property. This property is used in; + /// + /// * .MapExtraPropertiesTo() extension method. + /// * .MapExtraProperties() configuration for the AutoMapper. + /// + /// It this is true, these methods check if the mapping object + /// has defined the property using the . + /// + /// Default: null (unspecified, uses the default logic). + /// + public bool? CheckPairDefinitionOnMapping { get; set; } + [NotNull] public Dictionary Configuration { get; } diff --git a/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/AbpObjectExtendingTestModule.cs b/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/AbpObjectExtendingTestModule.cs index 6dcee4d5b2..470bb547e5 100644 --- a/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/AbpObjectExtendingTestModule.cs +++ b/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/AbpObjectExtendingTestModule.cs @@ -19,6 +19,7 @@ namespace Volo.Abp.ObjectExtending ObjectExtensionManager.Instance .AddOrUpdateProperty("Name") .AddOrUpdateProperty("Age") + .AddOrUpdateProperty("NoPairCheck", options => options.CheckPairDefinitionOnMapping = false) .AddOrUpdateProperty("Name") .AddOrUpdateProperty("ChildCount"); }); diff --git a/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs b/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs index a51d9514b2..7ba213b81c 100644 --- a/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs +++ b/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs @@ -16,7 +16,8 @@ namespace Volo.Abp.ObjectExtending .SetProperty("Name", "John") .SetProperty("Age", 42) .SetProperty("ChildCount", 2) - .SetProperty("Sex", "male"); + .SetProperty("Sex", "male") + .SetProperty("NoPairCheck", "test-value"); _personDto = new ExtensibleTestPersonDto() .SetProperty("ExistingDtoProperty", "existing-value"); @@ -31,6 +32,7 @@ namespace Volo.Abp.ObjectExtending _personDto.HasProperty("Age").ShouldBeFalse(); //Not defined on the destination _personDto.HasProperty("ChildCount").ShouldBeFalse(); //Not defined in the source _personDto.HasProperty("Sex").ShouldBeFalse(); //Not defined in both classes + _personDto.GetProperty("NoPairCheck").ShouldBe("test-value"); //CheckPairDefinitionOnMapping = false _personDto.GetProperty("ExistingDtoProperty").ShouldBe("existing-value"); //Should not clear existing values } From af15facc6be078210199f6ea3db7285cf7a05322 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Tue, 31 Mar 2020 15:13:58 +0300 Subject: [PATCH 06/16] docs: move linked list document to common utils --- docs/en/UI/Angular/Track-By-Service.md | 4 -- .../{Angular => Common/Utils}/Linked-List.md | 64 +++++++++++++------ docs/en/docs-nav.json | 9 ++- 3 files changed, 53 insertions(+), 24 deletions(-) rename docs/en/UI/{Angular => Common/Utils}/Linked-List.md (93%) diff --git a/docs/en/UI/Angular/Track-By-Service.md b/docs/en/UI/Angular/Track-By-Service.md index 71a98fda9d..e6b560a2eb 100644 --- a/docs/en/UI/Angular/Track-By-Service.md +++ b/docs/en/UI/Angular/Track-By-Service.md @@ -111,7 +111,3 @@ class DemoComponent { trackByTenantAccountId = trackByDeep('tenant', 'account', 'id'); } ``` - -## What's Next? - -* [Linked List (Doubly)](./Linked-List.md) \ No newline at end of file diff --git a/docs/en/UI/Angular/Linked-List.md b/docs/en/UI/Common/Utils/Linked-List.md similarity index 93% rename from docs/en/UI/Angular/Linked-List.md rename to docs/en/UI/Common/Utils/Linked-List.md index 388c5963cd..a11fb56279 100644 --- a/docs/en/UI/Angular/Linked-List.md +++ b/docs/en/UI/Common/Utils/Linked-List.md @@ -130,7 +130,11 @@ list.addTail({ x: 3 }); // {"x":1} <-> {"x":2} <-> {"x":3} -list.addAfter({ x: 0 }, { x: 2 }, (v1, v2) => v1.x === v2.x); +list.addAfter( + { x: 0 }, + 2, + (value, searchedValue) => value.x === searchedValue +); // {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3} ``` @@ -164,7 +168,11 @@ list.addManyTail([{ x: 1 },{ x: 2 },{ x: 3 }]); // {"x":1} <-> {"x":2} <-> {"x":3} -list.addManyAfter([{ x: 4 }, { x: 5 }], { x: 2 }, (v1, v2) => v1.x === v2.x); +list.addManyAfter( + [{ x: 4 }, { x: 5 }], + 2, + (value, searchedValue) => value.x === searchedValue +); // {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3} ``` @@ -203,7 +211,11 @@ list.addTail({ x: 3 }); // {"x":1} <-> {"x":2} <-> {"x":3} -list.addBefore({ x: 0 }, { x: 2 }, (v1, v2) => v1.x === v2.x); +list.addBefore( + { x: 0 }, + 2, + (value, searchedValue) => value.x === searchedValue +); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3} ``` @@ -237,7 +249,11 @@ list.addManyTail([{ x: 1 },{ x: 2 },{ x: 3 }]); // {"x":1} <-> {"x":2} <-> {"x":3} -list.addManyBefore([{ x: 4 }, { x: 5 }], { x: 2 }, (v1, v2) => v1.x === v2.x); +list.addManyBefore( + [{ x: 4 }, { x: 5 }], + 2, + (value, searchedValue) => value.x === searchedValue +); // {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3} ``` @@ -388,7 +404,9 @@ list.add({ x: 3 }).tail(); // {"x":1} <-> {"x":2} <-> {"x":3} -list.add({ x: 0 }).after({ x: 2 }, (v1, v2) => v1.x === v2.x); +list + .add({ x: 0 }) + .after(2, (value, searchedValue) => value.x === searchedValue); // {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3} ``` @@ -429,7 +447,9 @@ list.add({ x: 3 }).tail(); // {"x":1} <-> {"x":2} <-> {"x":3} -list.add({ x: 0 }).before({ x: 2 }, (v1, v2) => v1.x === v2.x); +list + .add({ x: 0 }) + .before(2, (value, searchedValue) => value.x === searchedValue); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3} ``` @@ -543,7 +563,9 @@ list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":2} <-> {"x":3} -list.addMany([{ x: 4 }, { x: 5 }]).after({ x: 2 }, (v1, v2) => v1.x === v2.x); +list + .addMany([{ x: 4 }, { x: 5 }]) + .after(2, (value, searchedValue) => value.x === searchedValue); // {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3} ``` @@ -579,7 +601,9 @@ list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":2} <-> {"x":3} -list.addMany([{ x: 4 }, { x: 5 }]).before({ x: 2 }, (v1, v2) => v1.x === v2.x); +list + .addMany([{ x: 4 }, { x: 5 }]) + .before(2, (value, searchedValue) => value.x === searchedValue); // {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3} ``` @@ -779,7 +803,7 @@ list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} -list.dropByValue({ x: 0 }, (v1, v2) => v1.x === v2.x); +list.dropByValue(0, (value, searchedValue) => value.x === searchedValue); // {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3} ``` @@ -813,7 +837,7 @@ list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} -list.dropByValue({ x: 0 }, (v1, v2) => v1.x === v2.x); +list.dropByValue(0, (value, searchedValue) => value.x === searchedValue); // {"x":1} <-> {"x":2} <-> {"x":3} ``` @@ -921,7 +945,9 @@ list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} -list.drop().byValue({ x: 0 }, (v1, v2) => v1.x === v2.x); +list + .drop() + .byValue(0, (value, searchedValue) => value.x === searchedValue); // {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3} ``` @@ -957,7 +983,9 @@ list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} -list.drop().byValueAll({ x: 0 }, (v1, v2) => v1.x === v2.x); +list + .drop() + .byValueAll(0, (value, searchedValue) => value.x === searchedValue); // {"x":1} <-> {"x":2} <-> {"x":3} ``` @@ -1114,7 +1142,7 @@ found.next.value === "c" -#### indexOf(value: T, compareFn = compare): number +#### indexOf(value: any, compareFn = compare): number Finds the position of the first node from the list that has the given value: @@ -1145,11 +1173,11 @@ list.addTailMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} -const i0 = indexOf({ x: 1 }, (v1, v2) => v1.x === v2.x); -const i1 = indexOf({ x: 2 }, (v1, v2) => v1.x === v2.x); -const i2 = indexOf({ x: 3 }, (v1, v2) => v1.x === v2.x); -const i3 = indexOf({ x: 0 }, (v1, v2) => v1.x === v2.x); -const i4 = indexOf({ x: 4 }, (v1, v2) => v1.x === v2.x); +const i0 = indexOf(1, (value, searchedValue) => value.x === searchedValue); +const i1 = indexOf(2, (value, searchedValue) => value.x === searchedValue); +const i2 = indexOf(3, (value, searchedValue) => value.x === searchedValue); +const i3 = indexOf(0, (value, searchedValue) => value.x === searchedValue); +const i4 = indexOf(4, (value, searchedValue) => value.x === searchedValue); /* i0 === 0 diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index d5b24f4404..52258520f7 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -344,10 +344,15 @@ { "text": "TrackByService", "path": "UI/Angular/Track-By-Service.md" - }, + } + ] + }, + { + "text": "Common", + "items": [ { "text": "Linked List (Doubly)", - "path": "UI/Angular/Linked-List.md" + "path": "UI/Common/Utils/Linked-List.md" } ] } From b3c052be54f7714405b57d9559cdd03a087bc6b3 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Tue, 31 Mar 2020 15:17:11 +0300 Subject: [PATCH 07/16] docs: set type of value back to T in indexOf --- docs/en/UI/Common/Utils/Linked-List.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/UI/Common/Utils/Linked-List.md b/docs/en/UI/Common/Utils/Linked-List.md index a11fb56279..971809e8a8 100644 --- a/docs/en/UI/Common/Utils/Linked-List.md +++ b/docs/en/UI/Common/Utils/Linked-List.md @@ -1142,7 +1142,7 @@ found.next.value === "c" -#### indexOf(value: any, compareFn = compare): number +#### indexOf(value: T, compareFn = compare): number Finds the position of the first node from the list that has the given value: From 0f00344749372b882cabbe6430188261b0aeb1b2 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 31 Mar 2020 15:42:04 +0300 Subject: [PATCH 08/16] feat(core): add checkAccessToken fn to initial-utils --- npm/ng-packs/package.json | 1 + .../core/src/lib/tests/initial-utils.spec.ts | 33 +++++++++++++++---- .../core/src/lib/utils/initial-utils.ts | 17 +++++++++- npm/ng-packs/yarn.lock | 12 ++++--- 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index 9e81892e58..80adfa3d3e 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -34,6 +34,7 @@ "@abp/ng.tenant-management.config": "~2.3.0", "@abp/ng.theme.basic": "~2.3.0", "@abp/ng.theme.shared": "^2.3.0", + "@abp/utils": "~2.3.0", "@angular-builders/jest": "^8.2.0", "@angular-devkit/build-angular": "~0.803.21", "@angular-devkit/build-ng-packagr": "~0.803.21", diff --git a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts index 3ca180a5df..1a8905202b 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts @@ -1,10 +1,10 @@ -import { getInitialData, localeInitializer } from '../utils'; -import { Injector } from '@angular/core'; -import { Spectator, createComponentFactory } from '@ngneat/spectator/jest'; -import { Component } from '@angular/core'; +import { Component, Injector } from '@angular/core'; +import { createComponentFactory, Spectator } from '@ngneat/spectator/jest'; import { Store } from '@ngxs/store'; +import { OAuthService } from 'angular-oauth2-oidc'; import { of } from 'rxjs'; import { GetAppConfiguration } from '../actions'; +import { getInitialData, localeInitializer } from '../utils'; @Component({ selector: 'abp-dummy', @@ -14,7 +14,10 @@ export class DummyComponent {} describe('InitialUtils', () => { let spectator: Spectator; - const createComponent = createComponentFactory({ component: DummyComponent, mocks: [Store] }); + const createComponent = createComponentFactory({ + component: DummyComponent, + mocks: [Store], + }); beforeEach(() => (spectator = createComponent())); @@ -25,7 +28,8 @@ describe('InitialUtils', () => { const store = spectator.get(Store); const dispatchSpy = jest.spyOn(store, 'dispatch'); - injectorSpy.mockReturnValue(store); + injectorSpy.mockReturnValueOnce(store); + injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => false }); dispatchSpy.mockReturnValue(of('test')); expect(typeof getInitialData(injector)).toBe('function'); @@ -34,6 +38,23 @@ describe('InitialUtils', () => { }); }); + describe('#checkAccessToken', () => { + test('should call logOut fn of OAuthService when token is valid and current user not found', async () => { + const injector = spectator.get(Injector); + const injectorSpy = jest.spyOn(injector, 'get'); + const store = spectator.get(Store); + const dispatchSpy = jest.spyOn(store, 'dispatch'); + const logOutFn = jest.fn(); + + injectorSpy.mockReturnValueOnce(store); + injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => true, logOut: logOutFn }); + dispatchSpy.mockReturnValue(of({ currentUser: { id: null } })); + + getInitialData(injector)(); + expect(logOutFn).toHaveBeenCalled(); + }); + }); + describe('#localeInitializer', () => { test('should resolve registerLocale', async () => { const injector = spectator.get(Injector); diff --git a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts index 2043b1e8b6..100710a53a 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts @@ -3,17 +3,32 @@ import { Injector } from '@angular/core'; import { Store } from '@ngxs/store'; import { GetAppConfiguration } from '../actions/config.actions'; import differentLocales from '../constants/different-locales'; +import { ApplicationConfiguration } from '../models/application-configuration'; +import { tap } from 'rxjs/operators'; +import { ConfigState } from '../states/config.state'; +import { OAuthService } from 'angular-oauth2-oidc'; export function getInitialData(injector: Injector) { const fn = () => { const store: Store = injector.get(Store); - return store.dispatch(new GetAppConfiguration()).toPromise(); + return store + .dispatch(new GetAppConfiguration()) + .pipe(tap(res => checkAccessToken(store, injector))) + .toPromise(); }; return fn; } +function checkAccessToken(store: Store, injector: Injector) { + const oAuth = injector.get(OAuthService); + console.warn(oAuth.hasValidAccessToken()); + if (oAuth.hasValidAccessToken() && !store.selectSnapshot(ConfigState.getDeep('currentUser.id'))) { + oAuth.logOut(); + } +} + export function localeInitializer(injector: Injector) { const fn = () => { const store: Store = injector.get(Store); diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index e4bf556c6b..9bd1c259c4 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -120,6 +120,13 @@ chart.js "^2.9.3" tslib "^1.9.0" +"@abp/utils@~2.3.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-2.3.1.tgz#728b978d598a98b643562250be54c92988b986e5" + integrity sha512-sZ1nrl8pV1Zx3WAqHRUQ2V3aJlsjaq1ggg2VIPYY4FjCYHFZ3L+Fkq5cPPZb/MczG1YZpAQiMtCJ/+8slvPHHQ== + dependencies: + just-compare "^1.3.0" + "@angular-builders/jest@^8.2.0": version "8.3.2" resolved "https://registry.yarnpkg.com/@angular-builders/jest/-/jest-8.3.2.tgz#669c350c9df2e3afc9ae048c5067759c36113728" @@ -9578,11 +9585,6 @@ pretty-format@^24.0.0, pretty-format@^24.3.0, pretty-format@^24.8.0, pretty-form ansi-styles "^3.2.0" react-is "^16.8.4" -primeicons@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/primeicons/-/primeicons-2.0.0.tgz#ec3e5a8d4d04a09309225a5a57deb911e08dc0d3" - integrity sha512-GJTCeMSQU8UU1GqbsaDrg/IH+b/vSinJQl52NVpdJ7sShYLZA8Eq6jLF48Ye3N/dQloGrE07i7XsZvxQ9pNbqg== - private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" From da9b2d39ca1a1499416ad90192643a1ae8b60218 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 31 Mar 2020 16:04:56 +0300 Subject: [PATCH 09/16] chore: remove console.warn --- npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts index 100710a53a..04a5a1ca83 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts @@ -23,7 +23,6 @@ export function getInitialData(injector: Injector) { function checkAccessToken(store: Store, injector: Injector) { const oAuth = injector.get(OAuthService); - console.warn(oAuth.hasValidAccessToken()); if (oAuth.hasValidAccessToken() && !store.selectSnapshot(ConfigState.getDeep('currentUser.id'))) { oAuth.logOut(); } From 7feffce4bcc38a5d39b1faf2649ce1100734bfba Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 31 Mar 2020 16:25:00 +0300 Subject: [PATCH 10/16] chore: update abp.resourcemapping.js in utils package --- npm/packs/utils/abp.resourcemapping.js | 2 +- npm/packs/utils/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/npm/packs/utils/abp.resourcemapping.js b/npm/packs/utils/abp.resourcemapping.js index 147008a28e..d8d4cb5f97 100644 --- a/npm/packs/utils/abp.resourcemapping.js +++ b/npm/packs/utils/abp.resourcemapping.js @@ -1,5 +1,5 @@ module.exports = { mappings: { - '@node_modules/@abp/utils/bundles/*': '@libs/abp/utils/', + '@node_modules/@abp/utils/dist/bundles/*.*': '@libs/abp/utils/', }, }; diff --git a/npm/packs/utils/package.json b/npm/packs/utils/package.json index 1a2aec8fa4..0b062aa4c5 100644 --- a/npm/packs/utils/package.json +++ b/npm/packs/utils/package.json @@ -1,6 +1,6 @@ { "name": "@abp/utils", - "version": "2.3.1", + "version": "2.3.2", "scripts": { "prepublish": "yarn install --ignore-scripts && node prepublish.js", "ng": "ng", From 8c917e390ee0ebf61a5caef71246e290acee8d01 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 1 Apr 2020 01:30:48 +0300 Subject: [PATCH 11/16] Show actual exception message from Identity Server . Issue volosoft/volo#1533 Identity server hides the exception message therefore I used Raw of the HTTP content. And hide the stack trace I used --- .../IdentityModelAuthenticationService.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs index e69d3f67c7..b78a05c684 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs +++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs @@ -70,9 +70,17 @@ namespace Volo.Abp.IdentityModel } var tokenResponse = await GetTokenResponse(discoveryResponse, configuration); + if (tokenResponse.IsError) { - throw new AbpException($"Could not get token from the OpenId Connect server! ErrorType: {tokenResponse.ErrorType}. Error: {tokenResponse.Error}. ErrorDescription: {tokenResponse.ErrorDescription}. HttpStatusCode: {tokenResponse.HttpStatusCode}"); + if (tokenResponse.ErrorDescription != null) + { + throw new AbpException($"Could not get token from the OpenId Connect server! ErrorType: {tokenResponse.ErrorType}. Error: {tokenResponse.Error}. ErrorDescription: {tokenResponse.ErrorDescription}. HttpStatusCode: {tokenResponse.HttpStatusCode}"); + } + + var rawError = tokenResponse.Raw; + var withoutInnerException = rawError.Split(new string[] { "" }, StringSplitOptions.RemoveEmptyEntries); + throw new AbpException(withoutInnerException[0]); } return tokenResponse.AccessToken; From d3b139ce10f2a75f76f2350ce8317ddeb6acc777 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 1 Apr 2020 13:46:06 +0300 Subject: [PATCH 12/16] ignore file not found exception (trivial) --- .../Volo/Blogging/Files/RawFileDto.cs | 17 ++++++++++++++++- .../Volo/Blogging/Files/FileAppService.cs | 18 +++++++++++------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs index 56a9653b73..d9b0a4c636 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs @@ -1,7 +1,22 @@ -namespace Volo.Blogging.Files +using System.Security.Cryptography; +using Volo.Abp.Threading; + +namespace Volo.Blogging.Files { public class RawFileDto { public byte[] Bytes { get; set; } + + public bool IsFileEmpty => Bytes == null || Bytes.Length == 0; + + public RawFileDto() + { + + } + + public static RawFileDto EmptyResult() + { + return new RawFileDto() {Bytes = new byte[0]}; + } } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs index 4673f5c6d1..cdfd4cb836 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs @@ -2,6 +2,7 @@ using System.ComponentModel.DataAnnotations; using System.IO; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp; using Volo.Abp.Validation; @@ -12,9 +13,11 @@ namespace Volo.Blogging.Files public class FileAppService : BloggingAppServiceBase, IFileAppService { public BlogFileOptions Options { get; } + private readonly ILogger _logger; - public FileAppService(IOptions options) + public FileAppService(IOptions options, ILogger logger) { + _logger = logger; Options = options.Value; } @@ -35,12 +38,13 @@ namespace Volo.Blogging.Files var filePath = Path.Combine(Options.FileUploadLocalFolder, name); - return Task.FromResult( - new RawFileDto - { - Bytes = File.ReadAllBytes(filePath) - } - ); + if (File.Exists(filePath)) + { + return Task.FromResult(new RawFileDto {Bytes = File.ReadAllBytes(filePath)}); + } + + _logger.LogError($"Cannot find the file {filePath}"); + return Task.FromResult(RawFileDto.EmptyResult()); } public virtual Task CreateAsync(FileUploadInputDto input) From 2d55f3aabc314d8c01d791cbc005066cb68259a9 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Wed, 1 Apr 2020 15:00:00 +0300 Subject: [PATCH 13/16] chore: add umdId to @abp/utils --- npm/packs/utils/projects/utils/ng-package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/npm/packs/utils/projects/utils/ng-package.json b/npm/packs/utils/projects/utils/ng-package.json index c5ccce90e4..23dfd158e5 100644 --- a/npm/packs/utils/projects/utils/ng-package.json +++ b/npm/packs/utils/projects/utils/ng-package.json @@ -3,7 +3,8 @@ "dest": "../../dist", "deleteDestPath": true, "lib": { - "entryFile": "src/public-api.ts" + "entryFile": "src/public-api.ts", + "umdId": "abp.utils.common" }, "whitelistedNonPeerDependencies": ["just-compare"] } From 4fef1aaea138880eea524407d6a4566495b23f44 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 1 Apr 2020 20:52:37 +0300 Subject: [PATCH 14/16] add --connection-string parameter to docs and NewCommand of CLI. Issue #3208 --- docs/en/CLI.md | 1 + .../src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/en/CLI.md b/docs/en/CLI.md index a347599135..f0fd3ae7bd 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -60,6 +60,7 @@ abp new Acme.BookStore * `--version` or `-v`: Specifies the ABP & template version. It can be a [release tag](https://github.com/abpframework/abp/releases) or a [branch name](https://github.com/abpframework/abp/branches). Uses the latest release if not specified. Most of the times, you will want to use the latest version. * `--template-source` or `-ts`: Specifies a custom template source to use to build the project. Local and network sources can be used(Like `D\localTemplate` or `https://.zip`). * `--create-solution-folder` or `-csf`: Specifies if the project will be in a new folder in the output folder or directly the output folder. +* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true`. You can set your own connection string if you don't want to use the default. Be aware that the default database provider is `SQL Server`, therefore you can only enter connection string for SQL Server! ### add-package diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 222bfee307..8a0c21a254 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -218,6 +218,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine(" abp new Acme.BookStore -t module --no-ui"); sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\""); sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); + sb.AppendLine(" abp new Acme.BookStore --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); sb.AppendLine(""); sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); From f192fcda494b500a9908275d13dbeb22f9d1fbfb Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 2 Apr 2020 07:04:18 +0300 Subject: [PATCH 15/16] fix(theme-shared): fix overflow problem in collapse animation --- .../src/lib/animations/collapse.animations.ts | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/animations/collapse.animations.ts b/npm/ng-packs/packages/theme-shared/src/lib/animations/collapse.animations.ts index e2125c4ea6..945ca6ab08 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/animations/collapse.animations.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/animations/collapse.animations.ts @@ -1,4 +1,12 @@ -import { animate, animation, trigger, state, style, transition, useAnimation } from '@angular/animations'; +import { + animate, + animation, + trigger, + state, + style, + transition, + useAnimation, +} from '@angular/animations'; export const collapseY = animation( [ @@ -9,7 +17,10 @@ export const collapseY = animation( ); export const collapseYWithMargin = animation( - [style({ 'margin-top': '0' }), animate('{{ time }} {{ easing }}', style({ 'margin-top': '-100%' }))], + [ + style({ 'margin-top': '0' }), + animate('{{ time }} {{ easing }}', style({ 'margin-left': '-100%' })), + ], { params: { time: '500ms', easing: 'ease' }, }, @@ -32,7 +43,10 @@ export const expandY = animation( ); export const expandYWithMargin = animation( - [style({ 'margin-top': '-100%' }), animate('{{ time }} {{ easing }}', style({ 'margin-top': '0' }))], + [ + style({ 'margin-top': '-100%' }), + animate('{{ time }} {{ easing }}', style({ 'margin-top': '0' })), + ], { params: { time: '500ms', easing: 'ease' }, }, @@ -63,11 +77,14 @@ export const collapseWithMargin = trigger('collapseWithMargin', [ ]); export const collapseLinearWithMargin = trigger('collapseLinearWithMargin', [ - state('collapsed', style({ 'margin-top': '-100%' })), + state('collapsed', style({ 'margin-top': '-100vh' })), state('expanded', style({ 'margin-top': '0' })), transition( 'expanded => collapsed', useAnimation(collapseYWithMargin, { params: { time: '200ms', easing: 'linear' } }), ), - transition('collapsed => expanded', useAnimation(expandYWithMargin, { params: { time: '250ms', easing: 'linear' } })), + transition( + 'collapsed => expanded', + useAnimation(expandYWithMargin, { params: { time: '250ms', easing: 'linear' } }), + ), ]); From 12f4b53e8dec8b9e74cee5d77ace44be1c0009a5 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 2 Apr 2020 13:34:59 +0300 Subject: [PATCH 16/16] feat(theme-basic): add login button to the header resolves #3448 --- .../application-layout.component.html | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html index 9d953dbf5e..ecb3509ce2 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html @@ -195,8 +195,19 @@ -