# Лучший способ enforce прав доступа — контроллер или ограничение?

**URL:** https://meta.discourse.org/t/best-way-to-enforce-permissions-controller-or-constraint/176113
**Category:** Development
**Created:** [14.Январь.2021 17:02:56 UTC](https://meta.discourse.org/t/best-way-to-enforce-permissions-controller-or-constraint/176113 "2021-01-14T17:02:56Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [14.Январь.2021 17:02:56 UTC](https://meta.discourse.org/t/best-way-to-enforce-permissions-controller-or-constraint/176113/1 "2021-01-14T17:02:56Z")

</div>

У меня есть плагин, который добавляет модель `server` с полем `user_id`. Я хочу, чтобы только владелец `server` мог выполнять `POST` (или, возможно, лучше `PUT`? — действие будет запускать пересборку экземпляра Discourse через командную строку на их сервере; я не уверен, что будет _лучшей практикой_.)

В `config/routes.rb` это выглядит так:

post “/upgrade/:id” =\> “servers#queue\_upgrade”, constraints: PfaffmanagerConstraint.new

Рекомендуется ли проверять `path_parameters[:action]` в методе `matches?` файла `pfaffmanager_constraint.rb` и применять разрешения там, или же это следует делать в `servers_controller.rb`?

Кроме того, я думаю, что на самом деле мне стоит перенести этот маршрут в пространство имен `namespace :user`. Возможно, после решения этой задачи проблема решится сама собой, но сейчас код почти работает, и я хотел бы позволить другим людям протестировать его.

Маршрут Rails здесь:  
[https://github.com/pfaffman/discourse-pfaffmanager/blob/master/config/routes.rb#L12](https://github.com/pfaffman/discourse-pfaffmanager/blob/master/config/routes.rb#L12)

А мой контроллер пытается применять разрешения:

[https://github.com/pfaffman/discourse-pfaffmanager/blob/master/app/controllers/pfaffmanager/servers\_controller.rb#L53-L70](https://github.com/pfaffman/discourse-pfaffmanager/blob/master/app/controllers/pfaffmanager/servers_controller.rb#L53-L70)

Однако мой тест возвращает статус 200, когда запрос `post` делает другой пользователь:

[https://github.com/pfaffman/discourse-pfaffmanager/blob/master/spec/requests/servers\_controller\_spec.rb#L149-L157](https://github.com/pfaffman/discourse-pfaffmanager/blob/master/spec/requests/servers_controller_spec.rb#L149-L157)

Похоже, мне нужно каким-то образом заставить Ember обратить на это внимание?

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [16.Январь.2021 13:10:10 UTC](https://meta.discourse.org/t/best-way-to-enforce-permissions-controller-or-constraint/176113/2 "2021-01-16T13:10:10Z")

</div>

Разве нельзя передать метод в `before_action` для проверки вашего условия?

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [16.Январь.2021 13:39:59 UTC](https://meta.discourse.org/t/best-way-to-enforce-permissions-controller-or-constraint/176113/3 "2021-01-16T13:39:59Z")

</div>

Я думаю, что проверку прав доступа нужно реализовать в контроллере или через ограничения. Модель, как я понимаю, не знает, кто её вызывает.

Большое спасибо за внимание к этому вопросу.

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [18.Январь.2021 07:07:23 UTC](https://meta.discourse.org/t/best-way-to-enforce-permissions-controller-or-constraint/176113/4 "2021-01-18T07:07:23Z")

</div>

Думаю, вам нужен метод-страж для проверки, разрешено ли пользователю выполнить данное действие. Например, `can_upgrade_server?`.

Также, после этого вы можете использовать метод `guardian.ensure_can_upgrade_server!`, который проверяет условие и выбрасывает исключение, что, как мне кажется, именно то, что вам нужно.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [18.Январь.2021 14:29:11 UTC](https://meta.discourse.org/t/best-way-to-enforce-permissions-controller-or-constraint/176113/5 "2021-01-18T14:29:11Z")

</div>

Оооо! Метод стража! Да! Я посмотрю на них! Спасибо.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [19.Январь.2021 21:11:38 UTC](https://meta.discourse.org/t/best-way-to-enforce-permissions-controller-or-constraint/176113/6 "2021-01-19T21:11:38Z")

</div>

Единственная модель, использующая `guardian`, — это [модель пользователя](https://github.com/discourse/discourse/blob/master/app/models/user.rb#L987-L989). Похоже, что основная логика работы с `guardian` сосредоточена в контроллерах.

Например, контроллер категорий использует [`ensure_can_create_category`](https://github.com/discourse/discourse/blob/master/app/controllers/categories_controller.rb#L95), который, как я полагаю, автоматически создается в [`lib/guardian.rb`](https://github.com/discourse/discourse/blob/master/lib/guardian.rb#L141).

Однако пока я не использую guardian, так как у меня возникают трудности с правильным его инициализированием. В моем контроллере у меня есть следующее:

[https://github.com/pfaffman/discourse-pfaffmanager/blob/master/app/controllers/pfaffmanager/servers\_controller.rb#L54-L75](https://github.com/pfaffman/discourse-pfaffmanager/blob/master/app/controllers/pfaffmanager/servers_controller.rb#L54-L75)

А вот спецификации, которые его тестируют:

[https://github.com/pfaffman/discourse-pfaffmanager/blob/master/spec/requests/servers\_controller\_spec.rb#L154-L181](https://github.com/pfaffman/discourse-pfaffmanager/blob/master/spec/requests/servers_controller_spec.rb#L154-L181)
