feat(admin): ручные варианты UTM и независимый редактор config (#30)

This commit is contained in:
Panfilov Konstantin committed 2026-10-26 05:42:03 +03:00
1 parent 47405b27d8
commit 941a4f01aa
28 files changed
+108 -174

No files matched your search

-33
View File
@@ -1,33 +0,0 @@
<?php
/** Read-only экспорт существующих групп; выполняется внутри текущего API-контейнера. */
declare(strict_types=1);
define('APP_ROOT', getenv('APP_ROOT') ?: getcwd());
require APP_ROOT . '/vendor/autoload.php';
require APP_ROOT . '/vendor/yiisoft/yii2/Yii.php';
$db = Yii::createObject(require APP_ROOT . '/config/database.php');
$transaction = $db->beginTransaction(yii\db\Transaction::REPEATABLE_READ);
try {
$db->createCommand('SET TRANSACTION READ ONLY')->execute();
$db->createCommand("SET LOCAL statement_timeout = '5s'")->execute();
$groups = [];
foreach (['degr' => 'degr_groups', 'tp' => 'tarif_groups', 'cons' => 'consent_groups'] as $marker => $table) {
$query = (new yii\db\Query())->select(['number', 'name'])
->from('{{%' . $table . '}}')->where(['between', 'number', 1, 9])->orderBy(['number' => SORT_ASC]);
if ($marker !== 'degr') {
$query->andWhere(['deleted_at' => null]);
}
$groups[$marker] = array_map(static fn(array $row): array => [
'number' => (int) $row['number'], 'name' => (string) $row['name'],
], $query->all($db));
}
$transaction->commit();
echo json_encode(['host' => 'zoomzilla.ru', 'generated_at' => gmdate(DATE_ATOM), 'groups' => $groups],
JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
} catch (Throwable $exception) {
if ($transaction->isActive) {
$transaction->rollBack();
}
// Сообщения PDO могут содержать DSN: наружу только безопасный результат.
fwrite(STDERR, "Каталог групп не обновлён.\n");
exit(1);
}
-24
View File
@@ -1,24 +0,0 @@
#!/bin/sh
set -eu
umask 077
base=/srv/preland-admin
# Подготовка root-процесса находится вне app-writable mount: UID приложения
# не может подменить файл ссылкой между проверкой, chown и chmod.
temporary=$(mktemp "$base/secrets/catalog.XXXXXX")
trap 'rm -f "$temporary"' EXIT HUP INT TERM
if ! /usr/bin/docker exec -i config-api-1 php < "$base/deploy/export-catalog.php" > "$temporary" 2>/dev/null; then
echo 'Каталог групп не обновлён; прежний снимок сохранён.' >&2
exit 1
fi
/usr/bin/python3 - "$temporary" <<'PY'
import json, sys
with open(sys.argv[1], encoding='utf-8') as stream:
value = json.load(stream)
assert value['host'] == 'zoomzilla.ru'
assert set(value['groups']) == {'degr', 'tp', 'cons'}
assert all(isinstance(items, list) for items in value['groups'].values())
PY
chown 997:987 "$temporary"
chmod 600 "$temporary"
# -T заменяет саму ссылку назначения, не следует в указанный ею каталог.
mv -fT "$temporary" "$base/state/catalog.json"