diff --git a/backend/src/database/schema.sql b/backend/src/database/schema.sql new file mode 100644 index 0000000..81c8e44 --- /dev/null +++ b/backend/src/database/schema.sql @@ -0,0 +1,198 @@ +PRAGMA foreign_keys = ON; + +-- Users table +CREATE TABLE IF NOT EXISTS users ( + id TEXT PRIMARY KEY, + email TEXT UNIQUE NOT NULL, + password_hash TEXT NOT NULL, + display_name TEXT NOT NULL, + role TEXT NOT NULL DEFAULT 'planner', + is_active INTEGER NOT NULL DEFAULT 1, + created_at TEXT, + updated_at TEXT +); + +-- Sessions table +CREATE TABLE IF NOT EXISTS sessions ( + id TEXT PRIMARY KEY, + user_id TEXT NOT NULL REFERENCES users(id), + token_hash TEXT UNIQUE NOT NULL, + expires_at TEXT NOT NULL, + created_at TEXT, + ip_address TEXT, + user_agent TEXT +); + +-- Projects table +CREATE TABLE IF NOT EXISTS projects ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + description TEXT, + owner_id TEXT NOT NULL REFERENCES users(id), + units TEXT NOT NULL DEFAULT 'mm', + created_at TEXT NOT NULL DEFAULT datetime('now'), + updated_at TEXT NOT NULL DEFAULT datetime('now'), + thumbnail_path TEXT +); + +-- Project members table +CREATE TABLE IF NOT EXISTS project_members ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, + user_id TEXT NOT NULL REFERENCES users(id), + role TEXT NOT NULL DEFAULT 'betrachter', + invited_at TEXT, + accepted_at TEXT, + UNIQUE(project_id, user_id) +); + +-- Layers table +CREATE TABLE IF NOT EXISTS layers ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, + name TEXT NOT NULL, + visible INTEGER NOT NULL DEFAULT 1, + locked INTEGER NOT NULL DEFAULT 0, + color TEXT, + line_type TEXT, + transparency REAL NOT NULL DEFAULT 0.0, + sort_order INTEGER NOT NULL DEFAULT 0, + created_at TEXT +); + +-- Elements table +CREATE TABLE IF NOT EXISTS elements ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, + layer_id TEXT REFERENCES layers(id), + element_type TEXT NOT NULL, + geometry TEXT NOT NULL, + style TEXT, + metadata TEXT, + created_at TEXT, + updated_at TEXT +); + +-- Blocks table +CREATE TABLE IF NOT EXISTS blocks ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, + name TEXT UNIQUE NOT NULL, + base_element_ids TEXT NOT NULL, + created_at TEXT +); + +-- Block instances table +CREATE TABLE IF NOT EXISTS block_instances ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, + block_id TEXT NOT NULL REFERENCES blocks(id) ON DELETE CASCADE, + layer_id TEXT REFERENCES layers(id), + position_x REAL NOT NULL, + position_y REAL NOT NULL, + rotation REAL NOT NULL DEFAULT 0.0, + scale_x REAL NOT NULL DEFAULT 1.0, + scale_y REAL NOT NULL DEFAULT 1.0, + created_at TEXT +); + +-- Background images table +CREATE TABLE IF NOT EXISTS background_images ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, + file_path TEXT NOT NULL, + position_x REAL NOT NULL DEFAULT 0.0, + position_y REAL NOT NULL DEFAULT 0.0, + scale REAL NOT NULL DEFAULT 1.0, + rotation REAL NOT NULL DEFAULT 0.0, + opacity REAL NOT NULL DEFAULT 1.0, + created_at TEXT +); + +-- Versions table +CREATE TABLE IF NOT EXISTS versions ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, + label TEXT, + description TEXT, + snapshot_data BLOB NOT NULL, + created_by TEXT REFERENCES users(id), + created_at TEXT +); + +-- Plugins table +CREATE TABLE IF NOT EXISTS plugins ( + id TEXT PRIMARY KEY, + name TEXT UNIQUE NOT NULL, + version TEXT NOT NULL, + display_name TEXT NOT NULL, + description TEXT, + manifest TEXT NOT NULL, + is_active INTEGER NOT NULL DEFAULT 0, + installed_at TEXT, + activated_at TEXT +); + +-- Settings table +CREATE TABLE IF NOT EXISTS settings ( + id TEXT PRIMARY KEY, + user_id TEXT REFERENCES users(id), + key TEXT NOT NULL, + value TEXT NOT NULL, + updated_at TEXT, + UNIQUE(user_id, key) +); + +-- AI Config table +CREATE TABLE IF NOT EXISTS ai_config ( + id TEXT PRIMARY KEY, + scope TEXT NOT NULL, + project_id TEXT REFERENCES projects(id), + api_base_url TEXT, + api_key_encrypted TEXT, + model TEXT NOT NULL DEFAULT 'gpt-4o', + created_at TEXT, + updated_at TEXT +); + +-- Webhooks table +CREATE TABLE IF NOT EXISTS webhooks ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, + url TEXT NOT NULL, + event TEXT NOT NULL, + is_active INTEGER NOT NULL DEFAULT 1, + created_at TEXT +); + +-- Audit log table +CREATE TABLE IF NOT EXISTS audit_log ( + id TEXT PRIMARY KEY, + user_id TEXT REFERENCES users(id), + project_id TEXT REFERENCES projects(id), + action TEXT NOT NULL, + details TEXT, + ip_address TEXT, + created_at TEXT +); + +-- Indexes +CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id); +CREATE INDEX IF NOT EXISTS idx_sessions_token_hash ON sessions(token_hash); +CREATE INDEX IF NOT EXISTS idx_projects_owner_id ON projects(owner_id); +CREATE INDEX IF NOT EXISTS idx_project_members_project_id ON project_members(project_id); +CREATE INDEX IF NOT EXISTS idx_project_members_user_id ON project_members(user_id); +CREATE INDEX IF NOT EXISTS idx_layers_project_id ON layers(project_id); +CREATE INDEX IF NOT EXISTS idx_elements_project_id ON elements(project_id); +CREATE INDEX IF NOT EXISTS idx_elements_layer_id ON elements(layer_id); +CREATE INDEX IF NOT EXISTS idx_blocks_project_id ON blocks(project_id); +CREATE INDEX IF NOT EXISTS idx_block_instances_project_id ON block_instances(project_id); +CREATE INDEX IF NOT EXISTS idx_block_instances_block_id ON block_instances(block_id); +CREATE INDEX IF NOT EXISTS idx_background_images_project_id ON background_images(project_id); +CREATE INDEX IF NOT EXISTS idx_versions_project_id ON versions(project_id); +CREATE INDEX IF NOT EXISTS idx_versions_created_by ON versions(created_by); +CREATE INDEX IF NOT EXISTS idx_settings_user_id ON settings(user_id); +CREATE INDEX IF NOT EXISTS idx_ai_config_project_id ON ai_config(project_id); +CREATE INDEX IF NOT EXISTS idx_webhooks_project_id ON webhooks(project_id); +CREATE INDEX IF NOT EXISTS idx_audit_log_user_id ON audit_log(user_id); +CREATE INDEX IF NOT EXISTS idx_audit_log_project_id ON audit_log(project_id);