Демо-режим¶
Демо-режим позволяет выложить сайт Grav в сеть, чтобы его мог попробовать кто угодно. Посетители входят в Admin2 под общей учётной записью, всё смотрят и меняют только то, что вы разрешили. Затем сайт сам по таймеру возвращается к сохранённому начальному состоянию, поэтому через несколько минут от действий посетителей ничего не остаётся.
Важно
Демо-режим предназначен для отдельного демо-сайта: копии Grav, настроенной только для публичного показа, с демонстрационным контентом, демо-учётной записью и вашей собственной административной учётной записью. Это не способ дать кому-то ограниченную учётную запись на настоящем работающем сайте. Сбросы откатывают настоящий контент, а демо-учётные записи могут читать то, что на настоящем сайте стоило бы держать закрытым, — например, список учётных записей. Для ограниченного доступа на работающем сайте используйте обычные права доступа.
Примечание
Разрешения на создание, изменение и удаление, разрешения на настройки, allow_routes, escape_html, include_code, extra_roots и demo:status требуют плагина API 1.0.54 или новее. В более ранних версиях были только api.pages.write и api.media.write, демо-учётным записям по умолчанию разрешалось редактировать страницы и медиафайлы, а при входе им отказывали.
Как это работает¶
Демо-режим включается для каждой учётной записи, а не для всего сайта. Любая учётная запись с правом Демо-режим (access.api.demo) является демо-учётной записью. Ваша собственная административная учётная запись не затрагивается, поэтому вы можете присматривать за демо-сайтом, пока им пользуются посетители.
Демо-учётная запись:
- может открывать любой экран и читать всё, что разрешают её остальные права (обычно она ещё и суперпользователь, то есть всё),
- получает отказ на любом изменении, кроме перечисленных в
demo.writable, - никогда не видит серверные пути, журналы, резервные копии и журнал аудита.
Ещё две детали делают публичный демо-сайт рабочим:
- базовый снимок — сохранённая копия папок, которые может менять демо-учётная запись, снятая в том состоянии сайта, с которого должен начинать каждый посетитель, и
- сбросы, которые возвращают эти папки к базовому снимку каждые
demo.reset_intervalминут — автоматически или по вашей команде.
Настройки демо-режима живут в настройках плагина API, на вкладке Демо-режим, или в секции demo: файла user/config/plugins/api.yaml. Они ничего не делают, пока у учётной записи нет права «Демо-режим».
Настройка демо-сайта¶
1. Создание демо-учётной записи¶
Демо-учётная запись — обычная учётная запись Grav с двумя правами: Суперпользователь API (access.api.super), чтобы видеть все экраны, и Демо-режим (access.api.demo), который забирает все изменения, которые вы не разрешили.
Предупреждение
Пока не добавлено право «Демо-режим», учётная запись остаётся полноценным суперпользователем. Создайте её отключённой, добавьте «Демо-режим» и только потом включите её и опубликуйте пароль.
Из командной строки:
bin/plugin login new-user -u demo -e demo@example.com -N "Demo Visitor" -P a --admin-type api -s disabled
Опция -P a --admin-type api даёт учётной записи доступ к Admin2 с правами суперпользователя. Если опустить -p, команда спросит пароль, и он не останется в истории оболочки. Пароль должен соответствовать политике паролей сайта (pwd_regex в системной конфигурации), поэтому короткий вроде demo отклоняется, пока вы не ослабите политику.
Затем откройте user/accounts/demo.yaml, добавьте demo: true в секции access.api и установите state в enabled:
# user/accounts/demo.yaml
email: demo@example.com
fullname: 'Demo Visitor'
state: enabled
access:
api:
login: true
super: true
demo: true
В Admin2 то же самое делается в разделе Пользователи: создайте учётную запись с выключенным Включён, включите в её правах Суперпользователь API и Демо-режим (учётная запись только для чтения), сохраните, а затем включите её.
Несколько вещей о демо-учётной записи:
- Она общая. Все, кто входит под ней, — один и тот же пользователь, а посетители не могут изменить её пароль, профиль, аватар, настройки двухфакторной аутентификации или ключи API, потому что запросы пользователей всегда отклоняются (см. Что отклоняется всегда).
- Их может быть несколько. Демо-учётной является любая учётная запись с правом «Демо-режим», и у всех у них одни и те же разрешения
demo.writable, действующие на весь сайт. - Она не обязана быть суперпользователем. Опустите
superдля демо, которое показывает только часть админки. Тогда учётной записи нужныapi.accessи права на чтение тех областей, которые она должна видеть, — как любой другой учётной записи. Демо-режим только забирает права. - Скажите посетителям, как войти. Укажите имя пользователя и пароль на главной странице сайта или там, куда вы их отправляете.
2. Выбор того, что могут менять посетители¶
Если в demo.writable ничего не перечислено (так по умолчанию), демо работает только для чтения: посетители могут осматриваться, но любые «Сохранить», «Загрузить» и «Удалить» отклоняются. Демо только для чтения сбрасывать нечего, поэтому базовый снимок и сбросы можно пропустить.
Чтобы позволить посетителям что-то пробовать, перечислите нужные разрешения:
| Разрешение | В форме настроек | Что разрешает демо-учётной записи |
|---|---|---|
api.pages.create |
Создание страниц | создавать, копировать и переводить страницы |
api.pages.update |
Изменение страниц | изменять, перемещать, менять порядок, публиковать и снимать с публикации страницы |
api.pages.delete |
Удаление страниц | удалять страницы |
api.media.upload |
Загрузка медиафайлов | загружать медиафайлы и создавать папки медиафайлов |
api.media.update |
Изменение сведений о медиафайлах | переименовывать медиафайлы, менять их порядок и редактировать метаданные |
api.media.delete |
Удаление медиафайлов | удалять медиафайлы |
api.config.site |
Изменение настроек сайта | изменять настройки сайта (site.yaml) |
api.config.plugins |
Изменение настроек плагинов | изменять настройки плагинов |
api.config.themes |
Изменение настроек тем | изменять настройки тем |
api.pages.write, api.media.write и api.config.write (Всё на страницах, Всё на медиафайлах и Настройки сайта, плагинов и тем в форме) — краткие записи для трёх разрешений каждой группы.
Демо, в котором посетители могут писать и изменять страницы и добавлять изображения, но ничего не удалять:
Admin2 следует этим разрешениям. С разрешением Изменение страниц, но без Удаление страниц, редактор страниц предлагает «Сохранить», но не «Удалить». Если посетитель всё же дойдёт до запрещённого действия, API отклонит его, а Admin2 покажет предупреждение, что в демо изменения отключены.
3. Подготовка начального контента¶
Настройте сайт ровно так, чтобы его нашёл каждый посетитель: страницы, изображения и настройки, которые хотите показать. Для этого входите под собственной учётной записью, а не под демо-учётной.
Всё, что лежит в папках, которые восстанавливает сброс, попадает в базовый снимок как есть, поэтому сначала приведите всё в порядок. Удалите тестовые страницы и оставшиеся загрузки, а если демо-учётная запись уже использовалась, убедитесь, что изменений посетителей не осталось (bin/plugin api demo:status перечисляет их, когда базовый снимок уже есть).
4. Сохранение базового снимка¶
Команда печатает сохранённые папки, например media, pages, и интервал сброса. Автоматические сбросы отсчитываются от этого момента: первый из них положен через reset_interval минут. О том, что входит в базовый снимок и когда его нужно сохранять заново, см. в разделе Базовый снимок.
5. Включение автоматических сбросов¶
С настройками по умолчанию сбросы уже происходят сами: первый запрос к API после истечения интервала запускает сброс. Чтобы сбросы выполнялись вовремя, даже когда никто не пользуется Admin2, добавьте планировщик Grav в crontab сервера:
О том, как работают вместе оба механизма, см. в разделе Автоматические сбросы.
6. Проверка¶
Команда перечисляет, что могут менять демо-учётные записи, какие папки восстанавливает сброс, когда был сохранён базовый снимок, когда были последний и следующий сбросы, а также какие файлы добавились, изменились или пропали после базового снимка. Под каждым заголовком показываются первые 20 файлов; добавьте --all, чтобы получить все.
Затем войдите под демо-учётной записью в приватном окне. Admin2 покажет баннер сверху: «Read-only demo» для демо только для чтения, а после появления базового снимка — как часто сбрасываются изменения и обратный отсчёт до следующего сброса. Попробуйте разрешённое действие и запрещённое, дождитесь сброса и убедитесь, что изменение отменено.
Базовый снимок¶
Базовый снимок — это начальное состояние, к которому возвращается каждый сброс. Это zip-архив папок, которые восстанавливает сброс, созданный командой demo:baseline (или POST /demo/baseline через API) и хранящийся в user/data/api/demo/baseline.zip. Время его сохранения записывается рядом в user/data/api/demo/state.json.
Что в него входит¶
Только те папки, которые восстанавливает сброс, — они определяются вашими настройками в момент сохранения:
| Настройки | Какие папки сохраняются |
|---|---|
Разрешения api.pages.* |
user/pages |
Разрешения api.media.* |
user/pages (медиафайлы страниц) и user/media (медиафайлы сайта) |
Разрешения api.config.* |
Настройки, которые может менять демо-учётная запись, из user/config и из папки настроек каждого окружения |
include_code: true |
user/plugins и user/themes |
extra_roots |
Каждая перечисленная папка |
Папка, которой нет на диске, в снимок не попадает. Базовый снимок — не резервная копия сайта: учётные записи, user/data, плагины, темы и настройки попадают в него только тогда, когда это сказано в таблице выше. Для остального используйте собственные резервные копии Grav.
Этого в нём никогда нет:
user/data/api, где лежат ключи API, журнал аудита и собственные файлы демо,- символические ссылки прямо внутри сохранённой папки или на один уровень ниже — например, плагин-ссылка в
user/pluginsили папка страниц-ссылка вродеuser/pages/01.home. Сбросы оставляют их ровно как есть, - в папке настроек — каждый файл, который демо-учётная запись не может менять. Если разрешено только
api.config.plugins, базовый снимок содержитuser/config/pluginsи больше ничего изuser/config, поэтомуsystem.yaml,site.yamlи собственные настройки плагина API остаются вашими.
Если не разрешено ничего и не заданы ни include_code, ни extra_roots, сохранять нечего: demo:baseline останавливается с сообщением «Nothing to capture», а демо просто остаётся только для чтения, без сбросов.
Сохранение заново¶
Сохранение нового базового снимка заменяет старый и перезапускает таймер сброса. Сохраняйте его заново всякий раз, когда происходит что-то из перечисленного:
- Вы меняете демо-контент. Сброс возвращает базовый снимок, поэтому любое ваше собственное изменение папок, которые он восстанавливает, — включая страницы и медиафайлы, — будет отменено следующим сбросом, если сначала не сохранить новый базовый снимок.
- Вы выкладываете обновление в восстанавливаемые папки (через git, rsync или конвейер развёртывания). Иначе следующий сброс откатит развёртывание.
- Вы меняете
writable,include_codeилиextra_roots. Папка, которой нет в базовом снимке, сбросы не трогают, поэтому новая разрешённая папка не будет сбрасываться, пока вы не сохраните снимок заново. Расширение разрешений на настройки без нового базового снимка даже хуже: в старом снимке нет недавно разрешённых файлов настроек, поэтому сброс может их удалить. - Вы обновляете плагины или темы на демо с
include_code: true. Иначе каждый сброс возвращает старые версии.
demo:status — самый быстрый способ проверить: всё, что перечислено в разделах Changed, Added и Removed, отменит следующий сброс.
Безопасное обновление демо-контента¶
Сброс может сработать, пока вы ещё редактируете, и уничтожить вашу работу. Чтобы обновить работающий демо-сайт:
- Приостановите сбросы: выключите Сброс по запросу и Сброс по расписанию в настройках API (
demo.reset_on_request: false,demo.reset_on_schedule: false). Эти настройки ваши, демо-учётные записи не могут их менять, и сбросы их не трогают. - Не давайте посетителям ничего менять, пока работаете: отключите демо-учётную запись или сначала выполните
bin/plugin api demo:reset, чтобы начать с чистого состояния. - Внесите изменения под собственной учётной записью.
- Выполните
bin/plugin api demo:statusи убедитесь, что перечисленные изменения — ваши. - Выполните
bin/plugin api demo:baseline. - Включите обе настройки сброса обратно и включите демо-учётную запись, если вы её отключали.
Сохранение и перенос базового снимка¶
Базовый снимок — обычный zip-архив, в котором на каждую сохранённую папку приходится одна папка верхнего уровня (pages/, media/, config/, environments/<name>/, plugins/, themes/ или путь дополнительной папки). Его можно сохранить у себя как заведомо рабочую точку отсчёта. При копировании всего сайта на другой сервер user/data/api/demo переезжает вместе с ним, и демо продолжает работать там. Скопированный отдельно, в свежий сайт, базовый снимок без своего state.json считается просроченным, поэтому первый запрос сбрасывает всё сразу.
Сбросы¶
Сброс возвращает каждую папку из базового снимка в то состояние, в котором она была при его сохранении. Он отменяет всё, что делали посетители, и всё остальное, что изменилось в этих папках с тех пор, — включая ваши собственные правки.
Автоматические сбросы¶
Сбросы выполняются каждые demo.reset_interval минут (по умолчанию 30) после последнего сброса или последнего базового снимка. Их запускают два механизма, и оба включены по умолчанию:
- По запросу (
demo.reset_on_request): первый запрос к API после истечения интервала выполняет сброс до того, как будет дан ответ. Cron не нужен, механизм работает на любом хостинге. Важно знать два момента: учитываются только запросы к API, поэтому сайт, где Admin2 никто не открывает, сбросится в следующий раз, когда его откроют, а запрос, который вызвал сброс, ждёт его окончания — на большом сайте это дольше. - По расписанию (
demo.reset_on_schedule): задание планировщика Grav проверяет состояние каждую минуту и сбрасывает, когда интервал истёк, поэтому сбросы идут вовремя, без ожидания. Для этого из cron должен работатьbin/grav scheduler(см. шаг 5). Задание называетсяapi-demo-reset, регистрируется только после появления базового снимка и показывается вbin/grav scheduler -jи на вкладке Планировщик в разделе Инструменты Admin2, где его можно отключить, как и любое другое задание. Его вывод пишется вlogs/api-demo-reset.out.
Когда включены оба механизма, блокировка гарантирует, что сброс выполняется только один за раз: тот, кто пришёл вторым, пропускает. Пока базового снимка нет, ничего не сбрасывается, поэтому на сайте без демо оба механизма безвредны. Выключите оба, чтобы остановить автоматические сбросы и сбрасывать только вручную.
Сброс вручную¶
Из командной строки:
Команда ждёт уже идущего автоматического сброса, а затем сбрасывает. Без базового снимка она останавливается с ошибкой и ничего не меняет.
Через API, с учётными данными суперпользователя (демо-учётной записи всегда отказывают, даже если она суперпользователь):
См. Сброс демо-контента. Ручной сброс перезапускает таймер, поэтому следующий автоматический произойдёт через полный интервал.
Что происходит во время сброса¶
- Сначала сохраняется страховочная копия текущего состояния папок (см. Страховочные копии).
- Каждая папка пересобирается из базового снимка рядом с действующей, а затем обе меняются местами переименованием. Посетители никогда не видят наполовину восстановленную папку, а если что-то пойдёт не так, действующая папка остаётся как была, а ошибка попадает в журнал Grav (
logs/grav.logкакapi.demo: ...). - То, чего сброс никогда не касается (
user/data/api, символические ссылки, настройки, которые не может менять демо-учётная запись), переносится из действующей папки без изменений. - Кэш Grav очищается, поэтому сайт сразу показывает восстановленный контент.
- Таймер перезапускается.
Восстановление большего числа папок¶
По умолчанию сброс восстанавливает только то, что разрешения позволяют менять посетителям. Есть две опции, которые добавляют ещё:
demo.include_code: true(Сбрасывать плагины и темы) восстанавливает ещё иuser/pluginsиuser/themes. Включайте её, когда посетители могут менять то, что хранится там.demo.extra_roots(Сбрасывать также) перечисляет дополнительные папкиuser://. Используйте её для того, что посетители делают на самом сайте, а не в Admin2: отправку форм, комментарии, собственные данные плагина или регистрации.
Указывайте дополнительные папки точно, потому что сброс возвращает в них всё:
user://dataвосстанавливает все данные всех плагинов в ней, а не только то, что добавили посетители. (user/data/apiвсегда исключается.)user://accountsвосстанавливает все учётные записи, включая вашу, поэтому изменённый пароль или добавленная после снимка учётная запись отменяются следующим сбросом. Используйте её, только если на сайте могут регистрироваться.
Запись в extra_roots, которая не является папкой user://, пересекается с папкой настроек или находится в user/data/api, игнорируется с предупреждением в журнале Grav.
Страховочные копии¶
Перед каждым сбросом текущее состояние папок сохраняется в user/data/api/demo/safety--<date>-<time>.zip — на случай, если сам базовый снимок оказался неверным. Параметр demo.keep_safety_snapshots (по умолчанию 5) задаёт, сколько копий хранится; более старые удаляются. Значение 0 отключает их хранение.
Страховочная копия имеет ту же структуру, что и базовый снимок, поэтому вернуться к ней можно так — например, после сохранения снимка, когда изменения посетителей ещё были на месте:
- Приостановите сбросы, как в разделе Безопасное обновление демо-контента.
- Скопируйте страховочный zip поверх
user/data/api/demo/baseline.zip. - Выполните
bin/plugin api demo:reset. Команда сначала сделает новую страховочную копию, а затем восстановит из выбранной вами. - Проверьте сайт, выполните
bin/plugin api demo:baseline, чтобы он стал настоящим базовым снимком, и включите сбросы обратно.
Что отклоняется всегда¶
Некоторые вещи отклоняются независимо от того, что указано в writable, потому что посетитель, который мог бы их менять, мог бы выключить демо-режим, захватить чужие учётные записи или выполнить код на сервере:
- пользователи, группы и приглашения, включая собственный профиль, пароль и ключи API демо-учётной записи;
- установка, обновление и удаление плагинов и тем;
- системные инструменты: кэш, планировщик, резервные копии, вебхуки, журналы и журнал аудита;
- сами элементы управления демо (базовый снимок и сброс), даже если демо-учётная запись — суперпользователь;
- настройки системы, безопасности, медиафайлов, планировщика, резервных копий, учётных записей и потоков;
- настройки плагинов API, Admin2, Login и Email;
- переопределения переводов и машинный перевод.
Поэтому api.config.plugins позволяет посетителям менять, например, настройки Markdown Notices или Sitemap, но никогда — настройки плагина Login.
Всё остальное, что сохраняется на сервере и не является изменением страницы, медиафайла или настройки, тоже отклоняется — если вы не перечислите это в allow_routes: макет панели управления, настройки и брендинг Admin2, Flex-объекты, действия отчётов, действия панели инструментов плагинов и собственные API-маршруты каждого плагина.
Что видят демо-учётные записи¶
Чтение остаётся открытым, чтобы демо показывало всю админку, но часть данных скрыта:
- Журналы, резервные копии (список, создание, скачивание и удаление) и журнал аудита отклоняются.
- Серверные пути и программное обеспечение в Сведениях о системе, команда cron и пользователь сервера в Планировщике, а также вывод заданий показывают «(hidden in demo mode)».
- Секреты в настройках — пароли и ключи API — скрываются для любой учётной записи, демо или нет.
Суперпользовательская демо-учётная запись может читать и страницы Пользователей и Групп — с именем пользователя, полным именем, адресом электронной почты и правами доступа каждой учётной записи. Это часть показа всей админки и ещё одна причина, по которой демо-режим должен жить на отдельном демо-сайте: оставьте там только демо-учётную запись и вашу собственную административную, с теми сведениями, которые не жалко показывать. Чтобы скрыть и эти страницы, оставьте super выключенным у демо-учётной записи и не давайте ей api.users.read.
Страницы, которые правят посетители¶
Публичный демо, в котором посетители правят страницы, позволяет им помещать на эти страницы что угодно, а страницы эти публичны. Два правила делают это безопасным:
- При включённом
demo.escape_html(по умолчанию, Показывать HTML как текст в форме) страницы, сохранённые демо-учётной записью, показывают любой сырой HTML как текст, поэтому посетитель не может добавить на сайт скрипты, iframe или скрытые ссылки. Markdown, блоки кода и изображения работают как обычно. API делает это, задаваяmarkdown.escape_markup: trueв метаданных сохранённой страницы, а следующий сброс возвращает исходную страницу. - Демо-учётная запись не может сохранить страницу, выполняющую Twig, что бы ни стояло в
escape_html. Если сайт выполняет Twig в каждой странице или в метаданных, демо-учётные записи не могут сохранять страницы вовсе, а при включённомescape_html— ещё и страницу, отключающую Markdown.
Затрагиваются только страницы, сохранённые демо-учётной записью. Ваши собственные сохранения работают как обычно.
Маршруты плагинов и Flex-объекты¶
Записи в собственные API-маршруты плагина для демо-учётных записей по умолчанию отклоняются, потому что API не знает, что они меняют. Перечислите в demo.allow_routes те, которыми посетителям положено пользоваться, в виде METHOD /path или просто /path (любой метод), ниже префикса API. * соответствует чему угодно, включая слэши:
Маршрут из этого списка проходит собственные проверки прав плагина для демо-учётных записей. Он не открывает ни один из маршрутов из раздела Что отклоняется всегда и не открывает маршруты страниц, медиафайлов или настроек. Те открываются только через writable.
Если плагин хранит то, что делают посетители, в папке, добавьте эту папку в extra_roots, чтобы сбросы очищали её тоже.
Flex-объекты работают так же: их API-маршруты (/flex-objects/...) можно открыть через allow_routes, а их папку с данными — добавить в extra_roots. Сам Admin2 оставляет Flex-объекты для демо-учётных записей только для чтения, поэтому это помогает лишь собственному фронтенду или приложению, использующему API.
Решение проблем¶
demo:baseline сообщает «Nothing to capture». В demo.writable ничего не разрешено, и ни include_code, ни extra_roots не добавляют папку. Значит, это демо только для чтения, которому базовый снимок не нужен.
На баннере нет обратного отсчёта. Базовый снимок ещё не сохранён, поэтому сброс не положен. Выполните bin/plugin api demo:baseline.
Сбросы не идут вовремя. С включённым только Сброс по запросу сброс ждёт следующего запроса к API. Добавьте планировщик в cron, проверьте, что api-demo-reset указан в bin/grav scheduler -j и не отключён, и посмотрите logs/api-demo-reset.out и logs/grav.log на наличие ошибок.
Мои собственные изменения постоянно исчезают. Они находятся в папке, которую восстанавливает сброс, и сделаны после базового снимка. Сохраните новый базовый снимок после изменения демо-контента, как в разделе Безопасное обновление демо-контента.
Изменение посетителя пережило сброс. Оно находится в папке, которой нет в базовом снимке: вновь разрешённой папке или в данных плагина, которым нужен extra_roots. Проверьте «A reset restores» в demo:status, добавьте недостающее и сохраните базовый снимок заново.
Посетители не могут сохранить страницу, которую должны были бы. Проверьте, что разрешение есть в demo.writable. Если оно есть, то страница выполняет Twig, либо сайт выполняет Twig в каждой странице или в метаданных, либо страница отключает Markdown при включённом escape_html. Всё это отклоняется для демо-учётных записей намеренно.
Демо-учётная запись не может войти. В версиях плагина API старше 1.0.54 демо-учётным записям отказывали в каждом запросе. Обновите плагин API.
Справка по настройкам¶
Всё в секции demo: файла user/config/plugins/api.yaml:
| Параметр | По умолчанию | |
|---|---|---|
writable |
[] |
Что могут менять демо-учётные записи. Пустой список — демо только для чтения. См. Выбор того, что могут менять посетители. |
allow_routes |
[] |
Маршруты плагинов, в которые демо-учётные записи могут писать. См. Маршруты плагинов и Flex-объекты. |
escape_html |
true |
Показывать сырой HTML как текст в страницах, которые сохраняют демо-учётные записи. |
include_code |
false |
Восстанавливать ещё и user/plugins и user/themes при каждом сбросе. |
extra_roots |
[] |
Дополнительные папки user://, восстанавливаемые при каждом сбросе. |
reset_interval |
30 |
Минут между сбросами. |
reset_on_request |
true |
Сбрасывать при первом запросе к API после истечения интервала. |
reset_on_schedule |
true |
Регистрировать задание планировщика, сбрасывающее после истечения интервала. |
keep_safety_snapshots |
5 |
Сколько страховочных копий хранится перед сбросами. 0 не хранит ни одной. |
Команды¶
| Команда | |
|---|---|
bin/plugin api demo:baseline |
Сохранить текущее состояние папок, которые восстанавливает сброс, как базовый снимок и перезапустить таймер. |
bin/plugin api demo:status [--all] |
Показать разрешения, сроки сброса и изменения после базового снимка. |
bin/plugin api demo:reset |
Сбросить к базовому снимку сейчас и перезапустить таймер. |
Те же действия доступны через API — см. Эндпоинты демо-режима. Базовый снимок и сброс требуют суперпользователя и всегда отказывают демо-учётным записям.