This commit is contained in:
2025-12-25 01:50:07 +01:00
parent 5d7dcfd950
commit 3b4b5cad3e
11 changed files with 743 additions and 372 deletions

142
schema.sql Normal file
View File

@@ -0,0 +1,142 @@
-- 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 'active',
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,
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,
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,
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;