diff --git a/.idea/config/applicationhost.config b/.idea/config/applicationhost.config
new file mode 100644
index 0000000..4ebad82
--- /dev/null
+++ b/.idea/config/applicationhost.config
@@ -0,0 +1,983 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Core/Core.csproj b/Core/Core.csproj
index 5a20b4d..5f9b7f3 100644
--- a/Core/Core.csproj
+++ b/Core/Core.csproj
@@ -16,6 +16,7 @@
+
diff --git a/Core/MultiKeyEncryption/MasterKey.cs b/Core/MultiKeyEncryption/MasterKey.cs
new file mode 100644
index 0000000..c2e40c1
--- /dev/null
+++ b/Core/MultiKeyEncryption/MasterKey.cs
@@ -0,0 +1,27 @@
+namespace Core.CryptoService
+{
+ internal class MasterKey
+ {
+ public async Task RotateMasterKey(int tenantId, string oldMasterKey, string newMasterKey)
+ {
+ // Hent alle bruger-keys for tenant
+ //var users = await GetTenantUsers(tenantId);
+
+ //// Dekrypter connection string med gammel master key
+ //var connString = DecryptWithKey(encryptedConnString, oldMasterKey);
+
+ //// Krypter med ny master key
+ //var newEncryptedConnString = EncryptWithKey(connString, newMasterKey);
+
+ //// Re-krypter master key for alle brugere
+ //foreach (var user in users)
+ //{
+ // var userKey = DeriveKeyFromPassword(user.Password);
+ // var newEncryptedMasterKey = EncryptWithKey(newMasterKey, userKey);
+ // await UpdateUserMasterKey(user.UserId, newEncryptedMasterKey);
+ //}
+
+ //await UpdateTenantConnectionString(tenantId, newEncryptedConnString);
+ }
+ }
+}
diff --git a/Core/MultiKeyEncryption/SecureConnectionString.cs b/Core/MultiKeyEncryption/SecureConnectionString.cs
new file mode 100644
index 0000000..d746e3c
--- /dev/null
+++ b/Core/MultiKeyEncryption/SecureConnectionString.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Core.CryptoService
+{
+ public class SecureConnectionString
+ {
+ const string _masterKey = "5AFD74B1C26E87FE6656099E850DC67A";
+
+ public class EncryptedData
+ {
+ public string EncryptedConnectionString { get; set; }
+ public Dictionary UserMasterKeys { get; set; } = new();
+ }
+
+ public EncryptedData EncryptConnectionString(string connectionString)
+ {
+ var encryptedConnString = EncryptWithKey(connectionString, _masterKey);
+ var userKeys = new Dictionary();
+
+
+
+ return new EncryptedData
+ {
+ EncryptedConnectionString = encryptedConnString,
+ UserMasterKeys = userKeys
+ };
+ }
+
+ public string AddNewUser(string username, string password)
+ {
+ var userKey = DeriveKeyFromPassword(password);
+ var encryptedMasterKey = EncryptWithKey(_masterKey, userKey);
+ return encryptedMasterKey;
+ }
+
+ public string Decrypt(string encryptedConnString, string encryptedMasterKey, string password)
+ {
+ var userKey = DeriveKeyFromPassword(password);
+ var masterKey = DecryptWithKey(encryptedMasterKey, userKey);
+ return DecryptWithKey(encryptedConnString, masterKey);
+ }
+
+ private string DeriveKeyFromPassword(string password)
+ {
+ using var deriveBytes = new Rfc2898DeriveBytes(
+ password,
+ new byte[16], // Fast salt for simpelhed - i produktion bør dette være unikt per bruger
+ 10000,
+ HashAlgorithmName.SHA256);
+
+ return Convert.ToBase64String(deriveBytes.GetBytes(32));
+ }
+
+ private string EncryptWithKey(string value, string key)
+ {
+ using var aes = Aes.Create();
+ var keyBytes = Convert.FromBase64String(key);
+ aes.Key = keyBytes;
+ aes.GenerateIV();
+
+ using var encryptor = aes.CreateEncryptor();
+ var valueBytes = Encoding.UTF8.GetBytes(value);
+ var encrypted = encryptor.TransformFinalBlock(valueBytes, 0, valueBytes.Length);
+
+ var result = new byte[aes.IV.Length + encrypted.Length];
+ Array.Copy(aes.IV, 0, result, 0, aes.IV.Length);
+ Array.Copy(encrypted, 0, result, aes.IV.Length, encrypted.Length);
+
+ return Convert.ToBase64String(result);
+ }
+
+ private string DecryptWithKey(string encryptedValue, string key)
+ {
+ var encryptedBytes = Convert.FromBase64String(encryptedValue);
+ using var aes = Aes.Create();
+
+ var keyBytes = Convert.FromBase64String(key);
+ aes.Key = keyBytes;
+
+ var iv = new byte[16];
+ Array.Copy(encryptedBytes, 0, iv, 0, iv.Length);
+ aes.IV = iv;
+
+ using var decryptor = aes.CreateDecryptor();
+ var decrypted = decryptor.TransformFinalBlock(
+ encryptedBytes,
+ iv.Length,
+ encryptedBytes.Length - iv.Length);
+
+ return Encoding.UTF8.GetString(decrypted);
+ }
+ }
+}
diff --git a/Database/Core/DCL/SetupApplicationUser.cs b/Database/Core/DCL/SetupApplicationUser.cs
index d90977b..f4236ff 100644
--- a/Database/Core/DCL/SetupApplicationUser.cs
+++ b/Database/Core/DCL/SetupApplicationUser.cs
@@ -25,11 +25,7 @@ namespace Database.Core.DCL
{
_db = db;
}
-
- public void Setup(string schema = null)
- {
- throw new NotImplementedException();
- }
+
public void With(Command command)
{
_command = command;
diff --git a/Database/Core/DCL/SetupDbAdmin.cs b/Database/Core/DCL/SetupDbAdmin.cs
new file mode 100644
index 0000000..e929faa
--- /dev/null
+++ b/Database/Core/DCL/SetupDbAdmin.cs
@@ -0,0 +1,119 @@
+using System.Data;
+using Database.Common;
+using Insight.Database;
+
+namespace Database.Core.DCL
+{
+
+ ///
+ /// Only a superadmin or similar can create Application Users
+ ///
+ public class SetupDbAdmin : IDbConfigure
+ {
+ public class Command
+ {
+ public required string Schema { get; init; }
+ public required string User { get; init; }
+ public required string Password { get; init; }
+ }
+
+
+ IDbConnection _db;
+ Command _command;
+
+ public SetupDbAdmin(IDbConnection db)
+ {
+ _db = db;
+ }
+
+
+ public void With(Command command)
+ {
+ _command = command;
+
+ if (!Validations.IsValidSchemaName(_command.Schema))
+ throw new ArgumentException("Invalid schema name", _command.Schema);
+
+ using (var transaction = _db.OpenWithTransaction())
+ {
+ 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 {_command.Schema}";
+ ExecuteSql(sql);
+ }
+
+ private void CreateRole()
+ {
+ var sql = $@"
+ DO $$
+ BEGIN
+ IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '{_command.User}') THEN
+ CREATE ROLE {_command.User} WITH CREATEDB CREATEROLE LOGIN PASSWORD '{_command.Password}';
+ END IF;
+ END $$;";
+ ExecuteSql(sql);
+
+ var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';";
+ ExecuteSql(sql1);
+
+ var sql2 = $"ALTER SCHEMA {_command.Schema} OWNER TO {_command.User};";
+ ExecuteSql(sql2);
+
+ }
+
+ private void GrantSchemaRights()
+ {
+ // Grant USAGE og alle CREATE rettigheder på schema niveau
+ //GRANT USAGE ON SCHEMA {_command.Schema} TO {_command.User};
+ var sql = $@"
+ GRANT CREATE ON SCHEMA {_command.Schema} TO {_command.User};";
+
+ ExecuteSql(sql);
+
+ // Grant rettigheder på eksisterende og fremtidige tabeller
+ //var sql1 = $"GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA {_command.Schema} TO {_command.User};";
+ //ExecuteSql(sql1);
+
+ //var sql2 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT ALL PRIVILEGES ON TABLES TO {_command.User};";
+ //ExecuteSql(sql2);
+
+ //// Grant sequence rettigheder
+ //var sql3 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_command.Schema} TO {_command.User};";
+ //ExecuteSql(sql3);
+
+ //// Grant execute på functions
+ //var sql4 = $"GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA {_command.Schema} TO {_command.User};";
+ //ExecuteSql(sql4);
+
+ //// Grant for fremtidige functions
+ //var sql5 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT EXECUTE ON FUNCTIONS TO {_command.User};";
+ //ExecuteSql(sql5);
+
+ //// Grant for fremtidige sequences
+ //var sql6 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT USAGE ON SEQUENCES TO {_command.User};";
+ //ExecuteSql(sql6);
+ }
+
+ }
+}
diff --git a/Database/Core/DDL/SetupIdentitySystem.cs b/Database/Core/DDL/SetupIdentitySystem.cs
index 2e39809..9ce0fba 100644
--- a/Database/Core/DDL/SetupIdentitySystem.cs
+++ b/Database/Core/DDL/SetupIdentitySystem.cs
@@ -3,63 +3,68 @@ using System.Data;
namespace Database.Core.DDL
{
- ///
- /// This is by purpose not async await
- /// It is intended that this is created with the correct Application User, which is why the schema name is omitted.
- ///
- public class SetupIdentitySystem : IDbConfigure
- {
- public class Command { }
+ ///
+ /// This is by purpose not async await
+ /// It is intended that this is created with the correct Application User, which is why the schema name is omitted.
+ ///
+ public class SetupIdentitySystem : IDbConfigure
+ {
+ public class Command
+ {
+ public required string Schema { get; init; }
+ }
- readonly IDbConnection _db;
- IDbTransaction _transaction = null;
- string _schema;
+ readonly IDbConnection _db;
+ IDbTransaction _transaction = null;
+ Command _command;
- public SetupIdentitySystem(IDbConnection db)
- {
- _db = db;
- }
+ public SetupIdentitySystem(IDbConnection db)
+ {
+ _db = db;
+ }
- ///
- /// Creates the system tables in the specified schema within a transaction.
- ///
- /// The schema name where the tables will be created.
- public void With(Command emptyByIntention)
- {
- using (_transaction = _db.OpenWithTransaction())
- {
- try
- {
- CreateUsersTable();
- CreateOrganizationsTable();
- CreateUserOrganizationsTable();
- SetupRLS();
+ ///
+ /// Creates the system tables in the specified schema within a transaction.
+ ///
+ /// The schema name where the tables will be created.
+ public void With(Command command)
+ {
+ _command = command;
- _transaction.Commit();
- }
- catch (Exception ex)
- {
- _transaction.Rollback();
- throw new InvalidOperationException("Failed to SetupIdentitySystem. Transaction is rolled back", ex);
- }
- }
- }
- private void ExecuteSql(string sql)
- {
- if (string.IsNullOrEmpty(sql))
- throw new ArgumentNullException(nameof(sql));
+ using (_transaction = _db.OpenWithTransaction())
+ {
+ try
+ {
+ CreateUsersTable();
+ CreateOrganizationsTable();
+ CreateUserOrganizationsTable();
+ SetupRLS();
- _db.ExecuteSql(sql);
- }
+ _transaction.Commit();
+ }
+ catch (Exception ex)
+ {
+ _transaction.Rollback();
+ throw new InvalidOperationException("Failed to SetupIdentitySystem. Transaction is rolled back", ex);
+ }
+ }
+ }
+ private void ExecuteSql(string sql)
+ {
+ if (string.IsNullOrEmpty(sql))
+ throw new ArgumentNullException(nameof(sql));
+
+ _db.ExecuteSql(sql);
+ }
- ///
- /// Creates the users table
- ///
- void CreateUsersTable()
- {
- var sql = @"
- CREATE TABLE IF NOT EXISTS users (
+ ///
+ /// Creates the users table
+ ///
+ void CreateUsersTable()
+ {
+ var sql = @$"
+ CREATE TABLE IF NOT EXISTS {_command.Schema}.users (
id SERIAL PRIMARY KEY,
email VARCHAR(256) NOT NULL UNIQUE,
password_hash VARCHAR(256) NOT NULL,
@@ -73,73 +78,73 @@ namespace Database.Core.DDL
last_login_at TIMESTAMPTZ NULL
);";
- ExecuteSql(sql);
+ ExecuteSql(sql);
- }
+ }
- ///
- /// Creates the organizations table
- ///
- void CreateOrganizationsTable()
- {
- var sql = @"
- CREATE TABLE IF NOT EXISTS organizations (
+ ///
+ /// Creates the organizations table
+ ///
+ void CreateOrganizationsTable()
+ {
+ var sql = @$"
+ CREATE TABLE IF NOT EXISTS {_command.Schema}.organizations (
id SERIAL PRIMARY KEY,
connection_string VARCHAR(500) NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
- created_by INTEGER NOT NULL REFERENCES users(id),
+ created_by INTEGER NOT NULL REFERENCES {_command.Schema}.users(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);";
- ExecuteSql(sql);
+ ExecuteSql(sql);
- }
+ }
- ///
- /// Creates the user_organizations table
- ///
- void CreateUserOrganizationsTable()
- {
- var sql = @"
- CREATE TABLE IF NOT EXISTS user_organizations (
- user_id INTEGER NOT NULL REFERENCES users(id),
- organization_id INTEGER NOT NULL REFERENCES organizations(id),
+ ///
+ /// Creates the user_organizations table
+ ///
+ void CreateUserOrganizationsTable()
+ {
+ var sql = @$"
+ CREATE TABLE IF NOT EXISTS {_command.Schema}.user_organizations (
+ user_id INTEGER NOT NULL REFERENCES {_command.Schema}.users(id),
+ organization_id INTEGER NOT NULL REFERENCES {_command.Schema}.organizations(id),
pin_code VARCHAR(10) NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, organization_id)
);";
- ExecuteSql(sql);
+ ExecuteSql(sql);
- }
+ }
- ///
- /// Sets up Row Level Security (RLS) for the organizations and user_organizations tables.
- ///
- void SetupRLS()
- {
- var sql = new[]
- {
- "ALTER TABLE organizations ENABLE ROW LEVEL SECURITY;",
- "ALTER TABLE user_organizations ENABLE ROW LEVEL SECURITY;",
- "DROP POLICY IF EXISTS organization_access ON organizations;",
- @"CREATE POLICY organization_access ON organizations
+ ///
+ /// Sets up Row Level Security (RLS) for the organizations and user_organizations tables.
+ ///
+ void SetupRLS()
+ {
+ var sql = new[]
+ {
+ $"ALTER TABLE {_command.Schema}.organizations ENABLE ROW LEVEL SECURITY;",
+ $"ALTER TABLE {_command.Schema}.user_organizations ENABLE ROW LEVEL SECURITY;",
+ $"DROP POLICY IF EXISTS organization_access ON {_command.Schema}.organizations;",
+ @$"CREATE POLICY organization_access ON {_command.Schema}.organizations
USING (id IN (
SELECT organization_id
- FROM user_organizations
+ FROM {_command.Schema}.user_organizations
WHERE user_id = current_setting('app.user_id', TRUE)::INTEGER
- ));",
- "DROP POLICY IF EXISTS user_organization_access ON user_organizations;",
- @"CREATE POLICY user_organization_access ON user_organizations
- USING (user_id = current_setting('app.user_id', TRUE)::INTEGER);"
- };
+ )) WITH CHECK (true);",
+ $"DROP POLICY IF EXISTS user_organization_access ON {_command.Schema}.user_organizations;",
+ @$"CREATE POLICY user_organization_access ON {_command.Schema}.user_organizations
+ USING (user_id = current_setting('app.user_id', TRUE)::INTEGER) WITH CHECK (true);"
+ };
- foreach (var statement in sql)
- {
- ExecuteSql(statement);
- }
- }
+ foreach (var statement in sql)
+ {
+ ExecuteSql(statement);
+ }
+ }
- }
+ }
}
\ No newline at end of file
diff --git a/SetupInfrastructure/Program.cs b/SetupInfrastructure/Program.cs
index af340fd..068aa9f 100644
--- a/SetupInfrastructure/Program.cs
+++ b/SetupInfrastructure/Program.cs
@@ -48,42 +48,49 @@ namespace SetupInfrastructure
{
Console.ForegroundColor = ConsoleColor.Green;
var sw = new Stopwatch();
- Console.Write("Database.Core.DCL.SetupApplicationUser...");
- sw.Start();
- var setupApplicationUser = _container.Resolve();
- setupApplicationUser.With(new Database.Core.DCL.SetupApplicationUser.Command { Password = "3911", Schema = "system", User = "sathumper" });
- Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms");
+
+ Console.Write("Database.Core.DCL.SetupDbAdmin...");
+ sw.Start();
+ var setupDbAdmin = _container.Resolve();
+ setupDbAdmin.With(new Database.Core.DCL.SetupDbAdmin.Command { Password = "3911", Schema = "system", User = "heimdall" });
+ Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms");
+
Console.WriteLine("::");
Console.WriteLine("::");
-
Console.Write("Database.Core.DDL.SetupIdentitySystem...");
sw.Restart();
+
//create new container with application user, we use that role from now.
- _container = new Startup().ConfigureContainer(new Startup.ConnectionStringTemplateParameters("sathumper", "3911"));
+ _container = new Startup().ConfigureContainer(new Startup.ConnectionStringTemplateParameters("heimdall", "3911"));
var setupIdentitySystem = _container.Resolve();
- setupIdentitySystem.With(new Database.Core.DDL.SetupIdentitySystem.Command());
+ setupIdentitySystem.With(new Database.Core.DDL.SetupIdentitySystem.Command { Schema = "system"});
Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms");
Console.WriteLine("::");
Console.WriteLine("::");
-
Console.Write("Database.ConfigurationManagementSystem.SetupConfiguration...");
sw.Restart();
var setupConfigurationSystem = _container.Resolve();
setupConfigurationSystem.With(new Database.ConfigurationManagementSystem.SetupConfiguration.Command());
Console.Write($"DONE, took: {sw.ElapsedMilliseconds} ms");
- // SetupConfiguration
+
+ Console.WriteLine("::");
+ Console.WriteLine("::");
+ Console.Write("Database.Core.DCL.SetupApplicationUser...");
+ sw.Start();
+ var setupApplicationUser = _container.Resolve();
+ setupApplicationUser.With(new Database.Core.DCL.SetupApplicationUser.Command { Password = "3911", Schema = "system", User = "sathumper" });
+ Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms");
+ //and a lot of other tables that we haven't defined yet
- //and a lot of other tables that we haven't defined yet
+ // input configurations!!! TODO:Missing
- // input configurations!!! TODO:Missing
-
- Console.ForegroundColor = _foregroundColor;
+ Console.ForegroundColor = _foregroundColor;
}
diff --git a/SqlManagement/.dbeaver/.project-metadata.json.bak b/SqlManagement/.dbeaver/.project-metadata.json.bak
index 91b0730..5119abe 100644
--- a/SqlManagement/.dbeaver/.project-metadata.json.bak
+++ b/SqlManagement/.dbeaver/.project-metadata.json.bak
@@ -1 +1 @@
-{"resources":{"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"}}}
\ No newline at end of file
+{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"}}}
\ No newline at end of file
diff --git a/SqlManagement/.dbeaver/project-metadata.json b/SqlManagement/.dbeaver/project-metadata.json
index f792e7c..3200961 100644
--- a/SqlManagement/.dbeaver/project-metadata.json
+++ b/SqlManagement/.dbeaver/project-metadata.json
@@ -1 +1 @@
-{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain","default-schema":"system"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01","default-schema":"public"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"}}}
\ No newline at end of file
+{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"}}}
\ No newline at end of file
diff --git a/SqlManagement/Scripts/Script.sql b/SqlManagement/Scripts/Script.sql
index e69de29..68ca72d 100644
--- a/SqlManagement/Scripts/Script.sql
+++ b/SqlManagement/Scripts/Script.sql
@@ -0,0 +1,40 @@
+
+GRANT USAGE ON SCHEMA "system" TO heimdall;
+GRANT CREATE ON SCHEMA "system" TO heimdall
+
+create schema "system"
+
+ ALTER DEFAULT PRIVILEGES FOR ROLE heimdall IN SCHEMA "system"
+GRANT ALL PRIVILEGES ON TABLES TO heimdall;
+
+-- Og for eksisterende tabeller
+GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA "system" TO heimdall;
+
+ ALTER TABLE susers OWNER TO db_admin;
+ GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA your_schema TO sathumper;
+
+
+ CREATE ROLE heimdall WITH LOGIN PASSWORD '3911';
+COMMENT ON ROLE heimdall IS 'Security auditor and guardian';
+drop role heimdall
+
+
+set role 'heimdall'
+ALTER ROLE heimdall SET search_path = "system"
+drop table system.foo
+
+SELECT CURRENT_ROLE;
+SELECT rolname FROM pg_roles
+select system_user()
+
+SET ROLE heimdall;
+RESET ALL; -- Nulstil alle sessionsvariabler til deres standardværdier
+SHOW search_path; -- Burde nu vise den konfigurerede værdi
+
+SHOW search_path;
+
+create table system.foos(id int)
+
+select * from system.foo
+
+
diff --git a/SqlManagement/Scripts/grant-privileges.sql b/SqlManagement/Scripts/grant-privileges.sql
index ec169fd..78bbc4d 100644
--- a/SqlManagement/Scripts/grant-privileges.sql
+++ b/SqlManagement/Scripts/grant-privileges.sql
@@ -19,9 +19,6 @@ WHERE useconfig IS NOT NULL
ALTER ROLE sathumper1 SET search_path='ss32'
-
- CREATE USER fm WITH PASSWORD 'asd'
- await _db.ExecuteAsync(sql);
\ No newline at end of file
diff --git a/Tests/PasswordHasherTest.cs b/Tests/PasswordHasherTest.cs
index a635ac2..512e706 100644
--- a/Tests/PasswordHasherTest.cs
+++ b/Tests/PasswordHasherTest.cs
@@ -5,12 +5,35 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.Logging;
using Core.Telemetry;
using Core.Entities.Users;
+using System.Diagnostics;
+using Sodium;
namespace Tests
{
[TestClass]
public class PasswordHasherTests : TestFixture
{
+
+ [TestMethod]
+ public void MyTestMethod()
+ {
+ var stopwatch = Stopwatch.StartNew();
+
+ byte[] salt = PasswordHash.ScryptGenerateSalt();
+
+ // 2. Konverter password til byte[]
+ byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes("password123");
+
+ // 3. Kald ScryptHashBinary korrekt
+ byte[] hash = PasswordHash.ScryptHashBinary(
+ password: passwordBytes,
+ salt: salt, // 32-byte array
+ limit: PasswordHash.Strength.Interactive,
+ outputLength: 32
+ );
+
+ stopwatch.Stop();
+ }
[TestMethod]
public void HashPassword_ShouldCreateValidHashFormat()
{
@@ -23,7 +46,7 @@ namespace Tests
// Assert
Assert.AreEqual(3, parts.Length);
- Assert.AreEqual("100000", parts[0]);
+ Assert.AreEqual("600000", parts[0]);
}
[TestMethod]
diff --git a/Tests/PostgresTests.cs b/Tests/PostgresTests.cs
index 61be7c2..956f2af 100644
--- a/Tests/PostgresTests.cs
+++ b/Tests/PostgresTests.cs
@@ -39,10 +39,12 @@ namespace Tests
);
}
var logger = Container.Resolve();
-
+
+
for (int i = 0; i < 5; i++)
{
- logger.TrackTrace("Hello 23" , Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
+
+ logger.TrackTrace("Hello 23", Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
}
diff --git a/Tests/SecureConnectionStringTests.cs b/Tests/SecureConnectionStringTests.cs
new file mode 100644
index 0000000..40d1549
--- /dev/null
+++ b/Tests/SecureConnectionStringTests.cs
@@ -0,0 +1,11 @@
+using Autofac;
+using System.Data;
+using Insight.Database;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.Extensions.Logging;
+using Core.Telemetry;
+
+namespace Tests
+{
+
+}
\ No newline at end of file
diff --git a/Tests/TestFixture.cs b/Tests/TestFixture.cs
index 0c9cf5a..fdb8df0 100644
--- a/Tests/TestFixture.cs
+++ b/Tests/TestFixture.cs
@@ -26,19 +26,12 @@ namespace Tests
return configuration;
}
- ///
- /// Should not be overriden. Rather override PreArrangeAll to setup data needed for a test class.
- /// Override PrebuildContainer with a method that does nothing to prevent early build of IOC container
- ///
- [TestInitialize]
- public void Setup()
+ protected TestFixture()
{
CreateContainerBuilder();
Container = ContainerBuilder.Build();
-
}
-
protected virtual void CreateContainerBuilder()
{
IConfigurationRoot configuration = Configuration();