aboutsummaryrefslogtreecommitdiff
path: root/VNLib.Plugins.Essentials.Accounts.Registration/src/EmailSystemConfig.cs
diff options
context:
space:
mode:
Diffstat (limited to 'VNLib.Plugins.Essentials.Accounts.Registration/src/EmailSystemConfig.cs')
-rw-r--r--VNLib.Plugins.Essentials.Accounts.Registration/src/EmailSystemConfig.cs126
1 files changed, 126 insertions, 0 deletions
diff --git a/VNLib.Plugins.Essentials.Accounts.Registration/src/EmailSystemConfig.cs b/VNLib.Plugins.Essentials.Accounts.Registration/src/EmailSystemConfig.cs
new file mode 100644
index 0000000..a0333c0
--- /dev/null
+++ b/VNLib.Plugins.Essentials.Accounts.Registration/src/EmailSystemConfig.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Text;
+using System.Text.Json;
+
+using RestSharp;
+
+using Emails.Transactional.Client;
+
+using VNLib.Utils.Extensions;
+using VNLib.Net.Rest.Client;
+using VNLib.Net.Rest.Client.OAuth2;
+using VNLib.Plugins.Extensions.Loading;
+
+namespace VNLib.Plugins.Essentials.Accounts.Registration
+{
+ /// <summary>
+ /// An extended <see cref="TransactionalEmailConfig"/> configuration
+ /// object that contains a <see cref="Net.Rest.Client.RestClientPool"/> pool for making
+ /// transactions
+ /// </summary>
+ internal sealed class EmailSystemConfig : TransactionalEmailConfig
+ {
+ public const string REG_TEMPLATE_NAME = "Registration";
+
+ public EmailSystemConfig(PluginBase pbase)
+ {
+ IReadOnlyDictionary<string, JsonElement> conf = pbase.GetConfig("email");
+ EmailFromName = conf["from_name"].GetString() ?? throw new KeyNotFoundException("");
+ EmailFromAddress = conf["from_address"].GetString() ?? throw new KeyNotFoundException("");
+ Uri baseServerPath = new(conf["base_url"].GetString()!, UriKind.RelativeOrAbsolute);
+ Uri tokenServerBase = new(conf["token_server_url"].GetString()!, UriKind.RelativeOrAbsolute);
+ Uri transactionEndpoint = new(conf["transaction_path"].GetString()!, UriKind.RelativeOrAbsolute);
+ //Load templates
+ Dictionary<string, string> templates = conf["templates"].EnumerateObject().ToDictionary(jp => jp.Name, jp => jp.Value.GetString()!);
+ //Init base config
+ WithTemplates(templates)
+ .WithUrl(transactionEndpoint);
+ //Load credentials
+ string authEndpoint = conf["token_path"].GetString() ?? throw new KeyNotFoundException();
+ int maxClients = conf["max_clients"].GetInt32();
+
+
+ //Load oauth secrets from vault
+ Task<string?> oauth2ClientID = pbase.TryGetSecretAsync("oauth2_client_id");
+ Task<string?> oauth2Password = pbase.TryGetSecretAsync("oauth2_client_secret");
+
+ //Lazy cred loaded, tasks should be loaded before this method will ever get called
+ Credential lazyCredentialGet()
+ {
+ //Load the results
+ string cliendId = oauth2ClientID.Result ?? throw new KeyNotFoundException("Missing required oauth2 client id");
+ string password = oauth2Password.Result ?? throw new KeyNotFoundException("Missing required oauth2 client secret");
+
+ return Credential.Create(cliendId, password);
+ }
+
+
+ //Init client creation options
+ RestClientOptions poolOptions = new()
+ {
+ AllowMultipleDefaultParametersWithSameName = true,
+ AutomaticDecompression = System.Net.DecompressionMethods.All,
+ PreAuthenticate = true,
+ Encoding = Encoding.UTF8,
+ MaxTimeout = conf["request_timeout_ms"].GetInt32(),
+ UserAgent = "Essentials.EmailRegistation",
+ FollowRedirects = false,
+ BaseUrl = baseServerPath
+ };
+ //Options for auth token endpoint
+ RestClientOptions oAuth2ClientOptions = new()
+ {
+ AllowMultipleDefaultParametersWithSameName = true,
+ AutomaticDecompression = System.Net.DecompressionMethods.All,
+ PreAuthenticate = false,
+ Encoding = Encoding.UTF8,
+ MaxTimeout = conf["request_timeout_ms"].GetInt32(),
+ UserAgent = "Essentials.EmailRegistation",
+ FollowRedirects = false,
+ BaseUrl = baseServerPath
+ };
+
+ //Init Oauth authenticator
+ OAuth2Authenticator authenticator = new(oAuth2ClientOptions, lazyCredentialGet, authEndpoint);
+ //Store pool
+ RestClientPool = new(maxClients, poolOptions, authenticator:authenticator);
+
+ void Cleanup()
+ {
+ authenticator.Dispose();
+ RestClientPool.Dispose();
+ }
+
+ //register password cleanup
+ _ = pbase.UnloadToken.RegisterUnobserved(Cleanup);
+ }
+
+ /// <summary>
+ /// A shared <see cref="Net.Rest.Client.RestClientPool"/> for renting configuraed
+ /// <see cref="RestClient"/>
+ /// </summary>
+ public RestClientPool RestClientPool { get; }
+ /// <summary>
+ /// A global from email address name
+ /// </summary>
+ public string EmailFromName { get; }
+ /// <summary>
+ /// A global from email address
+ /// </summary>
+ public string EmailFromAddress { get; }
+
+ /// <summary>
+ /// Prepares a new registration email transaction request
+ /// </summary>
+ /// <returns>The prepared <see cref="EmailTransactionRequest"/> object</returns>
+ public EmailTransactionRequest GetRegistrationMessage()
+ {
+ EmailTransactionRequest req = GetTemplateRequest(REG_TEMPLATE_NAME);
+ req.FromAddress = EmailFromAddress;
+ req.FromName = EmailFromName;
+ //set reg subject
+ req.Subject = "One more step to register";
+ return req;
+ }
+ }
+} \ No newline at end of file