Initial local commit
This commit is contained in:
109
scripts/create-user.js
Normal file
109
scripts/create-user.js
Normal file
@@ -0,0 +1,109 @@
|
||||
// scripts/create-user.js
|
||||
const { Pool } = require('pg');
|
||||
const bcrypt = require('bcrypt');
|
||||
const readline = require('readline');
|
||||
require('dotenv').config();
|
||||
|
||||
const pool = new Pool({
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT,
|
||||
database: process.env.DB_NAME,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
ssl: process.env.DB_SSL === 'true' ? { rejectUnauthorized: false } : false
|
||||
});
|
||||
|
||||
// Readline Interface für Benutzereingaben
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
// Hilfsfunktion für Benutzereingaben
|
||||
function askQuestion(question) {
|
||||
return new Promise((resolve) => {
|
||||
rl.question(question, (answer) => {
|
||||
resolve(answer.trim());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function createUser() {
|
||||
try {
|
||||
console.log('👤 Erstelle neuen Benutzer...\n');
|
||||
|
||||
// Verbindung testen
|
||||
await pool.query('SELECT NOW()');
|
||||
console.log('✅ Datenbankverbindung erfolgreich\n');
|
||||
|
||||
// Benutzereingaben abfragen
|
||||
const username = await askQuestion('Benutzername eingeben: ');
|
||||
if (!username) {
|
||||
console.log('❌ Benutzername darf nicht leer sein!');
|
||||
return;
|
||||
}
|
||||
|
||||
const password = await askQuestion('Passwort eingeben: ');
|
||||
if (!password) {
|
||||
console.log('❌ Passwort darf nicht leer sein!');
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmPassword = await askQuestion('Passwort bestätigen: ');
|
||||
if (password !== confirmPassword) {
|
||||
console.log('❌ Passwörter stimmen nicht überein!');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n🔄 Erstelle Benutzer...');
|
||||
|
||||
// Prüfen ob Benutzer bereits existiert
|
||||
const existingUser = await pool.query(
|
||||
'SELECT id FROM adminusers WHERE username = $1',
|
||||
[username]
|
||||
);
|
||||
|
||||
if (existingUser.rows.length > 0) {
|
||||
console.log(`ℹ️ Benutzer "${username}" existiert bereits`);
|
||||
|
||||
const update = await askQuestion('Passwort aktualisieren? (j/n): ');
|
||||
if (update.toLowerCase() === 'j' || update.toLowerCase() === 'ja' || update.toLowerCase() === 'y' || update.toLowerCase() === 'yes') {
|
||||
const passwordHash = await bcrypt.hash(password, 10);
|
||||
await pool.query(
|
||||
'UPDATE adminusers SET password_hash = $1 WHERE username = $2',
|
||||
[passwordHash, username]
|
||||
);
|
||||
console.log(`✅ Passwort für Benutzer "${username}" aktualisiert`);
|
||||
} else {
|
||||
console.log('❌ Vorgang abgebrochen');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Neuen Benutzer erstellen
|
||||
const passwordHash = await bcrypt.hash(password, 10);
|
||||
await pool.query(
|
||||
'INSERT INTO adminusers (username, password_hash) VALUES ($1, $2)',
|
||||
[username, passwordHash]
|
||||
);
|
||||
console.log(`✅ Benutzer "${username}" erfolgreich erstellt`);
|
||||
}
|
||||
|
||||
console.log('\n📝 Anmeldedaten:');
|
||||
console.log(` Benutzername: ${username}`);
|
||||
console.log(` Passwort: ${password}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Erstellen des Benutzers:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
rl.close();
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
// Skript ausführen wenn direkt aufgerufen
|
||||
if (require.main === module) {
|
||||
createUser();
|
||||
}
|
||||
|
||||
module.exports = { createUser };
|
||||
107
scripts/init-db.js
Normal file
107
scripts/init-db.js
Normal file
@@ -0,0 +1,107 @@
|
||||
// scripts/init-db.js
|
||||
const { Pool } = require('pg');
|
||||
const bcrypt = require('bcrypt');
|
||||
require('dotenv').config();
|
||||
|
||||
const pool = new Pool({
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT,
|
||||
database: process.env.DB_NAME,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
ssl: process.env.DB_SSL === 'true' ? { rejectUnauthorized: false } : false
|
||||
});
|
||||
|
||||
async function initDatabase() {
|
||||
try {
|
||||
console.log('🚀 Initialisiere Datenbank...');
|
||||
|
||||
// Verbindung testen
|
||||
await pool.query('SELECT NOW()');
|
||||
console.log('✅ Datenbankverbindung erfolgreich');
|
||||
|
||||
// Adminusers Tabelle erstellen
|
||||
await pool.query(`
|
||||
CREATE TABLE IF NOT EXISTS adminusers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
last_login TIMESTAMP
|
||||
)
|
||||
`);
|
||||
console.log('✅ adminusers Tabelle erstellt/überprüft');
|
||||
|
||||
// API Tokens Tabelle erstellen
|
||||
await pool.query(`
|
||||
CREATE TABLE IF NOT EXISTS api_tokens (
|
||||
id SERIAL PRIMARY KEY,
|
||||
token VARCHAR(255) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
standorte TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP,
|
||||
is_active BOOLEAN DEFAULT true
|
||||
)
|
||||
`);
|
||||
console.log('✅ api_tokens Tabelle erstellt/überprüft');
|
||||
|
||||
// Locations Tabelle erstellen
|
||||
await pool.query(`
|
||||
CREATE TABLE IF NOT EXISTS locations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) UNIQUE NOT NULL,
|
||||
latitude DECIMAL(10, 8) NOT NULL,
|
||||
longitude DECIMAL(11, 8) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`);
|
||||
console.log('✅ locations Tabelle erstellt/überprüft');
|
||||
|
||||
// Standardbenutzer erstellen (falls nicht vorhanden)
|
||||
const existingUser = await pool.query(
|
||||
'SELECT id FROM adminusers WHERE username = $1',
|
||||
['admin']
|
||||
);
|
||||
|
||||
if (existingUser.rows.length === 0) {
|
||||
const passwordHash = await bcrypt.hash('admin123', 10);
|
||||
await pool.query(
|
||||
'INSERT INTO adminusers (username, password_hash) VALUES ($1, $2)',
|
||||
['admin', passwordHash]
|
||||
);
|
||||
console.log('✅ Standardbenutzer "admin" mit Passwort "admin123" erstellt');
|
||||
} else {
|
||||
console.log('ℹ️ Standardbenutzer "admin" existiert bereits');
|
||||
}
|
||||
|
||||
// Index für bessere Performance
|
||||
await pool.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_adminusers_username ON adminusers(username);
|
||||
CREATE INDEX IF NOT EXISTS idx_adminusers_active ON adminusers(is_active);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_tokens_token ON api_tokens(token);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_tokens_active ON api_tokens(is_active);
|
||||
CREATE INDEX IF NOT EXISTS idx_locations_name ON locations(name);
|
||||
CREATE INDEX IF NOT EXISTS idx_locations_coords ON locations(latitude, longitude);
|
||||
`);
|
||||
console.log('✅ Indizes erstellt/überprüft');
|
||||
|
||||
console.log('🎉 Datenbank erfolgreich initialisiert!');
|
||||
console.log('📝 Standardanmeldung: admin / admin123');
|
||||
console.log('⚠️ Ändern Sie das Standardpasswort in der Produktion!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler bei der Datenbankinitialisierung:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
// Skript ausführen wenn direkt aufgerufen
|
||||
if (require.main === module) {
|
||||
initDatabase();
|
||||
}
|
||||
|
||||
module.exports = { initDatabase };
|
||||
87
scripts/setup-players.js
Normal file
87
scripts/setup-players.js
Normal file
@@ -0,0 +1,87 @@
|
||||
// scripts/setup-players.js
|
||||
// Script to set up players table and fix the player name issue
|
||||
const { Pool } = require('pg');
|
||||
require('dotenv').config();
|
||||
|
||||
const pool = new Pool({
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT,
|
||||
database: process.env.DB_NAME,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
ssl: process.env.DB_SSL === 'true' ? { rejectUnauthorized: false } : false
|
||||
});
|
||||
|
||||
async function setupPlayers() {
|
||||
try {
|
||||
console.log('🚀 Setting up players table and views...');
|
||||
|
||||
// Test connection
|
||||
await pool.query('SELECT NOW()');
|
||||
console.log('✅ Database connection successful');
|
||||
|
||||
// Check if players table exists and has the expected structure
|
||||
const tableCheck = await pool.query(`
|
||||
SELECT column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'players'
|
||||
`);
|
||||
|
||||
if (tableCheck.rows.length === 0) {
|
||||
console.log('❌ Players table not found. Please create it first with the structure:');
|
||||
console.log(' - id (UUID)');
|
||||
console.log(' - firstname (VARCHAR)');
|
||||
console.log(' - lastname (VARCHAR)');
|
||||
console.log(' - birthdate (DATE)');
|
||||
console.log(' - created_at (TIMESTAMP)');
|
||||
console.log(' - rfiduid (VARCHAR)');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('✅ Players table structure verified');
|
||||
console.log('📋 Available columns:', tableCheck.rows.map(r => r.column_name).join(', '));
|
||||
|
||||
// Create the updated view using your actual table structure
|
||||
await pool.query(`
|
||||
CREATE OR REPLACE VIEW "GetTimesWithPlayerAndLocation" AS
|
||||
SELECT
|
||||
gt.*,
|
||||
l.name as location_name,
|
||||
l.latitude,
|
||||
l.longitude,
|
||||
COALESCE(CONCAT(p.firstname, ' ', p.lastname), 'Unknown Player') as player_name
|
||||
FROM "gettimes" gt
|
||||
JOIN locations l ON gt.location_id = l.id
|
||||
LEFT JOIN players p ON gt.player_id = p.id
|
||||
`);
|
||||
console.log('✅ Updated view created');
|
||||
|
||||
// Test the view
|
||||
const testResult = await pool.query('SELECT COUNT(*) as count FROM "GetTimesWithPlayerAndLocation"');
|
||||
console.log(`✅ View test successful: ${testResult.rows[0].count} records found`);
|
||||
|
||||
// Show sample data
|
||||
const sampleData = await pool.query('SELECT player_name, location_name, recorded_time FROM "GetTimesWithPlayerAndLocation" LIMIT 3');
|
||||
console.log('📊 Sample data from view:');
|
||||
sampleData.rows.forEach((row, index) => {
|
||||
console.log(` ${index + 1}. ${row.player_name} at ${row.location_name}: ${row.recorded_time}`);
|
||||
});
|
||||
|
||||
console.log('\n🎉 Setup completed successfully!');
|
||||
console.log('📝 Your index.html should now display player names instead of IDs');
|
||||
console.log('🔄 Restart your server to use the new view');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error during setup:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
// Run if called directly
|
||||
if (require.main === module) {
|
||||
setupPlayers();
|
||||
}
|
||||
|
||||
module.exports = { setupPlayers };
|
||||
Reference in New Issue
Block a user