aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/Services
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2022-10-05 14:45:21 +0200
committerivarlovlie <git@ivarlovlie.no>2022-10-05 14:45:21 +0200
commitb7e39b59fd0fc7b5610ebff29035bf622079e0d8 (patch)
tree64be84ebbdac9f7ceced983390c53b10d575af5c /server/src/Services
parent2001c035fbb417ab0a3d42cfb04d17420bde4086 (diff)
downloadgreatoffice-b7e39b59fd0fc7b5610ebff29035bf622079e0d8.tar.xz
greatoffice-b7e39b59fd0fc7b5610ebff29035bf622079e0d8.zip
refactor: Change file structure
Diffstat (limited to 'server/src/Services')
-rw-r--r--server/src/Services/MailService.cs49
-rw-r--r--server/src/Services/PasswordResetService.cs115
-rw-r--r--server/src/Services/UserService.cs50
-rw-r--r--server/src/Services/VaultService.cs158
4 files changed, 0 insertions, 372 deletions
diff --git a/server/src/Services/MailService.cs b/server/src/Services/MailService.cs
deleted file mode 100644
index c08cb84..0000000
--- a/server/src/Services/MailService.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-namespace IOL.GreatOffice.Api.Services;
-
-public class MailService
-{
- private readonly ILogger<MailService> _logger;
- private static string _emailHost;
- private static int _emailPort;
- private static string _emailUser;
- private static string _emailPassword;
-
- public MailService(VaultService vaultService, ILogger<MailService> logger) {
- var configuration = vaultService.GetCurrentAppConfiguration();
- _logger = logger;
- _emailHost = configuration.SMTP_HOST;
- _emailPort = Convert.ToInt32(configuration.SMTP_PORT);
- _emailUser = configuration.SMTP_USER;
- _emailPassword = configuration.SMTP_PASSWORD;
- }
-
- /// <summary>
- /// Send an email.
- /// </summary>
- /// <param name="message"></param>
- public void SendMail(MailMessage message) {
- using var smtpClient = new SmtpClient {
- Host = _emailHost,
- EnableSsl = _emailPort == 587,
- Port = _emailPort,
- Credentials = new NetworkCredential {
- UserName = _emailUser,
- Password = _emailPassword,
- }
- };
- var configurationString = JsonSerializer.Serialize(new {
- smtpClient.Host,
- smtpClient.EnableSsl,
- smtpClient.Port,
- UserName = _emailUser.HasValue() ? "**REDACTED**" : "**MISSING**",
- Password = _emailPassword.HasValue() ? "**REDACTED**" : "**MISSING**",
- },
- new JsonSerializerOptions {
- WriteIndented = true
- });
-
- _logger.LogDebug("SmtpClient was instansiated with the following configuration\n" + configurationString);
-
- smtpClient.Send(message);
- }
-} \ No newline at end of file
diff --git a/server/src/Services/PasswordResetService.cs b/server/src/Services/PasswordResetService.cs
deleted file mode 100644
index 1b4f147..0000000
--- a/server/src/Services/PasswordResetService.cs
+++ /dev/null
@@ -1,115 +0,0 @@
-namespace IOL.GreatOffice.Api.Services;
-
-public class PasswordResetService
-{
- private readonly AppDbContext _context;
- private readonly MailService _mailService;
- private readonly AppConfiguration _configuration;
- private readonly ILogger<PasswordResetService> _logger;
-
-
- public PasswordResetService(
- AppDbContext context,
- VaultService vaultService,
- ILogger<PasswordResetService> logger,
- MailService mailService
- ) {
- _context = context;
- _configuration = vaultService.GetCurrentAppConfiguration();
- _logger = logger;
- _mailService = mailService;
- }
-
- public async Task<ForgotPasswordRequest> GetRequestAsync(Guid id, CancellationToken cancellationToken = default) {
- var request = await _context.ForgotPasswordRequests
- .Include(c => c.User)
- .SingleOrDefaultAsync(c => c.Id == id, cancellationToken);
- if (request == default) {
- return default;
- }
-
- _logger.LogInformation($"Found password reset request for user: {request.User.Username}, expires at {request.ExpirationDate} (in {request.ExpirationDate.Subtract(AppDateTime.UtcNow).Minutes} minutes).");
- return request;
- }
-
- public async Task<bool> FullFillRequestAsync(Guid id, string newPassword, CancellationToken cancellationToken = default) {
- var request = await GetRequestAsync(id, cancellationToken);
- if (request == default) {
- throw new ForgotPasswordRequestNotFoundException("Request with id: " + id + " was not found");
- }
-
- var user = _context.Users.SingleOrDefault(c => c.Id == request.User.Id);
- if (user == default) {
- throw new UserNotFoundException("User with id: " + request.User.Id + " was not found");
- }
-
- user.HashAndSetPassword(newPassword);
- _context.Users.Update(user);
- await _context.SaveChangesAsync(cancellationToken);
- _logger.LogInformation($"Fullfilled password reset request for user: {request.User.Username}");
- await DeleteRequestsForUserAsync(user.Id, cancellationToken);
- return true;
- }
-
-
- public async Task AddRequestAsync(User user, TimeZoneInfo requestTz, CancellationToken cancellationToken = default) {
- await DeleteRequestsForUserAsync(user.Id, cancellationToken);
- var request = new ForgotPasswordRequest(user);
- _context.ForgotPasswordRequests.Add(request);
- await _context.SaveChangesAsync(cancellationToken);
- var portalUrl = _configuration.PORTAL_URL;
- var emailFromAddress = _configuration.EMAIL_FROM_ADDRESS;
- var emailFromDisplayName = _configuration.EMAIL_FROM_DISPLAY_NAME;
- var zonedExpirationDate = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(request.ExpirationDate, requestTz.Id);
- var message = new MailMessage {
- From = new MailAddress(emailFromAddress, emailFromDisplayName),
- To = {
- new MailAddress(user.Username)
- },
- Subject = "Reset password - Greatoffice",
- Body = @$"
-Hi {user.Username}
-
-Go to the following link to set a new password.
-
-{portalUrl}/reset-password/{request.Id}
-
-The link expires at {zonedExpirationDate:yyyy-MM-dd hh:mm}.
-If you did not request a password reset, no action is required.
-"
- };
-
-#pragma warning disable 4014
- Task.Run(() => {
-#pragma warning restore 4014
- _mailService.SendMail(message);
- _logger.LogInformation($"Added password reset request for user: {request.User.Username}, expires in {request.ExpirationDate.Subtract(AppDateTime.UtcNow)}.");
- },
- cancellationToken);
- }
-
- public async Task DeleteRequestsForUserAsync(Guid userId, CancellationToken cancellationToken = default) {
- var requestsToRemove = _context.ForgotPasswordRequests.Where(c => c.UserId == userId).ToList();
- if (!requestsToRemove.Any()) return;
- _context.ForgotPasswordRequests.RemoveRange(requestsToRemove);
- await _context.SaveChangesAsync(cancellationToken);
- _logger.LogInformation($"Deleted {requestsToRemove.Count} password reset requests for user: {userId}.");
- }
-
-
- public async Task DeleteStaleRequestsAsync(CancellationToken cancellationToken = default) {
- var deleteCount = 0;
- foreach (var request in _context.ForgotPasswordRequests.Where(c => c.IsExpired)) {
- if (!request.IsExpired) {
- continue;
- }
-
- _context.ForgotPasswordRequests.Remove(request);
- deleteCount++;
- _logger.LogInformation($"Marking password reset request with id: {request.Id} for deletion, expiration date was {request.ExpirationDate}.");
- }
-
- await _context.SaveChangesAsync(cancellationToken);
- _logger.LogInformation($"Deleted {deleteCount} stale password reset requests.");
- }
-} \ No newline at end of file
diff --git a/server/src/Services/UserService.cs b/server/src/Services/UserService.cs
deleted file mode 100644
index 6db663a..0000000
--- a/server/src/Services/UserService.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-namespace IOL.GreatOffice.Api.Services;
-
-public class UserService
-{
- private readonly PasswordResetService _passwordResetService;
-
- /// <summary>
- /// Provides methods to perform common operations on user data.
- /// </summary>
- /// <param name="passwordResetService"></param>
- public UserService(PasswordResetService passwordResetService) {
- _passwordResetService = passwordResetService;
- }
-
- /// <summary>
- /// Log in a user.
- /// </summary>
- /// <param name="httpContext"></param>
- /// <param name="user"></param>
- /// <param name="persist"></param>
- public async Task LogInUser(HttpContext httpContext, User user, bool persist = false) {
- var claims = new List<Claim> {
- new(AppClaims.USER_ID, user.Id.ToString()),
- new(AppClaims.NAME, user.Username),
- };
-
- var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
- var principal = new ClaimsPrincipal(identity);
- var authenticationProperties = new AuthenticationProperties {
- AllowRefresh = true,
- IssuedUtc = DateTimeOffset.UtcNow,
- };
-
- if (persist) {
- authenticationProperties.ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(6);
- authenticationProperties.IsPersistent = true;
- }
-
- await httpContext.SignInAsync(principal, authenticationProperties);
- await _passwordResetService.DeleteRequestsForUserAsync(user.Id);
- }
-
- /// <summary>
- /// Log out a user.
- /// </summary>
- /// <param name="httpContext"></param>
- public async Task LogOutUser(HttpContext httpContext) {
- await httpContext.SignOutAsync();
- }
-}
diff --git a/server/src/Services/VaultService.cs b/server/src/Services/VaultService.cs
deleted file mode 100644
index 732911a..0000000
--- a/server/src/Services/VaultService.cs
+++ /dev/null
@@ -1,158 +0,0 @@
-using Microsoft.Extensions.Caching.Memory;
-
-namespace IOL.GreatOffice.Api.Services;
-
-public class VaultService
-{
- private readonly HttpClient _client;
- private readonly IMemoryCache _cache;
- private readonly IConfiguration _configuration;
- private readonly ILogger<VaultService> _logger;
- private int CACHE_TTL { get; set; }
-
- public VaultService(HttpClient client, IConfiguration configuration, IMemoryCache cache, ILogger<VaultService> logger) {
- var token = configuration.GetValue<string>(AppEnvironmentVariables.VAULT_TOKEN);
- var vaultUrl = configuration.GetValue<string>(AppEnvironmentVariables.VAULT_URL);
- CACHE_TTL = configuration.GetValue(AppEnvironmentVariables.VAULT_CACHE_TTL, 60 * 60 * 12);
- if (token.IsNullOrWhiteSpace()) throw new ApplicationException("VAULT_TOKEN is empty");
- if (vaultUrl.IsNullOrWhiteSpace()) throw new ApplicationException("VAULT_URL is empty");
- client.DefaultRequestHeaders.Add("X-Vault-Token", token);
- client.BaseAddress = new Uri(vaultUrl);
- _client = client;
- _cache = cache;
- _configuration = configuration;
- _logger = logger;
- }
-
- public static object Data { get; set; }
-
- public T Get<T>(string path) {
- var result = _cache.GetOrCreate(AppConstants.VAULT_CACHE_KEY,
- cacheEntry => {
- cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(CACHE_TTL);
- var getSecretResponse = _client.GetFromJsonAsync<GetSecretResponse<T>>("/v1/kv/data/" + path).Result;
-
- if (getSecretResponse == null) {
- return default;
- }
-
- Log.Debug("Setting new Vault cache, "
- + new {
- PATH = path,
- CACHE_TTL,
- Data = JsonSerializer.Serialize(getSecretResponse.Data.Data)
- });
- return getSecretResponse.Data.Data ?? default;
- });
- return result;
- }
-
- public T Refresh<T>(string path) {
- _cache.Remove(AppConstants.VAULT_CACHE_KEY);
- CACHE_TTL = _configuration.GetValue(AppEnvironmentVariables.VAULT_CACHE_TTL, 60 * 60 * 12);
- return Get<T>(path);
- }
-
- public async Task<RenewTokenResponse> RenewTokenAsync<T>(string token) {
- var response = await _client.PostAsJsonAsync("v1/auth/token/renew",
- new {
- Token = token
- });
- if (response.IsSuccessStatusCode) {
- return await response.Content.ReadFromJsonAsync<RenewTokenResponse>();
- }
-
- return default;
- }
-
- public AppConfiguration GetCurrentAppConfiguration() {
- var path = _configuration.GetValue<string>(AppEnvironmentVariables.MAIN_CONFIG_SHEET);
- var result = Get<AppConfiguration>(path);
- var overwrites = new {
- DB_HOST = _configuration.GetValue("OVERWRITE_DB_HOST", string.Empty),
- DB_PORT = _configuration.GetValue("OVERWRITE_DB_PORT", string.Empty),
- DB_USER = _configuration.GetValue("OVERWRITE_DB_USER", string.Empty),
- DB_PASSWORD = _configuration.GetValue("OVERWRITE_DB_PASSWORD", string.Empty),
- DB_NAME = _configuration.GetValue("OVERWRITE_DB_NAME", string.Empty),
- };
- if (overwrites.DB_HOST.HasValue()) {
- _logger.LogInformation("OVERWRITE_DB_HOST is specified, using it's value: " + overwrites.DB_HOST);
- result.DB_HOST = overwrites.DB_HOST;
- }
-
- if (overwrites.DB_PORT.HasValue()) {
- _logger.LogInformation("OVERWRITE_DB_PORT is specified, using it's value: " + overwrites.DB_PORT);
- result.DB_PORT = overwrites.DB_PORT;
- }
-
- if (overwrites.DB_USER.HasValue()) {
- _logger.LogInformation("OVERWRITE_DB_USER is specified, using it's value: " + overwrites.DB_USER);
- result.DB_USER = overwrites.DB_USER;
- }
-
- if (overwrites.DB_PASSWORD.HasValue()) {
- _logger.LogInformation("OVERWRITE_DB_PASSWORD is specified, using it's value: " + "(redacted)");
- result.DB_PASSWORD = overwrites.DB_PASSWORD;
- }
-
- if (overwrites.DB_NAME.HasValue()) {
- _logger.LogInformation("OVERWRITE_DB_NAME is specified, using it's value: " + overwrites.DB_NAME);
- result.DB_NAME = overwrites.DB_NAME;
- }
-
- return result;
- }
-
- public AppConfiguration RefreshCurrentAppConfiguration() {
- var path = _configuration.GetValue<string>(AppEnvironmentVariables.MAIN_CONFIG_SHEET);
- return Refresh<AppConfiguration>(path);
- }
-
- public class RenewTokenResponse
- {
- public Guid RequestId { get; set; }
- public string LeaseId { get; set; }
- public bool Renewable { get; set; }
- public long LeaseDuration { get; set; }
- public object Data { get; set; }
- public object WrapInfo { get; set; }
- public List<string> Warnings { get; set; }
- public Auth Auth { get; set; }
- }
-
- public class Auth
- {
- public string ClientToken { get; set; }
- public string Accessor { get; set; }
- public List<string> Policies { get; set; }
- public List<string> TokenPolicies { get; set; }
- public object Metadata { get; set; }
- public long LeaseDuration { get; set; }
- public bool Renewable { get; set; }
- public string EntityId { get; set; }
- public string TokenType { get; set; }
- public bool Orphan { get; set; }
- public object MfaRequirement { get; set; }
- public long NumUses { get; set; }
- }
-
- public class GetSecretResponse<T>
- {
- public VaultSecret<T> Data { get; set; }
- }
-
- public class VaultSecret<T>
- {
- public T Data { get; set; }
- public VaultSecretMetadata Metadata { get; set; }
- }
-
- public class VaultSecretMetadata
- {
- public DateTimeOffset CreatedTime { get; set; }
- public object CustomMetadata { get; set; }
- public string DeletionTime { get; set; }
- public bool Destroyed { get; set; }
- public long Version { get; set; }
- }
-}