Skip to content

Commit 29ce0a1

Browse files
committed
feat: 629
Merged PR 197: Auth API Related work items: #629
1 parent 8c6407e commit 29ce0a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+978
-312
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,3 +542,4 @@ src/Presentation/PortaleFatture.BE.SendEmailFunction/Infrastructure/Documenti/pa
542542
src/Presentation/PortaleFatture.BE.EmailPSPSender/Program.cs
543543
src/Presentation/PortaleFatture.BE.EmailPSPSender/Infrastructure/Documenti/pagoPA/credentials.json
544544
src/Presentation/PortaleFatture.BE.Function.API/local.settings.json
545+
src/Presentation/PortaleFatture.BE.Function.API/PortaleFatture.BE.Function.API.sln

PortaleFatture.BE.Api.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PortaleFatture.BE.SelfCareO
4141
EndProject
4242
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PortaleFatture.BE.EmailPSPSender", "src\Presentation\PortaleFatture.BE.EmailPSPSender\PortaleFatture.BE.EmailPSPSender.csproj", "{E41A8735-126D-4F6D-82C2-166CB605EB8D}"
4343
EndProject
44+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PortaleFatture.BE.Function.API", "src\Presentation\PortaleFatture.BE.Function.API\PortaleFatture.BE.Function.API.csproj", "{3BDADB61-3359-BEC6-F0D3-AAB0DD56D62B}"
45+
EndProject
4446
Global
4547
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4648
Debug|Any CPU = Debug|Any CPU
@@ -85,6 +87,10 @@ Global
8587
{E41A8735-126D-4F6D-82C2-166CB605EB8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
8688
{E41A8735-126D-4F6D-82C2-166CB605EB8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
8789
{E41A8735-126D-4F6D-82C2-166CB605EB8D}.Release|Any CPU.Build.0 = Release|Any CPU
90+
{3BDADB61-3359-BEC6-F0D3-AAB0DD56D62B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
91+
{3BDADB61-3359-BEC6-F0D3-AAB0DD56D62B}.Debug|Any CPU.Build.0 = Debug|Any CPU
92+
{3BDADB61-3359-BEC6-F0D3-AAB0DD56D62B}.Release|Any CPU.ActiveCfg = Release|Any CPU
93+
{3BDADB61-3359-BEC6-F0D3-AAB0DD56D62B}.Release|Any CPU.Build.0 = Release|Any CPU
8894
EndGlobalSection
8995
GlobalSection(SolutionProperties) = preSolution
9096
HideSolutionNode = FALSE
@@ -101,6 +107,7 @@ Global
101107
{58D379F3-5E9D-4C83-B4DA-7690318A2BD1} = {FCE0D4DD-5884-4A2A-814E-F58B18092F76}
102108
{E32705A0-D6F3-40F7-B2D0-4A08FEAE18B2} = {FCE0D4DD-5884-4A2A-814E-F58B18092F76}
103109
{E41A8735-126D-4F6D-82C2-166CB605EB8D} = {FCE0D4DD-5884-4A2A-814E-F58B18092F76}
110+
{3BDADB61-3359-BEC6-F0D3-AAB0DD56D62B} = {FCE0D4DD-5884-4A2A-814E-F58B18092F76}
104111
EndGlobalSection
105112
GlobalSection(ExtensibilityGlobals) = postSolution
106113
SolutionGuid = {E21864C8-BAF8-4D8B-957E-726DB3040371}

src/Core/PortaleFatture.BE.Core/Entities/Storici/TipoStorico.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@ public class TipoStorico
99
public const string RipristionFatture = "RF";
1010
public const string AnnullaSAP = "ASAP";
1111
public const string InvioSAP = "ISAP";
12+
public const string CreaAPIKey = "APIK";
13+
public const string CreaAPIIp = "APICIP";
14+
public const string EliminaAPIIp = "APIEIP";
1215
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using MediatR;
2+
using Microsoft.Extensions.Localization;
3+
using Microsoft.Extensions.Logging;
4+
using PortaleFatture.BE.Core.Resources;
5+
using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas;
6+
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands;
7+
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands.Persistence;
8+
9+
namespace PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.CommandHandlers;
10+
11+
public class CreateApyLogHandler(
12+
IFattureDbContextFactory factory,
13+
IStringLocalizer<Localization> localizer,
14+
ILogger<CreateApyLogHandler> logger) : IRequestHandler<CreateApyLogCommand, int?>
15+
{
16+
private readonly IFattureDbContextFactory _factory = factory;
17+
private readonly ILogger<CreateApyLogHandler> _logger = logger;
18+
private readonly IStringLocalizer<Localization> _localizer = localizer;
19+
public async Task<int?> Handle(CreateApyLogCommand request, CancellationToken ct)
20+
{
21+
using var rs = await _factory.Create(cancellationToken: ct);
22+
{
23+
return await rs.Execute(new CreateApyLogPersistence(request), ct);
24+
}
25+
}
26+
}
Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,60 @@
11
using System.Security;
2+
using DocumentFormat.OpenXml.Spreadsheet;
23
using MediatR;
34
using Microsoft.Extensions.Localization;
45
using Microsoft.Extensions.Logging;
6+
using PortaleFatture.BE.Core.Entities.Storici;
7+
using PortaleFatture.BE.Core.Exceptions;
58
using PortaleFatture.BE.Core.Extensions;
69
using PortaleFatture.BE.Core.Resources;
710
using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas;
811
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands;
912
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands.Persistence;
1013
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Queries;
1114
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Queries.Persistence;
15+
using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence;
16+
using PortaleFatture.BE.Infrastructure.Common.Storici.Commands;
17+
using PortaleFatture.BE.Infrastructure.Gateway;
1218

1319
namespace PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.CommandHandlers;
1420

1521
public class CreateIpsCommandHandler(
16-
ISelfCareDbContextFactory factory,
22+
IFattureDbContextFactory factory,
1723
IStringLocalizer<Localization> localizer,
18-
IMediator handler,
24+
IAesEncryption encryption,
1925
ILogger<CreateIpsCommandHandler> logger) : IRequestHandler<CreateIpsCommand, int?>
2026
{
21-
private readonly ISelfCareDbContextFactory _factory = factory;
27+
private readonly IFattureDbContextFactory _factory = factory;
2228
private readonly ILogger<CreateIpsCommandHandler> _logger = logger;
2329
private readonly IStringLocalizer<Localization> _localizer = localizer;
24-
private readonly IMediator _handler = handler;
30+
private readonly IAesEncryption _encryption = encryption;
2531
public async Task<int?> Handle(CreateIpsCommand request, CancellationToken ct)
26-
{
32+
{
2733
using var rs = await _factory.Create(true, cancellationToken: ct);
2834
{
29-
var result = await rs.Query(new CheckApiKeyQueryGetPersistence(new ApiKeyQueryGet(request!.AuthenticationInfo!) { }));
35+
var result = await rs.Query(new CheckApiKeyQueryGetPersistence(new ApiKeyQueryGet(request!.AuthenticationInfo!) { }, _encryption), ct);
3036
if (result.IsNullNotAny())
3137
throw new SecurityException("Ente non registrato!");
38+
request.IpAddress = request.IpAddress == null ? null : _encryption.EncryptString(request.IpAddress);
3239
var rowAffected = await rs.Query(new CreateIpsCommandPersistence(request), ct);
3340
if (rowAffected.HasValue && rowAffected > 0)
3441
{
35-
rs.Commit();
42+
rowAffected = await rs.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand(
43+
request.AuthenticationInfo!,
44+
DateTime.UtcNow.ItalianTime(),
45+
TipoStorico.CreaAPIIp,
46+
request.Serialize())), ct);
47+
if (rowAffected == 1)
48+
rs.Commit();
49+
else
50+
rs.Rollback();
3651
return rowAffected;
37-
}
52+
}
3853
else
3954
{
4055
rs.Rollback();
4156
return rowAffected;
42-
}
57+
}
4358
}
4459
}
4560
}

src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SEND/ApiKeys/CommandHandlers/CreateORModifyApiKeyCommandHandler.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using MediatR;
33
using Microsoft.Extensions.Localization;
44
using Microsoft.Extensions.Logging;
5+
using PortaleFatture.BE.Core.Entities.Storici;
56
using PortaleFatture.BE.Core.Exceptions;
67
using PortaleFatture.BE.Core.Extensions;
78
using PortaleFatture.BE.Core.Resources;
@@ -10,19 +11,22 @@
1011
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands.Persistence;
1112
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Queries;
1213
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Queries.Persistence;
14+
using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence;
15+
using PortaleFatture.BE.Infrastructure.Common.Storici.Commands;
16+
using PortaleFatture.BE.Infrastructure.Gateway;
1317

1418
namespace PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.CommandHandlers;
1519

1620
public class CreateORModifyApiKeyCommandHandler(
17-
ISelfCareDbContextFactory factory,
21+
IFattureDbContextFactory factory,
1822
IStringLocalizer<Localization> localizer,
19-
IMediator handler,
23+
IAesEncryption encryption,
2024
ILogger<CreateORModifyApiKeyCommandHandler> logger) : IRequestHandler<CreateORModifyApiKeyCommand, int?>
2125
{
22-
private readonly ISelfCareDbContextFactory _factory = factory;
26+
private readonly IFattureDbContextFactory _factory = factory;
2327
private readonly ILogger<CreateORModifyApiKeyCommandHandler> _logger = logger;
2428
private readonly IStringLocalizer<Localization> _localizer = localizer;
25-
private readonly IMediator _handler = handler;
29+
private readonly IAesEncryption _encryption = encryption;
2630
public async Task<int?> Handle(CreateORModifyApiKeyCommand request, CancellationToken ct)
2731
{
2832
if (string.IsNullOrEmpty(request.ApiKey))
@@ -37,13 +41,25 @@ public class CreateORModifyApiKeyCommandHandler(
3741

3842
using var rs = await _factory.Create(true, cancellationToken: ct);
3943
{
40-
var result = await rs.Query(new CheckApiKeyQueryGetPersistence(new ApiKeyQueryGet(request!.AuthenticationInfo!) { }));
44+
var result = await rs.Query(new CheckApiKeyQueryGetPersistence(new ApiKeyQueryGet(request!.AuthenticationInfo!) { }, _encryption), ct);
4145
if (result.IsNullNotAny())
4246
throw new SecurityException("Ente non registrato!");
47+
48+
request.ApiKey = request.ApiKey == null ? null : _encryption.EncryptString(request.ApiKey);
49+
request.PreviousApiKey = request.PreviousApiKey == null ? null : _encryption.EncryptString(request.PreviousApiKey);
50+
4351
var rowAffected = await rs.Query(new CreateORModifyApiKeyPersistence(request), ct);
4452
if (rowAffected.HasValue && rowAffected > 0)
4553
{
46-
rs.Commit();
54+
rowAffected = await rs.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand(
55+
request.AuthenticationInfo!,
56+
DateTime.UtcNow.ItalianTime(),
57+
TipoStorico.CreaAPIKey,
58+
request.Serialize())), ct);
59+
if (rowAffected == 1)
60+
rs.Commit();
61+
else
62+
rs.Rollback();
4763
return rowAffected;
4864
}
4965
else

src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SEND/ApiKeys/CommandHandlers/DeleteIpsCommandHandler.cs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,51 @@
22
using MediatR;
33
using Microsoft.Extensions.Localization;
44
using Microsoft.Extensions.Logging;
5+
using PortaleFatture.BE.Core.Entities.Storici;
56
using PortaleFatture.BE.Core.Extensions;
67
using PortaleFatture.BE.Core.Resources;
78
using PortaleFatture.BE.Infrastructure.Common.Persistence.Schemas;
89
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands;
910
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands.Persistence;
1011
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Queries;
1112
using PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Queries.Persistence;
13+
using PortaleFatture.BE.Infrastructure.Common.Storici.Commands.Persistence;
14+
using PortaleFatture.BE.Infrastructure.Common.Storici.Commands;
15+
using PortaleFatture.BE.Infrastructure.Gateway;
1216

1317
namespace PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.CommandHandlers;
1418

1519
public class DeleteIpsCommandHandler(
16-
ISelfCareDbContextFactory factory,
20+
IFattureDbContextFactory factory,
1721
IStringLocalizer<Localization> localizer,
18-
IMediator handler,
22+
IAesEncryption encryption,
1923
ILogger<DeleteIpsCommandHandler> logger) : IRequestHandler<DeleteIpsCommand, int?>
2024
{
21-
private readonly ISelfCareDbContextFactory _factory = factory;
25+
private readonly IFattureDbContextFactory _factory = factory;
2226
private readonly ILogger<DeleteIpsCommandHandler> _logger = logger;
2327
private readonly IStringLocalizer<Localization> _localizer = localizer;
24-
private readonly IMediator _handler = handler;
28+
private readonly IAesEncryption _encryption = encryption;
2529
public async Task<int?> Handle(DeleteIpsCommand request, CancellationToken ct)
2630
{
2731
using var rs = await _factory.Create(true, cancellationToken: ct);
2832
{
29-
var result = await rs.Query(new CheckApiKeyQueryGetPersistence(new ApiKeyQueryGet(request!.AuthenticationInfo!) { }));
33+
var result = await rs.Query(new CheckApiKeyQueryGetPersistence(new ApiKeyQueryGet(request!.AuthenticationInfo!) { }, _encryption), ct);
3034
if (result.IsNullNotAny())
3135
throw new SecurityException("Ente non registrato!");
36+
37+
request.IpAddress = request.IpAddress == null ? null : _encryption.EncryptString(request.IpAddress);
3238
var rowAffected = await rs.Query(new DeleteIpsCommandPersistence(request), ct);
3339
if (rowAffected.HasValue && rowAffected > 0)
3440
{
35-
rs.Commit();
41+
rowAffected = await rs.Execute(new StoricoCreateCommandPersistence(new StoricoCreateCommand(
42+
request.AuthenticationInfo!,
43+
DateTime.UtcNow.ItalianTime(),
44+
TipoStorico.EliminaAPIIp,
45+
request.Serialize())), ct);
46+
if (rowAffected == 1)
47+
rs.Commit();
48+
else
49+
rs.Rollback();
3650
return rowAffected;
3751
}
3852
else
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Text.Json.Serialization;
2+
using MediatR;
3+
using PortaleFatture.BE.Core.Auth;
4+
using PortaleFatture.BE.Core.Extensions;
5+
6+
namespace PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands;
7+
8+
public sealed class CreateApyLogCommand(IAuthenticationInfo? authenticationInfo) : IRequest<int?>
9+
{
10+
public IAuthenticationInfo? AuthenticationInfo { get; internal set; } = authenticationInfo;
11+
public string? FkIdEnte { get; set; } = authenticationInfo!.IdEnte;
12+
public DateTime Timestamp { get; set; } = DateTime.UtcNow.ItalianTime();
13+
public string? FunctionName { get; set; }
14+
public string? Stage { get; set; }
15+
public string? Method { get; set; }
16+
public string? Payload { get; set; }
17+
public string? Uri { get; set; }
18+
public string? IpAddress { get; set; }
19+
public string? Id { get; set; }
20+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Data;
2+
using PortaleFatture.BE.Infrastructure.Common.Persistence;
3+
4+
namespace PortaleFatture.BE.Infrastructure.Common.SEND.ApiKeys.Commands.Persistence;
5+
6+
public class CreateApyLogPersistence(CreateApyLogCommand command) : DapperBase, ICommand<int?>
7+
{
8+
private readonly CreateApyLogCommand _command = command;
9+
private static readonly string _sqlInsert =
10+
$@"
11+
INSERT INTO [pfw].[ApiLog]
12+
([Id]
13+
,[FkIdEnte]
14+
,[Timestamp]
15+
,[FunctionName]
16+
,[Method]
17+
,[Stage]
18+
,[Payload]
19+
,[IpAddress]
20+
,[Uri])
21+
VALUES
22+
(@Id
23+
,@FkIdEnte
24+
,@Timestamp
25+
,@FunctionName
26+
,@Method
27+
,@Stage
28+
,@Payload
29+
,@IpAddress
30+
,@Uri)
31+
";
32+
33+
public bool RequiresTransaction => false;
34+
35+
public async Task<int?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default)
36+
{
37+
return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert, _command, transaction);
38+
}
39+
}

src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/SEND/ApiKeys/Commands/Persistence/CreateIpsCommandPersistence.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ INSERT INTO [pfw].[ApiKeysIPs]
2222
public async Task<int?> Execute(IDbConnection? connection, string schema, IDbTransaction? transaction, CancellationToken cancellationToken = default)
2323
{
2424
try
25-
{
25+
{
2626
return await ((IDatabase)this).ExecuteAsync(connection!, _sqlInsert, _command, transaction);
2727
}
2828
catch (SqlException ex) when (ex.Number == 2601)

0 commit comments

Comments
 (0)