feat: единая админка runtime-конфигов и indpic (#22)
deploy-preland / deploy zoomstage.online (push) Successful in 1m1s
deploy-preland / deploy zoomstage.online (push) Successful in 1m1s
This commit is contained in:
1 parent
5b6b2d2053
commit
9515c1c62b
52 files changed
+2459
-34
No files matched your search
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require dirname(__DIR__).'/bootstrap.php';
|
||||
use PrelandAdmin\{Auth,Store,Config,Transport,Jobs,Sets,Problem,Catalog};
|
||||
header('X-Content-Type-Options: nosniff');header('X-Frame-Options: DENY');header('Referrer-Policy: same-origin');header('Cache-Control: no-store');
|
||||
$path=parse_url($_SERVER['REQUEST_URI']??'/',PHP_URL_PATH);
|
||||
if(!str_starts_with((string)$path,'/api/')) {require dirname(__DIR__).'/views/dashboard.php';exit;}
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
function reply(array $payload,int $status=200): never {http_response_code($status);echo json_encode(['ok'=>true]+$payload,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_THROW_ON_ERROR);exit;}
|
||||
try {
|
||||
Auth::session();$store=new Store();$auth=new Auth($store);$jobs=new Jobs($store);$sets=new Sets($store);$method=$_SERVER['REQUEST_METHOD']??'GET';$data=[];
|
||||
if(!in_array($method,['GET','POST','DELETE','PUT'],true))throw new Problem('Метод не поддерживается.',405);
|
||||
if($method!=='GET'){
|
||||
$origin=$_SERVER['HTTP_ORIGIN']??'';
|
||||
if($origin!=='' && strcasecmp((string)parse_url($origin,PHP_URL_HOST),(string)preg_replace('/:\d+$/','',$_SERVER['HTTP_HOST']??''))!==0)throw new Problem('Недопустимый источник запроса.',403);
|
||||
if(!str_starts_with($_SERVER['CONTENT_TYPE']??'','multipart/form-data')){
|
||||
if((int)($_SERVER['CONTENT_LENGTH']??0)>2097152)throw new Problem('Запрос слишком большой.',413);
|
||||
$raw=file_get_contents('php://input',false,null,0,2097153);if(strlen($raw)>2097152)throw new Problem('Запрос слишком большой.',413);
|
||||
if($raw!==''){$object=json_decode($raw,false,32,JSON_THROW_ON_ERROR);if(!$object instanceof stdClass)throw new Problem('Ожидался объект запроса.');$data=(array)$object;}
|
||||
}else $data=$_POST;
|
||||
}
|
||||
if($path==='/api/login'&&$method==='POST')reply($auth->login((string)($data['username']??''),(string)($data['password']??''),$_SERVER['REMOTE_ADDR']??'unknown'));
|
||||
$user=$auth->requireUser();
|
||||
if($method!=='GET')$auth->csrf($_SERVER['HTTP_X_CSRF_TOKEN']??'');
|
||||
if($path==='/api/state'&&$method==='GET')reply(['csrf'=>$_SESSION['csrf'],'user'=>$user,'targets'=>$store->targets()]);
|
||||
if($path==='/api/logout'&&$method==='POST'){$auth->logout();reply([]);}
|
||||
if($path==='/api/targets'&&$method==='POST')reply(['target'=>$store->saveTarget((array)($data['target']??[]),isset($data['secret'])?(string)$data['secret']:null)]);
|
||||
if($path==='/api/targets'&&$method==='DELETE'){$store->deleteTarget((string)($data['id']??''));reply([]);}
|
||||
if($path==='/api/targets/test'&&$method==='POST'){$id=(string)($data['id']??'');$t=$store->target($id);(new Transport($store,$t))->test();$store->verifyTarget($id,$t);reply(['message'=>'Пути, блокировка, чтение и права записи проверены.']);}
|
||||
if($path==='/api/config'&&$method==='GET'){
|
||||
$target=$store->target((string)($_GET['target']??''));$read=(new Transport($store,$target))->readConfig();
|
||||
$catalog=Catalog::read($store,$read['config']);$warnings=[];if($catalog===null)foreach(['degr','tp','cons'] as $key)if(isset($read['config']->utm->$key))$warnings[]="{$key}: существование группы на основном сайте не проверено.";
|
||||
reply(['config'=>$read['config'],'version'=>$read['version'],'warnings'=>$warnings,'catalog'=>$catalog,'sets'=>$sets->list($target,$read['config'])]);
|
||||
}
|
||||
if($path==='/api/apply'&&$method==='POST'){$data['targets']=array_map(static fn($t)=>(array)$t,(array)($data['targets']??[]));$data['changes']=array_map(static fn($c)=>(array)$c,(array)($data['changes']??[]));reply(['job'=>$jobs->create('apply',$data)],202);}
|
||||
if($path==='/api/jobs'&&$method==='GET')reply(isset($_GET['id'])?['job'=>$jobs->get((string)$_GET['id'])]:['jobs'=>$jobs->all()]);
|
||||
if($path==='/api/jobs/retry'&&$method==='POST')reply(['job'=>$jobs->retry((string)($data['id']??''),(array)($data['targets']??[]))],202);
|
||||
if($path==='/api/backups'&&$method==='GET'){$id=(string)($_GET['target']??'');$store->target($id);reply(['backups'=>$store->backups($id)]);}
|
||||
if($path==='/api/restore'&&$method==='POST')reply(['job'=>$jobs->create('restore',$data)],202);
|
||||
if($path==='/api/sets'&&$method==='GET'){$target=$store->target((string)($_GET['target']??''));$read=(new Transport($store,$target))->readConfig();reply(['sets'=>$sets->list($target,$read['config']),'version'=>$read['version']]);}
|
||||
if($path==='/api/sets/upload'&&$method==='POST'){
|
||||
if(($_FILES['file']['error']??UPLOAD_ERR_NO_FILE)!==UPLOAD_ERR_OK||!is_uploaded_file($_FILES['file']['tmp_name']))throw new Problem('ZIP не получен либо превышает лимит 64 МиБ.');
|
||||
$number=Sets::number($data['number']??0);$prepared=$sets->prepareZip($_FILES['file']['tmp_name'],$number);
|
||||
$targets=json_decode((string)($data['targets']??'[]'),true,16,JSON_THROW_ON_ERROR);
|
||||
reply(['job'=>$jobs->create('upload',['targets'=>$targets,'number'=>$number,'name'=>(string)($data['name']??''),'prepared'=>$prepared])],202);
|
||||
}
|
||||
if(in_array($path,['/api/sets/check','/api/sets/register'],true)&&$method==='POST'){$data['number']=Sets::number($data['number']??0);reply(['job'=>$jobs->create($path==='/api/sets/check'?'check':'register',$data)],202);}
|
||||
if(in_array($path,['/api/sets/name','/api/sets/delete'],true)&&$method==='POST'){$target=$store->target((string)($data['target']??''));$number=Sets::number($data['number']??0);if($path==='/api/sets/name')$sets->name($target,$number,(string)($data['name']??''));else $sets->delete($target,$number);reply([]);}
|
||||
throw new Problem('Маршрут не найден.',404);
|
||||
}catch(Problem $e){http_response_code($e->status);echo json_encode(['ok'=>false,'error'=>$e->getMessage()],JSON_UNESCAPED_UNICODE|JSON_THROW_ON_ERROR);}
|
||||
catch(JsonException){http_response_code(400);echo json_encode(['ok'=>false,'error'=>'Некорректный JSON запроса.'],JSON_UNESCAPED_UNICODE);}
|
||||
catch(Throwable){http_response_code(500);echo json_encode(['ok'=>false,'error'=>'Операция не выполнена. Проверьте доступность и повторите.'],JSON_UNESCAPED_UNICODE);}
|
||||
Reference in new issue
Block a user