Compare commits

...

10 Commits

Author SHA1 Message Date
8f722ce3c9 Add DigitalData.Auth.Claims project and enhance JWT handling
Added the `DigitalData.Auth.Claims` project to the solution,
including its build and debug configurations. Updated
`DigitalData.Auth.API.csproj` to reference the new project
and incremented version numbers to 1.4.0.

Enhanced `Program.cs` with a new JWT signature handler for
`EnvelopeReceiverSecretDto`, generating claims for envelope
and receiver-specific data. Added `DirectorySearchService`
to the service collection, configured via `DirectorySearchOptions`.
2026-05-29 08:48:10 +02:00
2fed1baff5 Add JWT token support for EnvelopeReceiver entities
Enhanced the `AuthController` to support JWT token generation
for `EnvelopeReceiverSecretDto` entities. Added a new
dependency `IJwtSignatureHandler<EnvelopeReceiverSecretDto>`
and updated the constructor to inject it.

Refactored the `CreateTokenForEnvelopeReceiver` method:
- Added a `cookie` query parameter to control token delivery.
- Implemented consumer validation using `_consumerService`.
- Added token descriptor retrieval from `_keyPool`.
- Improved `AccessCode` validation for `EnvelopeReceiver`.
- Added logic to set tokens as cookies or return in the body.

Updated `using` directives to include required namespaces.
Improved error handling, readability, and flexibility in
token generation and delivery.
2026-05-29 08:47:54 +02:00
3ba55cbe9a Add DigitalData.Auth.Claims project and EnvelopeClaimNames
Added a new .NET project `DigitalData.Auth.Claims` targeting `net8.0`
with metadata for NuGet packaging. The project is configured to
not generate a NuGet package on build.

Introduced the `EnvelopeClaimNames` static class to define strongly-typed
constants for custom JWT claim names specific to envelope receiver tokens.
These include `EnvelopeId`, `EnvelopeUuid`, `ReceiverId`, and
`ReceiverSignature`. Added XML documentation for all constants.
2026-05-29 08:47:18 +02:00
90d74282d8 Add envelope receiver token endpoint to AuthController
Refactor `AuthController` to include `IMediator` dependency and
introduce a new `CreateTokenForEnvelopeReceiver` API endpoint
to handle envelope receiver authentication.

- Updated `using` directives to remove unused namespaces and
  add required ones for new functionality.
- Added `ReceiverLogin` model to represent envelope receiver
  login credentials.
- Implemented `ReadEnvelopeReceiverSecretQuery` to validate
  access codes for envelope receivers.
- Cleaned up unused fields and dependencies in `AuthController`.
2026-05-29 00:21:36 +02:00
a7a386924e Update JwtBearer and EnvelopeGenerator packages
Added Microsoft.AspNetCore.Authentication.JwtBearer (8.0.17) to the test project.
Updated EnvelopeGenerator to version 1.2.0.3 in the API project.
Aligned JwtBearer version to 8.0.17 for the net8.0 target framework.
2026-05-29 00:21:10 +02:00
e55a6a3663 Add global exception handling middleware
Introduced `ExceptionHandlingMiddleware` to handle exceptions
globally, log errors, and return appropriate JSON responses.
Registered the middleware in `Program.cs` to ensure all requests
are processed through it. Added localization support in
`Program.cs` to enable localized error messages and other
features.
2026-05-29 00:20:55 +02:00
e80ad19c96 Add MediatR package to enable Mediator design pattern
The `MediatR` package (version 12.5.0) was added to the
`DigitalData.Auth.API.csproj` file. This introduces support
for the Mediator design pattern, which helps reduce coupling
between components and facilitates structured communication
via requests, commands, or queries.
2026-05-28 22:37:29 +02:00
d2d992b41e Add DbTriggerParams section to appsettings.json
Introduced a new `DbTriggerParams` configuration section in
`appsettings.json` to define database triggers for various
application components.

The section includes keys such as `Envelope`, `History`,
`EmailOut`, `EnvelopeReceiverReadOnly`, `Receiver`, and
`EmailTemplate`, each with corresponding arrays of trigger
names. This change enhances the application's ability to
manage database events in a structured and configurable way.
2026-05-28 22:30:28 +02:00
ff8d683040 Add EF Core SQL Server support to the project
Added `Microsoft.EntityFrameworkCore.SqlServer` package to the
`DigitalData.Auth.API.csproj` file to enable SQL Server as the
database provider. Updated `Program.cs` to include the
`Microsoft.EntityFrameworkCore` namespace for database interaction.
2026-05-28 22:26:48 +02:00
163916e330 Update dependencies and integrate EnvelopeGenerator
Updated `DigitalData.Auth.Tests.csproj` to include `Microsoft.EntityFrameworkCore` version `8.0.17`.

Refactored `AuthController.cs` to remove unused imports and update to the latest `DigitalData.Core.Abstraction.Application` namespaces.

Streamlined `DigitalData.Auth.API.csproj`:
- Changed target framework to `net8.0`.
- Upgraded `DigitalData.Core.Abstractions` to `4.3.0` and `DigitalData.Core.Application` to `3.4.0`.
- Added `EnvelopeGenerator` and `Microsoft.EntityFrameworkCore` dependencies.
- Removed outdated `UserManager` dependencies.

Enhanced `Program.cs`:
- Integrated `EnvelopeGenerator` services with database context and caching configuration.
- Removed `AddUserManager` service registration.
- Added SQL Server logging and error handling for `DbContext`.

These changes improve maintainability, adopt modern frameworks, and introduce new functionality with `EnvelopeGenerator`.
2026-05-28 22:26:31 +02:00
10 changed files with 312 additions and 21 deletions

View File

@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- NuGet package metadata -->
<PackageId>DigitalData.Auth.Claims</PackageId>
<Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company>
<Product>DigitalData.Auth.Claims</Product>
<Description>
Provides strongly-typed JWT claim name constants for the DigitalData.Auth ecosystem.
Includes domain-specific claim definitions (e.g. envelope and receiver claims)
to be shared across API, client, and consumer projects.
</Description>
<Copyright>Copyright 2026 Digital Data GmbH</Copyright>
<RepositoryUrl>https://git.dd/AppStd/DigitalData.Auth</RepositoryUrl>
<PackageTags>digital data auth claims jwt constants</PackageTags>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Version>1.0.0</Version>
<AssemblyVersion>1.0.0</AssemblyVersion>
<FileVersion>1.0.0</FileVersion>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,34 @@
namespace DigitalData.Auth.Claims
{
/// <summary>
/// Defines the custom JWT claim names used for envelope receiver tokens.
/// These claims are domain-specific and have no equivalent in <see cref="Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames"/>.
/// </summary>
public static class EnvelopeClaimNames
{
/// <summary>
/// The database primary key of the envelope.
/// Claim name: <c>envelope_id</c>
/// </summary>
public const string EnvelopeId = "envelope_id";
/// <summary>
/// The unique identifier (UUID) of the envelope.
/// Claim name: <c>envelope_uuid</c>
/// </summary>
public const string EnvelopeUuid = "envelope_uuid";
/// <summary>
/// The database primary key of the envelope receiver.
/// Claim name: <c>receiver_id</c>
/// </summary>
public const string ReceiverId = "receiver_id";
/// <summary>
/// The cryptographic signature of the envelope receiver.
/// Together with <see cref="EnvelopeUuid"/>, it forms the unique envelope key via <c>ToEnvelopeKey()</c>.
/// Claim name: <c>receiver_sig</c>
/// </summary>
public const string ReceiverSignature = "receiver_sig";
}
}

View File

@@ -16,6 +16,8 @@
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="DigitalData.Core.Security" Version="1.2.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.17" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" />

View File

@@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Auth.Tests", "D
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Auth.Abstractions", "DigitalData.Auth.Abstractions\DigitalData.Auth.Abstractions.csproj", "{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Auth.Claims", "DigitalData.Auth.Claims\DigitalData.Auth.Claims.csproj", "{5AF91476-1897-46D2-B9E0-323EB9D39B15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -35,6 +37,10 @@ Global
{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Release|Any CPU.Build.0 = Release|Any CPU
{5AF91476-1897-46D2-B9E0-323EB9D39B15}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{5AF91476-1897-46D2-B9E0-323EB9D39B15}.Debug|Any CPU.Build.0 = Release|Any CPU
{5AF91476-1897-46D2-B9E0-323EB9D39B15}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5AF91476-1897-46D2-B9E0-323EB9D39B15}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -44,6 +50,7 @@ Global
{521A2BC0-AEA8-4500-AAA9-1951556EDF9F} = {C0123B52-5168-4C87-98A0-11A220EC392F}
{AF517FD9-3EBE-4452-AAEC-DFF17CC270E3} = {C0123B52-5168-4C87-98A0-11A220EC392F}
{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C} = {C0123B52-5168-4C87-98A0-11A220EC392F}
{5AF91476-1897-46D2-B9E0-323EB9D39B15} = {C0123B52-5168-4C87-98A0-11A220EC392F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4D163037-043C-41AE-AB94-C7314F2C38DA}

View File

@@ -1,16 +1,26 @@
using DigitalData.Auth.API.Config;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User;
using DigitalData.Core.Abstractions.Application;
using DigitalData.Auth.API.Entities;
using DigitalData.Auth.API.Models;
using DigitalData.Auth.API.Services.Contracts;
using DigitalData.Auth.API.Entities;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstractions.Security.Services;
using DigitalData.Core.Abstraction.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using DigitalData.Core.Abstractions.Security.Extensions;
using DigitalData.Core.Abstractions.Security.Services;
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
using EnvelopeGenerator.Application.Receivers.Queries;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.FileSystemGlobbing;
using Microsoft.Extensions.Options;
using System.Net;
using System.Text;
namespace DigitalData.Auth.API.Controllers
{
@@ -18,6 +28,8 @@ namespace DigitalData.Auth.API.Controllers
[ApiController]
public class AuthController : ControllerBase
{
private readonly IJwtSignatureHandler<EnvelopeReceiverSecretDto> _erSignatureHandler;
private readonly IJwtSignatureHandler<UserReadDto> _userSignatureHandler;
private readonly IJwtSignatureHandler<Consumer> _consumerSignatureHandler;
@@ -36,7 +48,9 @@ namespace DigitalData.Auth.API.Controllers
private readonly IOptionsMonitor<BackdoorParams> _backdoorMonitor;
public AuthController(IJwtSignatureHandler<UserReadDto> userSignatureHandler, IOptions<AuthApiParams> cookieParamsOptions, IAsymmetricKeyPool keyPool, ILogger<AuthController> logger, IUserService userService, IDirectorySearchService dirSearchService, IConsumerService consumerService, IJwtSignatureHandler<Consumer> apiSignatureHandler, IOptionsMonitor<BackdoorParams> backdoorMonitor)
private readonly IMediator _mediator;
public AuthController(IJwtSignatureHandler<UserReadDto> userSignatureHandler, IOptions<AuthApiParams> cookieParamsOptions, IAsymmetricKeyPool keyPool, ILogger<AuthController> logger, IUserService userService, IDirectorySearchService dirSearchService, IConsumerService consumerService, IJwtSignatureHandler<Consumer> apiSignatureHandler, IOptionsMonitor<BackdoorParams> backdoorMonitor, IMediator mediator, IJwtSignatureHandler<EnvelopeReceiverSecretDto> erSignatureHandler)
{
_apiParams = cookieParamsOptions.Value;
_userSignatureHandler = userSignatureHandler;
@@ -47,6 +61,8 @@ namespace DigitalData.Auth.API.Controllers
_consumerService = consumerService;
_consumerSignatureHandler = apiSignatureHandler;
_backdoorMonitor = backdoorMonitor;
_mediator = mediator;
_erSignatureHandler = erSignatureHandler;
}
private async Task<IActionResult> CreateTokenAsync(UserLogin login, string consumerName, bool cookie = true)
@@ -210,5 +226,43 @@ namespace DigitalData.Auth.API.Controllers
[HttpGet("check")]
[Authorize]
public IActionResult Check() => Ok();
[HttpPost("envelope-receiver/{key}")]
public async Task<IActionResult> CreateTokenForEnvelopeReceiver([FromRoute]string key, [FromForm] ReceiverLogin receiverLogin, [FromQuery] bool cookie = true, CancellationToken cancel = default)
{
//find the consumer
var consumer = await _consumerService.ReadByNameAsync("sign-flow");
if (consumer is null)
return Unauthorized();
if (!_keyPool.TokenDescriptors.TryGet(_apiParams.Issuer, consumer.Audience, out var descriptor))
return StatusCode(StatusCodes.Status500InternalServerError);
// find receiver
var er = await _mediator.Send(new ReadEnvelopeReceiverSecretQuery()
{
Key = key
}, cancel);
if (er is null)
return NotFound();
// check acccess code
if (er.AccessCode != receiverLogin.AccessCode)
return Unauthorized();
// create token
var token = _erSignatureHandler.WriteToken(er, descriptor);
//set cookie
if (cookie)
{
var cookieOptions = consumer.CookieOptions ?? _apiParams.DefaultCookieOptions;
Response.Cookies.Append(_apiParams.DefaultCookieName, token, cookieOptions.Create(lifetime: descriptor.Lifetime));
return Ok();
}
else
return Ok(token);
}
}
}

View File

@@ -1,29 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>1.3.0</Version>
<AssemblyVersion>1.3.0</AssemblyVersion>
<FileVersion>1.3.0</FileVersion>
<Version>1.4.0</Version>
<AssemblyVersion>1.4.0</AssemblyVersion>
<FileVersion>1.4.0</FileVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="4.3.0" />
<PackageReference Include="DigitalData.Core.Abstractions.Security" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.4.0" />
<PackageReference Include="DigitalData.Core.Security" Version="1.2.2" />
<PackageReference Include="EnvelopeGenerator" Version="1.2.0.3" />
<PackageReference Include="MediatR" Version="12.5.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.17" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.3.1" />
<PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
<PackageReference Include="UserManager.Application" Version="3.1.2" />
<PackageReference Include="UserManager.Domain" Version="3.0.1" />
<PackageReference Include="UserManager.Infrastructure" Version="3.0.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
@@ -31,11 +32,12 @@
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.12" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.17" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\DigitalData.Auth.Abstractions\DigitalData.Auth.Abstractions.csproj" />
<ProjectReference Include="..\..\DigitalData.Auth.Claims\DigitalData.Auth.Claims.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,99 @@
using DigitalData.Core.Exceptions;
using Microsoft.AspNetCore.Mvc;
using System.Net;
namespace DigitalData.Auth.API.Middleware;
/// <summary>
/// Middleware for handling exceptions globally in the application.
/// Captures exceptions thrown during the request pipeline execution,
/// logs them, and returns an appropriate HTTP response with a JSON error details.
/// </summary>
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="ExceptionHandlingMiddleware"/> class.
/// </summary>
/// <param name="next">The next middleware in the request pipeline.</param>
/// <param name="logger">The logger instance for logging exceptions.</param>
public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
/// <summary>
/// Invokes the middleware to handle the HTTP request.
/// </summary>
/// <param name="context">The HTTP context of the current request.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context); // Continue down the pipeline
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex, _logger);
}
}
/// <summary>
/// Handles exceptions by logging them and writing an appropriate JSON response.
/// </summary>
/// <param name="context">The HTTP context of the current request.</param>
/// <param name="exception">The exception that occurred.</param>
/// <param name="logger">The logger instance for logging the exception.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
private static async Task HandleExceptionAsync(HttpContext context, Exception exception, ILogger logger)
{
context.Response.ContentType = "application/json";
ValidationProblemDetails? details = null;
switch (exception)
{
case BadRequestException badRequestEx:
if (badRequestEx.InnerException is not null)
{
logger.LogError(
badRequestEx.InnerException,
"BadRequestException inner exception captured.");
}
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
details = new()
{
Title = "Bad Procedure",
Detail = badRequestEx.Message
};
break;
case NotFoundException notFoundEx:
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
details = new()
{
Title = "Not Found",
Detail = notFoundEx.Message
};
break;
default:
logger.LogError(exception, "Unhandled exception occurred.");
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
details = new()
{
Title = "Internal Server Error",
Detail = "An unexpected error occurred. Please try again later."
};
break;
}
if (details is not null)
await context.Response.WriteAsJsonAsync(details);
}
}

View File

@@ -0,0 +1,4 @@
namespace DigitalData.Auth.API.Models
{
public record ReceiverLogin(string AccessCode);
}

View File

@@ -1,6 +1,7 @@
using DigitalData.Auth.API.Config;
using DigitalData.Auth.API.Entities;
using DigitalData.Auth.API.Hubs;
using DigitalData.Auth.API.Middleware;
using DigitalData.Auth.API.Services;
using DigitalData.Core.Abstractions.Security.Extensions;
using DigitalData.Core.Abstractions.Security.Services;
@@ -8,7 +9,14 @@ using DigitalData.Core.Application;
using DigitalData.Core.Security.Extensions;
using DigitalData.UserManager.Application;
using DigitalData.UserManager.Application.DTOs.User;
using DigitalData.UserManager.DependencyInjection;
using DigitalData.Auth.Claims;
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.DependencyInjection;
using EnvelopeGenerator.Infrastructure;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
@@ -69,12 +77,30 @@ try
return claims;
});
builder.Services.AddJwtSignatureHandler<EnvelopeReceiverSecretDto>(er =>
{
var claims = new Dictionary<string, object>
{
{ JwtRegisteredClaimNames.Sub, (er.Envelope!.Uuid, er.Receiver!.Signature).ToEnvelopeKey() },
{ EnvelopeClaimNames.EnvelopeId, er.Envelope.Id },
{ EnvelopeClaimNames.EnvelopeUuid, er.Envelope.Uuid },
{ EnvelopeClaimNames.ReceiverId, er.Receiver.Id },
{ EnvelopeClaimNames.ReceiverSignature, er.Receiver.Signature },
{ JwtRegisteredClaimNames.Email, er.Receiver.EmailAddress ?? string.Empty },
{ JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
{ ClaimTypes.Role, "receiver" }
};
return claims;
});
builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions"));
builder.Services.AddSignalR();
var cnn_str = builder.Configuration.GetConnectionString("Default") ?? throw new InvalidOperationException("Default connection string is not found.");
builder.Services.AddUserManager(cnn_str);
builder.Services.AddLocalization();
builder.Services.AddControllers();
@@ -146,8 +172,34 @@ try
};
});
// Add envelope generator services
builder.Services.AddEnvelopeGenerator(config,
infrastructureOptions: opt =>
{
opt.AddDbTriggerParams(config);
opt.AddDbContext((provider, options) =>
{
var logger = provider.GetRequiredService<ILogger<EGDbContext>>();
options.UseSqlServer(cnn_str)
.LogTo(log => logger.LogInformation("{log}", log), Microsoft.Extensions.Logging.LogLevel.Trace)
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
});
},
options: opt =>
{
opt.SqlCacheOptions = new()
{
ConnectionString = cnn_str,
SchemaName = "dbo",
TableName = "TBDD_CACHE"
};
});
var app = builder.Build();
app.UseMiddleware<ExceptionHandlingMiddleware>();
issuerSigningKeyInitiator = new Lazy<SecurityKey>(() =>
{
var factory = app.Services.GetRequiredService<IAsymmetricKeyPool>();

View File

@@ -117,5 +117,13 @@
"writeTo": "criticalLogs"
}
]
},
"DbTriggerParams": {
"Envelope": [ "TBSIG_ENVELOPE_AFT_INS" ],
"History": [ "TBSIG_ENVELOPE_HISTORY_AFT_INS" ],
"EmailOut": [ "TBEMLP_EMAIL_OUT_AFT_INS", "TBEMLP_EMAIL_OUT_AFT_UPD" ],
"EnvelopeReceiverReadOnly": [ "TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD" ],
"Receiver": [],
"EmailTemplate": [ "TBSIG_EMAIL_TEMPLATE_AFT_UPD" ]
}
}