147 lines
6.4 KiB
SQL
147 lines
6.4 KiB
SQL
-- Papa-Kind-Treff – Basis-Schema (MySQL 8)
|
||
-- Hinweise:
|
||
-- - Passwörter mit Argon2id hashen.
|
||
-- - Sensible Felder werden app-seitig mit libsodium (XChaCha20-Poly1305) verschlüsselt
|
||
-- und als base64 in VARBINARY-Spalten abgelegt (nonce + cipher).
|
||
-- - share_level steuert Papa-Infos (basic, papa, papa_contact).
|
||
-- - children_visibility steuert Kinder-Infos separat (hidden, age_only, details).
|
||
|
||
CREATE TABLE users (
|
||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
email VARCHAR(255) NOT NULL UNIQUE,
|
||
password_hash VARCHAR(255) NOT NULL,
|
||
status ENUM('active','pending','blocked') DEFAULT 'pending',
|
||
email_verified_at DATETIME NULL,
|
||
last_login_at DATETIME NULL,
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
|
||
CREATE TABLE user_profiles (
|
||
user_id BIGINT UNSIGNED PRIMARY KEY,
|
||
display_name VARCHAR(120) NOT NULL,
|
||
first_name VARCHAR(120) NULL,
|
||
last_name VARCHAR(120) NULL,
|
||
share_level ENUM('basic','papa','papa_contact') NOT NULL DEFAULT 'basic',
|
||
children_visibility ENUM('hidden','age_only','details') NOT NULL DEFAULT 'hidden',
|
||
zip CHAR(5) NULL,
|
||
city VARCHAR(120) NULL,
|
||
region VARCHAR(120) NULL,
|
||
lat DECIMAL(10,7) NULL,
|
||
lng DECIMAL(10,7) NULL,
|
||
contact_phone VARBINARY(512) NULL,
|
||
contact_email VARBINARY(512) NULL,
|
||
profession VARBINARY(512) NULL,
|
||
languages VARBINARY(1024) NULL, -- JSON verschlüsselt
|
||
about VARBINARY(2048) NULL,
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
CONSTRAINT fk_profile_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||
INDEX idx_profile_city (city),
|
||
INDEX idx_profile_region (region),
|
||
INDEX idx_profile_latlng (lat,lng)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
|
||
CREATE TABLE children (
|
||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
user_id BIGINT UNSIGNED NOT NULL,
|
||
gender ENUM('male','female','diverse','unknown') NOT NULL DEFAULT 'unknown',
|
||
birthdate DATE NULL,
|
||
age_years TINYINT UNSIGNED NULL,
|
||
encrypted_first_name VARBINARY(512) NOT NULL,
|
||
note VARBINARY(1024) NULL,
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
CONSTRAINT fk_child_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||
INDEX idx_child_user (user_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
|
||
CREATE TABLE events (
|
||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
created_by BIGINT UNSIGNED NOT NULL,
|
||
title VARCHAR(200) NOT NULL,
|
||
teaser_public VARCHAR(280) NOT NULL,
|
||
description TEXT NOT NULL,
|
||
location_label VARCHAR(180) NULL,
|
||
street VARCHAR(180) NULL,
|
||
zip CHAR(5) NULL,
|
||
city VARCHAR(120) NULL,
|
||
region VARCHAR(120) NULL,
|
||
lat DECIMAL(10,7) NULL,
|
||
lng DECIMAL(10,7) NULL,
|
||
starts_at DATETIME NOT NULL,
|
||
ends_at DATETIME NULL,
|
||
max_participants SMALLINT UNSIGNED NULL,
|
||
allow_kids TINYINT(1) NOT NULL DEFAULT 1,
|
||
min_child_age TINYINT UNSIGNED NULL,
|
||
max_child_age TINYINT UNSIGNED NULL,
|
||
visibility ENUM('public','members') NOT NULL DEFAULT 'public',
|
||
status ENUM('draft','published','cancelled') NOT NULL DEFAULT 'published',
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
CONSTRAINT fk_event_user FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE,
|
||
INDEX idx_event_city (city),
|
||
INDEX idx_event_region (region),
|
||
INDEX idx_event_time (starts_at),
|
||
INDEX idx_event_latlng (lat,lng)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
|
||
CREATE TABLE event_participants (
|
||
event_id BIGINT UNSIGNED NOT NULL,
|
||
user_id BIGINT UNSIGNED NOT NULL,
|
||
status ENUM('going','interested','waitlist','cancelled') NOT NULL DEFAULT 'going',
|
||
child_count TINYINT UNSIGNED NULL,
|
||
note VARBINARY(1024) NULL,
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (event_id, user_id),
|
||
CONSTRAINT fk_ep_event FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_ep_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
|
||
-- Session-Handling (neutral, keine sensiblen Inhalte)
|
||
CREATE TABLE sessions (
|
||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
user_id BIGINT UNSIGNED NOT NULL,
|
||
token_hash CHAR(64) NOT NULL UNIQUE, -- SHA-256 Hash des Session-Tokens
|
||
ip VARCHAR(45) NULL,
|
||
user_agent VARCHAR(255) NULL,
|
||
expires_at DATETIME NOT NULL,
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT fk_session_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||
INDEX idx_session_expires (expires_at)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
|
||
-- Kurzlebige Tokens (Passwort-Reset, Magic-Login, E-Mail-Verify)
|
||
CREATE TABLE user_tokens (
|
||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
user_id BIGINT UNSIGNED NOT NULL,
|
||
type ENUM('reset','verify','magic_login') NOT NULL,
|
||
code CHAR(12) NULL, -- z. B. 6-stelliger Code (optional Klartext)
|
||
token_hash CHAR(64) NOT NULL UNIQUE,
|
||
expires_at DATETIME NOT NULL,
|
||
used_at DATETIME NULL,
|
||
ip VARCHAR(45) NULL,
|
||
user_agent VARCHAR(255) NULL,
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT fk_ut_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||
INDEX idx_ut_expires (expires_at),
|
||
INDEX idx_ut_type (type)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
|
||
-- Audit-Log für wichtige Aktionen
|
||
CREATE TABLE audit_log (
|
||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
user_id BIGINT UNSIGNED NULL, -- NULL bei Gast-Ereignissen
|
||
action VARCHAR(100) NOT NULL, -- z.B. login, profile.update, event.create
|
||
target_type VARCHAR(50) NULL, -- z.B. user, event, child
|
||
target_id BIGINT UNSIGNED NULL,
|
||
metadata JSON NULL, -- nicht sensible Zusatzinfos
|
||
ip VARCHAR(45) NULL,
|
||
user_agent VARCHAR(255) NULL,
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
INDEX idx_audit_user (user_id),
|
||
INDEX idx_audit_action (action),
|
||
INDEX idx_audit_target (target_type, target_id),
|
||
INDEX idx_audit_created (created_at)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|