Commit ae3a9a78 authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat: FULL SYNC Phase 1+2 — ban enforcement, atomic economy, admin-controlled rewards

DATABASE CREATED (via SSH to Supabase):
- reward_config table: 8 configurable reward values (chess_win/loss/draw, daily, streak, etc.)
- seasons table: battle pass season config (name, dates, tiers, xp)
- challenge_templates table: 7 challenge types with rewards
- award_coins() function: atomic coin grant (prevents race conditions)

PLAYER APP CHANGES:
1. Ban enforcement: requireAuth() now checks is_banned + ban_expires_at
   - Returns 403 'Account banned' if player is banned
   - Respects expiration dates (temporary bans expire)

2. Economy from config: game.php reads chess_win_coins/draw/loss from reward_config
   - Admin can change reward values in DB → player app picks them up
   - No more hardcoded 50/20/10

3. Atomic coin award: calls award_coins() DB function
   - Single transaction: UPDATE profiles + INSERT economy_transactions
   - No race condition on concurrent coin grants

MANAGEMENT CAN NOW:
- Ban a player → immediately blocked from all player app actions
- Change reward_config values → player app uses new amounts
- Create seasons → player app reads active season from DB
- Create challenge templates → player app picks random 3 per day
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent af58cbf5
......@@ -158,10 +158,19 @@ function handleComplete($db, string $userId, array $input): void {
'result' => $result
]);
// Grant coins
$coins = ($result === 'win') ? 50 : (($result === 'draw') ? 20 : 10);
$currentCoins = $profile['coins'] ?? 0;
$db->update('profiles', ['coins' => $currentCoins + $coins], ['id' => 'eq.' . $userId]);
// Grant coins from reward_config (admin-configurable)
$rewardConfig = $sdb->get('reward_config', ['select' => 'key,value']);
$rewards = [];
if (is_array($rewardConfig) && !isset($rewardConfig['error'])) {
foreach ($rewardConfig as $r) $rewards[$r['key']] = intval($r['value']);
}
$coins = ($result === 'win') ? ($rewards['chess_win_coins'] ?? 50) : (($result === 'draw') ? ($rewards['chess_draw_coins'] ?? 20) : ($rewards['chess_loss_coins'] ?? 10));
// Use atomic DB function to prevent race conditions
$sdb->rpc('award_coins', ['p_player_id' => $userId, 'p_amount' => $coins, 'p_reason' => 'Chess ' . $result]);
// Legacy insert kept for compatibility
$currentCoins = ($profile['coins'] ?? 0) + $coins;
$sdb->insert('economy_transactions', [
'player_id' => $userId,
'type' => 'game_reward',
......
This diff is collapsed.
......@@ -27,6 +27,21 @@ function requireAuth(): string {
echo json_encode(['error' => 'Invalid or expired token']);
exit;
}
// Ban enforcement — check if player is banned
$userId = $user['id'] ?? null;
if ($userId) {
require_once __DIR__ . '/supabase.php';
$sdb = supabaseService();
$profiles = $sdb->get('profiles', ['id' => 'eq.' . $userId, 'select' => 'is_banned,ban_expires_at', 'limit' => 1]);
if (!empty($profiles) && !isset($profiles['error']) && ($profiles[0]['is_banned'] ?? false)) {
$banExpires = $profiles[0]['ban_expires_at'] ?? null;
if (!$banExpires || strtotime($banExpires) > time()) {
http_response_code(403);
echo json_encode(['error' => 'Account banned', 'ban_expires_at' => $banExpires]);
exit;
}
}
}
return $token;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment