feat: единая админка runtime-конфигов и indpic (#22)
deploy-preland / deploy zoomstage.online (push) Successful in 1m1s

This commit is contained in:
Panfilov Konstantin committed 2026-10-25 11:33:56 +03:00
1 parent 5b6b2d2053
commit 9515c1c62b
52 files changed
+2459 -34

No files matched your search

+31
View File
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace PrelandAdmin;
final class Auth
{
public function __construct(private Store $store) {}
public static function session(): void {
if(session_status()===PHP_SESSION_ACTIVE)return;
ini_set('session.use_strict_mode','1');ini_set('session.use_only_cookies','1');
session_name('preland_admin');
session_set_cookie_params(['lifetime'=>0,'path'=>'/','secure'=>getenv('ADMIN_COOKIE_SECURE')!=='0','httponly'=>true,'samesite'=>'Strict']);
session_start();
}
public function login(string $username,string $password,string $ip): array {
$key=hash('sha256',$ip);$this->store->locked('login',function() use($username,$password,$key){
$attempts=$this->store->read('login-attempts.json');$now=time();$entry=$attempts[$key]??['count'=>0,'since'=>$now];if($entry['since']<$now-900)$entry=['count'=>0,'since'=>$now];
if($entry['count']>=10)throw new Problem('Слишком много попыток. Подождите 15 минут.',429);
$expected=getenv('ADMIN_USERNAME')?:'';$hash=getenv('ADMIN_PASSWORD_HASH')?:'';
if($expected===''||$hash==='')throw new Problem('Администратор ещё не настроен.',503);
$valid=password_verify($password,$hash)&&hash_equals($expected,$username);
if(!$valid){$entry['count']++;$attempts[$key]=$entry;$attempts=array_filter($attempts,static fn($e)=>$e['since']>$now-900);$this->store->write('login-attempts.json',$attempts);throw new Problem('Неверный логин или пароль.',401);}
unset($attempts[$key]);$this->store->write('login-attempts.json',$attempts);
});
session_regenerate_id(true);$_SESSION=['user'=>$username,'csrf'=>bin2hex(random_bytes(32)),'last'=>time()];return ['user'=>$username,'csrf'=>$_SESSION['csrf']];
}
public function requireUser(): string {
if(empty($_SESSION['user'])||($_SESSION['last']??0)<time()-3600){$_SESSION=[];throw new Problem('Войдите в админку.',401);}$_SESSION['last']=time();return $_SESSION['user'];
}
public function csrf(string $token): void {if(!$token||!hash_equals($_SESSION['csrf']??'', $token))throw new Problem('Сессия формы истекла. Обновите страницу.',403);}
public function logout(): void {$_SESSION=[];session_regenerate_id(true);}
}