Каким образом можно спроектировать маршруты?

Есть существующие роуты для вопросов (questions), которые включают операции update, destroy и другие. Аналогично, есть роуты для ответов (answers). Мне необходимо добавить функционал модерации для обеих групп. У меня есть два варианта для реализации: 

1) Поместить роуты модерации в подроуты, например, questions.moderation.status_change.
2) Создать отдельную группу роутов moderation и внутри нее разместить вопросы и ответы.

Какой из предложенных вариантов является более правильным? Не рассматриваю возможность создания одного полиморфного роут модерации и управления логикой в контроллере, поскольку в каждом случае имеется своя специфика.
  • 1 декабря 2024 г. 11:13
Ответы на вопрос 2
Выбор между двумя предложенными вариантами проектирования маршрутов зависит от того, как вы планируете управлять густотой маршрутов, а также от удобства и ясности кода для будущих разработчиков.

### Вариант 1: Подроуты

Если вы добавите маршруты модерации как подроуты внутри существующих роутов для вопросов и ответов (например, `questions.moderation.status_change`), вы создадите более иерархичную структуру. Это может быть удобно, если:

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

Пример структуры маршрутов:
```
resources :questions do
  resources :moderation do
    post :status_change
  end
end

resources :answers do
  resources :moderation do
    post :status_change
  end
end
```

### Вариант 2: Отдельная группа роутов

Создание отдельной группы роутов для модерации (например, `/moderation/questions` и `/moderation/answers`) может обеспечить большую гибкость и простоту, если:

- Вы ожидаете, что функционал модерации будет развиваться независимо от основной логики управления вопросами и ответами.
- Вы хотите четко разделить логику модерации и управления контентом, что помогает в тестировании и поддержке.
- Роуты модерации потребуют значительно отличающейся бизнес-логики, и наличие отдельного пространства имен улучшит читаемость кода.

Пример структуры маршрутов:
```
namespace :moderation do
  resources :questions do
    post :status_change
  end

  resources :answers do
    post :status_change
  end
end
```

### Вывод

В конечном счете, оба подхода имеют свои плюсы и минусы. Если модерация будет сильно отличаться по логике для вопросов и ответов или вы хотите обеспечить четкое отделение этой функциональности, то лучше подойдет второй вариант. Если же вы хотите сохранить тесную связь логики модерации и существующих роутов, и у вас не ожидается значительной разницы в реализации, то первый вариант может быть более подходящим.

Важно также учесть, как эти маршруты будут использоваться в приложении, и какие маршруты будут более интуитивными для пользователей и разработчиков.
Не стоит выносить модерацию на уровень API. API так и должно быть обычным CRUD (create, read, update, delete). А далее нужно внутри построить систему доступа, которая будет определять, какой пользователь что может делать с конкретной сущностью. Потому что у вас могут появиться какие-то другие пользователи, кроме модераторов которые должны будут иметь немного другие полномочия, и т.д. 
Для гугления: Access Control

1. RBAC (Role-based access control). Самая простая система. Вы назначаете каждому пользователю роль или набор ролей, и при проверке, может ли данный пользователь что-то там сделать, просто проверяется, имеет ли он какую-то роль. Сделайте этот список ролей пользователя доступным в тех частях проекта, где надо проверять доступ, и спокойно себе там и проверять. Эта система очень часто прекрасно работает в простых проектах, но она не очень гибкая, и часто приходится писать много дополнительных условий, добавлять много ролей в каждое из условий. Похоже, вы пытаетесь как раз что-то подобное организовать, и вас это обилие условий раздражает.

2. Разрешения (permissions). Это слегка доработанный RBAC, где вы создаете список разрешений, которые описывают что конкретно надо разрешить, и добавляете к этому разрешению список ролей, которым это позволено. Такая система - то что нужно для простых проектов. Потому что вы не заблудитесь в дебрях условий со списком ролей, а будете проверять разрешения, которые легко читать, легко понимать. Система доступа становится глобальной, вы можете безболезненно добавлять новые роли и вносить их в списки разрешений, не меняя основной код программы. Список разрешений может храниться даже в базе данных, и тогда вы налету сможете ограничивать какие-то роли.

Например, самый простейший код на Javascript:
const permissions = {
  "view answers": ["ROLE_GUEST", "ROLE_USER"],
  "add answers": ["ROLE_USER"],
  "delete answers": ["ROLE_MODERATOR"],
  "delete own answers": ["ROLE_USER"],
  "edit answers": ["ROLE_MODERATOR"],
  "edit own answers": ["ROLE_USER"],
  "change status": ["ROLE_MODERATOR"],
};

const user1 = {
  roles: ["ROLE_USER"],
};

const user2 = {
  roles: ["ROLE_USER", "ROLE_MODERATOR"],
};

function checkPermission(user, action) {
  const activeRoles = permissions[action].filter((role) =>
    user.roles.includes(role),
  );
  return activeRoles.length > 0;
}

console.log(checkPermission(user1, "view answers")); // true
console.log(checkPermission(user1, "delete answers")); // false
console.log(checkPermission(user1, "delete own answers")); // true
console.log(checkPermission(user2, "delete answers")); // true
console.log(checkPermission(user2, "delete own answers")); // true


Система тоже имеет недостатки. Слишком сложную логику сюда не зашьёшь, и в некоторых случаях придется это делать в коде. Однако для подавляющего большинства простых проектов этого уже будет достаточно.

3. ABAC (Attribute-based access control), ReBAC (Relationship-based access control), PBAC (Policy-Based Access Control) - это уже более сложные, но в тоже время мощные и гибкие системы контроля доступа, и я оставляю их здесь для общего развития. Реализовать тот же ABAC не так уж и сложно, но за такую систему многие организации могут выложить кругленькую сумму.
Похожие вопросы