Rails Разрешения API REST (CanCan) с клиентом Angular JS. Как визуализировать пользовательский интерфейс на основе разрешений?

Я создаю проект, который работает только через API JSON (Rails 4.0, PostgreSQL). Это большое приложение с разрешениями на базе базы данных. И у меня есть приложение AngularJS, которое работает с этим REST API.

Упрощенная структура:

employees >--- position ---< permission

Employee.rb

belongs_to :position

Position.rb

has_many :employees
has_many :permissions, dependent: :destroy

Permission.rb

belongs_to :position
## Columns
 # action (:manage, :read, :update, :create, etc...)
 # subject_class
 # subject

У меня есть проблема с кнопками/ссылками действий на стороне клиента AngularJS.

Например, я не хочу показывать ссылку "Добавить заказ" где-то в приложении Angular, потому что разрешение позиции сотрудника позволяет читать только ресурс и не изменять его:

id    action     subject_class     subject
 1    :read      Order            

Как я попытался решить эту проблему

Я создаю ресурс GET api/v1/employees/me, который возвращает current_employee со всеми его правами:

"employee": {
    ...
    :position": {
        ...
        "permissions": {
           {"id": 1, "action": "read", "subject_class": "Order", "subject": ""},
           {"id": 6, "action": "manage", "subject_class": "Waybill", "subject": ""}
        }
     }
  }

Итак, у меня есть все разрешения на стороне клиента, но что является лучшим способом получения прекрасной интеграции, полученной разрешениями с пользовательским интерфейсом приложений AngularJS?

Ответ 1

После некоторого рытья я думаю, что нашел работоспособное решение. Это сочетание вашего подхода с комментарием Джона Самвелла выше:

http://jonsamwell.com/url-route-authorization-and-security-in-angular/

и сообщение Eric Zou в блоге:

http://blog.ericzou.com/2013/05/03/using-angularjs-for-existing-rails-app/

Подводя итог:

  • создать службу рельсов, которая отвечает cancan abilities текущего пользователя на стороне рельсов в формате json. Похоже, это то, что вы начали делать с вашим запросом GET для разрешений. Подобно этому (из блога Эрика) при вызове функции /abilities для пользователя:
{
  "manage": {
    "User": true,
    "Post": false,
    ...
  },
  "read": {
    "User": true,
    "Post": true
    ...
  },
  "Update": {
    "User": true,
    "Post": false
  }
  ...
}

Чтобы получить Способности для конкретного пользователя, вы бы сделали что-то вроде Ability.new(current_user) в контроллере. Он возвращает объект с кучей правил. Правила имеют условия, которые позволят вам ограничить доступ к определенным сообщениям.

  • создать службу в angular, которая обрабатывает синтаксический анализ, который работает как уровень абстракции между тем, что вы получаете со стороны рельсов (определяет, можете ли вы получить доступ к маршруту или можете управлять, читать и т.д. конкретную модель (например, может? (: управлять, отправлять)). Вы можете сделать эту услугу настолько сложной, насколько хотите.

  • также создайте директиву в angular, чтобы обработать то, что нужно показать. Эрик предлагает использовать ng-show для этого, что хорошо, но очистить его чем-то похожим на предложение Jon: <div access="post" access-type="read" access-options="options">Secret Post</div> имеет смысл для меня.

Убедитесь, что вы ничего не обслуживаете с сервера, который не хотите, чтобы ваши пользователи видели, как они взломали ваш javascript, чтобы изменить их разрешения. Это не безопасность, это управление пользовательским интерфейсом.