Added tech base model
This commit is contained in:
@@ -17,8 +17,6 @@ var app = builder.Build();
|
||||
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
context.Database.EnsureCreated();
|
||||
var migrationService = scope.ServiceProvider.GetRequiredService<MigrationService>();
|
||||
await migrationService.Migrate();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using dc_bot.db.Model;
|
||||
using dc_bot.db.Model.administration;
|
||||
using dc_bot.db.Model.administration;
|
||||
using dc_bot.db.Model.permission;
|
||||
using dc_bot.db.Model.system;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@@ -8,19 +8,17 @@ namespace dc_bot.db;
|
||||
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
|
||||
{
|
||||
public required DbSet<ExecutedMigration> ExecutedMigrations { get; set; }
|
||||
|
||||
public required DbSet<User> Users { get; set; }
|
||||
public required DbSet<ApiKey> ApiKeys { get; set; }
|
||||
|
||||
public required DbSet<Role> Roles { get; set; }
|
||||
public required DbSet<Permission> Permissions { get; set; }
|
||||
public required DbSet<RolePermission> RolePermissions { get; set; }
|
||||
public required DbSet<ApiKeyPermission> ApiKeyPermissions { get; set; }
|
||||
public required DbSet<RoleUser> RoleUsers { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<ExecutedMigration>(e =>
|
||||
{
|
||||
e.ToTable("_executed_migrations", "system");
|
||||
e.HasKey(e => e.MigrationId);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<User>(e =>
|
||||
{
|
||||
e.ToTable("users", "administration");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using dc_bot.db.Model.system;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace dc_bot.db;
|
||||
@@ -34,20 +34,21 @@ public class MigrationService
|
||||
using var scope = _scopeFactory.CreateScope();
|
||||
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
|
||||
await EnsureExecutedMigrationsTableExistsAsync(context);
|
||||
|
||||
var appliedMigrations = await context.ExecutedMigrations
|
||||
.Select(m => m.MigrationId)
|
||||
.ToListAsync();
|
||||
|
||||
var appliedMigrationNames = appliedMigrations
|
||||
.Select(m => m.Replace(".sql", string.Empty))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var migrations = GetMigrations()
|
||||
.Where(m => !appliedMigrationNames.Contains(m))
|
||||
var migrations = GetMigrations();
|
||||
var migrationsToApply = migrations
|
||||
.Where(m => !appliedMigrations.Contains(m.Replace(".sql", string.Empty)))
|
||||
.ToList();
|
||||
|
||||
foreach (var migration in migrations)
|
||||
foreach (var migration in migrationsToApply)
|
||||
{
|
||||
await using var transaction = await context.Database.BeginTransactionAsync();
|
||||
|
||||
try
|
||||
{
|
||||
var migrationPath = Path.Combine(MigrationDirectory, migration);
|
||||
@@ -57,18 +58,59 @@ public class MigrationService
|
||||
|
||||
var executedMigration = new ExecutedMigration
|
||||
{
|
||||
MigrationId = migration,
|
||||
MigrationId = migration.Replace(".sql", string.Empty),
|
||||
Created = DateTime.UtcNow,
|
||||
Updated = DateTime.UtcNow
|
||||
};
|
||||
context.ExecutedMigrations.Add(executedMigration);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error applying migration {migration}: {ex.Message}");
|
||||
try
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
Console.WriteLine($"Error applying migration: {migration} => {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task EnsureExecutedMigrationsTableExistsAsync(AppDbContext context)
|
||||
{
|
||||
var entityType = context.Model.FindEntityType(typeof(ExecutedMigration));
|
||||
if (entityType == null)
|
||||
return;
|
||||
|
||||
var schema = entityType.GetSchema() ?? "public";
|
||||
var tableName = entityType.GetTableName() ?? entityType.GetDefaultTableName();
|
||||
|
||||
// Spaltennamen ermitteln (relational)
|
||||
var storeIdentifier = StoreObjectIdentifier.Table(tableName, schema);
|
||||
string migrationIdCol = entityType.FindProperty(nameof(ExecutedMigration.MigrationId))
|
||||
.GetColumnName(storeIdentifier);
|
||||
string createdCol = entityType.FindProperty(nameof(ExecutedMigration.Created))
|
||||
.GetColumnName(storeIdentifier);
|
||||
string updatedCol = entityType.FindProperty(nameof(ExecutedMigration.Updated))
|
||||
.GetColumnName(storeIdentifier);
|
||||
|
||||
var createSchemaSql = $"CREATE SCHEMA IF NOT EXISTS \"{schema}\";";
|
||||
var createTableSql = $@"
|
||||
CREATE TABLE IF NOT EXISTS ""{schema}"".""{tableName}"" (
|
||||
""{migrationIdCol}"" TEXT PRIMARY KEY,
|
||||
""{createdCol}"" TIMESTAMPTZ NOT NULL,
|
||||
""{updatedCol}"" TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
";
|
||||
|
||||
await context.Database.ExecuteSqlRawAsync(createSchemaSql + createTableSql);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,9 @@ namespace dc_bot.db.Model;
|
||||
|
||||
public interface IDbModel
|
||||
{
|
||||
public double Id { get; set; }
|
||||
public bool Deleted { get; set; }
|
||||
public Double EditorId { get; set; }
|
||||
public double EditorId { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public DateTimeOffset Updated { get; set; }
|
||||
}
|
||||
16
api/dc_bot.API/dc_bot.db/Model/administration/ApiKey.cs
Normal file
16
api/dc_bot.API/dc_bot.db/Model/administration/ApiKey.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace dc_bot.db.Model.administration;
|
||||
|
||||
[Table("api_keys", Schema = "administration")]
|
||||
public class ApiKey : IDbModel
|
||||
{
|
||||
public double Id { get; set; }
|
||||
public required string Identifier { get; init; }
|
||||
public required string Key { get; init; }
|
||||
|
||||
public bool Deleted { get; set; }
|
||||
public double EditorId { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public DateTimeOffset Updated { get; set; }
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace dc_bot.db.Model.administration;
|
||||
|
||||
[Table("users", Schema = "administration")]
|
||||
public class User : IDbModel
|
||||
{
|
||||
public Double Id { get; set; }
|
||||
public double Id { get; set; }
|
||||
public required string KeycloakId { get; init; }
|
||||
|
||||
public bool Deleted { get; set; }
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace dc_bot.db.Model.permission;
|
||||
|
||||
[Table("api_key_permissions", Schema = "permission")]
|
||||
public class ApiKeyPermission : IDbModel
|
||||
{
|
||||
public double Id { get; set; }
|
||||
public double ApiKeyId { get; set; }
|
||||
public double PermissionId { get; set; }
|
||||
|
||||
public bool Deleted { get; set; }
|
||||
public double EditorId { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public DateTimeOffset Updated { get; set; }
|
||||
}
|
||||
16
api/dc_bot.API/dc_bot.db/Model/permission/Permission.cs
Normal file
16
api/dc_bot.API/dc_bot.db/Model/permission/Permission.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace dc_bot.db.Model.permission;
|
||||
|
||||
[Table("permissions", Schema = "permission")]
|
||||
public class Permission : IDbModel
|
||||
{
|
||||
public double Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
public bool Deleted { get; set; }
|
||||
public double EditorId { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public DateTimeOffset Updated { get; set; }
|
||||
}
|
||||
16
api/dc_bot.API/dc_bot.db/Model/permission/Role.cs
Normal file
16
api/dc_bot.API/dc_bot.db/Model/permission/Role.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace dc_bot.db.Model.permission;
|
||||
|
||||
[Table("roles", Schema = "permission")]
|
||||
public class Role : IDbModel
|
||||
{
|
||||
public double Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
public bool Deleted { get; set; }
|
||||
public double EditorId { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public DateTimeOffset Updated { get; set; }
|
||||
}
|
||||
16
api/dc_bot.API/dc_bot.db/Model/permission/RolePermission.cs
Normal file
16
api/dc_bot.API/dc_bot.db/Model/permission/RolePermission.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace dc_bot.db.Model.permission;
|
||||
|
||||
[Table("role_permissions", Schema = "permission")]
|
||||
public class RolePermission : IDbModel
|
||||
{
|
||||
public double Id { get; set; }
|
||||
public double RoleId { get; set; }
|
||||
public double PermissionId { get; set; }
|
||||
|
||||
public bool Deleted { get; set; }
|
||||
public double EditorId { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public DateTimeOffset Updated { get; set; }
|
||||
}
|
||||
16
api/dc_bot.API/dc_bot.db/Model/permission/RoleUser.cs
Normal file
16
api/dc_bot.API/dc_bot.db/Model/permission/RoleUser.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace dc_bot.db.Model.permission;
|
||||
|
||||
[Table("role_users", Schema = "permission")]
|
||||
public class RoleUser : IDbModel
|
||||
{
|
||||
public double Id { get; set; }
|
||||
public double UserId { get; set; }
|
||||
public double PermissionId { get; set; }
|
||||
|
||||
public bool Deleted { get; set; }
|
||||
public double EditorId { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public DateTimeOffset Updated { get; set; }
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace dc_bot.db.Model.system;
|
||||
|
||||
[Table("_executed_migrations", Schema = "system")]
|
||||
[PrimaryKey(nameof(MigrationId))]
|
||||
public class ExecutedMigration
|
||||
{
|
||||
public required string MigrationId { get; set; }
|
||||
|
||||
@@ -4,6 +4,9 @@ CREATE SCHEMA IF NOT EXISTS system;
|
||||
CREATE TABLE IF NOT EXISTS system._executed_migrations
|
||||
(
|
||||
MigrationId VARCHAR(255) PRIMARY KEY,
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW()
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
DROP EXTENSION IF EXISTS fuzzystrmatch;
|
||||
CREATE EXTENSION fuzzystrmatch SCHEMA public;
|
||||
@@ -6,13 +6,15 @@ CREATE TABLE IF NOT EXISTS administration.users
|
||||
KeycloakId UUID NOT NULL,
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId INT NULL REFERENCES administration.users (Id),
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT UC_KeycloakId UNIQUE (KeycloakId)
|
||||
Updated timestamptz NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS IX_UC_KeycloakId
|
||||
ON administration.users (KeycloakId)
|
||||
WHERE KeycloakId != '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS administration.users_history
|
||||
(
|
||||
LIKE administration.users
|
||||
@@ -0,0 +1,105 @@
|
||||
CREATE SCHEMA IF NOT EXISTS permission;
|
||||
|
||||
-- Permissions
|
||||
CREATE TABLE permission.permissions
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
Name VARCHAR(255) NOT NULL,
|
||||
Description TEXT NULL,
|
||||
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT UQ_PermissionName UNIQUE (Name)
|
||||
);
|
||||
|
||||
CREATE TABLE permission.permissions_history
|
||||
(
|
||||
LIKE permission.permissions
|
||||
);
|
||||
|
||||
CREATE TRIGGER versioning_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON permission.permissions
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE public.history_trigger_function();
|
||||
|
||||
-- Roles
|
||||
CREATE TABLE permission.roles
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
Name VARCHAR(255) NOT NULL,
|
||||
Description TEXT NULL,
|
||||
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT UQ_RoleName UNIQUE (Name)
|
||||
);
|
||||
|
||||
CREATE TABLE permission.roles_history
|
||||
(
|
||||
LIKE permission.roles
|
||||
);
|
||||
|
||||
CREATE TRIGGER versioning_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON permission.roles
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE public.history_trigger_function();
|
||||
|
||||
-- Role permissions
|
||||
CREATE TABLE permission.role_permissions
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
RoleId BIGINT NOT NULL REFERENCES permission.roles (Id) ON DELETE CASCADE,
|
||||
PermissionId BIGINT NOT NULL REFERENCES permission.permissions (Id) ON DELETE CASCADE,
|
||||
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT UQ_RolePermission UNIQUE (RoleId, PermissionId)
|
||||
);
|
||||
|
||||
CREATE TABLE permission.role_permissions_history
|
||||
(
|
||||
LIKE permission.role_permissions
|
||||
);
|
||||
|
||||
CREATE TRIGGER versioning_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON permission.role_permissions
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE public.history_trigger_function();
|
||||
|
||||
-- Role user
|
||||
CREATE TABLE permission.role_users
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
RoleId BIGINT NOT NULL REFERENCES permission.roles (Id) ON DELETE CASCADE,
|
||||
UserId BIGINT NOT NULL REFERENCES administration.users (Id) ON DELETE CASCADE,
|
||||
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT UQ_RoleUser UNIQUE (RoleId, UserId)
|
||||
);
|
||||
|
||||
CREATE TABLE permission.role_users_history
|
||||
(
|
||||
LIKE permission.role_users
|
||||
);
|
||||
|
||||
CREATE TRIGGER versioning_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON permission.role_users
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE public.history_trigger_function();
|
||||
@@ -0,0 +1,50 @@
|
||||
CREATE TABLE IF NOT EXISTS administration.api_keys
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
Identifier VARCHAR(255) NOT NULL,
|
||||
KeyString VARCHAR(255) NOT NULL,
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT UC_Identifier_Key UNIQUE (Identifier, KeyString),
|
||||
CONSTRAINT UC_Key UNIQUE (KeyString)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS administration.api_keys_history
|
||||
(
|
||||
LIKE administration.api_keys
|
||||
);
|
||||
|
||||
CREATE TRIGGER api_keys_history_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON administration.api_keys
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.history_trigger_function();
|
||||
|
||||
CREATE TABLE permission.api_key_permissions
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
ApiKeyId BIGINT NOT NULL REFERENCES administration.api_keys (Id) ON DELETE CASCADE,
|
||||
PermissionId BIGINT NOT NULL REFERENCES permission.permissions (Id) ON DELETE CASCADE,
|
||||
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT UQ_ApiKeyPermission UNIQUE (ApiKeyId, PermissionId)
|
||||
);
|
||||
|
||||
CREATE TABLE permission.api_key_permissions_history
|
||||
(
|
||||
LIKE permission.api_key_permissions
|
||||
);
|
||||
|
||||
CREATE TRIGGER versioning_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON permission.api_key_permissions
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE public.history_trigger_function();
|
||||
@@ -0,0 +1,26 @@
|
||||
CREATE SCHEMA IF NOT EXISTS system;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS system.settings
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
Key TEXT NOT NULL,
|
||||
Value TEXT NOT NULL,
|
||||
Type TEXT NOT NULL DEFAULT 'string' CHECK (type IN ('string', 'number', 'boolean')),
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT UC_Key UNIQUE (Key)
|
||||
);
|
||||
|
||||
CREATE TABLE system.settings_history
|
||||
(
|
||||
LIKE system.settings
|
||||
);
|
||||
|
||||
CREATE TRIGGER settings_history_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON system.settings
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.history_trigger_function();
|
||||
@@ -0,0 +1,25 @@
|
||||
CREATE SCHEMA IF NOT EXISTS system;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS system.feature_flags
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
Key TEXT NOT NULL,
|
||||
Value BOOLEAN NOT NULL,
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT UQ_FeatureFlagKey UNIQUE (Key)
|
||||
);
|
||||
|
||||
CREATE TABLE system.feature_flags_history
|
||||
(
|
||||
LIKE system.feature_flags
|
||||
);
|
||||
|
||||
CREATE TRIGGER feature_flags_history_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON system.feature_flags
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.history_trigger_function();
|
||||
@@ -0,0 +1,26 @@
|
||||
CREATE SCHEMA IF NOT EXISTS public;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.user_settings
|
||||
(
|
||||
Id SERIAL PRIMARY KEY,
|
||||
Key TEXT NOT NULL,
|
||||
Value TEXT NOT NULL,
|
||||
UserId BIGINT NOT NULL REFERENCES administration.users (Id) ON DELETE CASCADE,
|
||||
-- for history
|
||||
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
EditorId BIGINT NULL REFERENCES administration.users (Id),
|
||||
Created timestamptz NOT NULL DEFAULT NOW(),
|
||||
Updated timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT UQ_UserSetting UNIQUE (UserId, Key)
|
||||
);
|
||||
|
||||
CREATE TABLE public.user_settings_history
|
||||
(
|
||||
LIKE public.user_settings
|
||||
);
|
||||
|
||||
CREATE TRIGGER user_settings_history_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE
|
||||
ON public.user_settings
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.history_trigger_function();
|
||||
@@ -10,6 +10,36 @@
|
||||
<None Update="Scripts\**">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-06-01-15-api_keys.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-06-01-16-permissions.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-06-01-19-user-settings.sql">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-05-21-15-users.sql">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-05-21-05-inital-migration.sql">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-05-21-10-inital-trigger.sql">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-06-01-15-permissions.sql">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-06-01-16-api-keys.sql">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-06-01-17-settings.sql">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scripts\2026-01-06-01-18-feature-flags.sql">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user