2026-06-26 10:50:24 +02:00
|
|
|
|
-- Web CAD Backend – SQLite Schema
|
|
|
|
|
|
-- Version 1.0
|
|
|
|
|
|
|
|
|
|
|
|
PRAGMA journal_mode = WAL;
|
|
|
|
|
|
PRAGMA foreign_keys = ON;
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Users ──────────────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
email TEXT UNIQUE NOT NULL,
|
|
|
|
|
|
password_hash TEXT NOT NULL,
|
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
|
role TEXT NOT NULL DEFAULT 'planer' CHECK(role IN ('admin','planer','betrachter','gast')),
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Default User (seed) ────────────────────────────
|
|
|
|
|
|
INSERT OR IGNORE INTO users (id, email, password_hash, name, role) VALUES ('user-default', 'default@webcad.local', '', 'Default User', 'admin');
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Projects ───────────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS projects (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
owner_id TEXT NOT NULL,
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Drawings ───────────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS drawings (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
project_id TEXT NOT NULL,
|
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
|
data_json TEXT NOT NULL DEFAULT '{}',
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Layers ─────────────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS layers (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
drawing_id TEXT NOT NULL,
|
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
|
visible INTEGER NOT NULL DEFAULT 1,
|
|
|
|
|
|
locked INTEGER NOT NULL DEFAULT 0,
|
|
|
|
|
|
color TEXT NOT NULL DEFAULT '#ffffff',
|
|
|
|
|
|
line_type TEXT NOT NULL DEFAULT 'solid',
|
|
|
|
|
|
transparency REAL NOT NULL DEFAULT 0,
|
|
|
|
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
|
|
|
|
parent_id TEXT,
|
|
|
|
|
|
FOREIGN KEY (drawing_id) REFERENCES drawings(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Elements ───────────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS elements (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
drawing_id TEXT NOT NULL,
|
|
|
|
|
|
layer_id TEXT NOT NULL,
|
|
|
|
|
|
type TEXT NOT NULL,
|
|
|
|
|
|
x REAL NOT NULL,
|
|
|
|
|
|
y REAL NOT NULL,
|
|
|
|
|
|
width REAL NOT NULL,
|
|
|
|
|
|
height REAL NOT NULL,
|
|
|
|
|
|
properties_json TEXT NOT NULL DEFAULT '{}',
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (drawing_id) REFERENCES drawings(id) ON DELETE CASCADE,
|
|
|
|
|
|
FOREIGN KEY (layer_id) REFERENCES layers(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Block Definitions ──────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS blocks (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
drawing_id TEXT NOT NULL,
|
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
category TEXT NOT NULL DEFAULT 'Allgemein',
|
|
|
|
|
|
elements_json TEXT NOT NULL DEFAULT '[]',
|
|
|
|
|
|
thumbnail TEXT,
|
|
|
|
|
|
FOREIGN KEY (drawing_id) REFERENCES drawings(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-06-26 14:55:38 +02:00
|
|
|
|
-- ─── Sessions ──────────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
|
|
|
|
token TEXT PRIMARY KEY,
|
|
|
|
|
|
user_id TEXT NOT NULL,
|
|
|
|
|
|
expires_at INTEGER NOT NULL,
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-06-26 10:50:24 +02:00
|
|
|
|
-- ─── Settings ───────────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS settings (
|
|
|
|
|
|
key TEXT PRIMARY KEY,
|
|
|
|
|
|
value TEXT NOT NULL,
|
|
|
|
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-07-04 16:43:55 +02:00
|
|
|
|
-- ─── Project Folders ───────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS project_folders (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
|
parent_id TEXT,
|
|
|
|
|
|
owner_id TEXT NOT NULL,
|
|
|
|
|
|
created_at TEXT DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (parent_id) REFERENCES project_folders(id) ON DELETE CASCADE,
|
|
|
|
|
|
FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_project_folders_parent ON project_folders(parent_id);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_project_folders_owner ON project_folders(owner_id);
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Projects: add folder_id column ─────────────────────
|
|
|
|
|
|
-- NOTE: ALTER TABLE is idempotent-safe via try/catch in adapter; schema.sql
|
|
|
|
|
|
-- is only exec'd on fresh databases. For existing DBs, the adapter runs
|
|
|
|
|
|
-- the ALTER in init().
|
|
|
|
|
|
|
2026-06-26 10:50:24 +02:00
|
|
|
|
-- ─── Indexes ────────────────────────────────────────
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_drawings_project ON drawings(project_id);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_layers_drawing ON layers(drawing_id);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_elements_drawing ON elements(drawing_id);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_elements_layer ON elements(layer_id);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_blocks_drawing ON blocks(drawing_id);
|
2026-07-04 16:08:51 +02:00
|
|
|
|
|
|
|
|
|
|
-- ─── Notifications ───────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS notifications (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
user_id TEXT NOT NULL,
|
|
|
|
|
|
type TEXT NOT NULL DEFAULT 'info',
|
|
|
|
|
|
title TEXT NOT NULL,
|
|
|
|
|
|
message TEXT NOT NULL,
|
|
|
|
|
|
read INTEGER NOT NULL DEFAULT 0,
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Project Shares ──────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS project_shares (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
project_id TEXT NOT NULL,
|
|
|
|
|
|
shared_with_email TEXT NOT NULL,
|
|
|
|
|
|
shared_by TEXT NOT NULL,
|
|
|
|
|
|
permission TEXT NOT NULL DEFAULT 'view' CHECK(permission IN ('view','edit','admin')),
|
|
|
|
|
|
share_token TEXT UNIQUE,
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
|
|
|
|
FOREIGN KEY (shared_by) REFERENCES users(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications(user_id);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_shares_project ON project_shares(project_id);
|
2026-07-04 16:43:55 +02:00
|
|
|
|
|
|
|
|
|
|
-- ─── Global Block Folders ─────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS global_block_folders (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
|
parent_id TEXT,
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (parent_id) REFERENCES global_block_folders(id) ON DELETE CASCADE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
-- ─── Global Blocks ──────────────────────────────────────
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS global_blocks (
|
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
|
folder_id TEXT,
|
|
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
|
|
block_data TEXT NOT NULL DEFAULT '{}',
|
|
|
|
|
|
svg_data TEXT,
|
|
|
|
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
|
|
|
|
FOREIGN KEY (folder_id) REFERENCES global_block_folders(id) ON DELETE SET NULL
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_global_blocks_folder ON global_blocks(folder_id);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_global_block_folders_parent ON global_block_folders(parent_id);
|