Import initial du site depuis le serveur
This commit is contained in:
+97
-97
@@ -1,97 +1,97 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
if (session_status() === PHP_SESSION_NONE) { session_start(); }
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
exit('Méthode non autorisée');
|
||||
}
|
||||
|
||||
// CSRF
|
||||
if (empty($_POST['csrf_token']) || $_POST['csrf_token'] !== ($_SESSION['csrf_token'] ?? '')) {
|
||||
http_response_code(400);
|
||||
exit('Token CSRF invalide.');
|
||||
}
|
||||
|
||||
// Vérif login
|
||||
if (empty($_SESSION['user_id'])) {
|
||||
http_response_code(403);
|
||||
exit('Tu dois être connecté pour acheter.');
|
||||
}
|
||||
|
||||
$user_id = (int)$_SESSION['user_id'];
|
||||
$item_id = isset($_POST['item_id']) ? (int)$_POST['item_id'] : 0;
|
||||
|
||||
$pdo = pdo_connect();
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// Vérifie si le user possède déjà un item
|
||||
$stmt = $pdo->prepare("SELECT ui.id, i.name
|
||||
FROM user_items ui
|
||||
JOIN items i ON ui.item_id = i.id
|
||||
WHERE ui.user_id = :uid
|
||||
LIMIT 1 FOR UPDATE");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$existing = $stmt->fetch();
|
||||
|
||||
if ($existing) {
|
||||
$pdo->rollBack();
|
||||
exit("Tu possèdes déjà un item actif : " . htmlspecialchars($existing['name']));
|
||||
}
|
||||
|
||||
// Récupère item
|
||||
$stmt = $pdo->prepare("SELECT id, name, price FROM items WHERE id = :id FOR UPDATE");
|
||||
$stmt->execute([':id' => $item_id]);
|
||||
$item = $stmt->fetch();
|
||||
if (!$item) {
|
||||
$pdo->rollBack();
|
||||
exit('Item introuvable.');
|
||||
}
|
||||
|
||||
$total = (int)$item['price'];
|
||||
|
||||
// Vérifie aura
|
||||
$stmt = $pdo->prepare("SELECT aura FROM users WHERE id = :uid FOR UPDATE");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$u = $stmt->fetch();
|
||||
if (!$u) {
|
||||
$pdo->rollBack();
|
||||
exit('Utilisateur introuvable.');
|
||||
}
|
||||
$aura = (int)$u['aura'];
|
||||
|
||||
if ($aura < $total) {
|
||||
$pdo->rollBack();
|
||||
exit('Tu n\'as pas assez d\'aura pour cet achat.');
|
||||
}
|
||||
|
||||
// Débite l'aura
|
||||
$stmt = $pdo->prepare("UPDATE users SET aura = aura - :amt WHERE id = :uid");
|
||||
$stmt->execute([':amt' => $total, ':uid' => $user_id]);
|
||||
|
||||
// Ajoute item à user_items
|
||||
$stmt = $pdo->prepare("INSERT INTO user_items (user_id, item_id) VALUES (:uid, :iid)");
|
||||
$stmt->execute([':uid' => $user_id, ':iid' => $item_id]);
|
||||
|
||||
// Log (version simplifiée, sans actor_discord_id ni type)
|
||||
$stmt = $pdo->prepare("INSERT INTO logs (user_id, amount, reason)
|
||||
VALUES (:uid, :amount, :reason)");
|
||||
$stmt->execute([
|
||||
':uid' => $user_id,
|
||||
':amount' => -$total,
|
||||
':reason' => 'Achat: ' . $item['name']
|
||||
]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
header('Location: shop.php?buy=ok');
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
if ($pdo->inTransaction()) $pdo->rollBack();
|
||||
echo "Erreur détaillée : " . $e->getMessage();
|
||||
var_dump($item_id, $user_id, $total, $aura);
|
||||
exit;
|
||||
}
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
if (session_status() === PHP_SESSION_NONE) { session_start(); }
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
exit('Méthode non autorisée');
|
||||
}
|
||||
|
||||
// CSRF
|
||||
if (empty($_POST['csrf_token']) || $_POST['csrf_token'] !== ($_SESSION['csrf_token'] ?? '')) {
|
||||
http_response_code(400);
|
||||
exit('Token CSRF invalide.');
|
||||
}
|
||||
|
||||
// Vérif login
|
||||
if (empty($_SESSION['user_id'])) {
|
||||
http_response_code(403);
|
||||
exit('Tu dois être connecté pour acheter.');
|
||||
}
|
||||
|
||||
$user_id = (int)$_SESSION['user_id'];
|
||||
$item_id = isset($_POST['item_id']) ? (int)$_POST['item_id'] : 0;
|
||||
|
||||
$pdo = pdo_connect();
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// Vérifie si le user possède déjà un item
|
||||
$stmt = $pdo->prepare("SELECT ui.id, i.name
|
||||
FROM user_items ui
|
||||
JOIN items i ON ui.item_id = i.id
|
||||
WHERE ui.user_id = :uid
|
||||
LIMIT 1 FOR UPDATE");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$existing = $stmt->fetch();
|
||||
|
||||
if ($existing) {
|
||||
$pdo->rollBack();
|
||||
exit("Tu possèdes déjà un item actif : " . htmlspecialchars($existing['name']));
|
||||
}
|
||||
|
||||
// Récupère item
|
||||
$stmt = $pdo->prepare("SELECT id, name, price FROM items WHERE id = :id FOR UPDATE");
|
||||
$stmt->execute([':id' => $item_id]);
|
||||
$item = $stmt->fetch();
|
||||
if (!$item) {
|
||||
$pdo->rollBack();
|
||||
exit('Item introuvable.');
|
||||
}
|
||||
|
||||
$total = (int)$item['price'];
|
||||
|
||||
// Vérifie aura
|
||||
$stmt = $pdo->prepare("SELECT aura FROM users WHERE id = :uid FOR UPDATE");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$u = $stmt->fetch();
|
||||
if (!$u) {
|
||||
$pdo->rollBack();
|
||||
exit('Utilisateur introuvable.');
|
||||
}
|
||||
$aura = (int)$u['aura'];
|
||||
|
||||
if ($aura < $total) {
|
||||
$pdo->rollBack();
|
||||
exit('Tu n\'as pas assez d\'aura pour cet achat.');
|
||||
}
|
||||
|
||||
// Débite l'aura
|
||||
$stmt = $pdo->prepare("UPDATE users SET aura = aura - :amt WHERE id = :uid");
|
||||
$stmt->execute([':amt' => $total, ':uid' => $user_id]);
|
||||
|
||||
// Ajoute item à user_items
|
||||
$stmt = $pdo->prepare("INSERT INTO user_items (user_id, item_id) VALUES (:uid, :iid)");
|
||||
$stmt->execute([':uid' => $user_id, ':iid' => $item_id]);
|
||||
|
||||
// Log (version simplifiée, sans actor_discord_id ni type)
|
||||
$stmt = $pdo->prepare("INSERT INTO logs (user_id, amount, reason)
|
||||
VALUES (:uid, :amount, :reason)");
|
||||
$stmt->execute([
|
||||
':uid' => $user_id,
|
||||
':amount' => -$total,
|
||||
':reason' => 'Achat: ' . $item['name']
|
||||
]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
header('Location: shop.php?buy=ok');
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
if ($pdo->inTransaction()) $pdo->rollBack();
|
||||
echo "Erreur détaillée : " . $e->getMessage();
|
||||
var_dump($item_id, $user_id, $total, $aura);
|
||||
exit;
|
||||
}
|
||||
|
||||
+120
-120
@@ -1,120 +1,120 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
if (!isset($_GET['code']) || !isset($_GET['state'])) {
|
||||
http_response_code(400);
|
||||
exit("Paramètres manquants.");
|
||||
}
|
||||
|
||||
// CSRF : vérifier state
|
||||
if (!isset($_SESSION['oauth2_state']) || $_GET['state'] !== $_SESSION['oauth2_state']) {
|
||||
unset($_SESSION['oauth2_state']);
|
||||
http_response_code(400);
|
||||
exit("Échec de la vérification de sécurité (state).");
|
||||
}
|
||||
unset($_SESSION['oauth2_state']);
|
||||
|
||||
$code = $_GET['code'];
|
||||
|
||||
// Étape 1 : échange du code contre un access_token
|
||||
$token_url = "https://discord.com/api/oauth2/token";
|
||||
$post_fields = [
|
||||
'client_id' => DISCORD_CLIENT_ID,
|
||||
'client_secret' => DISCORD_CLIENT_SECRET,
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => $code,
|
||||
'redirect_uri' => DISCORD_REDIRECT_URI,
|
||||
'scope' => 'identify email'
|
||||
];
|
||||
|
||||
$ch = curl_init($token_url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/x-www-form-urlencoded'
|
||||
]);
|
||||
// ⚠️ remet le SSL, mieux pour la prod
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ($response === false) {
|
||||
exit("Erreur cURL token: " . curl_error($ch));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$token_data = json_decode($response, true);
|
||||
if (!isset($token_data['access_token'])) {
|
||||
exit("Échec de l'échange de token: " . htmlspecialchars($response));
|
||||
}
|
||||
$access_token = $token_data['access_token'];
|
||||
|
||||
// Étape 2 : récupérer infos utilisateur
|
||||
$ch = curl_init("https://discord.com/api/users/@me");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
"Authorization: Bearer $access_token"
|
||||
]);
|
||||
$user_json = curl_exec($ch);
|
||||
if ($user_json === false) {
|
||||
exit("Erreur cURL user: " . curl_error($ch));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$user_data = json_decode($user_json, true);
|
||||
if (!isset($user_data['id'])) {
|
||||
exit("Impossible de récupérer l'utilisateur Discord. Réponse: " . htmlspecialchars($user_json));
|
||||
}
|
||||
|
||||
// Préparation des données
|
||||
$discord_id = $user_data['id'];
|
||||
$username = $user_data['username'] . (isset($user_data['discriminator']) && $user_data['discriminator'] !== "0" ? '#' . $user_data['discriminator'] : "");
|
||||
$email = $user_data['email'] ?? null;
|
||||
$avatar = !empty($user_data['avatar'])
|
||||
? "https://cdn.discordapp.com/avatars/{$discord_id}/{$user_data['avatar']}.png"
|
||||
: null;
|
||||
|
||||
// Étape 3 : DB
|
||||
try {
|
||||
$pdo = pdo_connect();
|
||||
} catch (Exception $e) {
|
||||
exit("Erreur DB : " . $e->getMessage());
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM users WHERE discord_id = :did LIMIT 1");
|
||||
$stmt->execute([':did' => $discord_id]);
|
||||
$u = $stmt->fetch();
|
||||
|
||||
if ($u) {
|
||||
$stmt = $pdo->prepare("UPDATE users SET username = :username, email = :email, profile_picture = :avatar WHERE discord_id = :did");
|
||||
$stmt->execute([
|
||||
':username' => $username,
|
||||
':email' => $email,
|
||||
':avatar' => $avatar,
|
||||
':did' => $discord_id
|
||||
]);
|
||||
$user_id = $u['id'];
|
||||
} else {
|
||||
$stmt = $pdo->prepare("INSERT INTO users (discord_id, username, email, profile_picture, aura, tier)
|
||||
VALUES (:did, :username, :email, :avatar, 0, 'Aura')");
|
||||
$stmt->execute([
|
||||
':did' => $discord_id,
|
||||
':username' => $username,
|
||||
':email' => $email,
|
||||
':avatar' => $avatar
|
||||
]);
|
||||
$user_id = $pdo->lastInsertId();
|
||||
}
|
||||
|
||||
// Étape 4 : session
|
||||
$_SESSION['user_id'] = $user_id;
|
||||
$_SESSION['discord_id'] = $discord_id;
|
||||
$_SESSION['username'] = $username;
|
||||
$_SESSION['profile_picture'] = $avatar;
|
||||
|
||||
// Étape 5 : redirection
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
if (!isset($_GET['code']) || !isset($_GET['state'])) {
|
||||
http_response_code(400);
|
||||
exit("Paramètres manquants.");
|
||||
}
|
||||
|
||||
// CSRF : vérifier state
|
||||
if (!isset($_SESSION['oauth2_state']) || $_GET['state'] !== $_SESSION['oauth2_state']) {
|
||||
unset($_SESSION['oauth2_state']);
|
||||
http_response_code(400);
|
||||
exit("Échec de la vérification de sécurité (state).");
|
||||
}
|
||||
unset($_SESSION['oauth2_state']);
|
||||
|
||||
$code = $_GET['code'];
|
||||
|
||||
// Étape 1 : échange du code contre un access_token
|
||||
$token_url = "https://discord.com/api/oauth2/token";
|
||||
$post_fields = [
|
||||
'client_id' => DISCORD_CLIENT_ID,
|
||||
'client_secret' => DISCORD_CLIENT_SECRET,
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => $code,
|
||||
'redirect_uri' => DISCORD_REDIRECT_URI,
|
||||
'scope' => 'identify email'
|
||||
];
|
||||
|
||||
$ch = curl_init($token_url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/x-www-form-urlencoded'
|
||||
]);
|
||||
// ⚠️ remet le SSL, mieux pour la prod
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ($response === false) {
|
||||
exit("Erreur cURL token: " . curl_error($ch));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$token_data = json_decode($response, true);
|
||||
if (!isset($token_data['access_token'])) {
|
||||
exit("Échec de l'échange de token: " . htmlspecialchars($response));
|
||||
}
|
||||
$access_token = $token_data['access_token'];
|
||||
|
||||
// Étape 2 : récupérer infos utilisateur
|
||||
$ch = curl_init("https://discord.com/api/users/@me");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
"Authorization: Bearer $access_token"
|
||||
]);
|
||||
$user_json = curl_exec($ch);
|
||||
if ($user_json === false) {
|
||||
exit("Erreur cURL user: " . curl_error($ch));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$user_data = json_decode($user_json, true);
|
||||
if (!isset($user_data['id'])) {
|
||||
exit("Impossible de récupérer l'utilisateur Discord. Réponse: " . htmlspecialchars($user_json));
|
||||
}
|
||||
|
||||
// Préparation des données
|
||||
$discord_id = $user_data['id'];
|
||||
$username = $user_data['username'] . (isset($user_data['discriminator']) && $user_data['discriminator'] !== "0" ? '#' . $user_data['discriminator'] : "");
|
||||
$email = $user_data['email'] ?? null;
|
||||
$avatar = !empty($user_data['avatar'])
|
||||
? "https://cdn.discordapp.com/avatars/{$discord_id}/{$user_data['avatar']}.png"
|
||||
: null;
|
||||
|
||||
// Étape 3 : DB
|
||||
try {
|
||||
$pdo = pdo_connect();
|
||||
} catch (Exception $e) {
|
||||
exit("Erreur DB : " . $e->getMessage());
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM users WHERE discord_id = :did LIMIT 1");
|
||||
$stmt->execute([':did' => $discord_id]);
|
||||
$u = $stmt->fetch();
|
||||
|
||||
if ($u) {
|
||||
$stmt = $pdo->prepare("UPDATE users SET username = :username, email = :email, profile_picture = :avatar WHERE discord_id = :did");
|
||||
$stmt->execute([
|
||||
':username' => $username,
|
||||
':email' => $email,
|
||||
':avatar' => $avatar,
|
||||
':did' => $discord_id
|
||||
]);
|
||||
$user_id = $u['id'];
|
||||
} else {
|
||||
$stmt = $pdo->prepare("INSERT INTO users (discord_id, username, email, profile_picture, aura, tier)
|
||||
VALUES (:did, :username, :email, :avatar, 0, 'Aura')");
|
||||
$stmt->execute([
|
||||
':did' => $discord_id,
|
||||
':username' => $username,
|
||||
':email' => $email,
|
||||
':avatar' => $avatar
|
||||
]);
|
||||
$user_id = $pdo->lastInsertId();
|
||||
}
|
||||
|
||||
// Étape 4 : session
|
||||
$_SESSION['user_id'] = $user_id;
|
||||
$_SESSION['discord_id'] = $discord_id;
|
||||
$_SESSION['username'] = $username;
|
||||
$_SESSION['profile_picture'] = $avatar;
|
||||
|
||||
// Étape 5 : redirection
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
|
||||
+25
-25
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
// config.php
|
||||
session_start();
|
||||
|
||||
define('DB_HOST', '127.0.0.1');
|
||||
define('DB_PORT', '3306'); // ou 8035 si tu as changé
|
||||
define('DB_NAME', 'banque_aura');
|
||||
define('DB_USER', 'root');
|
||||
define('DB_PASS', 'root');
|
||||
|
||||
define('DISCORD_CLIENT_ID', '1318190631914307645');
|
||||
define('DISCORD_CLIENT_SECRET', 'zRXVwXeAYSSL1YbSwPkNVgrgBJN6-i1_');
|
||||
define('DISCORD_REDIRECT_URI', 'http://128.78.3.237:8082/aura_bank/callback.php'); // adapter
|
||||
|
||||
$options = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"
|
||||
];
|
||||
|
||||
function pdo_connect(){
|
||||
global $options;
|
||||
$dsn = "mysql:host=".DB_HOST.";port=".DB_PORT.";dbname=".DB_NAME.";charset=utf8mb4";
|
||||
return new PDO($dsn, DB_USER, DB_PASS, $options);
|
||||
}
|
||||
<?php
|
||||
// config.php
|
||||
session_start();
|
||||
|
||||
define('DB_HOST', '127.0.0.1');
|
||||
define('DB_PORT', '3306'); // ou 8035 si tu as changé
|
||||
define('DB_NAME', 'banque_aura');
|
||||
define('DB_USER', 'root');
|
||||
define('DB_PASS', 'root');
|
||||
|
||||
define('DISCORD_CLIENT_ID', '1318190631914307645');
|
||||
define('DISCORD_CLIENT_SECRET', 'zRXVwXeAYSSL1YbSwPkNVgrgBJN6-i1_');
|
||||
define('DISCORD_REDIRECT_URI', 'http://128.78.3.237:8082/aura_bank/callback.php'); // adapter
|
||||
|
||||
$options = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"
|
||||
];
|
||||
|
||||
function pdo_connect(){
|
||||
global $options;
|
||||
$dsn = "mysql:host=".DB_HOST.";port=".DB_PORT.";dbname=".DB_NAME.";charset=utf8mb4";
|
||||
return new PDO($dsn, DB_USER, DB_PASS, $options);
|
||||
}
|
||||
|
||||
+26
-26
@@ -1,26 +1,26 @@
|
||||
<?php
|
||||
// functions.php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
function get_top_users($limit = 10) {
|
||||
$pdo = pdo_connect();
|
||||
$stmt = $pdo->prepare("SELECT username, aura, discord_id, tier, profile_picture FROM users ORDER BY aura DESC LIMIT :lim");
|
||||
$stmt->bindValue(':lim', (int)$limit, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
function get_user_by_discord($discord_id) {
|
||||
$pdo = pdo_connect();
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE discord_id = :did LIMIT 1");
|
||||
$stmt->execute([':did' => $discord_id]);
|
||||
return $stmt->fetch();
|
||||
}
|
||||
|
||||
function get_user_rank($aura) {
|
||||
$pdo = pdo_connect();
|
||||
$stmt = $pdo->prepare("SELECT COUNT(*) + 1 AS 'rank' FROM users WHERE aura > :aura");
|
||||
$stmt->execute([':aura' => $aura]);
|
||||
$r = $stmt->fetch();
|
||||
return $r ? (int)$r['rank'] : null;
|
||||
}
|
||||
<?php
|
||||
// functions.php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
function get_top_users($limit = 10) {
|
||||
$pdo = pdo_connect();
|
||||
$stmt = $pdo->prepare("SELECT username, aura, discord_id, tier, profile_picture FROM users ORDER BY aura DESC LIMIT :lim");
|
||||
$stmt->bindValue(':lim', (int)$limit, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
function get_user_by_discord($discord_id) {
|
||||
$pdo = pdo_connect();
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE discord_id = :did LIMIT 1");
|
||||
$stmt->execute([':did' => $discord_id]);
|
||||
return $stmt->fetch();
|
||||
}
|
||||
|
||||
function get_user_rank($aura) {
|
||||
$pdo = pdo_connect();
|
||||
$stmt = $pdo->prepare("SELECT COUNT(*) + 1 AS 'rank' FROM users WHERE aura > :aura");
|
||||
$stmt->execute([':aura' => $aura]);
|
||||
$r = $stmt->fetch();
|
||||
return $r ? (int)$r['rank'] : null;
|
||||
}
|
||||
|
||||
+78
-78
@@ -1,78 +1,78 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/functions.php';
|
||||
$top = get_top_users(10);
|
||||
require_once __DIR__ . '/config.php';
|
||||
$logged = isset($_SESSION['discord_id']);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Banque de l'Aura — Classement</title>
|
||||
<style>
|
||||
body{font-family:Arial,Helvetica,sans-serif;background:#f4f4f9;color:#222;padding:20px}
|
||||
.card{max-width:800px;margin:0 auto;background:#fff;padding:18px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.06)}
|
||||
h1{margin:0 0 12px}
|
||||
table{width:100%;border-collapse:collapse}
|
||||
th,td{padding:10px;border-bottom:1px solid #eee;text-align:left;vertical-align:middle}
|
||||
th{background:#fbfbfc}
|
||||
.pos-1::before{content:"🥇 ";}
|
||||
.pos-2::before{content:"🥈 ";}
|
||||
.pos-3::before{content:"🥉 ";}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;object-fit:cover;vertical-align:middle;margin-right:8px}
|
||||
.user-link{display:flex;align-items:center;text-decoration:none;color:#222}
|
||||
.user-link:hover{text-decoration:underline}
|
||||
.user-id{font-size:12px;color:#666;margin-left:40px;margin-top:-4px}
|
||||
.welcome{display:flex;align-items:center;gap:12px;margin-bottom:18px;font-size:16px}
|
||||
.welcome img{width:40px;height:40px;border-radius:50%;object-fit:cover}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<?php if ($logged): ?>
|
||||
<div class="welcome" style="display:flex;align-items:center;gap:12px;margin-bottom:16px;">
|
||||
<?php if(!empty($_SESSION['profile_picture'])): ?>
|
||||
<a href="profile.php?discord_id=<?= urlencode($_SESSION['discord_id']) ?>">
|
||||
<img src="<?= htmlspecialchars($_SESSION['profile_picture']) ?>" alt="Avatar" style="width:40px;height:40px;border-radius:50%;object-fit:cover;">
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<span style="font-size:16px;">
|
||||
Bienvenue,
|
||||
<a href="profile.php?discord_id=<?= urlencode($_SESSION['discord_id']) ?>" style="text-decoration:none;color:#222;">
|
||||
<strong><?= htmlspecialchars($_SESSION['username']) ?></strong>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<a href="login.php">Se connecter avec Discord</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<h1>🏆 Classement des meilleures auras</h1>
|
||||
<?php if(empty($top)): ?>
|
||||
<p>Le classement est vide.</p>
|
||||
<?php else: ?>
|
||||
<table>
|
||||
<thead><tr><th>#</th><th>Utilisateur</th><th>Aura</th><th>Grade</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach($top as $i => $row): ?>
|
||||
<?php $pos = $i + 1; $cls = $pos<=3 ? "pos-{$pos}" : ""; ?>
|
||||
<tr>
|
||||
<td class="<?= htmlspecialchars($cls) ?>"><?= $pos ?></td>
|
||||
<td>
|
||||
<?php if(!empty($row['profile_picture'])): ?>
|
||||
<img src="<?= htmlspecialchars($row['profile_picture']) ?>" alt="" class="avatar">
|
||||
<?php endif; ?>
|
||||
<strong><?= htmlspecialchars($row['username']) ?></strong>
|
||||
<div class="user-id">ID: <?= htmlspecialchars($row['discord_id']) ?></div>
|
||||
</td>
|
||||
<td><?= (int)$row['aura'] ?></td>
|
||||
<td><?= htmlspecialchars($row['tier']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
require_once __DIR__ . '/functions.php';
|
||||
$top = get_top_users(10);
|
||||
require_once __DIR__ . '/config.php';
|
||||
$logged = isset($_SESSION['discord_id']);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Banque de l'Aura — Classement</title>
|
||||
<style>
|
||||
body{font-family:Arial,Helvetica,sans-serif;background:#f4f4f9;color:#222;padding:20px}
|
||||
.card{max-width:800px;margin:0 auto;background:#fff;padding:18px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.06)}
|
||||
h1{margin:0 0 12px}
|
||||
table{width:100%;border-collapse:collapse}
|
||||
th,td{padding:10px;border-bottom:1px solid #eee;text-align:left;vertical-align:middle}
|
||||
th{background:#fbfbfc}
|
||||
.pos-1::before{content:"🥇 ";}
|
||||
.pos-2::before{content:"🥈 ";}
|
||||
.pos-3::before{content:"🥉 ";}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;object-fit:cover;vertical-align:middle;margin-right:8px}
|
||||
.user-link{display:flex;align-items:center;text-decoration:none;color:#222}
|
||||
.user-link:hover{text-decoration:underline}
|
||||
.user-id{font-size:12px;color:#666;margin-left:40px;margin-top:-4px}
|
||||
.welcome{display:flex;align-items:center;gap:12px;margin-bottom:18px;font-size:16px}
|
||||
.welcome img{width:40px;height:40px;border-radius:50%;object-fit:cover}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<?php if ($logged): ?>
|
||||
<div class="welcome" style="display:flex;align-items:center;gap:12px;margin-bottom:16px;">
|
||||
<?php if(!empty($_SESSION['profile_picture'])): ?>
|
||||
<a href="profile.php?discord_id=<?= urlencode($_SESSION['discord_id']) ?>">
|
||||
<img src="<?= htmlspecialchars($_SESSION['profile_picture']) ?>" alt="Avatar" style="width:40px;height:40px;border-radius:50%;object-fit:cover;">
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<span style="font-size:16px;">
|
||||
Bienvenue,
|
||||
<a href="profile.php?discord_id=<?= urlencode($_SESSION['discord_id']) ?>" style="text-decoration:none;color:#222;">
|
||||
<strong><?= htmlspecialchars($_SESSION['username']) ?></strong>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<a href="login.php">Se connecter avec Discord</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<h1>🏆 Classement des meilleures auras</h1>
|
||||
<?php if(empty($top)): ?>
|
||||
<p>Le classement est vide.</p>
|
||||
<?php else: ?>
|
||||
<table>
|
||||
<thead><tr><th>#</th><th>Utilisateur</th><th>Aura</th><th>Grade</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach($top as $i => $row): ?>
|
||||
<?php $pos = $i + 1; $cls = $pos<=3 ? "pos-{$pos}" : ""; ?>
|
||||
<tr>
|
||||
<td class="<?= htmlspecialchars($cls) ?>"><?= $pos ?></td>
|
||||
<td>
|
||||
<?php if(!empty($row['profile_picture'])): ?>
|
||||
<img src="<?= htmlspecialchars($row['profile_picture']) ?>" alt="" class="avatar">
|
||||
<?php endif; ?>
|
||||
<strong><?= htmlspecialchars($row['username']) ?></strong>
|
||||
<div class="user-id">ID: <?= htmlspecialchars($row['discord_id']) ?></div>
|
||||
</td>
|
||||
<td><?= (int)$row['aura'] ?></td>
|
||||
<td><?= htmlspecialchars($row['tier']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+30
-30
@@ -1,30 +1,30 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
// scopes : identify pour ID + username, email si tu veux email
|
||||
$scope = 'identify email';
|
||||
|
||||
// génère un state CSRF
|
||||
$state = bin2hex(random_bytes(16));
|
||||
$_SESSION['oauth2_state'] = $state;
|
||||
|
||||
$params = http_build_query([
|
||||
'client_id' => DISCORD_CLIENT_ID,
|
||||
'redirect_uri' => DISCORD_REDIRECT_URI,
|
||||
'response_type' => 'code',
|
||||
'scope' => $scope,
|
||||
'state' => $state,
|
||||
'prompt' => 'consent'
|
||||
]);
|
||||
|
||||
$discord_authorize_url = "https://discord.com/oauth2/authorize?$params";
|
||||
?>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"><title>Login Discord</title></head>
|
||||
<body>
|
||||
<a href="<?= htmlspecialchars($discord_authorize_url) ?>">
|
||||
<img src="https://raw.githubusercontent.com/DiscordAssets/discord-open-graph/main/discord_logo.png" alt="Discord" style="height:28px;vertical-align:middle"> Se connecter avec Discord
|
||||
</a>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
// scopes : identify pour ID + username, email si tu veux email
|
||||
$scope = 'identify email';
|
||||
|
||||
// génère un state CSRF
|
||||
$state = bin2hex(random_bytes(16));
|
||||
$_SESSION['oauth2_state'] = $state;
|
||||
|
||||
$params = http_build_query([
|
||||
'client_id' => DISCORD_CLIENT_ID,
|
||||
'redirect_uri' => DISCORD_REDIRECT_URI,
|
||||
'response_type' => 'code',
|
||||
'scope' => $scope,
|
||||
'state' => $state,
|
||||
'prompt' => 'consent'
|
||||
]);
|
||||
|
||||
$discord_authorize_url = "https://discord.com/oauth2/authorize?$params";
|
||||
?>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"><title>Login Discord</title></head>
|
||||
<body>
|
||||
<a href="<?= htmlspecialchars($discord_authorize_url) ?>">
|
||||
<img src="https://raw.githubusercontent.com/DiscordAssets/discord-open-graph/main/discord_logo.png" alt="Discord" style="height:28px;vertical-align:middle"> Se connecter avec Discord
|
||||
</a>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
session_destroy();
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
session_destroy();
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
|
||||
+102
-102
@@ -1,102 +1,102 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/functions.php';
|
||||
|
||||
$discord_id = isset($_GET['discord_id']) ? trim($_GET['discord_id']) : null;
|
||||
if (!$discord_id) {
|
||||
http_response_code(400);
|
||||
echo "Paramètre discord_id manquant.";
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = get_user_by_discord($discord_id);
|
||||
if (!$user) {
|
||||
http_response_code(404);
|
||||
echo "Utilisateur introuvable.";
|
||||
exit;
|
||||
}
|
||||
|
||||
$rank = get_user_rank($user['aura']);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Profil de <?= htmlspecialchars($user['username']) ?></title>
|
||||
<style>
|
||||
body{font-family:Arial,Helvetica,sans-serif;background:#f4f4f9;color:#222;padding:20px}
|
||||
.card{max-width:700px;margin:0 auto;background:#fff;padding:18px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.06)}
|
||||
.avatar{width:96px;height:96px;border-radius:50%;object-fit:cover}
|
||||
.header{display:flex;align-items:center;gap:16px;justify-content:space-between}
|
||||
.user-info{flex:1}
|
||||
.btn-group{display:flex;gap:8px;margin-top:4px}
|
||||
.btn{padding:6px 12px;border:none;border-radius:4px;background:#4CAF50;color:white;text-decoration:none;cursor:pointer;}
|
||||
.btn.logout{background:#f44336;}
|
||||
table{width:100%;border-collapse:collapse;margin-top:8px;}
|
||||
th, td{padding:8px;border-bottom:1px solid #ccc;text-align:left;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="header">
|
||||
<div style="display:flex;align-items:center;gap:16px">
|
||||
<?php if(!empty($user['profile_picture'])): ?>
|
||||
<img src="<?= htmlspecialchars($user['profile_picture']) ?>" alt="" class="avatar">
|
||||
<?php endif; ?>
|
||||
<div class="user-info">
|
||||
<h2><?= htmlspecialchars($user['username']) ?></h2>
|
||||
<div>ID Discord: <?= htmlspecialchars($user['discord_id']) ?></div>
|
||||
<div style="margin-top:8px;"><strong>Aura:</strong> <?= (int)$user['aura'] ?> — <strong>Grade:</strong> <?= htmlspecialchars($user['tier']) ?></div>
|
||||
<div style="margin-top:6px;"><strong>Rang:</strong> #<?= (int)$rank ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a href="index.php" class="btn">Accueil</a>
|
||||
<a href="shop.php" class="btn">Boutique</a>
|
||||
<a href="logout.php" class="btn logout">Se déconnecter</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr style="margin:14px 0">
|
||||
|
||||
<h3>Historique récent</h3>
|
||||
<?php
|
||||
$pdo = pdo_connect();
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT amount, reason, created_at
|
||||
FROM logs
|
||||
WHERE user_id = :uid OR user_id = :discord_id
|
||||
ORDER BY created_at DESC
|
||||
");
|
||||
$stmt->execute([
|
||||
':uid' => $user['id'],
|
||||
':discord_id' => $user['discord_id']
|
||||
]);
|
||||
$logs = $stmt->fetchAll();
|
||||
if (!$logs): ?>
|
||||
<p>Aucun historique.</p>
|
||||
<?php else: ?>
|
||||
<table style="width:100%;border-collapse:collapse;margin-top:8px;">
|
||||
<thead>
|
||||
<tr style="background:#f0f0f0;text-align:left;">
|
||||
<th style="padding:8px;border-bottom:1px solid #ccc;">Date</th>
|
||||
<th style="padding:8px;border-bottom:1px solid #ccc;">Montant</th>
|
||||
<th style="padding:8px;border-bottom:1px solid #ccc;">Raison</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($logs as $l):
|
||||
$amount = (int)$l['amount'];
|
||||
$bg_color = $amount >= 0 ? '#d4f7d4' : '#f7d4d4'; // vert pale si gain, rouge pale si perte
|
||||
?>
|
||||
<tr style="background:<?= $bg_color ?>;border-bottom:1px solid #eee;">
|
||||
<td style="padding:10px;"><?= htmlspecialchars($l['created_at']) ?></td>
|
||||
<td style="padding:10px;"><?= $amount ?></td>
|
||||
<td style="padding:10px;"><?= htmlspecialchars($l['reason']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
require_once __DIR__ . '/functions.php';
|
||||
|
||||
$discord_id = isset($_GET['discord_id']) ? trim($_GET['discord_id']) : null;
|
||||
if (!$discord_id) {
|
||||
http_response_code(400);
|
||||
echo "Paramètre discord_id manquant.";
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = get_user_by_discord($discord_id);
|
||||
if (!$user) {
|
||||
http_response_code(404);
|
||||
echo "Utilisateur introuvable.";
|
||||
exit;
|
||||
}
|
||||
|
||||
$rank = get_user_rank($user['aura']);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Profil de <?= htmlspecialchars($user['username']) ?></title>
|
||||
<style>
|
||||
body{font-family:Arial,Helvetica,sans-serif;background:#f4f4f9;color:#222;padding:20px}
|
||||
.card{max-width:700px;margin:0 auto;background:#fff;padding:18px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.06)}
|
||||
.avatar{width:96px;height:96px;border-radius:50%;object-fit:cover}
|
||||
.header{display:flex;align-items:center;gap:16px;justify-content:space-between}
|
||||
.user-info{flex:1}
|
||||
.btn-group{display:flex;gap:8px;margin-top:4px}
|
||||
.btn{padding:6px 12px;border:none;border-radius:4px;background:#4CAF50;color:white;text-decoration:none;cursor:pointer;}
|
||||
.btn.logout{background:#f44336;}
|
||||
table{width:100%;border-collapse:collapse;margin-top:8px;}
|
||||
th, td{padding:8px;border-bottom:1px solid #ccc;text-align:left;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="header">
|
||||
<div style="display:flex;align-items:center;gap:16px">
|
||||
<?php if(!empty($user['profile_picture'])): ?>
|
||||
<img src="<?= htmlspecialchars($user['profile_picture']) ?>" alt="" class="avatar">
|
||||
<?php endif; ?>
|
||||
<div class="user-info">
|
||||
<h2><?= htmlspecialchars($user['username']) ?></h2>
|
||||
<div>ID Discord: <?= htmlspecialchars($user['discord_id']) ?></div>
|
||||
<div style="margin-top:8px;"><strong>Aura:</strong> <?= (int)$user['aura'] ?> — <strong>Grade:</strong> <?= htmlspecialchars($user['tier']) ?></div>
|
||||
<div style="margin-top:6px;"><strong>Rang:</strong> #<?= (int)$rank ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a href="index.php" class="btn">Accueil</a>
|
||||
<a href="shop.php" class="btn">Boutique</a>
|
||||
<a href="logout.php" class="btn logout">Se déconnecter</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr style="margin:14px 0">
|
||||
|
||||
<h3>Historique récent</h3>
|
||||
<?php
|
||||
$pdo = pdo_connect();
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT amount, reason, created_at
|
||||
FROM logs
|
||||
WHERE user_id = :uid OR user_id = :discord_id
|
||||
ORDER BY created_at DESC
|
||||
");
|
||||
$stmt->execute([
|
||||
':uid' => $user['id'],
|
||||
':discord_id' => $user['discord_id']
|
||||
]);
|
||||
$logs = $stmt->fetchAll();
|
||||
if (!$logs): ?>
|
||||
<p>Aucun historique.</p>
|
||||
<?php else: ?>
|
||||
<table style="width:100%;border-collapse:collapse;margin-top:8px;">
|
||||
<thead>
|
||||
<tr style="background:#f0f0f0;text-align:left;">
|
||||
<th style="padding:8px;border-bottom:1px solid #ccc;">Date</th>
|
||||
<th style="padding:8px;border-bottom:1px solid #ccc;">Montant</th>
|
||||
<th style="padding:8px;border-bottom:1px solid #ccc;">Raison</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($logs as $l):
|
||||
$amount = (int)$l['amount'];
|
||||
$bg_color = $amount >= 0 ? '#d4f7d4' : '#f7d4d4'; // vert pale si gain, rouge pale si perte
|
||||
?>
|
||||
<tr style="background:<?= $bg_color ?>;border-bottom:1px solid #eee;">
|
||||
<td style="padding:10px;"><?= htmlspecialchars($l['created_at']) ?></td>
|
||||
<td style="padding:10px;"><?= $amount ?></td>
|
||||
<td style="padding:10px;"><?= htmlspecialchars($l['reason']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+143
-143
@@ -1,143 +1,143 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php'; // contient pdo_connect() et session start
|
||||
require_once __DIR__ . '/functions.php'; // si nécessaire
|
||||
|
||||
// Vérifie session
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$pdo = pdo_connect();
|
||||
|
||||
// Récupère les items
|
||||
$stmt = $pdo->query("SELECT id, name, description, price FROM items ORDER BY price ASC");
|
||||
$items = $stmt->fetchAll();
|
||||
|
||||
// Génère token CSRF simple
|
||||
if (empty($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(16));
|
||||
}
|
||||
|
||||
// Récupère saldo de l'utilisateur si connecté
|
||||
$logged = isset($_SESSION['user_id']);
|
||||
$userAura = null;
|
||||
if ($logged) {
|
||||
$stmt = $pdo->prepare("SELECT aura FROM users WHERE id = :uid LIMIT 1");
|
||||
$stmt->execute([':uid' => $_SESSION['user_id']]);
|
||||
$row = $stmt->fetch();
|
||||
$userAura = $row ? (int)$row['aura'] : 0;
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Boutique — Banque de l'Aura</title>
|
||||
<style>
|
||||
body{font-family:Arial,Helvetica,sans-serif;background:#f4f4f9;color:#222;padding:20px}
|
||||
.card{max-width:1000px;margin:0 auto;background:#fff;padding:18px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.06)}
|
||||
h1{margin:0 0 12px}
|
||||
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}
|
||||
.item{border:1px solid #eee;padding:12px;border-radius:8px;background:#fafafa;display:flex;flex-direction:column;gap:8px}
|
||||
.badge{width:32px;height:32px;object-fit:cover}
|
||||
.item-icon{width:32px;height:32px;object-fit:cover;vertical-align:middle;margin-right:8px}
|
||||
.price{font-weight:700}
|
||||
.stock{font-size:13px;color:#666}
|
||||
.buy-form{margin-top:auto}
|
||||
.btn{display:inline-block;padding:8px 12px;border-radius:6px;background:#2d8aef;color:#fff;text-decoration:none;border:none;cursor:pointer}
|
||||
.btn.disabled{opacity:.5;cursor:not-allowed;background:#9bbbed}
|
||||
.row-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
padding: 10px 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.row-top .user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.row-top img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.balance{font-weight:700}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="row-top">
|
||||
<h1>🛒 Boutique</h1>
|
||||
|
||||
<?php if ($logged): ?>
|
||||
<div class="user-info">
|
||||
<div class="balance">
|
||||
💎 Solde : <strong><?= htmlspecialchars($userAura ?? 0) ?> aura</strong>
|
||||
</div>
|
||||
|
||||
<div class="active_item">
|
||||
<?php
|
||||
$stmt = $pdo->prepare("SELECT i.name
|
||||
FROM user_items ui
|
||||
JOIN items i ON ui.item_id = i.id
|
||||
WHERE ui.user_id = :uid
|
||||
LIMIT 1");
|
||||
$stmt->execute([':uid' => $_SESSION['user_id']]);
|
||||
$activeItem = $stmt->fetch();
|
||||
?>
|
||||
<?php if ($activeItem): ?>
|
||||
🎖️ Item actif : <strong><?= htmlspecialchars($activeItem['name']) ?></strong>
|
||||
<?php else: ?>
|
||||
🎖️ Aucun item actif
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="profile-link">
|
||||
<a href="profile.php?discord_id=<?= urlencode($_SESSION['discord_id']) ?>">Voir mon profil</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="login-link">
|
||||
<a href="login.php">Se connecter avec Discord pour acheter</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid">
|
||||
<?php foreach($items as $it): ?>
|
||||
<div class="item">
|
||||
<div>
|
||||
<span class="badge"><img class="item-icon" src="img/items/<?= htmlspecialchars($it['id']) ?>.png"></span>
|
||||
<strong><?= htmlspecialchars($it['name']) ?></strong>
|
||||
</div>
|
||||
<?php if(!empty($it['description'])): ?>
|
||||
<div style="font-size:14px;color:#333"><?= htmlspecialchars($it['description']) ?></div>
|
||||
<?php endif; ?>
|
||||
<div class="price"><?= (int)$it['price'] ?> aura</div>
|
||||
|
||||
<form class="buy-form" method="post" action="buy.php">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="item_id" value="<?= (int)$it['id'] ?>">
|
||||
<?php
|
||||
$canBuy = $logged && ($userAura !== null && $userAura >= (int)$it['price']);
|
||||
?>
|
||||
<button class="btn <?= $canBuy ? '' : 'disabled' ?>" <?= $canBuy ? '' : 'disabled' ?>>
|
||||
Acheter
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php'; // contient pdo_connect() et session start
|
||||
require_once __DIR__ . '/functions.php'; // si nécessaire
|
||||
|
||||
// Vérifie session
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$pdo = pdo_connect();
|
||||
|
||||
// Récupère les items
|
||||
$stmt = $pdo->query("SELECT id, name, description, price FROM items ORDER BY price ASC");
|
||||
$items = $stmt->fetchAll();
|
||||
|
||||
// Génère token CSRF simple
|
||||
if (empty($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(16));
|
||||
}
|
||||
|
||||
// Récupère saldo de l'utilisateur si connecté
|
||||
$logged = isset($_SESSION['user_id']);
|
||||
$userAura = null;
|
||||
if ($logged) {
|
||||
$stmt = $pdo->prepare("SELECT aura FROM users WHERE id = :uid LIMIT 1");
|
||||
$stmt->execute([':uid' => $_SESSION['user_id']]);
|
||||
$row = $stmt->fetch();
|
||||
$userAura = $row ? (int)$row['aura'] : 0;
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Boutique — Banque de l'Aura</title>
|
||||
<style>
|
||||
body{font-family:Arial,Helvetica,sans-serif;background:#f4f4f9;color:#222;padding:20px}
|
||||
.card{max-width:1000px;margin:0 auto;background:#fff;padding:18px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.06)}
|
||||
h1{margin:0 0 12px}
|
||||
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}
|
||||
.item{border:1px solid #eee;padding:12px;border-radius:8px;background:#fafafa;display:flex;flex-direction:column;gap:8px}
|
||||
.badge{width:32px;height:32px;object-fit:cover}
|
||||
.item-icon{width:32px;height:32px;object-fit:cover;vertical-align:middle;margin-right:8px}
|
||||
.price{font-weight:700}
|
||||
.stock{font-size:13px;color:#666}
|
||||
.buy-form{margin-top:auto}
|
||||
.btn{display:inline-block;padding:8px 12px;border-radius:6px;background:#2d8aef;color:#fff;text-decoration:none;border:none;cursor:pointer}
|
||||
.btn.disabled{opacity:.5;cursor:not-allowed;background:#9bbbed}
|
||||
.row-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
padding: 10px 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.row-top .user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.row-top img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.balance{font-weight:700}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="row-top">
|
||||
<h1>🛒 Boutique</h1>
|
||||
|
||||
<?php if ($logged): ?>
|
||||
<div class="user-info">
|
||||
<div class="balance">
|
||||
💎 Solde : <strong><?= htmlspecialchars($userAura ?? 0) ?> aura</strong>
|
||||
</div>
|
||||
|
||||
<div class="active_item">
|
||||
<?php
|
||||
$stmt = $pdo->prepare("SELECT i.name
|
||||
FROM user_items ui
|
||||
JOIN items i ON ui.item_id = i.id
|
||||
WHERE ui.user_id = :uid
|
||||
LIMIT 1");
|
||||
$stmt->execute([':uid' => $_SESSION['user_id']]);
|
||||
$activeItem = $stmt->fetch();
|
||||
?>
|
||||
<?php if ($activeItem): ?>
|
||||
🎖️ Item actif : <strong><?= htmlspecialchars($activeItem['name']) ?></strong>
|
||||
<?php else: ?>
|
||||
🎖️ Aucun item actif
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="profile-link">
|
||||
<a href="profile.php?discord_id=<?= urlencode($_SESSION['discord_id']) ?>">Voir mon profil</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="login-link">
|
||||
<a href="login.php">Se connecter avec Discord pour acheter</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid">
|
||||
<?php foreach($items as $it): ?>
|
||||
<div class="item">
|
||||
<div>
|
||||
<span class="badge"><img class="item-icon" src="img/items/<?= htmlspecialchars($it['id']) ?>.png"></span>
|
||||
<strong><?= htmlspecialchars($it['name']) ?></strong>
|
||||
</div>
|
||||
<?php if(!empty($it['description'])): ?>
|
||||
<div style="font-size:14px;color:#333"><?= htmlspecialchars($it['description']) ?></div>
|
||||
<?php endif; ?>
|
||||
<div class="price"><?= (int)$it['price'] ?> aura</div>
|
||||
|
||||
<form class="buy-form" method="post" action="buy.php">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="item_id" value="<?= (int)$it['id'] ?>">
|
||||
<?php
|
||||
$canBuy = $logged && ($userAura !== null && $userAura >= (int)$it['price']);
|
||||
?>
|
||||
<button class="btn <?= $canBuy ? '' : 'disabled' ?>" <?= $canBuy ? '' : 'disabled' ?>>
|
||||
Acheter
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user