diff --git a/SqlManagement/.dbeaver/project-metadata.json b/SqlManagement/.dbeaver/project-metadata.json index a63e45b..e83d733 100644 --- a/SqlManagement/.dbeaver/project-metadata.json +++ b/SqlManagement/.dbeaver/project-metadata.json @@ -1 +1 @@ -{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-19484872d85-cd2a4a40116e706","default-catalog":"ptdb01","default-schema":"ptmain"},"Scripts/Script-2.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-2.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"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","default-schema":"ptmain"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"}}} \ No newline at end of file diff --git a/SqlManagement/Scripts/Script-1.sql b/SqlManagement/Scripts/Script-1.sql deleted file mode 100644 index e69de29..0000000 diff --git a/SqlManagement/Scripts/Script.sql b/SqlManagement/Scripts/Script.sql index 741ad02..e69de29 100644 --- a/SqlManagement/Scripts/Script.sql +++ b/SqlManagement/Scripts/Script.sql @@ -1,9 +0,0 @@ -CREATE TABLE IF NOT EXISTS swp.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 -); \ No newline at end of file diff --git a/SqlManagement/Scripts/SmartConfigSystem.sql b/SqlManagement/Scripts/SmartConfigSystem.sql new file mode 100644 index 0000000..75cabae --- /dev/null +++ b/SqlManagement/Scripts/SmartConfigSystem.sql @@ -0,0 +1,179 @@ + +drop schema "public" +show search_path; + +set schema "ptmain"; + +CREATE SCHEMA if not exists ptmain; +GRANT USAGE, CREATE ON SCHEMA ptmain TO sathumper; +GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA ptmain TO sathumper; +GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA ptmain TO sathumper; + +ALTER DEFAULT PRIVILEGES IN SCHEMA ptmain +GRANT ALL PRIVILEGES ON TABLES TO sathumper; + + +-- Create schema if not exists + +insert into +-- Create main configuration table +CREATE TABLE app_configuration ( + id BIGSERIAL PRIMARY KEY, + key VARCHAR(255) NOT NULL, + value TEXT NOT NULL, + label VARCHAR(255), + content_type VARCHAR(255) DEFAULT 'text/plain', + valid_from TIMESTAMPTZ, + expires_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + modified_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + etag UUID DEFAULT gen_random_uuid(), + CONSTRAINT app_configuration_key_unique UNIQUE (key, valid_from) +); + +-- Create history table +CREATE TABLE app_configuration_history ( + history_id BIGSERIAL PRIMARY KEY, + operation CHAR(1) NOT NULL, -- I = Insert, U = Update, D = Delete + changed_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + changed_by TEXT NOT NULL DEFAULT CURRENT_USER, + -- Original columns + id BIGINT NOT NULL, + key VARCHAR(255) NOT NULL, + value TEXT NOT NULL, + label VARCHAR(255), + content_type VARCHAR(255), + valid_from TIMESTAMPTZ, + expires_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL, + modified_at TIMESTAMPTZ NOT NULL, + etag UUID +); + + + +-- Create function for updating modified_at +CREATE OR REPLACE FUNCTION update_modified_at() +RETURNS TRIGGER AS $$ +BEGIN + NEW.modified_at = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- Create history tracking function +CREATE OR REPLACE FUNCTION track_configuration_history() +RETURNS TRIGGER AS $$ +BEGIN + -- Indsæt historikpost baseret på operationstypen + IF TG_OP = 'INSERT' THEN + INSERT INTO app_configuration_history( + operation, + id, key, value, label, content_type, valid_from, expires_at, + created_at, modified_at, etag + ) + VALUES ( + 'I', + NEW.id, NEW.key, NEW.value, NEW.label, NEW.content_type, NEW.valid_from, + NEW.expires_at, NEW.created_at, NEW.modified_at, NEW.etag + ); + ELSIF TG_OP = 'UPDATE' OR TG_OP = 'DELETE' THEN + -- Brug OLD for både UPDATE og DELETE + INSERT INTO app_configuration_history( + operation, + id, key, value, label, content_type, valid_from, expires_at, + created_at, modified_at, etag + ) + VALUES ( + CASE + WHEN TG_OP = 'UPDATE' THEN 'U' + WHEN TG_OP = 'DELETE' THEN 'D' + END, + OLD.id, OLD.key, OLD.value, OLD.label, OLD.content_type, OLD.valid_from, + OLD.expires_at, OLD.created_at, OLD.modified_at, OLD.etag + ); + END IF; + + -- Returner NULL for AFTER-trigger + RETURN NULL; +EXCEPTION + WHEN others THEN + -- Log fejl og rejs undtagelse + RAISE EXCEPTION 'Fejl i track_configuration_history: %', SQLERRM; +END; +$$ LANGUAGE plpgsql; + +-- Create triggers +CREATE TRIGGER trg_app_configuration_modified_at + BEFORE UPDATE ON app_configuration + FOR EACH ROW + EXECUTE FUNCTION update_modified_at(); + +CREATE TRIGGER trg_app_configuration_history + AFTER INSERT OR UPDATE OR DELETE ON app_configuration + FOR EACH ROW + EXECUTE FUNCTION track_configuration_history(); + +CREATE TRIGGER trg_app_configuration_notify + AFTER INSERT OR UPDATE ON app_configuration + FOR EACH ROW + EXECUTE FUNCTION notify_config_change(); + +-- Comments +COMMENT ON TABLE app_configuration IS 'Application configuration with temporal validity'; +COMMENT ON TABLE app_configuration_history IS 'Historical changes to application configuration'; +COMMENT ON COLUMN app_configuration_history.operation IS 'Type of operation: I=Insert, U=Update, D=Delete'; +COMMENT ON COLUMN app_configuration_history.changed_at IS 'When the change occurred'; +COMMENT ON COLUMN app_configuration_history.changed_by IS 'User who made the change'; + + +```sql +-- Email templates configuration +INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES +('Email:Templates:Welcome', + '{"subject":"Velkommen til vores platform","template":"welcome-dk.html","sender":"velkommen@firma.dk"}', + 'Email Templates', + 'application/json', + '2024-01-01T00:00:00Z', + NULL); +select * from app_configuration_history +update app_configuration +set label = 'test' + +INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES +('Email:Templates:Password', + '{"subject":"Nulstil dit kodeord","template":"reset-password-dk.html","sender":"support@firma.dk"}', + 'Email Templates', + 'application/json', + '2024-01-01T00:00:00Z', + NULL); + +-- API configuration +INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES +('Api:Endpoints:BaseUrl', + '{"production":"https://api.firma.dk","staging":"https://staging-api.firma.dk"}', + 'API Settings', + 'application/json', + '2024-01-01T00:00:00Z', + NULL); + +-- Feature flags +INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES +('Features:NewUI', + '{"enabled":false,"rolloutPercentage":0,"description":"New React based UI"}', + 'Feature Flags', + 'application/json', + '2024-02-01T00:00:00Z', + '2024-12-31T23:59:59Z'); + +-- System settings +INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES +('System:Cache', + '{"timeoutMinutes":15,"maxItems":1000,"distributed":true}', + 'System Settings', + 'application/json', + '2024-01-01T00:00:00Z', + NULL); +``` + +