Skip to content

dileepnandanam/dynamic_acl

Repository files navigation

Dynamic Access Controll

dynamic_acl is a gem for access controll, which provides web view of an editable access controll matrix where user can give or take back permissions for each user type for each user action under specific state of resource

To get started:

#Gemfile
gem 'dynamic_acl'

#on command line
rake dynamic_acl:install

#example usage

#user.rb
def self.user_types
  [
    "admin",
    "student",
    "faculty"
  ]
end

def self.actions
    [
      "create",
      "edit",
      "update",
      "delete"
    ]
  end

def user_type
  if admin?
    "admin"
  elsif student?
    "student"
  else
    "faculty"
  end
end

#article.rb
def self.states
  [
    "new",
    "archived",
    "published"
    "hidden",
    "deleted"
  ]
end

#articles_controller.rb
def create
  @article = Article.new(article_params)
  if current_user.can?('create', @article) #Assuming Article.new.state => "new"
    @article.save
  end
end

Now your all set. Go to localhost:3000/dynamic_acl/<model_name> ex. localhost:3000/dynamic_acl/article

screenshot: https://www.dropbox.com/s/2edzn8v2i8ip1c9/dynamic_acl.jpg?dl=0

NB: initially theres no access controll for the controller where we edit access right. You have to manually put some before_action method to restrict access to DynamicAclsController depends on your app permissions.

Complex actions over derived/dynamic states of resource

If you have little more complicated access controll rules like student can't delete anothers article, you can define the action accordingly and set acl matrix like,

#articles_controller.rb
def delete
    @article = Article.find(params[:id])
    action = @article.user != current_user ? "delete_another's_article" : "delete_his_article"
    if current_user.can?(action, @article)
        @article.destroy
    end
end

#article.rb
def self.actions
    [ 
      "delete_his_article",
      "delete_another's_article",
      "create",
      "edit",
      "update",
      "delete"
    ]
  end

And you can uncheck the cell in acl matrix under "delete_another's_article" for each states and for students.

You can also play with dynamic/derived states for artiles. For ex. if you want to prevent deletion of article with comments which is created by the current_user himself, like

#article.rb
def self.states
    [
        "with_comments",
        "archived",
        "published",
       "new"
    ]
end

def state
    @article.comments.count > 0 ? "with_comments" : state
end

And you can uncheck delete action in acl matrix under state "with_comments" corresponding to students.

Forbid particular user from certain action.

This is little bit tricky since we create Acl object for allowed actions, if we want to allow a set of users to do something , we need to create as many Acl objects. So we create Acl objects for users who are prevented with actions like "not_create".

ex. Acl.create(action: "not_do_action", user_id: 420, user_type: "student", object_type: "Article", state: "archived")

When we call User.find(420).can?("not_do_action", @article), we will get the Acl object which means User#420 can not do this action. So we do

def action
    @user = User.find(420)
    unless @user.can?("not_do_action", @article)
        do_action(@article)
    end
end

For other users, there wont be an Acl object with action "not_do_action", hence the can? method returns false.

About

Dynamic access controll

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published