diff --git a/Controllers/AuthenticationController.cs b/Controllers/AuthenticationController.cs index d16d97e5a717d9f074c64c7bed34f87ed9001d44..b0e8d57bf766ac4a325c9449a938f6d35977dba3 100644 --- a/Controllers/AuthenticationController.cs +++ b/Controllers/AuthenticationController.cs @@ -2,16 +2,19 @@ namespace AuthenticationMicroservice.Controllers; using System.Net; using System.Security.Claims; +using System.Text; using Exceptions; using Helpers; using LazyCache; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Middleware; using Models.DTOs; using Models.Entities; using Services; +using Settings; using Swashbuckle.AspNetCore.Annotations; [Route("api/[controller]")] @@ -20,17 +23,19 @@ public class AuthController : BaseAuthController { private readonly IAuthService _authService; private readonly IEmailService _emailService; + private readonly FrontendStrings _frontendStrings; private readonly IAppCache _memoryCache; private readonly IRefreshTokenService _refreshTokenService; private readonly IUserService _userService; public AuthController(IAppCache memoryCache, IAuthService authService, IRefreshTokenService refreshTokenService, - IUserService userService, IEmailService emailService) + IUserService userService, IEmailService emailService, IOptions<FrontendStrings> frontendStrings) { _authService = authService; _memoryCache = memoryCache; _userService = userService; _emailService = emailService; + _frontendStrings = frontendStrings.Value; _refreshTokenService = refreshTokenService; } @@ -211,7 +216,8 @@ public class AuthController : BaseAuthController if (request.EmailAddress != null) _emailService.SendEmail(new EmailDTO { - Subject = "Successfully Registered", Body = "Test", Receiver = request.EmailAddress, + Subject = "Successfully Registered", Body = GetRegisteredUserTableEmail(createdUser), + Receiver = request.EmailAddress, To = request.Username }).FireAndForget(); return Ok(authenticatedUser); @@ -305,4 +311,34 @@ public class AuthController : BaseAuthController return BadRequest(ex.Message); } } + + private string GetRegisteredUserTableEmail(User user) + { + var s = new StringBuilder(); + s.Append($"<table {EmailHelper.TableProperties(TableSize.Small)}>"); + s.Append("<thead>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableHeader(2)}>New User Registration</th>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>First Name</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.FirstName}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>Surname</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.Surname}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>Username</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.Username}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<td {EmailHelper.TableFooter(2)}></td>"); + s.Append("</tr>"); + s.Append("</thead>"); + s.Append("</table>"); + s.Append( + $"<p style='font-family: sans-serif'>Please click here to <a href='{_frontendStrings.BaseUrl}/ConfirmEmail?{user.EmailConfirmationToken}'>confirm your email.</a></p>"); + return s.ToString(); + } } \ No newline at end of file diff --git a/Helpers/EmailHelper.cs b/Helpers/EmailHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..46cc419438594ddc643da3b792ed45feb9af65cc --- /dev/null +++ b/Helpers/EmailHelper.cs @@ -0,0 +1,32 @@ +namespace AuthenticationMicroservice.Helpers; + +public enum TableSize +{ + Small = 500, + Medium = 800, + Large = 1000 +} + +public static class EmailHelper +{ + public const string TableCell = + " style='color:#000; padding-bottom:1%; vertical-align: middle; border-bottom: 1px solid #8D8AD8; border-left: 1px solid #8D8AD8; border-right: 1px solid #8D8AD8;'"; + + public static string TableProperties(TableSize width) + { + return + $"width={width} cellpadding=0 cellspacing=0 border=0 style='text-align: center; font-family: sans-serif'"; + } + + public static string TableHeader(int colspan) + { + return + $"colspan='{colspan}' style='color:#000; background:#8D8AD8; text-align: center; border-bottom: 1px solid #414447; font-weight: 100; padding:8px; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); border-top-left-radius:10px; border-top-right-radius:10px;'"; + } + + public static string TableFooter(int colspan) + { + return + $"colspan='{colspan}' style='color:#000; background:#8D8AD8; text-align: center; font-weight: 100; padding:8px; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); border-bottom-left-radius:10px; border-bottom-right-radius:10px;'"; + } +} \ No newline at end of file diff --git a/Services/AuthService.cs b/Services/AuthService.cs index 3826dd8c3b6326a3e44f91717edb35ba1c938488..a0ee0190c5784af9c4e2500f8ad5717e7b142bf9 100644 --- a/Services/AuthService.cs +++ b/Services/AuthService.cs @@ -1,13 +1,16 @@ namespace AuthenticationMicroservice.Services; using System.Net; +using System.Text; using Exceptions; using Helpers; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Models; using Models.DTOs; using Models.Entities; +using Settings; using static Guid; public interface IAuthService @@ -28,13 +31,15 @@ public class AuthService : IAuthService { private readonly AuthenticationDbContext _context; private readonly IEmailService _emailService; + private readonly FrontendStrings _frontendStrings; private readonly IRefreshTokenService _refreshTokenService; public AuthService(AuthenticationDbContext context, IEmailService emailService, - IRefreshTokenService refreshTokenService) + IRefreshTokenService refreshTokenService, IOptions<FrontendStrings> frontendStrings) { _context = context; _emailService = emailService; + _frontendStrings = frontendStrings.Value; _refreshTokenService = refreshTokenService; } @@ -142,7 +147,8 @@ public class AuthService : IAuthService throw new AuthenticationException("User already confirmed.", HttpStatusCode.Unauthorized); _emailService.SendEmail(new EmailDTO { - Subject = "Resend Confirm Email", Body = "Test", To = user.UnconfirmedEmail!, Receiver = user.Username + Subject = "Resend Confirm Email", Body = GetResendConfirmTableEmail(user), To = user.UnconfirmedEmail!, + Receiver = user.Username }) .FireAndForget(); } @@ -158,7 +164,10 @@ public class AuthService : IAuthService _context.User.Update(user); await _context.SaveChangesAsync(); _emailService.SendEmail(new EmailDTO - {Subject = "Forgot Password", Body = "Test", To = request.EmailAddress!, Receiver = user.Username}) + { + Subject = "Forgot Password", Body = GetForgotPasswordTableEmail(user), To = request.EmailAddress!, + Receiver = user.Username + }) .FireAndForget(); } @@ -217,4 +226,64 @@ public class AuthService : IAuthService _context.User.Update(user); await _context.SaveChangesAsync(); } + + private string GetResendConfirmTableEmail(User user) + { + var s = new StringBuilder(); + s.Append($"<table {EmailHelper.TableProperties(TableSize.Small)}>"); + s.Append("<thead>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableHeader(2)}>New User Registration</th>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>First Name</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.FirstName}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>Surname</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.Surname}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>Username</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.Username}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<td {EmailHelper.TableFooter(2)}></td>"); + s.Append("</tr>"); + s.Append("</thead>"); + s.Append("</table>"); + s.Append( + $"<p style='font-family: sans-serif'>Please click here to <a href='{_frontendStrings.BaseUrl}/ConfirmEmail?{user.EmailConfirmationToken}'>confirm your email.</a></p>"); + return s.ToString(); + } + + private string GetForgotPasswordTableEmail(User user) + { + var s = new StringBuilder(); + s.Append($"<table {EmailHelper.TableProperties(TableSize.Small)}>"); + s.Append("<thead>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableHeader(2)}>Password Reset</th>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>First Name</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.FirstName}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>Surname</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.Surname}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<th {EmailHelper.TableCell}>Username</th>"); + s.Append($"<td {EmailHelper.TableCell}>{user.Username}</td>"); + s.Append("</tr>"); + s.Append("<tr>"); + s.Append($"<td {EmailHelper.TableFooter(2)}></td>"); + s.Append("</tr>"); + s.Append("</thead>"); + s.Append("</table>"); + s.Append( + $"<p style='font-family: sans-serif'>Please click here to <a href='{_frontendStrings.BaseUrl}/ResetPassword?{user.PasswordResetToken}'>reset your password.</a></p>"); + return s.ToString(); + } } \ No newline at end of file diff --git a/Settings/ConnectionStrings.cs b/Settings/ConnectionStrings.cs index bc9e8b1e2d71c3b8d3304970cb4f1300f2feb022..0b08d8641bc80c3100c2b24ba18027a62ce1f5dd 100644 --- a/Settings/ConnectionStrings.cs +++ b/Settings/ConnectionStrings.cs @@ -3,5 +3,4 @@ public class ConnectionStrings { public string? DbConnectionString { get; set; } = ""; - public string? AzureBlobStorage { get; set; } = ""; } \ No newline at end of file