diff --git a/EnvelopeGenerator.Application/Key.cs b/EnvelopeGenerator.Application/Key.cs
deleted file mode 100644
index aa44a367..00000000
--- a/EnvelopeGenerator.Application/Key.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-namespace EnvelopeGenerator.Application;
-
-///
-///
-///
-public static class Key
-{
- ///
- ///
- ///
- public static readonly string InnerServiceError = nameof(InnerServiceError);
-
- ///
- ///
- ///
- public static readonly string EnvelopeNotFound = nameof(EnvelopeNotFound);
-
- ///
- ///
- ///
- public static readonly string EnvelopeReceiverNotFound = nameof(EnvelopeReceiverNotFound);
-
- ///
- ///
- ///
- public static readonly string AccessCodeNull = nameof(AccessCodeNull);
-
- ///
- ///
- ///
- public static readonly string WrongAccessCode = nameof(WrongAccessCode);
-
- ///
- ///
- ///
- public static readonly string DataIntegrityIssue = nameof(DataIntegrityIssue);
-
- ///
- ///
- ///
- public static readonly string SecurityBreachOrDataIntegrity = nameof(SecurityBreachOrDataIntegrity);
-
- ///
- ///
- ///
- public static readonly string PossibleDataIntegrityIssue = nameof(PossibleDataIntegrityIssue);
-
- ///
- ///
- ///
- public static readonly string SecurityBreach = nameof(SecurityBreach);
-
- ///
- ///
- ///
- public static readonly string PossibleSecurityBreach = nameof(PossibleSecurityBreach);
-
- ///
- ///
- ///
- public static readonly string WrongEnvelopeReceiverId = nameof(WrongEnvelopeReceiverId);
-
- ///
- ///
- ///
- public static readonly string EnvelopeOrReceiverNonexists = nameof(EnvelopeOrReceiverNonexists);
-
- ///
- ///
- ///
- public static readonly string PhoneNumberNonexists = nameof(PhoneNumberNonexists);
-
- ///
- ///
- ///
- public static readonly string Default = nameof(Default);
-
- ///
- ///
- ///
- public static readonly string DbMigrationTest = nameof(DbMigrationTest);
-}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Application/Resources/Resource.cs b/EnvelopeGenerator.Application/Resources/Resource.cs
index 8b7e50aa..d8b51c1b 100644
--- a/EnvelopeGenerator.Application/Resources/Resource.cs
+++ b/EnvelopeGenerator.Application/Resources/Resource.cs
@@ -1,9 +1,137 @@
-namespace EnvelopeGenerator.Application.Resources
+using Microsoft.Extensions.Localization;
+using System.Runtime.CompilerServices;
+
+namespace EnvelopeGenerator.Application.Resources;
+
+///
+/// The place holder class for Resource.*.resx
+///
+public class Resource
+{
+}
+
+//TODO: use code generator
+///
+///
+///
+public static class Extensions
{
///
- /// The place holder class for Resource.*.resx
+ ///
///
- public class Resource
- {
- }
-}
+ ///
+ ///
+ public static string InnerServiceError(this IStringLocalizer localizer) => localizer[nameof(InnerServiceError)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string EnvelopeNotFound(this IStringLocalizer localizer) => localizer[nameof(EnvelopeNotFound)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string EnvelopeReceiverNotFound(this IStringLocalizer localizer) => localizer[nameof(EnvelopeReceiverNotFound)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string AccessCodeNull(this IStringLocalizer localizer) => localizer[nameof(AccessCodeNull)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string WrongAccessCode(this IStringLocalizer localizer) => localizer[nameof(WrongAccessCode)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string DataIntegrityIssue(this IStringLocalizer localizer) => localizer[nameof(DataIntegrityIssue)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string SecurityBreachOrDataIntegrity(this IStringLocalizer localizer) => localizer[nameof(SecurityBreachOrDataIntegrity)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string PossibleDataIntegrityIssue(this IStringLocalizer localizer) => localizer[nameof(PossibleDataIntegrityIssue)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string SecurityBreach(this IStringLocalizer localizer) => localizer[nameof(SecurityBreach)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string PossibleSecurityBreach(this IStringLocalizer localizer) => localizer[nameof(PossibleSecurityBreach)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string WrongEnvelopeReceiverId(this IStringLocalizer localizer) => localizer[nameof(WrongEnvelopeReceiverId)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string EnvelopeOrReceiverNonexists(this IStringLocalizer localizer) => localizer[nameof(EnvelopeOrReceiverNonexists)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string PhoneNumberNonexists(this IStringLocalizer localizer) => localizer[nameof(PhoneNumberNonexists)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string Default(this IStringLocalizer localizer) => localizer[nameof(Default)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string DbMigrationTest(this IStringLocalizer localizer) => localizer[nameof(DbMigrationTest)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string Culture(this IStringLocalizer localizer) => localizer[nameof(Culture)];
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string FiClass(this IStringLocalizer localizer) => localizer[nameof(FiClass)];
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx
index ca8a6a7d..2fe7b8d8 100644
--- a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx
+++ b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx
@@ -129,6 +129,9 @@
Bestätigung
+
+ de-DE
+
Deutch
@@ -150,6 +153,9 @@
Erstellt am {0} von {1}. Sie können den Absender über <span class="highlight highlight-envelope-info-2"><a class="mail-link" href="mailto:{2}?subject={3}&body=Sehr%20geehrter%20{4}%20{5},%0A%0A%0A">{6}</a></span> kontaktieren.
+
+ fi-de
+
Abschließen
diff --git a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx
index c2a8658c..d0e8d116 100644
--- a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx
+++ b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx
@@ -129,6 +129,9 @@
Confirmation
+
+ en-US
+
German
@@ -150,6 +153,9 @@
Created on {0} by {1}. You can contact the sender via <span class="highlight highlight-envelope-info-2"><a class="mail-link" href="mailto:{2}?subject={3}&body=Dear%20{4}%20{5},%0A%0A%0A">{6}</a></span>.
+
+ fi-us
+
Finalize
diff --git a/EnvelopeGenerator.Application/Services/EmailTemplateService.cs b/EnvelopeGenerator.Application/Services/EmailTemplateService.cs
index bb628376..97aaa752 100644
--- a/EnvelopeGenerator.Application/Services/EmailTemplateService.cs
+++ b/EnvelopeGenerator.Application/Services/EmailTemplateService.cs
@@ -36,7 +36,7 @@ public class EmailTemplateService : BasicCRUDService()
- .Message(Key.InnerServiceError)
+ .Message("InnerServiceError")
.Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"EmailTemplateType '{type}' is not found in DB. Please, define required e-mail template.")
: Result.Success(_mapper.Map(temp));
}
diff --git a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs
index c13c0ac9..c845dec6 100644
--- a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs
+++ b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs
@@ -82,7 +82,7 @@ public class EnvelopeReceiverService : BasicCRUDService>()
- .Message(_localizer[Key.EnvelopeReceiverNotFound]);
+ .Message(_localizer.EnvelopeReceiverNotFound());
return Result.Success(env_rcvs.Select(er => er.AccessCode) ?? Enumerable.Empty());
}
@@ -100,7 +100,7 @@ public class EnvelopeReceiverService : BasicCRUDService()
- .Message(Key.EnvelopeReceiverNotFound);
+ .Message("EnvelopeReceiverNotFound");
return Result.Success(_mapper.Map(env_rcv));
}
@@ -119,7 +119,7 @@ public class EnvelopeReceiverService : BasicCRUDService()
- .Message(Key.EnvelopeReceiverNotFound);
+ .Message("EnvelopeReceiverNotFound");
return Result.Success(_mapper.Map(env_rcv));
}
@@ -138,7 +138,7 @@ public class EnvelopeReceiverService : BasicCRUDService()
- .Message(_localizer[Key.WrongEnvelopeReceiverId])
+ .Message(_localizer.WrongEnvelopeReceiverId())
.Notice(LogLevel.Warning, (uuid, signature).ToTitle())
.Notice(LogLevel.Warning, EnvelopeFlag.WrongEnvelopeReceiverId)
.Notice(LogLevel.Warning, Flag.PossibleSecurityBreach);
@@ -159,7 +159,7 @@ public class EnvelopeReceiverService : BasicCRUDService()
- .Message(_localizer[Key.EnvelopeOrReceiverNonexists])
+ .Message(_localizer.EnvelopeOrReceiverNonexists())
.Notice(LogLevel.Warning, (uuid, signature).ToTitle())
.Notice(LogLevel.Warning, EnvelopeFlag.EnvelopeOrReceiverNonexists)
.Notice(LogLevel.Warning, Flag.PossibleDataIntegrityIssue);
@@ -168,13 +168,13 @@ public class EnvelopeReceiverService : BasicCRUDService()
- .Message(_localizer[Key.AccessCodeNull])
+ .Message(_localizer.AccessCodeNull())
.Notice(LogLevel.Critical, (uuid, signature).ToTitle())
.Notice(LogLevel.Critical, EnvelopeFlag.AccessCodeNull)
.Notice(LogLevel.Critical, Flag.DataIntegrityIssue);
else if (accessCode != actualAccessCode)
- return Result.Success(false).Message(_localizer[Key.WrongAccessCode]);
+ return Result.Success(false).Message(_localizer.WrongAccessCode());
else
return Result.Success(true);
}
@@ -191,7 +191,7 @@ public class EnvelopeReceiverService : BasicCRUDService()
- .Message(Key.WrongEnvelopeReceiverId)
+ .Message("WrongEnvelopeReceiverId")
.Notice(LogLevel.Critical, EnvelopeFlag.WrongEnvelopeReceiverId)
.Notice(LogLevel.Critical, Flag.SecurityBreach)
.Notice(LogLevel.Critical, "Attempt to verify access code detected. Such actions are generally not initiated by well-intentioned users. Potential security breach suspected. Immediate investigation required.");
@@ -287,7 +287,7 @@ public class EnvelopeReceiverService : BasicCRUDService()
- .Message(_localizer[Key.WrongEnvelopeReceiverId])
+ .Message(_localizer.WrongEnvelopeReceiverId())
.Notice(LogLevel.Warning, (uuid, signature).ToTitle())
.Notice(LogLevel.Warning, EnvelopeFlag.WrongEnvelopeReceiverId)
.Notice(LogLevel.Warning, Flag.PossibleSecurityBreach);
@@ -295,11 +295,11 @@ public class EnvelopeReceiverService : BasicCRUDService()
- .Message(Key.EnvelopeReceiverNotFound);
+ .Message("EnvelopeReceiverNotFound");
if (env_rcv.PhoneNumber is null)
return Result.Fail()
- .Message(Key.PhoneNumberNonexists)
+ .Message("PhoneNumberNonexists")
.Notice(LogLevel.Error, Flag.NotFound, $"An attempt was made to send sms to the user whose phone number is null. Envelope recipient ID is {envelopeReceiverId}, UUID is {uuid} and signature is {signature}.");
var res = await _smsSender.SendSmsAsync(recipient: env_rcv.PhoneNumber, message: message);
diff --git a/EnvelopeGenerator.Web/Controllers/ControllerBaseExtensions.cs b/EnvelopeGenerator.Web/Controllers/ControllerBaseExtensions.cs
index 4e095c09..0a18c0e0 100644
--- a/EnvelopeGenerator.Web/Controllers/ControllerBaseExtensions.cs
+++ b/EnvelopeGenerator.Web/Controllers/ControllerBaseExtensions.cs
@@ -1,7 +1,8 @@
using EnvelopeGenerator.Application.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Web.Models;
-using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
@@ -55,6 +56,25 @@ namespace EnvelopeGenerator.Web.Controllers
}
#endregion
+ #region Cookie
+ public static string? GetCulture(this IRequestCookieCollection cookies)
+ => cookies[CookieRequestCultureProvider.DefaultCookieName];
+
+ public static void SetCulture(this IResponseCookies cookies, string culture)
+ {
+ var cookieOptions = new CookieOptions
+ {
+ Secure = false,
+ SameSite = SameSiteMode.Strict,
+ HttpOnly = true
+ };
+ cookies.Append(
+ CookieRequestCultureProvider.DefaultCookieName,
+ CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
+ cookieOptions);
+ }
+ #endregion
+
#region View error
//TODO: integrate localizer for ready-to-use views
//TODO: integrate to global exception handler middleware
diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs
index 48ffec29..9a5d42f5 100644
--- a/EnvelopeGenerator.Web/Controllers/HomeController.cs
+++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs
@@ -58,8 +58,6 @@ public class HomeController : ViewControllerBase
[HttpGet("/")]
public IActionResult Main()
{
- ViewData["UserCulture"] = _cultures[UserLanguage];
-
return View(new MainViewModel()
{
Title = _configuration["MainPageTitle"]
@@ -118,8 +116,6 @@ public class HomeController : ViewControllerBase
{
try
{
- ViewData["UserCulture"] = _cultures[UserLanguage];
-
return await _envRcvService.ReadByEnvelopeReceiverIdAsync(envelopeReceiverId: envelopeReceiverId).ThenAsync(
SuccessAsync: async er => {
if (User.IsInRole(ReceiverRole.FullyAuth))
@@ -151,7 +147,6 @@ public class HomeController : ViewControllerBase
{
try
{
- ViewData["UserCulture"] = _cultures[UserLanguage];
ViewData["EnvelopeKey"] = envelopeReceiverId;
envelopeReceiverId = _sanitizer.Sanitize(envelopeReceiverId);
@@ -310,7 +305,6 @@ public class HomeController : ViewControllerBase
{
try
{
- ViewData["UserCulture"] = _cultures[UserLanguage];
ViewData["EnvelopeKey"] = envelopeReceiverId;
envelopeReceiverId = _sanitizer.Sanitize(envelopeReceiverId);
@@ -398,7 +392,6 @@ public class HomeController : ViewControllerBase
return base.Redirect($"/EnvelopeKey/{envelopeReceiverId}/Locked");
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
- ViewData["UserCulture"] = _cultures[UserLanguage];
ViewData["EnvelopeKey"] = envelopeReceiverId;
return base.View();
}),
@@ -428,8 +421,6 @@ public class HomeController : ViewControllerBase
return await _envRcvService.ReadByEnvelopeReceiverIdAsync(envelopeReceiverId).ThenAsync(
SuccessAsync: async (er) =>
{
- ViewData["UserCulture"] = _cultures[UserLanguage];
- ViewData["UserCulture"] = _cultures[UserLanguage];
return await _historyService.IsRejected(envelopeId: er.EnvelopeId)
? View(er)
: Redirect($"/EnvelopeKey/{envelopeReceiverId}/Locked");
@@ -454,8 +445,6 @@ public class HomeController : ViewControllerBase
{
try
{
- ViewData["UserCulture"] = _cultures[UserLanguage];
-
readOnlyKey = _sanitizer.Sanitize(readOnlyKey);
// check if the readOnlyId is valid
@@ -530,26 +519,15 @@ public class HomeController : ViewControllerBase
return Ok(new { EnvelopeUuid = envelopeUuid, ReceiverSignature = receiverSignature });
}
- [HttpPost("lang/{language}")]
- public IActionResult SetLanguage([FromRoute] string language)
+ [HttpPost("lang/{culture}")]
+ public IActionResult SetLanguage([FromRoute] string culture)
{
try
{
- language = _sanitizer.Sanitize(language);
- if (!_cultures.Languages.Contains(language))
+ if (!_cultures.Languages.Contains(culture))
return BadRequest();
- var cookieOptions = new CookieOptions()
- {
- Secure = false,
- SameSite = SameSiteMode.Strict,
- HttpOnly = true
- };
-
- Response.Cookies.Append(
- CookieRequestCultureProvider.DefaultCookieName,
- CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(language)),
- cookieOptions);
+ Response.Cookies.SetCulture(culture);
return Redirect(Request.Headers["Referer"].ToString());
}
@@ -563,7 +541,5 @@ public class HomeController : ViewControllerBase
[HttpGet("lang")]
public IActionResult GetLanguages() => Ok(_cultures.Languages);
- private string? UserLanguage => Request.Cookies[CookieRequestCultureProvider.DefaultCookieName];
-
public IActionResult Error404() => this.ViewError404();
}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Web/Middleware/CultureMiddleware.cs b/EnvelopeGenerator.Web/Middleware/CultureMiddleware.cs
index 170fa44d..51243878 100644
--- a/EnvelopeGenerator.Web/Middleware/CultureMiddleware.cs
+++ b/EnvelopeGenerator.Web/Middleware/CultureMiddleware.cs
@@ -1,4 +1,5 @@
-using EnvelopeGenerator.Web.Models;
+using EnvelopeGenerator.Web.Controllers;
+using EnvelopeGenerator.Web.Models;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Options;
using System.Globalization;
@@ -23,20 +24,7 @@ public class CultureMiddleware
if (string.IsNullOrEmpty(cookieValue))
{
- var culture = new RequestCulture(_cultures.Default.Language);
-
- var cookieOptions = new CookieOptions
- {
- Secure = false,
- SameSite = SameSiteMode.Strict,
- HttpOnly = true
- };
-
- context.Response.Cookies.Append(
- cookieName,
- CookieRequestCultureProvider.MakeCookieValue(culture),
- cookieOptions);
-
+ context.Response.Cookies.SetCulture(_cultures.Default.Language);
CultureInfo.CurrentCulture = new CultureInfo(_cultures.Default.Language);
CultureInfo.CurrentUICulture = new CultureInfo(_cultures.Default.Language);
}
diff --git a/EnvelopeGenerator.Web/Program.cs b/EnvelopeGenerator.Web/Program.cs
index 6ee88eb6..64df0616 100644
--- a/EnvelopeGenerator.Web/Program.cs
+++ b/EnvelopeGenerator.Web/Program.cs
@@ -90,7 +90,7 @@ try
//AddEF Core dbcontext
var useDbMigration = Environment.GetEnvironmentVariable("MIGRATION_TEST_MODE") == true.ToString() || config.GetValue("UseDbMigration");
- var cnnStrName = useDbMigration ? Key.DbMigrationTest : Key.Default;
+ var cnnStrName = useDbMigration ? "DbMigrationTest" : "Default";
var connStr = config.GetConnectionString(cnnStrName)
?? throw new InvalidOperationException($"Connection string '{cnnStrName}' is missing in the application configuration.");
diff --git a/EnvelopeGenerator.Web/Services/DatabaseService.cs b/EnvelopeGenerator.Web/Services/DatabaseService.cs
index 98674029..9ec03ae0 100644
--- a/EnvelopeGenerator.Web/Services/DatabaseService.cs
+++ b/EnvelopeGenerator.Web/Services/DatabaseService.cs
@@ -57,7 +57,7 @@ namespace EnvelopeGenerator.Web.Services
_logger = logger;
_logger.LogInformation("Establishing MSSQL Database connection..");
- MSSQL = new MSSQLServer(logConfig, config.GetConnectionString(Key.Default));
+ MSSQL = new MSSQLServer(logConfig, config.GetConnectionString("Default"));
if (MSSQL.DBInitialized == true)
{
diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml
index e28dae1b..c182dce6 100644
--- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml
+++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml
@@ -6,7 +6,6 @@
var nonce = _accessor.HttpContext?.Items["csp-nonce"] as string;
var cImg = _cImgOpt.Value;
ViewData["Title"] = _localizer[WebKey.DocProtected];
- var userCulture = ViewData["UserCulture"] as Culture;
string codeType = ViewData["CodeType"] is string _codeType ? _codeType : "accessCode";
string codeKeyName = (char.ToUpper(codeType[0]) + codeType.Substring(1)).Replace("Code", "");
bool viaSms = codeType == "smsCode";
diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml
index 6e4e8e37..467073ba 100644
--- a/EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml
+++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml
@@ -10,7 +10,6 @@
@using Newtonsoft.Json.Serialization
@model EnvelopeReceiverDto;
@{
- var userCulture = ViewData["UserCulture"] as Culture;
var envelope = Model.Envelope;
var document = Model.Envelope?.Documents?.FirstOrDefault();
var sender = Model.Envelope?.User;
diff --git a/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml b/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml
index 97f17d75..ce954b26 100644
--- a/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml
+++ b/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml
@@ -3,9 +3,6 @@
@using Newtonsoft.Json.Serialization
@{
var nonce = _accessor.HttpContext?.Items["csp-nonce"] as string;
- var userCulture = ViewData["UserCulture"] as Culture;
- //TODO: instead of default assignment add a middleware for culture
- userCulture ??= _cultures.Default;
var isReadOnly = false;
if (ViewData["IsReadOnly"] is bool isReadOnly_bool)
isReadOnly = isReadOnly_bool;
@@ -83,7 +80,7 @@
© SignFlow 2023-2024 Digital Data GmbH
- @_localizer[WebKey.Privacy]
+ @_localizer[WebKey.Privacy]