This commit is contained in:
Janus Knudsen 2025-02-10 18:41:51 +01:00
parent 05d6977a76
commit c83442b4af
16 changed files with 315 additions and 272 deletions

View file

@ -0,0 +1,86 @@
using System.Data;
using Database.Common;
using Insight.Database;
namespace Database.Core.DataControlLanguage
{
/// <summary>
/// Only a superadmin or similar can create Application Users
/// </summary>
public class SetupApplicationUser
{
IDbConnection _db;
string _schema;
string _user;
string _password;
public SetupApplicationUser(IDbConnection db)
{
_db = db;
}
public void CreateUserWithSchemaInDatabase(string schema, string user, string password)
{
_schema = schema;
_password = password;
_user = user;
if (!Validations.IsValidSchemaName(_schema))
throw new ArgumentException("Invalid schema name", _schema);
using (var transaction = _db.BeginTransaction())
{
try
{
CreateSchema();
CreateRole();
GrantSchemaRights();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw new InvalidOperationException("Failed to SetupApplicationUser in Database", ex);
}
}
}
private void ExecuteSql(string sql)
{
_db.ExecuteSql(sql);
}
private void CreateSchema()
{
var sql = $"CREATE SCHEMA IF NOT EXISTS {_schema}";
ExecuteSql(sql);
}
private void CreateRole()
{
var sql = $"CREATE ROLE {_user} WITH CREATEDB CREATEROLE LOGIN PASSWORD '{_password}';";
ExecuteSql(sql);
var sql1 = $"ALTER ROLE {_user} SET search_path='{_schema}';";
ExecuteSql(sql1);
}
private void GrantSchemaRights()
{
var sql = $"GRANT USAGE ON SCHEMA {_schema} TO {_user};";
ExecuteSql(sql);
var sql1 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_schema} " +
$"GRANT INSERT, SELECT, UPDATE PRIVILEGES ON TABLES TO {_user};";
ExecuteSql(sql1);
var sql2 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_schema} TO {_user};";
ExecuteSql(sql2);
}
}
}

View file

@ -0,0 +1,86 @@
using System.Data;
using Database.Common;
using Insight.Database;
namespace Database.Core.DataControlLanguage
{
public class SetupOrganization
{
IDbConnection _db;
string _schema;
string _user;
string _password;
public SetupOrganization(IDbConnection db)
{
_db = db;
}
public void CreateUserWithSchemaInDatabase(string schema, string user, string password)
{
_schema = schema;
_password = password;
_user = user;
if (!Validations.IsValidSchemaName(_schema))
throw new ArgumentException("Invalid schema name", _schema);
using (var transaction = _db.BeginTransaction())
{
try
{
CreateSchema();
CreateRole();
GrantSchemaRights();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw new InvalidOperationException("Failed to SetupOrganization in Database", ex);
}
}
}
private void ExecuteSql(string sql)
{
_db.ExecuteSql(sql);
}
private void CreateSchema()
{
var sql = $"CREATE SCHEMA IF NOT EXISTS {_schema}";
ExecuteSql(sql);
}
private void CreateRole()
{
var sql = $"CREATE ROLE {_user} LOGIN PASSWORD '{_password}';";
ExecuteSql(sql);
var sql1 = $"ALTER ROLE {_user} SET search_path='{_schema}';";
ExecuteSql(sql1);
}
private void GrantSchemaRights()
{
var sql = $"GRANT USAGE ON SCHEMA {_schema} TO {_user};";
ExecuteSql(sql);
var sql1 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_schema} " +
$"GRANT INSERT, SELECT, UPDATE PRIVILEGES ON TABLES TO {_user};";
ExecuteSql(sql1);
var sql2 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_schema} TO {_user};";
ExecuteSql(sql2);
}
}
}

View file

@ -1,7 +1,7 @@
using Insight.Database; using Insight.Database;
using System.Data; using System.Data;
namespace Database.Core namespace Database.Core.DataDefinitionLanguage
{ {
public interface IDbSetup public interface IDbSetup
{ {

View file

@ -1,88 +0,0 @@
using System;
using System.Data;
using System.Text.RegularExpressions;
using Database.Common;
using Insight.Database;
namespace Database.Tenants
{
public class Setup
{
IDbConnection _db;
string _schema;
string _user;
string _password;
public Setup(IDbConnection db)
{
_db = db;
}
public void CreateUserWithSchemaInDatabase(string schema, string user, string password)
{
_schema = schema;
_password = password;
_user = user;
if (!Validations.IsValidSchemaName(_schema))
throw new ArgumentException("Invalid schema name", _schema);
using (var transaction = _db.BeginTransaction())
{
try
{
CreateSchema();
CreateRole();
GrantSchemaRights();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw new InvalidOperationException("Failed to CreateUserWithSchemaInDatabase", ex);
}
}
}
private void ExecuteSql(string sql)
{
_db.ExecuteSql(sql);
}
private void CreateSchema()
{
var sql = $"CREATE SCHEMA IF NOT EXISTS {_schema}";
ExecuteSql(sql);
}
private void CreateRole()
{
var sql = $"CREATE ROLE {_user} LOGIN PASSWORD '{_password}';";
ExecuteSql(sql);
var sql1 = $"ALTER ROLE {_user} SET search_path='{_schema}';";
ExecuteSql(sql1);
}
private void GrantSchemaRights()
{
var sql = $"GRANT USAGE ON SCHEMA {_schema} TO {_user};";
ExecuteSql(sql);
var sql1 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_schema} " +
$"GRANT INSERT, SELECT, UPDATE PRIVILEGES ON TABLES TO {_user};";
ExecuteSql(sql1);
var sql2 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_schema} TO {_user};";
ExecuteSql(sql2);
}
}
}

View file

@ -1,4 +1,6 @@
using Autofac; using Autofac;
using Insight.Database;
using System.Data;
namespace SetupInfrastructure namespace SetupInfrastructure
{ {
@ -12,16 +14,22 @@ namespace SetupInfrastructure
/// After that is executed it is time for running this main program /// After that is executed it is time for running this main program
/// Remember to use the newly created sathumper /// Remember to use the newly created sathumper
/// "ConnectionStrings": { /// "ConnectionStrings": {
/// "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptdb01;User Id=sathumper;Password=<secret>;" /// "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptdb01;User Id=<uid>;Password=<secret>;"
/// </summary> /// </summary>
internal class Program internal class Program
{ {
static IContainer _container;
static async Task Main(string[] args) static async Task Main(string[] args)
{ {
string userPass; string userPass;
try
{
do do
{ {
Console.WriteLine("Input username:password"); Console.WriteLine("Input <username>:<password>");
userPass = Console.ReadLine() ?? string.Empty; userPass = Console.ReadLine() ?? string.Empty;
} while (!userPass.Contains(":") || userPass.Split(":").Length != 2 || } while (!userPass.Contains(":") || userPass.Split(":").Length != 2 ||
string.IsNullOrEmpty(userPass.Split(":")[0]) || string.IsNullOrEmpty(userPass.Split(":")[0]) ||
@ -31,18 +39,98 @@ namespace SetupInfrastructure
user: userPass.Split(":")[0], user: userPass.Split(":")[0],
pwd: userPass.Split(":")[1] pwd: userPass.Split(":")[1]
); );
var container = new Startup().ConfigureContainer(ctp); _container = new Startup().ConfigureContainer(ctp);
if (TestDbRole())
{
// SetupApplicationUser
// SetupIdentitySystem // SetupIdentitySystem
// ConfigurationDatabaseSetup // SetupConfiguration
//and a lot of other tables that we haven't defined yet
// input configurations!!! TODO:Missing // input configurations!!! TODO:Missing
}
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e);
}
}
static bool TestDbRole()
{
var backgroundColor = Console.BackgroundColor;
var foregroundColor = Console.ForegroundColor;
//test db access
Console.WriteLine("Testing db access...");
string query = @"SELECT usename, usesuper FROM pg_user WHERE usename = CURRENT_USER;";
var conn = _container.Resolve<IDbConnection>();
var result = (dynamic)conn.QuerySql(query).Single();
string username = result.usename;
bool isSuperuser = (bool)result.usesuper;
if ((bool)result.usesuper)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.BackgroundColor = ConsoleColor.Yellow;
Console.WriteLine();
Console.WriteLine("TEST SUCCESSFULLY");
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.White;
Console.BackgroundColor = backgroundColor;
Console.WriteLine("-------------------------------");
Console.WriteLine();
Console.WriteLine($"Username: {username}");
Console.WriteLine($"Super admin: true");
Console.WriteLine();
Console.WriteLine("-------------------------------");
Console.WriteLine("Press any key to start database setup");
Console.Read();
return true;
}
Console.ForegroundColor = ConsoleColor.Green;
Console.BackgroundColor = ConsoleColor.Red;
Console.WriteLine();
Console.WriteLine("TEST WAS NOT SUCCESSFULLY");
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.White;
Console.BackgroundColor = backgroundColor;
Console.WriteLine("-------------------------------");
Console.WriteLine();
Console.WriteLine($"Username: {username}");
Console.WriteLine($"Super admin: false");
Console.WriteLine();
Console.WriteLine("-------------------------------");
Console.WriteLine("User is required to be super admin");
Console.Read();
return false;
} }
} }
} }

View file

@ -4,7 +4,6 @@
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View file

@ -10,7 +10,7 @@ namespace SetupInfrastructure
public virtual IConfigurationRoot Configuration() public virtual IConfigurationRoot Configuration()
{ {
var configuration = new ConfigurationBuilder() var configuration = new ConfigurationBuilder()
.AddJsonFile("appconfiguration.dev.json") .AddJsonFile("appconfiguration.json")
.Build(); .Build();
return configuration; return configuration;

View file

@ -1,7 +1,7 @@
{ {
"AllowedHosts": "*", "AllowedHosts": "*",
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptdb01;User Id={usr};Password={pwd};" "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id={usr};Password={pwd};"
}, },
"ApplicationInsights": { "ApplicationInsights": {
"ConnectionString": "InstrumentationKey=6d2e76ee-5343-4691-a5e3-81add43cb584;IngestionEndpoint=https://northeurope-0.in.applicationinsights.azure.com/" "ConnectionString": "InstrumentationKey=6d2e76ee-5343-4691-a5e3-81add43cb584;IngestionEndpoint=https://northeurope-0.in.applicationinsights.azure.com/"

View file

@ -9,8 +9,7 @@
"configuration": { "configuration": {
"host": "192.168.1.57", "host": "192.168.1.57",
"port": "5432", "port": "5432",
"database": "postgres", "url": "jdbc:postgresql://192.168.1.57:5432/",
"url": "jdbc:postgresql://192.168.1.57:5432/postgres",
"configurationType": "MANUAL", "configurationType": "MANUAL",
"home": "postgresql_client", "home": "postgresql_client",
"type": "dev", "type": "dev",

View file

@ -1 +1 @@
{"resources":{"Scripts/Script-2.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01","default-schema":"ptmain"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"}}} {"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"postgres"},"Scripts/Script-2.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/Script-3.sql":{"default-datasource":"postgres-jdbc-19484872d85-cd2a4a40116e706","default-catalog":"ptdb01","default-schema":"ptmain"},"Scripts/Script-4.sql":{"default-datasource":"postgres-jdbc-19484872d85-cd2a4a40116e706","default-catalog":"ptdb01","default-schema":"ptmain"},"Scripts/Script-5.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"sandbox"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-19484872d85-cd2a4a40116e706","default-catalog":"sandbox","default-schema":"public"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"sandbox"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"}}}

View file

@ -9,8 +9,8 @@
"configuration": { "configuration": {
"host": "192.168.1.57", "host": "192.168.1.57",
"port": "5432", "port": "5432",
"database": "postgres", "database": "ptmain",
"url": "jdbc:postgresql://192.168.1.57:5432/postgres", "url": "jdbc:postgresql://192.168.1.57:5432/ptmain",
"configurationType": "MANUAL", "configurationType": "MANUAL",
"home": "postgresql_client", "home": "postgresql_client",
"type": "dev", "type": "dev",
@ -34,34 +34,6 @@
}, },
"auth-model": "native" "auth-model": "native"
} }
},
"postgres-jdbc-19484872d85-cd2a4a40116e706": {
"provider": "postgresql",
"driver": "postgres-jdbc",
"name": "UB-KK01-sathumper",
"configuration": {
"host": "192.168.1.57",
"port": "5432",
"database": "postgres",
"url": "jdbc:postgresql://192.168.1.57:5432/postgres",
"configurationType": "MANUAL",
"home": "postgresql_client",
"type": "dev",
"closeIdleConnection": true,
"provider-properties": {
"@dbeaver-show-non-default-db@": "true",
"@dbeaver-chosen-role@": "",
"@dbeaver-show-template-db@": "false",
"@dbeaver-show-unavailable-db@": "false",
"show-database-statistics": "false",
"@dbeaver-read-all-data-types-db@": "false",
"read-keys-with-columns": "false",
"@dbeaver-use-prepared-statements-db@": "false",
"postgresql.dd.plain.string": "false",
"postgresql.dd.tag.string": "false"
},
"auth-model": "native"
}
} }
}, },
"connection-types": { "connection-types": {

View file

@ -1 +1 @@
{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01","default-schema":"ptmain"},"Scripts/Script-2.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"}}} {"resources":{"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"sandbox"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"}}}

View file

@ -1,99 +0,0 @@
GRANT USAGE, CREATE ON SCHEMA swp TO sathumper;
ALTER DEFAULT PRIVILEGES IN SCHEMA swp
GRANT ALL PRIVILEGES ON TABLES TO sathumper;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA swp TO sathumper;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA swp TO sathumper;
select * from dev.app_configuration
CREATE OR REPLACE FUNCTION dev.notify_config_change()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'DELETE' THEN
PERFORM pg_notify(
'config_changes',
json_build_object('operation', TG_OP, 'data', row_to_json(OLD))::text
);
RETURN OLD; -- Return OLD for DELETE operations
ELSE
PERFORM pg_notify(
'config_changes',
json_build_object('operation', TG_OP, 'data', row_to_json(NEW))::text
);
RETURN NEW; -- Return NEW for INSERT/UPDATE operations
END IF;
END;
$$ LANGUAGE plpgsql;
-- Trigger på configuration tabellen
CREATE TRIGGER config_change_trigger
AFTER INSERT OR UPDATE OR DELETE ON dev.app_configuration
FOR EACH ROW EXECUTE FUNCTION dev.notify_config_change();
update dev.app_configuration
set "label" = "label" where id = 3
SELECT row_to_json(t)
FROM (SELECT 1 as id, 'test' as key) t;
SET myapp.tenant_id = '1';
SHOW myapp.tenant_id;
create TABLE dev.app_configuration1 (
tenant_id varchar(25),
config_key VARCHAR(255),
config_value TEXT,
PRIMARY KEY (tenant_id, config_key)
);
ALTER TABLE dev.app_configuration1 ENABLE ROW LEVEL SECURITY;
CREATE drop POLICY tenant_policy
ON dev.app_configuration1
FOR SELECT
USING (
current_setting('myapp.tenant_id', true) IS NOT NULL AND
tenant_id = current_setting('myapp.tenant_id')::INT
);
CREATE POLICY tenant_policy
ON dev.app_configuration1
FOR SELECT
USING (
tenant_id::text = current_user
);
insert into dev.app_configuration1
(tenant_id, config_key, config_value) values('dev', 't2', 'best dat')
SET myapp.tenant_id = 0
ALTER USER din_bruger NOBYPASS RLS;
select * from dev.app_configuration1
SHOW row_security;
GRANT USAGE, CREATE ON SCHEMA dev TO sathumper;
ALTER DEFAULT PRIVILEGES IN SCHEMA dev
GRANT ALL PRIVILEGES ON TABLES TO sathumper;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA dev TO sathumper;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA dev TO sathumper;