diff --git a/src/AliasVault.Admin/Main/Pages/MainBase.cs b/src/AliasVault.Admin/Main/Pages/MainBase.cs
index c72d559c4..b4431113d 100644
--- a/src/AliasVault.Admin/Main/Pages/MainBase.cs
+++ b/src/AliasVault.Admin/Main/Pages/MainBase.cs
@@ -56,10 +56,10 @@ public abstract class MainBase : OwningComponentBase
protected AliasServerDbContext DbContext { get; set; } = null!;
///
- /// Gets or sets the AliasServerDbContextFactory instance.
+ /// Gets or sets the IAliasServerDbContextFactory instance.
///
[Inject]
- protected IDbContextFactory DbContextFactory { get; set; } = null!;
+ protected IAliasServerDbContextFactory DbContextFactory { get; set; } = null!;
///
/// Gets or sets the GlobalLoadingService in order to manipulate the global loading spinner animation.
diff --git a/src/AliasVault.Admin/Program.cs b/src/AliasVault.Admin/Program.cs
index 876f4a558..1e272a766 100644
--- a/src/AliasVault.Admin/Program.cs
+++ b/src/AliasVault.Admin/Program.cs
@@ -69,7 +69,7 @@ builder.Services.ConfigureApplicationCookie(options =>
options.LoginPath = "/user/login";
});
-builder.Services.AddAliasVaultSqliteConfiguration();
+builder.Services.AddAliasVaultDatabaseConfiguration(builder.Configuration);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddIdentityCore(options =>
{
@@ -133,7 +133,7 @@ app.MapRazorComponents()
using (var scope = app.Services.CreateScope())
{
var container = scope.ServiceProvider;
- await using var db = await container.GetRequiredService>().CreateDbContextAsync();
+ await using var db = container.GetRequiredService().CreateDbContext();
await db.Database.MigrateAsync();
await StartupTasks.CreateRolesIfNotExist(scope.ServiceProvider);
diff --git a/src/AliasVault.Admin/appsettings.json b/src/AliasVault.Admin/appsettings.json
index a07244645..bc79ae18f 100644
--- a/src/AliasVault.Admin/appsettings.json
+++ b/src/AliasVault.Admin/appsettings.json
@@ -1,4 +1,5 @@
{
+ "DatabaseProvider": "sqlite",
"ConnectionStrings": {
"AliasServerDbContext": "Data Source=../../database/AliasServerDb.sqlite"
},
diff --git a/src/Databases/AliasServerDb/AliasServerDbContext.cs b/src/Databases/AliasServerDb/AliasServerDbContext.cs
index 24a3051dc..ae1468bdb 100644
--- a/src/Databases/AliasServerDb/AliasServerDbContext.cs
+++ b/src/Databases/AliasServerDb/AliasServerDbContext.cs
@@ -18,12 +18,12 @@ using Microsoft.Extensions.Configuration;
/// we have two separate user objects, one for the admin panel and one for the vault. We manually
/// define the Identity tables in the OnModelCreating method.
///
-public abstract class AliasServerDbContext : WorkerStatusDbContext, IDataProtectionKeyContext
+public class AliasServerDbContext : WorkerStatusDbContext, IDataProtectionKeyContext
{
///
/// Initializes a new instance of the class.
///
- protected AliasServerDbContext()
+ public AliasServerDbContext()
{
}
@@ -31,7 +31,7 @@ public abstract class AliasServerDbContext : WorkerStatusDbContext, IDataProtect
/// Initializes a new instance of the class.
///
/// DbContextOptions.
- protected AliasServerDbContext(DbContextOptions options)
+ public AliasServerDbContext(DbContextOptions options)
: base(options)
{
}
diff --git a/src/Databases/AliasServerDb/Configuration/DatabaseConfiguration.cs b/src/Databases/AliasServerDb/Configuration/DatabaseConfiguration.cs
index 448a91e68..2d4a67b72 100644
--- a/src/Databases/AliasServerDb/Configuration/DatabaseConfiguration.cs
+++ b/src/Databases/AliasServerDb/Configuration/DatabaseConfiguration.cs
@@ -7,9 +7,6 @@
namespace AliasServerDb.Configuration;
-using System.Data.Common;
-using Microsoft.Data.Sqlite;
-using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -22,39 +19,29 @@ public static class DatabaseConfiguration
/// Configures SQLite for use with Entity Framework Core.
///
/// The IServiceCollection to add the DbContext to.
+ /// The IConfiguration to use for the connection string.
/// The IServiceCollection for method chaining.
- public static IServiceCollection AddAliasVaultSqliteConfiguration(this IServiceCollection services)
+ public static IServiceCollection AddAliasVaultDatabaseConfiguration(this IServiceCollection services, IConfiguration configuration)
{
- var serviceProvider = services.BuildServiceProvider();
- var configuration = serviceProvider.GetRequiredService();
+ var dbProvider = configuration.GetValue("DatabaseProvider")?.ToLower() ?? "sqlite";
- var connectionString = configuration.GetConnectionString("AliasServerDbContext");
- if (string.IsNullOrEmpty(connectionString))
+ switch (dbProvider)
{
- throw new InvalidOperationException("Connection string 'AliasServerDbContext' not found.");
+ case "postgresql":
+ services.AddScoped();
+ break;
+ case "sqlite":
+ default:
+ services.AddScoped();
+ break;
}
- var sqliteConnectionStringBuilder = new SqliteConnectionStringBuilder(connectionString)
+ services.AddScoped(sp =>
{
- Cache = SqliteCacheMode.Private,
- Mode = SqliteOpenMode.ReadWriteCreate,
- };
-
- services.AddDbContextFactory(options =>
- {
- options.UseSqlite(CreateAndConfigureSqliteConnection(sqliteConnectionStringBuilder.ConnectionString), sqliteOptions =>
- {
- sqliteOptions.CommandTimeout(60);
- }).UseLazyLoadingProxies();
+ var factory = sp.GetRequiredService();
+ return factory.CreateDbContext();
});
return services;
}
-
- private static SqliteConnection CreateAndConfigureSqliteConnection(string connectionString)
- {
- var connection = new SqliteConnection(connectionString);
- connection.Open();
- return connection;
- }
}
diff --git a/src/Databases/AliasServerDb/IAliasServerDbContextFactory.cs b/src/Databases/AliasServerDb/IAliasServerDbContextFactory.cs
new file mode 100644
index 000000000..3b19af1cd
--- /dev/null
+++ b/src/Databases/AliasServerDb/IAliasServerDbContextFactory.cs
@@ -0,0 +1,27 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) lanedirt. All rights reserved.
+// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
+//
+//-----------------------------------------------------------------------
+
+namespace AliasServerDb;
+
+///
+/// The AliasServerDbContextFactory interface.
+///
+public interface IAliasServerDbContextFactory
+{
+ ///
+ /// Creates a new AliasServerDbContext.
+ ///
+ /// The AliasServerDbContext.
+ AliasServerDbContext CreateDbContext();
+
+ ///
+ /// Creates a new AliasServerDbContext asynchronously.
+ ///
+ /// The cancellation token.
+ /// A task that represents the asynchronous operation. The task result contains the AliasServerDbContext.
+ Task CreateDbContextAsync(CancellationToken cancellationToken = default);
+}
diff --git a/src/Databases/AliasServerDb/PostgresqlDbContextFactory.cs b/src/Databases/AliasServerDb/PostgresqlDbContextFactory.cs
new file mode 100644
index 000000000..262d040d1
--- /dev/null
+++ b/src/Databases/AliasServerDb/PostgresqlDbContextFactory.cs
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) lanedirt. All rights reserved.
+// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
+//
+//-----------------------------------------------------------------------
+
+namespace AliasServerDb;
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+
+///
+/// The AliasServerDbContextFactory interface.
+///
+public class PostgresqlDbContextFactory : IAliasServerDbContextFactory
+{
+ private readonly IConfiguration _configuration;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The configuration.
+ public PostgresqlDbContextFactory(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ ///
+ public AliasServerDbContext CreateDbContext()
+ {
+ var optionsBuilder = new DbContextOptionsBuilder();
+ var connectionString = _configuration.GetConnectionString("AliasServerDbContext");
+
+ optionsBuilder
+ .UseNpgsql(connectionString, options => options.CommandTimeout(60))
+ .UseLazyLoadingProxies();
+
+ return new AliasServerDbContextPostgresql(optionsBuilder.Options);
+ }
+
+ ///
+ public Task CreateDbContextAsync(CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult(CreateDbContext());
+ }
+}
diff --git a/src/Databases/AliasServerDb/SqliteDbContextFactory.cs b/src/Databases/AliasServerDb/SqliteDbContextFactory.cs
new file mode 100644
index 000000000..69f08b50a
--- /dev/null
+++ b/src/Databases/AliasServerDb/SqliteDbContextFactory.cs
@@ -0,0 +1,48 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) lanedirt. All rights reserved.
+// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
+//
+//-----------------------------------------------------------------------
+
+namespace AliasServerDb;
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+
+///
+/// The AliasServerDbContextFactory interface.
+///
+public class SqliteDbContextFactory : IAliasServerDbContextFactory
+{
+ private readonly IConfiguration _configuration;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The configuration.
+ public SqliteDbContextFactory(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ ///
+ public AliasServerDbContext CreateDbContext()
+ {
+ var optionsBuilder = new DbContextOptionsBuilder();
+ var connectionString = _configuration.GetConnectionString("AliasServerDbContext") +
+ ";Mode=ReadWriteCreate;Cache=Shared";
+
+ optionsBuilder
+ .UseSqlite(connectionString, options => options.CommandTimeout(60))
+ .UseLazyLoadingProxies();
+
+ return new AliasServerDbContextSqlite(optionsBuilder.Options);
+ }
+
+ ///
+ public Task CreateDbContextAsync(CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult(CreateDbContext());
+ }
+}
diff --git a/src/Shared/AliasVault.Shared.Server/Services/ServerSettingsService.cs b/src/Shared/AliasVault.Shared.Server/Services/ServerSettingsService.cs
index 5ac7622f1..c00305141 100644
--- a/src/Shared/AliasVault.Shared.Server/Services/ServerSettingsService.cs
+++ b/src/Shared/AliasVault.Shared.Server/Services/ServerSettingsService.cs
@@ -20,7 +20,7 @@ using Microsoft.EntityFrameworkCore;
/// Server settings service.
///
/// IDbContextFactory instance.
-public class ServerSettingsService(IDbContextFactory dbContextFactory)
+public class ServerSettingsService(IAliasServerDbContextFactory dbContextFactory)
{
private readonly Dictionary _cache = new();
@@ -36,7 +36,7 @@ public class ServerSettingsService(IDbContextFactory dbCon
return cachedValue;
}
- await using var dbContext = await dbContextFactory.CreateDbContextAsync(CancellationToken.None);
+ await using var dbContext = dbContextFactory.CreateDbContext();
var setting = await dbContext.ServerSettings.FirstOrDefaultAsync(x => x.Key == key);
_cache[key] = setting?.Value;
@@ -57,7 +57,7 @@ public class ServerSettingsService(IDbContextFactory dbCon
return;
}
- await using var dbContext = await dbContextFactory.CreateDbContextAsync(CancellationToken.None);
+ await using var dbContext = dbContextFactory.CreateDbContext();
var setting = await dbContext.ServerSettings.FirstOrDefaultAsync(x => x.Key == key);
var now = DateTime.UtcNow;
@@ -96,7 +96,7 @@ public class ServerSettingsService(IDbContextFactory dbCon
/// The settings.
public async Task GetAllSettingsAsync()
{
- await using var dbContext = await dbContextFactory.CreateDbContextAsync(CancellationToken.None);
+ await using var dbContext = dbContextFactory.CreateDbContext();
var settings = await dbContext.ServerSettings.ToDictionaryAsync(x => x.Key, x => x.Value);
// Create model with defaults