chore: восстановление репозитория из снапшота v0.3.1
Прежняя git-история утрачена при переносе проекта на машину владельца (снапшот без .git). Хэши коммитов в docs/reports/* относятся к утраченной истории. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
1c85091186
184 changed files with 33303 additions and 0 deletions
47
server/api/login.php
Normal file
47
server/api/login.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* POST /api/login.php {email, password}
|
||||
* → 200 {ok:true} + сессия | 401 | 403 | 413 | 422 | 429.
|
||||
* Rate limit проверяется ДО проверки пароля; успешный login чистит
|
||||
* счётчик ip+action.
|
||||
*/
|
||||
|
||||
require __DIR__ . '/../lib/http.php';
|
||||
require __DIR__ . '/../lib/db.php';
|
||||
require __DIR__ . '/../lib/auth.php';
|
||||
require __DIR__ . '/../lib/ratelimit.php';
|
||||
|
||||
http_security_headers();
|
||||
|
||||
try {
|
||||
method_must('POST');
|
||||
require_client_header();
|
||||
|
||||
$pdo = db();
|
||||
$ip = client_ip();
|
||||
rate_check($pdo, $ip, 'login');
|
||||
rate_record($pdo, $ip, 'login');
|
||||
|
||||
$body = read_json_object();
|
||||
$email = trim((string)($body->email ?? ''));
|
||||
$password = (string)($body->password ?? '');
|
||||
|
||||
$stmt = $pdo->prepare('SELECT id, pass_hash FROM users WHERE email = ?');
|
||||
$stmt->execute([$email]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if (!is_array($user) || !password_verify($password, (string)$user['pass_hash'])) {
|
||||
error_out(401, 'unauthorized');
|
||||
}
|
||||
|
||||
rate_clear($pdo, $ip, 'login');
|
||||
login_user((int)$user['id']);
|
||||
|
||||
json_out(['ok' => true]);
|
||||
} catch (Throwable $e) {
|
||||
error_log('login: ' . $e->getMessage());
|
||||
error_out(500, 'internal');
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue