Ответ вслух Middle Код-ревью спрашивают часто обновлено

Ревью: запрос с идентификатором организации

Вопрос

Перед тобой код на ревью. Скажи вслух, что здесь не так - по убыванию важности.

Читай вслух, как на ревью: сначала что делает код, потом что сломано.

// клиент
const orders = await fetch(`/api/orders?tenantId=${currentTenant.id}`).then((r) => r.json());

// сервер, обработчик
app.get('/api/orders', async (req, res) => {
  const orders = await db.order.findMany({ where: { tenantId: req.query.tenantId } });
  res.json(orders);
});

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Это уязвимость, а не стилистика. tenantId приходит параметром запроса: пользователь меняет его в адресной строке и получает заказы чужой организации. В мульти-тенантной системе это утечка данных между клиентами - самый дорогой класс ошибок, вплоть до расторжения договоров.

Что должно прозвучать в ответе

  • идентификатор организации приходит от клиента - подменив параметр, видно чужие данные

  • область видимости должна браться из токена сессии, а не из запроса

  • нет проверки, что пользователь состоит в этой организации

  • нет пагинации - выгрузка всей таблицы одним запросом

  • нет обработки ошибок и кода ответа при отсутствии прав

  • запрос без авторизации вообще - нет проверки сессии

Что могут спросить следом

  • Как бы вы это проверяли в тестах?
  • Где ещё в мульти-тенантной системе легко потерять фильтр?

Разбор

Это уязвимость, а не стилистика. tenantId приходит параметром запроса: пользователь меняет его в адресной строке и получает заказы чужой организации. В мульти-тенантной системе это утечка данных между клиентами - самый дорогой класс ошибок, вплоть до расторжения договоров.

Правило: область видимости берётся из сессии, а не из запроса. Сервер достаёт организацию из токена и подставляет сам; параметр от клиента максимум сверяется со списком доступных пользователю.

Отдельно стоит сказать про гварды: если проверка прав выполняется до подстановки области видимости, запрос внутри неё уйдёт без фильтра, и заметно это не сразу.

Второстепенное, но важное: нет пагинации - метод выгружает всю таблицу и ляжет на первом крупном клиенте.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.