feat: Add device-specific isolation for player IDs
- Add device ID generation (unique per device, stored in localStorage)
- Extend player ID format to: {basePlayerId}:{deviceId}
- Enable cross-domain sync on same device while keeping devices isolated
- Update backend APIs to support new player ID format
- Maintain backward compatibility with legacy UUID format
This allows:
- Each device (Desktop, Android, iOS) to have separate game states
- Cross-domain sync still works on the same device (hoerdle.de ↔ hördle.de)
- Easier debugging with visible device ID in player identifier
This commit is contained in:
@@ -7,10 +7,30 @@ const prisma = new PrismaClient();
|
||||
|
||||
/**
|
||||
* Validate UUID format (basic check)
|
||||
* Supports both legacy format (single UUID) and new format (basePlayerId:deviceId)
|
||||
*/
|
||||
function isValidUUID(uuid: string): boolean {
|
||||
function isValidPlayerId(playerId: string): boolean {
|
||||
// Legacy format: single UUID
|
||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
return uuidRegex.test(uuid);
|
||||
|
||||
// New format: basePlayerId:deviceId (two UUIDs separated by colon)
|
||||
const combinedRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
|
||||
return uuidRegex.test(playerId) || combinedRegex.test(playerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract base player ID from full player ID
|
||||
* Format: {basePlayerId}:{deviceId} -> {basePlayerId}
|
||||
* Legacy: {uuid} -> {uuid}
|
||||
*/
|
||||
function extractBasePlayerId(fullPlayerId: string): string {
|
||||
const colonIndex = fullPlayerId.indexOf(':');
|
||||
if (colonIndex === -1) {
|
||||
// Legacy format (no device ID) - return as is
|
||||
return fullPlayerId;
|
||||
}
|
||||
return fullPlayerId.substring(0, colonIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +53,7 @@ export async function GET(request: Request) {
|
||||
|
||||
// Get player identifier from header
|
||||
const playerId = request.headers.get('X-Player-Id');
|
||||
if (!playerId || !isValidUUID(playerId)) {
|
||||
if (!playerId || !isValidPlayerId(playerId)) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid or missing player identifier' },
|
||||
{ status: 400 }
|
||||
@@ -109,7 +129,7 @@ export async function POST(request: Request) {
|
||||
try {
|
||||
// Get player identifier from header
|
||||
const playerId = request.headers.get('X-Player-Id');
|
||||
if (!playerId || !isValidUUID(playerId)) {
|
||||
if (!playerId || !isValidPlayerId(playerId)) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid or missing player identifier' },
|
||||
{ status: 400 }
|
||||
|
||||
Reference in New Issue
Block a user