This commit is contained in:
2025-09-11 08:16:24 +02:00
parent 04ecdac6bb
commit 3210f1e14f
652 changed files with 12389 additions and 1011 deletions

View File

@@ -0,0 +1,70 @@
<?php
require "db.php";
//Felix
function user_id_from_username($u){
$st=db()->prepare("SELECT user_id FROM users WHERE username=?");
$st->execute([$u]);
$r=$st->fetch();
return $r ? (int)$r['user_id'] : 0;
}
$action = $_GET['action'] ?? '';
if ($action==='get_for_owner') {
$uname = $_GET['owner_username'] ?? '';
if ($uname==='') bad('owner_username required');
$st = db()->prepare("SELECT c.campaign_id, c.title, c.description
FROM campaigns c
JOIN users u ON u.user_id=c.owner_user_id
WHERE u.username=? LIMIT 1");
$st->execute([$uname]);
$row = $st->fetch();
if (!$row) bad('not_found',404);
ok($row);
}
if ($action==='ensure_for_owner') {
$b = body(); $uname = $b['owner_username'] ?? '';
if ($uname==='') bad('owner_username required');
$uid = user_id_from_username($uname);
if ($uid<=0) bad('user_not_found',404);
$st = db()->prepare("SELECT campaign_id, title, description FROM campaigns WHERE owner_user_id=? LIMIT 1");
$st->execute([$uid]);
$row = $st->fetch();
if ($row) ok($row);
$ins = db()->prepare("INSERT INTO campaigns(owner_user_id,title,description) VALUES(?,?,?)");
$ins->execute([$uid,'Meine Kampagne',null]);
ok(['campaign_id'=>(int)db()->lastInsertId(),'title'=>'Meine Kampagne','description'=>null]);
}
if ($action==='update_for_owner') {
$b = body();
$uname = $b['owner_username'] ?? '';
$title = trim($b['title'] ?? '');
$desc = $b['description'] ?? null;
if ($uname==='') bad('owner_username required');
if ($title==='') bad('title required');
$uid = user_id_from_username($uname);
if ($uid<=0) bad('user_not_found',404);
$st = db()->prepare("SELECT campaign_id FROM campaigns WHERE owner_user_id=? LIMIT 1");
$st->execute([$uid]);
$row = $st->fetch();
if ($row) {
$upd = db()->prepare("UPDATE campaigns SET title=?, description=? WHERE campaign_id=?");
$upd->execute([$title,$desc,(int)$row['campaign_id']]);
ok(['campaign_id'=>(int)$row['campaign_id']]);
} else {
$ins = db()->prepare("INSERT INTO campaigns(owner_user_id,title,description) VALUES(?,?,?)");
$ins->execute([$uid,$title,$desc]);
ok(['campaign_id'=>(int)db()->lastInsertId()]);
}
}
http_response_code(404); echo json_encode(['ok'=>false,'error'=>'unknown action']);

View File

@@ -0,0 +1,98 @@
<?php
require "db.php";
//Paul,Jakob
function out($ok, $msg='ok', $arr=[], $code=200){ if($ok) ok(['msg'=>$msg]+$arr); else bad($msg,$code); }
$a = $_GET['action'] ?? '';
$b = body();
function find_user($name){
$st=db()->prepare("SELECT user_id FROM users WHERE username=?");
$st->execute([trim($name)]);
$r=$st->fetch();
return $r? (int)$r["user_id"] : 0;
}
try {
if ($a === "create") {
$uid = isset($b['user_id']) ? (int)$b['user_id'] : 0;
if ($uid<=0){
$u = trim($b["username"] ?? "");
if ($u==="") out(false,"username or user_id required",[],400);
$uid = find_user($u);
if (!$uid) out(false,"user not found",[],404);
}
$c = trim($b["name"] ?? "");
if ($c==="") out(false,"invalid",[],400);
$ins = db()->prepare("INSERT INTO characters(user_id,name) VALUES(?,?)");
try { $ins->execute([$uid,$c]); }
catch(PDOException $e){ if($e->errorInfo[1]==1062) out(false,"character exists for this user",[],409); throw $e; }
out(true,"created",["character_id"=>(int)db()->lastInsertId()]);
}
if ($a === "list") {
$camp = (int)($_GET['campaign_id'] ?? 0);
if ($camp>0){
$st = db()->prepare("
SELECT c.character_id, c.user_id, c.name, u.username,
EXISTS(SELECT 1 FROM campaign_characters cc
WHERE cc.campaign_id=? AND cc.character_id=c.character_id) AS assigned
FROM characters c
JOIN users u ON u.user_id=c.user_id
ORDER BY u.username ASC, c.name ASC
");
$st->execute([$camp]);
} else {
$st = db()->query("
SELECT c.character_id, c.user_id, c.name, u.username, 0 AS assigned
FROM characters c
JOIN users u ON u.user_id=c.user_id
ORDER BY u.username ASC, c.name ASC
");
}
out(true,"ok",["items"=>$st->fetchAll()]);
}
// --- delete ---
if ($a === "delete") {
$u = trim($_GET['username'] ?? '');
$n = trim($_GET['name'] ?? '');
if ($u===''||$n==='') out(false,'username/name required',[],400);
$uid = find_user($u);
if (!$uid) out(false,"user not found",[],404);
$del = db()->prepare("DELETE FROM characters WHERE user_id=? AND name=?");
$del->execute([$uid,$n]);
out(true,"deleted",["count"=>$del->rowCount()]);
}
if ($a === "assign") {
$cid = (int)($b['character_id'] ?? 0);
$camp = $b['campaign_id'] ?? null;
if ($cid<=0) out(false,'character_id required',[],400);
if ($camp===null || $camp===''){
$st = db()->prepare("DELETE FROM campaign_characters WHERE character_id=?");
$st->execute([$cid]);
out(true,'unassigned',[]);
} else {
$camp = (int)$camp;
$st = db()->prepare("INSERT IGNORE INTO campaign_characters(campaign_id,character_id) VALUES(?,?)");
$st->execute([$camp,$cid]);
out(true,'assigned',[]);
}
}
out(false,"unknown action",[],404);
} catch (Throwable $e) {
bad("server error: ".$e->getMessage(),500);
}

37
Pen&Paper Main/api/db.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
header('Content-Type: application/json; charset=utf-8');
function db() {
static $pdo = null;
if ($pdo) return $pdo;
$dbName = "vpr"; //Datenbankname
$linkName = "localhost"; //Datenbank-Server
$user = "root"; //Benutzername
$pw = ""; //Passwort
$pdo = new \PDO("mysql:dbname=$dbName;host=$linkName"
, $user
, $pw
, array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
return $pdo;
}
function body() {
$raw = file_get_contents('php://input');
$b = json_decode($raw, true);
return is_array($b) ? $b : [];
}
const JSON_FLAGS = JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE;
function bad($m, $code = 400) {
http_response_code($code);
echo json_encode(['ok' => false, 'error' => $m], JSON_FLAGS);
exit;
}
function ok($arr = []) {
echo json_encode(['ok' => true] + $arr, JSON_FLAGS);
exit;
}

View File

@@ -0,0 +1,24 @@
<?php
//Lucas
require "db.php";
$action = $_GET['action'] ?? '';
if ($action==='list') {
$camp = isset($_GET['campaign_id']) ? (int)$_GET['campaign_id'] : 0;
if ($camp<=0) bad('campaign_id required');
$st=db()->prepare("SELECT id, campaign_id, user_id, text FROM campaign_notes WHERE campaign_id=? ORDER BY id DESC");
$st->execute([$camp]);
ok(['items'=>$st->fetchAll()]);
}
if ($action==='add') {
$b = body();
$camp=(int)($b['campaign_id']??0); $uid=(int)($b['user_id']??0); $txt=trim($b['text']??'');
if ($camp<=0||$uid<=0||$txt==='') bad('invalid');
$st=db()->prepare("INSERT INTO campaign_notes(campaign_id,user_id,text) VALUES(?,?,?)");
$st->execute([$camp,$uid,$txt]);
ok(['id'=>db()->lastInsertId()]);
}
http_response_code(404); echo json_encode(['ok'=>false,'error'=>'unknown action']);

View File

@@ -0,0 +1,16 @@
<?php
//Felix
require "db.php";$action=$_GET['action']??'';$b=body();
if($action==="join"){
$sid=(int)($b["session_id"]??0);$uid=(int)($b["user_id"]??0);$role=$b["role"]??"Player";if(!in_array($role,["DM","Player"]))$role="Player";
$st=db()->prepare("INSERT INTO participants (session_id,user_id,role) VALUES (?,?,?)");$st->execute([$sid,$uid,$role]);
out(true,"joined",[],201);
}
if($action==="list"){ $sid=(int)($_GET["session_id"]??0);
$st=db()->prepare("SELECT p.user_id,u.username,p.role FROM participants p JOIN users u ON u.user_id=p.user_id WHERE p.session_id=?");$st->execute([$sid]);
out(true,"ok",["items"=>$st->fetchAll()]);
}
if($action==="leave"){ $sid=(int)($_GET["session_id"]??0);$uid=(int)($_GET["user_id"]??0);
$st=db()->prepare("DELETE FROM participants WHERE session_id=? AND user_id=?");$st->execute([$sid,$uid]);
out(true,"left",["count"=>$st->rowCount()]);}
out(false,"unknown action",[],404);

View File

@@ -0,0 +1,62 @@
<?php
session_start();
spl_autoload_register(function ($className) {
if (substr($className, 0, 4) !== 'ppb\\') { return; }
$fileName = __DIR__.'/'.str_replace('\\', DIRECTORY_SEPARATOR, substr($className, 4)).'.php';
if (file_exists($fileName)) { include $fileName; }
});
$endpoint = explode('/', trim($_SERVER['PATH_INFO'],'/'));
$data = json_decode(file_get_contents('php://input'), true);
$controllerName = $endpoint[0];
$id = false;
$alias = false;
if (isset($endpoint[1])) {
if (preg_match('/\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b/', $$endpoint[1])) {
$id = $$endpoint[1];
} else {
$alias = $$endpoint[1];
}
}
$controllerClassName = 'ppb\\Controller\\'.ucfirst($controllerName). 'Controller';
if ($_SERVER['REQUEST_METHOD'] == "DELETE") {
$methodName = "delete" . ucfirst($controllerName);
} else if ($_SERVER['REQUEST_METHOD'] == "PUT") {
$methodName = "update" . ucfirst($controllerName);
} else if ($_SERVER['REQUEST_METHOD'] == "POST") {
$methodName = "write" . ucfirst($controllerName);
} else if ($_SERVER['REQUEST_METHOD'] == "GET") {
if ($alias) {
$methodName = $alias;
} else {
$methodName = "get" . ucfirst($controllerName);
}
}
if (method_exists($controllerClassName, $methodName)) {
$controller = new $controllerClassName();
if ($_SERVER['REQUEST_METHOD'] == "GET") {
if ($id) {
$controller->$methodName($id);
} else {
$controller->$methodName();
}
} else if ($_SERVER['REQUEST_METHOD'] == "POST"){
$controller->$methodName($data);
} else if ($_SERVER['REQUEST_METHOD'] == "DELETE"){
$controller->$methodName($id);
} else {
$controller->$methodName($id, $data);
}
} else {
}
?>

View File

@@ -0,0 +1,21 @@
<?php
//Lucas
require "db.php";
$action=$_GET['action']??'';$b=body();
if($action==="create"){
$owner=(int)($b["owner_id"]??0);$title=trim($b["title"]??"");
if($owner<1||$title==="") out(false,"invalid data",[],400);
$st=db()->prepare("INSERT INTO sessions (owner_id,title) VALUES (?,?)");$st->execute([$owner,$title]);
out(true,"created",["session_id"=>db()->lastInsertId()],201);
}
if($action==="list"){
$owner=isset($_GET["owner_id"])?(int)$_GET["owner_id"]:null;$q=trim($_GET["q"]??"");$sort=$_GET["sort"]??"created_at_desc";
$allowed=["created_at_asc"=>"created_at ASC","created_at_desc"=>"created_at DESC","title_asc"=>"title ASC","title_desc"=>"title DESC"];
$order=$allowed[$sort]??$allowed["created_at_desc"];
$sql="SELECT s.session_id,s.title,s.created_at,u.username FROM sessions s JOIN users u ON u.user_id=s.owner_id WHERE 1=1";$p=[];
if($owner){$sql.=" AND s.owner_id=?";$p[]=$owner;}if($q!==""){$sql.=" AND s.title LIKE ?";$p[]="%$q%";}$sql.=" ORDER BY $order";
$st=db()->prepare($sql);$st->execute($p);out(true,"ok",["items"=>$st->fetchAll()]);
}
if($action==="delete"){ $id=(int)($_GET["id"]??0);$st=db()->prepare("DELETE FROM sessions WHERE session_id=?");$st->execute([$id]);
out(true,"deleted",["count"=>$st->rowCount()]);}
out(false,"unknown action",[],404);

View File

@@ -0,0 +1,55 @@
CREATE DATABASE IF NOT EXISTS vpr DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE vpr;
--Jakob
DROP TABLE IF EXISTS campaign_notes;
DROP TABLE IF EXISTS campaign_characters;
DROP TABLE IF EXISTS campaigns;
DROP TABLE IF EXISTS characters;
DROP TABLE IF EXISTS sessions;
DROP TABLE IF EXISTS users;
-- User
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(40) NOT NULL UNIQUE,
pass_hash VARCHAR(255) NOT NULL
);
CREATE TABLE campaigns (
campaign_id INT AUTO_INCREMENT PRIMARY KEY,
owner_user_id INT NOT NULL,
title VARCHAR(100) NOT NULL DEFAULT 'Meine Kampagne',
description TEXT NULL,
UNIQUE KEY ux_owner_one_campaign (owner_user_id),
CONSTRAINT fk_campaign_owner FOREIGN KEY (owner_user_id)
REFERENCES users(user_id) ON DELETE CASCADE
);
CREATE TABLE characters (
character_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
campaign_id INT NULL,
name VARCHAR(50) NOT NULL,
CONSTRAINT fk_char_user FOREIGN KEY (user_id)
REFERENCES users(user_id) ON DELETE CASCADE,
CONSTRAINT fk_char_campaign FOREIGN KEY (campaign_id)
REFERENCES campaigns(campaign_id) ON DELETE SET NULL,
CONSTRAINT ux_user_char UNIQUE (user_id, name)
);
CREATE TABLE sessions (
session_id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(100) NOT NULL
);
CREATE TABLE campaign_notes (
note_id INT AUTO_INCREMENT PRIMARY KEY,
campaign_id INT NOT NULL,
user_id INT NOT NULL,
text TEXT NOT NULL,
CONSTRAINT fk_note_campaign FOREIGN KEY (campaign_id)
REFERENCES campaigns(campaign_id) ON DELETE CASCADE,
CONSTRAINT fk_note_user FOREIGN KEY (user_id)
REFERENCES users(user_id) ON DELETE CASCADE
);

View File

@@ -0,0 +1,43 @@
<?php
require "db.php";
//Gabriel,Jakob
$action = $_GET['action'] ?? '';
$b = body();
function out_ok($arr = []) { echo json_encode(['ok'=>true] + $arr, JSON_UNESCAPED_UNICODE); exit; }
function out_err($msg, $code=400) { http_response_code($code); echo json_encode(['ok'=>false,'error'=>$msg], JSON_UNESCAPED_UNICODE); exit; }
if ($action === 'register') {
$u = trim($b['username'] ?? '');
$p = (string)($b['password'] ?? '');
if ($u === '' || $p === '') out_err('username/password required');
$st = db()->prepare("SELECT user_id FROM users WHERE username=?");
$st->execute([$u]);
if ($st->fetch()) out_err('username exists', 409);
$hash = password_hash($p, PASSWORD_DEFAULT);
$ins = db()->prepare("INSERT INTO users(username, pass_hash) VALUES(?, ?)");
$ins->execute([$u, $hash]);
out_ok(['user_id' => (int)db()->lastInsertId(), 'username' => $u]);
}
if ($action === 'login') {
$u = trim($b['username'] ?? '');
$p = (string)($b['password'] ?? '');
if ($u === '' || $p === '') out_err('username/password required');
$st = db()->prepare("SELECT user_id, pass_hash FROM users WHERE username=?");
$st->execute([$u]);
$row = $st->fetch();
if (!$row) out_err('invalid credentials', 401);
if (!password_verify($p, $row['pass_hash'])) out_err('invalid credentials', 401);
out_ok(['user_id' => (int)$row['user_id'], 'username' => $u]);
}
out_err('unknown action', 404);