feat(GtxMessagingService): Zwischenspeicherung für SMS-Code und Ablauf des SMS-Codes mittels Envelope-Receiver-ID hinzugefügt
- Erweiterungsmethode für Zeitcaching hinzugefügt.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using DigitalData.Core.Abstractions.Client;
|
using DigitalData.Core.Abstractions.Client;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Configurations.GtxMessaging
|
namespace EnvelopeGenerator.Application.Configurations.GtxMessaging
|
||||||
{
|
{
|
||||||
@@ -20,5 +21,19 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging
|
|||||||
public string MessageQueryParamName { get; init; } = "text";
|
public string MessageQueryParamName { get; init; } = "text";
|
||||||
|
|
||||||
public int CodeLength { get; init; } = 5;
|
public int CodeLength { get; init; } = 5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the cache key format for SMS codes.
|
||||||
|
/// The placeholder {0} represents the envelopeReceiverId.
|
||||||
|
/// </summary>
|
||||||
|
public string CodeCacheKeyFormat { get; init; } = "sms-code-{0}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the cache expiration key format for SMS codes.
|
||||||
|
/// The placeholder {0} represents the envelopeReceiverId.
|
||||||
|
/// </summary>
|
||||||
|
public string CodeExpirationCacheKeyFormat { get; init; } = "sms-code-expiration-{0}";
|
||||||
|
|
||||||
|
public TimeSpan CodeCacheValidityPeriod { get; init; } = new(0, 5, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,6 @@ namespace EnvelopeGenerator.Application.Contracts
|
|||||||
|
|
||||||
Task<SmsResponse> SendSmsAsync(string recipient, string message);
|
Task<SmsResponse> SendSmsAsync(string recipient, string message);
|
||||||
|
|
||||||
Task<SmsResponse> SendSmsCodeAsync(string recipient);
|
Task<SmsResponse> SendSmsCodeAsync(string recipient, string envelopeReceiverId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
43
EnvelopeGenerator.Application/Extensions/CacheExtensions.cs
Normal file
43
EnvelopeGenerator.Application/Extensions/CacheExtensions.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Extensions
|
||||||
|
{
|
||||||
|
public static class CacheExtensions
|
||||||
|
{
|
||||||
|
public static Task SetLongAsync(this IDistributedCache cache, string key, long value, DistributedCacheEntryOptions? options = null)
|
||||||
|
=> options is null
|
||||||
|
? cache.SetAsync(key, BitConverter.GetBytes(value))
|
||||||
|
: cache.SetAsync(key, BitConverter.GetBytes(value), options: options);
|
||||||
|
|
||||||
|
public static async Task<long?> GetLongAsync(this IDistributedCache cache, string key)
|
||||||
|
{
|
||||||
|
var value = await cache.GetAsync(key);
|
||||||
|
return value is null ? null : BitConverter.ToInt64(value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task SetDateTimeAsync(this IDistributedCache cache, string key, DateTime value, DistributedCacheEntryOptions? options = null)
|
||||||
|
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options);
|
||||||
|
|
||||||
|
public static async Task<DateTime?> GetDateTimeAsync(this IDistributedCache cache, string key)
|
||||||
|
{
|
||||||
|
var value = await cache.GetAsync(key);
|
||||||
|
return value is null ? null : new(BitConverter.ToInt64(value, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task SetTimeSpanAsync(this IDistributedCache cache, string key, TimeSpan value, DistributedCacheEntryOptions? options = null)
|
||||||
|
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options);
|
||||||
|
|
||||||
|
public static async Task<TimeSpan?> GetTimeSpanAsync(this IDistributedCache cache, string key)
|
||||||
|
{
|
||||||
|
var value = await cache.GetAsync(key);
|
||||||
|
return value is null ? null : new(BitConverter.ToInt64(value, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
|||||||
using DigitalData.Core.Client;
|
using DigitalData.Core.Client;
|
||||||
using EnvelopeGenerator.Application.Configurations.GtxMessaging;
|
using EnvelopeGenerator.Application.Configurations.GtxMessaging;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application
|
namespace EnvelopeGenerator.Application.Extensions
|
||||||
{
|
{
|
||||||
public static class DIExtensions
|
public static class DIExtensions
|
||||||
{
|
{
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using EnvelopeGenerator.Domain.HttpResponse;
|
using EnvelopeGenerator.Domain.HttpResponse;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application
|
namespace EnvelopeGenerator.Application.Extensions
|
||||||
{
|
{
|
||||||
public static class MappingExtensions
|
public static class MappingExtensions
|
||||||
{
|
{
|
||||||
@@ -5,6 +5,7 @@ using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
|||||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
|
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
|
||||||
using EnvelopeGenerator.Application.DTOs.Messaging;
|
using EnvelopeGenerator.Application.DTOs.Messaging;
|
||||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||||
|
using EnvelopeGenerator.Application.Extensions;
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
using EnvelopeGenerator.Domain.HttpResponse;
|
using EnvelopeGenerator.Domain.HttpResponse;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ using DigitalData.Core.Client;
|
|||||||
using EnvelopeGenerator.Application.Configurations.GtxMessaging;
|
using EnvelopeGenerator.Application.Configurations.GtxMessaging;
|
||||||
using EnvelopeGenerator.Application.Contracts;
|
using EnvelopeGenerator.Application.Contracts;
|
||||||
using EnvelopeGenerator.Application.DTOs.Messaging;
|
using EnvelopeGenerator.Application.DTOs.Messaging;
|
||||||
|
using EnvelopeGenerator.Application.Extensions;
|
||||||
using EnvelopeGenerator.Domain.HttpResponse;
|
using EnvelopeGenerator.Domain.HttpResponse;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Services
|
namespace EnvelopeGenerator.Application.Services
|
||||||
@@ -19,15 +21,21 @@ namespace EnvelopeGenerator.Application.Services
|
|||||||
|
|
||||||
private readonly ICodeGenerator _codeGen;
|
private readonly ICodeGenerator _codeGen;
|
||||||
|
|
||||||
|
private readonly IDistributedCache _cache;
|
||||||
|
|
||||||
public string ServiceProvider { get; }
|
public string ServiceProvider { get; }
|
||||||
|
|
||||||
public GtxMessagingService(IHttpClientService<SmsParams> smsClient, IOptions<SmsParams> smsParamsOptions, IMapper mapper, ICodeGenerator codeGenerator)
|
private readonly DistributedCacheEntryOptions _codeCacheOptions;
|
||||||
|
|
||||||
|
public GtxMessagingService(IHttpClientService<SmsParams> smsClient, IOptions<SmsParams> smsParamsOptions, IMapper mapper, ICodeGenerator codeGenerator, IDistributedCache distributedCache)
|
||||||
{
|
{
|
||||||
_smsClient = smsClient;
|
_smsClient = smsClient;
|
||||||
_smsParams = smsParamsOptions.Value;
|
_smsParams = smsParamsOptions.Value;
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
ServiceProvider = GetType().Name.Replace("Service", string.Empty);
|
ServiceProvider = GetType().Name.Replace("Service", string.Empty);
|
||||||
_codeGen = codeGenerator;
|
_codeGen = codeGenerator;
|
||||||
|
_cache = distributedCache;
|
||||||
|
_codeCacheOptions = new() { AbsoluteExpirationRelativeToNow = smsParamsOptions.Value.CodeCacheValidityPeriod };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SmsResponse> SendSmsAsync(string recipient, string message)
|
public async Task<SmsResponse> SendSmsAsync(string recipient, string message)
|
||||||
@@ -41,10 +49,30 @@ namespace EnvelopeGenerator.Application.Services
|
|||||||
.ThenAsync(_mapper.Map<SmsResponse>);
|
.ThenAsync(_mapper.Map<SmsResponse>);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SmsResponse> SendSmsCodeAsync(string recipient)
|
public async Task<SmsResponse> SendSmsCodeAsync(string recipient, string envelopeReceiverId)
|
||||||
{
|
{
|
||||||
var code = _codeGen.GenerateCode(_smsParams.CodeLength);
|
var code_expiration_key = string.Format(_smsParams.CodeExpirationCacheKeyFormat, envelopeReceiverId);
|
||||||
|
|
||||||
|
var code_key = string.Format(_smsParams.CodeCacheKeyFormat, envelopeReceiverId);
|
||||||
|
var code = await _cache.GetStringAsync(code_key);
|
||||||
|
|
||||||
|
if (code is null)
|
||||||
|
{
|
||||||
|
code = _codeGen.GenerateCode(_smsParams.CodeLength);
|
||||||
|
|
||||||
|
await _cache.SetStringAsync(code_key, code, _codeCacheOptions);
|
||||||
|
|
||||||
|
await _cache.SetDateTimeAsync(code_expiration_key, DateTime.Now + _smsParams.CodeCacheValidityPeriod, _codeCacheOptions);
|
||||||
|
|
||||||
return await SendSmsAsync(recipient: recipient, message: code);
|
return await SendSmsAsync(recipient: recipient, message: code);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var code_expiration = await _cache.GetDateTimeAsync(code_expiration_key);
|
||||||
|
return code_expiration is null
|
||||||
|
? new() { Ok = false }
|
||||||
|
: new() { Ok = false, AllowedAt = code_expiration };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using DigitalData.Core.API;
|
using DigitalData.Core.API;
|
||||||
using DigitalData.Core.Application;
|
using DigitalData.Core.Application;
|
||||||
using DigitalData.UserManager.Application;
|
using DigitalData.UserManager.Application;
|
||||||
using EnvelopeGenerator.Application;
|
using EnvelopeGenerator.Application.Extensions;
|
||||||
using EnvelopeGenerator.Infrastructure;
|
using EnvelopeGenerator.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ namespace EnvelopeGenerator.Web.Controllers
|
|||||||
//check if the user has phone is added
|
//check if the user has phone is added
|
||||||
if (er_secret.HasPhoneNumber)
|
if (er_secret.HasPhoneNumber)
|
||||||
{
|
{
|
||||||
var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!);
|
var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!, envelopeReceiverId: envelopeReceiverId);
|
||||||
if(res.Ok)
|
if(res.Ok)
|
||||||
return View("EnvelopeLocked").WithData("ViaSms", true);
|
return View("EnvelopeLocked").WithData("ViaSms", true);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ using EnvelopeGenerator.Application;
|
|||||||
using DigitalData.EmailProfilerDispatcher;
|
using DigitalData.EmailProfilerDispatcher;
|
||||||
using EnvelopeGenerator.Infrastructure;
|
using EnvelopeGenerator.Infrastructure;
|
||||||
using EnvelopeGenerator.Web.Sanitizers;
|
using EnvelopeGenerator.Web.Sanitizers;
|
||||||
|
using EnvelopeGenerator.Application.Extensions;
|
||||||
|
|
||||||
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
||||||
logger.Info("Logging initialized!");
|
logger.Info("Logging initialized!");
|
||||||
|
|||||||
Reference in New Issue
Block a user