Compare commits
26 Commits
2fcea78574
...
eb96842122
| Author | SHA1 | Date | |
|---|---|---|---|
| eb96842122 | |||
| a8cb8f935c | |||
| 387456659d | |||
| 17e3a67fe5 | |||
| 632723de5a | |||
| 6611b92fdb | |||
| 5baa28bac8 | |||
| c965975f82 | |||
| d480dd3a36 | |||
| ae7f0b80f3 | |||
| ef7c9c2b97 | |||
| 27f0aae8e0 | |||
| 1b10162c85 | |||
| bd0426dbee | |||
| b1551537c8 | |||
| 95b2ab5aed | |||
| ebed51b46a | |||
| 0d2425c9cf | |||
| c6c8747d23 | |||
| eb345a0e4d | |||
| 1b95b9d7e0 | |||
| d99193979f | |||
| 8742ea6025 | |||
| 2b8edc697a | |||
| 7c88d4ed4b | |||
| a6be907307 |
@@ -18,7 +18,7 @@ namespace EnvelopeGenerator.API.Controllers;
|
||||
/// <summary>
|
||||
/// Manages annotations and signature lifecycle for envelopes.
|
||||
/// </summary>
|
||||
[Authorize(Roles = Role.Receiver.FullyAuth)]
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AnnotationController : ControllerBase
|
||||
@@ -54,7 +54,7 @@ public class AnnotationController : ControllerBase
|
||||
/// </summary>
|
||||
/// <param name="psPdfKitAnnotation">Annotation payload.</param>
|
||||
/// <param name="cancel">Cancellation token.</param>
|
||||
[Authorize(Roles = Role.Receiver.FullyAuth)]
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[HttpPost]
|
||||
[Obsolete("PSPDF Kit will no longer be used.")]
|
||||
public async Task<IActionResult> CreateOrUpdate([FromBody] PsPdfKitAnnotation? psPdfKitAnnotation = null, CancellationToken cancel = default)
|
||||
@@ -87,7 +87,7 @@ public class AnnotationController : ControllerBase
|
||||
/// Rejects the document for the current receiver.
|
||||
/// </summary>
|
||||
/// <param name="reason">Optional rejection reason.</param>
|
||||
[Authorize(Roles = Role.Receiver.FullyAuth)]
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[HttpPost("reject")]
|
||||
[Obsolete("Use MediatR")]
|
||||
public async Task<IActionResult> Reject([FromBody] string? reason = null)
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using EnvelopeGenerator.API.Controllers.Interfaces;
|
||||
using EnvelopeGenerator.API.Models;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus.
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public partial class AuthController(ILogger<AuthController> logger) : ControllerBase
|
||||
public partial class AuthController(IOptions<AuthTokenKeys> authTokenKeyOptions, IAuthorizationService authService) : ControllerBase, IAuthController
|
||||
{
|
||||
private readonly AuthTokenKeys authTokenKeys = authTokenKeyOptions.Value;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IAuthorizationService AuthService { get; } = authService;
|
||||
|
||||
/// <summary>
|
||||
/// Entfernt das Authentifizierungs-Cookie des Benutzers (AuthCookie)
|
||||
@@ -29,13 +37,19 @@ public partial class AuthController(ILogger<AuthController> logger) : Controller
|
||||
/// </remarks>
|
||||
/// <response code="200">Erfolgreich gelöscht, wenn der Benutzer ein berechtigtes Cookie hat.</response>
|
||||
/// <response code="401">Wenn es kein zugelassenes Cookie gibt, wird „nicht zugelassen“ zurückgegeben.</response>
|
||||
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
|
||||
[Authorize]
|
||||
[Authorize(Policy = AuthPolicy.SenderOrReceiver)]
|
||||
[HttpPost("logout")]
|
||||
public async Task<IActionResult> Logout()
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
if (await this.IsUserInPolicyAsync(AuthPolicy.Sender))
|
||||
Response.Cookies.Delete(authTokenKeys.Cookie);
|
||||
else if (await this.IsUserInPolicyAsync(AuthPolicy.ReceiverOrReceiverTFA))
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
else
|
||||
return Unauthorized();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -51,9 +65,12 @@ public partial class AuthController(ILogger<AuthController> logger) : Controller
|
||||
/// </remarks>
|
||||
/// <response code="200">Wenn es einen autorisierten Cookie gibt.</response>
|
||||
/// <response code="401">Wenn kein Cookie vorhanden ist oder nicht autorisierte.</response>
|
||||
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
|
||||
[HttpGet("check")]
|
||||
[Authorize]
|
||||
[HttpGet]
|
||||
public IActionResult IsAuthenticated() => Ok();
|
||||
public IActionResult Check(string? role = null)
|
||||
=> role is not null && !User.IsInRole(role)
|
||||
? Unauthorized()
|
||||
: Ok();
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using EnvelopeGenerator.API.Controllers.Interfaces;
|
||||
using EnvelopeGenerator.API.Extensions;
|
||||
using EnvelopeGenerator.Application.Documents.Queries;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
@@ -16,19 +17,24 @@ namespace EnvelopeGenerator.API.Controllers;
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class DocumentController(IMediator mediator, ILogger<DocumentController> logger) : ControllerBase
|
||||
public class DocumentController(IMediator mediator, IAuthorizationService authService) : ControllerBase, IAuthController
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IAuthorizationService AuthService => authService;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the document bytes receiver.
|
||||
/// </summary>
|
||||
/// <param name="query">Encoded envelope key.</param>
|
||||
/// <param name="cancel">Cancellation token.</param>
|
||||
[HttpGet]
|
||||
[Authorize(Roles = $"{Role.Sender},{Role.Receiver.FullyAuth}")]
|
||||
[Authorize(Policy = AuthPolicy.SenderOrReceiver)]
|
||||
public async Task<IActionResult> GetDocument(CancellationToken cancel, [FromQuery] ReadDocumentQuery? query = null)
|
||||
{
|
||||
// Sender: expects query with envelope key
|
||||
if (User.IsInRole(Role.Sender))
|
||||
if (await this.IsUserInPolicyAsync(AuthPolicy.Sender))
|
||||
{
|
||||
if (query is null)
|
||||
return BadRequest("Missing document query.");
|
||||
@@ -40,7 +46,7 @@ public class DocumentController(IMediator mediator, ILogger<DocumentController>
|
||||
}
|
||||
|
||||
// Receiver: resolve envelope id from claims
|
||||
if (User.IsInRole(Role.Receiver.FullyAuth))
|
||||
if (await this.IsUserInPolicyAsync(AuthPolicy.Receiver))
|
||||
{
|
||||
if (query is not null)
|
||||
return BadRequest("Query parameters are not allowed for receiver role.");
|
||||
|
||||
@@ -11,6 +11,7 @@ using EnvelopeGenerator.Application.Common.Dto;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
@@ -18,32 +19,18 @@ namespace EnvelopeGenerator.API.Controllers;
|
||||
/// Controller for managing temp templates.
|
||||
/// Steuerung zur Verwaltung von E-Mail-Vorlagen.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initialisiert eine neue Instanz der <see cref="EmailTemplateController"/>-Klasse.
|
||||
/// </remarks>
|
||||
/// <param name="mapper">
|
||||
/// <param name="repository">
|
||||
/// Die AutoMapper-Instanz, die zum Zuordnen von Objekten verwendet wird.
|
||||
/// </param>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class EmailTemplateController : ControllerBase
|
||||
[Authorize(Policy = AuthPolicy.Sender)]
|
||||
public class EmailTemplateController(IMapper mapper, IRepository<EmailTemplate> repository, IMediator mediator) : ControllerBase
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<EmailTemplate> _repository;
|
||||
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
/// <summary>
|
||||
/// Initialisiert eine neue Instanz der <see cref="EmailTemplateController"/>-Klasse.
|
||||
/// </summary>
|
||||
/// <param name="mapper">
|
||||
/// <param name="repository">
|
||||
/// Die AutoMapper-Instanz, die zum Zuordnen von Objekten verwendet wird.
|
||||
/// </param>
|
||||
[Obsolete("Use MediatR")]
|
||||
public EmailTemplateController(IMapper mapper, IRepository<EmailTemplate> repository, IMediator mediator)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repository = repository;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ruft E-Mail-Vorlagen basierend auf der angegebenen Abfrage ab.
|
||||
/// Gibt alles zurück, wenn keine Id- oder Typ-Informationen eingegeben wurden.
|
||||
@@ -63,12 +50,12 @@ public class EmailTemplateController : ControllerBase
|
||||
{
|
||||
if (emailTemplate is null || (emailTemplate.Id is null && emailTemplate.Type is null))
|
||||
{
|
||||
var temps = await _repository.Query.ToListAsync();
|
||||
return Ok(_mapper.Map<IEnumerable<EmailTemplateDto>>(temps));
|
||||
var temps = await repository.Query.ToListAsync();
|
||||
return Ok(mapper.Map<IEnumerable<EmailTemplateDto>>(temps));
|
||||
}
|
||||
else
|
||||
{
|
||||
var temp = await _mediator.Send(emailTemplate);
|
||||
var temp = await mediator.Send(emailTemplate);
|
||||
return temp is null ? NotFound() : Ok(temp);
|
||||
}
|
||||
}
|
||||
@@ -95,11 +82,11 @@ public class EmailTemplateController : ControllerBase
|
||||
/// <response code="401">Wenn der Benutzer nicht authentifiziert ist.</response>
|
||||
/// <response code="404">Wenn die gesuchte Abfrage nicht gefunden wird.</response>
|
||||
[HttpPut]
|
||||
public async Task<IActionResult> Update([FromQuery] EmailTemplateQuery? temp = null, [FromBody] UpdateEmailTemplateCommand? update = null)
|
||||
public async Task<IActionResult> Update([FromQuery] EmailTemplateQueryBase? temp = null, [FromBody] UpdateEmailTemplateCommand? update = null)
|
||||
{
|
||||
if (update is null)
|
||||
{
|
||||
await _mediator.Send(new ResetEmailTemplateCommand(temp));
|
||||
await mediator.Send(new ResetEmailTemplateCommand(temp));
|
||||
return Ok();
|
||||
}
|
||||
else if (temp is null)
|
||||
@@ -109,7 +96,7 @@ public class EmailTemplateController : ControllerBase
|
||||
else
|
||||
{
|
||||
update.EmailTemplateQuery = temp;
|
||||
await _mediator.Send(update);
|
||||
await mediator.Send(update);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface IAuthController
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
IAuthorizationService AuthService { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
ClaimsPrincipal User { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class AuthControllerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="controller"></param>
|
||||
/// <param name="policyName"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> IsUserInPolicyAsync(this IAuthController controller, string policyName)
|
||||
{
|
||||
var result = await controller.AuthService.AuthorizeAsync(controller.User, policyName);
|
||||
return result.Succeeded;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public class ReadOnlyController : ControllerBase
|
||||
/// </summary>
|
||||
/// <param name="createDto">Creation payload.</param>
|
||||
[HttpPost]
|
||||
[Authorize(Roles = Role.Receiver.FullyAuth)]
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
public async Task<IActionResult> CreateAsync([FromBody] EnvelopeReceiverReadOnlyCreateDto createDto)
|
||||
{
|
||||
var authReceiverMail = User.GetReceiverMailOfReceiver();
|
||||
|
||||
@@ -111,7 +111,7 @@ public class TfaRegistrationController : ControllerBase
|
||||
/// <summary>
|
||||
/// Logs out the envelope receiver from cookie authentication.
|
||||
/// </summary>
|
||||
[Authorize(Roles = Role.FullyAuth)]
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[HttpPost("auth/logout")]
|
||||
public async Task<IActionResult> LogOutAsync()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using DigitalData.Core.API;
|
||||
using DigitalData.Core.Application;
|
||||
using EnvelopeGenerator.Infrastructure;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -93,7 +94,7 @@ try
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
},
|
||||
@@ -176,6 +177,16 @@ try
|
||||
options.SlidingExpiration = true;
|
||||
});
|
||||
|
||||
builder.Services.AddAuthorizationBuilder()
|
||||
.AddPolicy(AuthPolicy.SenderOrReceiver, policy =>
|
||||
policy.RequireRole(Role.Sender, Role.Receiver.Full))
|
||||
.AddPolicy(AuthPolicy.Sender, policy =>
|
||||
policy.RequireRole(Role.Sender))
|
||||
.AddPolicy(AuthPolicy.Receiver, policy =>
|
||||
policy.RequireRole(Role.Receiver.Full))
|
||||
.AddPolicy(AuthPolicy.ReceiverTFA, policy =>
|
||||
policy.RequireRole(Role.Receiver.TFA));
|
||||
|
||||
// User manager
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
builder.Services.AddUserManager<EGDbContext>();
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Dto
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record EmailTemplateDto
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EmailTemplateDto
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Id{ get; init; }
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public required string Name { get; init; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public required string Body { get; set; }
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann die Vorlage hinzugefügt wurde.
|
||||
/// </summary>
|
||||
public DateTime AddedWhen { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public required string Subject { get; set; }
|
||||
};
|
||||
}
|
||||
/// <summary>
|
||||
/// Der Inhalt (Body) der E-Mail-Vorlage. Kann null sein.
|
||||
/// </summary>
|
||||
public string? Body { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Betreff der E-Mail-Vorlage. Kann null sein.
|
||||
/// </summary>
|
||||
public string? Subject { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann die Vorlage zuletzt geändert wurde. Kann null sein.
|
||||
/// </summary>
|
||||
public DateTime? ChangedWhen { get; init; }
|
||||
};
|
||||
@@ -6,7 +6,7 @@ namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Reset;
|
||||
|
||||
/// <summary>
|
||||
/// Ein Befehl zum Zurücksetzen einer E-Mail-Vorlage auf die Standardwerte.
|
||||
/// Erbt von <see cref="EmailTemplateQuery"/> und ermöglicht die Angabe einer optionalen ID und eines Typs der E-Mail-Vorlage.<br/><br/>
|
||||
/// Erbt von <see cref="EmailTemplateQueryBase"/> und ermöglicht die Angabe einer optionalen ID und eines Typs der E-Mail-Vorlage.<br/><br/>
|
||||
/// Beispiele:<br/>
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.<br/>
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.<br/>
|
||||
@@ -19,13 +19,13 @@ namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Reset;
|
||||
/// 8 - DocumentRejected_REC (Für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 9 - DocumentRejected_REC_2 (Für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.<br/>
|
||||
/// </summary>
|
||||
public record ResetEmailTemplateCommand : EmailTemplateQuery, IRequest
|
||||
public record ResetEmailTemplateCommand : EmailTemplateQueryBase, IRequest
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="orginal"></param>
|
||||
public ResetEmailTemplateCommand(EmailTemplateQuery? orginal = null) : base(orginal ?? new())
|
||||
public ResetEmailTemplateCommand(EmailTemplateQueryBase? orginal = null) : base(orginal ?? new())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public record UpdateEmailTemplateCommand(string? Body = null, string? Subject =
|
||||
/// Die Abfrage, die die E-Mail-Vorlage darstellt, die aktualisiert werden soll.
|
||||
/// </param>
|
||||
[JsonIgnore]
|
||||
public EmailTemplateQuery? EmailTemplateQuery { get; set; }
|
||||
public EmailTemplateQueryBase? EmailTemplateQuery { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -62,12 +62,6 @@ public class UpdateEmailTemplateCommandHandler : IRequestHandler<UpdateEmailTemp
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (request.Body is not null)
|
||||
tempDto.Body = request.Body;
|
||||
|
||||
if (request.Subject is not null)
|
||||
tempDto.Subject = request.Subject;
|
||||
|
||||
await _repository.UpdateAsync(tempDto, t => t.Id == tempDto.Id, cancel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ namespace EnvelopeGenerator.Application.EmailTemplates;
|
||||
/// 8 - DocumentRejected_REC (Für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.
|
||||
/// 9 - DocumentRejected_REC_2 (Für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
|
||||
/// </param>
|
||||
public record EmailTemplateQuery(int? Id = null, EmailTemplateType? Type = null)
|
||||
public record EmailTemplateQueryBase(int? Id = null, EmailTemplateType? Type = null)
|
||||
{
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class MappingProfile : Profile
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public MappingProfile()
|
||||
{
|
||||
CreateMap<EmailTemplate, ReadEmailTemplateResponse>();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Abfrage dar, um eine E-Mail-Vorlage zu lesen.
|
||||
/// Diese Klasse erbt von <see cref="EmailTemplateQuery"/>.
|
||||
/// </summary>
|
||||
public record ReadEmailTemplateQuery : EmailTemplateQuery, IRequest<ReadEmailTemplateResponse?>
|
||||
{
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEmailTemplateQueryHandler : IRequestHandler<ReadEmailTemplateQuery, ReadEmailTemplateResponse?>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
|
||||
private readonly IEmailTemplateRepository _repository;
|
||||
|
||||
/// <summary>
|
||||
/// Initialisiert eine neue Instanz der <see cref="EmailTemplateController"/>-Klasse.
|
||||
/// </summary>
|
||||
/// <param name="mapper">
|
||||
/// <param name="repository">
|
||||
/// Die AutoMapper-Instanz, die zum Zuordnen von Objekten verwendet wird.
|
||||
/// </param>
|
||||
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
|
||||
public ReadEmailTemplateQueryHandler(IMapper mapper, IEmailTemplateRepository repository)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
[Obsolete("Use IRepository")]
|
||||
public async Task<ReadEmailTemplateResponse?> Handle(ReadEmailTemplateQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var temp = request.Id is int id
|
||||
? await _repository.ReadByIdAsync(id)
|
||||
: request.Type is EmailTemplateType type
|
||||
? await _repository.ReadByNameAsync(type)
|
||||
: throw new InvalidOperationException("Either a valid integer ID or a valid EmailTemplateType must be provided in the request.");
|
||||
|
||||
var res = _mapper.Map<ReadEmailTemplateResponse>(temp);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt die Antwort für eine Abfrage von E-Mail-Vorlagen bereit.
|
||||
/// </summary>
|
||||
public class ReadEmailTemplateResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung der E-Mail-Vorlage.
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name des Typs
|
||||
/// </summary>
|
||||
public required string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann die Vorlage hinzugefügt wurde.
|
||||
/// </summary>
|
||||
public DateTime AddedWhen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Inhalt (Body) der E-Mail-Vorlage. Kann null sein.
|
||||
/// </summary>
|
||||
public string? Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Betreff der E-Mail-Vorlage. Kann null sein.
|
||||
/// </summary>
|
||||
public string? Subject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann die Vorlage zuletzt geändert wurde. Kann null sein.
|
||||
/// </summary>
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using AutoMapper;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Abfrage dar, um eine E-Mail-Vorlage zu lesen.
|
||||
/// Diese Klasse erbt von <see cref="EmailTemplateQueryBase"/>.
|
||||
/// </summary>
|
||||
public record ReadEmailTemplateQuery : EmailTemplateQueryBase, IRequest<EmailTemplateDto?>
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEmailTemplateQueryHandler : IRequestHandler<ReadEmailTemplateQuery, EmailTemplateDto?>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<EmailTemplate> _repo;
|
||||
|
||||
/// <summary>
|
||||
/// Initialisiert eine neue Instanz der <see cref="EmailTemplateController"/>-Klasse.
|
||||
/// </summary>
|
||||
/// <param name="mapper">
|
||||
/// <param name="repo">
|
||||
/// Die AutoMapper-Instanz, die zum Zuordnen von Objekten verwendet wird.
|
||||
/// </param>
|
||||
public ReadEmailTemplateQueryHandler(IMapper mapper, IRepository<EmailTemplate> repo)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
public async Task<EmailTemplateDto?> Handle(ReadEmailTemplateQuery request, CancellationToken cancel)
|
||||
{
|
||||
var query = request.Id is int id
|
||||
? _repo.Query.Where(temp => temp.Id == id)
|
||||
: _repo.Query.Where(temp => temp.Name == request.Type!.ToString());
|
||||
|
||||
return _mapper.Map<EmailTemplateDto>(await query.FirstOrDefaultAsync(cancel));
|
||||
}
|
||||
}
|
||||
15
EnvelopeGenerator.Domain/Constants/AuthPolicy.cs
Normal file
15
EnvelopeGenerator.Domain/Constants/AuthPolicy.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace EnvelopeGenerator.Domain.Constants
|
||||
{
|
||||
public static class AuthPolicy
|
||||
{
|
||||
public const string SenderOrReceiver = nameof(SenderOrReceiver) + nameof(AuthPolicy);
|
||||
|
||||
public const string ReceiverOrReceiverTFA = nameof(ReceiverOrReceiverTFA) + nameof(AuthPolicy);
|
||||
|
||||
public const string Sender = nameof(Sender) + nameof(AuthPolicy);
|
||||
|
||||
public const string Receiver = nameof(Receiver) + nameof(AuthPolicy);
|
||||
|
||||
public const string ReceiverTFA = nameof(ReceiverTFA) + nameof(AuthPolicy);
|
||||
}
|
||||
}
|
||||
@@ -6,18 +6,18 @@ namespace EnvelopeGenerator.Domain.Constants
|
||||
{
|
||||
public static class Role
|
||||
{
|
||||
[Obsolete("Use Receiver.PreAuth or Receiver.FullyAuth")]
|
||||
public const string PreAuth = "PreAuth";
|
||||
[Obsolete("Use Receiver.TFA")]
|
||||
public const string ReceiverTFA = Receiver.TFA;
|
||||
|
||||
[Obsolete("Use Receiver.PreAuth or Receiver.FullyAuth")]
|
||||
public const string FullyAuth = "FullyAuth";
|
||||
[Obsolete("Use Receiver.Full")]
|
||||
public const string ReceiverFull = Receiver.Full;
|
||||
|
||||
public static class Receiver
|
||||
{
|
||||
public const string PreAuth = "PreAuth";
|
||||
public const string FullyAuth = "FullyAuth";
|
||||
public const string TFA = "EGReceiverTFA";
|
||||
public const string Full = "EGReceiver";
|
||||
}
|
||||
|
||||
public const string Sender = "Sender";
|
||||
public const string Sender = "EGSender";
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Web.Controllers;
|
||||
|
||||
[Authorize(Roles = Role.FullyAuth)]
|
||||
[Authorize(Roles = Role.ReceiverFull)]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AnnotationController : ControllerBase
|
||||
@@ -42,7 +42,7 @@ public class AnnotationController : ControllerBase
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[Authorize(Roles = Role.FullyAuth)]
|
||||
[Authorize(Roles = Role.ReceiverFull)]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateOrUpdate([FromBody] PsPdfKitAnnotation? psPdfKitAnnotation = null, CancellationToken cancel = default)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ public class AnnotationController : ControllerBase
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[Authorize(Roles = Role.FullyAuth)]
|
||||
[Authorize(Roles = Role.ReceiverFull)]
|
||||
[HttpPost("reject")]
|
||||
[Obsolete("Use DigitalData.Core.Exceptions and .Middleware")]
|
||||
public async Task<IActionResult> Reject([FromBody] string? reason = null)
|
||||
|
||||
@@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Web.Controllers;
|
||||
|
||||
[Authorize(Roles = Role.FullyAuth)]
|
||||
[Authorize(Roles = Role.ReceiverFull)]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class DocumentController : ControllerBase
|
||||
|
||||
@@ -107,7 +107,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
return this.ViewEnvelopeNotFound();
|
||||
}
|
||||
var er_secret = er_secret_res.Data;
|
||||
await HttpContext.SignInEnvelopeAsync(er_secret, Role.FullyAuth);
|
||||
await HttpContext.SignInEnvelopeAsync(er_secret, Role.ReceiverFull);
|
||||
return await CreateShowEnvelopeView(er_secret);
|
||||
}
|
||||
#endregion UseAccessCode
|
||||
@@ -172,7 +172,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
}
|
||||
|
||||
// show envelope if already logged in
|
||||
if (User.IsInRole(Role.FullyAuth))
|
||||
if (User.IsInRole(Role.ReceiverFull))
|
||||
return await CreateShowEnvelopeView(er_secret);
|
||||
|
||||
if (auth.HasMulti)
|
||||
@@ -206,7 +206,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
.WithData("ErrorMessage", _localizer.WrongEnvelopeReceiverId());
|
||||
}
|
||||
|
||||
await HttpContext.SignInEnvelopeAsync(er_secret, Role.FullyAuth);
|
||||
await HttpContext.SignInEnvelopeAsync(er_secret, Role.ReceiverFull);
|
||||
|
||||
return await CreateShowEnvelopeView(er_secret);
|
||||
}
|
||||
@@ -225,9 +225,9 @@ public class EnvelopeController : ViewControllerBase
|
||||
&& uuidClaim == er.Envelope?.Uuid
|
||||
&& signatureClaim is not null
|
||||
&& signatureClaim == er.Receiver?.Signature
|
||||
&& User.IsInRole(Role.FullyAuth))
|
||||
&& User.IsInRole(Role.ReceiverFull))
|
||||
{
|
||||
await HttpContext.SignInEnvelopeAsync(er, Role.FullyAuth);
|
||||
await HttpContext.SignInEnvelopeAsync(er, Role.ReceiverFull);
|
||||
|
||||
//add PSPDFKit licence key
|
||||
ViewData["PSPDFKitLicenseKey"] = _configuration["PSPDFKitLicenseKey"];
|
||||
@@ -262,7 +262,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
return this.ViewDocumentNotFound();
|
||||
}
|
||||
|
||||
await HttpContext.SignInEnvelopeAsync(er, Role.FullyAuth);
|
||||
await HttpContext.SignInEnvelopeAsync(er, Role.ReceiverFull);
|
||||
|
||||
ViewData["ReadAndConfirm"] = er.Envelope.ReadOnly;
|
||||
|
||||
@@ -334,7 +334,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
await _rcvService.UpdateAsync(rcv);
|
||||
}
|
||||
|
||||
await HttpContext.SignInEnvelopeAsync(er_secret, Role.PreAuth);
|
||||
await HttpContext.SignInEnvelopeAsync(er_secret, Role.ReceiverTFA);
|
||||
|
||||
return await TFAViewAsync(auth.UserSelectSMS, er_secret, envelopeReceiverId);
|
||||
}
|
||||
@@ -348,7 +348,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
if (er_secret.Receiver!.TotpSecretkey is null)
|
||||
throw new InvalidOperationException($"TotpSecretkey of DTO cannot validate without TotpSecretkey. Dto: {JsonConvert.SerializeObject(er_secret)}");
|
||||
|
||||
if (!User.IsInRole(Role.PreAuth) || !_envSmsHandler.VerifyTotp(auth.SmsCode!, er_secret.Receiver.TotpSecretkey))
|
||||
if (!User.IsInRole(Role.ReceiverTFA) || !_envSmsHandler.VerifyTotp(auth.SmsCode!, er_secret.Receiver.TotpSecretkey))
|
||||
{
|
||||
Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||||
ViewData["ErrorMessage"] = _localizer.WrongAccessCode();
|
||||
@@ -364,7 +364,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
if (er_secret.Receiver!.TotpSecretkey is null)
|
||||
throw new InvalidOperationException($"TotpSecretkey of DTO cannot validate without TotpSecretkey. Dto: {JsonConvert.SerializeObject(er_secret)}");
|
||||
|
||||
if (!User.IsInRole(Role.PreAuth) || !_authenticator.VerifyTotp(auth.AuthenticatorCode!, er_secret.Receiver.TotpSecretkey, window: VerificationWindow.RfcSpecifiedNetworkDelay))
|
||||
if (!User.IsInRole(Role.ReceiverTFA) || !_authenticator.VerifyTotp(auth.AuthenticatorCode!, er_secret.Receiver.TotpSecretkey, window: VerificationWindow.RfcSpecifiedNetworkDelay))
|
||||
{
|
||||
Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||||
ViewData["ErrorMessage"] = _localizer.WrongAccessCode();
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace EnvelopeGenerator.Web.Controllers
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = Role.FullyAuth)]
|
||||
[Authorize(Roles = Role.ReceiverFull)]
|
||||
[Obsolete("Use MediatR")]
|
||||
public async Task<IActionResult> CreateAsync([FromBody] EnvelopeReceiverReadOnlyCreateDto createDto)
|
||||
{
|
||||
|
||||
@@ -91,7 +91,7 @@ public class TFARegController : ViewControllerBase
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize(Roles = Role.FullyAuth)]
|
||||
[Authorize(Roles = Role.ReceiverFull)]
|
||||
[HttpPost("auth/logout")]
|
||||
public async Task<IActionResult> LogOut()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user