@ -1,425 +0,0 @@ |
|||
# Deploy Abp Webapp to Azure App Service |
|||
|
|||
> In this document, you'll learn how to create and deploy your first abp web app to [Azure App Service](https://docs.microsoft.com/en-us/azure/app-service/overview). The App Service supports various versions of .NET apps, and provides a highly scalable, self-patching web hosting service. Abp web apps are cross-platform and can be hosted on Linux and Windows. |
|||
|
|||
****Prerequisites**** |
|||
|
|||
- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/dotnet). |
|||
- A GitHub account [Create an account for free](http://github.com/). |
|||
|
|||
|
|||
## Create a new ABP Framework application |
|||
|
|||
Create a repository on [GitHub.com](https://github.com/) (keep all the default settings) |
|||
|
|||
Open the command prompt and clone the repository into a folder on your computer |
|||
|
|||
```bash |
|||
git clone https://github.com/your-username/your-repository-name.git |
|||
``` |
|||
Check your dotnet version. It should be at least 3.1.x |
|||
```bash |
|||
dotnet --version |
|||
``` |
|||
Install or update the *ABP CLI* using a command line window |
|||
|
|||
```bash |
|||
dotnet tool install -g Volo.Abp.Cli || dotnet tool update -g Volo.Abp.Cli |
|||
``` |
|||
|
|||
Open the command prompt in the *GitHub repository folder* and create a *new abp Blazor solution* with the command below |
|||
|
|||
```bash |
|||
abp new YourAppName -u blazor |
|||
``` |
|||
|
|||
Open the command prompt in the *[YourAppName].DbMigrator* project and enter the command below to apply the database migrations |
|||
|
|||
```bash |
|||
dotnet run |
|||
``` |
|||
|
|||
Open the command prompt in the *[YourAppName].HttpApi.Host* project to run the API project |
|||
|
|||
```bash |
|||
dotnet run |
|||
``` |
|||
|
|||
Navigate to the *applicationUrl* specified in *the launchSettings.json* file of the *[YourAppName].HttpApi.Host project*. You should get the *Swagger window* |
|||
|
|||
Open the command prompt in the *[YourAppName].Blazor* folder and enter the command below to run the Blazor project |
|||
|
|||
```bash |
|||
dotnet run |
|||
``` |
|||
|
|||
Navigate to the *applicationUrl* specified in the *launchSettings.json* file of the *[YourAppName].Blazor* project. You should get the *ABP Framework Welcome window* |
|||
|
|||
Stop both the *API* and the *Blazor* project by pressing **CTRL+C** |
|||
|
|||
Before the github commit, you have to delete "**/wwwroot/libs/*" at *.gitignore* file. |
|||
|
|||
 |
|||
|
|||
Open the command prompt in the root folder of your project and *add, commit and push* all your changes to your GitHub repository |
|||
|
|||
```bash |
|||
git add . |
|||
git commit -m initialcommit |
|||
git push |
|||
``` |
|||
|
|||
|
|||
## Create a SQL Database on Azure and change the connection string in the appsettings.json files |
|||
|
|||
* Login into [Azure Portal](https://portal.azure.com/) |
|||
|
|||
* Click **Create a resource** |
|||
|
|||
* Search for *SQL Database* |
|||
|
|||
* Click the **Create** button in the *SQL Database window* |
|||
|
|||
* Create a new resource group. Name it *rg[YourAppName]* |
|||
|
|||
* Enter *[YourAppName]Db* as database name |
|||
|
|||
* Create a new Server and name it *[yourappname]server* |
|||
|
|||
* Enter a serveradmin login and passwords. Click the **OK** button |
|||
|
|||
* Select your *Location* |
|||
|
|||
* Check *Allow Azure services to access server* |
|||
|
|||
* Click **Configure database**. Go to the *Basic* version and click the **Apply** button |
|||
|
|||
* Click the **Review + create** button. Click **Create** |
|||
|
|||
* Click **Go to resource** and click **SQL server** when the SQL Database is created |
|||
|
|||
* Click **Networking** under Security left side menu |
|||
|
|||
* Select **Selected networks** and click **Add your client IP$ address** at the Firewall rules |
|||
|
|||
* Select **Allow Azure and resources to access this seerver** and save |
|||
|
|||
* Go to your **SQL database**, click **Connection strings** and copy the connection string |
|||
|
|||
* Copy/paste the appsettings.json files of the [YourAppName].HttpApi.Host and the [YourAppName].DbMigrator project |
|||
|
|||
* Do not forget to replace {your_password} with the correct server password you entered in Azure SQL Database |
|||
|
|||
Open the command prompt in the [YourAppName].DbMigrator project again and enter the command below to apply the database migrations |
|||
|
|||
```bash |
|||
dotnet run |
|||
``` |
|||
Open the command prompt in the [YourAppName].HttpApi.Host project and enter the command below to check your API is working |
|||
|
|||
```bash |
|||
dotnet run |
|||
``` |
|||
|
|||
Stop the [YourAppName].HttpApi.Host by entering CTRL+C |
|||
|
|||
Open the command prompt in the root folder of your project and add, commit and push all your changes to your GitHub repository |
|||
```bash |
|||
git add . |
|||
git commit -m initialcommit |
|||
git push |
|||
``` |
|||
|
|||
|
|||
## Set up the Build pipeline in AzureDevops and publish the Build Artifacts |
|||
|
|||
* Sign in into Azure DevOps |
|||
|
|||
* Click **New organization** and follow the steps to create a new organisation. Name it [YourAppName]org |
|||
|
|||
* Enter [YourAppName]Proj as project name in the ***Create a project to get started*** window |
|||
|
|||
* Select **Public visibility** and click the **Create project** button |
|||
|
|||
* Click the **Pipelines** button to continue |
|||
|
|||
* Click the **Create Pipeline** button |
|||
|
|||
Select GitHub in the Select your repository window |
|||
|
|||
 |
|||
|
|||
* Enter the Connection name. [YourAppName]GitHubConnection and click **Authorize using OAuth** |
|||
|
|||
* Select your **GitHub** [YourAppName]repo and click Continue |
|||
|
|||
* Search for **ASP.NET** in the ***Select a template*** window |
|||
|
|||
 |
|||
|
|||
* Select the ASP.NET Core template and click the **Apply** button |
|||
|
|||
* Add the below commands block as a first step in the pipeline |
|||
|
|||
``` |
|||
- task: UseDotNet@2 |
|||
inputs: |
|||
packageType: 'sdk' |
|||
version: '6.0.106' |
|||
``` |
|||
|
|||
 |
|||
|
|||
* Select **Settings** on the second task(Nugetcommand@2) in the pipeline |
|||
|
|||
* Select **Feeds in my Nuget.config** and type **Nuget.config** in the text box |
|||
|
|||
 |
|||
|
|||
* Add the below commands block to the end of the pipeline |
|||
|
|||
``` |
|||
- task: PublishBuildArtifacts@1 |
|||
displayName: 'Publish Artifact' |
|||
inputs: |
|||
PathtoPublish: '$(build.artifactstagingdirectory)' |
|||
ArtifactName: '$(Parameters.ArtifactName)' |
|||
condition: succeededOrFailed() |
|||
``` |
|||
 |
|||
|
|||
``` |
|||
# ASP.NET |
|||
# Build and test ASP.NET projects. |
|||
# Add steps that publish symbols, save build artifacts, deploy, and more: |
|||
# https://docs.microsoft.com/azure/devops/pipelines/apps/aspnet/build-aspnet-4 |
|||
|
|||
trigger: |
|||
- main |
|||
|
|||
pool: |
|||
vmImage: 'windows-latest' |
|||
|
|||
variables: |
|||
solution: '**/*.sln' |
|||
buildPlatform: 'Any CPU' |
|||
buildConfiguration: 'Release' |
|||
|
|||
steps: |
|||
- task: UseDotNet@2 |
|||
inputs: |
|||
packageType: 'sdk' |
|||
version: '6.0.106' |
|||
|
|||
- task: NuGetToolInstaller@1 |
|||
|
|||
- task: NuGetCommand@2 |
|||
inputs: |
|||
command: 'restore' |
|||
restoreSolution: '$(solution)' |
|||
feedsToUse: 'config' |
|||
nugetConfigPath: 'NuGet.config' |
|||
|
|||
- task: VSBuild@1 |
|||
inputs: |
|||
solution: '$(solution)' |
|||
msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"' |
|||
platform: '$(buildPlatform)' |
|||
configuration: '$(buildConfiguration)' |
|||
|
|||
- task: VSTest@2 |
|||
inputs: |
|||
platform: '$(buildPlatform)' |
|||
configuration: '$(buildConfiguration)' |
|||
|
|||
- task: PublishBuildArtifacts@1 |
|||
displayName: 'Publish Artifact' |
|||
inputs: |
|||
PathtoPublish: '$(build.artifactstagingdirectory)' |
|||
ArtifactName: '$(Parameters.ArtifactName)' |
|||
publishLocation: 'Container' |
|||
condition: succeededOrFailed() |
|||
``` |
|||
|
|||
* Click **Save & queue** in the top menu. Click **Save & queue** again and click **Save and run** to run the Build pipeline |
|||
|
|||
* When the Build pipeline has finished. Click **1 published; 1 consumed** |
|||
|
|||
|
|||
|
|||
## Create a Web App in the Azure Portal to deploy [YourAppName].HttpApi.Host project |
|||
|
|||
* Search for Web App in the *Search the Marketplace* field |
|||
|
|||
* Click the **Create** button in the Web App window |
|||
|
|||
* Select rg[YourAppName] in the *Resource Group* dropdown |
|||
|
|||
* Enter [YourAppName]API in the *Name input* field |
|||
|
|||
* Select code, .NET Core 3.1 (LTS) and windows as *Operating System* |
|||
|
|||
* Enter [YourAppName]API in the *Name input* field |
|||
|
|||
* Select .NET Core 3.1 (LTS) in the *Runtime stack* dropdown |
|||
|
|||
* Select Windows as *Operating System* |
|||
|
|||
* Select the same *Region* as in the SQL server you created in Part 3 |
|||
|
|||
 |
|||
|
|||
* Click **Create new** in the Windows Plan. Name it [YourAppName]ApiWinPlan |
|||
|
|||
* Click **Change size** in Sku and size. Go to the Dev/Test Free F1 version and click the **Apply** button |
|||
|
|||
 |
|||
|
|||
* Click the **Review + create** button. Click the **Create** button |
|||
|
|||
* Click **Go to resource** when the Web App has been created |
|||
|
|||
|
|||
|
|||
## Create a Release pipeline in the AzureDevops and deploy [YourAppName].HttpApi.Host project |
|||
|
|||
* Sign in into [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) |
|||
|
|||
* Click [YourAppName]Proj and click **Releases** in the *Pipelines* menu |
|||
|
|||
* Click the **New pipeline** button in the *No release pipelines found* window |
|||
|
|||
* Select *Azure App Service deployment* and click the **Apply** button |
|||
|
|||
 |
|||
|
|||
* Enter *[YourAppName]staging* in the *Stage name* field in the *Stage* window. And close the window |
|||
|
|||
* Click **+ Add an artifact** in the *Pipeline* tab |
|||
|
|||
* Select the **Build** icon as *Source type* in the *Add an artifact* window |
|||
|
|||
* Select Build pipeline in the *Source (build pipeline)* dropdown and click the **Add** button |
|||
|
|||
 |
|||
|
|||
* Click the **Continuous deployment trigger (thunderbolt icon)** |
|||
|
|||
* Set the toggle to **Enabled** in the the *Continuous deployment trigger* window |
|||
|
|||
* Click **+ Add** in *No filters added*. Select **Include** in the *Type* dropdown. Select your branch in the *Build branch* dropdown and close the window |
|||
|
|||
 |
|||
|
|||
* Click **the little red circle with the exclamation mark** in the *Tasks* tab menu |
|||
|
|||
* Select your subscription in the *Azure subscription* dropdown. |
|||
|
|||
 |
|||
|
|||
* Click **Authorize** and enter your credentials in the next screens |
|||
|
|||
* After Authorization, select the **[YourAppName]API** in the *App service name* dropdown |
|||
|
|||
* Click the **Deploy Azure App Service** task |
|||
|
|||
* Select **[YourAppName].HttpApi.Host.zip** in the *Package or folder* input field |
|||
|
|||
 |
|||
|
|||
* Click the **Save** icon in the top menu and click **OK** |
|||
|
|||
* Click **Create release** in the top menu. Click **Create** to create a release |
|||
|
|||
* Click the *Pipeline* tab and wait until the Deployment succeeds |
|||
|
|||
 |
|||
|
|||
* Open a browser and navigate to the URL of your Web App |
|||
|
|||
``` |
|||
https://[YourAppName]api.azurewebsites.net |
|||
``` |
|||
|
|||
 |
|||
|
|||
|
|||
|
|||
## Create a Web App in Azure Portal to deploy [YourAppName].Blazor project |
|||
|
|||
* Login into [Azure Portal](https://portal.azure.com/) |
|||
|
|||
* Click **Create a resource** |
|||
|
|||
* Search for *Web App* in the *Search the Marketplace* field |
|||
|
|||
* Click the **Create** button in the *Web App* window |
|||
|
|||
* Select *rg[YourAppName]* in the *Resource Group* dropdown |
|||
|
|||
* Enter *[YourAppName]Blazor* in the *Name* input field |
|||
|
|||
* Select *.NET Core 3.1 (LTS)* in the *Runtime stack* dropdown |
|||
|
|||
* Select *Windows* as *Operating System* |
|||
|
|||
* Select the same region as the SQL server you created in Part 3 |
|||
|
|||
* Select the [YourAppName]ApiWinPlan in the *Windows Plan* dropdown |
|||
|
|||
 |
|||
|
|||
* Click the **Review + create** button. Click **Create** button |
|||
|
|||
* Click **Go to resource** when the Web App has been created |
|||
|
|||
* Copy the URL of the Blazor Web App for later use |
|||
|
|||
``` |
|||
https://[YourAppName]blazor.azurewebsites.net |
|||
``` |
|||
|
|||
|
|||
## Change the Web App configuration for the Azure App Service |
|||
|
|||
Copy the URL of the Api Host and Blazor Web App. Change appsettings.json files in the Web App as follows images. |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
|
|||
|
|||
## Add an extra Stage in the Release pipeline in the AzureDevops to deploy [YourAppName].Blazor project |
|||
|
|||
* Go to the *Release* pipeline in [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) and click **Edit** |
|||
|
|||
* Click the **+ Add** link and add a **New Stage** |
|||
|
|||
 |
|||
|
|||
* Select *Azure App Service deployment* and click the **Apply** button |
|||
|
|||
* Enter *BlazorDeployment* in the *Stage name* input field and close the *Stage* window |
|||
|
|||
* Click the **little red circle with the exclamation mark** in the BlazorDeployment stage |
|||
|
|||
* Select your subscription in the *Azure subscription* dropdown |
|||
|
|||
* Select your Blazor Web App in the *App service name* dropdown |
|||
|
|||
* Click the **Deploy Azure App Service task** |
|||
|
|||
* Select *[YourAppName].Blazor.zip* in the *Package or folder* input field |
|||
|
|||
 |
|||
|
|||
* Click **Save** in the top menu and click the **OK** button after |
|||
|
|||
* Click **Create release** in the top menu and click the **Create** button |
|||
|
|||
 |
|||
|
|||
 |
|||
@ -0,0 +1,20 @@ |
|||
# Angular UI: Current User |
|||
|
|||
The current user information stored in Config State. |
|||
|
|||
### How to Get a Current User Information Configuration |
|||
|
|||
You can use the `getOne` or `getOne$` method of `ConfigStateService` to get a specific configuration property. For that, the property name should be passed to the method as parameter. |
|||
|
|||
```js |
|||
// this.config is an instance of ConfigStateService |
|||
|
|||
const currentUser = this.config.getOne("currentUser"); |
|||
|
|||
// or |
|||
this.config.getOne$("currentUser").subscribe(currentUser => { |
|||
// use currentUser here |
|||
}) |
|||
``` |
|||
|
|||
> See the [ConfigStateService](./Config-State-Service) for more information. |
|||
|
Before Width: | Height: | Size: 252 KiB |
|
Before Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 487 KiB |
|
Before Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 368 KiB |
|
Before Width: | Height: | Size: 281 KiB |
|
Before Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 418 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 491 KiB |
|
Before Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 539 KiB |
|
Before Width: | Height: | Size: 415 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 352 KiB |
|
Before Width: | Height: | Size: 400 KiB |
|
Before Width: | Height: | Size: 295 KiB |
|
Before Width: | Height: | Size: 219 KiB |
|
Before Width: | Height: | Size: 288 KiB |
|
Before Width: | Height: | Size: 309 KiB |
|
Before Width: | Height: | Size: 304 KiB |
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 24 KiB |
@ -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,18 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Dapr\Volo.Abp.AspNetCore.Mvc.Dapr.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.EventBus.Dapr\Volo.Abp.EventBus.Dapr.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,29 @@ |
|||
using Microsoft.AspNetCore.Http.Json; |
|||
using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.SystemTextJson; |
|||
using Volo.Abp.EventBus.Dapr; |
|||
using Volo.Abp.Json.SystemTextJson; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreMvcDaprModule), |
|||
typeof(AbpEventBusDaprModule) |
|||
)] |
|||
public class AbpAspNetCoreMvcDaprEventBusModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
// TODO: Add NewtonsoftJson json converter.
|
|||
|
|||
Configure<JsonOptions>(options => |
|||
{ |
|||
options.SerializerOptions.Converters.Add(new AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter()); |
|||
}); |
|||
|
|||
Configure<AbpSystemTextJsonSerializerOptions>(options => |
|||
{ |
|||
options.JsonSerializerOptions.Converters.Add(new AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter()); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus; |
|||
|
|||
public class AbpAspNetCoreMvcDaprEventBusOptions |
|||
{ |
|||
public List<IAbpAspNetCoreMvcDaprPubSubProviderContributor> Contributors { get; } |
|||
|
|||
public AbpAspNetCoreMvcDaprEventBusOptions() |
|||
{ |
|||
Contributors = new List<IAbpAspNetCoreMvcDaprPubSubProviderContributor>(); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus; |
|||
|
|||
public class AbpAspNetCoreMvcDaprPubSubConsts |
|||
{ |
|||
public const string DaprSubscribeUrl = "dapr/subscribe"; |
|||
|
|||
public const string DaprEventCallbackUrl = "api/abp/dapr/event"; |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.EventBus; |
|||
using Volo.Abp.EventBus.Dapr; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus; |
|||
|
|||
public class AbpAspNetCoreMvcDaprPubSubProvider : ITransientDependency |
|||
{ |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
protected AbpAspNetCoreMvcDaprEventBusOptions AspNetCoreMvcDaprEventBusOptions { get; } |
|||
protected AbpDaprEventBusOptions DaprEventBusOptions { get; } |
|||
protected AbpDistributedEventBusOptions DistributedEventBusOptions { get; } |
|||
|
|||
public AbpAspNetCoreMvcDaprPubSubProvider( |
|||
IServiceProvider serviceProvider, |
|||
IOptions<AbpAspNetCoreMvcDaprEventBusOptions> aspNetCoreDaprEventBusOptions, |
|||
IOptions<AbpDaprEventBusOptions> daprEventBusOptions, |
|||
IOptions<AbpDistributedEventBusOptions> distributedEventBusOptions) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
AspNetCoreMvcDaprEventBusOptions = aspNetCoreDaprEventBusOptions.Value; |
|||
DaprEventBusOptions = daprEventBusOptions.Value; |
|||
DistributedEventBusOptions = distributedEventBusOptions.Value; |
|||
} |
|||
|
|||
public virtual async Task<List<AbpAspNetCoreMvcDaprSubscriptionDefinition>> GetSubscriptionsAsync() |
|||
{ |
|||
var subscriptions = new List<AbpAspNetCoreMvcDaprSubscriptionDefinition>(); |
|||
foreach (var handler in DistributedEventBusOptions.Handlers) |
|||
{ |
|||
foreach (var @interface in handler.GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDistributedEventHandler<>))) |
|||
{ |
|||
var eventType = @interface.GetGenericArguments()[0]; |
|||
var eventName = EventNameAttribute.GetNameOrDefault(eventType); |
|||
|
|||
subscriptions.Add(new AbpAspNetCoreMvcDaprSubscriptionDefinition() |
|||
{ |
|||
PubSubName = DaprEventBusOptions.PubSubName, |
|||
Topic = eventName, |
|||
Route = AbpAspNetCoreMvcDaprPubSubConsts.DaprEventCallbackUrl |
|||
}); |
|||
} |
|||
} |
|||
|
|||
if (AspNetCoreMvcDaprEventBusOptions.Contributors.Any()) |
|||
{ |
|||
using (var scope = ServiceProvider.CreateScope()) |
|||
{ |
|||
var context = new AbpAspNetCoreMvcDaprPubSubProviderContributorContext(scope.ServiceProvider, subscriptions); |
|||
foreach (var contributor in AspNetCoreMvcDaprEventBusOptions.Contributors) |
|||
{ |
|||
await contributor.ContributeAsync(context); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return subscriptions; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus; |
|||
|
|||
public class AbpAspNetCoreMvcDaprPubSubProviderContributorContext |
|||
{ |
|||
public IServiceProvider ServiceProvider { get; } |
|||
|
|||
public List<AbpAspNetCoreMvcDaprSubscriptionDefinition> Subscriptions { get; } |
|||
|
|||
public AbpAspNetCoreMvcDaprPubSubProviderContributorContext(IServiceProvider serviceProvider, List<AbpAspNetCoreMvcDaprSubscriptionDefinition> daprSubscriptionModels) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
Subscriptions = daprSubscriptionModels; |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System.Text.Json; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models; |
|||
using Volo.Abp.Dapr; |
|||
using Volo.Abp.EventBus.Dapr; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Controllers; |
|||
|
|||
[Area("abp")] |
|||
[RemoteService(Name = "abp")] |
|||
public class AbpAspNetCoreMvcDaprPubSubController : AbpController |
|||
{ |
|||
[HttpGet(AbpAspNetCoreMvcDaprPubSubConsts.DaprSubscribeUrl)] |
|||
public virtual async Task<List<AbpAspNetCoreMvcDaprSubscriptionDefinition>> SubscribeAsync() |
|||
{ |
|||
return await HttpContext.RequestServices.GetRequiredService<AbpAspNetCoreMvcDaprPubSubProvider>().GetSubscriptionsAsync(); |
|||
} |
|||
|
|||
[HttpPost(AbpAspNetCoreMvcDaprPubSubConsts.DaprEventCallbackUrl)] |
|||
public virtual async Task<IActionResult> EventsAsync() |
|||
{ |
|||
var bodyJsonDocument = await JsonDocument.ParseAsync(HttpContext.Request.Body); |
|||
var request = JsonSerializer.Deserialize<AbpAspNetCoreMvcDaprSubscriptionRequest>(bodyJsonDocument.RootElement.GetRawText(), |
|||
HttpContext.RequestServices.GetRequiredService<IOptions<JsonOptions>>().Value.JsonSerializerOptions); |
|||
|
|||
var distributedEventBus = HttpContext.RequestServices.GetRequiredService<DaprDistributedEventBus>(); |
|||
var daprSerializer = HttpContext.RequestServices.GetRequiredService<IDaprSerializer>(); |
|||
|
|||
var eventData = daprSerializer.Deserialize(bodyJsonDocument.RootElement.GetProperty("data").GetRawText(), distributedEventBus.GetEventType(request.Topic)); |
|||
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(request.Topic), eventData); |
|||
|
|||
return Ok(); |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus; |
|||
|
|||
public interface IAbpAspNetCoreMvcDaprPubSubProviderContributor |
|||
{ |
|||
Task ContributeAsync(AbpAspNetCoreMvcDaprPubSubProviderContributorContext context); |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models; |
|||
|
|||
public class AbpAspNetCoreMvcDaprSubscriptionDefinition |
|||
{ |
|||
public string PubSubName { get; set; } |
|||
|
|||
public string Topic { get; set; } |
|||
|
|||
public string Route { get; set; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models; |
|||
|
|||
public class AbpAspNetCoreMvcDaprSubscriptionRequest |
|||
{ |
|||
public string PubSubName { get; set; } |
|||
|
|||
public string Topic { get; set; } |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.Text.Json; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.SystemTextJson; |
|||
|
|||
public class AbpAspNetCoreMvcDaprPubSubJsonNamingPolicy : JsonNamingPolicy |
|||
{ |
|||
public override string ConvertName(string name) |
|||
{ |
|||
return name.ToLower(); |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.SystemTextJson; |
|||
|
|||
public class AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter : JsonConverter<AbpAspNetCoreMvcDaprSubscriptionDefinition> |
|||
{ |
|||
private JsonSerializerOptions _writeJsonSerializerOptions; |
|||
|
|||
public override AbpAspNetCoreMvcDaprSubscriptionDefinition Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
throw new NotSupportedException(); |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, AbpAspNetCoreMvcDaprSubscriptionDefinition value, JsonSerializerOptions options) |
|||
{ |
|||
_writeJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(new JsonSerializerOptions(options) |
|||
{ |
|||
PropertyNamingPolicy = new AbpAspNetCoreMvcDaprPubSubJsonNamingPolicy() |
|||
}, x => x == this); |
|||
|
|||
JsonSerializer.Serialize(writer, value, _writeJsonSerializerOptions); |
|||
} |
|||
} |
|||
@ -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,22 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Dapr\Volo.Abp.Dapr.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Dapr.AspNetCore" Version="1.8.0" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,13 @@ |
|||
using Volo.Abp.Dapr; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Dapr; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreMvcModule), |
|||
typeof(AbpDaprModule) |
|||
)] |
|||
public class AbpAspNetCoreMvcDaprModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions; |
|||
|
|||
public interface ICanAddChildPermission |
|||
{ |
|||
PermissionDefinition AddPermission( |
|||
[NotNull] string name, |
|||
ILocalizableString displayName = null, |
|||
MultiTenancySides multiTenancySide = MultiTenancySides.Both, |
|||
bool isEnabled = true); |
|||
} |
|||
@ -1,17 +1,18 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions; |
|||
|
|||
public interface IPermissionDefinitionManager |
|||
{ |
|||
[NotNull] |
|||
PermissionDefinition Get([NotNull] string name); |
|||
[ItemNotNull] |
|||
Task<PermissionDefinition> GetAsync([NotNull] string name); |
|||
|
|||
[CanBeNull] |
|||
PermissionDefinition GetOrNull([NotNull] string name); |
|||
[ItemCanBeNull] |
|||
Task<PermissionDefinition> GetOrNullAsync([NotNull] string name); |
|||
|
|||
IReadOnlyList<PermissionDefinition> GetPermissions(); |
|||
Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync(); |
|||
|
|||
IReadOnlyList<PermissionGroupDefinition> GetGroups(); |
|||
Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync(); |
|||
} |
|||
|
|||
@ -0,0 +1,38 @@ |
|||
using System.Text.Json.Nodes; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.SimpleStateChecking; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions; |
|||
|
|||
public class AuthenticatedSimpleStateCheckerSerializerContributor : |
|||
ISimpleStateCheckerSerializerContributor, |
|||
ISingletonDependency |
|||
{ |
|||
public const string CheckerShortName = "A"; |
|||
|
|||
public string SerializeToJson<TState>(ISimpleStateChecker<TState> checker) |
|||
where TState : IHasSimpleStateCheckers<TState> |
|||
{ |
|||
if (checker is not RequireAuthenticatedSimpleStateChecker<TState>) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var jsonObject = new JsonObject { |
|||
["T"] = CheckerShortName |
|||
}; |
|||
|
|||
return jsonObject.ToJsonString(); |
|||
} |
|||
|
|||
public ISimpleStateChecker<TState> Deserialize<TState>(JsonObject jsonObject, TState state) |
|||
where TState : IHasSimpleStateCheckers<TState> |
|||
{ |
|||
if (jsonObject["T"]?.ToString() != CheckerShortName) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return new RequireAuthenticatedSimpleStateChecker<TState>(); |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions; |
|||
|
|||
public interface IDynamicPermissionDefinitionStore |
|||
{ |
|||
Task<PermissionDefinition> GetOrNullAsync(string name); |
|||
|
|||
Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync(); |
|||
|
|||
Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync(); |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions; |
|||
|
|||
public interface IStaticPermissionDefinitionStore |
|||
{ |
|||
Task<PermissionDefinition> GetOrNullAsync(string name); |
|||
|
|||
Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync(); |
|||
|
|||
Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync(); |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Immutable; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions; |
|||
|
|||
public class NullDynamicPermissionDefinitionStore : IDynamicPermissionDefinitionStore, ISingletonDependency |
|||
{ |
|||
private readonly static Task<PermissionDefinition> CachedPermissionResult = Task.FromResult((PermissionDefinition)null); |
|||
|
|||
private readonly static Task<IReadOnlyList<PermissionDefinition>> CachedPermissionsResult = |
|||
Task.FromResult((IReadOnlyList<PermissionDefinition>)Array.Empty<PermissionDefinition>().ToImmutableList()); |
|||
|
|||
private readonly static Task<IReadOnlyList<PermissionGroupDefinition>> CachedGroupsResult = |
|||
Task.FromResult((IReadOnlyList<PermissionGroupDefinition>)Array.Empty<PermissionGroupDefinition>().ToImmutableList()); |
|||
|
|||
public Task<PermissionDefinition> GetOrNullAsync(string name) |
|||
{ |
|||
return CachedPermissionResult; |
|||
} |
|||
|
|||
public Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync() |
|||
{ |
|||
return CachedPermissionsResult; |
|||
} |
|||
|
|||
public Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
|||
{ |
|||
return CachedGroupsResult; |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using System.Linq; |
|||
using System.Text.Json.Nodes; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.SimpleStateChecking; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures; |
|||
|
|||
public class PermissionsSimpleStateCheckerSerializerContributor : |
|||
ISimpleStateCheckerSerializerContributor, |
|||
ISingletonDependency |
|||
{ |
|||
public const string CheckerShortName = "P"; |
|||
|
|||
public string SerializeToJson<TState>(ISimpleStateChecker<TState> checker) |
|||
where TState : IHasSimpleStateCheckers<TState> |
|||
{ |
|||
if (checker is not RequirePermissionsSimpleStateChecker<TState> permissionsSimpleStateChecker) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var jsonObject = new JsonObject { |
|||
["T"] = CheckerShortName, |
|||
["A"] = permissionsSimpleStateChecker.RequiresAll |
|||
}; |
|||
|
|||
var nameArray = new JsonArray(); |
|||
foreach (var permissionName in permissionsSimpleStateChecker.PermissionNames) |
|||
{ |
|||
nameArray.Add(permissionName); |
|||
} |
|||
|
|||
jsonObject["N"] = nameArray; |
|||
return jsonObject.ToJsonString(); |
|||
} |
|||
|
|||
public ISimpleStateChecker<TState> Deserialize<TState>( |
|||
JsonObject jsonObject, |
|||
TState state) |
|||
where TState : IHasSimpleStateCheckers<TState> |
|||
{ |
|||
if (jsonObject["T"]?.ToString() != CheckerShortName) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var nameArray = jsonObject["N"] as JsonArray; |
|||
if (nameArray == null) |
|||
{ |
|||
throw new AbpException("'N' is not an array in the serialized state checker! JsonObject: " + jsonObject.ToJsonString()); |
|||
} |
|||
|
|||
return new RequirePermissionsSimpleStateChecker<TState>( |
|||
new RequirePermissionsSimpleBatchStateCheckerModel<TState>( |
|||
state, |
|||
nameArray.Select(x => x.ToString()).ToArray(), |
|||
(bool?)jsonObject["A"] ?? false |
|||
) |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,122 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Immutable; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions; |
|||
|
|||
public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore, ISingletonDependency |
|||
{ |
|||
protected IDictionary<string, PermissionGroupDefinition> PermissionGroupDefinitions => _lazyPermissionGroupDefinitions.Value; |
|||
private readonly Lazy<Dictionary<string, PermissionGroupDefinition>> _lazyPermissionGroupDefinitions; |
|||
|
|||
protected IDictionary<string, PermissionDefinition> PermissionDefinitions => _lazyPermissionDefinitions.Value; |
|||
private readonly Lazy<Dictionary<string, PermissionDefinition>> _lazyPermissionDefinitions; |
|||
|
|||
protected AbpPermissionOptions Options { get; } |
|||
|
|||
private readonly IServiceProvider _serviceProvider; |
|||
|
|||
public StaticPermissionDefinitionStore( |
|||
IServiceProvider serviceProvider, |
|||
IOptions<AbpPermissionOptions> options) |
|||
{ |
|||
_serviceProvider = serviceProvider; |
|||
Options = options.Value; |
|||
|
|||
_lazyPermissionDefinitions = new Lazy<Dictionary<string, PermissionDefinition>>( |
|||
CreatePermissionDefinitions, |
|||
isThreadSafe: true |
|||
); |
|||
|
|||
_lazyPermissionGroupDefinitions = new Lazy<Dictionary<string, PermissionGroupDefinition>>( |
|||
CreatePermissionGroupDefinitions, |
|||
isThreadSafe: true |
|||
); |
|||
} |
|||
|
|||
protected virtual Dictionary<string, PermissionDefinition> CreatePermissionDefinitions() |
|||
{ |
|||
var permissions = new Dictionary<string, PermissionDefinition>(); |
|||
|
|||
foreach (var groupDefinition in PermissionGroupDefinitions.Values) |
|||
{ |
|||
foreach (var permission in groupDefinition.Permissions) |
|||
{ |
|||
AddPermissionToDictionaryRecursively(permissions, permission); |
|||
} |
|||
} |
|||
|
|||
return permissions; |
|||
} |
|||
|
|||
protected virtual void AddPermissionToDictionaryRecursively( |
|||
Dictionary<string, PermissionDefinition> permissions, |
|||
PermissionDefinition permission) |
|||
{ |
|||
if (permissions.ContainsKey(permission.Name)) |
|||
{ |
|||
throw new AbpException("Duplicate permission name: " + permission.Name); |
|||
} |
|||
|
|||
permissions[permission.Name] = permission; |
|||
|
|||
foreach (var child in permission.Children) |
|||
{ |
|||
AddPermissionToDictionaryRecursively(permissions, child); |
|||
} |
|||
} |
|||
|
|||
protected virtual Dictionary<string, PermissionGroupDefinition> CreatePermissionGroupDefinitions() |
|||
{ |
|||
using (var scope = _serviceProvider.CreateScope()) |
|||
{ |
|||
var context = new PermissionDefinitionContext(scope.ServiceProvider); |
|||
|
|||
var providers = Options |
|||
.DefinitionProviders |
|||
.Select(p => scope.ServiceProvider.GetRequiredService(p) as IPermissionDefinitionProvider) |
|||
.ToList(); |
|||
|
|||
foreach (var provider in providers) |
|||
{ |
|||
provider.PreDefine(context); |
|||
} |
|||
|
|||
foreach (var provider in providers) |
|||
{ |
|||
provider.Define(context); |
|||
} |
|||
|
|||
foreach (var provider in providers) |
|||
{ |
|||
provider.PostDefine(context); |
|||
} |
|||
|
|||
return context.Groups; |
|||
} |
|||
} |
|||
|
|||
public Task<PermissionDefinition> GetOrNullAsync(string name) |
|||
{ |
|||
return Task.FromResult(PermissionDefinitions.GetOrDefault(name)); |
|||
} |
|||
|
|||
public virtual Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync() |
|||
{ |
|||
return Task.FromResult<IReadOnlyList<PermissionDefinition>>( |
|||
PermissionDefinitions.Values.ToImmutableList() |
|||
); |
|||
} |
|||
|
|||
public Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
|||
{ |
|||
return Task.FromResult<IReadOnlyList<PermissionGroupDefinition>>( |
|||
PermissionGroupDefinitions.Values.ToImmutableList() |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.DependencyInjection; |
|||
|
|||
/// <summary>
|
|||
/// The root service provider of the application.
|
|||
/// Be careful to use the root service provider since there is no way
|
|||
/// to release/dispose objects resolved from the root service provider.
|
|||
/// So, always create a new scope if you need to resolve any service.
|
|||
/// </summary>
|
|||
public interface IRootServiceProvider : IServiceProvider |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.DependencyInjection; |
|||
|
|||
[ExposeServices(typeof(IRootServiceProvider))] |
|||
public class RootServiceProvider : IRootServiceProvider, ISingletonDependency |
|||
{ |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
|
|||
public RootServiceProvider(IObjectAccessor<IServiceProvider> objectAccessor) |
|||
{ |
|||
ServiceProvider = objectAccessor.Value; |
|||
} |
|||
|
|||
public virtual object GetService(Type serviceType) |
|||
{ |
|||
return ServiceProvider.GetService(serviceType); |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
namespace Volo.Abp; |
|||
|
|||
public interface IApplicationNameAccessor |
|||
{ |
|||
/// <summary>
|
|||
/// Name of the application.
|
|||
/// This is useful for systems with multiple applications, to distinguish
|
|||
/// resources of the applications located together.
|
|||
/// </summary>
|
|||
string ApplicationName { get; } |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System.Text.Json.Nodes; |
|||
|
|||
namespace Volo.Abp.SimpleStateChecking; |
|||
|
|||
public interface ISimpleStateCheckerSerializer |
|||
{ |
|||
public string Serialize<TState>(ISimpleStateChecker<TState> checker) |
|||
where TState : IHasSimpleStateCheckers<TState>; |
|||
|
|||
public ISimpleStateChecker<TState> Deserialize<TState>(JsonObject jsonObject, TState state) |
|||
where TState : IHasSimpleStateCheckers<TState>; |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System.Text.Json.Nodes; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.SimpleStateChecking; |
|||
|
|||
public interface ISimpleStateCheckerSerializerContributor |
|||
{ |
|||
[CanBeNull] |
|||
public string SerializeToJson<TState>(ISimpleStateChecker<TState> checker) |
|||
where TState : IHasSimpleStateCheckers<TState>; |
|||
|
|||
[CanBeNull] |
|||
public ISimpleStateChecker<TState> Deserialize<TState>(JsonObject jsonObject, TState state) |
|||
where TState : IHasSimpleStateCheckers<TState>; |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
using System.Collections.Generic; |
|||
using System.Text.Json.Nodes; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.SimpleStateChecking; |
|||
|
|||
public class SimpleStateCheckerSerializer : |
|||
ISimpleStateCheckerSerializer, |
|||
ISingletonDependency |
|||
{ |
|||
private readonly IEnumerable<ISimpleStateCheckerSerializerContributor> _contributors; |
|||
|
|||
public SimpleStateCheckerSerializer(IEnumerable<ISimpleStateCheckerSerializerContributor> contributors) |
|||
{ |
|||
_contributors = contributors; |
|||
} |
|||
|
|||
[CanBeNull] |
|||
public string Serialize<TState>(ISimpleStateChecker<TState> checker) |
|||
where TState : IHasSimpleStateCheckers<TState> |
|||
{ |
|||
foreach (var contributor in _contributors) |
|||
{ |
|||
var result = contributor.SerializeToJson(checker); |
|||
if (result != null) |
|||
{ |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
[CanBeNull] |
|||
public ISimpleStateChecker<TState> Deserialize<TState>(JsonObject jsonObject, TState state) |
|||
where TState : IHasSimpleStateCheckers<TState> |
|||
{ |
|||
foreach (var contributor in _contributors) |
|||
{ |
|||
var result = contributor.Deserialize(jsonObject, state); |
|||
if (result != null) |
|||
{ |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text.Json.Nodes; |
|||
|
|||
namespace Volo.Abp.SimpleStateChecking; |
|||
|
|||
public static class SimpleStateCheckerSerializerExtensions |
|||
{ |
|||
public static string Serialize<TState>( |
|||
this ISimpleStateCheckerSerializer serializer, |
|||
IList<ISimpleStateChecker<TState>> stateCheckers) |
|||
where TState : IHasSimpleStateCheckers<TState> |
|||
{ |
|||
switch (stateCheckers.Count) |
|||
{ |
|||
case 0: |
|||
return null; |
|||
case 1: |
|||
var serializedChecker = serializer.Serialize(stateCheckers.Single()); |
|||
return serializedChecker != null |
|||
? $"[{serializedChecker}]" |
|||
: null; |
|||
default: |
|||
var serializedCheckers = new List<string>(stateCheckers.Count); |
|||
|
|||
foreach (var stateChecker in stateCheckers) |
|||
{ |
|||
var serialized = serializer.Serialize(stateChecker); |
|||
if (serialized != null) |
|||
{ |
|||
serializedCheckers.Add(serialized); |
|||
} |
|||
} |
|||
|
|||
return serializedCheckers.Any() |
|||
? $"[{serializedCheckers.JoinAsString(",")}]" |
|||
: null; |
|||
} |
|||
} |
|||
|
|||
public static ISimpleStateChecker<TState>[] DeserializeArray<TState>( |
|||
this ISimpleStateCheckerSerializer serializer, |
|||
string value, |
|||
TState state) |
|||
where TState : IHasSimpleStateCheckers<TState> |
|||
{ |
|||
if (value.IsNullOrWhiteSpace()) |
|||
{ |
|||
return Array.Empty<ISimpleStateChecker<TState>>(); |
|||
} |
|||
|
|||
var array = JsonNode.Parse(value) as JsonArray; |
|||
if (array == null || array.Count == 0) |
|||
{ |
|||
return Array.Empty<ISimpleStateChecker<TState>>(); |
|||
} |
|||
|
|||
if (array.Count == 1) |
|||
{ |
|||
var jsonObject = array[0] as JsonObject; |
|||
if (jsonObject == null) |
|||
{ |
|||
throw new AbpException("JSON value is not an array of objects: " + value); |
|||
} |
|||
|
|||
var checker = serializer.Deserialize(jsonObject, state); |
|||
if (checker == null) |
|||
{ |
|||
return Array.Empty<ISimpleStateChecker<TState>>(); |
|||
} |
|||
|
|||
return new[] { checker }; |
|||
} |
|||
|
|||
var checkers = new List<ISimpleStateChecker<TState>>(); |
|||
|
|||
for (var i = 0; i < array.Count; i++) |
|||
{ |
|||
if (array[i] is not JsonObject jsonObject) |
|||
{ |
|||
throw new AbpException("JSON value is not an array of objects: " + value); |
|||
} |
|||
|
|||
checkers.Add(serializer.Deserialize(jsonObject, state)); |
|||
} |
|||
|
|||
return checkers.Where(x => x != null).ToArray(); |
|||
} |
|||
} |
|||
@ -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,21 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Dapr.Client" Version="1.8.0" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,48 @@ |
|||
using System.Collections.Concurrent; |
|||
using System.Text.Json; |
|||
using Dapr.Client; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json.SystemTextJson; |
|||
|
|||
namespace Volo.Abp.Dapr; |
|||
|
|||
public class AbpDaprClientFactory : ITransientDependency |
|||
{ |
|||
protected AbpDaprOptions Options { get; } |
|||
protected AbpSystemTextJsonSerializerOptions SystemTextJsonSerializerOptions { get; } |
|||
|
|||
public AbpDaprClientFactory( |
|||
IOptions<AbpDaprOptions> options, |
|||
IOptions<AbpSystemTextJsonSerializerOptions> systemTextJsonSerializerOptions) |
|||
{ |
|||
Options = options.Value; |
|||
SystemTextJsonSerializerOptions = systemTextJsonSerializerOptions.Value; |
|||
} |
|||
|
|||
public virtual async Task<DaprClient> CreateAsync() |
|||
{ |
|||
var builder = new DaprClientBuilder() |
|||
.UseJsonSerializationOptions(await CreateJsonSerializerOptions()); |
|||
|
|||
if (!Options.HttpEndpoint.IsNullOrWhiteSpace()) |
|||
{ |
|||
builder.UseHttpEndpoint(Options.HttpEndpoint); |
|||
} |
|||
|
|||
if (!Options.GrpcEndpoint.IsNullOrWhiteSpace()) |
|||
{ |
|||
builder.UseGrpcEndpoint(Options.GrpcEndpoint); |
|||
} |
|||
|
|||
return builder.Build(); |
|||
} |
|||
|
|||
private readonly static ConcurrentDictionary<string, JsonSerializerOptions> JsonSerializerOptionsCache = new ConcurrentDictionary<string, JsonSerializerOptions>(); |
|||
|
|||
protected virtual Task<JsonSerializerOptions> CreateJsonSerializerOptions() |
|||
{ |
|||
return Task.FromResult(JsonSerializerOptionsCache.GetOrAdd(nameof(AbpDaprClientFactory), |
|||
_ => new JsonSerializerOptions(SystemTextJsonSerializerOptions.JsonSerializerOptions))); |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Dapr; |
|||
|
|||
[DependsOn(typeof(AbpJsonModule))] |
|||
public class AbpDaprModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
Configure<AbpDaprOptions>(configuration.GetSection("Dapr")); |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace Volo.Abp.Dapr; |
|||
|
|||
public class AbpDaprOptions |
|||
{ |
|||
public string AppId { get; set; } |
|||
|
|||
public string HttpEndpoint { get; set; } |
|||
|
|||
public string GrpcEndpoint { get; set; } |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
namespace Volo.Abp.Dapr; |
|||
|
|||
public interface IDaprSerializer |
|||
{ |
|||
byte[] Serialize(object obj); |
|||
|
|||
object Deserialize(byte[] value, Type type); |
|||
|
|||
T Deserialize<T>(byte[] value); |
|||
|
|||
string SerializeToString(object obj); |
|||
|
|||
object Deserialize(string value, Type type); |
|||
|
|||
T Deserialize<T>(string value); |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
using System.Text; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace Volo.Abp.Dapr; |
|||
|
|||
public class Utf8JsonDaprSerializer : IDaprSerializer, ITransientDependency |
|||
{ |
|||
private readonly IJsonSerializer _jsonSerializer; |
|||
|
|||
public Utf8JsonDaprSerializer(IJsonSerializer jsonSerializer) |
|||
{ |
|||
_jsonSerializer = jsonSerializer; |
|||
} |
|||
|
|||
public byte[] Serialize(object obj) |
|||
{ |
|||
return Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(obj)); |
|||
} |
|||
|
|||
public object Deserialize(byte[] value, Type type) |
|||
{ |
|||
return _jsonSerializer.Deserialize(type, Encoding.UTF8.GetString(value)); |
|||
} |
|||
|
|||
public T Deserialize<T>(byte[] value) |
|||
{ |
|||
return _jsonSerializer.Deserialize<T>(Encoding.UTF8.GetString(value)); |
|||
} |
|||
|
|||
public string SerializeToString(object obj) |
|||
{ |
|||
return _jsonSerializer.Serialize(obj); |
|||
} |
|||
|
|||
public object Deserialize(string value, Type type) |
|||
{ |
|||
return _jsonSerializer.Deserialize(type, value); |
|||
} |
|||
|
|||
public T Deserialize<T>(string value) |
|||
{ |
|||
return _jsonSerializer.Deserialize<T>(value); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||