mirror of
https://github.com/ceratic/project_vollidioten_website.git
synced 2026-05-14 00:16:47 +02:00
feat: Add DatabaseManager and LinkPlayer components, implement authentication and linking logic
- Created DatabaseManager component for managing database access via phpMyAdmin. - Developed LinkPlayer component to link Discord accounts with game characters, including user authentication and error handling. - Added mock data files for players, organizations, and projects to handle backend unavailability. - Implemented AuthService for managing user authentication and session checks. - Created DatabaseService to fetch and manage player, organization, and project data with fallback to mock data. - Added HTML page for handling authentication unavailability. - Developed a test script for validating Docker setup and required files.
This commit is contained in:
226
backend/database.js
Normal file
226
backend/database.js
Normal file
@@ -0,0 +1,226 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// Database Config from Env
|
||||
const dbConfig = {
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASS || '',
|
||||
database: process.env.DB_NAME || 'obsidian_db',
|
||||
waitForConnections: true,
|
||||
connectionLimit: 10,
|
||||
queueLimit: 0
|
||||
};
|
||||
|
||||
let pool;
|
||||
|
||||
// Mock Data for Seeding
|
||||
const SEED_PLAYERS = [
|
||||
{
|
||||
uuid: '80301bff-74df-4579-bcfc-082ac8d26b5b',
|
||||
username: 'kaiwastoshort',
|
||||
isOnline: 1,
|
||||
isNpc: 0,
|
||||
isAdmin: 0,
|
||||
tags: JSON.stringify(['#Bürger', '#Händler']),
|
||||
stats: JSON.stringify({ playtimeHours: 482, level: 45, role: 'Bürger', organizationId: 'org-3' }),
|
||||
inventory: JSON.stringify([]),
|
||||
storyMarkdown: '# Der Bauplan von V\n\n> "Stein erinnert sich..."'
|
||||
},
|
||||
{
|
||||
uuid: '8984c0b5-d912-4462-b189-c864fba4a1af',
|
||||
username: 'DrKButz',
|
||||
isOnline: 0,
|
||||
isNpc: 0,
|
||||
isAdmin: 1, // DrKButz is admin for testing
|
||||
tags: JSON.stringify(['#Bauunternehmer']),
|
||||
stats: JSON.stringify({ playtimeHours: 120, level: 12, role: 'Unternehmer', organizationId: 'org-4' }),
|
||||
inventory: JSON.stringify([]),
|
||||
storyMarkdown: '# Forschungslogbuch:\n\nSpezialisiert auf...'
|
||||
}
|
||||
];
|
||||
|
||||
const SEED_ORGS = [
|
||||
{
|
||||
id: 'org-3',
|
||||
name: 'Provisorium Null',
|
||||
type: 'City',
|
||||
description: 'Die erste Siedlung...',
|
||||
memberCount: 6,
|
||||
status: 'active',
|
||||
mayor: '',
|
||||
establishedYear: 'Day 0',
|
||||
bannerUrl: 'images/screenshots/2025-12-28_01.11.10.png',
|
||||
gallery: JSON.stringify(['images/screenshots/2025-12-28_01.12.07.png']),
|
||||
cityStats: JSON.stringify({ taxRate: 3.5, biome: 'Ebene', defenseRating: 8, government: 'Feudal', specialty: 'Handel' })
|
||||
},
|
||||
{
|
||||
id: 'org-4',
|
||||
name: 'Sakura',
|
||||
type: 'City',
|
||||
description: 'Eine dunkle, biolumineszente Hafenstadt...',
|
||||
memberCount: 2,
|
||||
status: 'active',
|
||||
mayor: 'Kampfzwerk',
|
||||
establishedYear: 'Ära 2',
|
||||
bannerUrl: 'images/screenshots/2025-12-28_01.11.32.png',
|
||||
gallery: JSON.stringify([]),
|
||||
cityStats: JSON.stringify({ taxRate: 15.0, biome: 'Deep Dark', defenseRating: 4, government: 'Syndikat', specialty: 'Schmuggel' })
|
||||
}
|
||||
];
|
||||
|
||||
const SEED_PROJECTS = [
|
||||
{
|
||||
id: 'ven-1',
|
||||
title: 'DrkButz Architektur',
|
||||
description: 'Führendes Architekturbüro...',
|
||||
category: 'Enterprise',
|
||||
status: 'active',
|
||||
progress: 85,
|
||||
owner: 'DrKButz',
|
||||
employees: JSON.stringify([]),
|
||||
hiring: 0,
|
||||
foundedDate: 'Zyklus 12',
|
||||
associatedOrgId: 'org-4',
|
||||
bannerUrl: 'images/screenshots/2025-12-28_01.11.49.png',
|
||||
shopCatalog: JSON.stringify([])
|
||||
}
|
||||
];
|
||||
|
||||
// Retry connection logic for Docker
|
||||
function init() {
|
||||
const tryConnect = () => {
|
||||
console.log("Attempting to connect to MySQL...");
|
||||
const tempPool = mysql.createPool(dbConfig);
|
||||
|
||||
tempPool.getConnection((err, connection) => {
|
||||
if (err) {
|
||||
console.error("Database connection failed. Retrying in 5s...", err.code);
|
||||
setTimeout(tryConnect, 5000);
|
||||
} else {
|
||||
console.log("MySQL Connected!");
|
||||
pool = tempPool;
|
||||
connection.release();
|
||||
setupTables();
|
||||
}
|
||||
});
|
||||
};
|
||||
tryConnect();
|
||||
}
|
||||
|
||||
function setupTables() {
|
||||
const queries = [
|
||||
`CREATE TABLE IF NOT EXISTS players (
|
||||
uuid VARCHAR(36) PRIMARY KEY,
|
||||
username VARCHAR(255),
|
||||
isOnline TINYINT,
|
||||
isNpc TINYINT DEFAULT 0,
|
||||
isAdmin TINYINT DEFAULT 0,
|
||||
tags JSON,
|
||||
stats JSON,
|
||||
inventory JSON,
|
||||
storyMarkdown TEXT,
|
||||
discordId VARCHAR(255)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS orgs (
|
||||
id VARCHAR(50) PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
type VARCHAR(50),
|
||||
description TEXT,
|
||||
memberCount INTEGER,
|
||||
status VARCHAR(50),
|
||||
mayor VARCHAR(255),
|
||||
establishedYear VARCHAR(100),
|
||||
bannerUrl VARCHAR(255),
|
||||
gallery JSON,
|
||||
cityStats JSON
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS projects (
|
||||
id VARCHAR(50) PRIMARY KEY,
|
||||
title VARCHAR(255),
|
||||
description TEXT,
|
||||
category VARCHAR(50),
|
||||
status VARCHAR(50),
|
||||
progress INTEGER,
|
||||
owner VARCHAR(255),
|
||||
employees JSON,
|
||||
hiring TINYINT,
|
||||
foundedDate VARCHAR(100),
|
||||
associatedOrgId VARCHAR(50),
|
||||
bannerUrl VARCHAR(255),
|
||||
shopCatalog JSON,
|
||||
gallery JSON
|
||||
)`
|
||||
];
|
||||
|
||||
queries.forEach(q => {
|
||||
pool.query(q, (err) => {
|
||||
if (err) console.error("Error creating table:", err);
|
||||
});
|
||||
});
|
||||
|
||||
seedData();
|
||||
}
|
||||
|
||||
function seedData() {
|
||||
// Check if players exist
|
||||
pool.query("SELECT COUNT(*) as count FROM players", (err, rows) => {
|
||||
if (!err && rows[0].count === 0) {
|
||||
console.log("Seeding Players...");
|
||||
SEED_PLAYERS.forEach(p => {
|
||||
pool.query("INSERT INTO players VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
[p.uuid, p.username, p.isOnline, p.isNpc, p.isAdmin, p.tags, p.stats, p.inventory, p.storyMarkdown, null]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
pool.query("SELECT COUNT(*) as count FROM orgs", (err, rows) => {
|
||||
if (!err && rows[0].count === 0) {
|
||||
console.log("Seeding Orgs...");
|
||||
SEED_ORGS.forEach(o => {
|
||||
pool.query("INSERT INTO orgs VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
[o.id, o.name, o.type, o.description, o.memberCount, o.status, o.mayor, o.establishedYear, o.bannerUrl, o.gallery, o.cityStats]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
pool.query("SELECT COUNT(*) as count FROM projects", (err, rows) => {
|
||||
if (!err && rows[0].count === 0) {
|
||||
console.log("Seeding Projects...");
|
||||
SEED_PROJECTS.forEach(p => {
|
||||
pool.query("INSERT INTO projects VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
[p.id, p.title, p.description, p.category, p.status, p.progress, p.owner, p.employees, p.hiring, p.foundedDate, p.associatedOrgId, p.bannerUrl, p.shopCatalog, '[]']);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Wrapper to mimic SQLite API for easy migration in server.js
|
||||
const dbWrapper = {
|
||||
get: (sql, params, cb) => {
|
||||
if (!pool) return cb(new Error("DB not ready"));
|
||||
pool.query(sql, params, (err, rows) => {
|
||||
if (err) return cb(err);
|
||||
cb(null, rows[0]);
|
||||
});
|
||||
},
|
||||
all: (sql, params, cb) => {
|
||||
// Handle case where params is omitted and cb is second parameter
|
||||
if (typeof params === 'function') {
|
||||
cb = params;
|
||||
params = [];
|
||||
}
|
||||
if (!pool) return cb(new Error("DB not ready"));
|
||||
pool.query(sql, params || [], (err, rows) => {
|
||||
cb(err, rows);
|
||||
});
|
||||
},
|
||||
run: (sql, params, cb) => {
|
||||
if (!pool) return cb(new Error("DB not ready"));
|
||||
pool.query(sql, params, function(err, result) {
|
||||
// "this" context in sqlite callback contains changes, mock it if needed
|
||||
if (cb) cb(err);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { db: dbWrapper, init };
|
||||
Reference in New Issue
Block a user