160 lines
3.5 KiB
PHP
160 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../db.php';
|
|
require_once __DIR__ . '/../auth.php';
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
function jsonResponse(array $data, int $status = 200): void
|
|
{
|
|
http_response_code($status);
|
|
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
exit;
|
|
}
|
|
|
|
function getInputData(): array
|
|
{
|
|
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
|
|
|
|
if (str_contains($contentType, 'application/json')) {
|
|
$raw = file_get_contents('php://input');
|
|
$data = json_decode($raw, true);
|
|
|
|
return is_array($data) ? $data : [];
|
|
}
|
|
|
|
return $_POST;
|
|
}
|
|
|
|
function getBearerTokenFromHeader(): ?string
|
|
{
|
|
$header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
|
|
|
|
if (preg_match('/Bearer\s+(.+)/', $header, $matches)) {
|
|
return trim($matches[1]);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
$api = $_GET['api'] ?? '';
|
|
|
|
switch ($api) {
|
|
|
|
case 'Login': {
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'error' => 'Login requires POST.'
|
|
], 405);
|
|
}
|
|
|
|
$data = getInputData();
|
|
|
|
$email = trim($data['email'] ?? '');
|
|
$password = (string)($data['password'] ?? '');
|
|
|
|
if ($email === '' || $password === '') {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'error' => 'Email and password are required.'
|
|
], 400);
|
|
}
|
|
|
|
$token = login($email, $password, false);
|
|
|
|
if ($token === null) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'error' => 'Invalid email or password.'
|
|
], 401);
|
|
}
|
|
|
|
$user = currentUser();
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'token_type' => 'Bearer',
|
|
'access_token' => $token,
|
|
'expires_in' => 43200,
|
|
'user' => $user
|
|
]);
|
|
}
|
|
|
|
case 'CreateToken': {
|
|
$user = currentUser();
|
|
|
|
if (!$user) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'error' => 'Not logged in.'
|
|
], 401);
|
|
}
|
|
|
|
$token = createAuthToken((int)$user['id']);
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'token_type' => 'Bearer',
|
|
'access_token' => $token,
|
|
'expires_in' => 43200,
|
|
'user' => $user
|
|
]);
|
|
}
|
|
|
|
case 'Me': {
|
|
$token = getBearerTokenFromHeader();
|
|
|
|
if ($token) {
|
|
$user = authenticateApiToken($token);
|
|
} else {
|
|
$user = currentUser();
|
|
}
|
|
|
|
if (!$user) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'error' => 'Not authenticated.'
|
|
], 401);
|
|
}
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'user' => $user
|
|
]);
|
|
}
|
|
|
|
case 'Logout': {
|
|
$token = getBearerTokenFromHeader();
|
|
|
|
if ($token) {
|
|
$tokenHash = hash('sha256', $token);
|
|
|
|
db()->prepare(
|
|
'UPDATE auth_tokens
|
|
SET revoked_at = NOW()
|
|
WHERE token_hash = ?
|
|
AND revoked_at IS NULL'
|
|
)->execute([$tokenHash]);
|
|
|
|
jsonResponse([
|
|
'success' => true
|
|
]);
|
|
}
|
|
|
|
logout();
|
|
|
|
jsonResponse([
|
|
'success' => true
|
|
]);
|
|
}
|
|
|
|
default: {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'error' => 'Unknown API action.'
|
|
], 404);
|
|
}
|
|
} |