From 6561771c435f9d9bed1589b5ed13d17aee0b7873 Mon Sep 17 00:00:00 2001 From: ivarlovlie Date: Sun, 11 Dec 2022 20:46:58 +0100 Subject: feat: Add frontpage --- .../Internal/Account/CreateAccountRoute.cs | 1 + .../Internal/Root/IsAuthenticatedRoute.cs | 10 +++++ .../Endpoints/Internal/Root/ValidSessionRoute.cs | 10 ----- .../src/Endpoints/Internal/Root/ValidateRoute.cs | 25 ++++++++++++ .../src/Resources/SharedResources.nb.Designer.cs | 6 +++ code/api/src/Resources/SharedResources.nb.resx | 13 +++++++ code/api/src/Services/UserService.cs | 45 ++++++++++++++++++---- 7 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 code/api/src/Endpoints/Internal/Root/IsAuthenticatedRoute.cs delete mode 100644 code/api/src/Endpoints/Internal/Root/ValidSessionRoute.cs create mode 100644 code/api/src/Endpoints/Internal/Root/ValidateRoute.cs (limited to 'code/api/src') diff --git a/code/api/src/Endpoints/Internal/Account/CreateAccountRoute.cs b/code/api/src/Endpoints/Internal/Account/CreateAccountRoute.cs index 44b8376..c114bb8 100644 --- a/code/api/src/Endpoints/Internal/Account/CreateAccountRoute.cs +++ b/code/api/src/Endpoints/Internal/Account/CreateAccountRoute.cs @@ -46,6 +46,7 @@ public class CreateAccountRoute : RouteBaseAsync.WithRequest _userService.SendValidationEmail(user), cancellationToken); return Ok(); } } \ No newline at end of file diff --git a/code/api/src/Endpoints/Internal/Root/IsAuthenticatedRoute.cs b/code/api/src/Endpoints/Internal/Root/IsAuthenticatedRoute.cs new file mode 100644 index 0000000..7bb0a86 --- /dev/null +++ b/code/api/src/Endpoints/Internal/Root/IsAuthenticatedRoute.cs @@ -0,0 +1,10 @@ +namespace IOL.GreatOffice.Api.Endpoints.Internal.Root; + +public class IsAuthenticatedRoute : RouteBaseSync.WithoutRequest.WithActionResult +{ + [Authorize] + [HttpGet("~/_/is-authenticated")] + public override ActionResult Handle() { + return Ok(); + } +} \ No newline at end of file diff --git a/code/api/src/Endpoints/Internal/Root/ValidSessionRoute.cs b/code/api/src/Endpoints/Internal/Root/ValidSessionRoute.cs deleted file mode 100644 index f377ff6..0000000 --- a/code/api/src/Endpoints/Internal/Root/ValidSessionRoute.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace IOL.GreatOffice.Api.Endpoints.Internal.Root; - -public class ValidSessionRoute : RouteBaseSync.WithoutRequest.WithActionResult -{ - [Authorize] - [HttpGet("~/_/valid-session")] - public override ActionResult Handle() { - return Ok(); - } -} \ No newline at end of file diff --git a/code/api/src/Endpoints/Internal/Root/ValidateRoute.cs b/code/api/src/Endpoints/Internal/Root/ValidateRoute.cs new file mode 100644 index 0000000..682a869 --- /dev/null +++ b/code/api/src/Endpoints/Internal/Root/ValidateRoute.cs @@ -0,0 +1,25 @@ +namespace IOL.GreatOffice.Api.Endpoints.Internal.Root; + +public class ValidateRoute : RouteBaseSync.WithRequest.WithActionResult +{ + private readonly UserService _userService; + private readonly string _continueTo; + + public ValidateRoute(UserService userService, VaultService vaultService) { + _userService = userService; + var c = vaultService.GetCurrentAppConfiguration(); + _continueTo = c.CANONICAL_FRONTEND_URL + "/?act=email-validated"; + } + + public class QueryParams + { + [FromQuery] + public Guid Id { get; set; } + } + + [HttpGet("~/_/validate")] + public override ActionResult Handle([FromQuery] QueryParams request) { + _userService.FulfillEmailValidationRequest(request.Id, LoggedInUser.Id); + return Redirect(_continueTo); + } +} \ No newline at end of file diff --git a/code/api/src/Resources/SharedResources.nb.Designer.cs b/code/api/src/Resources/SharedResources.nb.Designer.cs index 37006f2..2613026 100644 --- a/code/api/src/Resources/SharedResources.nb.Designer.cs +++ b/code/api/src/Resources/SharedResources.nb.Designer.cs @@ -80,5 +80,11 @@ namespace IOL.GreatOffice.Api.Resources { return ResourceManager.GetString("One or more validation errors occured", resourceCulture); } } + + internal static string Greatoffice_Email_Validation { + get { + return ResourceManager.GetString("Greatoffice Email Validation", resourceCulture); + } + } } } diff --git a/code/api/src/Resources/SharedResources.nb.resx b/code/api/src/Resources/SharedResources.nb.resx index 880274e..ac31409 100644 --- a/code/api/src/Resources/SharedResources.nb.resx +++ b/code/api/src/Resources/SharedResources.nb.resx @@ -46,4 +46,17 @@ En eller flere valideringsfeil har oppstått + + Hei, {0}. + +Bekreft din e-postadresse ved å åpne denne lenken i en nettleser {1} + Hello, {0}. + + Validate your email address by opening this link in a browser {1} + + + Greatoffice e-postaddresse bekreftelse + Greatoffice Email Validation + \ No newline at end of file diff --git a/code/api/src/Services/UserService.cs b/code/api/src/Services/UserService.cs index 8b925be..4c632be 100644 --- a/code/api/src/Services/UserService.cs +++ b/code/api/src/Services/UserService.cs @@ -10,15 +10,16 @@ public class UserService private readonly ILogger _logger; private readonly IStringLocalizer _localizer; private readonly MainAppDatabase _database; - private string EmailValidationUrl; + private readonly string EmailValidationUrl; - public UserService(PasswordResetService passwordResetService, MailService mailService, IStringLocalizer localizer, VaultService vaultService, MainAppDatabase database) { + public UserService(PasswordResetService passwordResetService, MailService mailService, IStringLocalizer localizer, VaultService vaultService, MainAppDatabase database, ILogger logger) { _passwordResetService = passwordResetService; _mailService = mailService; _localizer = localizer; _database = database; + _logger = logger; var configuration = vaultService.GetCurrentAppConfiguration(); - EmailValidationUrl = configuration.CANONICAL_BACKEND_URL + "/validate"; + EmailValidationUrl = configuration.CANONICAL_BACKEND_URL + "/_/validate"; } public async Task LogInUser(HttpContext httpContext, User user, bool persist = false) { @@ -49,7 +50,39 @@ public class UserService _logger.LogInformation("Logged out user {0}", httpContext.User.FindFirst(AppClaims.USER_ID)); } + public bool FulfillEmailValidationRequest(Guid id, Guid userId) { + var item = _database.ValidationEmails.FirstOrDefault(c => c.Id == id); + if (item == default) { + _logger.LogDebug("Did not find email validation request with id: {0}", id); + return false; + } + + if (item.UserId != userId) { + _logger.LogInformation("An unknown user tried to validate the email validation request {0}"); + return false; + } + + var user = _database.Users.FirstOrDefault(c => c.Id == item.UserId); + if (user == default) { + _database.ValidationEmails.Remove(item); + _database.SaveChanges(); + _logger.LogInformation("Deleting request {0} because user does not exist anymore"); + return false; + } + + user.EmailLastValidated = DateTime.UtcNow; + user.SetModified(); + _database.ValidationEmails.Remove(item); + _database.SaveChanges(); + _logger.LogInformation("Successfully validated the email for user {0}", user.Id); + return true; + } + public async Task SendValidationEmail(User user) { + var queueItem = new ValidationEmail() { + UserId = user.Id, + Id = Guid.NewGuid() + }; var email = new MailService.PostmarkEmail() { To = user.Username, Subject = _localizer["Greatoffice Email Validation"], @@ -57,11 +90,7 @@ public class UserService Hello, {0}. Validate your email address by opening this link in a browser {1} -""", user.DisplayName(), EmailValidationUrl + "?email=" + user.Username] - }; - var queueItem = new ValidationEmail() { - UserId = user.Id, - Id = Guid.NewGuid() +""", user.DisplayName(), EmailValidationUrl + "?id=" + queueItem.Id] }; await _mailService.SendMail(email); queueItem.EmailSentAt = DateTime.UtcNow; -- cgit v1.3