shinkan-jinkendo/backend/migrations/001_auth_membership.sql
Lars b2bc8590c4
Some checks failed
Deploy Development / deploy (push) Failing after 4s
feat: Complete MVP setup - Docker, Frontend, Migrations, CI/CD
Docker & Deployment:
- docker-compose.yml (Prod: Port 3003/8003)
- docker-compose.dev-env.yml (Dev: Port 3098/8098)
- Backend Dockerfile (Python 3.12-slim)
- Frontend Dockerfile (Node 20 + Nginx)
- Gitea Actions (deploy-dev.yml, deploy-prod.yml)

Frontend:
- React 18 + Vite setup
- package.json, vite.config.js, index.html
- App.jsx (minimal with version display)
- api.js (complete API client)
- app.css + AuthContext from Mitai
- main.jsx entry point

Backend Migrations:
- 001_auth_membership.sql (Auth + Features + Tier Limits)
- 002_organization.sql (Clubs, Divisions, Training Groups)
- 003_catalogs.sql (Skills + Methods with sample data)

Documentation:
- .claude/rules/ (ARCHITECTURE, CODING_RULES, etc.)
- SHINKAN_PROJECT_SETUP.md (technical setup guide)

Server:
- Directories created on Pi: /home/lars/docker/shinkan[-dev]
- Gitea Runner configured and running

Ready for first deployment to dev.shinkan.jinkendo.de

version: 0.1.0
date: 2026-04-21
2026-04-21 14:36:52 +02:00

115 lines
3.7 KiB
SQL

-- Migration 001: Auth & Membership (von Mitai übernommen, angepasst)
-- Erstellt: 2026-04-21
-- Beschreibung: Basis-Auth-System und Membership-Infrastruktur
-- Profiles (Nutzer)
CREATE TABLE profiles (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
pin_hash VARCHAR(255) NOT NULL,
name VARCHAR(200),
role VARCHAR(50) DEFAULT 'user',
tier VARCHAR(50) DEFAULT 'free',
email_verified BOOLEAN DEFAULT false,
verification_token VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_profiles_email ON profiles(email);
CREATE INDEX idx_profiles_role ON profiles(role);
-- Sessions (Auth-Tokens)
CREATE TABLE sessions (
id SERIAL PRIMARY KEY,
profile_id INT REFERENCES profiles(id) ON DELETE CASCADE,
token VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP NOT NULL
);
CREATE INDEX idx_sessions_token ON sessions(token);
CREATE INDEX idx_sessions_profile ON sessions(profile_id);
-- Features (Feature-Definitionen)
CREATE TABLE features (
id SERIAL PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL,
display_name VARCHAR(200),
description TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
-- Tier Limits (Limits pro Tier)
CREATE TABLE tier_limits (
id SERIAL PRIMARY KEY,
tier VARCHAR(50) NOT NULL,
feature_id INT REFERENCES features(id),
limit_value INT, -- -1 = unlimited
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(tier, feature_id)
);
-- Subscriptions (Nutzer-Subscriptions)
CREATE TABLE subscriptions (
id SERIAL PRIMARY KEY,
profile_id INT REFERENCES profiles(id) ON DELETE CASCADE,
tier VARCHAR(50) NOT NULL,
status VARCHAR(50) DEFAULT 'trial',
start_date DATE NOT NULL,
end_date DATE,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_subscriptions_profile ON subscriptions(profile_id);
-- User Feature Usage (Tracking)
CREATE TABLE user_feature_usage (
id SERIAL PRIMARY KEY,
profile_id INT REFERENCES profiles(id) ON DELETE CASCADE,
feature_id INT REFERENCES features(id),
usage_count INT DEFAULT 0,
last_used TIMESTAMP,
last_reset TIMESTAMP DEFAULT NOW(),
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(profile_id, feature_id)
);
CREATE INDEX idx_usage_profile_feature ON user_feature_usage(profile_id, feature_id);
-- Insert Default Features (Shinkan-spezifisch)
INSERT INTO features (name, display_name, description) VALUES
('exercises', 'Übungen', 'Anzahl Übungen pro Verein'),
('training_units', 'Trainingseinheiten', 'Anzahl Trainingseinheiten pro Monat'),
('training_programs', 'Trainingsprogramme', 'Anzahl aktive Trainingsprogramme'),
('exercise_media', 'Medien-Uploads', 'Anzahl Medien-Uploads pro Monat'),
('wiki_import', 'MediaWiki-Import', 'Zugriff auf MediaWiki-Import'),
('ai_analysis', 'KI-Analysen', 'Anzahl KI-Analysen pro Monat (zukünftig)');
-- Insert Default Tier Limits
-- Free Tier
INSERT INTO tier_limits (tier, feature_id, limit_value)
SELECT 'free', id,
CASE
WHEN name = 'exercises' THEN 50
WHEN name = 'training_units' THEN 20
WHEN name = 'training_programs' THEN 2
WHEN name = 'exercise_media' THEN 10
WHEN name = 'wiki_import' THEN 0
WHEN name = 'ai_analysis' THEN 0
END
FROM features;
-- Premium Tier
INSERT INTO tier_limits (tier, feature_id, limit_value)
SELECT 'premium', id,
CASE
WHEN name = 'exercises' THEN -1 -- unlimited
WHEN name = 'training_units' THEN -1
WHEN name = 'training_programs' THEN -1
WHEN name = 'exercise_media' THEN 100
WHEN name = 'wiki_import' THEN 1
WHEN name = 'ai_analysis' THEN 50
END
FROM features;