Add sample project for WorkflowContext module
This commit is contained in:
parent
90e4b4680c
commit
be911646e6
7
Elsa.sln
7
Elsa.sln
|
|
@ -174,6 +174,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.HangfireIntegr
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.ProtoActorRuntime", "src\samples\aspnet\Elsa.Samples.ProtoActorRuntime\Elsa.Samples.ProtoActorRuntime.csproj", "{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.WorkflowContexts", "src\samples\aspnet\Elsa.Samples.WorkflowContexts\Elsa.Samples.WorkflowContexts.csproj", "{F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -432,6 +434,10 @@ Global
|
|||
{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{155227F0-A33B-40AA-A4B4-06F813EB921B} = {61017E64-6D00-49CB-9E81-5002DC8F7D5F}
|
||||
|
|
@ -508,5 +514,6 @@ Global
|
|||
{B0312D9E-FA30-43E9-B666-40A8782D6E1C} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
|
||||
{D2614FC7-102F-4F78-BB06-7C87304A10BA} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
|
||||
{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
|
||||
{F88AB1C2-100E-459F-B2BE-5F2ACF050A0A} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
namespace Elsa.Samples.WorkflowContexts.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// A sample repository of customers.
|
||||
/// </summary>
|
||||
public interface ICustomerStore
|
||||
{
|
||||
Task<Customer?> GetAsync(string id, CancellationToken cancellationToken = default);
|
||||
Task SaveAsync(Customer customer, CancellationToken cancellationToken = default);
|
||||
}
|
||||
20
src/samples/aspnet/Elsa.Samples.WorkflowContexts/Dockerfile
Normal file
20
src/samples/aspnet/Elsa.Samples.WorkflowContexts/Dockerfile
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["src/samples/aspnet/Elsa.Samples.WorkflowContexts/Elsa.Samples.WorkflowContexts.csproj", "src/samples/aspnet/Elsa.Samples.WorkflowContexts/"]
|
||||
RUN dotnet restore "src/samples/aspnet/Elsa.Samples.WorkflowContexts/Elsa.Samples.WorkflowContexts.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/src/samples/aspnet/Elsa.Samples.WorkflowContexts"
|
||||
RUN dotnet build "Elsa.Samples.WorkflowContexts.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "Elsa.Samples.WorkflowContexts.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "Elsa.Samples.WorkflowContexts.dll"]
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\..\..\.dockerignore">
|
||||
<Link>.dockerignore</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\bundles\Elsa\Elsa.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.Email\Elsa.Email.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.EntityFrameworkCore.Sqlite\Elsa.EntityFrameworkCore.Sqlite.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.EntityFrameworkCore\Elsa.EntityFrameworkCore.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.Identity\Elsa.Identity.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.JavaScript\Elsa.JavaScript.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.Scheduling\Elsa.Scheduling.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.WorkflowContexts\Elsa.WorkflowContexts.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.Workflows.Api\Elsa.Workflows.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace Elsa.Samples.WorkflowContexts.Contracts;
|
||||
|
||||
public class Customer
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Phone { get; set; }
|
||||
public string Website { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using Elsa.Expressions.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Samples.WorkflowContexts.Contracts;
|
||||
using Elsa.Samples.WorkflowContexts.Providers;
|
||||
|
||||
namespace Elsa.Samples.WorkflowContexts.Extensions;
|
||||
|
||||
public static class ExpressionExecutionContextExtensions
|
||||
{
|
||||
public static Customer GetCustomer(this ExpressionExecutionContext context) => context.GetWorkflowContext<CustomerWorkflowContextProvider, Customer>();
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using Elsa.Workflows.Core.Models;
|
||||
|
||||
namespace Elsa.Samples.WorkflowContexts.Extensions;
|
||||
|
||||
public static class WorkflowExecutionContextExtensions
|
||||
{
|
||||
private const string CustomerIdKey = "CustomerId";
|
||||
public static string? GetCustomerId(this WorkflowExecutionContext context) => context.GetProperty<string>(CustomerIdKey);
|
||||
public static void SetCustomerId(this WorkflowExecutionContext context, string? customerId) => context.SetProperty(CustomerIdKey, customerId);
|
||||
}
|
||||
106
src/samples/aspnet/Elsa.Samples.WorkflowContexts/Program.cs
Normal file
106
src/samples/aspnet/Elsa.Samples.WorkflowContexts/Program.cs
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
using Elsa.EntityFrameworkCore.Extensions;
|
||||
using Elsa.EntityFrameworkCore.Modules.Management;
|
||||
using Elsa.EntityFrameworkCore.Modules.Runtime;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Samples.WorkflowContexts.Contracts;
|
||||
using Elsa.Samples.WorkflowContexts.Providers;
|
||||
using Elsa.Samples.WorkflowContexts.Services;
|
||||
using Elsa.Samples.WorkflowContexts.Workflows;
|
||||
using Elsa.Workflows.Core.Middleware.Workflows;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var services = builder.Services;
|
||||
var configuration = builder.Configuration;
|
||||
var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!;
|
||||
var identitySection = configuration.GetSection("Identity");
|
||||
var identityTokenSection = identitySection.GetSection("Tokens");
|
||||
|
||||
// Add Elsa services.
|
||||
services
|
||||
.AddElsa(elsa => elsa
|
||||
.AddActivitiesFrom<Program>()
|
||||
.AddWorkflow<CustomerCommunicationsWorkflow>()
|
||||
.UseIdentity(identity =>
|
||||
{
|
||||
identity.IdentityOptions = options => identitySection.Bind(options);
|
||||
identity.TokenOptions = options => identityTokenSection.Bind(options);
|
||||
identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options));
|
||||
identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options));
|
||||
identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options));
|
||||
})
|
||||
.UseDefaultAuthentication()
|
||||
.UseWorkflows(workflows => workflows.WithWorkflowExecutionPipeline(pipeline => pipeline
|
||||
.Reset()
|
||||
.UsePersistentVariables()
|
||||
.UseBookmarkPersistence()
|
||||
.UseWorkflowExecutionLogPersistence()
|
||||
.UseWorkflowStatePersistence()
|
||||
.UseWorkflowContexts()
|
||||
.UseDefaultActivityScheduler()
|
||||
))
|
||||
.UseWorkflowManagement(management =>
|
||||
{
|
||||
// Use EF core for workflow definitions and instances.
|
||||
management.UseWorkflowInstances(m => m.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)));
|
||||
management.UseEntityFrameworkCore(m => m.UseSqlite(sqliteConnectionString));
|
||||
})
|
||||
.UseWorkflowRuntime(runtime =>
|
||||
{
|
||||
// Use EF core for triggers and bookmarks.
|
||||
runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString));
|
||||
|
||||
// Use EF core for execution log records.
|
||||
runtime.UseExecutionLogRecords(log => log.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)));
|
||||
|
||||
// Use the default workflow runtime with EF core.
|
||||
runtime.UseDefaultRuntime(defaultRuntime => defaultRuntime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)));
|
||||
|
||||
// Install a workflow state exporter to capture workflow states and store them in IWorkflowInstanceStore.
|
||||
runtime.UseAsyncWorkflowStateExporter();
|
||||
})
|
||||
.UseScheduling()
|
||||
.UseWorkflowsApi(api => api.AddFastEndpointsAssembly<Program>())
|
||||
.UseJavaScript()
|
||||
.UseLiquid()
|
||||
.UseHttp()
|
||||
.UseEmail(email => email.ConfigureOptions = options => configuration.GetSection("Smtp").Bind(options))
|
||||
);
|
||||
|
||||
// Add health checks.
|
||||
services.AddHealthChecks();
|
||||
|
||||
// Add CORS.
|
||||
services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()));
|
||||
|
||||
// Add domain services.
|
||||
services.AddSingleton<ICustomerStore, MemoryCustomerStore>();
|
||||
|
||||
// Add workflow context providers.
|
||||
services.AddWorkflowContextProvider<CustomerWorkflowContextProvider>();
|
||||
|
||||
// Configure middleware pipeline.
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
app.UseDeveloperExceptionPage();
|
||||
|
||||
// CORS.
|
||||
app.UseCors();
|
||||
|
||||
// Health checks.
|
||||
app.MapHealthChecks("/");
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
// Elsa API endpoints for designer.
|
||||
app.UseWorkflowsApi();
|
||||
|
||||
// Captures unhandled exceptions and returns a JSON response.
|
||||
app.UseJsonSerializationErrorHandler();
|
||||
|
||||
// Elsa HTTP Endpoint activities
|
||||
app.UseWorkflows();
|
||||
|
||||
// Run.
|
||||
app.Run();
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:32709",
|
||||
"sslPort": 44321
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5286",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7019;http://localhost:5286",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using Elsa.Samples.WorkflowContexts.Contracts;
|
||||
using Elsa.Samples.WorkflowContexts.Extensions;
|
||||
using Elsa.WorkflowContexts.Abstractions;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
|
||||
namespace Elsa.Samples.WorkflowContexts.Providers;
|
||||
|
||||
public class CustomerWorkflowContextProvider : WorkflowContextProvider<Customer>
|
||||
{
|
||||
private readonly ICustomerStore _customerStore;
|
||||
|
||||
public CustomerWorkflowContextProvider(ICustomerStore customerStore)
|
||||
{
|
||||
_customerStore = customerStore;
|
||||
}
|
||||
|
||||
protected override async ValueTask<Customer?> LoadAsync(WorkflowExecutionContext workflowExecutionContext)
|
||||
{
|
||||
var customerId = workflowExecutionContext.GetCustomerId();
|
||||
return customerId != null ? await _customerStore.GetAsync(customerId) : null;
|
||||
}
|
||||
|
||||
protected override async ValueTask SaveAsync(WorkflowExecutionContext workflowExecutionContext, Customer? context)
|
||||
{
|
||||
if (context != null)
|
||||
{
|
||||
await _customerStore.SaveAsync(context);
|
||||
workflowExecutionContext.SetCustomerId(context.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/samples/aspnet/Elsa.Samples.WorkflowContexts/README.md
Normal file
10
src/samples/aspnet/Elsa.Samples.WorkflowContexts/README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Server
|
||||
|
||||
This project represents an Elsa application that hosts workflows and exposes API endpoints to manage & execute workflows.
|
||||
|
||||
## Secrets
|
||||
The following are the secrets stored in hashed form in appsettings.json:
|
||||
|
||||
**API key**: `4E753976726458745954355043687772-e54d5a2c-33a3-4c05-a216-b09569062aed`
|
||||
**Admin user**: `admin`
|
||||
**Admin password**: `password`
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
using Elsa.Samples.WorkflowContexts.Contracts;
|
||||
|
||||
namespace Elsa.Samples.WorkflowContexts.Services;
|
||||
|
||||
/// <summary>
|
||||
/// An in-memory implementation of <see cref="ICustomerStore"/>.
|
||||
/// </summary>
|
||||
public class MemoryCustomerStore : ICustomerStore
|
||||
{
|
||||
private readonly IDictionary<string, Customer> _customers = CreateCustomersDatabase();
|
||||
|
||||
public Task<Customer?> GetAsync(string id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(_customers.TryGetValue(id, out var customer) ? customer : null);
|
||||
}
|
||||
|
||||
public Task SaveAsync(Customer customer, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_customers[customer.Id] = customer;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static IDictionary<string, Customer> CreateCustomersDatabase()
|
||||
{
|
||||
return new Dictionary<string, Customer>
|
||||
{
|
||||
["1"] = new()
|
||||
{
|
||||
Id = "1",
|
||||
Name = "John Doe",
|
||||
Email = "john.doe@acme.com",
|
||||
Phone = "+1 555 123 4567",
|
||||
Website = "https://acme.com"
|
||||
},
|
||||
["2"] = new()
|
||||
{
|
||||
Id = "2",
|
||||
Name = "Alice Smith",
|
||||
Email = "alice.smith@example.com",
|
||||
Phone = "+1 555 123 4567",
|
||||
Website = "https://example.com"
|
||||
},
|
||||
["3"] = new()
|
||||
{
|
||||
Id = "3",
|
||||
Name = "Bob Jones",
|
||||
Email = "bob.jones@supplier.com",
|
||||
Phone = "+1 555 123 4567",
|
||||
Website = "https://supplier.com"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
using Elsa.Email.Activities;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Samples.WorkflowContexts.Extensions;
|
||||
using Elsa.Samples.WorkflowContexts.Providers;
|
||||
using Elsa.Scheduling.Activities;
|
||||
using Elsa.Workflows.Core.Abstractions;
|
||||
using Elsa.Workflows.Core.Activities;
|
||||
using Elsa.Workflows.Core.Contracts;
|
||||
|
||||
namespace Elsa.Samples.WorkflowContexts.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// A workflow that sends annoying emails to customers.
|
||||
/// </summary>
|
||||
public class CustomerCommunicationsWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
builder.AddWorkflowContextProvider<CustomerWorkflowContextProvider>();
|
||||
|
||||
builder.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
Inline.From(context => context.WorkflowExecutionContext.SetCustomerId(context.GetInput<string>("CustomerId"))),
|
||||
Delay.FromSeconds(5),
|
||||
new SendEmail
|
||||
{
|
||||
Subject = new(context => $"Welcome to our family, {context.GetCustomer().Name}!"),
|
||||
Body = new("Welcome aboard!"),
|
||||
To = new(context => new[] { context.GetCustomer().Email })
|
||||
},
|
||||
Delay.FromSeconds(5),
|
||||
new SendEmail
|
||||
{
|
||||
Subject = new(context => $"{context.GetCustomer().Name}, we got great deals for you!"),
|
||||
Body = new("Get your creditcard ready!"),
|
||||
To = new(context => new[] { context.GetCustomer().Email })
|
||||
},
|
||||
Delay.FromSeconds(5),
|
||||
new SendEmail
|
||||
{
|
||||
Subject = new(context => $"{context.GetCustomer().Name}, you're missing out!"),
|
||||
Body = new("Sale ends in 2 hours!"),
|
||||
To = new(context => new[] { context.GetCustomer().Email })
|
||||
},
|
||||
Delay.FromSeconds(5),
|
||||
new SendEmail
|
||||
{
|
||||
Subject = new(context => $"{context.GetCustomer().Name}, the clock is ticking!"),
|
||||
Body = new("Tick tik tick!"),
|
||||
To = new(context => new[] { context.GetCustomer().Email })
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"Elsa.Mediator": "Warning",
|
||||
"MassTransit": "Warning",
|
||||
"Microsoft.Extensions.Http": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information",
|
||||
"Microsoft.EntityFrameworkCore": "Warning",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"System.Net.Http": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;"
|
||||
},
|
||||
"Identity": {
|
||||
"Tokens": {
|
||||
"SigningKey": "secret-signing-key",
|
||||
"AccessTokenLifetime": "1:00:00:00",
|
||||
"RefreshTokenLifetime": "1:00:10:00"
|
||||
},
|
||||
"Roles": [{
|
||||
"Id": "admin",
|
||||
"Name": "Administrator",
|
||||
"Permissions": ["*"]
|
||||
}],
|
||||
"Users": [
|
||||
{
|
||||
"Id": "a2323f46-42db-4e15-af8b-94238717d817",
|
||||
"Name": "admin",
|
||||
"HashedPassword": "TfKzh9RLix6FPcCNeHLkGrysFu3bYxqzGqduNdi8v1U=",
|
||||
"HashedPasswordSalt": "JEy9kBlhHCNsencitRHlGxmErmSgY+FVyMJulCH27Ds=",
|
||||
"Roles": ["admin"]
|
||||
}
|
||||
],
|
||||
"Applications": [{
|
||||
"id": "529572c2df854b13807b8bf23f1784cd",
|
||||
"name": "Postman",
|
||||
"roles": [
|
||||
"admin"
|
||||
],
|
||||
"clientId": "Nu9vrdXtYT5PChwr",
|
||||
"clientSecret": "011pp2C$|j01-qrMZpC9VC0F00XCJq(5",
|
||||
"hashedApiKey": "d0rDld3A+ugKmdctGtMzOLTYjQFkOlUWN+kt0VyW9D0=",
|
||||
"hashedApiKeySalt": "EnutGOyy5MuJWV0fF5jCQiciK7a8PU/DRF+fr6nekSY=",
|
||||
"hashedClientSecret": "ERia2zBcCSWb/9dvB0grQ9yf7fWgFrClNeR8A5RMTzk=",
|
||||
"hashedClientSecretSalt": "z3z8KmzHt+xkAj/zYTXcB8I7y0xAkLm95v4Er/oNqiY="
|
||||
}]
|
||||
},
|
||||
"Smtp": {
|
||||
"Host": "localhost",
|
||||
"Port": 2525,
|
||||
"DefaultSender": "noreply@crmservices.com"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
version: '3.9'
|
||||
|
||||
services:
|
||||
|
||||
smtp4dev:
|
||||
image: rnwood/smtp4dev:3.1.3-ci20211206101
|
||||
ports:
|
||||
- "3000:80"
|
||||
- "2525:25"
|
||||
|
||||
volumes:
|
||||
mssql-azuresql-edge-data:
|
||||
Loading…
Reference in a new issue