вход переехал на доверенный заголовок Authelia вместо собственного OIDC
- пришедшего называет заголовок Remote-User от прокси, и верят ему только с адреса из перечня trusted_proxies; своего входа у сервиса не осталось — ни корня /auth, ни кук, ни срока сессии, ни секрета клиента в конфиге и в базе - учётная запись заводится первым обращением: EnsureUser в пакете хранилища, шаг схемы 202608220001 с колонкой provider_login и снятыми правилами users - cmd/oidcstub заменён на cmd/devtools с подкомандой proxy; заодно закрыт унаследованный DL3066 — пользователь образа назван числом
This commit is contained in:
@@ -8,9 +8,7 @@
|
||||
Спека отвечает за **сервис**, а не за сборщик: правило неизвестного пути, срок
|
||||
хранения ответов, поведение при несобранном приложении и то, что уходит в журнал.
|
||||
Отпечаток в именах ресурсов — свойство сборки, и его дом — конвенция приложения.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Приложение отдаётся самим бинарником
|
||||
|
||||
Сервис SHALL отдавать разметку приложения и её ресурсы из самого бинарника.
|
||||
@@ -71,8 +69,15 @@
|
||||
|
||||
Сервис SHALL отдавать разметку приложения на всяком пути, который не принадлежит
|
||||
ни одному корню сервиса и не совпадает с отдельным адресом наблюдения. Корни
|
||||
перечислены поимённо — `/api` у хранилища, `/app` у приложения, `/auth` у входа,
|
||||
`/_` у панели, — отдельными адресами стоят `/health` и `/metrics`.
|
||||
перечислены поимённо — `/api` у хранилища, `/app` у приложения, `/_` у панели, —
|
||||
отдельными адресами стоят `/health` и `/metrics`.
|
||||
|
||||
Корня `/auth` в перечне больше нет: собственного входа у сервиса не осталось, и
|
||||
адресов под этим корнем не существует. Прежние адреса входа поэтому отвечают тем
|
||||
же, чем отвечает всякий путь вне корней, — разметкой приложения. Резервировать имя
|
||||
за отказом сервис не берётся: имя, за которым ничего не стоит, ничем не отличается
|
||||
от любого другого свободного имени, а второй перечень «когда-то занятых корней»
|
||||
разошёлся бы с первым молча.
|
||||
|
||||
Путь принадлежит корню, когда **совпадает с ним точно либо начинается им вместе с
|
||||
косой чертой**. Оба условия обязательны: по одному лишь префиксу корню `/app`
|
||||
@@ -114,16 +119,23 @@
|
||||
- **THEN** ответ имеет код `200`
|
||||
- **AND** тело ответа — разметка приложения
|
||||
|
||||
#### Scenario: Прежний адрес входа открывает приложение
|
||||
|
||||
- **WHEN** запрос приходит на путь под прежним корнем входа
|
||||
- **THEN** ответ имеет код `200`
|
||||
- **AND** тело ответа — разметка приложения
|
||||
|
||||
#### Scenario: Неизвестный путь под корнем приложения отвечает отказом
|
||||
|
||||
- **GIVEN** человек вошёл и предъявил сессию
|
||||
- **GIVEN** запрос идёт с заголовком, поставленным прокси
|
||||
- **WHEN** он спрашивает неизвестный путь под корнем приложения
|
||||
- **THEN** ответ имеет код `404`
|
||||
- **AND** тело ответа — отказ приложения с машиночитаемым кодом, а не разметка
|
||||
|
||||
#### Scenario: Неизвестный путь под корнем приложения без сессии отвечает как все прочие его адреса
|
||||
#### Scenario: Неизвестный путь под корнем приложения неузнанному отвечает как все прочие его адреса
|
||||
|
||||
- **WHEN** запрос приходит на неизвестный путь под корнем приложения без сессии
|
||||
- **WHEN** запрос приходит на неизвестный путь под корнем приложения без
|
||||
заголовка
|
||||
- **THEN** ответ имеет код `401`
|
||||
- **AND** тело ответа — не разметка приложения
|
||||
|
||||
@@ -138,22 +150,6 @@
|
||||
- **THEN** ответ имеет код `404`
|
||||
- **AND** тело ответа — не разметка приложения
|
||||
|
||||
#### Scenario: Наблюдение приложением не подменяется
|
||||
|
||||
- **WHEN** запрос приходит на пробу здоровья
|
||||
- **THEN** отвечает проба здоровья, а не приложение
|
||||
|
||||
#### Scenario: Чужой метод отвечает отказом
|
||||
|
||||
- **WHEN** на неизвестный путь вне корней приходит запрос методом, которым
|
||||
страницу не открывают
|
||||
- **THEN** ответ имеет код `405`
|
||||
|
||||
#### Scenario: Проверка доступности разметку получает
|
||||
|
||||
- **WHEN** разметку спрашивают методом `HEAD`
|
||||
- **THEN** ответ имеет код `200`
|
||||
|
||||
### Requirement: Обновлённое приложение доходит до браузера
|
||||
|
||||
Сервис SHALL отдавать **ресурс из каталога, который наполняет сборщик**, с долгим
|
||||
@@ -239,44 +235,41 @@
|
||||
|
||||
### Requirement: Открытое приложение показывает вошедшего
|
||||
|
||||
Приложение SHALL спрашивать сервис, кто вошёл, и показывать его имя. Отказ
|
||||
`401` MUST уводить ко входу: человек, ещё не вошедший, получает его на всяком
|
||||
адресе данных, и это его штатное состояние, а не поломка.
|
||||
Приложение SHALL спрашивать сервис, кто пришёл, и показывать его имя. Отказ
|
||||
`401` MUST показываться строкой о том, что сервис его не узнал, и MUST никуда не
|
||||
уводить: своего входа у сервиса нет, а вести человека некуда — заголовок ставит
|
||||
обратный прокси, и человек, которого прокси не назвал, до приложения дошёл бы
|
||||
только мимо него.
|
||||
|
||||
Всякий **иной** отказ и сорванный запрос MUST ко входу не уводить, а показываться
|
||||
строкой о неудаче. Трактовка «любой отказ значит не вошёл» замкнула бы круг:
|
||||
приложение ушло бы ко входу, вход вернул бы человека в приложение, и на отказе
|
||||
сервиса или ограничителя частоты круг пошёл бы заново.
|
||||
Всякий **иной** отказ и сорванный запрос MUST показываться строкой о неудаче.
|
||||
Разделять их приложение обязано: «сервис вас не узнал» и «сервис не отвечает» —
|
||||
разные состояния, и человек по ним делает разное. Прежде отказ `401` уводил ко
|
||||
входу; уводить стало некуда, и различие сохраняется ради текста, а не ради
|
||||
перехода.
|
||||
|
||||
Имя вошедшего берётся ответом сервиса, а не кукой сессии: кука недоступна
|
||||
скриптам страницы, и другого способа узнать вошедшего у приложения нет. Имени в
|
||||
ответе может не быть вовсе — тогда приложение MUST показать, что вход выполнен,
|
||||
и MUST не подставлять вместо имени адрес почты: его в ответе нет по норме
|
||||
`access`.
|
||||
Имя пришедшего берётся ответом сервиса, а не заголовком запроса: заголовок ставит
|
||||
прокси, и приложение его не видит вовсе. Имени в ответе может не быть — тогда
|
||||
приложение MUST показать, что человек узнан, и MUST не подставлять вместо имени
|
||||
адрес почты: его в ответе нет по норме `access`.
|
||||
|
||||
#### Scenario: Вошедший виден
|
||||
#### Scenario: Узнанный виден
|
||||
|
||||
- **GIVEN** человек вошёл и получил куку сессии
|
||||
- **GIVEN** запрос приложения идёт с заголовком, поставленным прокси
|
||||
- **WHEN** он открывает приложение
|
||||
- **THEN** приложение показывает его имя
|
||||
|
||||
#### Scenario: Не вошедшему предлагается вход
|
||||
#### Scenario: Неузнанному показывают, что его не узнали
|
||||
|
||||
- **GIVEN** сессии у человека нет
|
||||
- **WHEN** он открывает приложение
|
||||
- **THEN** приложение ведёт его ко входу
|
||||
- **GIVEN** сервис отвечает на вопрос о пришедшем кодом `401`
|
||||
- **WHEN** человек открывает приложение
|
||||
- **THEN** приложение показывает строку о том, что его не узнали
|
||||
- **AND** никуда его не уводит
|
||||
|
||||
#### Scenario: Отказ сервиса ко входу не уводит
|
||||
#### Scenario: Отказ сервиса от неузнавания отличается
|
||||
|
||||
- **GIVEN** сервис отвечает на вопрос о вошедшем отказом, который не является
|
||||
отсутствием сессии
|
||||
- **GIVEN** сервис отвечает на вопрос о пришедшем отказом, который не является
|
||||
неузнаванием
|
||||
- **WHEN** человек открывает приложение
|
||||
- **THEN** приложение показывает строку о неудаче
|
||||
- **AND** ко входу оно не уводит
|
||||
- **AND** эта строка не та, которой оно сообщает о неузнавании
|
||||
|
||||
#### Scenario: Учётная запись без имени
|
||||
|
||||
- **GIVEN** человек вошёл, а имени у его учётной записи нет
|
||||
- **WHEN** он открывает приложение
|
||||
- **THEN** приложение показывает, что вход выполнен
|
||||
- **AND** адреса почты на экране нет
|
||||
|
||||
Reference in New Issue
Block a user