-- =========== -- Users & Plans -- =========== -- A function to automatically update 'updated_at' columns CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ language 'plpgsql'; CREATE TABLE users ( id SERIAL PRIMARY KEY, email TEXT NOT NULL UNIQUE, username TEXT, hashed_password TEXT NOT NULL, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE plans ( id SERIAL PRIMARY KEY, name TEXT NOT NULL UNIQUE, -- 'Free', 'Pro', 'Enterprise' -- Features des Plans als JSONB. Flexibel und indizierbar. features JSONB NOT NULL, stripe_price_id TEXT UNIQUE, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP ); -- =========== -- Tenancy (Workspaces & Members) -- =========== CREATE TABLE workspaces ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, owner_id INTEGER NOT NULL REFERENCES users (id), plan_id INTEGER NOT NULL REFERENCES plans (id), subscription_status TEXT NOT NULL, -- z.B. 'active', 'trialing' created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE workspace_members ( user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, workspace_id INTEGER NOT NULL REFERENCES workspaces (id) ON DELETE CASCADE, role_id INTEGER NOT NULL REFERENCES roles (id), joined_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, workspace_id) ); -- =========== -- RBAC (Roles & Permissions) -- =========== CREATE TABLE roles ( id SERIAL PRIMARY KEY, name TEXT NOT NULL UNIQUE -- 'Workspace Owner', 'Admin', 'Developer', 'Viewer' ); CREATE TABLE permissions ( id SERIAL PRIMARY KEY, action TEXT NOT NULL UNIQUE, -- 'project:create', 'route:delete', etc. description TEXT ); CREATE TABLE role_permissions ( role_id INTEGER NOT NULL REFERENCES roles (id) ON DELETE CASCADE, permission_id INTEGER NOT NULL REFERENCES permissions (id) ON DELETE CASCADE, PRIMARY KEY (role_id, permission_id) ); -- =========== -- Product Logic (Projects & Routes) -- =========== CREATE TABLE projects ( id SERIAL PRIMARY KEY, workspace_id INTEGER NOT NULL REFERENCES workspaces (id) ON DELETE CASCADE, name TEXT NOT NULL, description TEXT, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE routes ( id SERIAL PRIMARY KEY, project_id INTEGER NOT NULL REFERENCES projects (id) ON DELETE CASCADE, -- Matching Rules method TEXT NOT NULL, path TEXT NOT NULL, request_body_contains TEXT, -- Protocol Dispatcher protocol TEXT NOT NULL CHECK (protocol IN ('REST_JSON', 'GRAPHQL', 'RAW_BYTESTREAM', 'JSON_RPC')), schema_definition TEXT, -- Response Definition response_mode TEXT NOT NULL CHECK (response_mode IN ('STATIC', 'DYNAMIC')) DEFAULT 'STATIC', response_script TEXT, status_code INTEGER NOT NULL DEFAULT 200, -- JSONB für Header und Text für Body response_headers JSONB, response_body TEXT, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP ); -- =========== -- Indizes für schnelle Abfragen (Syntax is the same) -- =========== CREATE INDEX idx_workspaces_owner_id ON workspaces (owner_id); CREATE INDEX idx_projects_workspace_id ON projects (workspace_id); CREATE INDEX idx_routes_project_id ON routes (project_id); -- =========== -- Trigger to auto-update 'updated_at' fields -- Apply this to all tables that have the 'updated_at' column -- =========== CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column(); CREATE TRIGGER update_plans_updated_at BEFORE UPDATE ON plans FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column(); CREATE TRIGGER update_workspaces_updated_at BEFORE UPDATE ON workspaces FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column(); CREATE TRIGGER update_projects_updated_at BEFORE UPDATE ON projects FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column(); CREATE TRIGGER update_routes_updated_at BEFORE UPDATE ON routes FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();