Viel Push und achivements + AGB
This commit is contained in:
@@ -1045,7 +1045,7 @@ const { checkNameAgainstBlacklist, addToBlacklist, removeFromBlacklist, getBlack
|
||||
|
||||
// Create new player with RFID and blacklist validation (no auth required for dashboard)
|
||||
router.post('/v1/public/players/create-with-rfid', async (req, res) => {
|
||||
const { rfiduid, firstname, lastname, birthdate, supabase_user_id } = req.body;
|
||||
const { rfiduid, firstname, lastname, birthdate, supabase_user_id, agb_accepted } = req.body;
|
||||
|
||||
// Validierung
|
||||
if (!rfiduid || !firstname || !lastname || !birthdate) {
|
||||
@@ -1119,10 +1119,10 @@ router.post('/v1/public/players/create-with-rfid', async (req, res) => {
|
||||
|
||||
// Spieler in Datenbank einfügen
|
||||
const result = await pool.query(
|
||||
`INSERT INTO players (rfiduid, firstname, lastname, birthdate, supabase_user_id, created_at, show_in_leaderboard)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING id, rfiduid, firstname, lastname, birthdate, created_at`,
|
||||
[rfiduid, firstname, lastname, birthdate, supabase_user_id || null, new Date(), true]
|
||||
`INSERT INTO players (rfiduid, firstname, lastname, birthdate, supabase_user_id, created_at, show_in_leaderboard, agb_accepted)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING id, rfiduid, firstname, lastname, birthdate, created_at, agb_accepted`,
|
||||
[rfiduid, firstname, lastname, birthdate, supabase_user_id || null, new Date(), !!agb_accepted, !!agb_accepted]
|
||||
);
|
||||
|
||||
const newPlayer = result.rows[0];
|
||||
@@ -1824,6 +1824,12 @@ router.delete('/v1/admin/players/:id', requireAdminAuth, async (req, res) => {
|
||||
try {
|
||||
// Erst alle zugehörigen Zeiten löschen
|
||||
await pool.query('DELETE FROM times WHERE player_id = $1', [playerId]);
|
||||
|
||||
// Alle zugehörigen Notifications löschen
|
||||
await pool.query('DELETE FROM sent_notifications WHERE player_id = $1', [playerId]);
|
||||
|
||||
// Alle zugehörigen Player Achievements löschen
|
||||
await pool.query('DELETE FROM player_achievements WHERE player_id = $1', [playerId]);
|
||||
|
||||
// Dann den Spieler löschen
|
||||
const result = await pool.query('DELETE FROM players WHERE id = $1', [playerId]);
|
||||
@@ -2212,22 +2218,17 @@ router.get('/v1/public/times-with-details', async (req, res) => {
|
||||
|
||||
// Get all times with player and location details, ordered by time (fastest first)
|
||||
// Only show times from players who have opted into leaderboard visibility
|
||||
// SECURITY: Only return data needed for leaderboard display
|
||||
const result = await pool.query(`
|
||||
SELECT
|
||||
t.id,
|
||||
EXTRACT(EPOCH FROM t.recorded_time) as recorded_time_seconds,
|
||||
t.created_at,
|
||||
json_build_object(
|
||||
'id', p.id,
|
||||
'firstname', p.firstname,
|
||||
'lastname', p.lastname,
|
||||
'rfiduid', p.rfiduid
|
||||
'lastname', p.lastname
|
||||
) as player,
|
||||
json_build_object(
|
||||
'id', l.id,
|
||||
'name', l.name,
|
||||
'latitude', l.latitude,
|
||||
'longitude', l.longitude
|
||||
'name', l.name
|
||||
) as location
|
||||
FROM times t
|
||||
LEFT JOIN players p ON t.player_id = p.id
|
||||
@@ -2843,6 +2844,23 @@ router.get('/v1/public/best-times', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== LOGGING ENDPOINT ====================
|
||||
|
||||
// Log endpoint for client-side logging
|
||||
router.post('/v1/public/log', async (req, res) => {
|
||||
try {
|
||||
const { level, message, playerId } = req.body;
|
||||
const timestamp = new Date().toISOString();
|
||||
|
||||
console.log(`[${timestamp}] [${level?.toUpperCase() || 'INFO'}] [Player: ${playerId || 'unknown'}] ${message}`);
|
||||
|
||||
res.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Error processing log:', error);
|
||||
res.status(500).json({ success: false });
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== PUSH NOTIFICATION ENDPOINTS ====================
|
||||
|
||||
// Subscribe to push notifications
|
||||
@@ -3026,6 +3044,29 @@ router.get('/v1/public/notification-sent/:playerId/:type', async (req, res) => {
|
||||
const { playerId, type } = req.params;
|
||||
const { achievementId, locationId } = req.query;
|
||||
|
||||
// Validate required parameters
|
||||
if (!playerId || playerId === 'undefined' || playerId === 'null') {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Player ID ist erforderlich'
|
||||
});
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Notification Type ist erforderlich'
|
||||
});
|
||||
}
|
||||
|
||||
// Validate achievementId if provided
|
||||
if (achievementId && (achievementId === 'undefined' || achievementId === 'null')) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Ungültige Achievement ID'
|
||||
});
|
||||
}
|
||||
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
|
||||
const result = await pool.query(`
|
||||
@@ -3058,6 +3099,19 @@ router.post('/v1/public/notification-sent', async (req, res) => {
|
||||
try {
|
||||
const { playerId, notificationType, achievementId, locationId } = req.body;
|
||||
|
||||
// Log notification details to server console
|
||||
const logData = {
|
||||
playerId: playerId,
|
||||
notificationType: notificationType,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
|
||||
// Only add achievementId and locationId if they exist
|
||||
if (achievementId) logData.achievementId = achievementId;
|
||||
if (locationId) logData.locationId = locationId;
|
||||
|
||||
console.log('📱 Push Notification marked as sent:', logData);
|
||||
|
||||
await pool.query(`
|
||||
INSERT INTO sent_notifications (player_id, notification_type, achievement_id, location_id)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
|
||||
Reference in New Issue
Block a user