aboutsummaryrefslogtreecommitdiffstats
path: root/code/api/src/Services
diff options
context:
space:
mode:
Diffstat (limited to 'code/api/src/Services')
-rw-r--r--code/api/src/Services/EmailValidationService.cs27
-rw-r--r--code/api/src/Services/MailService.cs41
-rw-r--r--code/api/src/Services/PasswordResetService.cs5
-rw-r--r--code/api/src/Services/VaultService.cs219
4 files changed, 44 insertions, 248 deletions
diff --git a/code/api/src/Services/EmailValidationService.cs b/code/api/src/Services/EmailValidationService.cs
index c7be20a..5d909f3 100644
--- a/code/api/src/Services/EmailValidationService.cs
+++ b/code/api/src/Services/EmailValidationService.cs
@@ -8,29 +8,33 @@ public class EmailValidationService
private readonly ILogger<EmailValidationService> _logger;
private readonly string EmailValidationUrl;
- public EmailValidationService(IStringLocalizer<SharedResources> localizer, MainAppDatabase database, MailService mailService, ILogger<EmailValidationService> logger, VaultService vaultService) {
+ public EmailValidationService(IStringLocalizer<SharedResources> localizer, MainAppDatabase database, MailService mailService, ILogger<EmailValidationService> logger)
+ {
_localizer = localizer;
_database = database;
_mailService = mailService;
_logger = logger;
- var configuration = vaultService.GetCurrentAppConfiguration();
- EmailValidationUrl = configuration.CANONICAL_BACKEND_URL + "/_/validate";
+ EmailValidationUrl = Program.AppConfiguration.CANONICAL_BACKEND_URL + "/_/validate";
}
- public bool FulfillEmailValidationRequest(Guid id, Guid userId) {
+ public bool FulfillEmailValidationRequest(Guid id, Guid userId)
+ {
var item = _database.ValidationEmails.FirstOrDefault(c => c.Id == id);
- if (item == default) {
+ if (item == default)
+ {
_logger.LogDebug("Did not find email validation request with id: {requestId}", id);
return false;
}
- if (item.UserId != userId) {
+ if (item.UserId != userId)
+ {
_logger.LogInformation("An unknown user tried to validate the email validation request {requestId}", id);
return false;
}
var user = _database.Users.FirstOrDefault(c => c.Id == item.UserId);
- if (user == default) {
+ if (user == default)
+ {
_database.ValidationEmails.Remove(item);
_database.SaveChanges();
_logger.LogInformation("Deleting request {requestId} because user does not exist anymore", id);
@@ -45,12 +49,15 @@ public class EmailValidationService
return true;
}
- public async Task SendValidationEmailAsync(User user) {
- var queueItem = new ValidationEmail() {
+ public async Task SendValidationEmailAsync(User user)
+ {
+ var queueItem = new ValidationEmail()
+ {
UserId = user.Id,
Id = Guid.NewGuid()
};
- var email = new MailService.PostmarkEmail() {
+ var email = new MailService.PostmarkEmail()
+ {
To = user.Username,
Subject = _localizer["Greatoffice Email Validation"],
TextBody = _localizer["""
diff --git a/code/api/src/Services/MailService.cs b/code/api/src/Services/MailService.cs
index a6f7db4..4cc5288 100644
--- a/code/api/src/Services/MailService.cs
+++ b/code/api/src/Services/MailService.cs
@@ -6,11 +6,11 @@ public class MailService
private static string _fromEmail;
private readonly HttpClient _httpClient;
- public MailService(VaultService vaultService, ILogger<MailService> logger, HttpClient httpClient) {
- var configuration = vaultService.GetCurrentAppConfiguration();
- _fromEmail = configuration.EMAIL_FROM_ADDRESS;
+ public MailService(ILogger<MailService> logger, HttpClient httpClient)
+ {
+ _fromEmail = Program.AppConfiguration.EMAIL_FROM_ADDRESS;
_logger = logger;
- httpClient.DefaultRequestHeaders.Add("X-Postmark-Server-Token", configuration.POSTMARK_TOKEN);
+ httpClient.DefaultRequestHeaders.Add("X-Postmark-Server-Token", Program.AppConfiguration.POSTMARK_TOKEN);
_httpClient = httpClient;
}
@@ -19,35 +19,46 @@ public class MailService
/// </summary>
/// <param name="message"></param>
/// <exception cref="ArgumentException"></exception>
- public async Task SendMailAsync(PostmarkEmail message) {
- try {
- if (message.MessageStream.IsNullOrWhiteSpace()) {
+ public async Task SendMailAsync(PostmarkEmail message)
+ {
+ try
+ {
+ if (message.MessageStream.IsNullOrWhiteSpace())
+ {
message.MessageStream = "outbound";
}
- if (message.From.IsNullOrWhiteSpace() && _fromEmail.HasValue()) {
+ if (message.From.IsNullOrWhiteSpace() && _fromEmail.HasValue())
+ {
message.From = _fromEmail;
- } else {
+ }
+ else
+ {
throw new ApplicationException("Not one from-email is available");
}
- if (message.To.IsNullOrWhiteSpace()) {
+ if (message.To.IsNullOrWhiteSpace())
+ {
throw new ArgumentNullException(nameof(message.To), "A recipient should be specified.");
}
- if (!message.To.IsValidEmailAddress()) {
+ if (!message.To.IsValidEmailAddress())
+ {
throw new ArgumentException(nameof(message.To), "To is not a valid email address");
}
- if (message.HtmlBody.IsNullOrWhiteSpace() && message.TextBody.IsNullOrWhiteSpace()) {
+ if (message.HtmlBody.IsNullOrWhiteSpace() && message.TextBody.IsNullOrWhiteSpace())
+ {
throw new ArgumentNullException(nameof(message), "Both HtmlBody and TextBody is empty, nothing to send");
}
#if DEBUG
- _logger.LogInformation("Sending email: {0}", JsonSerializer.Serialize(message, new JsonSerializerOptions() {WriteIndented = true}));
+ _logger.LogInformation("Sending email: {0}", JsonSerializer.Serialize(message, new JsonSerializerOptions() { WriteIndented = true }));
#endif
var response = await _httpClient.PostAsJsonAsync("https://api.postmarkapp.com/email", message);
_logger.LogInformation("Postmark returned with message: {0}", (await response.Content.ReadFromJsonAsync<PostmarkSendResponse>()).Message);
- } catch (Exception e) {
+ }
+ catch (Exception e)
+ {
_logger.LogError(e, "A silent exception occured while trying to send an email");
}
}
@@ -60,7 +71,7 @@ public class MailService
public Guid MessageID { get; set; }
/// <summary>
- /// The message from the API.
+ /// The message from the API.
/// In the event of an error, this message may contain helpful text.
/// </summary>
public string Message { get; set; }
diff --git a/code/api/src/Services/PasswordResetService.cs b/code/api/src/Services/PasswordResetService.cs
index d4aeb0d..7f70ad1 100644
--- a/code/api/src/Services/PasswordResetService.cs
+++ b/code/api/src/Services/PasswordResetService.cs
@@ -4,18 +4,15 @@ public class PasswordResetService
{
private readonly MainAppDatabase _database;
private readonly MailService _mailService;
- private readonly AppConfiguration _configuration;
private readonly ILogger<PasswordResetService> _logger;
private readonly IStringLocalizer<SharedResources> _localizer;
public PasswordResetService(
MainAppDatabase database,
- VaultService vaultService,
ILogger<PasswordResetService> logger,
MailService mailService, IStringLocalizer<SharedResources> localizer)
{
_database = database;
- _configuration = vaultService.GetCurrentAppConfiguration();
_logger = logger;
_mailService = mailService;
_localizer = localizer;
@@ -69,7 +66,7 @@ Go to the following link to set a new password.
The link expires at {3}.
If you did not request a password reset, no action is required.
-""", user.DisplayName(true), _configuration.CANONICAL_FRONTEND_URL, request.Id, zonedExpirationDate.ToString("yyyy-MM-dd hh:mm")]
+""", user.DisplayName(true), Program.AppConfiguration.CANONICAL_FRONTEND_URL, request.Id, zonedExpirationDate.ToString("yyyy-MM-dd hh:mm")]
};
await Task.Run(() =>
diff --git a/code/api/src/Services/VaultService.cs b/code/api/src/Services/VaultService.cs
deleted file mode 100644
index 3290e30..0000000
--- a/code/api/src/Services/VaultService.cs
+++ /dev/null
@@ -1,219 +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 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;
- }
-
- public async Task<T> GetSecretJsonAsync<T>(string path) {
- var result = await _cache.GetOrCreate(AppConstants.VAULT_CACHE_KEY,
- async cacheEntry => {
- cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(CACHE_TTL);
- var getSecretResponse = await _client.GetFromJsonAsync<GetSecretResponse<T>>("/v1/kv/data/" + path);
- 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 Task<T> RefreshAsync<T>(string path) {
- _cache.Remove(AppConstants.VAULT_CACHE_KEY);
- CACHE_TTL = _configuration.GetValue(AppEnvironmentVariables.VAULT_CACHE_TTL, 60 * 60 * 12);
- return GetSecretJsonAsync<T>(path);
- }
-
- public async Task<RenewTokenResponse> RenewTokenAsync() {
- var response = await _client.PostAsJsonAsync("v1/auth/token/renew-self", new {increment = "2h"});
- if (response.IsSuccessStatusCode) {
- return await response.Content.ReadFromJsonAsync<RenewTokenResponse>();
- }
-
- return default;
- }
-
- public async Task<TokenLookupResponse> LookupTokenAsync() {
- var response = await _client.GetAsync("v1/auth/token/lookup-self");
- if (response.IsSuccessStatusCode) {
- return await response.Content.ReadFromJsonAsync<TokenLookupResponse>();
- }
-
- return default;
- }
-
- public AppConfiguration GetCurrentAppConfiguration() {
-#if DEBUG
- if (_configuration.GetValue<bool>(AppEnvironmentVariables.FLIGHT_MODE)) {
- var text = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), _configuration.GetValue(AppEnvironmentVariables.FLIGHT_MODE_JSON, "flightmode.json")));
- return JsonSerializer.Deserialize<AppConfiguration>(text);
- }
-#endif
-
- return GetSecretJsonAsync<AppConfiguration>(
- _configuration.GetValue<string>(AppEnvironmentVariables.MAIN_CONFIG_SHEET)
- ).Result;
- }
-
- public async Task RefreshCurrentAppConfigurationAsync() {
- await RefreshAsync<AppConfiguration>(_configuration.GetValue<string>(AppEnvironmentVariables.MAIN_CONFIG_SHEET));
- }
-
- 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; }
- }
-
- public class TokenLookupResponse
- {
- [JsonPropertyName("request_id")]
- public Guid RequestId { get; set; }
-
- [JsonPropertyName("lease_id")]
- public string LeaseId { get; set; }
-
- [JsonPropertyName("renewable")]
- public bool Renewable { get; set; }
-
- [JsonPropertyName("lease_duration")]
- public long LeaseDuration { get; set; }
-
- [JsonPropertyName("data")]
- public TokenLookupResponseData Data { get; set; }
-
- [JsonPropertyName("wrap_info")]
- public object WrapInfo { get; set; }
-
- [JsonPropertyName("warnings")]
- public object Warnings { get; set; }
-
- [JsonPropertyName("auth")]
- public object Auth { get; set; }
- }
-
- public class TokenLookupResponseData
- {
- [JsonPropertyName("accessor")]
- public string Accessor { get; set; }
-
- [JsonPropertyName("creation_time")]
- public long CreationTime { get; set; }
-
- [JsonPropertyName("creation_ttl")]
- public long CreationTtl { get; set; }
-
- [JsonPropertyName("display_name")]
- public string DisplayName { get; set; }
-
- [JsonPropertyName("entity_id")]
- public string EntityId { get; set; }
-
- [JsonPropertyName("expire_time")]
- public DateTimeOffset ExpireTime { get; set; }
-
- [JsonPropertyName("explicit_max_ttl")]
- public long ExplicitMaxTtl { get; set; }
-
- [JsonPropertyName("id")]
- public string Id { get; set; }
-
- [JsonPropertyName("issue_time")]
- public DateTimeOffset IssueTime { get; set; }
-
- [JsonPropertyName("last_renewal")]
- public DateTimeOffset LastRenewal { get; set; }
-
- [JsonPropertyName("last_renewal_time")]
- public long LastRenewalTime { get; set; }
-
- [JsonPropertyName("meta")]
- public object Meta { get; set; }
-
- [JsonPropertyName("num_uses")]
- public long NumUses { get; set; }
-
- [JsonPropertyName("orphan")]
- public bool Orphan { get; set; }
-
- [JsonPropertyName("path")]
- public string Path { get; set; }
-
- [JsonPropertyName("policies")]
- public List<string> Policies { get; set; }
-
- [JsonPropertyName("renewable")]
- public bool Renewable { get; set; }
-
- [JsonPropertyName("ttl")]
- public long Ttl { get; set; }
-
- [JsonPropertyName("type")]
- public string Type { get; set; }
- }
-} \ No newline at end of file