最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Rails REST API permissions (CanCan) with Angular JS client. How to render UI based on permissions? - Stack Overflow

programmeradmin2浏览0评论

I'm building a project which works only via JSON API (Rails 4.0, PostgreSQL). It's a big application with database based permissions. And I have AngularJS app which works with this REST API.

Simplified structure:

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

I have a problem with action buttons/links on AngularJS client side.

For example I don't want to show link "Add Order" somewhere in Angular app because Employee's position permission allows only to read resource and not to modify it:

id    action     subject_class     subject
 1    :read      Order            

How I tried to solve this problem

I create a resource GET api/v1/employees/me which returns current_employee with all his permissions:

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

So I have all permissions on client side, but what is the best way of beautiful integration received permissions with AngularJS applications UI?

I'm building a project which works only via JSON API (Rails 4.0, PostgreSQL). It's a big application with database based permissions. And I have AngularJS app which works with this REST API.

Simplified structure:

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

I have a problem with action buttons/links on AngularJS client side.

For example I don't want to show link "Add Order" somewhere in Angular app because Employee's position permission allows only to read resource and not to modify it:

id    action     subject_class     subject
 1    :read      Order            

How I tried to solve this problem

I create a resource GET api/v1/employees/me which returns current_employee with all his permissions:

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

So I have all permissions on client side, but what is the best way of beautiful integration received permissions with AngularJS applications UI?

Share asked Jul 21, 2014 at 6:15 Pavel TkackenkoPavel Tkackenko 9537 silver badges20 bronze badges 1
  • 2 I wrote a blog post about this explaining how to do this kind of stuff jonsamwell./url-route-authorization-and-security-in-angular – Jon Commented Jul 21, 2014 at 8:10
Add a ment  | 

1 Answer 1

Reset to default 8

After some digging I think I have found a workable solution. It is a bination of your approach with Jon Samwell's ment above:

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

and Eric Zou's blog post:

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

To summarize:

  • create a rails service that responds with the cancan abilities of the current user on the rails side in json format. Looks like that is what you have started doing with your GET request for permissions. Like this(from Eric's blog) when calling /abilities.json for current user:
{
  "manage": {
    "User": true,
    "Post": false,
    ...
  },
  "read": {
    "User": true,
    "Post": true
    ...
  },
  "Update": {
    "User": true,
    "Post": false
  }
  ...
}

To get the Abilities for a specific user you would do something like Ability.new(current_user) in the controller. It returns an object with a bunch of rules. The rules have conditions which will allow you to limit the access to specific posts.

  • create a service in angular that handles parsing that works as an abstraction layer between what you get from the rails side(determines if you can access a route or can manage, read, etc a specific model( e.g., can?(:manage, post) ). You can make this service as plicated as you'd like.

  • also create a directive in angular to handle what to show. Eric suggests using ng-show to do this which is fine, but cleaning it up with something similar to Jon's suggestion: <div access="post" access-type="read" access-options="options">Secret Post</div> makes sense to me.

Make sure that you don't serve up anything from the server that you wouldn't want your users to see after they have hacked your javascript to change their permissions. This is not security, it is UI management.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论