Compare commits
5 Commits
17c8e5e9ed
...
testbranch
| Author | SHA1 | Date | |
|---|---|---|---|
| a89779a00c | |||
| febc875834 | |||
| 2305e4b728 | |||
| b6dc66744f | |||
| a01f80bb14 |
@@ -28,9 +28,14 @@ services:
|
||||
- DB_PROVIDER=PostgreSQL
|
||||
- ConnectionStrings__DefaultConnection=Host=db;Database=timetracker;Username=timetracker_user;Password=SecretPassword123;
|
||||
- EnableHttpsRedirect=false
|
||||
- TenantSettings__BaseDomain=timetracker.marc-wieland.de
|
||||
volumes:
|
||||
- dpkeys:/home/app/.aspnet/DataProtection-Keys
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
name: timetracker_pgdata
|
||||
dpkeys:
|
||||
name: timetracker_dpkeys
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
@@ -13,7 +13,6 @@ namespace timetracker.Data.Migrations
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsTenantAdmin",
|
||||
table: "Users",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class TenantProvider : ITenantProvider
|
||||
}
|
||||
|
||||
// Resolve and cache in HttpContext.Items
|
||||
ResolveTenantAsync().GetAwaiter().GetResult();
|
||||
ResolveTenant();
|
||||
|
||||
if (httpContext.Items.TryGetValue("TenantId", out cachedId))
|
||||
{
|
||||
@@ -48,27 +48,27 @@ public class TenantProvider : ITenantProvider
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Tenant?> GetCurrentTenantAsync()
|
||||
public Task<Tenant?> GetCurrentTenantAsync()
|
||||
{
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext == null) return null;
|
||||
if (httpContext == null) return Task.FromResult<Tenant?>(null);
|
||||
|
||||
if (httpContext.Items.TryGetValue("CurrentTenant", out var cachedTenant))
|
||||
{
|
||||
return (Tenant?)cachedTenant;
|
||||
return Task.FromResult((Tenant?)cachedTenant);
|
||||
}
|
||||
|
||||
await ResolveTenantAsync();
|
||||
ResolveTenant();
|
||||
|
||||
if (httpContext.Items.TryGetValue("CurrentTenant", out cachedTenant))
|
||||
{
|
||||
return (Tenant?)cachedTenant;
|
||||
return Task.FromResult((Tenant?)cachedTenant);
|
||||
}
|
||||
|
||||
return null;
|
||||
return Task.FromResult<Tenant?>(null);
|
||||
}
|
||||
|
||||
private async Task ResolveTenantAsync()
|
||||
private void ResolveTenant()
|
||||
{
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext == null) return;
|
||||
@@ -82,9 +82,9 @@ public class TenantProvider : ITenantProvider
|
||||
|
||||
if (!string.IsNullOrEmpty(subdomain))
|
||||
{
|
||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
||||
var tenant = await db.Tenants
|
||||
.FirstOrDefaultAsync(t => t.Subdomain.ToLower() == subdomain.ToLower());
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
var tenant = db.Tenants
|
||||
.FirstOrDefault(t => t.Subdomain.ToLower() == subdomain.ToLower());
|
||||
|
||||
if (tenant != null)
|
||||
{
|
||||
|
||||
@@ -133,7 +133,150 @@ using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var factory = scope.ServiceProvider.GetRequiredService<IDbContextFactory<TimetrackerDbContext>>();
|
||||
await using var db = await factory.CreateDbContextAsync();
|
||||
|
||||
if (dbProvider.Equals("PostgreSQL", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
try
|
||||
{
|
||||
var conn = db.Database.GetDbConnection();
|
||||
if (conn.State != System.Data.ConnectionState.Open)
|
||||
{
|
||||
await conn.OpenAsync();
|
||||
}
|
||||
|
||||
// Check if AppSettings table already exists
|
||||
using (var cmdCheck = conn.CreateCommand())
|
||||
{
|
||||
cmdCheck.CommandText = "SELECT EXISTS (SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = 'AppSettings');";
|
||||
var appSettingsExists = (bool)(await cmdCheck.ExecuteScalarAsync() ?? false);
|
||||
|
||||
if (appSettingsExists)
|
||||
{
|
||||
// Ensure __EFMigrationsHistory table exists
|
||||
using (var cmdCreateHistory = conn.CreateCommand())
|
||||
{
|
||||
cmdCreateHistory.CommandText = @"
|
||||
CREATE TABLE IF NOT EXISTS ""__EFMigrationsHistory"" (
|
||||
""MigrationId"" character varying(150) NOT NULL,
|
||||
""ProductVersion"" character varying(32) NOT NULL,
|
||||
CONSTRAINT ""PK___EFMigrationsHistory"" PRIMARY KEY (""MigrationId"")
|
||||
);";
|
||||
await cmdCreateHistory.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
// Check if the initial migration is already recorded
|
||||
using (var cmdCheckHistory = conn.CreateCommand())
|
||||
{
|
||||
cmdCheckHistory.CommandText = @"SELECT COUNT(*) FROM ""__EFMigrationsHistory"" WHERE ""MigrationId"" = '20260520133634_Initial';";
|
||||
var historyCount = Convert.ToInt32(await cmdCheckHistory.ExecuteScalarAsync() ?? 0);
|
||||
|
||||
if (historyCount == 0)
|
||||
{
|
||||
// Seed the history table with the migrations that were already created by EnsureCreated in older versions
|
||||
using (var cmdInsertHistory = conn.CreateCommand())
|
||||
{
|
||||
cmdInsertHistory.CommandText = @"
|
||||
INSERT INTO ""__EFMigrationsHistory"" (""MigrationId"", ""ProductVersion"") VALUES
|
||||
('20260520133634_Initial', '10.0.9'),
|
||||
('20260520200000_AddPublicHolidays', '10.0.9'),
|
||||
('20260522081459_AddMultiUser', '10.0.9'),
|
||||
('20260607213215_AddFlexTimeAndHolidayState', '10.0.9');";
|
||||
await cmdInsertHistory.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Fehler beim Vorbereiten der PostgreSQL Migrationshistorie: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
await db.Database.MigrateAsync();
|
||||
|
||||
if (dbProvider.Equals("PostgreSQL", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
try
|
||||
{
|
||||
var conn = db.Database.GetDbConnection();
|
||||
if (conn.State != System.Data.ConnectionState.Open)
|
||||
{
|
||||
await conn.OpenAsync();
|
||||
}
|
||||
|
||||
// Check if column IsTenantAdmin in Users table is of type integer
|
||||
using (var cmdCheckType = conn.CreateCommand())
|
||||
{
|
||||
cmdCheckType.CommandText = @"
|
||||
SELECT data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'Users' AND column_name = 'IsTenantAdmin';";
|
||||
var dataType = await cmdCheckType.ExecuteScalarAsync() as string;
|
||||
if (dataType != null && dataType.Equals("integer", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Alter the column type to boolean
|
||||
using (var cmdAlterType = conn.CreateCommand())
|
||||
{
|
||||
cmdAlterType.CommandText = @"
|
||||
ALTER TABLE ""Users""
|
||||
ALTER COLUMN ""IsTenantAdmin"" TYPE boolean
|
||||
USING (""IsTenantAdmin"" <> 0);";
|
||||
await cmdAlterType.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if column IsApproved in Tenants table is of type integer
|
||||
using (var cmdCheckApproved = conn.CreateCommand())
|
||||
{
|
||||
cmdCheckApproved.CommandText = @"
|
||||
SELECT data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'Tenants' AND column_name = 'IsApproved';";
|
||||
var dataType = await cmdCheckApproved.ExecuteScalarAsync() as string;
|
||||
if (dataType != null && dataType.Equals("integer", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Alter the column type to boolean
|
||||
using (var cmdAlterApproved = conn.CreateCommand())
|
||||
{
|
||||
cmdAlterApproved.CommandText = @"
|
||||
ALTER TABLE ""Tenants""
|
||||
ALTER COLUMN ""IsApproved"" TYPE boolean
|
||||
USING (""IsApproved"" <> 0);";
|
||||
await cmdAlterApproved.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if column CreatedAt in Tenants table is of type text or character varying
|
||||
using (var cmdCheckCreatedAt = conn.CreateCommand())
|
||||
{
|
||||
cmdCheckCreatedAt.CommandText = @"
|
||||
SELECT data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'Tenants' AND column_name = 'CreatedAt';";
|
||||
var dataType = await cmdCheckCreatedAt.ExecuteScalarAsync() as string;
|
||||
if (dataType != null && (dataType.Equals("text", StringComparison.OrdinalIgnoreCase) || dataType.Equals("character varying", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
// Alter the column type to timestamp without time zone
|
||||
using (var cmdAlterCreatedAt = conn.CreateCommand())
|
||||
{
|
||||
cmdAlterCreatedAt.CommandText = @"
|
||||
ALTER TABLE ""Tenants""
|
||||
ALTER COLUMN ""CreatedAt"" TYPE timestamp without time zone
|
||||
USING (""CreatedAt""::timestamp without time zone);";
|
||||
await cmdAlterCreatedAt.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Fehler beim Konvertieren der PostgreSQL-Spaltentypen (IsTenantAdmin/IsApproved/CreatedAt): {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var forwardedHeadersOptions = new ForwardedHeadersOptions
|
||||
|
||||
Reference in New Issue
Block a user