From 2e0b20a53e1dd2e70e67ea8e7cf07f4e32b298b5 Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Wed, 22 Jan 2025 17:30:10 +0100 Subject: [PATCH] Test and Run DbSetup, succes --- .../PostgresqlConfigurationBuilder/Class2.cs | 9 +- Database/Identity/DbSetup.cs | 143 ++++++++++-------- Database/Tenants/TenantSetupService.cs | 4 +- PlanTempus.sln | 3 +- ...resLISTEN.csproj => TestPostgresql.csproj} | 0 Tests/Tests.csproj | 1 + Tests/UnitTest1.cs | 16 +- Tests/appsettings.dev.json | 2 +- 8 files changed, 102 insertions(+), 76 deletions(-) rename TestPostgresLISTEN/{TestPostgresLISTEN.csproj => TestPostgresql.csproj} (100%) diff --git a/Core/Configurations/PostgresqlConfigurationBuilder/Class2.cs b/Core/Configurations/PostgresqlConfigurationBuilder/Class2.cs index f1cb84f..1c8e1cb 100644 --- a/Core/Configurations/PostgresqlConfigurationBuilder/Class2.cs +++ b/Core/Configurations/PostgresqlConfigurationBuilder/Class2.cs @@ -1,12 +1,9 @@ using Microsoft.Extensions.Configuration; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Core.Configurations.PostgresqlConfigurationBuilder { + /// + /// LISTEN / NOTIFY in Postgresql + /// public static class PostgresConfigurationExtensions { public static IConfigurationBuilder AddPostgresConfiguration( diff --git a/Database/Identity/DbSetup.cs b/Database/Identity/DbSetup.cs index a8ab1b0..09d2fe4 100644 --- a/Database/Identity/DbSetup.cs +++ b/Database/Identity/DbSetup.cs @@ -3,77 +3,94 @@ using System.Data; namespace Database.Identity { - public class DbSetup - { - private readonly IDbConnection _db; + public class DbSetup + { + private readonly IDbConnection _db; + string _schema; - public DbSetup(IDbConnection db) - { - _db = db; - } + public DbSetup(IDbConnection db) + { + _db = db; + } - public void CreateDatabase() - { - var schema = "dev"; + public async Task CreateDatabase(string schema) + { + _schema = schema; - if (_db.State != ConnectionState.Open) - _db.Open(); + if (_db.State != ConnectionState.Open) + _db.Open(); - using var transaction = _db.BeginTransaction(); - try - { - // Create tables - _db.Execute(@$" - CREATE TABLE IF NOT EXISTS {schema}.users ( - id SERIAL PRIMARY KEY, - email VARCHAR(256) NOT NULL UNIQUE, - password_hash VARCHAR(256) NOT NULL, - security_stamp VARCHAR(36) NOT NULL, - email_confirmed BOOLEAN NOT NULL DEFAULT FALSE, - created_date TIMESTAMP NOT NULL, - last_login_date TIMESTAMP NULL - ); + using var transaction = _db.BeginTransaction(); + try + { + await CreateUserTable(); + await CreateTenantTable(); + await CreateUserTenantTable(); + await SetupRLS(); - CREATE TABLE IF NOT EXISTS {schema}.tenants ( - id SERIAL PRIMARY KEY, - connection_string VARCHAR(500) NOT NULL, - created_date TIMESTAMP NOT NULL, - created_by INTEGER REFERENCES users(id), - is_active BOOLEAN DEFAULT true - ); + transaction.Commit(); + } + catch + { + transaction.Rollback(); + throw; + } + } - CREATE TABLE IF NOT EXISTS {schema}.user_tenants ( - user_id INTEGER REFERENCES users(id), - tenant_id INTEGER REFERENCES tenants(id), - created_date TIMESTAMP NOT NULL, - PRIMARY KEY (user_id, tenant_id) - ); + private async Task CreateUserTable() + { + await _db.ExecuteSqlAsync(@$" + CREATE TABLE IF NOT EXISTS {_schema}.users ( + id SERIAL PRIMARY KEY, + email VARCHAR(256) NOT NULL UNIQUE, + password_hash VARCHAR(256) NOT NULL, + security_stamp VARCHAR(36) NOT NULL, + email_confirmed BOOLEAN NOT NULL DEFAULT FALSE, + created_date TIMESTAMP NOT NULL, + last_login_date TIMESTAMP NULL + );"); + } - -- Enable RLS på både tenants og user_tenants - ALTER TABLE {schema}.tenants ENABLE ROW LEVEL SECURITY; - ALTER TABLE {schema}.user_tenants ENABLE ROW LEVEL SECURITY; + private async Task CreateTenantTable() + { + await _db.ExecuteSqlAsync(@$" + CREATE TABLE IF NOT EXISTS {_schema}.tenants ( + id SERIAL PRIMARY KEY, + connection_string VARCHAR(500) NOT NULL, + created_date TIMESTAMP NOT NULL, + created_by INTEGER REFERENCES {_schema}.users(id), + is_active BOOLEAN DEFAULT true + );"); + } - -- RLS policy for tenants - DROP POLICY IF EXISTS tenant_access ON {schema}.tenants; - CREATE POLICY tenant_access ON {schema}.tenants - USING (id IN ( - SELECT tenant_id - FROM {schema}.user_tenants - WHERE user_id = current_setting('app.user_id', TRUE)::INTEGER - )); + private async Task CreateUserTenantTable() + { + await _db.ExecuteSqlAsync(@$" + CREATE TABLE IF NOT EXISTS {_schema}.user_tenants ( + user_id INTEGER REFERENCES {_schema}.users(id), + tenant_id INTEGER REFERENCES {_schema}.tenants(id), + created_date TIMESTAMP NOT NULL, + PRIMARY KEY (user_id, tenant_id) + );"); + } - -- RLS policy for user_tenants - DROP POLICY IF EXISTS user_tenant_access ON {schema}.user_tenants; - CREATE POLICY user_tenant_access ON {schema}.user_tenants - USING (user_id = current_setting('app.user_id', TRUE)::INTEGER);"); + private async Task SetupRLS() + { + await _db.ExecuteSqlAsync(@$" + ALTER TABLE {_schema}.tenants ENABLE ROW LEVEL SECURITY; + ALTER TABLE {_schema}.user_tenants ENABLE ROW LEVEL SECURITY; - transaction.Commit(); - } - catch - { - transaction.Rollback(); - throw; - } - } - } + DROP POLICY IF EXISTS tenant_access ON {_schema}.tenants; + CREATE POLICY tenant_access ON {_schema}.tenants + USING (id IN ( + SELECT tenant_id + FROM {_schema}.user_tenants + WHERE user_id = current_setting('app.user_id', TRUE)::INTEGER + )); + + DROP POLICY IF EXISTS user_tenant_access ON {_schema}.user_tenants; + CREATE POLICY user_tenant_access ON {_schema}.user_tenants + USING (user_id = current_setting('app.user_id', TRUE)::INTEGER);"); + } + } } diff --git a/Database/Tenants/TenantSetupService.cs b/Database/Tenants/TenantSetupService.cs index 81a646c..9ea033d 100644 --- a/Database/Tenants/TenantSetupService.cs +++ b/Database/Tenants/TenantSetupService.cs @@ -17,9 +17,9 @@ namespace Database.Tenants public async Task CreateTenantInDatabase(string schema, string user, string password) { if (!Regex.IsMatch(schema, "^[a-zA-Z0-9_]+$")) - { throw new ArgumentException("Invalid schema name"); - } + + await CreateUser(user, password); await CreateSchema(schema); await CreateRolesTable(schema); diff --git a/PlanTempus.sln b/PlanTempus.sln index add7632..d85aa5c 100644 --- a/PlanTempus.sln +++ b/PlanTempus.sln @@ -10,7 +10,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "Application\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Database", "Database\Database.csproj", "{D5096A7F-E6D4-4C87-874E-2D9A6BEAD57F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPostgresLISTEN", "TestPostgresLISTEN\TestPostgresLISTEN.csproj", "{743EF625-6C74-419C-A492-AA069956F471}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPostgresql", "TestPostgresLISTEN\TestPostgresql.csproj", "{743EF625-6C74-419C-A492-AA069956F471}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -46,3 +46,4 @@ Global SolutionGuid = {AF20C396-63E0-48AE-A4EA-5D24A20C4845} EndGlobalSection EndGlobal +Global diff --git a/TestPostgresLISTEN/TestPostgresLISTEN.csproj b/TestPostgresLISTEN/TestPostgresql.csproj similarity index 100% rename from TestPostgresLISTEN/TestPostgresLISTEN.csproj rename to TestPostgresLISTEN/TestPostgresql.csproj diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 3ab9fcb..6e294c1 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -17,6 +17,7 @@ + diff --git a/Tests/UnitTest1.cs b/Tests/UnitTest1.cs index 675313e..d1492dc 100644 --- a/Tests/UnitTest1.cs +++ b/Tests/UnitTest1.cs @@ -19,8 +19,8 @@ namespace Tests conn.ExecuteSql("SELECT 1 as p"); - var sql = "SELECT * FROM swp.foo"; - var customers = conn.Query(sql, commandType:CommandType.Text); + //var sql = "SELECT * FROM swp.foo"; + //var customers = conn.Query(sql, commandType:CommandType.Text); } @@ -30,9 +30,19 @@ namespace Tests var conn = Container.Resolve(); } + [TestMethod] + public async Task TryDbSetup() + { + var conn = Container.Resolve(); + + var dbSetup = new Database.Identity.DbSetup(conn); + await dbSetup.CreateDatabase("swp"); + } + + [TestMethod] - public void MyTestMethod() + public void SetupPostgresql_LISTEN() { var builder = new ConfigurationBuilder() .AddPostgresConfiguration(options => diff --git a/Tests/appsettings.dev.json b/Tests/appsettings.dev.json index 0e3cd9a..bd7624b 100644 --- a/Tests/appsettings.dev.json +++ b/Tests/appsettings.dev.json @@ -1,7 +1,7 @@ { "AllowedHosts": "*", "ConnectionStrings": { - "ptdb": "Host=192.168.1.57;Port=5432;Database=ptdb01;User Id=sathumper;Password=3911;" + "ptdb": "Host=192.168.1.57;Port=5432;Database=ptdb01;User Id=postgres;Password=3911;" }, "ApplicationInsights": { "ConnectionString": "InstrumentationKey=6d2e76ee-5343-4691-a5e3-81add43cb584;IngestionEndpoint=https://northeurope-0.in.applicationinsights.azure.com/"