diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 8ba77e32a9..d06e505e40 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -208,7 +208,7 @@ "WhenShouldIRenewMyLicense": "When should I renew my license?", "WhenShouldIRenewMyLicenseExplanation": "If you renew your license within 1 month after your license expires, the following discounts will be applied: Team License {0}; Business License {1}; Enterprise License {2}. However, if you renew your license after 1 month since the expiry date of your license, the renewal price will be the same as the license purchase price and there will be no discount on your renewal.", "TrialPlan": "Do you have a trial plan?", - "TrialPlanExplanation": "It has a 14 days trial period for the ABP Commercial team license. For more information visit here. Furthermore, for the Team licenses we provide a 30 days money-back guarantee. You can just request a refund in the first 30 days. For the Business and Enterprise licenses, we provide 60% refund in 30 days. This is because Business and Enterprise licenses include the full source code of all the modules and the themes.", + "TrialPlanExplanation": "No, there is no trial version for ABP Commercial. You can check the community edition to understand the code quality and approaches. We also offer a 30-day money-back guarantee for the Team license, no questions asked! You can request a refund within the first 30 days. We provide a 60% refund within 30 days for Business and Enterprise licenses. This is because the Business and Enterprise licenses contain the full source-code of all the modules and themes.", "DoYouAcceptBankWireTransfer": "Do you accept bank wire transfers?", "DoYouAcceptBankWireTransferExplanation": "Yes, we accept bank wire transfers.
After sending the license fee via bank transfer, send your receipt and requested license type to accounting@volosoft.com.
Our international bank account information:", "HowToUpgrade": "How to upgrade existing applications when a new version is available?", diff --git a/docs/en/Modules/OpenIddict.md b/docs/en/Modules/OpenIddict.md index cfa35b7e2c..0271f96065 100644 --- a/docs/en/Modules/OpenIddict.md +++ b/docs/en/Modules/OpenIddict.md @@ -414,6 +414,65 @@ https://documentation.openiddict.com/guides/index.html#events-model https://documentation.openiddict.com/configuration/proof-key-for-code-exchange.html +### Setting Tokens Lifetime + +Update `PreConfigureServices` method of AuthServerModule (or HttpApiHostModule if you don't have tiered/separate-authserver) file: + +```csharp +PreConfigure(builder => +{ + builder.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(30)); + builder.SetAccessTokenLifetime(TimeSpan.FromMinutes(30)); + builder.SetIdentityTokenLifetime(TimeSpan.FromMinutes(30)); + builder.SetRefreshTokenLifetime(TimeSpan.FromDays(14)); +}); +``` + +### Refresh Token + +To use refresh token, it must be supported by OpenIddictServer and the `refresh_token` must be requested by the application. + +> **Note:** Angular application is already configured to use `refresh_token`. + +#### Configuring OpenIddictServer + +Update the **OpenIddictDataSeedContributor**, add `OpenIddictConstants.GrantTypes.RefreshToken` to grant types in `CreateApplicationAsync` method: + +```csharp +await CreateApplicationAsync( + ... + grantTypes: new List //Hybrid flow + { + OpenIddictConstants.GrantTypes.AuthorizationCode, + OpenIddictConstants.GrantTypes.Implicit, + OpenIddictConstants.GrantTypes.RefreshToken, + }, + ... +``` + +> **Note:** You need to re-create this client if you have generated the database already. + +#### Configuring Application: + +You need to request the **offline_access scope** to be able to receive `refresh_token`. + +In **Razor/MVC, Blazor-Server applications**, add `options.Scope.Add("offline_access");` to **OpenIdConnect** options. These application templates are using cookie authentication by default and has default cookie expire options set as: + +```csharp +.AddCookie("Cookies", options => +{ + options.ExpireTimeSpan = TimeSpan.FromDays(365); +}) +``` + +[Cookie ExpireTimeSpan will ignore access_token expiration](https://learn.microsoft.com/en-us/dotnet/api/Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions.ExpireTimeSpan?view=aspnetcore-7.0&viewFallbackFrom=net-7.0) and expired access_token will still be valid if it is set to higher value than the `refresh_token lifetime`. It is recommended to keep **Cookie ExpireTimeSpan** and the **Refresh Token lifetime** same, hence the new token will be persisted in the cookie. + +In **Blazor wasm** applications, add `options.ProviderOptions.DefaultScopes.Add("offline_access");` to **AddOidcAuthentication** options. + +In **Angular** applications, add `offline_access` to **oAuthConfig** scopes in *environment.ts* file. (Angular applications already have this configuration). + + + ## Demo projects In the module's `app` directory there are six projects(including `angular`) diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 7dac3762aa..19cf8fa443 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -32,25 +32,6 @@ Configure(options => > Multi-Tenancy is disabled in the ABP Framework by default. However, it is **enabled by default** when you create a new solution using the [startup template](Startup-Templates/Application.md). `MultiTenancyConsts` class in the solution has a constant to control it in a single place. -### AbpMultiTenancyOptions: Handle inactive and non-existent tenants. - -The `MultiTenancyMiddlewareErrorPageBuilder` of `AbpMultiTenancyOptions` is used to handle inactive and non-existent tenants. - -It will respond to an error page by default, you can change it if you want, eg: only output the error log and continue ASP NET Core's request pipeline. - -```csharp -Configure(options => -{ - options.MultiTenancyMiddlewareErrorPageBuilder = async (context, exception) => - { - // Handle the exception. - - // Return true to stop the pipeline, false to continue. - return true; - }; -}); -``` - ### Database Architecture ABP Framework supports all the following approaches to store the tenant data in the database; @@ -273,6 +254,23 @@ class SomeComponent { > However, we don't suggest to change this value since some clients may assume the the `__tenant` as the parameter name and they might need to manually configure then. +The `MultiTenancyMiddlewareErrorPageBuilder` is used to handle inactive and non-existent tenants. + +It will respond to an error page by default, you can change it if you want, eg: only output the error log and continue ASP NET Core's request pipeline. + +```csharp +Configure(options => +{ + options.MultiTenancyMiddlewareErrorPageBuilder = async (context, exception) => + { + // Handle the exception. + + // Return true to stop the pipeline, false to continue. + return true; + }; +}); +``` + ##### Domain/Subdomain Tenant Resolver In a real application, most of times you will want to determine current tenant either by subdomain (like mytenant1.mydomain.com) or by the whole domain (like mytenant.com). If so, you can configure the `AbpTenantResolveOptions` to add the domain tenant resolver. diff --git a/docs/en/UI/Angular/List-Service.md b/docs/en/UI/Angular/List-Service.md index fc3697bd35..8df8b945d7 100644 --- a/docs/en/UI/Angular/List-Service.md +++ b/docs/en/UI/Angular/List-Service.md @@ -201,3 +201,4 @@ You may use observables in combination with [AsyncPipe](https://angular.io/guide ``` +ABP doesn't have a built-in filtering mechanism. You need to implement it yourself and handle the `filter` property in the backend. diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs index aacb26e5f4..3b14c96330 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs @@ -1,8 +1,11 @@ - +using System; + namespace Volo.Abp.Cli.Auth; public class LoginInfo { + public Guid? Id { get; set; } + public string Name { get; set; } public string Surname { get; set; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginInfoCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginInfoCommand.cs index 9d17bf4c4f..d8f007dc2c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginInfoCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginInfoCommand.cs @@ -1,5 +1,4 @@ -using System; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using System.Text; using System.Threading.Tasks; @@ -41,7 +40,7 @@ public class LoginInfoCommand : IConsoleCommand, ITransientDependency var sb = new StringBuilder(); sb.AppendLine(""); - sb.AppendLine($"Login info:"); + sb.AppendLine("Login info:"); sb.AppendLine($"Name: {loginInfo.Name}"); sb.AppendLine($"Surname: {loginInfo.Surname}"); sb.AppendLine($"Username: {loginInfo.Username}"); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs index bc6cf40ebe..8e89d7b203 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs @@ -308,7 +308,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep { var projectNames = new[] { - ".Web", ".HttpApi.Host", ".AuthServer", + ".Web", ".HttpApi.Host", ".AuthServer", ".Web.Public", ".Web.Public.Host", "" //for app-nolayers-mvc }; @@ -781,6 +781,8 @@ public class ChangeThemeStep : ProjectBuildPipelineStep {".Web", "MyProjectNameWebModule"}, {".HttpApi.Host", "MyProjectNameHttpApiHostModule"}, {".AuthServer", "MyProjectNameAuthServerModule"}, + {".Web.Public", "MyProjectNameWebPublicModule"}, + {".Web.Public.Host", "MyProjectNameWebPublicModule"}, {"", "MyProjectNameWebModule"} }; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs index 7cf58db1cf..244b1008b0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs @@ -258,6 +258,8 @@ public abstract class AppTemplateBase : TemplateInfo { "/MyCompanyName.MyProjectName.Web/package.json", "/MyCompanyName.MyProjectName.Web.Host/package.json", + "/MyCompanyName.MyProjectName.Web.Public/package.json", + "/MyCompanyName.MyProjectName.Web.Public.Host/package.json", "/MyCompanyName.MyProjectName.HttpApi.HostWithIds/package.json", "/MyCompanyName.MyProjectName.HttpApi.Host/package.json", "/MyCompanyName.MyProjectName.AuthServer/package.json", diff --git a/framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj b/framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj index da83bc80f4..77da44eb47 100644 --- a/framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj +++ b/framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj @@ -1,20 +1,21 @@ - - - - - - - netstandard2.0 - Volo.Abp.MultiLingualObject - $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; - false - false - false - - - - - - - - + + + + + + + netstandard2.0 + Volo.Abp.MultiLingualObject + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + enable + + + + + + + diff --git a/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IMultiLingualObjectManager.cs b/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IMultiLingualObjectManager.cs index 904f3abd32..4edbd984bd 100644 --- a/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IMultiLingualObjectManager.cs +++ b/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IMultiLingualObjectManager.cs @@ -5,16 +5,30 @@ namespace Volo.Abp.MultiLingualObjects; public interface IMultiLingualObjectManager { - Task GetTranslationAsync( + Task GetTranslationAsync( TMultiLingual multiLingual, - string culture = null, + string? culture = null, bool fallbackToParentCultures = true) where TMultiLingual : IMultiLingualObject where TTranslation : class, IObjectTranslation; - Task GetTranslationAsync( - ICollection translations, - string culture = null, + Task GetTranslationAsync( + IEnumerable translations, + string? culture = null, bool fallbackToParentCultures = true) + where TTranslation : class, IObjectTranslation; + + + Task> GetBulkTranslationsAsync( + IEnumerable> translationsCombined, + string? culture = null, + bool fallbackToParentCultures = true) + where TTranslation : class, IObjectTranslation; + + Task> GetBulkTranslationsAsync( + IEnumerable multiLinguals, + string? culture = null, + bool fallbackToParentCultures = true) + where TMultiLingual : IMultiLingualObject where TTranslation : class, IObjectTranslation; } diff --git a/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs b/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs index afb4509917..908431e997 100644 --- a/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs +++ b/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs @@ -19,16 +19,16 @@ public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientD { SettingProvider = settingProvider; } - public virtual async Task GetTranslationAsync( - ICollection translations, - string culture, + public virtual async Task GetTranslationAsync( + IEnumerable translations, + string? culture, bool fallbackToParentCultures) where TTranslation : class, IObjectTranslation { culture ??= CultureInfo.CurrentUICulture.Name; - if (translations.IsNullOrEmpty()) + if (translations == null || !translations.Any()) { return null; } @@ -65,9 +65,9 @@ public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientD return translation; } - public virtual Task GetTranslationAsync( + public virtual Task GetTranslationAsync( TMultiLingual multiLingual, - string culture = null, + string? culture = null, bool fallbackToParentCultures = true) where TMultiLingual : IMultiLingualObject where TTranslation : class, IObjectTranslation @@ -75,13 +75,13 @@ public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientD return GetTranslationAsync(multiLingual.Translations, culture: culture, fallbackToParentCultures: fallbackToParentCultures); } - protected virtual TTranslation GetTranslationBasedOnCulturalRecursive( - CultureInfo culture, ICollection translations, int currentDepth) + protected virtual TTranslation? GetTranslationBasedOnCulturalRecursive( + CultureInfo culture, IEnumerable translations, int currentDepth) where TTranslation : class, IObjectTranslation { if (culture == null || culture.Name.IsNullOrWhiteSpace() || - translations.IsNullOrEmpty() || + translations == null || !translations.Any() || currentDepth > MaxCultureFallbackDepth) { return null; @@ -89,5 +89,108 @@ public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientD var translation = translations.FirstOrDefault(pt => pt.Language.Equals(culture.Name, StringComparison.OrdinalIgnoreCase)); return translation ?? GetTranslationBasedOnCulturalRecursive(culture.Parent, translations, currentDepth + 1); - } + } + + public virtual async Task> GetBulkTranslationsAsync(IEnumerable> translationsCombined, string? culture, bool fallbackToParentCultures) + where TTranslation : class, IObjectTranslation + { + culture ??= CultureInfo.CurrentUICulture.Name; + + if (translationsCombined == null || !translationsCombined.Any()) + { + return new(); + } + + var someHaveNoTranslations = false; + var res = new List(); + foreach (var translations in translationsCombined) + { + if (!translations.Any()) + { + //if the src has no translations, don't try to find a translation + res.Add(null); + continue; + } + var translation = translations.FirstOrDefault(pt => pt.Language == culture); + if (translation != null) + { + res.Add(translation); + } + else + { + if (fallbackToParentCultures) + { + translation = GetTranslationBasedOnCulturalRecursive( + CultureInfo.CurrentUICulture.Parent, + translations, + 0 + ); + + if (translation != null) + { + res.Add(translation); + } + else + { + res.Add(null); + someHaveNoTranslations = true; + } + } + else + { + res.Add(null); + someHaveNoTranslations = true; + } + } + } + + + if (someHaveNoTranslations) + { + var defaultLanguage = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); + + var index = 0; + foreach (var translations in translationsCombined) + { + if (!translations.Any()) + { + //don't try to find a translation + } + else + { + var translation = res[index]; + if (translation != null) + { + continue; + } + translation = translations.FirstOrDefault(pt => pt.Language == defaultLanguage); + if (translation != null) + { + res[index] = translation; + } + else + { + res[index] = translations.FirstOrDefault(); + } + } + index++; + } + } + return res; + } + + public virtual async Task> GetBulkTranslationsAsync(IEnumerable multiLinguals, string? culture, bool fallbackToParentCultures) + where TMultiLingual : IMultiLingualObject + where TTranslation : class, IObjectTranslation + { + var resInitial = await GetBulkTranslationsAsync(multiLinguals.Select(x => x.Translations), culture, fallbackToParentCultures); + var index = 0; + var res = new List<(TMultiLingual entity, TTranslation? translation)>(); + foreach (var item in multiLinguals) + { + var t = resInitial[index++]; + res.Add((item, t)); + } + return res; + } } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs index 1a69de7f2c..9f48aebf97 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using JetBrains.Annotations; using Volo.Abp.Data; @@ -5,7 +6,7 @@ using Volo.Abp.UI.Navigation; namespace Volo.Abp.UI.Navigation; -public class ApplicationMenu : IHasMenuItems +public class ApplicationMenu : IHasMenuItems, IHasMenuGroups { /// /// Unique name of the menu in the application. @@ -31,6 +32,10 @@ public class ApplicationMenu : IHasMenuItems [NotNull] public ApplicationMenuItemList Items { get; } + /// + [NotNull] + public ApplicationMenuGroupList Groups { get; } + /// /// Can be used to store a custom object related to this menu. /// @@ -47,6 +52,7 @@ public class ApplicationMenu : IHasMenuItems DisplayName = displayName ?? Name; Items = new ApplicationMenuItemList(); + Groups = new ApplicationMenuGroupList(); } /// @@ -60,6 +66,17 @@ public class ApplicationMenu : IHasMenuItems return this; } + /// + /// Adds a to . + /// + /// to be added + /// This object + public ApplicationMenu AddGroup([NotNull] ApplicationMenuGroup group) + { + Groups.Add(group); + return this; + } + /// /// Adds a custom data item to with given key & value. /// diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs index eec549cf9c..624abde425 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs @@ -64,4 +64,54 @@ public static class ApplicationMenuExtensions return menuWithItems; } + + [NotNull] + public static ApplicationMenuGroup GetMenuGroup( + [NotNull] this IHasMenuGroups menuWithGroups, + string groupName) + { + var menuGroup = menuWithGroups.GetMenuGroupOrNull(groupName); + if (menuGroup == null) + { + throw new AbpException($"Could not find a group item with given name: {groupName}"); + } + + return menuGroup; + } + + [CanBeNull] + public static ApplicationMenuGroup GetMenuGroupOrNull( + [NotNull] this IHasMenuGroups menuWithGroups, + string menuGroupName) + { + Check.NotNull(menuWithGroups, nameof(menuWithGroups)); + + return menuWithGroups.Groups.FirstOrDefault(group => group.Name == menuGroupName); + } + + public static bool TryRemoveMenuGroup( + [NotNull] this IHasMenuGroups menuWithGroups, + string menuGroupName) + { + Check.NotNull(menuWithGroups, nameof(menuWithGroups)); + + return menuWithGroups.Groups.RemoveAll(group => group.Name == menuGroupName) > 0; + } + + [NotNull] + public static IHasMenuGroups SetMenuGroupOrder( + [NotNull] this IHasMenuGroups menuWithGroups, + string menuGroupName, + int order) + { + Check.NotNull(menuWithGroups, nameof(menuWithGroups)); + + var menuGroup = menuWithGroups.GetMenuGroupOrNull(menuGroupName); + if (menuGroup != null) + { + menuGroup.Order = order; + } + + return menuWithGroups; + } } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs new file mode 100644 index 0000000000..469c0ad355 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs @@ -0,0 +1,67 @@ +using JetBrains.Annotations; + +namespace Volo.Abp.UI.Navigation; + +public class ApplicationMenuGroup +{ + private string _displayName; + + /// + /// Default value of a group item. + /// + public const int DefaultOrder = 1000; + + /// + /// Unique name of the group in the application. + /// + [NotNull] + public string Name { get; } + + /// + /// Display name of the group. + /// + [NotNull] + public string DisplayName { + get { return _displayName; } + set { + Check.NotNullOrWhiteSpace(value, nameof(value)); + _displayName = value; + } + } + + /// + /// Can be used to render the element with a specific Id for DOM selections. + /// + public string ElementId { get; set; } + + /// + /// The Display order of the group. + /// Default value: 1000. + /// + public int Order { get; set; } + + public ApplicationMenuGroup( + [NotNull] string name, + [NotNull] string displayName, + string elementId = null, + int order = DefaultOrder) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); + Check.NotNullOrWhiteSpace(displayName, nameof(displayName)); + + Name = name; + DisplayName = displayName; + ElementId = elementId; + Order = order; + } + + private string GetDefaultElementId() + { + return "MenuGroup_" + Name; + } + + public override string ToString() + { + return $"[ApplicationMenuGroup] Name = {Name}"; + } +} diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroupList.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroupList.cs new file mode 100644 index 0000000000..f280f5d4f9 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroupList.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.UI.Navigation; + +public class ApplicationMenuGroupList: List +{ + public ApplicationMenuGroupList() + { + + } + + public ApplicationMenuGroupList(int capacity) + : base(capacity) + { + + } + + public ApplicationMenuGroupList(IEnumerable collection) + : base(collection) + { + + } + + public void Normalize() + { + Order(); + } + + private void Order() + { + var orderedItems = this.OrderBy(item => item.Order).ToArray(); + Clear(); + AddRange(orderedItems); + } +} diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs index 32241ba7ac..dc1614e3e5 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs @@ -92,6 +92,11 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers public string CssClass { get; set; } + /// + /// Can be used to group menu items. + /// + public string GroupName { get; set; } + public ApplicationMenuItem( [NotNull] string name, [NotNull] string displayName, @@ -101,6 +106,7 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers>(); Items = new ApplicationMenuItemList(); diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/IHasMenuGroups.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/IHasMenuGroups.cs new file mode 100644 index 0000000000..fbbe7a63a4 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/IHasMenuGroups.cs @@ -0,0 +1,9 @@ +namespace Volo.Abp.UI.Navigation; + +public interface IHasMenuGroups +{ + /// + /// Menu groups. + /// + ApplicationMenuGroupList Groups { get; } +} diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs index aa933c6e09..349aa8e5a5 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs @@ -96,6 +96,7 @@ public class MenuManager : IMenuManager, ITransientDependency } NormalizeMenu(menu); + NormalizeMenuGroup(menu); return menu; } @@ -159,4 +160,23 @@ public class MenuManager : IMenuManager, ITransientDependency menuWithItems.Items.Normalize(); } + + protected virtual void NormalizeMenuGroup(ApplicationMenu applicationMenu) + { + foreach (var menuGroup in applicationMenu.Items.Where(x => !x.GroupName.IsNullOrWhiteSpace()).GroupBy(x => x.GroupName)) + { + var group = applicationMenu.GetMenuGroupOrNull(menuGroup.First().GroupName); + if (group != null) + { + continue; + } + + foreach (var menuItem in menuGroup) + { + menuItem.GroupName = null; + } + } + + applicationMenu.Groups.Normalize(); + } } diff --git a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo.Abp.MultiLingualObjects.Tests.csproj b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo.Abp.MultiLingualObjects.Tests.csproj index a037cfbcf3..b26ea500bf 100644 --- a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo.Abp.MultiLingualObjects.Tests.csproj +++ b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo.Abp.MultiLingualObjects.Tests.csproj @@ -1,18 +1,21 @@ - + - - net7.0 - - + + net7.0 + + enable + - - - - - - - + + + + + + + + + diff --git a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/AbpMultiLingualObjectsTestModule.cs b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/AbpMultiLingualObjectsTestModule.cs index f099b4fa6c..6fc3a45132 100644 --- a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/AbpMultiLingualObjectsTestModule.cs +++ b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/AbpMultiLingualObjectsTestModule.cs @@ -1,19 +1,34 @@ -using Volo.Abp.Autofac; -using Volo.Abp.Localization; -using Volo.Abp.Modularity; -using Volo.Abp.ObjectMapping; -using Volo.Abp.Settings; - -namespace Volo.Abp.MultiLingualObjects; - -[DependsOn( - typeof(AbpAutofacModule), - typeof(AbpLocalizationModule), - typeof(AbpSettingsModule), - typeof(AbpObjectMappingModule), - typeof(AbpMultiLingualObjectsModule), - typeof(AbpTestBaseModule) -)] -public class AbpMultiLingualObjectsTestModule : AbpModule -{ -} +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Autofac; +using Volo.Abp.AutoMapper; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.ObjectMapping; +using Volo.Abp.Settings; + +namespace Volo.Abp.MultiLingualObjects; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpLocalizationModule), + typeof(AbpSettingsModule), + typeof(AbpObjectMappingModule), + typeof(AbpMultiLingualObjectsModule), + typeof(AbpTestBaseModule), + typeof(AbpAutoMapperModule) +)] +public class AbpMultiLingualObjectsTestModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.DefinitionProviders.Add(); + }); + context.Services.AddAutoMapperObjectMapper(); + Configure(options => + { + options.AddMaps(validate: true); + }); + } +} diff --git a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager_Tests.cs b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager_Tests.cs index afe15bff99..e442d80953 100644 --- a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager_Tests.cs +++ b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager_Tests.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp.AutoMapper; using Volo.Abp.Localization; using Volo.Abp.MultiLingualObjects.TestObjects; using Volo.Abp.Testing; @@ -14,40 +16,63 @@ public class MultiLingualObjectManager_Tests : AbpIntegratedTest _books; + private readonly IMapperAccessor _mapperAccessor; + private readonly Dictionary _testTranslations = new() + { + ["ar"] = "C# التعمق في", + ["zh-Hans"] = "深入理解C#", + ["en"] = "C# in Depth" + }; + public MultiLingualObjectManager_Tests() { - _multiLingualObjectManager = ServiceProvider.GetRequiredService(); - + _multiLingualObjectManager = ServiceProvider.GetRequiredService(); + + //Single Lookup + _book = GetTestBook("en", "zh-Hans"); + //Bulk lookup + _books = new List + { + //has no translations + GetTestBook(), + //english only + GetTestBook("en"), + //arabic only + GetTestBook("ar"), + //arabic + english + GetTestBook("en","ar"), + //arabic + english + chineese + GetTestBook("en", "ar", "zh-Hans") + }; + _mapperAccessor = ServiceProvider.GetRequiredService(); + } + MultiLingualBook GetTestBook(params string[] included) + { var id = Guid.NewGuid(); - _book = new MultiLingualBook(id, 100) - { - Translations = new List() - }; - - var en = new MultiLingualBookTranslation - { - Language = "en", - Name = "C# in Depth", - }; - var zh = new MultiLingualBookTranslation - { - Language = "zh-Hans", - Name = "深入理解C#", - }; - - _book.Translations.Add(en); - _book.Translations.Add(zh); - } + //Single book + var res = new MultiLingualBook(id, 100); + foreach (var language in included) + { + res.Translations.Add(new MultiLingualBookTranslation + { + Language = language, + Name = _testTranslations[language], + }); + } + + return res; + } + [Fact] public async Task GetTranslationAsync() { using (CultureHelper.Use("en-us")) { var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); - - translation.Name.ShouldBe("C# in Depth"); + translation.ShouldNotBeNull(); + translation.Name.ShouldBe(_testTranslations["en"]); } } @@ -57,8 +82,8 @@ public class MultiLingualObjectManager_Tests : AbpIntegratedTest(_book, culture: "en"); + translation.ShouldNotBeNull(); + translation.Name.ShouldBe(_testTranslations["en"]); + } + } + + + [Fact] + public async Task GetBulkTranslationsAsync() + { + using (CultureHelper.Use("en-us")) + { + var translations = await _multiLingualObjectManager.GetBulkTranslationsAsync(_books); + foreach (var (entity, translation) in translations) + { + if (entity.Translations.Any(x => x.Language == "en")) + { + translation.ShouldNotBeNull(); + translation.Name.ShouldBe(_testTranslations["en"]); + } + else + { + translation.ShouldBeNull(); + } + } + } + } - translation.Name.ShouldBe("C# in Depth"); + [Fact] + public async Task GetBulkTranslationsFromListAsync() + { + using (CultureHelper.Use("en-us")) + { + var translations = await _multiLingualObjectManager.GetBulkTranslationsAsync(_books.Select(x => x.Translations)); + foreach (var translation in translations) + { + translation?.Name.ShouldBe(_testTranslations["en"]); + } } } + + [Fact] + public async Task TestBulkMapping() + { + using (CultureHelper.Use("en-us")) + { + var translations = await _multiLingualObjectManager.GetBulkTranslationsAsync(_books); + var translationsDict = translations.ToDictionary(x => x.entity.Id, x => x.translation); + var mapped = _mapperAccessor.Mapper.Map, List>(_books, options => + { + options.Items.Add(nameof(MultiLingualBookTranslation), translationsDict); + }); + Assert.Equal(mapped.Count, _books.Count); + for (int i = 0; i < mapped.Count; i++) + { + var og = _books[i]; + var m = mapped[i]; + Assert.Equal(og.Translations.FirstOrDefault(x => x.Language == "en")?.Name, m.Name); + } + } + } } diff --git a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/MultiLingualObjectTestProfile.cs b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/MultiLingualObjectTestProfile.cs new file mode 100644 index 0000000000..89cc9a51b7 --- /dev/null +++ b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/MultiLingualObjectTestProfile.cs @@ -0,0 +1,23 @@ +namespace Volo.Abp.MultiLingualObjects; + +using System; +using System.Collections.Generic; +using global::AutoMapper; +using Volo.Abp.MultiLingualObjects.TestObjects; + +public class MultiLingualObjectTestProfile : Profile +{ + public MultiLingualObjectTestProfile() + { + CreateMap() + .ForMember(x => x.Name, + x => x.MapFrom((src, target, member, context) => + { + if (context.Items.TryGetValue(nameof(MultiLingualBookTranslation), out var translationsRaw) && translationsRaw is IReadOnlyDictionary translations) + { + return translations.GetValueOrDefault(src.Id)?.Name; + } + return null; + })); + } +} diff --git a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBook.cs b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBook.cs index 92a295e0c5..3b880f48f2 100644 --- a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBook.cs +++ b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBook.cs @@ -1,19 +1,19 @@ -using System; -using System.Collections.Generic; - -namespace Volo.Abp.MultiLingualObjects.TestObjects; - -public class MultiLingualBook : IMultiLingualObject -{ - public MultiLingualBook(Guid id, decimal price) - { - Id = id; - Price = price; - } - - public Guid Id { get; } - - public decimal Price { get; set; } - - public ICollection Translations { get; set; } -} +using System; +using System.Collections.Generic; + +namespace Volo.Abp.MultiLingualObjects.TestObjects; + +public class MultiLingualBook : IMultiLingualObject +{ + public MultiLingualBook(Guid id, decimal price) + { + Id = id; + Price = price; + } + + public Guid Id { get; } + + public decimal Price { get; set; } + + public ICollection Translations { get; set; } = new List(); +} diff --git a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBookDto.cs b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBookDto.cs index ea7e7e9afd..8d61449961 100644 --- a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBookDto.cs +++ b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBookDto.cs @@ -1,12 +1,12 @@ -using System; - -namespace Volo.Abp.MultiLingualObjects.TestObjects; - -public class MultiLingualBookDto -{ - public Guid Id { get; set; } - - public string Name { get; set; } - - public decimal Price { get; set; } -} +using System; + +namespace Volo.Abp.MultiLingualObjects.TestObjects; + +public class MultiLingualBookDto +{ + public Guid Id { get; set; } + + public string? Name { get; set; } + + public decimal Price { get; set; } +} diff --git a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBookTranslation.cs b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBookTranslation.cs index 06cfc33b55..adf482fa17 100644 --- a/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBookTranslation.cs +++ b/framework/test/Volo.Abp.MultiLingualObjects.Tests/Volo/Abp/MultiLingualObjects/TestObjects/MultiLingualBookTranslation.cs @@ -1,8 +1,8 @@ -namespace Volo.Abp.MultiLingualObjects.TestObjects; - -public class MultiLingualBookTranslation : IObjectTranslation -{ - public string Name { get; set; } - - public string Language { get; set; } -} +namespace Volo.Abp.MultiLingualObjects.TestObjects; + +public class MultiLingualBookTranslation : IObjectTranslation +{ + public string? Name { get; set; } + + public required string Language { get; set; } +} diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/AbpUiNavigationTestModule.cs b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/AbpUiNavigationTestModule.cs index 6088984cb9..c482963d75 100644 --- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/AbpUiNavigationTestModule.cs +++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/AbpUiNavigationTestModule.cs @@ -16,6 +16,7 @@ public class AbpUiNavigationTestModule : AbpModule options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor1()); options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor2()); options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor3()); + options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor4()); options.MainMenuNames.Add(MenuManager_Tests.TestMenuContributor3.MenuName); }); diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs index b27de60c10..421e072b0f 100644 --- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs +++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs @@ -46,7 +46,7 @@ public class MenuManager_Tests : AbpIntegratedTest mainMenu.Name.ShouldBe(StandardMenus.Main); mainMenu.DisplayName.ShouldBe("Main Menu"); - mainMenu.Items.Count.ShouldBe(2); + mainMenu.Items.Count.ShouldBe(5); mainMenu.Items[0].Name.ShouldBe("Dashboard"); mainMenu.Items[1].Name.ShouldBe(DefaultMenuNames.Application.Main.Administration); mainMenu.Items[1].Items[0].Name.ShouldBe("Administration.UserManagement"); @@ -63,12 +63,29 @@ public class MenuManager_Tests : AbpIntegratedTest mainMenu.Name.ShouldBe(StandardMenus.Main); - mainMenu.Items.Count.ShouldBe(3); + mainMenu.Items.Count.ShouldBe(6); mainMenu.Items.ShouldContain(x => x.Name == "Products"); mainMenu.Items.ShouldContain(x => x.Name == "Dashboard"); } + [Fact] + public async Task GetMainMenuAsync_GroupMenuItems() + { + var mainMenu = await _menuManager.GetMainMenuAsync(); + + mainMenu.Name.ShouldBe(StandardMenus.Main); + mainMenu.Items.Count.ShouldBe(6); + + mainMenu.Items[2].GroupName.ShouldBe("Layouts"); + mainMenu.Items[3].GroupName.ShouldBe("Layouts"); + mainMenu.Items[4].GroupName.ShouldBe(null); // No group defined + + var layoutsGroup = mainMenu.GetMenuGroup("Layouts"); + layoutsGroup.Name.ShouldBe("Layouts"); + layoutsGroup.DisplayName.ShouldBe("Layouts"); + } + /* Adds menu items: * - Administration * - User Management @@ -149,4 +166,29 @@ public class MenuManager_Tests : AbpIntegratedTest return Task.CompletedTask; } } + + /* Adds group and menu items: + * - Layouts + * - Toolbars + * - Page Header + */ + public class TestMenuContributor4 : IMenuContributor + { + public Task ConfigureMenuAsync(MenuConfigurationContext context) + { + if (context.Menu.Name != StandardMenus.Main) + { + return Task.CompletedTask; + } + + context.Menu.AddGroup(new ApplicationMenuGroup("Layouts", "Layouts")); + + context.Menu.AddItem(new ApplicationMenuItem("Toolbars", "Toolbars", url: "/layouts/toolbars", groupName: "Layouts")); + context.Menu.AddItem(new ApplicationMenuItem("PageHeader", "Page Header", url: "/layouts/page-header", groupName: "Layouts")); + + context.Menu.AddItem(new ApplicationMenuItem("Branding", "Branding", url: "/layouts/branding", groupName: "NotDefinedGroup")); + + return Task.CompletedTask; + } + } } diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json index 84179b9893..5d94aa5242 100644 --- a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json +++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json @@ -3,6 +3,6 @@ "name": "my-app-identityserver", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "^7.1.0-rc.2" + "@abp/aspnetcore.mvc.ui.theme.basic": "^7.1.0-rc.3" } } diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230106050616_Initial.Designer.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230307054116_Initial.Designer.cs similarity index 99% rename from modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230106050616_Initial.Designer.cs rename to modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230307054116_Initial.Designer.cs index 64ad616624..bc14c07aec 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230106050616_Initial.Designer.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230307054116_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace OpenIddict.Demo.Server.Migrations { [DbContext(typeof(ServerDbContext))] - [Migration("20230106050616_Initial")] + [Migration("20230307054116_Initial")] partial class Initial { /// @@ -235,6 +235,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("EntityVersion") + .HasColumnType("int"); + b.Property("ExtraProperties") .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -421,6 +424,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasDefaultValue(false) .HasColumnName("EmailConfirmed"); + b.Property("EntityVersion") + .HasColumnType("int"); + b.Property("ExtraProperties") .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -497,6 +503,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(256)") .HasColumnName("SecurityStamp"); + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + b.Property("Surname") .HasMaxLength(64) .HasColumnType("nvarchar(64)") @@ -699,6 +708,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(128)") .HasColumnName("DisplayName"); + b.Property("EntityVersion") + .HasColumnType("int"); + b.Property("ExtraProperties") .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -1277,6 +1289,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("datetime2") .HasColumnName("DeletionTime"); + b.Property("EntityVersion") + .HasColumnType("int"); + b.Property("ExtraProperties") .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230106050616_Initial.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230307054116_Initial.cs similarity index 99% rename from modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230106050616_Initial.cs rename to modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230307054116_Initial.cs index 611a9ad2ca..ab3646a62c 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230106050616_Initial.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20230307054116_Initial.cs @@ -106,6 +106,7 @@ namespace OpenIddict.Demo.Server.Migrations ParentId = table.Column(type: "uniqueidentifier", nullable: true), Code = table.Column(type: "nvarchar(95)", maxLength: 95, nullable: false), DisplayName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), @@ -186,6 +187,7 @@ namespace OpenIddict.Demo.Server.Migrations IsDefault = table.Column(type: "bit", nullable: false), IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true) }, @@ -240,6 +242,7 @@ namespace OpenIddict.Demo.Server.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), @@ -278,6 +281,8 @@ namespace OpenIddict.Demo.Server.Migrations LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), LockoutEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), AccessFailedCount = table.Column(type: "int", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "bit", nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs index c0599ebe15..f5e599fe73 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs @@ -232,6 +232,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("EntityVersion") + .HasColumnType("int"); + b.Property("ExtraProperties") .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -418,6 +421,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasDefaultValue(false) .HasColumnName("EmailConfirmed"); + b.Property("EntityVersion") + .HasColumnType("int"); + b.Property("ExtraProperties") .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -494,6 +500,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(256)") .HasColumnName("SecurityStamp"); + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + b.Property("Surname") .HasMaxLength(64) .HasColumnType("nvarchar(64)") @@ -696,6 +705,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(128)") .HasColumnName("DisplayName"); + b.Property("EntityVersion") + .HasColumnType("int"); + b.Property("ExtraProperties") .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -1274,6 +1286,9 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("datetime2") .HasColumnName("DeletionTime"); + b.Property("EntityVersion") + .HasColumnType("int"); + b.Property("ExtraProperties") .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs index d7eacfa498..8a664da5c1 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs @@ -127,6 +127,9 @@ public class AbpOpenIddictAspNetCoreModule : AbpModule builder.RemoveEventHandler(OpenIddictServerHandlers.Session.ValidatePostLogoutRedirectUriParameter.Descriptor); builder.AddEventHandler(AbpValidatePostLogoutRedirectUriParameter.Descriptor); + + builder.RemoveEventHandler(OpenIddictServerHandlers.Session.ValidateAuthorizedParty.Descriptor); + builder.AddEventHandler(AbpValidateAuthorizedParty.Descriptor); } builder.AddEventHandler(RemoveClaimsFromClientCredentialsGrantType.Descriptor); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpOpenIddictWildcardDomainBase.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpOpenIddictWildcardDomainBase.cs index 2a603b8f44..8839871832 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpOpenIddictWildcardDomainBase.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpOpenIddictWildcardDomainBase.cs @@ -7,19 +7,16 @@ using Volo.Abp.Text.Formatting; namespace Volo.Abp.OpenIddict.WildcardDomains; public abstract class AbpOpenIddictWildcardDomainBase : IOpenIddictServerHandler - where THandler : class, new() + where THandler : class where TContext : OpenIddictServerEvents.BaseContext { protected THandler Handler { get; set; } protected AbpOpenIddictWildcardDomainOptions WildcardDomainOptions { get; } - protected AbpOpenIddictWildcardDomainBase(IOptions wildcardDomainOptions, bool initHandler = true) + protected AbpOpenIddictWildcardDomainBase(IOptions wildcardDomainOptions, THandler handler) { WildcardDomainOptions = wildcardDomainOptions.Value; - if (initHandler) - { - Handler = new THandler(); - } + Handler = handler; } public abstract ValueTask HandleAsync(TContext context); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateAuthorizedParty.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateAuthorizedParty.cs new file mode 100644 index 0000000000..81c7d66788 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateAuthorizedParty.cs @@ -0,0 +1,37 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using OpenIddict.Abstractions; +using OpenIddict.Server; + +namespace Volo.Abp.OpenIddict.WildcardDomains; + +public class AbpValidateAuthorizedParty : AbpOpenIddictWildcardDomainBase +{ + public static OpenIddictServerHandlerDescriptor Descriptor { get; } + = OpenIddictServerHandlerDescriptor.CreateBuilder() + .UseScopedHandler() + .SetOrder(OpenIddictServerHandlers.Session.ValidateToken.Descriptor.Order + 1_000) + .SetType(OpenIddictServerHandlerType.BuiltIn) + .Build(); + + public AbpValidateAuthorizedParty( + IOptions wildcardDomainsOptions, + IOpenIddictApplicationManager applicationManager) + : base(wildcardDomainsOptions, new OpenIddictServerHandlers.Session.ValidateAuthorizedParty(applicationManager)) + { + Handler = new OpenIddictServerHandlers.Session.ValidateAuthorizedParty(applicationManager); + } + + public async override ValueTask HandleAsync(OpenIddictServerEvents.ValidateLogoutRequestContext context) + { + Check.NotNull(context, nameof(context)); + Check.NotNull(context.IdentityTokenHintPrincipal, nameof(context.IdentityTokenHintPrincipal)); + + if (await CheckWildcardDomainAsync(context.PostLogoutRedirectUri)) + { + return; + } + + await Handler.HandleAsync(context); + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateClientPostLogoutRedirectUri.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateClientPostLogoutRedirectUri.cs index 527eb05eb0..e1fe8b94f8 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateClientPostLogoutRedirectUri.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateClientPostLogoutRedirectUri.cs @@ -19,7 +19,7 @@ public class AbpValidateClientPostLogoutRedirectUri : AbpOpenIddictWildcardDomai public AbpValidateClientPostLogoutRedirectUri( IOptions wildcardDomainsOptions, IOpenIddictApplicationManager applicationManager) - : base(wildcardDomainsOptions, false) + : base(wildcardDomainsOptions, new OpenIddictServerHandlers.Session.ValidateClientPostLogoutRedirectUri(applicationManager)) { Handler = new OpenIddictServerHandlers.Session.ValidateClientPostLogoutRedirectUri(applicationManager); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateClientRedirectUri.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateClientRedirectUri.cs index 85d82a95ab..d2871a57cc 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateClientRedirectUri.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateClientRedirectUri.cs @@ -18,7 +18,7 @@ public class AbpValidateClientRedirectUri : AbpOpenIddictWildcardDomainBase wildcardDomainsOptions, IOpenIddictApplicationManager applicationManager) - : base(wildcardDomainsOptions, false) + : base(wildcardDomainsOptions, new OpenIddictServerHandlers.Authentication.ValidateClientRedirectUri()) { Handler = new OpenIddictServerHandlers.Authentication.ValidateClientRedirectUri(applicationManager); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidatePostLogoutRedirectUriParameter.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidatePostLogoutRedirectUriParameter.cs index 83f33d015c..c6bfc155b5 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidatePostLogoutRedirectUriParameter.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidatePostLogoutRedirectUriParameter.cs @@ -14,7 +14,7 @@ public class AbpValidatePostLogoutRedirectUriParameter : AbpOpenIddictWildcardDo .Build(); public AbpValidatePostLogoutRedirectUriParameter(IOptions wildcardDomainsOptions) - : base(wildcardDomainsOptions) + : base(wildcardDomainsOptions, new OpenIddictServerHandlers.Session.ValidatePostLogoutRedirectUriParameter()) { } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateRedirectUriParameter.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateRedirectUriParameter.cs index 5354646b56..3bac84e2c4 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateRedirectUriParameter.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/WildcardDomains/AbpValidateRedirectUriParameter.cs @@ -14,7 +14,7 @@ public class AbpValidateRedirectUriParameter : AbpOpenIddictWildcardDomainBase wildcardDomainsOptions) - : base(wildcardDomainsOptions) + : base(wildcardDomainsOptions, new OpenIddictServerHandlers.Authentication.ValidateRedirectUriParameter()) { } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts index 095af5ef26..238bc19589 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts @@ -12,3 +12,5 @@ export * from './toast-container/toast-container.component'; export * from './toast/toast.component'; export * from './password/password.component'; export * from './card/index'; +export * from './checkbox/checkbox.component'; +export * from './form-input/form-input.component'; diff --git a/source-code/Volo.Abp.Account.SourceCode/Volo.Abp.Account.SourceCode.zip b/source-code/Volo.Abp.Account.SourceCode/Volo.Abp.Account.SourceCode.zip index 6c37f4e2de..f46999ad2b 100644 Binary files a/source-code/Volo.Abp.Account.SourceCode/Volo.Abp.Account.SourceCode.zip and b/source-code/Volo.Abp.Account.SourceCode/Volo.Abp.Account.SourceCode.zip differ diff --git a/source-code/Volo.Abp.AuditLogging.SourceCode/Volo.Abp.AuditLogging.SourceCode.zip b/source-code/Volo.Abp.AuditLogging.SourceCode/Volo.Abp.AuditLogging.SourceCode.zip index 4ae1b9758f..a730ea7f6f 100644 Binary files a/source-code/Volo.Abp.AuditLogging.SourceCode/Volo.Abp.AuditLogging.SourceCode.zip and b/source-code/Volo.Abp.AuditLogging.SourceCode/Volo.Abp.AuditLogging.SourceCode.zip differ diff --git a/source-code/Volo.Abp.BackgroundJobs.SourceCode/Volo.Abp.BackgroundJobs.SourceCode.zip b/source-code/Volo.Abp.BackgroundJobs.SourceCode/Volo.Abp.BackgroundJobs.SourceCode.zip index 5b606fbf0d..6a66815b1d 100644 Binary files a/source-code/Volo.Abp.BackgroundJobs.SourceCode/Volo.Abp.BackgroundJobs.SourceCode.zip and b/source-code/Volo.Abp.BackgroundJobs.SourceCode/Volo.Abp.BackgroundJobs.SourceCode.zip differ diff --git a/source-code/Volo.Abp.BasicTheme.SourceCode/Volo.Abp.BasicTheme.SourceCode.zip b/source-code/Volo.Abp.BasicTheme.SourceCode/Volo.Abp.BasicTheme.SourceCode.zip index 6f0146465a..8b4676ddda 100644 Binary files a/source-code/Volo.Abp.BasicTheme.SourceCode/Volo.Abp.BasicTheme.SourceCode.zip and b/source-code/Volo.Abp.BasicTheme.SourceCode/Volo.Abp.BasicTheme.SourceCode.zip differ diff --git a/source-code/Volo.Abp.BlobStoring.Database.SourceCode/Volo.Abp.BlobStoring.Database.SourceCode.zip b/source-code/Volo.Abp.BlobStoring.Database.SourceCode/Volo.Abp.BlobStoring.Database.SourceCode.zip index f5f414ee71..01bae0b19c 100644 Binary files a/source-code/Volo.Abp.BlobStoring.Database.SourceCode/Volo.Abp.BlobStoring.Database.SourceCode.zip and b/source-code/Volo.Abp.BlobStoring.Database.SourceCode/Volo.Abp.BlobStoring.Database.SourceCode.zip differ diff --git a/source-code/Volo.Abp.FeatureManagement.SourceCode/Volo.Abp.FeatureManagement.SourceCode.zip b/source-code/Volo.Abp.FeatureManagement.SourceCode/Volo.Abp.FeatureManagement.SourceCode.zip index 2744192134..336f49dbf3 100644 Binary files a/source-code/Volo.Abp.FeatureManagement.SourceCode/Volo.Abp.FeatureManagement.SourceCode.zip and b/source-code/Volo.Abp.FeatureManagement.SourceCode/Volo.Abp.FeatureManagement.SourceCode.zip differ diff --git a/source-code/Volo.Abp.Identity.SourceCode/Volo.Abp.Identity.SourceCode.zip b/source-code/Volo.Abp.Identity.SourceCode/Volo.Abp.Identity.SourceCode.zip index 712b2e08d2..5287538a47 100644 Binary files a/source-code/Volo.Abp.Identity.SourceCode/Volo.Abp.Identity.SourceCode.zip and b/source-code/Volo.Abp.Identity.SourceCode/Volo.Abp.Identity.SourceCode.zip differ diff --git a/source-code/Volo.Abp.IdentityServer.SourceCode/Volo.Abp.IdentityServer.SourceCode.zip b/source-code/Volo.Abp.IdentityServer.SourceCode/Volo.Abp.IdentityServer.SourceCode.zip index 8671bb0e54..4fb56edb7a 100644 Binary files a/source-code/Volo.Abp.IdentityServer.SourceCode/Volo.Abp.IdentityServer.SourceCode.zip and b/source-code/Volo.Abp.IdentityServer.SourceCode/Volo.Abp.IdentityServer.SourceCode.zip differ diff --git a/source-code/Volo.Abp.OpenIddict.SourceCode/Volo.Abp.OpenIddict.SourceCode.zip b/source-code/Volo.Abp.OpenIddict.SourceCode/Volo.Abp.OpenIddict.SourceCode.zip index 4270aef02b..178374ef64 100644 Binary files a/source-code/Volo.Abp.OpenIddict.SourceCode/Volo.Abp.OpenIddict.SourceCode.zip and b/source-code/Volo.Abp.OpenIddict.SourceCode/Volo.Abp.OpenIddict.SourceCode.zip differ diff --git a/source-code/Volo.Abp.PermissionManagement.SourceCode/Volo.Abp.PermissionManagement.SourceCode.zip b/source-code/Volo.Abp.PermissionManagement.SourceCode/Volo.Abp.PermissionManagement.SourceCode.zip index 8b6474bb42..5f677c2ae5 100644 Binary files a/source-code/Volo.Abp.PermissionManagement.SourceCode/Volo.Abp.PermissionManagement.SourceCode.zip and b/source-code/Volo.Abp.PermissionManagement.SourceCode/Volo.Abp.PermissionManagement.SourceCode.zip differ diff --git a/source-code/Volo.Abp.SettingManagement.SourceCode/Volo.Abp.SettingManagement.SourceCode.zip b/source-code/Volo.Abp.SettingManagement.SourceCode/Volo.Abp.SettingManagement.SourceCode.zip index 8d80ea18e0..f6a4a5bc2f 100644 Binary files a/source-code/Volo.Abp.SettingManagement.SourceCode/Volo.Abp.SettingManagement.SourceCode.zip and b/source-code/Volo.Abp.SettingManagement.SourceCode/Volo.Abp.SettingManagement.SourceCode.zip differ diff --git a/source-code/Volo.Abp.TenantManagement.SourceCode/Volo.Abp.TenantManagement.SourceCode.zip b/source-code/Volo.Abp.TenantManagement.SourceCode/Volo.Abp.TenantManagement.SourceCode.zip index 3af8d93b5c..e5a8db2e3b 100644 Binary files a/source-code/Volo.Abp.TenantManagement.SourceCode/Volo.Abp.TenantManagement.SourceCode.zip and b/source-code/Volo.Abp.TenantManagement.SourceCode/Volo.Abp.TenantManagement.SourceCode.zip differ diff --git a/source-code/Volo.Abp.Users.SourceCode/Volo.Abp.Users.SourceCode.zip b/source-code/Volo.Abp.Users.SourceCode/Volo.Abp.Users.SourceCode.zip index 83dd9cdf5a..4d1f400c9c 100644 Binary files a/source-code/Volo.Abp.Users.SourceCode/Volo.Abp.Users.SourceCode.zip and b/source-code/Volo.Abp.Users.SourceCode/Volo.Abp.Users.SourceCode.zip differ diff --git a/source-code/Volo.Abp.VirtualFileExplorer.SourceCode/Volo.Abp.VirtualFileExplorer.SourceCode.zip b/source-code/Volo.Abp.VirtualFileExplorer.SourceCode/Volo.Abp.VirtualFileExplorer.SourceCode.zip index 71bdacb47f..75be0fb58d 100644 Binary files a/source-code/Volo.Abp.VirtualFileExplorer.SourceCode/Volo.Abp.VirtualFileExplorer.SourceCode.zip and b/source-code/Volo.Abp.VirtualFileExplorer.SourceCode/Volo.Abp.VirtualFileExplorer.SourceCode.zip differ diff --git a/source-code/Volo.Blogging.SourceCode/Volo.Blogging.SourceCode.zip b/source-code/Volo.Blogging.SourceCode/Volo.Blogging.SourceCode.zip index 730991592e..1695880fdc 100644 Binary files a/source-code/Volo.Blogging.SourceCode/Volo.Blogging.SourceCode.zip and b/source-code/Volo.Blogging.SourceCode/Volo.Blogging.SourceCode.zip differ diff --git a/source-code/Volo.ClientSimulation.SourceCode/Volo.ClientSimulation.SourceCode.zip b/source-code/Volo.ClientSimulation.SourceCode/Volo.ClientSimulation.SourceCode.zip index 90b0ffa8f7..24df5c1aa5 100644 Binary files a/source-code/Volo.ClientSimulation.SourceCode/Volo.ClientSimulation.SourceCode.zip and b/source-code/Volo.ClientSimulation.SourceCode/Volo.ClientSimulation.SourceCode.zip differ diff --git a/source-code/Volo.CmsKit.SourceCode/Volo.CmsKit.SourceCode.zip b/source-code/Volo.CmsKit.SourceCode/Volo.CmsKit.SourceCode.zip index 7d5b7d25f8..446906ecd6 100644 Binary files a/source-code/Volo.CmsKit.SourceCode/Volo.CmsKit.SourceCode.zip and b/source-code/Volo.CmsKit.SourceCode/Volo.CmsKit.SourceCode.zip differ diff --git a/source-code/Volo.Docs.SourceCode/Volo.Docs.SourceCode.zip b/source-code/Volo.Docs.SourceCode/Volo.Docs.SourceCode.zip index b7fc6f1909..4bd3707ca3 100644 Binary files a/source-code/Volo.Docs.SourceCode/Volo.Docs.SourceCode.zip and b/source-code/Volo.Docs.SourceCode/Volo.Docs.SourceCode.zip differ diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/Pages/Index.cshtml b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/Pages/Index.cshtml index e45ec1b8f1..55b17f3453 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/Pages/Index.cshtml +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/Pages/Index.cshtml @@ -23,7 +23,7 @@