Replace raw environment variable reads with IConfiguration in backend

This commit is contained in:
Aaron Po
2026-08-22 20:26:13 -04:00
parent 9e9fc98d33
commit c514eb9814
17 changed files with 291 additions and 100 deletions

View File

@@ -7,6 +7,7 @@ using Features.Auth.Tests.TestSupport;
using FluentAssertions;
using Infrastructure.Jwt;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Moq;
namespace Features.Auth.Tests.Services;
@@ -22,21 +23,23 @@ public class TokenServiceRefreshTests
_tokenInfraMock = new Mock<ITokenInfrastructure>();
_userManagerMock = UserManagerMockFactory.Create();
// Set environment variables for tokens
Environment.SetEnvironmentVariable(
"ACCESS_TOKEN_SECRET",
"test-access-secret-that-is-very-long-1234567890"
);
Environment.SetEnvironmentVariable(
"REFRESH_TOKEN_SECRET",
"test-refresh-secret-that-is-very-long-1234567890"
);
Environment.SetEnvironmentVariable(
"CONFIRMATION_TOKEN_SECRET",
"test-confirmation-secret-that-is-very-long-1234567890"
);
IConfiguration configuration = new ConfigurationBuilder()
.AddInMemoryCollection(
new Dictionary<string, string?>
{
["ACCESS_TOKEN_SECRET"] = "test-access-secret-that-is-very-long-1234567890",
["REFRESH_TOKEN_SECRET"] = "test-refresh-secret-that-is-very-long-1234567890",
["CONFIRMATION_TOKEN_SECRET"] =
"test-confirmation-secret-that-is-very-long-1234567890",
}
)
.Build();
_tokenService = new TokenService(_tokenInfraMock.Object, _userManagerMock.Object);
_tokenService = new TokenService(
_tokenInfraMock.Object,
_userManagerMock.Object,
configuration
);
}
[Fact]

View File

@@ -5,6 +5,7 @@ using Features.Auth.Services;
using Features.Auth.Tests.TestSupport;
using FluentAssertions;
using Infrastructure.Jwt;
using Microsoft.Extensions.Configuration;
using Moq;
namespace Features.Auth.Tests.Services;
@@ -18,23 +19,22 @@ public class TokenServiceValidationTests
{
_tokenInfraMock = new Mock<ITokenInfrastructure>();
// Set environment variables for tokens
Environment.SetEnvironmentVariable(
"ACCESS_TOKEN_SECRET",
"test-access-secret-that-is-very-long-1234567890"
);
Environment.SetEnvironmentVariable(
"REFRESH_TOKEN_SECRET",
"test-refresh-secret-that-is-very-long-1234567890"
);
Environment.SetEnvironmentVariable(
"CONFIRMATION_TOKEN_SECRET",
"test-confirmation-secret-that-is-very-long-1234567890"
);
IConfiguration configuration = new ConfigurationBuilder()
.AddInMemoryCollection(
new Dictionary<string, string?>
{
["ACCESS_TOKEN_SECRET"] = "test-access-secret-that-is-very-long-1234567890",
["REFRESH_TOKEN_SECRET"] = "test-refresh-secret-that-is-very-long-1234567890",
["CONFIRMATION_TOKEN_SECRET"] =
"test-confirmation-secret-that-is-very-long-1234567890",
}
)
.Build();
_tokenService = new TokenService(
_tokenInfraMock.Object,
UserManagerMockFactory.Create().Object
UserManagerMockFactory.Create().Object,
configuration
);
}

View File

@@ -4,12 +4,13 @@ using Domain.Exceptions;
using Features.Auth.Identity;
using Infrastructure.Jwt;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
namespace Features.Auth.Services;
/// <summary>
/// Default implementation of <see cref="ITokenService" /> that generates and validates JWTs
/// for access, refresh, and confirmation flows using secrets read from environment variables.
/// for access, refresh, and confirmation flows using secrets read from configuration.
/// </summary>
public class TokenService : ITokenService
{
@@ -22,30 +23,31 @@ public class TokenService : ITokenService
/// <summary>Initializes a new instance of the <see cref="TokenService" /> class.</summary>
/// <exception cref="InvalidOperationException">
/// Thrown when any of the <c>ACCESS_TOKEN_SECRET</c>, <c>REFRESH_TOKEN_SECRET</c>, or
/// <c>CONFIRMATION_TOKEN_SECRET</c> environment variables are not set.
/// <c>CONFIRMATION_TOKEN_SECRET</c> configuration values are not set.
/// </exception>
public TokenService(
ITokenInfrastructure tokenInfrastructure,
UserManager<ApplicationUser> userManager
UserManager<ApplicationUser> userManager,
IConfiguration configuration
)
{
_tokenInfrastructure = tokenInfrastructure;
_userManager = userManager;
_accessTokenSecret =
Environment.GetEnvironmentVariable("ACCESS_TOKEN_SECRET")
configuration["ACCESS_TOKEN_SECRET"]
?? throw new InvalidOperationException(
"ACCESS_TOKEN_SECRET environment variable is not set"
);
_refreshTokenSecret =
Environment.GetEnvironmentVariable("REFRESH_TOKEN_SECRET")
configuration["REFRESH_TOKEN_SECRET"]
?? throw new InvalidOperationException(
"REFRESH_TOKEN_SECRET environment variable is not set"
);
_confirmationTokenSecret =
Environment.GetEnvironmentVariable("CONFIRMATION_TOKEN_SECRET")
configuration["CONFIRMATION_TOKEN_SECRET"]
?? throw new InvalidOperationException(
"CONFIRMATION_TOKEN_SECRET environment variable is not set"
);

View File

@@ -6,6 +6,13 @@
<RootNamespace>Features.Emails</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference
Include="Microsoft.Extensions.Configuration.Abstractions"
Version="10.0.1"
/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Infrastructure\Infrastructure.Email\Infrastructure.Email.csproj" />
<ProjectReference Include="..\..\Infrastructure\Infrastructure.Email.Templates\Infrastructure.Email.Templates.csproj" />

View File

@@ -1,5 +1,6 @@
using Infrastructure.Email;
using Infrastructure.Email.Templates.Rendering;
using Microsoft.Extensions.Configuration;
namespace Features.Emails.Services;
@@ -8,18 +9,19 @@ namespace Features.Emails.Services;
/// </summary>
public class EmailDispatcher(
IEmailProvider emailProvider,
IEmailTemplateProvider emailTemplateProvider
IEmailTemplateProvider emailTemplateProvider,
IConfiguration configuration
) : IEmailDispatcher
{
/// <summary>
/// The base URL of the website, used to build confirmation links. Read from the
/// <c>WEBSITE_BASE_URL</c> environment variable.
/// <c>WEBSITE_BASE_URL</c> configuration value.
/// </summary>
/// <exception cref="InvalidOperationException">
/// Thrown at type initialization time when the <c>WEBSITE_BASE_URL</c> environment variable is not set.
/// Thrown when the <c>WEBSITE_BASE_URL</c> configuration value is not set.
/// </exception>
private static readonly string WebsiteBaseUrl =
Environment.GetEnvironmentVariable("WEBSITE_BASE_URL")
private string WebsiteBaseUrl =>
configuration["WEBSITE_BASE_URL"]
?? throw new InvalidOperationException("WEBSITE_BASE_URL environment variable is not set");
/// <inheritdoc />