diff --git a/docs/en/API/Auto-API-Controllers.md b/docs/en/API/Auto-API-Controllers.md index 1644e2d28a..0ffbc644a8 100644 --- a/docs/en/API/Auto-API-Controllers.md +++ b/docs/en/API/Auto-API-Controllers.md @@ -204,7 +204,7 @@ public class MyApplicationConfigurationDto : ApplicationConfigurationDto } ```` -### Remove contoller +### Remove controller Configure `ControllersToRemove` of `AbpAspNetCoreMvcOptions` to remove the controllers. diff --git a/docs/en/Background-Jobs-Hangfire.md b/docs/en/Background-Jobs-Hangfire.md index 77f2da8bd0..69903e1c85 100644 --- a/docs/en/Background-Jobs-Hangfire.md +++ b/docs/en/Background-Jobs-Hangfire.md @@ -70,7 +70,7 @@ After you have installed these NuGet packages, you need to configure your projec > You have to configure a storage for Hangfire. -2. If you want to use hangfire's dashboard, you can add `UseHangfireDashboard` call in the `OnApplicationInitialization` method in `Module` class: +2. If you want to use hangfire's dashboard, you can add `UseAbpHangfireDashboard` call in the `OnApplicationInitialization` method in `Module` class: ````csharp public override void OnApplicationInitialization(ApplicationInitializationContext context) @@ -79,7 +79,7 @@ After you have installed these NuGet packages, you need to configure your projec // ... others - app.UseHangfireDashboard(); //should add to the request pipeline before the app.UseConfiguredEndpoints() + app.UseAbpHangfireDashboard(); //should add to the request pipeline before the app.UseConfiguredEndpoints() app.UseConfiguredEndpoints(); } ```` @@ -128,9 +128,9 @@ You can integrate the Hangfire dashboard to [ABP authorization system](Authoriza class. This class is defined in the `Volo.Abp.Hangfire` package. The following example, checks if the current user is logged in to the application: ```csharp -app.UseHangfireDashboard("/hangfire", new DashboardOptions +app.UseAbpHangfireDashboard("/hangfire", options => { - AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() } + options.AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() }; }); ``` @@ -146,11 +146,11 @@ app.UseHangfireDashboard("/hangfire", new DashboardOptions If you want to require an additional permission, you can pass it into the constructor as below: ```csharp -app.UseHangfireDashboard("/hangfire", new DashboardOptions +app.UseAbpHangfireDashboard("/hangfire", options => { - AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter(requiredPermissionName: "MyHangFireDashboardPermissionName") } + options.AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter(requiredPermissionName: "MyHangFireDashboardPermissionName") }; }); ``` -**Important**: `UseHangfireDashboard` should be called after the authentication and authorization middlewares in your `Startup` class (probably at the last line). Otherwise, +**Important**: `UseAbpHangfireDashboard` should be called after the authentication and authorization middlewares in your `Startup` class (probably at the last line). Otherwise, authorization will always fail! diff --git a/docs/en/Background-Workers-Hangfire.md b/docs/en/Background-Workers-Hangfire.md index 9506eb97a7..70c8d0cf95 100644 --- a/docs/en/Background-Workers-Hangfire.md +++ b/docs/en/Background-Workers-Hangfire.md @@ -70,7 +70,7 @@ After you have installed these NuGet packages, you need to configure your projec > You have to configure a storage for Hangfire. -2. If you want to use hangfire's dashboard, you can add `UseHangfireDashboard` call in the `OnApplicationInitialization` method in `Module` class +2. If you want to use hangfire's dashboard, you can add `UseAbpHangfireDashboard` call in the `OnApplicationInitialization` method in `Module` class ````csharp public override void OnApplicationInitialization(ApplicationInitializationContext context) @@ -79,7 +79,7 @@ After you have installed these NuGet packages, you need to configure your projec // ... others - app.UseHangfireDashboard(); //should add to the request pipeline before the app.UseConfiguredEndpoints() + app.UseAbpHangfireDashboard(); //should add to the request pipeline before the app.UseConfiguredEndpoints() app.UseConfiguredEndpoints(); } ```` diff --git a/docs/en/Modules/OpenIddict.md b/docs/en/Modules/OpenIddict.md index cb9d36a30c..20098eb975 100644 --- a/docs/en/Modules/OpenIddict.md +++ b/docs/en/Modules/OpenIddict.md @@ -471,7 +471,24 @@ In **Blazor wasm** applications, add `options.ProviderOptions.DefaultScopes.Add( In **Angular** applications, add `offline_access` to **oAuthConfig** scopes in *environment.ts* file. (Angular applications already have this configuration). +## About localization +We don't localize any error messages in the OpenIddict module, Because the OAuth 2.0 specification restricts the charset you're allowed to use for the error and error_description parameters: + +> A.7. "error" Syntax +> The "error" element is defined in Sections 4.1.2.1, 4.2.2.1, 5.2, 7.2, and 8.5: + +``` +error = 1*NQSCHAR +``` + +> A.8. "error_description" Syntax +>T he "error_description" element is defined in Sections 4.1.2.1, 4.2.2.1, 5.2, and 7.2: + +``` +error-description = 1*NQSCHAR +NQSCHAR = %x20-21 / %x23-5B / %x5D-7E +``` ## Demo projects diff --git a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Microsoft/AspNetCore/Builder/AbpHangfireApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Microsoft/AspNetCore/Builder/AbpHangfireApplicationBuilderExtensions.cs new file mode 100644 index 0000000000..1b49510517 --- /dev/null +++ b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Microsoft/AspNetCore/Builder/AbpHangfireApplicationBuilderExtensions.cs @@ -0,0 +1,20 @@ +using System; +using Hangfire; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.BackgroundJobs.Hangfire; + +namespace Microsoft.AspNetCore.Builder; + +public static class AbpHangfireApplicationBuilderExtensions +{ + public static IApplicationBuilder UseAbpHangfireDashboard( + this IApplicationBuilder app, + string pathMatch = "/hangfire", + Action? configure = null, + JobStorage? storage = null) + { + var options = app.ApplicationServices.GetRequiredService().Get(); + configure?.Invoke(options); + return app.UseHangfireDashboard(pathMatch, options, storage); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpDashboardOptionsProvider.cs b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpDashboardOptionsProvider.cs index bc41b21ce8..e68489290a 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpDashboardOptionsProvider.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpDashboardOptionsProvider.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Threading; using Hangfire; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; @@ -18,8 +19,16 @@ public class AbpDashboardOptionsProvider : ITransientDependency { return new DashboardOptions { - DisplayNameFunc = (dashboardContext, job) => - AbpBackgroundJobOptions.GetJob(job.Args.First().GetType()).JobName + DisplayNameFunc = (_, job) => + { + var jobName = job.ToString(); + if (job.Args.Count == 3 && job.Args.Last() is CancellationToken) + { + jobName = AbpBackgroundJobOptions.GetJob(job.Args[1].GetType()).JobName; + } + + return jobName; + } }; } } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml index aa5ecba592..137715804a 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml @@ -12,20 +12,28 @@ @L["Login"]
- @if (!Model.IsExternalLogin) + @if (!Model.IsExternalLogin && Model.EnableLocalRegister) { } + + @if(Model.EnableLocalRegister || Model.IsExternalLogin) + { + + } - - - @if (!Model.IsExternalLogin) + @if (!Model.IsExternalLogin && Model.EnableLocalRegister) { } -
- @L["Register"] -
+ + @if(Model.EnableLocalRegister || Model.IsExternalLogin) + { +
+ @L["Register"] +
+ } + @if (!Model.IsExternalLogin && Model.VisibleExternalProviders.Any()) diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs index 5836ec2123..7bc536ba9d 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs @@ -38,6 +38,9 @@ public class RegisterModel : AccountPageModel public IEnumerable ExternalProviders { get; set; } public IEnumerable VisibleExternalProviders => ExternalProviders.Where(x => !string.IsNullOrWhiteSpace(x.DisplayName)); + public bool EnableLocalRegister { get; set; } + public bool IsExternalLoginOnly => EnableLocalRegister == false && ExternalProviders?.Count() == 1; + public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null; protected IAuthenticationSchemeProvider SchemeProvider { get; } @@ -55,13 +58,20 @@ public class RegisterModel : AccountPageModel public virtual async Task OnGetAsync() { - if (!IsExternalLogin) + ExternalProviders = await GetExternalProviders(); + + if (!await CheckSelfRegistrationAsync()) { - await CheckSelfRegistrationAsync(); + if (IsExternalLoginOnly) + { + return await OnPostExternalLogin(ExternalLoginScheme); + } + + Alerts.Warning(L["SelfRegistrationDisabledMessage"]); } await TrySetEmailAsync(); - ExternalProviders = await GetExternalProviders(); + return Page(); } @@ -96,12 +106,12 @@ public class RegisterModel : AccountPageModel { try { - if (!IsExternalLogin) + ExternalProviders = await GetExternalProviders(); + + if (!await CheckSelfRegistrationAsync()) { - await CheckSelfRegistrationAsync(); + throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]); } - - ExternalProviders = await GetExternalProviders(); if (IsExternalLogin) { @@ -172,17 +182,27 @@ public class RegisterModel : AccountPageModel await SignInManager.SignInAsync(user, isPersistent: true, ExternalLoginAuthSchema); } - protected virtual async Task CheckSelfRegistrationAsync() + protected virtual async Task CheckSelfRegistrationAsync() { - if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled) || - !await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin)) + EnableLocalRegister = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin) && + await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled); + + if (IsExternalLogin) + { + return true; + } + + if (!EnableLocalRegister) { - throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]); + return false; } + + return true; } protected virtual async Task> GetExternalProviders() { + var schemes = await SchemeProvider.GetAllSchemesAsync(); return schemes @@ -194,6 +214,15 @@ public class RegisterModel : AccountPageModel }) .ToList(); } + + protected virtual async Task OnPostExternalLogin(string provider) + { + var redirectUrl = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { ReturnUrl, ReturnUrlHash }); + var properties = SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); + properties.Items["scheme"] = provider; + + return await Task.FromResult(Challenge(properties, provider)); + } public class PostInput {