From 64302286fb2b2e001a830c815e9d9b2e10504066 Mon Sep 17 00:00:00 2001 From: Aaron Po Date: Tue, 4 Aug 2026 06:18:54 -0400 Subject: [PATCH] update infra docs --- .../Rendering/EmailTemplateProvider.cs | 21 -------- .../Infrastructure.Email/IEmailProvider.cs | 14 ------ .../Infrastructure.Email/SmtpEmailProvider.cs | 50 ++----------------- .../ITokenInfrastructure.cs | 13 +---- .../Infrastructure.Jwt/JwtInfrastructure.cs | 16 ++---- .../Argon2Infrastructure.cs | 22 ++------ .../IPasswordInfrastructure.cs | 7 +-- .../DefaultSqlConnectionFactory.cs | 17 ++----- .../ISqlConnectionFactory.cs | 1 - .../Infrastructure.Sql/Repository.cs | 5 -- .../SqlConnectionStringHelper.cs | 6 +-- 11 files changed, 21 insertions(+), 151 deletions(-) diff --git a/web/backend/Infrastructure/Infrastructure.Email.Templates/Rendering/EmailTemplateProvider.cs b/web/backend/Infrastructure/Infrastructure.Email.Templates/Rendering/EmailTemplateProvider.cs index 3759ccb9..332fc582 100644 --- a/web/backend/Infrastructure/Infrastructure.Email.Templates/Rendering/EmailTemplateProvider.cs +++ b/web/backend/Infrastructure/Infrastructure.Email.Templates/Rendering/EmailTemplateProvider.cs @@ -9,20 +9,9 @@ namespace Infrastructure.Email.Templates.Rendering; /// /// Service for rendering Razor email templates to HTML using HtmlRenderer. /// -/// -/// The service provider used to resolve dependencies for the Razor component rendering -/// pipeline. -/// -/// The logger factory passed to the used to render components. public class EmailTemplateProvider(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) : IEmailTemplateProvider { - /// - /// Renders the UserRegisteredEmail template with the specified parameters. - /// - /// The username to include in the email - /// The email confirmation link - /// The rendered HTML string public async Task RenderUserRegisteredEmailAsync( string username, string confirmationLink @@ -37,12 +26,6 @@ public class EmailTemplateProvider(IServiceProvider serviceProvider, ILoggerFact return await RenderComponentAsync(parameters); } - /// - /// Renders the ResendConfirmation template with the specified parameters. - /// - /// The username to include in the email - /// The new confirmation link - /// The rendered HTML string public async Task RenderResendConfirmationEmailAsync( string username, string confirmationLink @@ -58,13 +41,9 @@ public class EmailTemplateProvider(IServiceProvider serviceProvider, ILoggerFact } /// - /// Generic method to render any Razor component to HTML. /// Creates a scoped , dispatches the render onto its renderer thread, /// and returns the resulting HTML string. /// - /// The type of the Razor component to render. - /// A dictionary of parameter names and values to pass to the component. - /// The rendered HTML string for the component. private async Task RenderComponentAsync( Dictionary parameters ) diff --git a/web/backend/Infrastructure/Infrastructure.Email/IEmailProvider.cs b/web/backend/Infrastructure/Infrastructure.Email/IEmailProvider.cs index bf466752..4bca5326 100644 --- a/web/backend/Infrastructure/Infrastructure.Email/IEmailProvider.cs +++ b/web/backend/Infrastructure/Infrastructure.Email/IEmailProvider.cs @@ -5,21 +5,7 @@ namespace Infrastructure.Email; /// public interface IEmailProvider { - /// - /// Sends an email to a single recipient. - /// - /// Recipient email address - /// Email subject line - /// Email body (HTML or plain text) - /// Whether the body is HTML (default: true) Task SendAsync(string to, string subject, string body, bool isHtml = true); - /// - /// Sends an email to multiple recipients. - /// - /// List of recipient email addresses - /// Email subject line - /// Email body (HTML or plain text) - /// Whether the body is HTML (default: true) Task SendAsync(IEnumerable to, string subject, string body, bool isHtml = true); } diff --git a/web/backend/Infrastructure/Infrastructure.Email/SmtpEmailProvider.cs b/web/backend/Infrastructure/Infrastructure.Email/SmtpEmailProvider.cs index 5b15f1a6..71b67b34 100644 --- a/web/backend/Infrastructure/Infrastructure.Email/SmtpEmailProvider.cs +++ b/web/backend/Infrastructure/Infrastructure.Email/SmtpEmailProvider.cs @@ -19,38 +19,10 @@ public class SmtpEmailProvider : IEmailProvider private readonly bool _useSsl; /// - /// Initializes a new instance of , reading SMTP configuration - /// from environment variables. + /// Initializes a new instance of the class, reading SMTP configuration + /// from environment variables (SMTP_HOST, SMTP_PORT, SMTP_USERNAME, + /// SMTP_PASSWORD, SMTP_USE_SSL, SMTP_FROM_EMAIL, SMTP_FROM_NAME). /// - /// - /// Reads the following environment variables: - /// - /// - /// SMTP_HOST (required) - the SMTP server hostname. - /// - /// - /// SMTP_PORT (optional, default "587") - the SMTP server port, must be a valid integer. - /// - /// - /// SMTP_USERNAME (optional) - the username used for authentication. - /// - /// - /// SMTP_PASSWORD (optional) - the password used for authentication. - /// - /// - /// SMTP_USE_SSL (optional, default "true") - whether to use StartTls when connecting. - /// - /// - /// SMTP_FROM_EMAIL (required) - the email address used as the sender. - /// - /// - /// - /// SMTP_FROM_NAME (optional, default "The Biergarten") - the display name used as the - /// sender. - /// - /// - /// - /// /// /// Thrown when SMTP_HOST or SMTP_FROM_EMAIL is not set, or when SMTP_PORT is not a valid integer. /// @@ -79,31 +51,17 @@ public class SmtpEmailProvider : IEmailProvider _fromName = Environment.GetEnvironmentVariable("SMTP_FROM_NAME") ?? "The Biergarten"; } - /// - /// Sends an email to a single recipient by delegating to the multi-recipient overload. - /// - /// Recipient email address - /// Email subject line - /// Email body (HTML or plain text) - /// Whether the body is HTML (default: true) - /// Thrown when connecting, authenticating, or sending via SMTP fails. public async Task SendAsync(string to, string subject, string body, bool isHtml = true) { await SendAsync([to], subject, body, isHtml); } /// - /// Sends an email to multiple recipients using MailKit's . /// Connects using StartTls when SSL is enabled (or no encryption otherwise), authenticates /// if credentials were configured, sends the message, and disconnects. /// - /// List of recipient email addresses - /// Email subject line - /// Email body (HTML or plain text) - /// Whether the body is HTML (default: true) /// - /// Thrown when connecting, authenticating, or sending via SMTP fails. The - /// original exception is included as the inner exception. + /// Thrown when connecting, authenticating, or sending via SMTP fails, wrapping the original exception. /// public async Task SendAsync( IEnumerable to, diff --git a/web/backend/Infrastructure/Infrastructure.Jwt/ITokenInfrastructure.cs b/web/backend/Infrastructure/Infrastructure.Jwt/ITokenInfrastructure.cs index c26ea328..0f6199d7 100644 --- a/web/backend/Infrastructure/Infrastructure.Jwt/ITokenInfrastructure.cs +++ b/web/backend/Infrastructure/Infrastructure.Jwt/ITokenInfrastructure.cs @@ -10,22 +10,11 @@ public interface ITokenInfrastructure /// /// Generates a signed JWT for the given user. /// - /// The unique identifier of the user the token is issued for. - /// The username of the user, included as a claim. - /// The date and time at which the token expires. - /// The symmetric secret used to sign the token. - /// The serialized, signed JWT string. string GenerateJwt(Guid userId, string username, DateTime expiry, string secret); /// /// Validates a JWT and returns the resulting claims principal. /// - /// The JWT string to validate. - /// The symmetric secret used to verify the token's signature. - /// A representing the validated token's claims. - /// - /// Thrown when the token is invalid, expired, or fails - /// validation. - /// + /// Thrown when the token is invalid, expired, or fails validation. Task ValidateJwtAsync(string token, string secret); } diff --git a/web/backend/Infrastructure/Infrastructure.Jwt/JwtInfrastructure.cs b/web/backend/Infrastructure/Infrastructure.Jwt/JwtInfrastructure.cs index f8707b34..7a9e0516 100644 --- a/web/backend/Infrastructure/Infrastructure.Jwt/JwtInfrastructure.cs +++ b/web/backend/Infrastructure/Infrastructure.Jwt/JwtInfrastructure.cs @@ -13,18 +13,13 @@ namespace Infrastructure.Jwt; public class JwtInfrastructure : ITokenInfrastructure { /// - /// Generates a signed JWT containing the user's ID, username, issued-at time, expiry time, - /// and a unique token identifier (JTI), signed using HMAC-SHA256 with the provided secret. + /// Generates a signed JWT, signed using HMAC-SHA256 with the provided secret. /// /// - /// Sets the following registered claims: sub (userId), unique_name (username), - /// iat (current UTC time), exp (expiry), and jti (a newly generated GUID). + /// Sets registered claims sub (userId), unique_name (username), iat (current UTC time), + /// exp (expiry), and jti (a newly generated GUID). /// - /// The unique identifier of the user the token is issued for. - /// The username of the user, included as a claim. - /// The date and time at which the token expires. /// The symmetric secret used to sign the token (encoded as UTF-8 bytes). - /// The serialized, signed JWT string. public string GenerateJwt(Guid userId, string username, DateTime expiry, string secret) { JsonWebTokenHandler handler = new(); @@ -61,12 +56,9 @@ public class JwtInfrastructure : ITokenInfrastructure /// Validates a JWT's signature and lifetime (issuer and audience validation are disabled), /// using the provided secret as the HMAC-SHA256 symmetric signing key. /// - /// The JWT string to validate. /// The symmetric secret used to verify the token's signature (encoded as UTF-8 bytes). - /// A wrapping the validated token's claims identity. /// - /// Thrown when the token is invalid, has no claims identity, is expired, or otherwise fails validation - /// (including when validation itself throws, e.g. due to a malformed token or signature mismatch). + /// Thrown when the token is invalid, has no claims identity, is expired, or otherwise fails validation. /// public async Task ValidateJwtAsync(string token, string secret) { diff --git a/web/backend/Infrastructure/Infrastructure.PasswordHashing/Argon2Infrastructure.cs b/web/backend/Infrastructure/Infrastructure.PasswordHashing/Argon2Infrastructure.cs index 9914745c..9331e293 100644 --- a/web/backend/Infrastructure/Infrastructure.PasswordHashing/Argon2Infrastructure.cs +++ b/web/backend/Infrastructure/Infrastructure.PasswordHashing/Argon2Infrastructure.cs @@ -15,15 +15,9 @@ public class Argon2Infrastructure : IPasswordInfrastructure private const int ArgonMemoryKb = 65536; // 64MB /// - /// Hashes a plaintext password using Argon2id with a newly generated 128-bit cryptographically - /// random salt, 4 iterations, 64MB of memory, and a degree of parallelism equal to the number of - /// available processors (minimum 1). + /// Hashes a plaintext password using Argon2id with a fresh random salt. /// - /// The plaintext password to hash. - /// - /// A string of the form "{base64Salt}:{base64Hash}" containing the salt and the resulting - /// 256-bit hash, suitable for storage and later verification. - /// + /// A string of the form "{base64Salt}:{base64Hash}", suitable for storage. public string Hash(string password) { byte[] salt = RandomNumberGenerator.GetBytes(SaltSize); @@ -40,18 +34,12 @@ public class Argon2Infrastructure : IPasswordInfrastructure } /// - /// Verifies a plaintext password against a stored salt/hash string by recomputing the Argon2id - /// hash with the extracted salt and comparing it to the stored hash using a fixed-time comparison + /// Verifies a plaintext password against a stored salt/hash string, using a fixed-time comparison /// to mitigate timing attacks. /// - /// The plaintext password to verify. - /// - /// The stored string of the form "{base64Salt}:{base64Hash}" previously produced by . - /// /// - /// true if the password matches the stored hash; false if it does not match, the stored - /// string is malformed (e.g. not in the expected two-part format, or not valid base64), or any other - /// error occurs while verifying. + /// false if the password doesn't match, if is malformed, or if any + /// other error occurs during verification. /// public bool Verify(string password, string stored) { diff --git a/web/backend/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfrastructure.cs b/web/backend/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfrastructure.cs index bb771238..50e13b6a 100644 --- a/web/backend/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfrastructure.cs +++ b/web/backend/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfrastructure.cs @@ -8,15 +8,10 @@ public interface IPasswordInfrastructure /// /// Hashes a plaintext password, generating a new random salt. /// - /// The plaintext password to hash. - /// A string encoding both the salt and the resulting hash, suitable for storage. public string Hash(string password); /// - /// Verifies a plaintext password against a previously stored hash. + /// Verifies a plaintext password against a previously stored hash produced by . /// - /// The plaintext password to verify. - /// The stored salt/hash string previously produced by . - /// true if the password matches the stored hash; otherwise false. public bool Verify(string password, string stored); } diff --git a/web/backend/Infrastructure/Infrastructure.Sql/DefaultSqlConnectionFactory.cs b/web/backend/Infrastructure/Infrastructure.Sql/DefaultSqlConnectionFactory.cs index 5ef7cc9d..ed59f78e 100644 --- a/web/backend/Infrastructure/Infrastructure.Sql/DefaultSqlConnectionFactory.cs +++ b/web/backend/Infrastructure/Infrastructure.Sql/DefaultSqlConnectionFactory.cs @@ -8,15 +8,11 @@ namespace Infrastructure.Sql; /// Default implementation that creates SQL Server connections, /// resolving the connection string from environment variables or application configuration. /// -/// The application configuration, used as a fallback source for the connection string. public class DefaultSqlConnectionFactory(IConfiguration configuration) : ISqlConnectionFactory { private readonly string _connectionString = GetConnectionString(configuration); - /// - /// Creates a new, unopened using the resolved connection string. - /// - /// A new instance. + /// public DbConnection CreateConnection() { return new SqlConnection(_connectionString); @@ -24,15 +20,10 @@ public class DefaultSqlConnectionFactory(IConfiguration configuration) : ISqlCon /// /// Resolves the SQL Server connection string, preferring (in order): the DB_CONNECTION_STRING - /// environment variable, a connection string built from individual DB_* environment variables - /// via , and finally the "Default" - /// connection string from . + /// environment variable, a connection string built from individual DB_* environment variables, + /// and finally the "Default" connection string from configuration. /// - /// The application configuration to fall back to. - /// The resolved SQL Server connection string. - /// - /// Thrown when no connection string can be resolved from any of the supported sources. - /// + /// Thrown when no connection string can be resolved from any source. private static string GetConnectionString(IConfiguration configuration) { // Check for full connection string first diff --git a/web/backend/Infrastructure/Infrastructure.Sql/ISqlConnectionFactory.cs b/web/backend/Infrastructure/Infrastructure.Sql/ISqlConnectionFactory.cs index 89976560..9561d9f5 100644 --- a/web/backend/Infrastructure/Infrastructure.Sql/ISqlConnectionFactory.cs +++ b/web/backend/Infrastructure/Infrastructure.Sql/ISqlConnectionFactory.cs @@ -10,6 +10,5 @@ public interface ISqlConnectionFactory /// /// Creates a new, unopened database connection. /// - /// A new instance. DbConnection CreateConnection(); } diff --git a/web/backend/Infrastructure/Infrastructure.Sql/Repository.cs b/web/backend/Infrastructure/Infrastructure.Sql/Repository.cs index b223cd12..85e56701 100644 --- a/web/backend/Infrastructure/Infrastructure.Sql/Repository.cs +++ b/web/backend/Infrastructure/Infrastructure.Sql/Repository.cs @@ -6,15 +6,12 @@ namespace Infrastructure.Sql; /// Base class for ADO.NET-based repositories, providing shared connection creation and /// entity-mapping infrastructure for derived repository implementations. /// -/// The entity type managed by the repository. -/// The factory used to create database connections. public abstract class Repository(ISqlConnectionFactory connectionFactory) where T : class { /// /// Creates and opens a new database connection using the configured . /// - /// An open ready for use. /// Thrown when the connection cannot be opened. protected async Task CreateConnection() { @@ -26,7 +23,5 @@ public abstract class Repository(ISqlConnectionFactory connectionFactory) /// /// Maps the current row of a data reader to an instance of . /// - /// The data reader positioned on the row to map. - /// The mapped entity instance. protected abstract T MapToEntity(DbDataReader reader); } diff --git a/web/backend/Infrastructure/Infrastructure.Sql/SqlConnectionStringHelper.cs b/web/backend/Infrastructure/Infrastructure.Sql/SqlConnectionStringHelper.cs index a5ecb395..ae78fb97 100644 --- a/web/backend/Infrastructure/Infrastructure.Sql/SqlConnectionStringHelper.cs +++ b/web/backend/Infrastructure/Infrastructure.Sql/SqlConnectionStringHelper.cs @@ -9,10 +9,9 @@ public static class SqlConnectionStringHelper { /// /// Builds a SQL Server connection string from environment variables. - /// Expects DB_SERVER, DB_NAME, DB_USER, DB_PASSWORD, and DB_TRUST_SERVER_CERTIFICATE. /// - /// Optional override for the database name. If null, uses DB_NAME env var. - /// A properly formatted SQL Server connection string. + /// Throws if DB_SERVER, DB_NAME, DB_USER, or DB_PASSWORD is unset. + /// If null, falls back to the DB_NAME environment variable. public static string BuildConnectionString(string? databaseName = null) { string server = @@ -48,7 +47,6 @@ public static class SqlConnectionStringHelper /// /// Builds a connection string to the master database using environment variables. /// - /// A connection string for the master database. public static string BuildMasterConnectionString() { return BuildConnectionString("master");