@ -0,0 +1,3 @@ |
|||
## ABP Application Startup |
|||
|
|||
TODO |
|||
@ -0,0 +1,35 @@ |
|||
# Deploying Distributed / Microservice Solutions |
|||
|
|||
The ABP Framework is designed to consider distributed and microservice systems, where you have multiple applications and/or services communicating internally. All of its features are compatible with distributed scenarios. This document highlights some points you should care when you deploy your distributed or microservice solution. |
|||
|
|||
## Application Name & Instance Id |
|||
|
|||
ABP provides `IApplicationInfoAccessor` service that provides the following properties: |
|||
|
|||
* `ApplicationName`: A human-readable name for an application. It is a unique value for an application. |
|||
* `InstanceId`: A random (GUID) value generated by the ABP Framework each time you start the application. |
|||
|
|||
These values are used by the ABP Framework for several places to distinguish the application and the application instance (process) in the system. For example, [audit logging](../Audit-Logging.md) system saves the `ApplicationName` in each audit log record written by the related application, so you can understand which application has created the audit log entry. So, if your system consists of multiple applications saving audit logs to a single point, you should be sure that each application has a different `ApplicationName`. |
|||
|
|||
The `ApplicationName` property's value is set automatically from the **entry assembly's name** (generally, the project name in a .NET solution) by default, which is proper for most cases, since each application typically has a unique entry assembly name. |
|||
|
|||
There are two ways to set the application name to a different value. In this first approach, you can set the `ApplicationName` property in your application's [configuration](../Configuration.md). The easiest way is to add an `ApplicationName` field to your `appsettings.json` file: |
|||
|
|||
````json |
|||
{ |
|||
"ApplicationName": "Services.Ordering" |
|||
} |
|||
```` |
|||
|
|||
Alternatively, you can set `AbpApplicationCreationOptions.ApplicationName` while creating the ABP application. You can find the `AddApplication` or `AddApplicationAsync` call in your solution (typically in the `Program.cs` file), and set the `ApplicationName` option as shown below: |
|||
|
|||
````csharp |
|||
await builder.AddApplicationAsync<OrderingServiceHttpApiHostModule>(options => |
|||
{ |
|||
options.ApplicationName = "Services.Ordering"; |
|||
}); |
|||
```` |
|||
|
|||
|
|||
|
|||
s |
|||
@ -0,0 +1,82 @@ |
|||
using MyCompanyName.MyProjectName.Blazor.Menus; |
|||
using MyCompanyName.MyProjectName.Shared.Localization; |
|||
using MyCompanyName.MyProjectName.Shared.MultiTenancy; |
|||
using Volo.Abp.Account.Localization; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Identity.Blazor; |
|||
using Volo.Abp.SettingManagement.Blazor.Menus; |
|||
using Volo.Abp.TenantManagement.Blazor.Navigation; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Client.Menus; |
|||
|
|||
public class MyProjectNameMenuContributor : IMenuContributor |
|||
{ |
|||
private readonly IConfiguration _configuration; |
|||
|
|||
public MyProjectNameMenuContributor(IConfiguration configuration) |
|||
{ |
|||
_configuration = configuration; |
|||
} |
|||
|
|||
public async Task ConfigureMenuAsync(MenuConfigurationContext context) |
|||
{ |
|||
if (context.Menu.Name == StandardMenus.Main) |
|||
{ |
|||
await ConfigureMainMenuAsync(context); |
|||
} |
|||
else if (context.Menu.Name == StandardMenus.User) |
|||
{ |
|||
await ConfigureUserMenuAsync(context); |
|||
} |
|||
} |
|||
|
|||
private Task ConfigureMainMenuAsync(MenuConfigurationContext context) |
|||
{ |
|||
var l = context.GetLocalizer<MyProjectNameResource>(); |
|||
|
|||
context.Menu.Items.Insert( |
|||
0, |
|||
new ApplicationMenuItem( |
|||
MyProjectNameMenus.Home, |
|||
l["Menu:Home"], |
|||
"/", |
|||
icon: "fas fa-home", |
|||
order: 0 |
|||
) |
|||
); |
|||
|
|||
var administration = context.Menu.GetAdministration(); |
|||
|
|||
if (MultiTenancyConsts.IsEnabled) |
|||
{ |
|||
administration.SetSubItemOrder(TenantManagementMenuNames.GroupName, 1); |
|||
} |
|||
else |
|||
{ |
|||
administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName); |
|||
} |
|||
|
|||
administration.SetSubItemOrder(IdentityMenuNames.GroupName, 2); |
|||
administration.SetSubItemOrder(SettingManagementMenus.GroupName, 3); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
private Task ConfigureUserMenuAsync(MenuConfigurationContext context) |
|||
{ |
|||
var accountStringLocalizer = context.GetLocalizer<AccountResource>(); |
|||
|
|||
var authServerUrl = _configuration["AuthServer:Authority"] ?? ""; |
|||
|
|||
context.Menu.AddItem(new ApplicationMenuItem( |
|||
"Account.Manage", |
|||
accountStringLocalizer["MyAccount"], |
|||
$"{authServerUrl.EnsureEndsWith('/')}Account/Manage?returnUrl={_configuration["App:SelfUrl"]}", |
|||
icon: "fa fa-cog", |
|||
order: 1000, |
|||
null).RequireAuthenticated()); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace MyCompanyName.MyProjectName.Blazor.Menus; |
|||
|
|||
public class MyProjectNameMenus |
|||
{ |
|||
private const string Prefix = "MyProjectName"; |
|||
public const string Home = Prefix + ".Home"; |
|||
|
|||
//Add your menu items here...
|
|||
|
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Blazorise.Bootstrap5" Version="1.1.4.1" /> |
|||
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.1.4.1" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<!-- <TEMPLATE-REMOVE> --> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Components.Web.Theming\Volo.Abp.AspNetCore.Components.Web.Theming.csproj" /> |
|||
<!-- </TEMPLATE-REMOVE> --> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme" Version="2.0.0-*" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac.WebAssembly\Volo.Abp.Autofac.WebAssembly.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.Blazor.WebAssembly\Volo.Abp.Identity.Blazor.WebAssembly.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Blazor.WebAssembly\Volo.Abp.TenantManagement.Blazor.WebAssembly.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Blazor.WebAssembly\Volo.Abp.SettingManagement.Blazor.WebAssembly.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\account\src\Volo.Abp.Account.HttpApi.Client\Volo.Abp.Account.HttpApi.Client.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi.Client\Volo.Abp.Identity.HttpApi.Client.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi.Client\Volo.Abp.PermissionManagement.HttpApi.Client.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.HttpApi.Client\Volo.Abp.TenantManagement.HttpApi.Client.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.HttpApi.Client\Volo.Abp.FeatureManagement.HttpApi.Client.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.HttpApi.Client\Volo.Abp.SettingManagement.HttpApi.Client.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\openiddict\src\Volo.Abp.OpenIddict.Domain.Shared\Volo.Abp.OpenIddict.Domain.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Shared\MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,11 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Client; |
|||
|
|||
public class MyProjectNameBlazorAutoMapperProfile : Profile |
|||
{ |
|||
public MyProjectNameBlazorAutoMapperProfile() |
|||
{ |
|||
//Define your AutoMapper configuration here for the Blazor project.
|
|||
} |
|||
} |
|||
@ -0,0 +1,142 @@ |
|||
using Blazorise.Bootstrap5; |
|||
using Blazorise.Icons.FontAwesome; |
|||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
|||
using MyCompanyName.MyProjectName.Client.Menus; |
|||
using MyCompanyName.MyProjectName.Shared; |
|||
using OpenIddict.Abstractions; |
|||
using Volo.Abp.Account; |
|||
using Volo.Abp.AspNetCore.Components.Web.LeptonXLiteTheme.Themes.LeptonXLite; |
|||
using Volo.Abp.AspNetCore.Components.Web.Theming.Routing; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme; |
|||
using Volo.Abp.Autofac.WebAssembly; |
|||
using Volo.Abp.AutoMapper; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.Identity.Blazor.WebAssembly; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.OpenIddict; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.SettingManagement.Blazor.WebAssembly; |
|||
using Volo.Abp.TenantManagement; |
|||
using Volo.Abp.TenantManagement.Blazor.WebAssembly; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Client; |
|||
|
|||
[DependsOn( |
|||
typeof(MyProjectNameSharedModule), |
|||
|
|||
// ABP Framework packages
|
|||
typeof(AbpAutofacWebAssemblyModule), |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeModule), |
|||
|
|||
// Account module packages
|
|||
typeof(AbpAccountHttpApiClientModule), |
|||
|
|||
// Identity module packages
|
|||
typeof(AbpIdentityHttpApiClientModule), |
|||
typeof(AbpIdentityBlazorWebAssemblyModule), |
|||
typeof(AbpOpenIddictDomainSharedModule), |
|||
|
|||
// Permission Management module packages
|
|||
typeof(AbpPermissionManagementHttpApiClientModule), |
|||
|
|||
// Tenant Management module packages
|
|||
typeof(AbpTenantManagementHttpApiClientModule), |
|||
typeof(AbpTenantManagementBlazorWebAssemblyModule), |
|||
|
|||
// Feature Management module packages
|
|||
typeof(AbpFeatureManagementHttpApiClientModule), |
|||
|
|||
// Setting Management module packages
|
|||
typeof(AbpSettingManagementHttpApiClientModule), |
|||
typeof(AbpSettingManagementBlazorWebAssemblyModule) |
|||
)] |
|||
public class MyProjectNameBlazorModule : AbpModule |
|||
{ |
|||
public const string RemoteServiceName = "Default"; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var environment = context.Services.GetSingletonInstance<IWebAssemblyHostEnvironment>(); |
|||
var builder = context.Services.GetSingletonInstance<WebAssemblyHostBuilder>(); |
|||
|
|||
ConfigureAuthentication(builder); |
|||
ConfigureHttpClient(context, environment); |
|||
ConfigureBlazorise(context); |
|||
ConfigureRouter(context); |
|||
ConfigureUI(builder); |
|||
ConfigureMenu(context); |
|||
ConfigureAutoMapper(context); |
|||
ConfigureHttpClientProxies(context); |
|||
} |
|||
|
|||
private void ConfigureRouter(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpRouterOptions>(options => |
|||
{ |
|||
options.AppAssembly = typeof(MyProjectNameBlazorModule).Assembly; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureMenu(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpNavigationOptions>(options => |
|||
{ |
|||
options.MenuContributors.Add(new MyProjectNameMenuContributor(context.Services.GetConfiguration())); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureBlazorise(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services |
|||
.AddBootstrap5Providers() |
|||
.AddFontAwesomeIcons(); |
|||
} |
|||
|
|||
private void ConfigureHttpClientProxies(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddHttpClientProxies( |
|||
typeof(MyProjectNameSharedModule).Assembly, |
|||
RemoteServiceName |
|||
); |
|||
} |
|||
|
|||
private static void ConfigureAuthentication(WebAssemblyHostBuilder builder) |
|||
{ |
|||
builder.Services.AddOidcAuthentication(options => |
|||
{ |
|||
builder.Configuration.Bind("AuthServer", options.ProviderOptions); |
|||
options.UserOptions.NameClaim = OpenIddictConstants.Claims.Name; |
|||
options.UserOptions.RoleClaim = OpenIddictConstants.Claims.Role; |
|||
|
|||
options.ProviderOptions.DefaultScopes.Add("MyProjectName"); |
|||
options.ProviderOptions.DefaultScopes.Add("roles"); |
|||
options.ProviderOptions.DefaultScopes.Add("email"); |
|||
options.ProviderOptions.DefaultScopes.Add("phone"); |
|||
}); |
|||
} |
|||
|
|||
private static void ConfigureUI(WebAssemblyHostBuilder builder) |
|||
{ |
|||
builder.RootComponents.Add<App>("#ApplicationContainer"); |
|||
|
|||
} |
|||
|
|||
private static void ConfigureHttpClient(ServiceConfigurationContext context, IWebAssemblyHostEnvironment environment) |
|||
{ |
|||
context.Services.AddTransient(sp => new HttpClient |
|||
{ |
|||
BaseAddress = new Uri(environment.BaseAddress) |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureAutoMapper(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpAutoMapperOptions>(options => |
|||
{ |
|||
options.AddMaps<MyProjectNameBlazorModule>(); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Ui.Branding; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Client; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
public class MyProjectNameBrandingProvider : DefaultBrandingProvider |
|||
{ |
|||
public override string AppName => "MyProjectName"; |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using Volo.Abp.Bundling; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Client; |
|||
|
|||
/* Add your global styles/scripts here. |
|||
* See https://docs.abp.io/en/abp/latest/UI/Blazor/Global-Scripts-Styles to learn how to use it
|
|||
*/ |
|||
public class MyProjectNameBundleContributor : IBundleContributor |
|||
{ |
|||
public void AddScripts(BundleContext context) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public void AddStyles(BundleContext context) |
|||
{ |
|||
context.Add("main.css", true); |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using MyCompanyName.MyProjectName.Shared.Localization; |
|||
using Volo.Abp.AspNetCore.Components; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Client; |
|||
|
|||
public abstract class MyProjectNameComponentBase : AbpComponentBase |
|||
{ |
|||
protected MyProjectNameComponentBase() |
|||
{ |
|||
LocalizationResource = typeof(MyProjectNameResource); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
@page "/" |
|||
@inherits MyProjectNameComponentBase |
|||
<div class="container"> |
|||
<div class="card"> |
|||
<div class="card-header"> |
|||
<h5 class="card-title"> |
|||
@L["Welcome_Title"] |
|||
</h5> |
|||
</div> |
|||
<div class="card-body"> |
|||
@L["Welcome_Text"] |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="card mt-5"> |
|||
<div class="card-body"> |
|||
<div class="row"> |
|||
<div class="col-md-auto text-center"> |
|||
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3"> |
|||
</div> |
|||
<div class="col-md d-flex align-items-center"> |
|||
<div class="pe-0 pe-md-4"> |
|||
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small> |
|||
<h2 class="mb-4">Mastering ABP Framework</h2> |
|||
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p> |
|||
<div class="mb-4"> |
|||
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1"> |
|||
Buy on Amazon US |
|||
</a> |
|||
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1"> |
|||
Buy on PACKT |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,6 @@ |
|||
namespace MyCompanyName.MyProjectName.Client.Pages; |
|||
|
|||
public partial class Index |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1 @@ |
|||
/* Write here your styles for the Index page */ |
|||
@ -0,0 +1,22 @@ |
|||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Client; |
|||
|
|||
public class Program |
|||
{ |
|||
public async static Task Main(string[] args) |
|||
{ |
|||
var builder = WebAssemblyHostBuilder.CreateDefault(args); |
|||
|
|||
var application = await builder.AddApplicationAsync<MyProjectNameBlazorModule>(options => |
|||
{ |
|||
options.UseAutofac(); |
|||
}); |
|||
|
|||
var host = builder.Build(); |
|||
|
|||
await application.InitializeApplicationAsync(host.Services); |
|||
|
|||
await host.RunAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
{ |
|||
"iisSettings": { |
|||
"windowsAuthentication": false, |
|||
"anonymousAuthentication": true, |
|||
"iisExpress": { |
|||
"applicationUrl": "https://localhost:44300", |
|||
"sslPort": 44300 |
|||
} |
|||
}, |
|||
"profiles": { |
|||
"https": { |
|||
"commandName": "Project", |
|||
"dotnetRunMessages": true, |
|||
"launchBrowser": true, |
|||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|||
"applicationUrl": "https://localhost:44300", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
}, |
|||
"IIS Express": { |
|||
"commandName": "IISExpress", |
|||
"launchBrowser": true, |
|||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
@using System.Net.Http |
|||
@using Microsoft.AspNetCore.Authorization |
|||
@using Microsoft.AspNetCore.Components.Authorization |
|||
@using Microsoft.AspNetCore.Components.Forms |
|||
@using Microsoft.AspNetCore.Components.Routing |
|||
@using Microsoft.AspNetCore.Components.Web |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Http |
|||
@using Microsoft.JSInterop |
|||
@using Volo.Abp.AspNetCore.Components.Web |
|||
@using MyCompanyName.MyProjectName.Client |
|||
@using Blazorise |
|||
@using Blazorise.DataGrid |
|||
@using Volo.Abp.BlazoriseUI |
|||
@using Volo.Abp.BlazoriseUI.Components |
|||
@ -0,0 +1,24 @@ |
|||
{ |
|||
"App": { |
|||
"SelfUrl": "https://localhost:44300" |
|||
}, |
|||
"AuthServer": { |
|||
"Authority": "https://localhost:44300", |
|||
"ClientId": "MyProjectName_Blazor", |
|||
"ResponseType": "code" |
|||
}, |
|||
"RemoteServices": { |
|||
"Default": { |
|||
"BaseUrl": "https://localhost:44300" |
|||
} |
|||
}, |
|||
"AbpCli": { |
|||
"Bundle": { |
|||
"Mode": "BundleAndMinify", /* Options: None, Bundle, BundleAndMinify */ |
|||
"Name": "global", |
|||
"Parameters": { |
|||
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 38 KiB |
@ -0,0 +1,35 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
|
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
|||
<title>MyCompanyName.MyProjectName.Blazor</title> |
|||
<base href="/" /> |
|||
|
|||
<!--ABP:Styles--> |
|||
<link href="global.css?_v=638058527301625844" rel="stylesheet"/> |
|||
<link href="main.css" rel="stylesheet"/> |
|||
<!--/ABP:Styles--> |
|||
<link href="MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.styles.css" rel="stylesheet"/> |
|||
|
|||
<!-- <TEMPLATE-REMOVE IF-NOT='PWA'> --> |
|||
<link href="manifest.json" rel="manifest" /> |
|||
<link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" /> |
|||
<link rel="apple-touch-icon" sizes="192x192" href="icon-192.png" /> |
|||
<!-- </TEMPLATE-REMOVE> --> |
|||
</head> |
|||
|
|||
<body class="abp-application-layout bg-light"> |
|||
<div id="ApplicationContainer"> |
|||
<div class="spinner"> |
|||
<div class="double-bounce1"></div> |
|||
<div class="double-bounce2"></div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!--ABP:Scripts--> |
|||
<script src="global.js?_v=638058527305084060"></script> |
|||
<!--/ABP:Scripts--> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,57 @@ |
|||
/* Global styles for the MyProjectName application */ |
|||
|
|||
/* <TEMPLATE-REMOVE IF-NOT='LEPTONX'> */ |
|||
:root .lpx-brand-logo { |
|||
--lpx-logo: url('/images/logo/leptonx/logo-light.png'); |
|||
--lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); |
|||
} |
|||
/* </TEMPLATE-REMOVE> */ |
|||
|
|||
.spinner { |
|||
width: 40px; |
|||
height: 40px; |
|||
display: block; |
|||
position: fixed; |
|||
top: calc( 50% - ( 40px / 2) ); |
|||
right: calc( 50% - ( 40px / 2) ); |
|||
} |
|||
|
|||
.double-bounce1, .double-bounce2 { |
|||
width: 100%; |
|||
height: 100%; |
|||
border-radius: 50%; |
|||
background-color: #333; |
|||
opacity: 0.6; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
-webkit-animation: sk-bounce 2.0s infinite ease-in-out; |
|||
animation: sk-bounce 2.0s infinite ease-in-out; |
|||
} |
|||
|
|||
.double-bounce2 { |
|||
-webkit-animation-delay: -1.0s; |
|||
animation-delay: -1.0s; |
|||
} |
|||
|
|||
@-webkit-keyframes sk-bounce { |
|||
0%, 100% { |
|||
-webkit-transform: scale(0.0) |
|||
} |
|||
|
|||
50% { |
|||
-webkit-transform: scale(1.0) |
|||
} |
|||
} |
|||
|
|||
@keyframes sk-bounce { |
|||
0%, 100% { |
|||
transform: scale(0.0); |
|||
-webkit-transform: scale(0.0); |
|||
} |
|||
|
|||
50% { |
|||
transform: scale(1.0); |
|||
-webkit-transform: scale(1.0); |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
{ |
|||
"name": "MyProjectName", |
|||
"short_name": "MyCompanyName.MyProjectName", |
|||
"start_url": "./", |
|||
"display": "standalone", |
|||
"background_color": "#ffffff", |
|||
"theme_color": "#03173d", |
|||
"prefer_related_applications": false, |
|||
"icons": [ |
|||
{ |
|||
"src": "icon-512.png", |
|||
"type": "image/png", |
|||
"sizes": "512x512" |
|||
}, |
|||
{ |
|||
"src": "icon-192.png", |
|||
"type": "image/png", |
|||
"sizes": "192x192" |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
[ConnectionStringName("Default")] |
|||
public class MyProjectNameDbContext : AbpMongoDbContext |
|||
{ |
|||
/* Add mongo collections here. Example: |
|||
* public IMongoCollection<Question> Questions => Collection<Question>(); |
|||
*/ |
|||
|
|||
protected override void CreateModel(IMongoModelBuilder modelBuilder) |
|||
{ |
|||
base.CreateModel(modelBuilder); |
|||
|
|||
//builder.Entity<YourEntity>(b =>
|
|||
//{
|
|||
// //...
|
|||
//});
|
|||
} |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.TenantManagement; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
public class MyProjectNameDbMigrationService : ITransientDependency |
|||
{ |
|||
public ILogger<MyProjectNameDbMigrationService> Logger { get; set; } |
|||
|
|||
private readonly IDataSeeder _dataSeeder; |
|||
private readonly MyProjectNameMongoDbSchemaMigrator _dbSchemaMigrator; |
|||
private readonly ITenantRepository _tenantRepository; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
|
|||
public MyProjectNameDbMigrationService( |
|||
IDataSeeder dataSeeder, |
|||
MyProjectNameMongoDbSchemaMigrator dbSchemaMigrator, |
|||
ITenantRepository tenantRepository, |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
_dataSeeder = dataSeeder; |
|||
_dbSchemaMigrator = dbSchemaMigrator; |
|||
_tenantRepository = tenantRepository; |
|||
_currentTenant = currentTenant; |
|||
|
|||
Logger = NullLogger<MyProjectNameDbMigrationService>.Instance; |
|||
} |
|||
|
|||
public async Task MigrateAsync() |
|||
{ |
|||
Logger.LogInformation("Started database migrations..."); |
|||
|
|||
await MigrateDatabaseSchemaAsync(); |
|||
await SeedDataAsync(); |
|||
|
|||
Logger.LogInformation($"Successfully completed host database migrations."); |
|||
|
|||
var tenants = await _tenantRepository.GetListAsync(includeDetails: true); |
|||
|
|||
var migratedDatabaseSchemas = new HashSet<string>(); |
|||
foreach (var tenant in tenants) |
|||
{ |
|||
using (_currentTenant.Change(tenant.Id)) |
|||
{ |
|||
if (tenant.ConnectionStrings.Any()) |
|||
{ |
|||
var tenantConnectionStrings = tenant.ConnectionStrings |
|||
.Select(x => x.Value) |
|||
.ToList(); |
|||
|
|||
if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) |
|||
{ |
|||
await MigrateDatabaseSchemaAsync(tenant); |
|||
|
|||
migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); |
|||
} |
|||
} |
|||
|
|||
await SeedDataAsync(tenant); |
|||
} |
|||
|
|||
Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); |
|||
} |
|||
|
|||
Logger.LogInformation("Successfully completed all database migrations."); |
|||
Logger.LogInformation("You can safely end this process..."); |
|||
} |
|||
|
|||
private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null) |
|||
{ |
|||
Logger.LogInformation($"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); |
|||
await _dbSchemaMigrator.MigrateAsync(); |
|||
} |
|||
|
|||
private async Task SeedDataAsync(Tenant? tenant = null) |
|||
{ |
|||
Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); |
|||
|
|||
await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) |
|||
.WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) |
|||
.WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
using MongoDB.Driver; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MongoDB; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
public class MyProjectNameMongoDbSchemaMigrator : ITransientDependency |
|||
{ |
|||
private readonly IServiceProvider _serviceProvider; |
|||
|
|||
public MyProjectNameMongoDbSchemaMigrator(IServiceProvider serviceProvider) |
|||
{ |
|||
_serviceProvider = serviceProvider; |
|||
} |
|||
|
|||
public async Task MigrateAsync() |
|||
{ |
|||
var dbContexts = _serviceProvider.GetServices<IAbpMongoDbContext>(); |
|||
var connectionStringResolver = _serviceProvider.GetRequiredService<IConnectionStringResolver>(); |
|||
|
|||
foreach (var dbContext in dbContexts) |
|||
{ |
|||
var connectionString = |
|||
await connectionStringResolver.ResolveAsync( |
|||
ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType())); |
|||
var mongoUrl = new MongoUrl(connectionString); |
|||
var databaseName = mongoUrl.DatabaseName; |
|||
var client = new MongoClient(mongoUrl); |
|||
|
|||
if (databaseName.IsNullOrWhiteSpace()) |
|||
{ |
|||
databaseName = ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType()); |
|||
} |
|||
|
|||
(dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,308 @@ |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Localization; |
|||
using OpenIddict.Abstractions; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.OpenIddict.Applications; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
/* Creates initial data that is needed to property run the application |
|||
* and make client-to-server communication possible. |
|||
*/ |
|||
public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency |
|||
{ |
|||
private readonly IConfiguration _configuration; |
|||
private readonly IOpenIddictApplicationManager _applicationManager; |
|||
private readonly IOpenIddictScopeManager _scopeManager; |
|||
private readonly IPermissionDataSeeder _permissionDataSeeder; |
|||
private readonly IStringLocalizer<OpenIddictResponse> L; |
|||
|
|||
public OpenIddictDataSeedContributor( |
|||
IConfiguration configuration, |
|||
IOpenIddictApplicationManager applicationManager, |
|||
IOpenIddictScopeManager scopeManager, |
|||
IPermissionDataSeeder permissionDataSeeder, |
|||
IStringLocalizer<OpenIddictResponse> l) |
|||
{ |
|||
_configuration = configuration; |
|||
_applicationManager = applicationManager; |
|||
_scopeManager = scopeManager; |
|||
_permissionDataSeeder = permissionDataSeeder; |
|||
L = l; |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
public virtual async Task SeedAsync(DataSeedContext context) |
|||
{ |
|||
await CreateScopesAsync(); |
|||
await CreateApplicationsAsync(); |
|||
} |
|||
|
|||
private async Task CreateScopesAsync() |
|||
{ |
|||
if (await _scopeManager.FindByNameAsync("MyProjectName") == null) |
|||
{ |
|||
await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor |
|||
{ |
|||
Name = "MyProjectName", |
|||
DisplayName = "MyProjectName API", |
|||
Resources = |
|||
{ |
|||
"MyProjectName" |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private async Task CreateApplicationsAsync() |
|||
{ |
|||
var commonScopes = new List<string> |
|||
{ |
|||
OpenIddictConstants.Permissions.Scopes.Address, |
|||
OpenIddictConstants.Permissions.Scopes.Email, |
|||
OpenIddictConstants.Permissions.Scopes.Phone, |
|||
OpenIddictConstants.Permissions.Scopes.Profile, |
|||
OpenIddictConstants.Permissions.Scopes.Roles, |
|||
"MyProjectName" |
|||
}; |
|||
|
|||
var configurationSection = _configuration.GetSection("OpenIddict:Applications"); |
|||
|
|||
//Blazor Client
|
|||
var blazorClientId = configurationSection["MyProjectName_Blazor:ClientId"]; |
|||
if (!blazorClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
var blazorRootUrl = configurationSection["MyProjectName_Blazor:RootUrl"]?.TrimEnd('/'); |
|||
await CreateApplicationAsync( |
|||
name: blazorClientId!, |
|||
type: OpenIddictConstants.ClientTypes.Public, |
|||
consentType: OpenIddictConstants.ConsentTypes.Implicit, |
|||
displayName: "Blazor Application", |
|||
secret: null, |
|||
grantTypes: new List<string> |
|||
{ |
|||
OpenIddictConstants.GrantTypes.AuthorizationCode |
|||
}, |
|||
scopes: commonScopes, |
|||
redirectUri: $"{blazorRootUrl}/authentication/login-callback", |
|||
clientUri: blazorRootUrl, |
|||
postLogoutRedirectUri: $"{blazorRootUrl}/authentication/logout-callback" |
|||
); |
|||
} |
|||
|
|||
// Swagger Client
|
|||
var swaggerClientId = configurationSection["MyProjectName_Swagger:ClientId"]; |
|||
if (!swaggerClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
var swaggerRootUrl = configurationSection["MyProjectName_Swagger:RootUrl"]?.TrimEnd('/'); |
|||
|
|||
await CreateApplicationAsync( |
|||
name: swaggerClientId!, |
|||
type: OpenIddictConstants.ClientTypes.Public, |
|||
consentType: OpenIddictConstants.ConsentTypes.Implicit, |
|||
displayName: "Swagger Application", |
|||
secret: null, |
|||
grantTypes: new List<string> |
|||
{ |
|||
OpenIddictConstants.GrantTypes.AuthorizationCode, |
|||
}, |
|||
scopes: commonScopes, |
|||
redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html" |
|||
); |
|||
} |
|||
} |
|||
|
|||
private async Task CreateApplicationAsync( |
|||
[NotNull] string name, |
|||
[NotNull] string type, |
|||
[NotNull] string consentType, |
|||
string displayName, |
|||
string? secret, |
|||
List<string> grantTypes, |
|||
List<string> scopes, |
|||
string? clientUri = null, |
|||
string? redirectUri = null, |
|||
string? postLogoutRedirectUri = null, |
|||
List<string>? permissions = null) |
|||
{ |
|||
if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); |
|||
} |
|||
|
|||
if (!string.IsNullOrEmpty(name) && await _applicationManager.FindByClientIdAsync(name) != null) |
|||
{ |
|||
return; |
|||
//throw new BusinessException(L["TheClientIdentifierIsAlreadyTakenByAnotherApplication"]);
|
|||
} |
|||
|
|||
var client = await _applicationManager.FindByClientIdAsync(name); |
|||
if (client == null) |
|||
{ |
|||
var application = new AbpApplicationDescriptor |
|||
{ |
|||
ClientId = name, |
|||
Type = type, |
|||
ClientSecret = secret, |
|||
ConsentType = consentType, |
|||
DisplayName = displayName, |
|||
ClientUri = clientUri |
|||
}; |
|||
|
|||
Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); |
|||
Check.NotNullOrEmpty(scopes, nameof(scopes)); |
|||
|
|||
if (new [] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All(grantTypes.Contains)) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); |
|||
|
|||
if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); |
|||
} |
|||
} |
|||
|
|||
if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); |
|||
} |
|||
|
|||
foreach (var grantType in grantTypes) |
|||
{ |
|||
if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || grantType == OpenIddictConstants.GrantTypes.Implicit) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || |
|||
grantType == OpenIddictConstants.GrantTypes.ClientCredentials || |
|||
grantType == OpenIddictConstants.GrantTypes.Password || |
|||
grantType == OpenIddictConstants.GrantTypes.RefreshToken || |
|||
grantType == OpenIddictConstants.GrantTypes.DeviceCode) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.Implicit) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.Password) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.Implicit) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); |
|||
if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); |
|||
} |
|||
} |
|||
} |
|||
|
|||
var buildInScopes = new [] |
|||
{ |
|||
OpenIddictConstants.Permissions.Scopes.Address, |
|||
OpenIddictConstants.Permissions.Scopes.Email, |
|||
OpenIddictConstants.Permissions.Scopes.Phone, |
|||
OpenIddictConstants.Permissions.Scopes.Profile, |
|||
OpenIddictConstants.Permissions.Scopes.Roles |
|||
}; |
|||
|
|||
foreach (var scope in scopes) |
|||
{ |
|||
if (buildInScopes.Contains(scope)) |
|||
{ |
|||
application.Permissions.Add(scope); |
|||
} |
|||
else |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); |
|||
} |
|||
} |
|||
|
|||
if (redirectUri != null) |
|||
{ |
|||
if (!redirectUri.IsNullOrEmpty()) |
|||
{ |
|||
if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) |
|||
{ |
|||
throw new BusinessException(L["InvalidRedirectUri", redirectUri]); |
|||
} |
|||
|
|||
if (application.RedirectUris.All(x => x != uri)) |
|||
{ |
|||
application.RedirectUris.Add(uri); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (postLogoutRedirectUri != null) |
|||
{ |
|||
if (!postLogoutRedirectUri.IsNullOrEmpty()) |
|||
{ |
|||
if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) |
|||
{ |
|||
throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); |
|||
} |
|||
|
|||
if (application.PostLogoutRedirectUris.All(x => x != uri)) |
|||
{ |
|||
application.PostLogoutRedirectUris.Add(uri); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (permissions != null) |
|||
{ |
|||
await _permissionDataSeeder.SeedAsync( |
|||
ClientPermissionValueProvider.ProviderName, |
|||
name, |
|||
permissions, |
|||
null |
|||
); |
|||
} |
|||
|
|||
await _applicationManager.CreateAsync(application); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" /> |
|||
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Swashbuckle\Volo.Abp.Swashbuckle.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Authentication.JwtBearer\Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Serilog\Volo.Abp.AspNetCore.Serilog.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\account\src\Volo.Abp.Account.Application\Volo.Abp.Account.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\account\src\Volo.Abp.Account.HttpApi\Volo.Abp.Account.HttpApi.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\account\src\Volo.Abp.Account.Web.OpenIddict\Volo.Abp.Account.Web.OpenIddict.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.PermissionManagement.Domain.Identity\Volo.Abp.PermissionManagement.Domain.Identity.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi\Volo.Abp.Identity.HttpApi.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.MongoDB\Volo.Abp.Identity.MongoDB.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\openiddict\src\Volo.Abp.OpenIddict.MongoDB\Volo.Abp.OpenIddict.MongoDB.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\openiddict\src\Volo.Abp.PermissionManagement.Domain.OpenIddict\Volo.Abp.PermissionManagement.Domain.OpenIddict.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Application\Volo.Abp.PermissionManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.MongoDB\Volo.Abp.PermissionManagement.MongoDB.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Application\Volo.Abp.TenantManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.MongoDB\Volo.Abp.TenantManagement.MongoDB.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.HttpApi\Volo.Abp.TenantManagement.HttpApi.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Application\Volo.Abp.FeatureManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.MongoDB\Volo.Abp.FeatureManagement.MongoDB.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.HttpApi\Volo.Abp.FeatureManagement.HttpApi.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Application\Volo.Abp.SettingManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.MongoDB\Volo.Abp.SettingManagement.MongoDB.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.HttpApi\Volo.Abp.SettingManagement.HttpApi.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.MongoDB\Volo.Abp.AuditLogging.MongoDB.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<!-- <TEMPLATE-REMOVE> --> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
|||
<!-- </TEMPLATE-REMOVE> --> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="2.0.0-*" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="7.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Client\MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj" /> |
|||
<ProjectReference Include="..\Shared\MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Remove="Logs\**" /> |
|||
<Content Remove="Logs\**" /> |
|||
<EmbeddedResource Remove="Logs\**" /> |
|||
<None Remove="Logs\**" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,318 @@ |
|||
using Microsoft.AspNetCore.Cors; |
|||
using Microsoft.AspNetCore.DataProtection; |
|||
using Microsoft.AspNetCore.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.DependencyInjection.Extensions; |
|||
using Microsoft.OpenApi.Models; |
|||
using MyCompanyName.MyProjectName.Server.Data; |
|||
using MyCompanyName.MyProjectName.Shared.Localization; |
|||
using MyCompanyName.MyProjectName.Shared; |
|||
using MyCompanyName.MyProjectName.Shared.MultiTenancy; |
|||
using OpenIddict.Validation.AspNetCore; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Account; |
|||
using Volo.Abp.Account.Web; |
|||
using Volo.Abp.AspNetCore.MultiTenancy; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.Localization; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; |
|||
using Volo.Abp.AspNetCore.Serilog; |
|||
using Volo.Abp.AuditLogging.MongoDB; |
|||
using Volo.Abp.Autofac; |
|||
using Volo.Abp.AutoMapper; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.FeatureManagement.MongoDB; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.Identity.MongoDB; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.OpenIddict.MongoDB; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.PermissionManagement.MongoDB; |
|||
using Volo.Abp.PermissionManagement.HttpApi; |
|||
using Volo.Abp.PermissionManagement.Identity; |
|||
using Volo.Abp.PermissionManagement.OpenIddict; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.SettingManagement.MongoDB; |
|||
using Volo.Abp.Swashbuckle; |
|||
using Volo.Abp.TenantManagement; |
|||
using Volo.Abp.TenantManagement.MongoDB; |
|||
using Volo.Abp.UI.Navigation.Urls; |
|||
using Volo.Abp.Uow; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server; |
|||
|
|||
[DependsOn( |
|||
|
|||
typeof(MyProjectNameSharedModule), |
|||
|
|||
// ABP Framework packages
|
|||
typeof(AbpAspNetCoreMvcModule), |
|||
typeof(AbpAspNetCoreMultiTenancyModule), |
|||
typeof(AbpAutofacModule), |
|||
typeof(AbpAutoMapperModule), |
|||
typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), |
|||
typeof(AbpSwashbuckleModule), |
|||
typeof(AbpAspNetCoreSerilogModule), |
|||
|
|||
// Account module packages
|
|||
typeof(AbpAccountApplicationModule), |
|||
typeof(AbpAccountHttpApiModule), |
|||
typeof(AbpAccountWebOpenIddictModule), |
|||
|
|||
// Identity module packages
|
|||
typeof(AbpPermissionManagementDomainIdentityModule), |
|||
typeof(AbpPermissionManagementDomainOpenIddictModule), |
|||
typeof(AbpIdentityApplicationModule), |
|||
typeof(AbpIdentityHttpApiModule), |
|||
typeof(AbpIdentityMongoDbModule), |
|||
typeof(AbpOpenIddictMongoDbModule), |
|||
|
|||
// Audit logging module packages
|
|||
typeof(AbpAuditLoggingMongoDbModule), |
|||
|
|||
// Permission Management module packages
|
|||
typeof(AbpPermissionManagementApplicationModule), |
|||
typeof(AbpPermissionManagementHttpApiModule), |
|||
typeof(AbpPermissionManagementMongoDbModule), |
|||
|
|||
// Tenant Management module packages
|
|||
typeof(AbpTenantManagementApplicationModule), |
|||
typeof(AbpTenantManagementHttpApiModule), |
|||
typeof(AbpTenantManagementMongoDbModule), |
|||
|
|||
// Feature Management module packages
|
|||
typeof(AbpFeatureManagementApplicationModule), |
|||
typeof(AbpFeatureManagementMongoDbModule), |
|||
typeof(AbpFeatureManagementHttpApiModule), |
|||
|
|||
// Setting Management module packages
|
|||
typeof(AbpSettingManagementApplicationModule), |
|||
typeof(AbpSettingManagementMongoDbModule), |
|||
typeof(AbpSettingManagementHttpApiModule) |
|||
)] |
|||
public class MyProjectNameServerModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
|||
{ |
|||
options.AddAssemblyResource( |
|||
typeof(MyProjectNameResource) |
|||
); |
|||
}); |
|||
|
|||
PreConfigure<OpenIddictBuilder>(builder => |
|||
{ |
|||
builder.AddValidation(options => |
|||
{ |
|||
options.AddAudiences("MyProjectName"); |
|||
options.UseLocalServer(); |
|||
options.UseAspNetCore(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
if (hostingEnvironment.IsDevelopment()) |
|||
{ |
|||
context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>()); |
|||
} |
|||
|
|||
ConfigureAuthentication(context); |
|||
ConfigureBundles(); |
|||
ConfigureMultiTenancy(); |
|||
ConfigureUrls(configuration); |
|||
ConfigureAutoMapper(context); |
|||
ConfigureSwagger(context.Services, configuration); |
|||
ConfigureAutoApiControllers(); |
|||
ConfigureVirtualFiles(hostingEnvironment); |
|||
ConfigureCors(context, configuration); |
|||
ConfigureDataProtection(context); |
|||
ConfigureMongoDB(context); |
|||
} |
|||
|
|||
private void ConfigureAuthentication(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); |
|||
} |
|||
|
|||
private void ConfigureBundles() |
|||
{ |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.StyleBundles.Configure( |
|||
LeptonXLiteThemeBundles.Styles.Global, |
|||
bundle => { bundle.AddFiles("/global-styles.css"); } |
|||
); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureMultiTenancy() |
|||
{ |
|||
Configure<AbpMultiTenancyOptions>(options => |
|||
{ |
|||
options.IsEnabled = MultiTenancyConsts.IsEnabled; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureUrls(IConfiguration configuration) |
|||
{ |
|||
Configure<AppUrlOptions>(options => |
|||
{ |
|||
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; |
|||
options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty<string>()); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureVirtualFiles(IWebHostEnvironment hostingEnvironment) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<MyProjectNameServerModule>(); |
|||
if (hostingEnvironment.IsDevelopment()) |
|||
{ |
|||
/* Using physical files in development, so we don't need to recompile on changes */ |
|||
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameServerModule>(hostingEnvironment.ContentRootPath); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureAutoApiControllers() |
|||
{ |
|||
Configure<AbpAspNetCoreMvcOptions>(options => |
|||
{ |
|||
options.ConventionalControllers.Create(typeof(MyProjectNameServerModule).Assembly); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) |
|||
{ |
|||
services.AddAbpSwaggerGenWithOAuth( |
|||
configuration["AuthServer:Authority"], |
|||
new Dictionary<string, string> |
|||
{ |
|||
{"MyProjectName", "MyProjectName API"} |
|||
}, |
|||
options => |
|||
{ |
|||
options.SwaggerDoc("v1", new OpenApiInfo { Title = "MyProjectName API", Version = "v1" }); |
|||
options.DocInclusionPredicate((docName, description) => true); |
|||
options.CustomSchemaIds(type => type.FullName); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureAutoMapper(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAutoMapperObjectMapper<MyProjectNameServerModule>(); |
|||
Configure<AbpAutoMapperOptions>(options => |
|||
{ |
|||
/* Uncomment `validate: true` if you want to enable the Configuration Validation feature. |
|||
* See AutoMapper's documentation to learn what it is: |
|||
* https://docs.automapper.org/en/stable/Configuration-validation.html
|
|||
*/ |
|||
options.AddMaps<MyProjectNameServerModule>(/* validate: true */); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) |
|||
{ |
|||
context.Services.AddCors(options => |
|||
{ |
|||
options.AddDefaultPolicy(builder => |
|||
{ |
|||
builder |
|||
.WithOrigins( |
|||
configuration["App:CorsOrigins"]? |
|||
.Split(",", StringSplitOptions.RemoveEmptyEntries) |
|||
.Select(o => o.RemovePostFix("/")) |
|||
.ToArray() ?? Array.Empty<string>() |
|||
) |
|||
.WithAbpExposedHeaders() |
|||
.SetIsOriginAllowedToAllowWildcardSubdomains() |
|||
.AllowAnyHeader() |
|||
.AllowAnyMethod() |
|||
.AllowCredentials(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureDataProtection(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddDataProtection().SetApplicationName("MyProjectName"); |
|||
} |
|||
|
|||
private void ConfigureMongoDB(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddMongoDbContext<MyProjectNameDbContext>(options => |
|||
{ |
|||
options.AddDefaultRepositories(); |
|||
}); |
|||
|
|||
Configure<AbpUnitOfWorkDefaultOptions>(options => |
|||
{ |
|||
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; |
|||
}); |
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
var env = context.GetEnvironment(); |
|||
|
|||
if (env.IsDevelopment()) |
|||
{ |
|||
app.UseDeveloperExceptionPage(); |
|||
} |
|||
|
|||
app.UseAbpRequestLocalization(); |
|||
|
|||
if (!env.IsDevelopment()) |
|||
{ |
|||
app.UseErrorPage(); |
|||
} |
|||
|
|||
app.UseCorrelationId(); |
|||
app.UseBlazorFrameworkFiles(); |
|||
app.UseStaticFiles(); |
|||
app.UseRouting(); |
|||
app.UseCors(); |
|||
app.UseAuthentication(); |
|||
app.UseAbpOpenIddictValidation(); |
|||
|
|||
if (MultiTenancyConsts.IsEnabled) |
|||
{ |
|||
app.UseMultiTenancy(); |
|||
} |
|||
|
|||
app.UseUnitOfWork(); |
|||
app.UseAuthorization(); |
|||
|
|||
app.UseSwagger(); |
|||
app.UseAbpSwaggerUI(options => |
|||
{ |
|||
options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyProjectName API"); |
|||
|
|||
var configuration = context.GetConfiguration(); |
|||
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); |
|||
options.OAuthScopes("MyProjectName"); |
|||
}); |
|||
|
|||
app.UseAuditing(); |
|||
app.UseAbpSerilogEnrichers(); |
|||
app.UseConfiguredEndpoints(); |
|||
|
|||
if (app is WebApplication webApp) |
|||
{ |
|||
webApp.MapFallbackToFile("index.html"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.ObjectMapping; |
|||
|
|||
public class MyProjectNameAutoMapperProfile : Profile |
|||
{ |
|||
public MyProjectNameAutoMapperProfile() |
|||
{ |
|||
/* Create your AutoMapper object mappings here */ |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
using MyCompanyName.MyProjectName.Server; |
|||
using MyCompanyName.MyProjectName.Server.Data; |
|||
using Serilog; |
|||
using Serilog.Events; |
|||
using Volo.Abp.Data; |
|||
|
|||
public class Program |
|||
{ |
|||
public async static Task<int> Main(string[] args) |
|||
{ |
|||
//<TEMPLATE-REMOVE IF-NOT='dbms:PostgreSQL'>
|
|||
// https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic
|
|||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); |
|||
|
|||
//</TEMPLATE-REMOVE>
|
|||
var loggerConfiguration = new LoggerConfiguration() |
|||
#if DEBUG
|
|||
.MinimumLevel.Debug() |
|||
#else
|
|||
.MinimumLevel.Information() |
|||
#endif
|
|||
.MinimumLevel.Override("Microsoft", LogEventLevel.Information) |
|||
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) |
|||
.Enrich.FromLogContext() |
|||
.WriteTo.Async(c => c.File("Logs/logs.txt")) |
|||
.WriteTo.Async(c => c.Console()); |
|||
|
|||
if (IsMigrateDatabase(args)) |
|||
{ |
|||
loggerConfiguration.MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning); |
|||
loggerConfiguration.MinimumLevel.Override("Microsoft", LogEventLevel.Warning); |
|||
} |
|||
|
|||
Log.Logger = loggerConfiguration.CreateLogger(); |
|||
|
|||
try |
|||
{ |
|||
|
|||
var builder = WebApplication.CreateBuilder(args); |
|||
builder.Host.AddAppSettingsSecretsJson() |
|||
.UseAutofac() |
|||
.UseSerilog(); |
|||
await builder.AddApplicationAsync<MyProjectNameServerModule>(); |
|||
if (IsMigrateDatabase(args)) |
|||
{ |
|||
builder.Services.AddDataMigrationEnvironment(); |
|||
} |
|||
var app = builder.Build(); |
|||
await app.InitializeApplicationAsync(); |
|||
|
|||
if (IsMigrateDatabase(args)) |
|||
{ |
|||
await app.Services.GetRequiredService<MyProjectNameDbMigrationService>().MigrateAsync(); |
|||
return 0; |
|||
} |
|||
|
|||
Log.Information("Starting MyCompanyName.MyProjectName."); |
|||
await app.RunAsync(); |
|||
return 0; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
if (ex is HostAbortedException) |
|||
{ |
|||
throw; |
|||
} |
|||
|
|||
Log.Fatal(ex, "MyCompanyName.MyProjectName terminated unexpectedly!"); |
|||
return 1; |
|||
} |
|||
finally |
|||
{ |
|||
Log.CloseAndFlush(); |
|||
} |
|||
} |
|||
|
|||
private static bool IsMigrateDatabase(string[] args) |
|||
{ |
|||
return args.Any(x => x.Contains("--migrate-database", StringComparison.OrdinalIgnoreCase)); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
{ |
|||
"iisSettings": { |
|||
"windowsAuthentication": false, |
|||
"anonymousAuthentication": true, |
|||
"iisExpress": { |
|||
"applicationUrl": "https://localhost:44300", |
|||
"sslPort": 44300 |
|||
} |
|||
}, |
|||
"profiles": { |
|||
"https": { |
|||
"commandName": "Project", |
|||
"dotnetRunMessages": true, |
|||
"launchBrowser": true, |
|||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|||
"applicationUrl": "https://localhost:44300", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
}, |
|||
"IIS Express": { |
|||
"commandName": "IISExpress", |
|||
"launchBrowser": true, |
|||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
{ |
|||
"App": { |
|||
"SelfUrl": "https://localhost:44300", |
|||
"CorsOrigins": "https://*.MyProjectName.com,http://localhost:44300", |
|||
"RedirectAllowedUrls": "http://localhost:44300" |
|||
}, |
|||
"ConnectionStrings": { |
|||
"Default": "mongodb://localhost:27017/MyProjectName" |
|||
}, |
|||
"AuthServer": { |
|||
"Authority": "https://localhost:44300", |
|||
"RequireHttpsMetadata": "false", |
|||
"SwaggerClientId": "MyProjectName_Swagger", |
|||
"SwaggerClientSecret": "1q2w3e*" |
|||
}, |
|||
"StringEncryption": { |
|||
"DefaultPassPhrase": "gsKnGZ041HLL4IM8" |
|||
}, |
|||
"OpenIddict": { |
|||
"Applications": { |
|||
"MyProjectName_Blazor": { |
|||
"ClientId": "MyProjectName_Blazor", |
|||
"RootUrl": "https://localhost:44300" |
|||
}, |
|||
"MyProjectName_Swagger": { |
|||
"ClientId": "MyProjectName_Swagger", |
|||
"RootUrl": "https://localhost:44300" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"version": "1.0.0", |
|||
"name": "my-app", |
|||
"private": true, |
|||
"dependencies": { |
|||
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~2.0.0-rc.1" |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<location path="." inheritInChildApplications="false"> |
|||
<system.webServer> |
|||
<handlers> |
|||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> |
|||
</handlers> |
|||
<aspNetCore processPath="dotnet" arguments=".\MyCompanyName.MyProjectName.Server.dll" stdoutLogEnabled="false" stdoutLogFile=".\Logs\stdout" hostingModel="inprocess" /> |
|||
</system.webServer> |
|||
</location> |
|||
<system.webServer> |
|||
<httpProtocol> |
|||
<customHeaders> |
|||
<remove name="x-powered-by" /> |
|||
</customHeaders> |
|||
</httpProtocol> |
|||
</system.webServer> |
|||
</configuration> |
|||
@ -0,0 +1,8 @@ |
|||
/* Your Global Styles */ |
|||
|
|||
/* <TEMPLATE-REMOVE IF-NOT='LEPTONX'> */ |
|||
:root .lpx-brand-logo { |
|||
--lpx-logo: url('/images/logo/leptonx/logo-light.png'); |
|||
--lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); |
|||
} |
|||
/* </TEMPLATE-REMOVE> */ |
|||
@ -0,0 +1,36 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.AuditLogging.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.FeatureManagement.EntityFrameworkCore; |
|||
using Volo.Abp.Identity.EntityFrameworkCore; |
|||
using Volo.Abp.OpenIddict.EntityFrameworkCore; |
|||
using Volo.Abp.PermissionManagement.EntityFrameworkCore; |
|||
using Volo.Abp.SettingManagement.EntityFrameworkCore; |
|||
using Volo.Abp.TenantManagement.EntityFrameworkCore; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
public class MyProjectNameDbContext : AbpDbContext<MyProjectNameDbContext> |
|||
{ |
|||
public MyProjectNameDbContext(DbContextOptions<MyProjectNameDbContext> options) |
|||
: base(options) |
|||
{ |
|||
} |
|||
|
|||
protected override void OnModelCreating(ModelBuilder builder) |
|||
{ |
|||
base.OnModelCreating(builder); |
|||
|
|||
/* Include modules to your migration db context */ |
|||
|
|||
builder.ConfigurePermissionManagement(); |
|||
builder.ConfigureSettingManagement(); |
|||
builder.ConfigureAuditLogging(); |
|||
builder.ConfigureIdentity(); |
|||
builder.ConfigureOpenIddict(); |
|||
builder.ConfigureFeatureManagement(); |
|||
builder.ConfigureTenantManagement(); |
|||
|
|||
/* Configure your own entities here */ |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Design; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
public class MyProjectNameDbContextFactory : IDesignTimeDbContextFactory<MyProjectNameDbContext> |
|||
{ |
|||
public MyProjectNameDbContext CreateDbContext(string[] args) |
|||
{ |
|||
//<TEMPLATE-REMOVE IF-NOT='dbms:PostgreSQL'>
|
|||
// https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic
|
|||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); |
|||
//</TEMPLATE-REMOVE>
|
|||
|
|||
var configuration = BuildConfiguration(); |
|||
|
|||
var builder = new DbContextOptionsBuilder<MyProjectNameDbContext>() |
|||
.UseSqlServer(configuration.GetConnectionString("Default")); |
|||
|
|||
return new MyProjectNameDbContext(builder.Options); |
|||
} |
|||
|
|||
private static IConfigurationRoot BuildConfiguration() |
|||
{ |
|||
var builder = new ConfigurationBuilder() |
|||
.SetBasePath(Directory.GetCurrentDirectory()) |
|||
.AddJsonFile("appsettings.json", optional: false); |
|||
|
|||
return builder.Build(); |
|||
} |
|||
} |
|||
@ -0,0 +1,203 @@ |
|||
using System.Diagnostics; |
|||
using System.Runtime.InteropServices; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.TenantManagement; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
public class MyProjectNameDbMigrationService : ITransientDependency |
|||
{ |
|||
public ILogger<MyProjectNameDbMigrationService> Logger { get; set; } |
|||
|
|||
private readonly IDataSeeder _dataSeeder; |
|||
private readonly MyProjectNameEFCoreDbSchemaMigrator _dbSchemaMigrator; |
|||
private readonly ITenantRepository _tenantRepository; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
|
|||
public MyProjectNameDbMigrationService( |
|||
IDataSeeder dataSeeder, |
|||
MyProjectNameEFCoreDbSchemaMigrator dbSchemaMigrator, |
|||
ITenantRepository tenantRepository, |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
_dataSeeder = dataSeeder; |
|||
_dbSchemaMigrator = dbSchemaMigrator; |
|||
_tenantRepository = tenantRepository; |
|||
_currentTenant = currentTenant; |
|||
|
|||
Logger = NullLogger<MyProjectNameDbMigrationService>.Instance; |
|||
} |
|||
|
|||
public async Task MigrateAsync() |
|||
{ |
|||
var initialMigrationAdded = AddInitialMigrationIfNotExist(); |
|||
|
|||
if (initialMigrationAdded) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
Logger.LogInformation("Started database migrations..."); |
|||
|
|||
await MigrateDatabaseSchemaAsync(); |
|||
await SeedDataAsync(); |
|||
|
|||
Logger.LogInformation($"Successfully completed host database migrations."); |
|||
|
|||
var tenants = await _tenantRepository.GetListAsync(includeDetails: true); |
|||
|
|||
var migratedDatabaseSchemas = new HashSet<string>(); |
|||
foreach (var tenant in tenants) |
|||
{ |
|||
using (_currentTenant.Change(tenant.Id)) |
|||
{ |
|||
if (tenant.ConnectionStrings.Any()) |
|||
{ |
|||
var tenantConnectionStrings = tenant.ConnectionStrings |
|||
.Select(x => x.Value) |
|||
.ToList(); |
|||
|
|||
if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) |
|||
{ |
|||
await MigrateDatabaseSchemaAsync(tenant); |
|||
|
|||
migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); |
|||
} |
|||
} |
|||
|
|||
await SeedDataAsync(tenant); |
|||
} |
|||
|
|||
Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); |
|||
} |
|||
|
|||
Logger.LogInformation("Successfully completed all database migrations."); |
|||
Logger.LogInformation("You can safely end this process..."); |
|||
} |
|||
|
|||
private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null) |
|||
{ |
|||
Logger.LogInformation($"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); |
|||
await _dbSchemaMigrator.MigrateAsync(); |
|||
} |
|||
|
|||
private async Task SeedDataAsync(Tenant? tenant = null) |
|||
{ |
|||
Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); |
|||
|
|||
await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) |
|||
.WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) |
|||
.WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) |
|||
); |
|||
} |
|||
|
|||
private bool AddInitialMigrationIfNotExist() |
|||
{ |
|||
try |
|||
{ |
|||
if (!DbMigrationsProjectExists()) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
if (!MigrationsFolderExists()) |
|||
{ |
|||
AddInitialMigration(); |
|||
return true; |
|||
} |
|||
else |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
private bool DbMigrationsProjectExists() |
|||
{ |
|||
return Directory.Exists(GetEntityFrameworkCoreProjectFolderPath()); |
|||
} |
|||
|
|||
private bool MigrationsFolderExists() |
|||
{ |
|||
var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); |
|||
|
|||
return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations")); |
|||
} |
|||
|
|||
private void AddInitialMigration() |
|||
{ |
|||
Logger.LogInformation("Creating initial migration..."); |
|||
|
|||
string argumentPrefix; |
|||
string fileName; |
|||
|
|||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) |
|||
{ |
|||
argumentPrefix = "-c"; |
|||
fileName = "/bin/bash"; |
|||
} |
|||
else |
|||
{ |
|||
argumentPrefix = "/C"; |
|||
fileName = "cmd.exe"; |
|||
} |
|||
|
|||
var procStartInfo = new ProcessStartInfo(fileName, |
|||
$"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\" --nolayers\"" |
|||
); |
|||
|
|||
try |
|||
{ |
|||
Process.Start(procStartInfo); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
throw new Exception("Couldn't run ABP CLI..."); |
|||
} |
|||
} |
|||
|
|||
private string GetEntityFrameworkCoreProjectFolderPath() |
|||
{ |
|||
var slnDirectoryPath = GetSolutionDirectoryPath(); |
|||
|
|||
if (slnDirectoryPath == null) |
|||
{ |
|||
throw new Exception("Solution folder not found!"); |
|||
} |
|||
|
|||
return Path.Combine(slnDirectoryPath, "MyCompanyName.MyProjectName.Host"); |
|||
} |
|||
|
|||
private string? GetSolutionDirectoryPath() |
|||
{ |
|||
var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); |
|||
|
|||
while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null) |
|||
{ |
|||
currentDirectory = Directory.GetParent(currentDirectory.FullName); |
|||
|
|||
if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null) |
|||
{ |
|||
return currentDirectory.FullName; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
public class MyProjectNameEFCoreDbSchemaMigrator : ITransientDependency |
|||
{ |
|||
private readonly IServiceProvider _serviceProvider; |
|||
|
|||
public MyProjectNameEFCoreDbSchemaMigrator( |
|||
IServiceProvider serviceProvider) |
|||
{ |
|||
_serviceProvider = serviceProvider; |
|||
} |
|||
|
|||
public async Task MigrateAsync() |
|||
{ |
|||
/* We intentionally resolving the MyProjectNameDbContext |
|||
* from IServiceProvider (instead of directly injecting it) |
|||
* to properly get the connection string of the current tenant in the |
|||
* current scope. |
|||
*/ |
|||
|
|||
await _serviceProvider |
|||
.GetRequiredService<MyProjectNameDbContext>() |
|||
.Database |
|||
.MigrateAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,308 @@ |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Localization; |
|||
using OpenIddict.Abstractions; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.OpenIddict.Applications; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.Data; |
|||
|
|||
/* Creates initial data that is needed to property run the application |
|||
* and make client-to-server communication possible. |
|||
*/ |
|||
public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency |
|||
{ |
|||
private readonly IConfiguration _configuration; |
|||
private readonly IOpenIddictApplicationManager _applicationManager; |
|||
private readonly IOpenIddictScopeManager _scopeManager; |
|||
private readonly IPermissionDataSeeder _permissionDataSeeder; |
|||
private readonly IStringLocalizer<OpenIddictResponse> L; |
|||
|
|||
public OpenIddictDataSeedContributor( |
|||
IConfiguration configuration, |
|||
IOpenIddictApplicationManager applicationManager, |
|||
IOpenIddictScopeManager scopeManager, |
|||
IPermissionDataSeeder permissionDataSeeder, |
|||
IStringLocalizer<OpenIddictResponse> l) |
|||
{ |
|||
_configuration = configuration; |
|||
_applicationManager = applicationManager; |
|||
_scopeManager = scopeManager; |
|||
_permissionDataSeeder = permissionDataSeeder; |
|||
L = l; |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
public virtual async Task SeedAsync(DataSeedContext context) |
|||
{ |
|||
await CreateScopesAsync(); |
|||
await CreateApplicationsAsync(); |
|||
} |
|||
|
|||
private async Task CreateScopesAsync() |
|||
{ |
|||
if (await _scopeManager.FindByNameAsync("MyProjectName") == null) |
|||
{ |
|||
await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor |
|||
{ |
|||
Name = "MyProjectName", |
|||
DisplayName = "MyProjectName API", |
|||
Resources = |
|||
{ |
|||
"MyProjectName" |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private async Task CreateApplicationsAsync() |
|||
{ |
|||
var commonScopes = new List<string> |
|||
{ |
|||
OpenIddictConstants.Permissions.Scopes.Address, |
|||
OpenIddictConstants.Permissions.Scopes.Email, |
|||
OpenIddictConstants.Permissions.Scopes.Phone, |
|||
OpenIddictConstants.Permissions.Scopes.Profile, |
|||
OpenIddictConstants.Permissions.Scopes.Roles, |
|||
"MyProjectName" |
|||
}; |
|||
|
|||
var configurationSection = _configuration.GetSection("OpenIddict:Applications"); |
|||
|
|||
//Blazor Client
|
|||
var blazorClientId = configurationSection["MyProjectName_Blazor:ClientId"]; |
|||
if (!blazorClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
var blazorRootUrl = configurationSection["MyProjectName_Blazor:RootUrl"]?.TrimEnd('/'); |
|||
await CreateApplicationAsync( |
|||
name: blazorClientId!, |
|||
type: OpenIddictConstants.ClientTypes.Public, |
|||
consentType: OpenIddictConstants.ConsentTypes.Implicit, |
|||
displayName: "Blazor Application", |
|||
secret: null, |
|||
grantTypes: new List<string> |
|||
{ |
|||
OpenIddictConstants.GrantTypes.AuthorizationCode |
|||
}, |
|||
scopes: commonScopes, |
|||
redirectUri: $"{blazorRootUrl}/authentication/login-callback", |
|||
clientUri: blazorRootUrl, |
|||
postLogoutRedirectUri: $"{blazorRootUrl}/authentication/logout-callback" |
|||
); |
|||
} |
|||
|
|||
// Swagger Client
|
|||
var swaggerClientId = configurationSection["MyProjectName_Swagger:ClientId"]; |
|||
if (!swaggerClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
var swaggerRootUrl = configurationSection["MyProjectName_Swagger:RootUrl"]?.TrimEnd('/'); |
|||
|
|||
await CreateApplicationAsync( |
|||
name: swaggerClientId!, |
|||
type: OpenIddictConstants.ClientTypes.Public, |
|||
consentType: OpenIddictConstants.ConsentTypes.Implicit, |
|||
displayName: "Swagger Application", |
|||
secret: null, |
|||
grantTypes: new List<string> |
|||
{ |
|||
OpenIddictConstants.GrantTypes.AuthorizationCode, |
|||
}, |
|||
scopes: commonScopes, |
|||
redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html" |
|||
); |
|||
} |
|||
} |
|||
|
|||
private async Task CreateApplicationAsync( |
|||
[NotNull] string name, |
|||
[NotNull] string type, |
|||
[NotNull] string consentType, |
|||
string displayName, |
|||
string? secret, |
|||
List<string> grantTypes, |
|||
List<string> scopes, |
|||
string? clientUri = null, |
|||
string? redirectUri = null, |
|||
string? postLogoutRedirectUri = null, |
|||
List<string>? permissions = null) |
|||
{ |
|||
if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); |
|||
} |
|||
|
|||
if (!string.IsNullOrEmpty(name) && await _applicationManager.FindByClientIdAsync(name) != null) |
|||
{ |
|||
return; |
|||
//throw new BusinessException(L["TheClientIdentifierIsAlreadyTakenByAnotherApplication"]);
|
|||
} |
|||
|
|||
var client = await _applicationManager.FindByClientIdAsync(name); |
|||
if (client == null) |
|||
{ |
|||
var application = new AbpApplicationDescriptor |
|||
{ |
|||
ClientId = name, |
|||
Type = type, |
|||
ClientSecret = secret, |
|||
ConsentType = consentType, |
|||
DisplayName = displayName, |
|||
ClientUri = clientUri |
|||
}; |
|||
|
|||
Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); |
|||
Check.NotNullOrEmpty(scopes, nameof(scopes)); |
|||
|
|||
if (new [] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All(grantTypes.Contains)) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); |
|||
|
|||
if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); |
|||
} |
|||
} |
|||
|
|||
if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); |
|||
} |
|||
|
|||
foreach (var grantType in grantTypes) |
|||
{ |
|||
if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || grantType == OpenIddictConstants.GrantTypes.Implicit) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || |
|||
grantType == OpenIddictConstants.GrantTypes.ClientCredentials || |
|||
grantType == OpenIddictConstants.GrantTypes.Password || |
|||
grantType == OpenIddictConstants.GrantTypes.RefreshToken || |
|||
grantType == OpenIddictConstants.GrantTypes.DeviceCode) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.Implicit) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.Password) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); |
|||
} |
|||
|
|||
if (grantType == OpenIddictConstants.GrantTypes.Implicit) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); |
|||
if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); |
|||
} |
|||
} |
|||
} |
|||
|
|||
var buildInScopes = new [] |
|||
{ |
|||
OpenIddictConstants.Permissions.Scopes.Address, |
|||
OpenIddictConstants.Permissions.Scopes.Email, |
|||
OpenIddictConstants.Permissions.Scopes.Phone, |
|||
OpenIddictConstants.Permissions.Scopes.Profile, |
|||
OpenIddictConstants.Permissions.Scopes.Roles |
|||
}; |
|||
|
|||
foreach (var scope in scopes) |
|||
{ |
|||
if (buildInScopes.Contains(scope)) |
|||
{ |
|||
application.Permissions.Add(scope); |
|||
} |
|||
else |
|||
{ |
|||
application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); |
|||
} |
|||
} |
|||
|
|||
if (redirectUri != null) |
|||
{ |
|||
if (!redirectUri.IsNullOrEmpty()) |
|||
{ |
|||
if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) |
|||
{ |
|||
throw new BusinessException(L["InvalidRedirectUri", redirectUri]); |
|||
} |
|||
|
|||
if (application.RedirectUris.All(x => x != uri)) |
|||
{ |
|||
application.RedirectUris.Add(uri); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (postLogoutRedirectUri != null) |
|||
{ |
|||
if (!postLogoutRedirectUri.IsNullOrEmpty()) |
|||
{ |
|||
if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) |
|||
{ |
|||
throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); |
|||
} |
|||
|
|||
if (application.PostLogoutRedirectUris.All(x => x != uri)) |
|||
{ |
|||
application.PostLogoutRedirectUris.Add(uri); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (permissions != null) |
|||
{ |
|||
await _permissionDataSeeder.SeedAsync( |
|||
ClientPermissionValueProvider.ProviderName, |
|||
name, |
|||
permissions, |
|||
null |
|||
); |
|||
} |
|||
|
|||
await _applicationManager.CreateAsync(application); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,107 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" /> |
|||
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Swashbuckle\Volo.Abp.Swashbuckle.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Authentication.JwtBearer\Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Serilog\Volo.Abp.AspNetCore.Serilog.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.EntityFrameworkCore.SqlServer\Volo.Abp.EntityFrameworkCore.SqlServer.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\account\src\Volo.Abp.Account.Application\Volo.Abp.Account.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\account\src\Volo.Abp.Account.HttpApi\Volo.Abp.Account.HttpApi.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\account\src\Volo.Abp.Account.Web.OpenIddict\Volo.Abp.Account.Web.OpenIddict.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.PermissionManagement.Domain.Identity\Volo.Abp.PermissionManagement.Domain.Identity.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi\Volo.Abp.Identity.HttpApi.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\openiddict\src\Volo.Abp.OpenIddict.EntityFrameworkCore\Volo.Abp.OpenIddict.EntityFrameworkCore.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\openiddict\src\Volo.Abp.PermissionManagement.Domain.OpenIddict\Volo.Abp.PermissionManagement.Domain.OpenIddict.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Application\Volo.Abp.PermissionManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.EntityFrameworkCore\Volo.Abp.PermissionManagement.EntityFrameworkCore.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Application\Volo.Abp.TenantManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.EntityFrameworkCore\Volo.Abp.TenantManagement.EntityFrameworkCore.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.HttpApi\Volo.Abp.TenantManagement.HttpApi.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Application\Volo.Abp.FeatureManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.EntityFrameworkCore\Volo.Abp.FeatureManagement.EntityFrameworkCore.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.HttpApi\Volo.Abp.FeatureManagement.HttpApi.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Application\Volo.Abp.SettingManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.EntityFrameworkCore\Volo.Abp.SettingManagement.EntityFrameworkCore.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.HttpApi\Volo.Abp.SettingManagement.HttpApi.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.EntityFrameworkCore\Volo.Abp.AuditLogging.EntityFrameworkCore.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<!-- <TEMPLATE-REMOVE> --> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
|||
<!-- </TEMPLATE-REMOVE> --> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="2.0.0-*" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="7.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0"> |
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> |
|||
<PrivateAssets>compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native</PrivateAssets> |
|||
</PackageReference> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Client\MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj" /> |
|||
<ProjectReference Include="..\Shared\MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Remove="Logs\**" /> |
|||
<Content Remove="Logs\**" /> |
|||
<EmbeddedResource Remove="Logs\**" /> |
|||
<None Remove="Logs\**" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,335 @@ |
|||
using Microsoft.AspNetCore.Cors; |
|||
using Microsoft.AspNetCore.DataProtection; |
|||
using Microsoft.AspNetCore.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.DependencyInjection.Extensions; |
|||
using Microsoft.OpenApi.Models; |
|||
using MyCompanyName.MyProjectName.Server.Data; |
|||
using MyCompanyName.MyProjectName.Shared.Localization; |
|||
using MyCompanyName.MyProjectName.Shared; |
|||
using MyCompanyName.MyProjectName.Shared.MultiTenancy; |
|||
using OpenIddict.Validation.AspNetCore; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Account; |
|||
using Volo.Abp.Account.Web; |
|||
using Volo.Abp.AspNetCore.MultiTenancy; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.Localization; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; |
|||
using Volo.Abp.AspNetCore.Serilog; |
|||
using Volo.Abp.AuditLogging.EntityFrameworkCore; |
|||
using Volo.Abp.Autofac; |
|||
using Volo.Abp.AutoMapper; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore.SqlServer; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.FeatureManagement.EntityFrameworkCore; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.Identity.EntityFrameworkCore; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.OpenIddict.EntityFrameworkCore; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.PermissionManagement.EntityFrameworkCore; |
|||
using Volo.Abp.PermissionManagement.HttpApi; |
|||
using Volo.Abp.PermissionManagement.Identity; |
|||
using Volo.Abp.PermissionManagement.OpenIddict; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.SettingManagement.EntityFrameworkCore; |
|||
using Volo.Abp.Swashbuckle; |
|||
using Volo.Abp.TenantManagement; |
|||
using Volo.Abp.TenantManagement.EntityFrameworkCore; |
|||
using Volo.Abp.UI.Navigation.Urls; |
|||
using Volo.Abp.Uow; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server; |
|||
|
|||
[DependsOn( |
|||
|
|||
typeof(MyProjectNameSharedModule), |
|||
|
|||
// ABP Framework packages
|
|||
typeof(AbpAspNetCoreMvcModule), |
|||
typeof(AbpAspNetCoreMultiTenancyModule), |
|||
typeof(AbpAutofacModule), |
|||
typeof(AbpAutoMapperModule), |
|||
typeof(AbpEntityFrameworkCoreSqlServerModule), |
|||
typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), |
|||
typeof(AbpSwashbuckleModule), |
|||
typeof(AbpAspNetCoreSerilogModule), |
|||
|
|||
// Account module packages
|
|||
typeof(AbpAccountApplicationModule), |
|||
typeof(AbpAccountHttpApiModule), |
|||
typeof(AbpAccountWebOpenIddictModule), |
|||
|
|||
// Identity module packages
|
|||
typeof(AbpPermissionManagementDomainIdentityModule), |
|||
typeof(AbpPermissionManagementDomainOpenIddictModule), |
|||
typeof(AbpIdentityApplicationModule), |
|||
typeof(AbpIdentityHttpApiModule), |
|||
typeof(AbpIdentityEntityFrameworkCoreModule), |
|||
typeof(AbpOpenIddictEntityFrameworkCoreModule), |
|||
|
|||
// Audit logging module packages
|
|||
typeof(AbpAuditLoggingEntityFrameworkCoreModule), |
|||
|
|||
// Permission Management module packages
|
|||
typeof(AbpPermissionManagementApplicationModule), |
|||
typeof(AbpPermissionManagementHttpApiModule), |
|||
typeof(AbpPermissionManagementEntityFrameworkCoreModule), |
|||
|
|||
// Tenant Management module packages
|
|||
typeof(AbpTenantManagementApplicationModule), |
|||
typeof(AbpTenantManagementHttpApiModule), |
|||
typeof(AbpTenantManagementEntityFrameworkCoreModule), |
|||
|
|||
// Feature Management module packages
|
|||
typeof(AbpFeatureManagementApplicationModule), |
|||
typeof(AbpFeatureManagementEntityFrameworkCoreModule), |
|||
typeof(AbpFeatureManagementHttpApiModule), |
|||
|
|||
// Setting Management module packages
|
|||
typeof(AbpSettingManagementApplicationModule), |
|||
typeof(AbpSettingManagementEntityFrameworkCoreModule), |
|||
typeof(AbpSettingManagementHttpApiModule) |
|||
)] |
|||
public class MyProjectNameServerModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
|||
{ |
|||
options.AddAssemblyResource( |
|||
typeof(MyProjectNameResource) |
|||
); |
|||
}); |
|||
|
|||
PreConfigure<OpenIddictBuilder>(builder => |
|||
{ |
|||
builder.AddValidation(options => |
|||
{ |
|||
options.AddAudiences("MyProjectName"); |
|||
options.UseLocalServer(); |
|||
options.UseAspNetCore(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
if (hostingEnvironment.IsDevelopment()) |
|||
{ |
|||
context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>()); |
|||
} |
|||
|
|||
ConfigureAuthentication(context); |
|||
ConfigureBundles(); |
|||
ConfigureMultiTenancy(); |
|||
ConfigureUrls(configuration); |
|||
ConfigureAutoMapper(context); |
|||
ConfigureSwagger(context.Services, configuration); |
|||
ConfigureAutoApiControllers(); |
|||
ConfigureVirtualFiles(hostingEnvironment); |
|||
ConfigureCors(context, configuration); |
|||
ConfigureDataProtection(context); |
|||
ConfigureEfCore(context); |
|||
} |
|||
|
|||
private void ConfigureAuthentication(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); |
|||
} |
|||
|
|||
private void ConfigureBundles() |
|||
{ |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.StyleBundles.Configure( |
|||
LeptonXLiteThemeBundles.Styles.Global, |
|||
bundle => { bundle.AddFiles("/global-styles.css"); } |
|||
); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureMultiTenancy() |
|||
{ |
|||
Configure<AbpMultiTenancyOptions>(options => |
|||
{ |
|||
options.IsEnabled = MultiTenancyConsts.IsEnabled; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureUrls(IConfiguration configuration) |
|||
{ |
|||
Configure<AppUrlOptions>(options => |
|||
{ |
|||
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; |
|||
options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty<string>()); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureVirtualFiles(IWebHostEnvironment hostingEnvironment) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<MyProjectNameServerModule>(); |
|||
if (hostingEnvironment.IsDevelopment()) |
|||
{ |
|||
/* Using physical files in development, so we don't need to recompile on changes */ |
|||
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameServerModule>(hostingEnvironment.ContentRootPath); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureAutoApiControllers() |
|||
{ |
|||
Configure<AbpAspNetCoreMvcOptions>(options => |
|||
{ |
|||
options.ConventionalControllers.Create(typeof(MyProjectNameServerModule).Assembly); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) |
|||
{ |
|||
services.AddAbpSwaggerGenWithOAuth( |
|||
configuration["AuthServer:Authority"], |
|||
new Dictionary<string, string> |
|||
{ |
|||
{"MyProjectName", "MyProjectName API"} |
|||
}, |
|||
options => |
|||
{ |
|||
options.SwaggerDoc("v1", new OpenApiInfo { Title = "MyProjectName API", Version = "v1" }); |
|||
options.DocInclusionPredicate((docName, description) => true); |
|||
options.CustomSchemaIds(type => type.FullName); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureAutoMapper(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAutoMapperObjectMapper<MyProjectNameServerModule>(); |
|||
Configure<AbpAutoMapperOptions>(options => |
|||
{ |
|||
/* Uncomment `validate: true` if you want to enable the Configuration Validation feature. |
|||
* See AutoMapper's documentation to learn what it is: |
|||
* https://docs.automapper.org/en/stable/Configuration-validation.html
|
|||
*/ |
|||
options.AddMaps<MyProjectNameServerModule>(/* validate: true */); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) |
|||
{ |
|||
context.Services.AddCors(options => |
|||
{ |
|||
options.AddDefaultPolicy(builder => |
|||
{ |
|||
builder |
|||
.WithOrigins( |
|||
configuration["App:CorsOrigins"]? |
|||
.Split(",", StringSplitOptions.RemoveEmptyEntries) |
|||
.Select(o => o.RemovePostFix("/")) |
|||
.ToArray() ?? Array.Empty<string>() |
|||
) |
|||
.WithAbpExposedHeaders() |
|||
.SetIsOriginAllowedToAllowWildcardSubdomains() |
|||
.AllowAnyHeader() |
|||
.AllowAnyMethod() |
|||
.AllowCredentials(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureDataProtection(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddDataProtection().SetApplicationName("MyProjectName"); |
|||
} |
|||
|
|||
private void ConfigureEfCore(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAbpDbContext<MyProjectNameDbContext>(options => |
|||
{ |
|||
/* You can remove "includeAllEntities: true" to create |
|||
* default repositories only for aggregate roots |
|||
* Documentation: https://docs.abp.io/en/abp/latest/Entity-Framework-Core#add-default-repositories
|
|||
*/ |
|||
options.AddDefaultRepositories(includeAllEntities: true); |
|||
}); |
|||
|
|||
Configure<AbpDbContextOptions>(options => |
|||
{ |
|||
options.Configure(configurationContext => |
|||
{ |
|||
configurationContext.UseSqlServer(); |
|||
}); |
|||
}); |
|||
|
|||
//<TEMPLATE-REMOVE IF-NOT='dbms:SQLite'>
|
|||
Configure<AbpUnitOfWorkDefaultOptions>(options => |
|||
{ |
|||
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; |
|||
}); |
|||
//</TEMPLATE-REMOVE>
|
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
var env = context.GetEnvironment(); |
|||
|
|||
if (env.IsDevelopment()) |
|||
{ |
|||
app.UseDeveloperExceptionPage(); |
|||
} |
|||
|
|||
app.UseAbpRequestLocalization(); |
|||
|
|||
if (!env.IsDevelopment()) |
|||
{ |
|||
app.UseErrorPage(); |
|||
} |
|||
|
|||
app.UseCorrelationId(); |
|||
app.UseBlazorFrameworkFiles(); |
|||
app.UseStaticFiles(); |
|||
app.UseRouting(); |
|||
app.UseCors(); |
|||
app.UseAuthentication(); |
|||
app.UseAbpOpenIddictValidation(); |
|||
|
|||
if (MultiTenancyConsts.IsEnabled) |
|||
{ |
|||
app.UseMultiTenancy(); |
|||
} |
|||
|
|||
app.UseUnitOfWork(); |
|||
app.UseAuthorization(); |
|||
|
|||
app.UseSwagger(); |
|||
app.UseAbpSwaggerUI(options => |
|||
{ |
|||
options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyProjectName API"); |
|||
|
|||
var configuration = context.GetConfiguration(); |
|||
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); |
|||
options.OAuthScopes("MyProjectName"); |
|||
}); |
|||
|
|||
app.UseAuditing(); |
|||
app.UseAbpSerilogEnrichers(); |
|||
app.UseConfiguredEndpoints(); |
|||
|
|||
if (app is WebApplication webApp) |
|||
{ |
|||
webApp.MapFallbackToFile("index.html"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Server.ObjectMapping; |
|||
|
|||
public class MyProjectNameAutoMapperProfile : Profile |
|||
{ |
|||
public MyProjectNameAutoMapperProfile() |
|||
{ |
|||
/* Create your AutoMapper object mappings here */ |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
using MyCompanyName.MyProjectName.Server; |
|||
using MyCompanyName.MyProjectName.Server.Data; |
|||
using Serilog; |
|||
using Serilog.Events; |
|||
using Volo.Abp.Data; |
|||
|
|||
public class Program |
|||
{ |
|||
public async static Task<int> Main(string[] args) |
|||
{ |
|||
//<TEMPLATE-REMOVE IF-NOT='dbms:PostgreSQL'>
|
|||
// https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic
|
|||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); |
|||
|
|||
//</TEMPLATE-REMOVE>
|
|||
var loggerConfiguration = new LoggerConfiguration() |
|||
#if DEBUG
|
|||
.MinimumLevel.Debug() |
|||
#else
|
|||
.MinimumLevel.Information() |
|||
#endif
|
|||
.MinimumLevel.Override("Microsoft", LogEventLevel.Information) |
|||
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) |
|||
.Enrich.FromLogContext() |
|||
.WriteTo.Async(c => c.File("Logs/logs.txt")) |
|||
.WriteTo.Async(c => c.Console()); |
|||
|
|||
if (IsMigrateDatabase(args)) |
|||
{ |
|||
loggerConfiguration.MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning); |
|||
loggerConfiguration.MinimumLevel.Override("Microsoft", LogEventLevel.Warning); |
|||
} |
|||
|
|||
Log.Logger = loggerConfiguration.CreateLogger(); |
|||
|
|||
try |
|||
{ |
|||
|
|||
var builder = WebApplication.CreateBuilder(args); |
|||
builder.Host.AddAppSettingsSecretsJson() |
|||
.UseAutofac() |
|||
.UseSerilog(); |
|||
await builder.AddApplicationAsync<MyProjectNameServerModule>(); |
|||
if (IsMigrateDatabase(args)) |
|||
{ |
|||
builder.Services.AddDataMigrationEnvironment(); |
|||
} |
|||
var app = builder.Build(); |
|||
await app.InitializeApplicationAsync(); |
|||
|
|||
if (IsMigrateDatabase(args)) |
|||
{ |
|||
await app.Services.GetRequiredService<MyProjectNameDbMigrationService>().MigrateAsync(); |
|||
return 0; |
|||
} |
|||
|
|||
Log.Information("Starting MyCompanyName.MyProjectName."); |
|||
await app.RunAsync(); |
|||
return 0; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
if (ex is HostAbortedException) |
|||
{ |
|||
throw; |
|||
} |
|||
|
|||
Log.Fatal(ex, "MyCompanyName.MyProjectName terminated unexpectedly!"); |
|||
return 1; |
|||
} |
|||
finally |
|||
{ |
|||
Log.CloseAndFlush(); |
|||
} |
|||
} |
|||
|
|||
private static bool IsMigrateDatabase(string[] args) |
|||
{ |
|||
return args.Any(x => x.Contains("--migrate-database", StringComparison.OrdinalIgnoreCase)); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
{ |
|||
"iisSettings": { |
|||
"windowsAuthentication": false, |
|||
"anonymousAuthentication": true, |
|||
"iisExpress": { |
|||
"applicationUrl": "https://localhost:44300", |
|||
"sslPort": 44300 |
|||
} |
|||
}, |
|||
"profiles": { |
|||
"https": { |
|||
"commandName": "Project", |
|||
"dotnetRunMessages": true, |
|||
"launchBrowser": true, |
|||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|||
"applicationUrl": "https://localhost:44300", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
}, |
|||
"IIS Express": { |
|||
"commandName": "IISExpress", |
|||
"launchBrowser": true, |
|||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
{ |
|||
"App": { |
|||
"SelfUrl": "https://localhost:44300", |
|||
"CorsOrigins": "https://*.MyProjectName.com,http://localhost:44300", |
|||
"RedirectAllowedUrls": "http://localhost:44300" |
|||
}, |
|||
"ConnectionStrings": { |
|||
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True" |
|||
}, |
|||
"AuthServer": { |
|||
"Authority": "https://localhost:44300", |
|||
"RequireHttpsMetadata": "false", |
|||
"SwaggerClientId": "MyProjectName_Swagger", |
|||
"SwaggerClientSecret": "1q2w3e*" |
|||
}, |
|||
"StringEncryption": { |
|||
"DefaultPassPhrase": "gsKnGZ041HLL4IM8" |
|||
}, |
|||
"OpenIddict": { |
|||
"Applications": { |
|||
"MyProjectName_Blazor": { |
|||
"ClientId": "MyProjectName_Blazor", |
|||
"RootUrl": "https://localhost:44300" |
|||
}, |
|||
"MyProjectName_Swagger": { |
|||
"ClientId": "MyProjectName_Swagger", |
|||
"RootUrl": "https://localhost:44300" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"version": "1.0.0", |
|||
"name": "my-app", |
|||
"private": true, |
|||
"dependencies": { |
|||
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~2.0.0-rc.1" |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<location path="." inheritInChildApplications="false"> |
|||
<system.webServer> |
|||
<handlers> |
|||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> |
|||
</handlers> |
|||
<aspNetCore processPath="dotnet" arguments=".\MyCompanyName.MyProjectName.Server.dll" stdoutLogEnabled="false" stdoutLogFile=".\Logs\stdout" hostingModel="inprocess" /> |
|||
</system.webServer> |
|||
</location> |
|||
<system.webServer> |
|||
<httpProtocol> |
|||
<customHeaders> |
|||
<remove name="x-powered-by" /> |
|||
</customHeaders> |
|||
</httpProtocol> |
|||
</system.webServer> |
|||
</configuration> |
|||
@ -0,0 +1,8 @@ |
|||
/* Your Global Styles */ |
|||
|
|||
/* <TEMPLATE-REMOVE IF-NOT='LEPTONX'> */ |
|||
:root .lpx-brand-logo { |
|||
--lpx-logo: url('/images/logo/leptonx/logo-light.png'); |
|||
--lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); |
|||
} |
|||
/* </TEMPLATE-REMOVE> */ |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "ar", |
|||
"texts": { |
|||
"Welcome_Title": "مرحبا", |
|||
"Welcome_Text": "هذا هو قالب بدء تشغيل تطبيق ذو طبقة واحدة مبسط لإطار عمل ABP.", |
|||
"Menu:Home": "الصفحة الرئيسية" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "cs", |
|||
"texts": { |
|||
"Welcome_Title": "Vítejte", |
|||
"Welcome_Text": "Toto je minimalistická šablona pro spuštění aplikace s jednou vrstvou pro ABP Framework.", |
|||
"Menu:Home": "Úvod" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "de", |
|||
"texts": { |
|||
"Welcome_Title": "Willkommen", |
|||
"Welcome_Text": "Dies ist eine minimalistische, einschichtige Anwendungsstartvorlage für das ABP-Framework.", |
|||
"Menu:Home": "Home" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "en-GB", |
|||
"texts": { |
|||
"Welcome_Title": "Welcome_Title", |
|||
"Welcome_Text": "This is a minimalist, single layer application startup template for the ABP Framework.", |
|||
"Menu:Home": "Home" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "en", |
|||
"texts": { |
|||
"Welcome_Title": "Welcome", |
|||
"Welcome_Text": "This is a minimalist, single layer application startup template for the ABP Framework.", |
|||
"Menu:Home": "Home" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "es", |
|||
"texts": { |
|||
"Welcome_Title": "Bienvenido", |
|||
"Welcome_Text": "Esta es una plantilla de inicio de aplicación minimalista de una sola capa para ABP Framework.", |
|||
"Menu:Home": "Inicio" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "fi", |
|||
"texts": { |
|||
"Welcome_Title": "Tervetuloa", |
|||
"Welcome_Text": "Tämä on minimalistinen yksikerroksinen sovelluksen käynnistysmalli ABP Frameworkille.", |
|||
"Menu:Home": "Koti" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "fr", |
|||
"texts": { |
|||
"Welcome_Title": "Bienvenue", |
|||
"Welcome_Text": "Il s'agit d'un modèle de démarrage d'application minimaliste à une seule couche pour le cadre ABP.", |
|||
"Menu:Home": "Accueil" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "hi", |
|||
"texts": { |
|||
"Welcome_Title": "स्वागत हे", |
|||
"Welcome_Text": "यह एबीपी फ्रेमवर्क के लिए एक न्यूनतम, सिंगल लेयर एप्लिकेशन स्टार्टअप टेम्प्लेट है।", |
|||
"Menu:Home": "घर" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "hu", |
|||
"texts": { |
|||
"Welcome_Title": "Üdvözlöm", |
|||
"Welcome_Text": "Ez egy minimalista, egyrétegű alkalmazásindítási sablon az ABP-keretrendszerhez.", |
|||
"Menu:Home": "Kezdőlap" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "is", |
|||
"texts": { |
|||
"Welcome_Title": "Velkomin", |
|||
"Welcome_Text": "Þetta er lægstur, eins lags ræsingarsniðmát fyrir ABP Framework.", |
|||
"Menu:Home": "Heim" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "it", |
|||
"texts": { |
|||
"Welcome_Title": "Benvenuto", |
|||
"Welcome_Text": "Questo è un modello di avvio dell'applicazione minimalista a livello singolo per ABP Framework.", |
|||
"Menu:Home": "Home" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "nl", |
|||
"texts": { |
|||
"Welcome_Title": "Welkom", |
|||
"Welcome_Text": "Dit is een minimalistische, enkellaagse applicatie-opstartsjabloon voor het ABP Framework.", |
|||
"Menu:Home": "Home" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "pl-PL", |
|||
"texts": { |
|||
"Welcome_Title": "Witaj", |
|||
"Welcome_Text": "Jest to minimalistyczny, jednowarstwowy szablon uruchamiania aplikacji dla ABP Framework.", |
|||
"Menu:Home": "Home" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "pt-BR", |
|||
"texts": { |
|||
"Welcome_Title": "Seja bem-vindo!", |
|||
"Welcome_Text": "Este é um modelo de inicialização de aplicativo de camada única minimalista para o ABP Framework.", |
|||
"Menu:Home": "Principal" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "ro-RO", |
|||
"texts": { |
|||
"Welcome_Title": "Bun venit", |
|||
"Welcome_Text": "Acesta este un șablon de pornire a aplicației minimaliste, cu un singur strat, pentru Cadrul ABP.", |
|||
"Menu:Home": "Acasă" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "ru", |
|||
"texts": { |
|||
"Welcome_Title": "Bine ati venit", |
|||
"Welcome_Text": "Acesta este un șablon de pornire a aplicației minimaliste, cu un singur strat, pentru Cadrul ABP.", |
|||
"Menu:Home": "Главная" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "sk", |
|||
"texts": { |
|||
"Welcome_Title": "Vitajte", |
|||
"Welcome_Text": "Toto je minimalistická šablóna na spustenie aplikácie s jednou vrstvou pre rámec ABP.", |
|||
"Menu:Home": "Domov" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "sl", |
|||
"texts": { |
|||
"Welcome_Title": "Dobrodošli", |
|||
"Welcome_Text": "To je minimalistična enoslojna predloga za zagon aplikacije za ABP Framework.", |
|||
"Menu:Home": "Domov" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "tr", |
|||
"texts": { |
|||
"Welcome_Title": "Hoşgeldiniz", |
|||
"Welcome_Text": "Bu proje tek katmanlı ABP uygulamaları yapmak için bir başlangıç şablonudur.", |
|||
"Menu:Home": "Ana sayfa" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "vi", |
|||
"texts": { |
|||
"Welcome_Title": "Chào mừng bạn", |
|||
"Welcome_Text": "Đây là một mẫu khởi động ứng dụng lớp đơn, tối giản cho ABP Framework.", |
|||
"Menu:Home": "Trang chủ" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"Welcome_Title": "欢迎", |
|||
"Welcome_Text": "这是ABP框架的极简单层应用程序启动模板.", |
|||
"Menu:Home": "首页" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "zh-Hant", |
|||
"texts": { |
|||
"Welcome_Title": "歡迎", |
|||
"Welcome_Text": "這是 ABP 框架的極簡單層應用程序啟動模板.", |
|||
"Menu:Home": "首頁" |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Shared.Localization; |
|||
|
|||
[LocalizationResourceName("MyProjectName")] |
|||
public class MyProjectNameResource |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace MyCompanyName.MyProjectName.Shared.MultiTenancy; |
|||
|
|||
public static class MultiTenancyConsts |
|||
{ |
|||
/* Enable/disable multi-tenancy easily in a single point. |
|||
* If you will never need to multi-tenancy, you can remove |
|||
* related modules and code parts, including this file. |
|||
*/ |
|||
public const bool IsEnabled = true; |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<SupportedPlatform Include="browser" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="Localization\MyProjectName\*.json" /> |
|||
<Content Remove="Localization\MyProjectName\*.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Validation\Volo.Abp.Validation.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="7.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,59 @@ |
|||
using MyCompanyName.MyProjectName.Shared.Localization; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Localization.ExceptionHandling; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Validation; |
|||
using Volo.Abp.Validation.Localization; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Shared; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpValidationModule) |
|||
)] |
|||
public class MyProjectNameSharedModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<MyProjectNameSharedModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Add<MyProjectNameResource>("en") |
|||
.AddBaseTypes(typeof(AbpValidationResource)) |
|||
.AddVirtualJson("/Localization/MyProjectName"); |
|||
|
|||
options.DefaultResourceType = typeof(MyProjectNameResource); |
|||
|
|||
options.Languages.Add(new LanguageInfo("en", "en", "English")); |
|||
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); |
|||
options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); |
|||
options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); |
|||
options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); |
|||
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); |
|||
options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); |
|||
options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); |
|||
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in")); |
|||
options.Languages.Add(new LanguageInfo("is", "is", "Icelandic", "is")); |
|||
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it")); |
|||
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); |
|||
options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română")); |
|||
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); |
|||
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); |
|||
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); |
|||
options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); |
|||
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de")); |
|||
options.Languages.Add(new LanguageInfo("es", "es", "Español")); |
|||
options.Languages.Add(new LanguageInfo("el", "el", "Ελληνικά")); |
|||
}); |
|||
|
|||
Configure<AbpExceptionLocalizationOptions>(options => |
|||
{ |
|||
options.MapCodeNamespace("MyProjectName", typeof(MyProjectNameResource)); |
|||
}); |
|||
} |
|||
} |
|||