mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-01-01 02:29:32 -05:00
124 lines
4.7 KiB
C#
124 lines
4.7 KiB
C#
//-----------------------------------------------------------------------
|
|
// <copyright file="PostgresqlDbContextFactory.cs" company="aliasvault">
|
|
// Copyright (c) aliasvault. All rights reserved.
|
|
// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information.
|
|
// </copyright>
|
|
//-----------------------------------------------------------------------
|
|
|
|
namespace AliasServerDb;
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Npgsql;
|
|
|
|
/// <summary>
|
|
/// The PostgreSQL DbContext factory.
|
|
/// </summary>
|
|
public class PostgresqlDbContextFactory : IAliasServerDbContextFactory
|
|
{
|
|
private readonly IConfiguration _configuration;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="PostgresqlDbContextFactory"/> class.
|
|
/// </summary>
|
|
/// <param name="configuration">The configuration.</param>
|
|
public PostgresqlDbContextFactory(IConfiguration configuration)
|
|
{
|
|
_configuration = configuration;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public AliasServerDbContext CreateDbContext()
|
|
{
|
|
var optionsBuilder = new DbContextOptionsBuilder<AliasServerDbContext>();
|
|
ConfigureDbContextOptions(optionsBuilder);
|
|
|
|
return new AliasServerDbContext(optionsBuilder.Options);
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public Task<AliasServerDbContext> CreateDbContextAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
return Task.FromResult(CreateDbContext());
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public void ConfigureDbContextOptions(DbContextOptionsBuilder optionsBuilder)
|
|
{
|
|
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
|
|
|
// Check environment variable first.
|
|
var connectionString = Environment.GetEnvironmentVariable("ConnectionStrings__AliasServerDbContext");
|
|
|
|
// If no environment variable, fall back to configuration.
|
|
if (string.IsNullOrEmpty(connectionString))
|
|
{
|
|
connectionString = _configuration.GetConnectionString("AliasServerDbContext");
|
|
}
|
|
|
|
// If running in container override the connection string with the one from the secret file
|
|
if (IsRunningInContainer())
|
|
{
|
|
try
|
|
{
|
|
// Parse the existing connection string
|
|
var builder = new NpgsqlConnectionStringBuilder();
|
|
|
|
// Check for environment variables first, fall back to defaults if not set
|
|
builder.Host = Environment.GetEnvironmentVariable("POSTGRES_HOST") ?? "postgres";
|
|
builder.Database = Environment.GetEnvironmentVariable("POSTGRES_DATABASE") ?? "aliasvault";
|
|
builder.Username = Environment.GetEnvironmentVariable("POSTGRES_USER") ?? "aliasvault";
|
|
|
|
var portEnvString = Environment.GetEnvironmentVariable("POSTGRES_PORT");
|
|
builder.Port = int.TryParse(portEnvString, out var port) ? port : 5432;
|
|
|
|
builder.Password = GetPostgresPasswordFromSecretFile();
|
|
|
|
// Build the connection string with the new password
|
|
connectionString = builder.ConnectionString;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Log the error but don't fail - use the original connection string
|
|
Console.WriteLine($"Warning: Failed to override PostgreSQL password from secret file: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
optionsBuilder
|
|
.UseNpgsql(connectionString, options => options.CommandTimeout(60))
|
|
.UseLazyLoadingProxies();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if the application is running in a container.
|
|
/// </summary>
|
|
/// <returns>True if running in a container, false otherwise.</returns>
|
|
private static bool IsRunningInContainer()
|
|
{
|
|
return Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the PostgreSQL password from the secret file.
|
|
/// </summary>
|
|
/// <returns>The PostgreSQL password.</returns>
|
|
/// <exception cref="KeyNotFoundException">Thrown when the PostgreSQL password cannot be found.</exception>
|
|
private static string GetPostgresPasswordFromSecretFile()
|
|
{
|
|
const string secretsFilePath = "/secrets/postgres_password";
|
|
|
|
if (!File.Exists(secretsFilePath))
|
|
{
|
|
throw new KeyNotFoundException($"PostgreSQL password file not found at {secretsFilePath}. Container initialization may have failed.");
|
|
}
|
|
|
|
var secretValue = File.ReadAllText(secretsFilePath).Trim();
|
|
if (string.IsNullOrEmpty(secretValue))
|
|
{
|
|
throw new KeyNotFoundException($"PostgreSQL password file at {secretsFilePath} is empty.");
|
|
}
|
|
|
|
return secretValue;
|
|
}
|
|
}
|