mirror of https://github.com/abpframework/abp.git
442 changed files with 22750 additions and 3522 deletions
@ -0,0 +1,67 @@ |
|||
# Build Command |
|||
|
|||
Building a .NET project is hard when the project references a project reference outside of the solution or even from a different GIT repository. This command builds a GIT repository and it's depending repositories or a single .NET solution File. In order ```build``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain one of; |
|||
|
|||
* A .NET solution file (*.sln) |
|||
* abp-build-config.json |
|||
|
|||
When the executing directory (or ```--working-directory``` parameter's directory) contains a .NET solution file, ```build``` command builds all the projects in the related solution file and all project references on building project files recursively. |
|||
|
|||
When the executing directory (or ```--working-directory``` parameter's directory) contains a ```abp-build-config.json```, ```build``` command builds all changed projects form its last build and all project references on building project files recursively. |
|||
|
|||
# Build Command Config |
|||
|
|||
```abp-build-config.json``` contains properties below; |
|||
|
|||
* ```Name```: Name of the GIT repository. This can be friendly name of your GIT repository or any other unique string for the repository. |
|||
* ```RootPath```: Root path of the repository which contains ```.git``` folder. |
|||
* ```DependingRepositories```: Depending repository list of a repository. Each depending repository item contains same fields as a repository. |
|||
* ```IgnoredDirectories```: Relative directory paths to ignore while building a GIT repository. |
|||
|
|||
A sample ```abp-build-config.json``` looks like for a Windows OS; |
|||
|
|||
````json |
|||
{ |
|||
"Name": "main-repository", |
|||
"RootPath": "D:\\GitHub\\main-repository", |
|||
"DependingRepositories": [{ |
|||
"Name": "module-repository", |
|||
"RootPath": "D:\\GitHub\\module-repository" |
|||
}], |
|||
"IgnoredDirectories": [ |
|||
"utils" |
|||
] |
|||
} |
|||
```` |
|||
|
|||
# Build Status |
|||
|
|||
ABP CLI stores a build status file for builds using the repository friendly names and current branch names in the; |
|||
|
|||
* ```%USERPROFILE%\.abp\build\``` for Windows. |
|||
* ```$HOME/.abp/build/``` for Linux/macOS. |
|||
|
|||
and uses this file when building same repository next time and only builds affected projects and decreases the total build time. A sample build status file content looks like; |
|||
|
|||
````json |
|||
{ |
|||
"RepositoryName": "main-repository", |
|||
"BranchName": "dev", |
|||
"CommitId": "84ecde8ba275aeeb14d24a87ad46a1e941adf8ba", |
|||
"SucceedProjects": [{ |
|||
"CsProjPath": "D:\\GitHub\\main-repository\\BookStore\\BookStore.Web.csproj", |
|||
"CommitId": "84ecde8ba275aeeb14d24a87ad46a1e941adf8ba" |
|||
}], |
|||
"DependingRepositories": [{ |
|||
"RepositoryName": "module-repository", |
|||
"BranchName": "dev", |
|||
"CommitId": "0598b8e45af9507fc9ba8abf304e78fc7d434e04", |
|||
"SucceedProjects": [{ |
|||
"CsProjPath": "D:\\GitHub\\module-repository\\identity-module\Identity\\Identity.Web.csproj", |
|||
"CommitId": "0598b8e45af9507fc9ba8abf304e78fc7d434e04" |
|||
}], |
|||
"DependingRepositories": [] |
|||
}] |
|||
} |
|||
```` |
|||
|
|||
@ -1,5 +1,28 @@ |
|||
# 身份管理模块 |
|||
|
|||
身份模块基于Microsoft Identity 库用于管理[组织单元](Organization-Units.md), 角色, 用户和他们的权限. |
|||
身份模块基于Microsoft Identity库用于管理[组织单元](Organization-Units.md), 角色, 用户和他们的权限. |
|||
|
|||
参阅 [源码](https://github.com/abpframework/abp/tree/dev/modules/identity). 文档很快会被完善. |
|||
参阅 [源码](https://github.com/abpframework/abp/tree/dev/modules/identity). 文档很快会被完善. |
|||
|
|||
## Identity安全日志 |
|||
|
|||
安全日志可以记录账户的一些重要的操作或者改动, 你可以在在一些功能中保存安全日志. |
|||
|
|||
你可以注入和使用 `IdentitySecurityLogManager` 或 `ISecurityLogManager` 来保存安全日志. 默认它会创建一个安全日志对象并填充常用的值. 如 `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `current user/tenant`等等. 当然你可以自定义这些值. |
|||
|
|||
```cs |
|||
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() |
|||
{ |
|||
Identity = "IdentityServer"; |
|||
Action = "ChangePassword"; |
|||
}); |
|||
``` |
|||
|
|||
通过配置 `AbpSecurityLogOptions` 来提供应用程序的名称或者禁用安全日志功能. 默认是**启用**状态. |
|||
|
|||
```cs |
|||
Configure<AbpSecurityLogOptions>(options => |
|||
{ |
|||
options.ApplicationName = "AbpSecurityTest"; |
|||
}); |
|||
``` |
|||
|
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,50 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
using Microsoft.AspNetCore.Authentication.OAuth.Claims; |
|||
using Microsoft.AspNetCore.Authentication.OpenIdConnect; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.AspNetCore.MultiTenancy; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
public static class AbpOpenIdConnectExtensions |
|||
{ |
|||
public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder) |
|||
=> builder.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, _ => { }); |
|||
|
|||
public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, Action<OpenIdConnectOptions> configureOptions) |
|||
=> builder.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, configureOptions); |
|||
|
|||
public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, Action<OpenIdConnectOptions> configureOptions) |
|||
=> builder.AddAbpOpenIdConnect(authenticationScheme, OpenIdConnectDefaults.DisplayName, configureOptions); |
|||
|
|||
public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<OpenIdConnectOptions> configureOptions) |
|||
{ |
|||
return builder.AddOpenIdConnect(authenticationScheme, displayName, options => |
|||
{ |
|||
options.ClaimActions.MapAbpClaimTypes(); |
|||
|
|||
options.Events = new OpenIdConnectEvents |
|||
{ |
|||
OnAuthorizationCodeReceived = receivedContext => |
|||
{ |
|||
var tenantKey = receivedContext.HttpContext.RequestServices |
|||
.GetRequiredService<IOptionsSnapshot<AbpAspNetCoreMultiTenancyOptions>>().Value.TenantKey; |
|||
|
|||
if (receivedContext.HttpContext.Request != null && |
|||
receivedContext.Request.Cookies.ContainsKey(tenantKey)) |
|||
{ |
|||
receivedContext.TokenEndpointRequest.SetParameter(tenantKey, |
|||
receivedContext.Request.Cookies[tenantKey]); |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
}; |
|||
|
|||
configureOptions?.Invoke(options); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.6" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.MultiTenancy\Volo.Abp.AspNetCore.MultiTenancy.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Authentication.OAuth\Volo.Abp.AspNetCore.Authentication.OAuth.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,14 @@ |
|||
using Volo.Abp.AspNetCore.Authentication.OAuth; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Authentication.OpenIdConnect |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpMultiTenancyModule), |
|||
typeof(AbpAspNetCoreAuthenticationOAuthModule))] |
|||
public class AbpAspNetCoreAuthenticationOpenIdConnectModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule) |
|||
)] |
|||
public class AbpAspNetCoreComponentsWebAssemblyBasicThemeModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpRouterOptions>(options => |
|||
{ |
|||
options.AdditionalAssemblies.Add(typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule).Assembly); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,7 @@ |
|||
@page "/authentication/{action}" |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
<RemoteAuthenticatorView Action="@Action" /> |
|||
|
|||
@code{ |
|||
[Parameter] public string Action { get; set; } |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
@using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
|||
@using Microsoft.Extensions.Options |
|||
@inject IOptions<AbpRouterOptions> RouterOptions |
|||
<CascadingAuthenticationState> |
|||
<Router AppAssembly="RouterOptions.Value.AppAssembly" |
|||
AdditionalAssemblies="RouterOptions.Value.AdditionalAssemblies"> |
|||
<Found Context="routeData"> |
|||
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> |
|||
<NotAuthorized> |
|||
@if (!context.User.Identity.IsAuthenticated) |
|||
{ |
|||
<RedirectToLogin /> |
|||
} |
|||
else |
|||
{ |
|||
<p>You are not authorized to access this resource.</p> |
|||
} |
|||
</NotAuthorized> |
|||
</AuthorizeRouteView> |
|||
</Found> |
|||
<NotFound> |
|||
<LayoutView Layout="@typeof(MainLayout)"> |
|||
<p>Sorry, there's nothing at this address.</p> |
|||
</LayoutView> |
|||
</NotFound> |
|||
</Router> |
|||
</CascadingAuthenticationState> |
|||
@ -0,0 +1,65 @@ |
|||
@using Volo.Abp.Localization |
|||
@using System.Globalization |
|||
@using System.Collections.Immutable |
|||
@inject ILanguageProvider LanguageProvider |
|||
@inject IJSRuntime JsRuntime |
|||
@if (_otherLanguages != null && _otherLanguages.Any()) |
|||
{ |
|||
<Dropdown> |
|||
<DropdownToggle Color="Color.None"> |
|||
@_currentLanguage.DisplayName |
|||
</DropdownToggle> |
|||
<DropdownMenu> |
|||
@foreach (var language in _otherLanguages) |
|||
{ |
|||
<DropdownItem Clicked="() => ChangeLanguageAsync(language)">@language.DisplayName</DropdownItem> |
|||
} |
|||
</DropdownMenu> |
|||
</Dropdown> |
|||
} |
|||
@code { |
|||
private IReadOnlyList<LanguageInfo> _otherLanguages; |
|||
private LanguageInfo _currentLanguage; |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
var selectedLanguageName = await JsRuntime.InvokeAsync<string>( |
|||
"localStorage.getItem", |
|||
"Abp.SelectedLanguage" |
|||
); |
|||
|
|||
_otherLanguages = await LanguageProvider.GetLanguagesAsync(); |
|||
|
|||
if (!_otherLanguages.Any()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (!selectedLanguageName.IsNullOrWhiteSpace()) |
|||
{ |
|||
_currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == selectedLanguageName); |
|||
} |
|||
|
|||
if (_currentLanguage == null) |
|||
{ |
|||
_currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == CultureInfo.CurrentUICulture.Name); |
|||
} |
|||
|
|||
if (_currentLanguage == null) |
|||
{ |
|||
_currentLanguage = _otherLanguages.FirstOrDefault(); |
|||
} |
|||
|
|||
_otherLanguages = _otherLanguages.Where(l => l != _currentLanguage).ToImmutableList(); |
|||
} |
|||
|
|||
private async Task ChangeLanguageAsync(LanguageInfo language) |
|||
{ |
|||
await JsRuntime.InvokeVoidAsync( |
|||
"localStorage.setItem", |
|||
"Abp.SelectedLanguage", language.UiCultureName |
|||
); |
|||
|
|||
await JsRuntime.InvokeVoidAsync("location.reload"); |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
@using Volo.Abp.Users |
|||
@inject ICurrentUser CurrentUser |
|||
@inject NavigationManager Navigation |
|||
@inject SignOutSessionStateManager SignOutManager |
|||
<AuthorizeView> |
|||
<Authorized> |
|||
<Dropdown> |
|||
<DropdownToggle Color="Color.None"> |
|||
@CurrentUser.UserName |
|||
</DropdownToggle> |
|||
<DropdownMenu> |
|||
@if (Menu != null) |
|||
{ |
|||
@foreach (var menuItem in Menu.Items) |
|||
{ |
|||
<DropdownItem Clicked="@(() => NavigateTo(menuItem.Url))">@menuItem.DisplayName</DropdownItem> |
|||
} |
|||
} |
|||
<Divider /> |
|||
<DropdownItem Clicked="BeginSignOut">Logout</DropdownItem> |
|||
</DropdownMenu> |
|||
</Dropdown> |
|||
</Authorized> |
|||
<NotAuthorized> |
|||
<a class="nav-link" href="authentication/login">Log in</a> |
|||
</NotAuthorized> |
|||
</AuthorizeView> |
|||
@code{ |
|||
|
|||
private void NavigateTo(string uri) |
|||
{ |
|||
Navigation.NavigateTo(uri); |
|||
} |
|||
|
|||
private async Task BeginSignOut() |
|||
{ |
|||
await SignOutManager.SetSignOutState(); |
|||
NavigateTo("authentication/logout"); |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic |
|||
{ |
|||
public partial class LoginDisplay |
|||
{ |
|||
[Inject] protected IMenuManager MenuManager { get; set; } |
|||
|
|||
protected ApplicationMenu Menu { get; set; } |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
Menu = await MenuManager.GetAsync(StandardMenus.User); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
@inherits LayoutComponentBase |
|||
@using Volo.Abp.Ui.Branding |
|||
@inject IBrandingProvider BrandingProvider |
|||
<nav class="navbar navbar-expand-md navbar-dark bg-dark shadow-sm flex-column flex-md-row mb-4" id="main-navbar" style="min-height: 4rem;"> |
|||
<div class="container"> |
|||
<a class="navbar-brand" href="/">@BrandingProvider.AppName</a> |
|||
<button class="navbar-toggler" type="button" data-toggle="collapse" |
|||
data-target="#main-navbar-collapse" aria-controls="main-navbar-collapse" |
|||
aria-expanded="false" aria-label="Toggle navigation"> |
|||
<span class="navbar-toggler-icon"></span> |
|||
</button> |
|||
<div class="collapse navbar-collapse" id="main-navbar-collapse"> |
|||
<ul class="navbar-nav mx-auto"> |
|||
<NavMenu/> |
|||
</ul> |
|||
<ul class="navbar-nav"> |
|||
<li class="nav-item"> |
|||
<LanguageSwitch/> |
|||
</li> |
|||
<li class="nav-item"> |
|||
<LoginDisplay/> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</nav> |
|||
<div class="container"> |
|||
@Body |
|||
</div> |
|||
@ -0,0 +1,7 @@ |
|||
@if (Menu != null) |
|||
{ |
|||
foreach (var menuItem in Menu.Items) |
|||
{ |
|||
<NavMenuItem MenuItem="@menuItem" /> |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic |
|||
{ |
|||
public partial class NavMenu |
|||
{ |
|||
[Inject] protected IMenuManager MenuManager { get; set; } |
|||
|
|||
protected ApplicationMenu Menu { get; set; } |
|||
|
|||
private bool collapseNavMenu = true; |
|||
|
|||
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
Menu = await MenuManager.GetAsync(StandardMenus.Main); |
|||
} |
|||
|
|||
private void ToggleNavMenu() |
|||
{ |
|||
collapseNavMenu = !collapseNavMenu; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
@using Volo.Abp.UI.Navigation |
|||
@{ |
|||
var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_"); |
|||
var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass; |
|||
var url = string.IsNullOrEmpty(MenuItem.Url) ? "#" : MenuItem.Url; |
|||
} |
|||
@if (MenuItem.IsLeaf) |
|||
{ |
|||
if (MenuItem.Url != null) |
|||
{ |
|||
<li class="nav-item @cssClass" disabled="@MenuItem.IsDisabled"> |
|||
<NavLink class="nav-link" href="@url" id="@elementId"> |
|||
@if (MenuItem.Icon != null) |
|||
{ |
|||
if (MenuItem.Icon.StartsWith("fa")) |
|||
{ |
|||
<i class="@MenuItem.Icon"></i> |
|||
} |
|||
} |
|||
@MenuItem.DisplayName |
|||
</NavLink> |
|||
</li> |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
<li class="nav-item"> |
|||
<div class="dropdown"> |
|||
<a class="nav-link dropdown-toggle" href="#" id="@elementId" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
|||
@if (MenuItem.Icon != null) |
|||
{ |
|||
if (MenuItem.Icon.StartsWith("fa")) |
|||
{ |
|||
<i class="@MenuItem.Icon"></i> |
|||
} |
|||
} |
|||
@MenuItem.DisplayName |
|||
</a> |
|||
<div class="dropdown-menu border-0 shadow-sm" aria-labelledby="@elementId"> |
|||
@foreach (var childMenuItem in MenuItem.Items) |
|||
{ |
|||
<NavMenuItem MenuItem="@childMenuItem" /> |
|||
} |
|||
</div> |
|||
</div> |
|||
</li> |
|||
|
|||
} |
|||
@code { |
|||
[Parameter] |
|||
public ApplicationMenuItem MenuItem { get; set; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
@inject NavigationManager Navigation |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
@code { |
|||
protected override void OnInitialized() |
|||
{ |
|||
Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}"); |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
@using System.Net.Http |
|||
@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.WebAssembly |
|||
@using Blazorise |
|||
@using Blazorise.DataGrid |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RazorLangVersion>3.0</RazorLangVersion> |
|||
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme</PackageId> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,105 @@ |
|||
|
|||
#main-navbar-tools a.dropdown-toggle { |
|||
text-decoration: none; |
|||
color: #fff; |
|||
} |
|||
|
|||
.navbar .dropdown-submenu { |
|||
position: relative; |
|||
} |
|||
.navbar .dropdown-menu { |
|||
margin: 0; |
|||
padding: 0; |
|||
} |
|||
.navbar .dropdown-menu a { |
|||
font-size: .9em; |
|||
padding: 10px 15px; |
|||
display: block; |
|||
min-width: 210px; |
|||
text-align: left; |
|||
border-radius: 0.25rem; |
|||
min-height: 44px; |
|||
} |
|||
.navbar .dropdown-submenu a::after { |
|||
transform: rotate(-90deg); |
|||
position: absolute; |
|||
right: 16px; |
|||
top: 18px; |
|||
} |
|||
.navbar .dropdown-submenu .dropdown-menu { |
|||
top: 0; |
|||
left: 100%; |
|||
} |
|||
|
|||
.card-header .btn { |
|||
padding: 2px 6px; |
|||
} |
|||
.card-header h5 { |
|||
margin: 0; |
|||
} |
|||
.container > .card { |
|||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; |
|||
} |
|||
|
|||
@media screen and (min-width: 768px) { |
|||
.navbar .dropdown:hover > .dropdown-menu { |
|||
display: block; |
|||
} |
|||
|
|||
.navbar .dropdown-submenu:hover > .dropdown-menu { |
|||
display: block; |
|||
} |
|||
} |
|||
.input-validation-error { |
|||
border-color: #dc3545; |
|||
} |
|||
.field-validation-error { |
|||
font-size: 0.8em; |
|||
} |
|||
|
|||
.dataTables_scrollBody { |
|||
min-height: 248px; |
|||
} |
|||
|
|||
div.dataTables_wrapper div.dataTables_info { |
|||
padding-top: 11px; |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
div.dataTables_wrapper div.dataTables_length label { |
|||
padding-top: 10px; |
|||
margin-bottom: 0; |
|||
} |
|||
|
|||
.rtl .dropdown-menu-right { |
|||
right: auto; |
|||
left: 0; |
|||
} |
|||
|
|||
.rtl .dropdown-menu-right a { |
|||
text-align: right; |
|||
} |
|||
|
|||
.rtl .navbar .dropdown-menu a { |
|||
text-align: right; |
|||
} |
|||
.rtl .navbar .dropdown-submenu .dropdown-menu { |
|||
top: 0; |
|||
left: auto; |
|||
right: 100%; |
|||
} |
|||
|
|||
/* TEMP */ |
|||
|
|||
.navbar-dark .navbar-nav .nav-link { |
|||
color: #000 !important; |
|||
} |
|||
|
|||
.navbar-nav > .nav-item > .nav-link, |
|||
.navbar-nav > .nav-item > .dropdown > .nav-link { |
|||
color: #fff !important; |
|||
} |
|||
|
|||
.navbar-nav>.nav-item>div>button{ |
|||
color:#fff; |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
$(function () { |
|||
$('.dropdown-menu a.dropdown-toggle').on('click', function (e) { |
|||
if (!$(this).next().hasClass('show')) { |
|||
$(this).parents('.dropdown-menu').first().find('.show').removeClass("show"); |
|||
} |
|||
|
|||
var $subMenu = $(this).next(".dropdown-menu"); |
|||
$subMenu.toggleClass('show'); |
|||
|
|||
$(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function (e) { |
|||
$('.dropdown-submenu .show').removeClass("show"); |
|||
}); |
|||
|
|||
return false; |
|||
}); |
|||
}); |
|||
@ -0,0 +1,17 @@ |
|||
using Volo.Abp.BlazoriseUI; |
|||
using Volo.Abp.Http.Client.IdentityModel.WebAssembly; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpBlazoriseUIModule), |
|||
typeof(AbpHttpClientIdentityModelWebAssemblyModule), |
|||
typeof(AbpUiNavigationModule) |
|||
)] |
|||
public class AbpAspNetCoreComponentsWebAssemblyThemingModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,16 @@ |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
|||
{ |
|||
public class AbpRouterOptions |
|||
{ |
|||
public Assembly AppAssembly { get; set; } |
|||
|
|||
public RouterAssemblyList AdditionalAssemblies { get; } |
|||
|
|||
public AbpRouterOptions() |
|||
{ |
|||
AdditionalAssemblies = new RouterAssemblyList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
|||
{ |
|||
public class RouterAssemblyList : List<Assembly> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RazorLangVersion>3.0</RazorLangVersion> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.BlazoriseUI\Volo.Abp.BlazoriseUI.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.UI.Navigation\Volo.Abp.UI.Navigation.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,51 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly; |
|||
using Volo.Abp.AspNetCore.Mvc.Client; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting |
|||
{ |
|||
public static class AbpWebAssemblyHostBuilderExtensions |
|||
{ |
|||
public static IAbpApplicationWithExternalServiceProvider AddApplication<TStartupModule>( |
|||
[NotNull] this WebAssemblyHostBuilder builder, |
|||
Action<AbpWebAssemblyApplicationCreationOptions> options) |
|||
where TStartupModule : IAbpModule |
|||
{ |
|||
Check.NotNull(builder, nameof(builder)); |
|||
|
|||
builder.Services.AddSingleton<IConfiguration>(builder.Configuration); |
|||
builder.Services.AddSingleton(builder); |
|||
|
|||
var application = builder.Services.AddApplication<TStartupModule>(opts => |
|||
{ |
|||
options?.Invoke(new AbpWebAssemblyApplicationCreationOptions(builder, opts)); |
|||
}); |
|||
|
|||
return application; |
|||
} |
|||
|
|||
public static async Task InitializeAsync( |
|||
[NotNull] this IAbpApplicationWithExternalServiceProvider application, |
|||
[NotNull] IServiceProvider serviceProvider) |
|||
{ |
|||
Check.NotNull(application, nameof(application)); |
|||
Check.NotNull(serviceProvider, nameof(serviceProvider)); |
|||
|
|||
application.Initialize(serviceProvider); |
|||
|
|||
using (var scope = serviceProvider.CreateScope()) |
|||
{ |
|||
await scope.ServiceProvider |
|||
.GetRequiredService<ICachedApplicationConfigurationClient>() |
|||
.InitializeAsync(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<AssemblyName>Volo.Abp.AspNetCore.Components.WebAssembly</AssemblyName> |
|||
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly</PackageId> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Client.Common\Volo.Abp.AspNetCore.Mvc.Client.Common.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.UI\Volo.Abp.UI.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.1" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.1.6" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,26 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Mvc.Client; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.UI; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreMvcClientCommonModule), |
|||
typeof(AbpUiModule) |
|||
)] |
|||
public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
PreConfigure<AbpHttpClientBuilderOptions>(options => |
|||
{ |
|||
options.ProxyClientBuildActions.Add((_, builder) => |
|||
{ |
|||
builder.AddHttpMessageHandler<AbpBlazorClientHttpMessageHandler>(); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Net.Http.Headers; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.JSInterop; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDependency |
|||
{ |
|||
private readonly IJSRuntime _jsRuntime; |
|||
|
|||
public AbpBlazorClientHttpMessageHandler(IJSRuntime jsRuntime) |
|||
{ |
|||
_jsRuntime = jsRuntime; |
|||
} |
|||
|
|||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) |
|||
{ |
|||
await SetLanguageAsync(request, cancellationToken); |
|||
|
|||
return await base.SendAsync(request, cancellationToken); |
|||
} |
|||
|
|||
private async Task SetLanguageAsync(HttpRequestMessage request, CancellationToken cancellationToken) |
|||
{ |
|||
var selectedLanguage = await _jsRuntime.InvokeAsync<string>( |
|||
"localStorage.getItem", |
|||
cancellationToken, |
|||
"Abp.SelectedLanguage" |
|||
); |
|||
|
|||
if (!selectedLanguage.IsNullOrWhiteSpace()) |
|||
{ |
|||
request.Headers.AcceptLanguage.Clear(); |
|||
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(selectedLanguage)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class AbpWebAssemblyApplicationCreationOptions |
|||
{ |
|||
public WebAssemblyHostBuilder HostBuilder { get; } |
|||
|
|||
public AbpApplicationCreationOptions ApplicationCreationOptions { get; } |
|||
|
|||
public AbpWebAssemblyApplicationCreationOptions( |
|||
WebAssemblyHostBuilder hostBuilder, |
|||
AbpApplicationCreationOptions applicationCreationOptions) |
|||
{ |
|||
HostBuilder = hostBuilder; |
|||
ApplicationCreationOptions = applicationCreationOptions; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class ApplicationConfigurationCache : ISingletonDependency |
|||
{ |
|||
protected ApplicationConfigurationDto Configuration { get; set; } |
|||
|
|||
public virtual ApplicationConfigurationDto Get() |
|||
{ |
|||
return Configuration; |
|||
} |
|||
|
|||
internal void Set(ApplicationConfigurationDto configuration) |
|||
{ |
|||
Configuration = configuration; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public interface IUiMessageService |
|||
{ |
|||
Task InfoAsync(string message, string title = null); |
|||
|
|||
Task SuccessAsync(string message, string title = null); |
|||
|
|||
Task WarnAsync(string message, string title = null); |
|||
|
|||
Task ErrorAsync(string message, string title = null); |
|||
|
|||
Task<bool> ConfirmAsync(string message, string title = null); |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.JSInterop; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
//TODO: Implement with sweetalert in a new package
|
|||
public class UiMessageService : IUiMessageService, ITransientDependency |
|||
{ |
|||
protected IJSRuntime JsRuntime { get; } |
|||
|
|||
public UiMessageService(IJSRuntime jsRuntime) |
|||
{ |
|||
JsRuntime = jsRuntime; |
|||
} |
|||
|
|||
public async Task InfoAsync(string message, string title = null) |
|||
{ |
|||
await JsRuntime.InvokeVoidAsync("alert", message); |
|||
} |
|||
|
|||
public async Task SuccessAsync(string message, string title = null) |
|||
{ |
|||
await JsRuntime.InvokeVoidAsync("alert", message); |
|||
} |
|||
|
|||
public async Task WarnAsync(string message, string title = null) |
|||
{ |
|||
await JsRuntime.InvokeVoidAsync("alert", message); |
|||
} |
|||
|
|||
public async Task ErrorAsync(string message, string title = null) |
|||
{ |
|||
await JsRuntime.InvokeVoidAsync("alert", message); |
|||
} |
|||
|
|||
public async Task<bool> ConfirmAsync(string message, string title = null) |
|||
{ |
|||
return await JsRuntime.InvokeAsync<bool>("confirm", message); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
|||
using Volo.Abp.AspNetCore.Mvc.Client; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Client.DynamicProxying; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency |
|||
{ |
|||
protected IHttpClientProxy<IAbpApplicationConfigurationAppService> Proxy { get; } |
|||
|
|||
protected ApplicationConfigurationCache Cache { get; } |
|||
|
|||
public WebAssemblyCachedApplicationConfigurationClient( |
|||
IHttpClientProxy<IAbpApplicationConfigurationAppService> proxy, |
|||
ApplicationConfigurationCache cache) |
|||
{ |
|||
Proxy = proxy; |
|||
Cache = cache; |
|||
} |
|||
|
|||
public virtual async Task InitializeAsync() |
|||
{ |
|||
Cache.Set(await Proxy.Service.GetAsync()); |
|||
} |
|||
|
|||
public virtual Task<ApplicationConfigurationDto> GetAsync() |
|||
{ |
|||
return Task.FromResult(GetConfigurationByChecking()); |
|||
} |
|||
|
|||
public virtual ApplicationConfigurationDto Get() |
|||
{ |
|||
return GetConfigurationByChecking(); |
|||
} |
|||
|
|||
private ApplicationConfigurationDto GetConfigurationByChecking() |
|||
{ |
|||
var configuration = Cache.Get(); |
|||
if (configuration == null) |
|||
{ |
|||
throw new AbpException( |
|||
$"{nameof(WebAssemblyCachedApplicationConfigurationClient)} should be initialized before using it."); |
|||
} |
|||
|
|||
return configuration; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Security.Claims; |
|||
using Volo.Abp.AspNetCore.Mvc.Client; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Security.Claims; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class WebAssemblyCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency |
|||
{ |
|||
protected ICachedApplicationConfigurationClient ConfigurationClient { get; } |
|||
|
|||
public WebAssemblyCurrentPrincipalAccessor( |
|||
ICachedApplicationConfigurationClient configurationClient) |
|||
{ |
|||
ConfigurationClient = configurationClient; |
|||
} |
|||
|
|||
protected override ClaimsPrincipal GetClaimsPrincipal() |
|||
{ |
|||
var configuration = ConfigurationClient.Get(); |
|||
|
|||
var claims = new List<Claim>(); |
|||
|
|||
if (!configuration.CurrentUser.UserName.IsNullOrWhiteSpace()) |
|||
{ |
|||
claims.Add(new Claim(AbpClaimTypes.UserName,configuration.CurrentUser.UserName)); |
|||
} |
|||
|
|||
if (!configuration.CurrentUser.Email.IsNullOrWhiteSpace()) |
|||
{ |
|||
claims.Add(new Claim(AbpClaimTypes.Email,configuration.CurrentUser.Email)); |
|||
} |
|||
|
|||
if (configuration.CurrentUser.Id != null) |
|||
{ |
|||
claims.Add(new Claim(AbpClaimTypes.UserId,configuration.CurrentUser.Id.ToString())); |
|||
} |
|||
|
|||
if (configuration.CurrentUser.TenantId != null) |
|||
{ |
|||
claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentUser.TenantId.ToString())); |
|||
} |
|||
else if (configuration.CurrentTenant.Id != null) |
|||
{ |
|||
claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentTenant.Id.ToString())); |
|||
} |
|||
|
|||
foreach (var role in configuration.CurrentUser.Roles) |
|||
{ |
|||
claims.Add(new Claim(AbpClaimTypes.Role, role)); |
|||
} |
|||
|
|||
return new ClaimsPrincipal(new ClaimsIdentity(claims)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.AspNetCore.Mvc.MultiTenancy; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Client.DynamicProxying; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class WebAssemblyRemoteTenantStore : ITenantStore, ITransientDependency |
|||
{ |
|||
protected IHttpClientProxy<IAbpTenantAppService> Proxy { get; } |
|||
|
|||
public WebAssemblyRemoteTenantStore( |
|||
IHttpClientProxy<IAbpTenantAppService> proxy) |
|||
{ |
|||
Proxy = proxy; |
|||
} |
|||
|
|||
public async Task<TenantConfiguration> FindAsync(string name) |
|||
{ |
|||
//TODO: Cache
|
|||
|
|||
return CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name)); |
|||
} |
|||
|
|||
public async Task<TenantConfiguration> FindAsync(Guid id) |
|||
{ |
|||
//TODO: Cache
|
|||
|
|||
return CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id)); |
|||
} |
|||
|
|||
public TenantConfiguration Find(string name) |
|||
{ |
|||
//TODO: Cache
|
|||
|
|||
return AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name))); |
|||
} |
|||
|
|||
public TenantConfiguration Find(Guid id) |
|||
{ |
|||
//TODO: Cache
|
|||
|
|||
return AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id))); |
|||
} |
|||
|
|||
protected virtual TenantConfiguration CreateTenantConfiguration(FindTenantResultDto tenantResultDto) |
|||
{ |
|||
if (!tenantResultDto.Success || tenantResultDto.TenantId == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name); |
|||
} |
|||
|
|||
protected virtual string CreateCacheKey(string tenantName) |
|||
{ |
|||
return $"RemoteTenantStore_Name_{tenantName}"; |
|||
} |
|||
|
|||
protected virtual string CreateCacheKey(Guid tenantId) |
|||
{ |
|||
return $"RemoteTenantStore_Id_{tenantId:N}"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using System.Linq; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.AspNetCore.MultiTenancy |
|||
{ |
|||
public class FormTenantResolveContributor : HttpTenantResolveContributorBase |
|||
{ |
|||
public const string ContributorName = "Form"; |
|||
|
|||
public override string Name => ContributorName; |
|||
|
|||
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) |
|||
{ |
|||
if (httpContext.Request == null || !httpContext.Request.Form.Any()) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return httpContext.Request.Form[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,24 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Client.Common</AssemblyName> |
|||
<PackageId>Volo.Abp.AspNetCore.Mvc.Client.Common</PackageId> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,33 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Client |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpHttpClientModule), |
|||
typeof(AbpAspNetCoreMvcContractsModule), |
|||
typeof(AbpCachingModule), |
|||
typeof(AbpLocalizationModule) |
|||
)] |
|||
public class AbpAspNetCoreMvcClientCommonModule : AbpModule |
|||
{ |
|||
public const string RemoteServiceName = "AbpMvcClient"; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddHttpClientProxies( |
|||
typeof(AbpAspNetCoreMvcContractsModule).Assembly, |
|||
RemoteServiceName, |
|||
asDefaultServices: false |
|||
); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.GlobalContributors.Add<RemoteLocalizationContributor>(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,33 +1,11 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Client |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpHttpClientModule), |
|||
typeof(AbpAspNetCoreMvcContractsModule), |
|||
typeof(AbpCachingModule), |
|||
typeof(AbpLocalizationModule) |
|||
typeof(AbpAspNetCoreMvcClientCommonModule) |
|||
)] |
|||
public class AbpAspNetCoreMvcClientModule : AbpModule |
|||
{ |
|||
public const string RemoteServiceName = "AbpMvcClient"; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddHttpClientProxies( |
|||
typeof(AbpAspNetCoreMvcContractsModule).Assembly, |
|||
RemoteServiceName, |
|||
asDefaultServices: false |
|||
); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.GlobalContributors.Add<RemoteLocalizationContributor>(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,23 @@ |
|||
using System; |
|||
using Autofac; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly; |
|||
|
|||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting |
|||
{ |
|||
public static class AbpWebAssemblyApplicationCreationOptionsAutofacExtensions |
|||
{ |
|||
public static void UseAutofac( |
|||
[NotNull] this AbpWebAssemblyApplicationCreationOptions options, |
|||
[CanBeNull] Action<ContainerBuilder> configure = null) |
|||
{ |
|||
options.HostBuilder.Services.AddAutofacServiceProviderFactory(); |
|||
options.HostBuilder.ConfigureContainer( |
|||
options.HostBuilder.Services.GetSingletonInstance<IServiceProviderFactory<ContainerBuilder>>(), |
|||
configure |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly\Volo.Abp.AspNetCore.Components.WebAssembly.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,14 @@ |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Autofac.WebAssembly |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAutofacModule), |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyModule) |
|||
)] |
|||
public class AbpAutofacWebAssemblyModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue