Пользователи и права доступа
Учётная запись относится ко всей установке Dee Wan. Доступ к каждому сайту предоставляется через назначение роли на этом сайте. Сам выбор сайта доступа не даёт. Перед назначением, изменением или отзывом роли проверьте, какой сайт выбран.
Добавление человека
Заголовок раздела «Добавление человека»Откройте Настройки → Люди с правом выдавать доступ к сайту. В блоке Добавить человека введите email, выберите роль и нажмите Добавить. Роль не может быть выше вашей собственной.
- У адреса уже есть аккаунт: он сразу получает роль. Письмо не отправляется.
- Аккаунта ещё нет: аккаунт не создаётся. Вместо этого создаётся приглашение. Доступ появляется только после его принятия.
Как доставляется приглашение:
- Почта настроена (
RESEND_API_KEYиMAIL_FROMили ваш почтовый транспорт): ссылка отправляется письмом. Экран сообщает об отправке, только если провайдер принял письмо. - Почта не настроена: письмо не отправляется. Скопируйте ссылку и передайте её приватно. Ссылка показывается один раз.
Человек открывает ссылку и вводит адрес, на который она была отправлена. Если почта настроена, на этот адрес приходит код, и его нужно ввести: адрес считается подтверждённым после ввода кода, а не открытия ссылки. Без почты единственная проверка — введённый адрес, а новый аккаунт отмечается как неподтверждённый. Новый пользователь сам задаёт пароль. Существующий аккаунт получает роль и сохраняет свой пароль. Существующий аккаунт без способа входа получает пароль только после того, как код подтвердил адрес; без почты он получает роль, а ссылку установки пароля выдаёт суперадминистратор.
Ссылка работает один раз и истекает через 7 дней. Кнопка повторной отправки приглашения (доступное название Отправить приглашение для {email} повторно) выдаёт новую ссылку, и старая перестаёт работать. Повторная отправка отклоняется с escalation_refused, если роль приглашения выше вашей; старая ссылка продолжает работать. Кнопка отмены приглашения (доступное название Отменить приглашение для {email}) сначала спрашивает подтверждение и отключает ссылку. Ожидающие и истёкшие приглашения показаны в блоке Приглашения под списком людей, со своими действиями. Принятые и отменённые переходят в Прежние приглашения ({count}). Истёкшая, отменённая или использованная ссылка получает один и тот же отказ.
Если роль или ваш собственный доступ меняются, пока вы добавляете человека, приглашаете или отправляете ссылку повторно, ничего не выдаётся, не создаётся и не отправляется, а при повторной отправке старая ссылка продолжает работать. Если вы больше не можете выдавать доступ к сайту или роль теперь выше вашей, отказ говорит об этом (missing_permission или escalation_refused). Иначе экран сообщает, что изменилась роль или ваш доступ и ничего не сохранено: попробуйте снова.
В каждой строке указан статус пользователя:
- Может войти (пароль, привязанный провайдер или подтверждённый адрес)
- Ссылка ожидает со сроком действия
- Ссылка истекла
- Нужна ссылка для настройки
- Cloudflare Access (Access настроен, и продукт не видит, пользуется ли им человек)
- Деактивирован
Когда Добавить выдаёт роль существующему аккаунту, который ещё не может войти, суперадминистратору предлагается Создать ссылку. Остальным предлагается обратиться к суперадминистратору. Передайте ссылку приватно. Не помещайте её в контент или скриншоты. Суперадминистратор может отозвать действующую ссылку из строки, включая ссылку восстановления для человека, который уже может войти. Отзыв также аннулирует ожидающую использования ссылку входа, которую пользователь запросил сам. Деактивированный аккаунт ссылку не получает: сначала активируйте его.
Ни назначение роли, ни приглашение не открывают публичную регистрацию.
Транспорт почты
Заголовок раздела «Транспорт почты»По умолчанию используется Resend. Чтобы отправлять через собственный сервис, задайте MAIL_TRANSPORT_URL (var), MAIL_TRANSPORT_TOKEN (secret) и MAIL_FROM. В Dee Wan нет почтового сервера и SMTP-клиента: доставляет ваш сервис.
- Когда он используется. Если задан
MAIL_TRANSPORT_URL, каждое сообщение уходит на ваш сервис, а Resend не используется. Если нет токена илиMAIL_FROM, либо адрес отклонён (нуженhttps://, без учётных данных и публичный адрес), почта не настроена: ничего не отправляется, а ссылка приглашения или пароля показывается вам для передачи. - Запрос. Один
POSTна сообщение, сAuthorization: Bearer <token>, заголовкомIdempotency-Keyи JSON{ "message_id", "from", "to", "subject", "text" }.message_idравен ключу. То же сообщение при повторе несёт тот же идентификатор. - Ответ. Ваш сервис отвечает HTTP 200 и JSON:
{ "status": "sent" }(при желании сid),{ "status": "sent", "duplicate": true }, если он уже доставил этотmessage_id, или{ "status": "failed" }. Любой другой статус, тело или перенаправление, а также отсутствие ответа за 10 секунд считаются неудачей. Поэтому повтор одногоmessage_idдоставляет письмо один раз и никогда не сообщается как вторая доставка. - Что вы видите. Отправлено, не удалось или не настроено — как сообщил ваш сервис. Неудачная или отсутствующая доставка не отменяет созданное: приглашение или ссылка пароля существует и показывается вам.
- Плагины не получают токен и не видят ни одного сообщения.
Выбор минимально достаточной роли
Заголовок раздела «Выбор минимально достаточной роли»| Встроенная роль | Полномочия |
|---|---|
admin |
Полное администрирование сайта. Аккаунт не становится суперадминистратором установки. |
editor |
Создание, редактирование, публикация, снятие с публикации, согласование и экспорт контента; полный доступ к медиа. Не управление моделями или сайтом. |
author |
Чтение и создание контента. Редактирование только собственных записей. Добавление файлов медиа, но не их изменение или удаление. Без публикации, снятия с публикации, согласования и восстановления. |
viewer |
Только чтение. |
Роли, созданные для сайта, могут иметь другие права. Проверяйте их определения в разделе Настройки → Роли: название роли само по себе не определяет доступ. Владение проверяется на контенте, включая перевод и первичную запись, если операция затрагивает обе. Общий черновик и блокировка редактирования (lease) учитывают владельца записи на данном языке: роль с доступом только к собственным записям (read:own, update:own) получает к ним доступ только для той языковой версии, владельцем которой является пользователь, иначе получает отказ not_owner. Суперадминистратор имеет полномочия уровня установки на всех сайтах.
В разделе «Настройки» → «Роли» разрешения строки «Все модели» действуют для каждой модели, даже если у неё есть отдельная строка. Кнопки меняют прямые разрешения, а значок ↳ показывает унаследованные. Доступ складывается из обоих наборов: удаление прямого разрешения не отменяет унаследованное. При изменении разрешения * на все действия оно заменяется отдельными разрешениями. Если разрешения не менять, сохранение оставит * как есть.
Права на медиа
Заголовок раздела «Права на медиа»У файлов медиатеки три отдельных права, поэтому добавление, изменение и удаление можно выдавать порознь:
| Право | Разрешает |
|---|---|
media:upload |
Добавлять файлы, включая приватные. |
media:update |
Менять alt-текст, точки фокуса, заменять файл, папки, теги и публичную или приватную видимость. |
media:delete |
Удалять файл. Удаление файла, который используется в контенте или сохранённой истории, отклоняется независимо от того, кто отправил запрос. |
admin и editor имеют все три. author имеет только media:upload, поэтому автор может добавлять файлы, но не может менять или удалять их. У viewer нет ни одного. Учётные данные management API с областью media:write несут все три, сужаемые до того, что есть у их создателя при использовании. Импорту нужно media:upload для добавляемых файлов и media:update для создаваемых папок, а для его отмены нужны media:delete и media:update.
Фрагменты форматированного текста следуют доступу к контенту: кто может создавать или изменять записи модели, может использовать их в ней и управлять теми, что сохранил сам. site:settings управляет всеми фрагментами.
Рабочие процессы администрируются правом site:settings: создание, изменение и удаление именованного процесса, выбор процесса модели и просмотр переноса записей на проверке. Обратная связь по записи следует доступу к записи: чтобы читать её, нужно право чтения, чтобы писать и закрывать — право изменения. Уведомление видно, только пока получатель может читать запись.
Ограничение роли отдельными полями или языками
Заголовок раздела «Ограничение роли отдельными полями или языками»Роль получает доступ ко всем полям и всем языкам моделей, с которыми может работать. Для этого ничего настраивать не нужно. Чтобы сузить пользовательскую или встроенную роль, откройте Настройки → Роли, измените роль и откройте Ограничить поля и языки.
- Ограничить поля перечисляет поля модели, а также Поиск и публикация в соцсетях и Адрес. Нажатие на поле переключает его по кругу между Изменение, Просмотр и Скрыто.
- Ограничить языки выбирает языки, в которых работает роль. Выбор применяется ко всем действиям роли: создание, изменение, удаление, восстановление, проверка, публикация и снятие с публикации. Может читать все языки оставляет чтение открытым, чтобы переводчик видел исходный текст, редактируя только свой язык.
- Строка Все остальные модели ограничивает языки для всех моделей, доступных роли через права по умолчанию. Собственная настройка модели заменяет её.
Что делает ограничение:
- Скрытое поле исключается из редактора, истории версий и сравнений, поиска в списке контента, выгрузки в таблицу и management API. Поле только для просмотра показывается неактивным.
- Сохранение, в котором указано поле, недоступное роли для изменения, отклоняется с
field_deniedи называет это поле. Ничего не отбрасывается молча, а значения в полях, которые роль не видит, сохраняются. - Действие на языке вне роли отклоняется с
locale_deniedи называет язык. Операция, охватывающая несколько языков, например публикация всей записи или массовое действие, отклоняется целиком. - Общее (непереводимое) поле, общий список связей и медиа хранятся в основном языке. Чтобы их изменить, роли нужно право изменять основной язык. Отправка общего значения без изменений вместе с переводом изменением не считается.
- Восстановить только французский в истории версий (кнопка называет язык) восстанавливает один язык: его поля, его собственные списки связей и его адрес. Общие поля, общие связи, медиа и все остальные языки остаются как есть. Для этого нужно действие восстановления только на этом языке, поэтому переводчик может восстановить свой язык.
- Восстановить эту версию восстанавливает всю запись: все языки и все поля. Для этого нужно действие восстановления на всех языках записи.
- В обоих случаях роль с ограничением полей может восстанавливать только там, где поля, которые она не может менять, уже совпадают с версией.
- Общий черновик подчиняется тем же ограничениям. Каждый ответ с черновиком, включая конфликты, содержит только поля, которые роль может читать. Черновик страницы показывает пустое название без права чтения названия и отклоняется с
field_deniedбез права чтения разделов. Чтобы присоединиться к редактированию языка или перехватить его, роли нужно право изменения на этом языке (создания, если строки на этом языке ещё нет); иначе отказlocale_denied. - Отзывы подчиняются тем же ограничениям. Заметка принадлежит языку, на котором она написана. Роль видит только заметки языков, которые может читать; для новой заметки нужно действие update в этом языке; чтобы закрыть или вернуть заметку, нужны read и update в языке заметки. Иначе запрос отклоняется с
locale_denied. - Языки, которые роль не может читать, скрыты из списка языков редактора и из списков контента. Ссылка предпросмотра отдаёт только то, что может читать её автор, и никогда не переходит на язык вне роли.
- Обмен через Экспорт таблицы → Импорт таблицы только обновляет записи и требует прав чтения и изменения модели. Ограничение своими записями (
read:ownилиupdate:own) действует и при выгрузке, и при применении; чужая запись получает ответspreadsheet_row_not_found. Столбцы включают только поля, которые роль может и читать, и менять. Поля только для просмотра не выгружаются; сохранённые скрытые значения остаются при применении. Листы содержат только доступные для чтения языки. Изменение языка без права update блокируется сlocale_denied. Для создания и upsert через CSV/XLSX используйте коллекцию, описанную ниже. - Файлы коллекции выгружает JSON с правом
readна модель и только строки, поля, связанные записи и языки, доступные для чтения. При импорте JSON, CSV и XLSX права проверяются для каждой строки: для создания нужноcreate, для обновления —readиupdate; ограничение своими записями сохраняется. В режиме upsert строке нужно право на фактическое действие, а не оба права сразу. Добавление перевода в существующую запись также требует права create для этого языка. Каждому изменяемому полю и языку нужно право записи; неизменённые значения остаются как есть. См. редактирование контента. - Экспорт всего сайта копирует все поля и языки, поэтому роль с ограничением чтения не может его запустить.
- Если у человека несколько ролей, каждое поле и язык получают наиболее широкие из предоставленных для них прав. Роль без ограничения для действия делает это действие неограниченным. Если для одного языка разрешено только
update:own, а для другого —update, ограничение владельцем сохраняется для первого языка. В объединённых правах эти языки перечислены отдельно дляupdate:own. - Выдавать можно только ограничения в пределах своих собственных. Сохранение роли, дающей доступ к полю или языку, недоступному вам, отклоняется с
escalation_refused, и редактор сообщает об этом до нажатия Сохранить. - Ограничения называют поля по ключу. Переименование ключа поля в конструкторе моделей переписывает ограничения всех ролей на новый ключ после сохранения переименования.
- Компоновщик страниц открывает страницу только на языке, который роль читает, и отказывает в странице, разделы которой роль читать не может. Библиотека страниц скрывает названия и языки, которые роль читать не может.
- Ролями, включая ограничения, можно также управлять через management API с
roles:write.
Изменение или отзыв доступа
Заголовок раздела «Изменение или отзыв доступа»Измените роль пользователя в разделе Люди либо отзовите его доступ к этому сайту. Отзыв не удаляет аккаунт. Суперадминистратор может деактивировать аккаунт и отозвать его сессии. После активации нужно войти заново. Самодеактивация и удаление последнего активного суперадминистратора отклоняются. Отозвать доступ последнего администратора сайта также нельзя.
Вход через Cloudflare Access
Заголовок раздела «Вход через Cloudflare Access»Нужна установка с настроенным Cloudflare Access. Откройте Настройки → Люди → Вход через Cloudflare Access с правом выдавать доступ к сайту.
Правило связывает один точный почтовый домен, например example.com, или одну группу Access с одной ролью этого сайта. Когда переключатель включён и человек, проверенный Access, входит с подходящим доменом или группой, он получает аккаунт и эту роль за один шаг. Поддомены не подходят. Имя группы должно точно совпадать с именем у вашего поставщика удостоверений, включая регистр.
Группы читаются из Cloudflare Access (get-identity на домене вашей команды), а не из токена входа, который может терять группы. Они читаются, только если на каком-то сайте есть правило группы, и один раз за сеанс входа Access.
- Следующие входы меняют роль вместе с правилами. Удаление правила снимает выданную им роль.
- Люди, добавленные вручную или по приглашению, сохраняют свою роль. Ни одно правило её не меняет и не снимает. В разделе Люди рядом с ролью, выданной правилом, стоит Access.
- Одному человеку подходят несколько правил (домен и группы): действует роль, которая включает остальные. Если такой нет, этот сайт не даёт роли. Два несовместимых правила для одного домена или группы отклоняются при сохранении. Правило, ставшее неоднозначным после правки роли, помечается Конфликт.
- Группы не удаётся прочитать: правило группы не создаёт ни аккаунт, ни роль, а роли, выданные правилом группы, не меняются и не снимаются. Правила доменов продолжают работать. Первый вход, который могло бы пропустить только правило группы, отклоняется, его можно повторить.
- Последнего администратора сайта правило никогда не удаляет и не понижает. Экран называет, кто сохранён.
- Выключено останавливает все автоматические изменения: ни новых аккаунтов, ни смены ролей, ни удалений. Существующие аккаунты и роли остаются.
- Деактивированный аккаунт по-прежнему отклоняется. Ни одно правило не делает суперадминистратором. Вход по паролю, по ссылке на почту, через Google и GitHub по-прежнему не создаёт аккаунтов.
- Выдавать можно только роль в пределах своей. Изменение правила, даже только его домена или группы, отклоняется с
escalation_refused, если роль правила выше вашей. Удалить такое правило или сменить его роль на роль в пределах вашей можно. - Если роль или ваш собственный доступ изменились, пока вы сохраняли правило, ничего не сохраняется. Если роль правила теперь выше вашей или вы потеряли право выдавать доступ к сайту, сохранение отклоняется с
escalation_refusedилиmissing_permission. Иначе экран показывает актуальные правила; попробуйте ещё раз. - Роль, которую использует правило, нельзя удалить. Сначала измените правило. На сайте может быть не больше 100 правил.
Каждое изменение переключателя или правил и каждая роль, выданная или снятая правилом, записывается в административную историю сайта.
Замена суперадминистратора
Заголовок раздела «Замена суперадминистратора»Следуйте разделу Замените суперадмина. Для другого человека используется отдельный аккаунт с Сделать суперадминистратором. Только свой email меняйте подтверждённым способом в разделе Безопасность аккаунта ниже.
Ключи доступа (passkeys)
Заголовок раздела «Ключи доступа (passkeys)»Суперадминистратор включает ключи доступа на странице Установка, в разделе Способы входа. По умолчанию они выключены. Для ключей доступа интерфейс администратора должен открываться по доменному имени или localhost. На IP-адресе вроде 127.0.0.1 браузеры их отклоняют, поэтому переключатель остаётся недоступным и объясняет причину. Затем каждый управляет своими ключами доступа в разделе Безопасность аккаунта. См. Ключи доступа.
Потерянное устройство. Войдите другим способом (пароль, ссылка по email, Google или GitHub) и удалите потерянный ключ в разделе Безопасность аккаунта. При настроенной почте используйте включённую ссылку входа или запрос сброса пароля на экране входа. Без почты суперадминистратор выдаёт ссылку установки пароля из списка Люди, как описано ниже, человек задаёт пароль и входит с ним, затем удаляет потерянный ключ.
Пароли и восстановление
Заголовок раздела «Пароли и восстановление»Ссылки получения аккаунта и сброса пароля одноразовые и действуют 15 минут. Новая ссылка отменяет предыдущую. Пароль должен содержать не менее 12 символов. Публичной регистрации нет. При настроенной почте вход предлагает самостоятельный запрос сброса пароля; без почты ссылку восстановления выдаёт уполномоченный человек.
Если заблокирован существующий единственный активный суперадминистратор, владелец развёртывания может выполнить npm run claim:link -- --remote --email <existing-email> из репозитория CMS. Команда не создаёт новый аккаунт и не сбрасывает пароль произвольного пользователя. При первой установке используется ссылка установщика. Условия см. в установке.
Источники: backend/src/api/sites.ts, backend/src/api/users.ts, backend/src/lib/invitation.ts, backend/src/lib/access-provisioning.ts, backend/src/lib/access-identity.ts, backend/src/api/access-provisioning.ts, frontend/src/routes/settings/components/tabs/People.svelte и scripts/claim-link.ts. Доступ в автономном бэкенде независим: см. необязательную аутентификацию и доступ артефакта. Аккаунты и роли CMS туда не экспортируются.
Следующий шаг
Заголовок раздела «Следующий шаг»Разрабатывайте с Dee Wan, начиная с предпросмотра и генерируемого TypeScript-клиента.
Изменение адреса и восстановление пароля
Заголовок раздела «Изменение адреса и восстановление пароля»Откройте Безопасность аккаунта → Изменить адрес электронной почты. Введите свободный адрес и код из нового почтового ящика. Код действует 15 минут. Идентификатор, доступ к сайтам, способы входа и история сохраняются. Все сеансы завершаются; войдите с новым адресом. Нужна настроенная отправка почты. Вход через Google и GitHub не меняет адрес учётной записи.
На экране входа выберите Забыли пароль?, затем введите адрес и запросите ссылку. Этот пункт доступен при настроенной почте; для его открытия адрес не нужен. Ответ одинаков для известных и неизвестных адресов. Для активной учётной записи отправляется одноразовая ссылка, действующая 15 минут. Откройте ссылку и задайте новый пароль. Если отправка почты не настроена, попросите суперадминистратора выдать ссылку для сброса пароля через раздел Люди. Последний суперадминистратор выполняет npm run claim:link -- --remote --email <address>, используя учётные данные развёртывания.
Правила записей в пользовательских ролях
Заголовок раздела «Правила записей в пользовательских ролях»Откройте Настройки → Роли, измените роль и откройте Ограничить доступ по записи. Выберите модель, действие и Добавить правило записи. Настройте владельца либо поле, оператор и значение: заданный текст, ID, почта или роли текущего пользователя. Объединяйте условия группами Все и Любой. Разрешены четыре условия и три уровня групп; незаполненное правило блокирует сохранение. Отказ сервера остаётся видимым, если поле или права изменились. Ключ модели — её slug, действия — create, read, update, delete. Правила ограничивают уже выданные права по текущим значениям полей. Ограничения владельца, полей и языков действуют вместе с ними. Обновление должно соответствовать правилам чтения и изменения до и после записи. Создание проверяет новые значения; удаление и переходы процесса — текущие.
При сохранении или восстановлении одного языка проверяются основная запись и каждый изменяемый язык. Неизменённые языковые версии не требуют дополнительных прав.
{"article":{"read":{"field":"department","op":"in","values":[{"user":"roles"}]},"update":{"field":"assigned_editor","op":"eq","values":[{"user":"id"}]}}}Условие содержит ключ поля, op (eq, in, contains, empty, not_empty) и values. Значения — строки либо {"user":"id"}, {"user":"email"}, {"user":"roles"}. {"owner":true} означает запись, созданную текущим пользователем. Группы: {"join":"and","conditions":[...]} или {"join":"or","conditions":[...]}. Максимум четыре условия и три уровня групп. Общие поля читаются из основного языка записи.
Права ролей складываются; независимая роль без ограничения сохраняет свой доступ. Ограничение владельца и правило одной роли остаются связаны при объединении ролей. Некорректное правило блокирует выдачу прав этой роли. Делегированная роль не может ослабить ограничения, заданные вашими правилами. Эти правила не меняют публикацию или адреса.
Сохранённые связи сохраняют идентификаторы, даже если их цели стали недоступны вашей роли: скрытое имя не означает разрыв связи. История версий показывает имена и адреса целей только в пределах текущих прав. Сохранённая версия не меняется.
Правила значений поддерживают текст, выбор, логические значения, числа и даты. Для выбора eq и in точно сопоставляют идентификаторы вариантов, включая элементы множественного выбора; [] считается пустым. contains работает только с текстом. Числа сравниваются как числовые значения, логические значения задаются как true или false, даты — как YYYY-MM-DD. Отсутствующее или переименованное поле закрывает доступ, в том числе для правила empty. Используйте empty или not_empty с values: []; пустые значения сравнения не принимаются.
Административная история
Заголовок раздела «Административная история»Откройте Настройки → История с правом audit:read, чтобы просмотреть изменения моделей, ролей, доступа, токенов, настроек, имени хоста и развёртываний этого сайта. Фильтруйте по действию, результату, человеку, объекту и датам; Скачать CSV выгружает результаты с учётом фильтров. Результат Неизвестно не подтверждает ни успех, ни отказ. Здесь нельзя изменить или удалить строки. Для контента есть отдельная история версий.
Стабильная версия ещё не выпущена (pre-MVP)
Коммит исходного кода: fe23db481c422b40e317b92fc98116b4c0c26a87 (с локальными изменениями)
Дата сборки (UTC): 2026-10-18T09:22:34.630Z
Коммит для обновления: не определён: в рабочей копии есть изменения. Примечания к выпуску