Add linking of RFID with camera
This commit is contained in:
309
routes/api.js
309
routes/api.js
@@ -998,4 +998,313 @@ router.post('/users/find', requireApiKey, async (req, res) => {
|
||||
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// RFID LINKING & USER MANAGEMENT ENDPOINTS (No API Key required for dashboard)
|
||||
// ============================================================================
|
||||
|
||||
// Get all players for RFID linking (no auth required for dashboard)
|
||||
router.get('/players', async (req, res) => {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`SELECT id, firstname, lastname, birthdate, rfiduid, created_at
|
||||
FROM players
|
||||
ORDER BY created_at DESC`
|
||||
);
|
||||
|
||||
res.json(result.rows);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen der Spieler:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Fehler beim Abrufen der Spieler'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Create new player with optional Supabase user linking (no auth required for dashboard)
|
||||
router.post('/players', async (req, res) => {
|
||||
const { firstname, lastname, birthdate, rfiduid, supabase_user_id } = req.body;
|
||||
|
||||
// Validierung
|
||||
if (!firstname || !lastname || !birthdate) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Firstname, Lastname und Birthdate sind erforderlich'
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// Prüfen ob RFID UID bereits existiert (falls angegeben)
|
||||
if (rfiduid) {
|
||||
const existingRfid = await pool.query(
|
||||
'SELECT id FROM players WHERE rfiduid = $1',
|
||||
[rfiduid]
|
||||
);
|
||||
|
||||
if (existingRfid.rows.length > 0) {
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
message: 'RFID UID existiert bereits'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Prüfen ob Supabase User bereits verknüpft ist
|
||||
if (supabase_user_id) {
|
||||
const existingUser = await pool.query(
|
||||
'SELECT id FROM players WHERE supabase_user_id = $1',
|
||||
[supabase_user_id]
|
||||
);
|
||||
|
||||
if (existingUser.rows.length > 0) {
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
message: 'Dieser Benutzer ist bereits mit einem Spieler verknüpft'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Spieler in Datenbank einfügen
|
||||
const result = await pool.query(
|
||||
`INSERT INTO players (firstname, lastname, birthdate, rfiduid, supabase_user_id, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id, created_at`,
|
||||
[firstname, lastname, birthdate, rfiduid, supabase_user_id, new Date()]
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Spieler erfolgreich erstellt',
|
||||
data: {
|
||||
id: result.rows[0].id,
|
||||
firstname: firstname,
|
||||
lastname: lastname,
|
||||
birthdate: birthdate,
|
||||
rfiduid: rfiduid,
|
||||
supabase_user_id: supabase_user_id,
|
||||
created_at: result.rows[0].created_at
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen des Spielers:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Interner Serverfehler beim Erstellen des Spielers'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Link existing player to Supabase user (no auth required for dashboard)
|
||||
router.post('/link-player', async (req, res) => {
|
||||
const { player_id, supabase_user_id } = req.body;
|
||||
|
||||
// Validierung
|
||||
if (!player_id || !supabase_user_id) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Player ID und Supabase User ID sind erforderlich'
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// Prüfen ob Spieler existiert
|
||||
const playerExists = await pool.query(
|
||||
'SELECT id, firstname, lastname FROM players WHERE id = $1',
|
||||
[player_id]
|
||||
);
|
||||
|
||||
if (playerExists.rows.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Spieler nicht gefunden'
|
||||
});
|
||||
}
|
||||
|
||||
// Prüfen ob Supabase User bereits verknüpft ist
|
||||
const existingLink = await pool.query(
|
||||
'SELECT id FROM players WHERE supabase_user_id = $1',
|
||||
[supabase_user_id]
|
||||
);
|
||||
|
||||
if (existingLink.rows.length > 0) {
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
message: 'Dieser Benutzer ist bereits mit einem Spieler verknüpft'
|
||||
});
|
||||
}
|
||||
|
||||
// Verknüpfung erstellen
|
||||
const result = await pool.query(
|
||||
'UPDATE players SET supabase_user_id = $1 WHERE id = $2 RETURNING id, firstname, lastname, rfiduid',
|
||||
[supabase_user_id, player_id]
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Spieler erfolgreich verknüpft',
|
||||
data: result.rows[0]
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Verknüpfen des Spielers:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Interner Serverfehler beim Verknüpfen des Spielers'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Get user times by Supabase user ID (no auth required for dashboard)
|
||||
router.get('/user-times/:supabase_user_id', async (req, res) => {
|
||||
const { supabase_user_id } = req.params;
|
||||
|
||||
try {
|
||||
// Finde verknüpften Spieler
|
||||
const playerResult = await pool.query(
|
||||
'SELECT id FROM players WHERE supabase_user_id = $1',
|
||||
[supabase_user_id]
|
||||
);
|
||||
|
||||
if (playerResult.rows.length === 0) {
|
||||
return res.json([]); // Noch keine Verknüpfung
|
||||
}
|
||||
|
||||
const player_id = playerResult.rows[0].id;
|
||||
|
||||
// Hole alle Zeiten für diesen Spieler mit Location-Namen
|
||||
const timesResult = await pool.query(`
|
||||
SELECT
|
||||
t.id,
|
||||
t.recorded_time,
|
||||
t.created_at,
|
||||
l.name as location_name,
|
||||
l.latitude,
|
||||
l.longitude
|
||||
FROM times t
|
||||
JOIN locations l ON t.location_id = l.id
|
||||
WHERE t.player_id = $1
|
||||
ORDER BY t.created_at DESC
|
||||
`, [player_id]);
|
||||
|
||||
res.json(timesResult.rows);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen der Benutzerzeiten:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Fehler beim Abrufen der Benutzerzeiten'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Get player info by Supabase user ID (no auth required for dashboard)
|
||||
router.get('/user-player/:supabase_user_id', async (req, res) => {
|
||||
const { supabase_user_id } = req.params;
|
||||
|
||||
try {
|
||||
const result = await pool.query(
|
||||
'SELECT id, firstname, lastname, birthdate, rfiduid FROM players WHERE supabase_user_id = $1',
|
||||
[supabase_user_id]
|
||||
);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Kein verknüpfter Spieler gefunden'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result.rows[0]
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen der Spielerdaten:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Fehler beim Abrufen der Spielerdaten'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Link user by RFID UID (scanned from QR code)
|
||||
router.post('/link-by-rfid', async (req, res) => {
|
||||
const { rfiduid, supabase_user_id } = req.body;
|
||||
|
||||
// Validierung
|
||||
if (!rfiduid || !supabase_user_id) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'RFID UID und Supabase User ID sind erforderlich'
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// Prüfen ob Spieler mit dieser RFID UID existiert
|
||||
const playerResult = await pool.query(
|
||||
'SELECT id, firstname, lastname, rfiduid, supabase_user_id FROM players WHERE rfiduid = $1',
|
||||
[rfiduid]
|
||||
);
|
||||
|
||||
if (playerResult.rows.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: `Kein Spieler mit RFID UID '${rfiduid}' gefunden. Bitte erstelle zuerst einen Spieler mit dieser RFID UID.`
|
||||
});
|
||||
}
|
||||
|
||||
const player = playerResult.rows[0];
|
||||
|
||||
// Prüfen ob dieser Spieler bereits mit einem anderen Benutzer verknüpft ist
|
||||
if (player.supabase_user_id && player.supabase_user_id !== supabase_user_id) {
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
message: 'Dieser Spieler ist bereits mit einem anderen Benutzer verknüpft'
|
||||
});
|
||||
}
|
||||
|
||||
// Prüfen ob dieser Benutzer bereits mit einem anderen Spieler verknüpft ist
|
||||
const existingLink = await pool.query(
|
||||
'SELECT id, firstname, lastname FROM players WHERE supabase_user_id = $1 AND id != $2',
|
||||
[supabase_user_id, player.id]
|
||||
);
|
||||
|
||||
if (existingLink.rows.length > 0) {
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
message: `Du bist bereits mit dem Spieler '${existingLink.rows[0].firstname} ${existingLink.rows[0].lastname}' verknüpft. Ein Benutzer kann nur mit einem Spieler verknüpft sein.`
|
||||
});
|
||||
}
|
||||
|
||||
// Verknüpfung erstellen (falls noch nicht vorhanden)
|
||||
if (!player.supabase_user_id) {
|
||||
await pool.query(
|
||||
'UPDATE players SET supabase_user_id = $1 WHERE id = $2',
|
||||
[supabase_user_id, player.id]
|
||||
);
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'RFID erfolgreich verknüpft',
|
||||
data: {
|
||||
id: player.id,
|
||||
firstname: player.firstname,
|
||||
lastname: player.lastname,
|
||||
rfiduid: player.rfiduid
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Verknüpfen per RFID UID:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Interner Serverfehler beim Verknüpfen per RFID UID'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = { router, requireApiKey };
|
||||
|
||||
Reference in New Issue
Block a user