106 lines
4.1 KiB
PHP
106 lines
4.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require __DIR__ . '/../../includes/bootstrap.php';
|
|
|
|
require_admin_login();
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
if (!csrf_check((string)($_POST['csrf'] ?? ''))) {
|
|
flash_set('danger', 'Bad CSRF token.');
|
|
header('Location: ' . url_path('/public/admin/dashboard.php'));
|
|
exit;
|
|
}
|
|
|
|
$token = trim((string)($_POST['access_token'] ?? ''));
|
|
$ttl = (int)($_POST['ttl'] ?? 3600);
|
|
if ($ttl < 300) $ttl = 300;
|
|
|
|
if ($token === '') {
|
|
flash_set('danger', 'Token is empty.');
|
|
header('Location: ' . url_path('/public/admin/spotify_token.php'));
|
|
exit;
|
|
}
|
|
|
|
$exp = time() + $ttl;
|
|
|
|
// ensure schema
|
|
try { pdo()->exec("ALTER TABLE spotify_tokens ADD COLUMN access_token TEXT NULL"); } catch (Throwable $e) {}
|
|
try { pdo()->exec("ALTER TABLE spotify_tokens ADD COLUMN access_expires INT NULL"); } catch (Throwable $e) {}
|
|
try { pdo()->exec("INSERT IGNORE INTO spotify_tokens (id) VALUES (1)"); } catch (Throwable $e) {}
|
|
|
|
pdo()->prepare("UPDATE spotify_tokens SET access_token=?, access_expires=? WHERE id=1")
|
|
->execute([$token, $exp]);
|
|
|
|
flash_set('success', 'Spotify access token saved (temporary).');
|
|
header('Location: ' . url_path('/public/admin/dashboard.php'));
|
|
exit;
|
|
}
|
|
?>
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>Spotify Token • Admin</title>
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/remixicon@4.6.0/fonts/remixicon.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="<?= htmlspecialchars(url_path('/css/admin.css')) ?>">
|
|
</head>
|
|
<body class="min-vh-100">
|
|
<div class="bg-aurora"></div>
|
|
<div class="bg-grid"></div>
|
|
|
|
<div class="topbar-glass py-3 mb-4">
|
|
<div class="container d-flex align-items-center justify-content-between">
|
|
<div class="d-flex align-items-center gap-3">
|
|
<div class="brand-badge">GM</div>
|
|
<div>
|
|
<div class="text-white-50 small">Portfolio Admin</div>
|
|
<div class="fw-bold hero-gradient">Spotify Token</div>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<a class="navlink" href="<?= htmlspecialchars(url_path('/public/admin/dashboard.php')) ?>"><i class="ri-dashboard-line"></i><span>Dashboard</span></a>
|
|
<a class="navlink" href="<?= htmlspecialchars(url_path('/public/admin/logout.php')) ?>"><i class="ri-logout-box-r-line"></i><span>Logout</span></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container pb-5" style="max-width: 900px;">
|
|
<div class="card-glass p-4 p-md-5 rounded-4">
|
|
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-2">
|
|
<div class="pill d-inline-flex align-items-center gap-2">
|
|
<span class="dot"></span> Temporary method
|
|
</div>
|
|
<span class="tag"><i class="ri-alert-line"></i> Expires</span>
|
|
</div>
|
|
|
|
<h1 class="h3 m-0">Paste Spotify Access Token</h1>
|
|
<div class="text-white-50 mt-2">
|
|
Access tokens expire (usually ~1h). Best solution is storing a refresh token and letting <code>/api/spotify.php</code> refresh automatically.
|
|
</div>
|
|
|
|
<form method="post" class="row g-3 mt-3">
|
|
<input type="hidden" name="csrf" value="<?= htmlspecialchars(csrf_token()) ?>">
|
|
|
|
<div class="col-12">
|
|
<label class="form-label text-white-50">Access token</label>
|
|
<textarea class="form-control" name="access_token" rows="5" required></textarea>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label text-white-50">TTL seconds</label>
|
|
<input class="form-control" name="ttl" type="number" value="3600" min="300">
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<button class="btn btn-violet px-4 py-2"><i class="ri-save-3-line"></i> Save Token</button>
|
|
<a class="btn btn-outline-light ms-2" href="<?= htmlspecialchars(url_path('/public/admin/dashboard.php')) ?>">Back</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|