Code Monkey home page Code Monkey logo

acl9's Introduction

acl9

Travis-CI

Acl9 is a role-based authorization system that provides a concise DSL for securing your Rails application.

Access control is pointless if you're not sure you've done it right. The fundamental goal of acl9 is to ensure that your rules are easy to understand and easy to test - in other words acl9 makes it easy to ensure you've got your permissions correct.

Installation

Acl9 is Semantically Versioned, so just add this to your Gemfile (note that you need 3.2 for Rails 6+ support):

gem 'acl9', '~> 3.2'

You will need Ruby > 2.0

Rails 4 - stick with 2.x

gem 'acl9', '~> 2.0'

Rails < 4 - upgrade Rails!

We dropped support for Rails < 4 in the 1.x releases, so if you're still using Rails 2.x or 3.x then you'll want this:

gem 'acl9', '~> 0.12'

Getting Started

The simplest way to demonstrate this is with some examples.

Access Control

You declare the access control directly in your controller, so it's visible and obvious for any developer looking at the controller:

class Admin::SchoolsController < ApplicationController
  access_control do
    allow :support, :of => School
    allow :admins, :managers, :teachers, :of => :school
    deny :teachers, :only => :destroy

    action :index do
      allow anonymous, logged_in
    end

    allow logged_in, :only => :show
    deny :students
  end

  def index
    # ...
  end

  # ...
end

You can see more about all this stuff in the wiki under Access Control Subsystem

Roles

The other side of acl9 is where you give and remove roles to and from a user. As you're looking through these examples refer back to the Access Control example and you should be able to see which access control rule each role corresponds to.

Let's say we want to create an admin of a given school, not a global admin, just the admin for a particular school:

user.has_role! :admin, school
user.has_role! :admin, of: school

Then let's say we have some support people in our organization who are dedicated to supporting all the schools. We could do two things, either we could come up with a new role name like :school_support or we can use the fact that we can assign roles to any object, including a class, and do this:

user.has_role! :support, School
user.has_role! :support, for: School

You can see the allow line in our access_control block that this corresponds with. If we had used :school_support instead then that line would have to be: allow :school_support

Now, when a support person leaves that team, we need to remove that role:

user.has_no_role! :support, School
user.has_no_role! :support, at: School

You can see more about all this stuff in the wiki under Role Subsystem

Database Setup

As mentioned in Role Subsystem you don't have to use these, if your role system is very simple all you need is a has_role? method in your subject model that returns a boolean and the Access Control part of Acl9 will work from that.

However, most commonly, the roles and role assignments are stored in two new tables that you create specifically for Acl9. There's a rails generator for creating the migrations, role model and updating the subject model and optionally any number of object models.

You can view the USAGE for this generator by running the following in your app directory:

bin/rails g acl9:setup -h

Configuration

There are five configurable settings. These all have sensible defaults which can be easily overridden in config/initializers/acl9.rb

You can also override each of the :default_* settings (dropping the "default_" prefix) in your models/controllers - see below for more detail:

:default_role_class_name

Set to 'Role' and can be overridden in your "user" model, see the wiki for more.

:default_association_name

Set to :role_objects and can be overridden in your "user" model, see the wiki for more. We chose a name for this association that was unlikely to conflict with existing models but a lot of people override this to be just :roles

:default_subject_class_name

Set to 'User' and can be overridden in your "role" model, see the wiki for more.

:default_subject_method

Set to :current_user and can be overridden in your controllers, see the wiki for more.

:default_join_table_name

This is set to nil by default, which will mean it will use the Rails method of calculating the join table name for a has_and_belongs_to_many (eg. users_roles). Remember that if you override this value, either do it before you run rails g acl9:setup or be sure to update your migration or database.

:normalize_role_names

Set to true (see "Upgrade Notes" below if you're upgrading) and can only be changed by setting it in Acl9.config. When true this causes Acl9 to normalize your role names, normalization is .to_s.underscore.singularize. This is done on both the setter and getter.

:protect_global_roles

Set to true (see "Upgrade Notes" below if you're upgrading) and can only be changed by merging into Acl9.config. This setting changes how global roles (ie. roles with no object) are treated.

Say we set a role like so:

user.has_role! :admin, school

When :protect_global_roles is true (as is the default) then user.has_role? :admin is false. Ie. changing the role on a specific instance doesn't impact the global role (hence the name).

When :protect_global_roles is false then user.has_role? :admin is true. Ie. setting a role on a specific instance makes that person a global one of those roles.

Basically these are just two different ways of working with roles, if you're protecting your global roles then you can use them as sort of a superuser version of a given role. So you can have an admin of a school and a global admin with different privileges.

If you don't protect your global roles then you can use them as a catch-all for any specific roles, so then the admins of schools, classrooms and students can all be granted a privilege by allowing the global :admin role.

Example

# config/initializers/acl9.rb
Acl9.config.default_association_name = :roles

# or...
Acl9.configure do |c|
  c.default_association_name = :roles
end

Reset Defaults

On the off chance that you ever need to reset the config back to its default you can use:

Acl9.config.reset!

Upgrade Notes

Acl9 now protects global roles by default

Please, PLEASE, PLEASE note. If you're upgrading from the 0.x series of acl9 then there's an important change in one of the defaults for 1.x. We flipped the default value of :protect_global_roles from false to true.

Say you had a role on an object:

user.has_role! :manager, department

We all know that this means:

user.has_role? :manager, department    # => true
user.has_role? :manager, in: department    # => true

With :protect_global_roles set to false, as it was in 0.x then the above role would mean that the global :manager role would also be true.

Ie. this is how 0.x behaved:

user.has_role? :manager      # => true

Now in 1.x we default :protect_global_roles to true which means that the global :manager role is protected, ie:

user.has_role? :manager      # => false

In words, in 1.x just because you're the :manager of a department that doesn't make you a global :manager (anymore).

Acl9 now normalizes role names by default

So basically we downcase, underscore, and singularize your role names, so:

user.has_role! 'FooBars'

user.has_role? 'FooBars'     # => true
user.has_role? :foo_bar      # => true

user.has_role! :foo_bar      # => nil, because it was already set above

If you're upgrading then you will want to do something like this:

Role.all.each do |role|
  role.update! name: role.name.underscore.singularize
end

Then check for any duplicates and resolve those manually.

Acl9 now raises ArgumentError on bad args to allow/deny

In 2.x and above we now try to help the developer by raising ArgumentError if they mess up with the options they pass to allow/deny, this prevents people doing things that they think are going to work but actually aren't like:

  allow all, actions: [ :index, :show ]    # <---- BROKEN!!

Community

Gitter: Join the gitter chat here

docs: Rdocs are available here.

StackOverflow: Go ask (or answer) a question on StackOverflow

Mailing list: We have an old skule mailing list as well acl9-discuss group

Contributing: Last but not least, check out the Contributing Guide if you want to get even more involved

Acknowledgements

All these people are awesome! as are all the people who have raised or investigated issues.

acl9's People

Contributors

antono avatar barttenbrinke avatar be9 avatar coreyward avatar d2kagw avatar enriquevidal avatar gitter-badger avatar javierg avatar jej avatar justincinmd avatar matadon avatar narnach avatar pjungwir avatar robuye avatar s-panferov avatar seancookr avatar sjain avatar smathy avatar smeevil avatar trydionel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

acl9's Issues

authorization_object.authorization_subject raises Deprecation Warning in Rails 3.0.8

DEPRECATION WARNING: String-based interpolation of association conditions is deprecated. Please use a proc instead. So, for example, has_many :older_friends, :conditions => 'age > #{age}' should be changed to has_many :older_friends, :conditions => proc { "age > #{age}" }.

is raised in newer Rails versions (3.0.5 and up? - certainly in 3.0.8).

propably related to model_extensions.rb
--> product.users #=> returns User objects, associated with the product
and the has_many ... :finder_sql ... (not using a proc seems to raise above deprecation warning)

Handle derived controllers better

Some people expect ACL block in derived controller to extend its counterpart from the base controller. So they put rather restrictive rules to the base (e.g. deny all), trynig to loosen the restrictions in descendant controllers.

Unfortunately this doesn't work. Each access_control call with a block results in a filter being appended to the "before" filter chain. Now add more filters, get more restrictive behavior.

skip_before_filter comes to the rescue when you need to circumvent ACL block from the base controller, but how could we truly inherit ACL rules?

I see several possibilities.

  1. Declare "virtual" ACL blocks, which are used only for inheritance. Something like:

    class BaseController < ApplicationController
      # ...
      access_control :base, :virtual => true do
        deny anonymous
      end
      # ...
    end
    
    class DerivedController < BaseController
      access_control do
        extends :base
        allow anonymous, :to => [:show, :index]
        allow logged_in
      end
    end
    

Here :base block doesn't get installed in BaseController as a filter.

  1. Modification of (1).

Install the filter, but also save the rules into inheritable array. Each derived controller will append its rules, calling skip_before_filter against the inherited filter.

    class BaseController < ApplicationController
      # ...
      access_control :base, :virtual => true do
        deny anonymous
      end
      # ...
    end

    class DerivedController < BaseController
      access_control :base do
        allow anonymous, :to => [:show, :index]
        allow logged_in
      end
    end

    class DerivedDerivedController < DerivedController
      access_control :base do
        allow anonymous, :to => [:custom]
      end
    end

We get 3 blocks here. The 3rd block is used to match first (both for allow and for deny). If it doesn't bring a match, the 2nd block is tried and then the 1st.

Versioning and Releasing

It doesn't look like you're touching the release version at all — the last bump was 2 years ago.

Likewise, the code RubyGems is serving up for gem 'acl9' is from January 2010.

Releasing is just as important as actually writing the code, otherwise nobody gets updates.

Using the ACL9 roles table as a has_many :through link

Well, it appears that you cannot reply to posts on the Google Groups without signing up, something I have no intention of doing (I like how they let you start a thread though...eugh).

Following on from :http://groups.google.com/group/acl9-discuss/browse_thread/thread/5b663c80191ac35a

I have the following

has_many :committee_memberships, :class_name => "Role", :finder_sql => 'SELECT * FROM roles r WHERE name = "member" AND authorizable_type = "Committee" AND id = (SELECT role_id FROM roles_users WHERE user_id = #{id} and role_id = r.id)'

This nicely returns all the role records for that user with the match. It is possible to use this to hardcode a "commitees" has_many without using the :through of users_roles but that isn't quite what I am after.

Has anyone got any ideas if this could be built on using a :through to get what I am after? Or any other ideas on how to get a :through working.

Complex roles

Something like

```
access_control do
allow all, :except => :destroy
allow complex_role, :to => :destroy do
is :strong
is :decisive
is :owner, :of => :object
is_not :banned
is_not :fake
end
end
```

Check for pre-existing associations?

Roles are great, but it would be awesome to be able to control authorization based on associations that already exist, without having to manually assign a role to a user. For example, let's say a User created a Post, so @post.creator returns the user that created it. I want to be able to do this:

allow :creator, :of => :post

without calling user.has_role!('creator', post).

I know that you can override #has_role?, I currently do that to achieve this. I just thought that this could be a rather common issue. My implementation also allows for the same role to be applied to other subjects (users, in this case), so it doesn't get in the way of anything else you would do.

What do you think? Here is my version of has_role?

def has_role?(role_name, object = nil)
  !! if object.nil?
    self.roles.find_by_name(role_name.to_s) ||
    self.roles.member?(get_role(role_name, nil))
  else
    role = get_role(role_name, object)
    subject_owns_object = object.send(role_name) == self if object.respond_to?(role_name)
    (role && self.roles.exists?(role.id)) || subject_owns_object
  end
end

Fix deprecation warning regarding has_and_belongs_to_many

After upgrading Rails to 3.0.4, I'm getting the following warning:

DEPRECATION WARNING: Having additional attributes on the join table of a has_and_belongs_to_many association is deprecated and will be removed in Rails 3.1. Please use a has_many :through association instead.

Issue with action block when allow anonymous and another role

I run into a bug with the dsl when using action blocks.

This work :
access_control do
allow :superadmin
action :index, :show do
allow anonymous
end
end

This doesn't :
access_control do
allow :superadmin
action :index, :show do
allow anonymous
allow :member
end
end

After some testing, the wrong expression is :
.(@_subject.nil?) || (!@_subject.nil? && @_subject.has_role?('member', nil)) && Set.new(['index','show']).include?(@_current_action)

As you can see, when anonymous is used, this expression always true.

This issue come from missing parentheses in _either_of function.

I correct it like so, and it works :
def _either_of(exprs)
clause = exprs.map { |expr| "(#{expr})" }.join(' || ')
return "(#{clause})"
end

I'll fork acl9, add few tests, and commit the correction.

Cheers
Franck

Add named scope to filter queries by role

It would be great if the autorization objects could have something like a named scope for querying instances based on a given authorization subject:

Foo.find_all_with (:manager=> @user)

Currently I'm guessing I would have to specify a join to the roles table.

acl9 work with mongo mapper?

Hello,

acl9 can work with mongo mapper? is it possible if yes then how because I am getting error

ActionView::Template::Error (undefined method `acts_as_authorization_subject' for User:Class):

Thanks
Akeel Qureshi

has_access? method

In the view, we might want to display links to some actions. And we might want to display them only to people having access to that action.

An helper method for that would be very helpful.

Let's guess the following restriction :

access_control do
    action :index do
        allow :staff
    end
end

Then to display the link only to the people having access to the index method, we could to :

<% if has_access?('index') do %>
    ....
<% end %>

Being able to check for access in an other controller would be also quite helpful.

<% if has_access?('controller/index') do %>
    ....
<% end %>

need to put habtm for user.roles

I have:

class User < ActiveRecord::Base
acts_as_authentic do |c|
c.transition_from_restful_authentication = true
end

acts_as_authorization_subject
end

class Role < ActiveRecord::Base
acts_as_authorization_role
end

All works fine except that user.roles that give me method_missing error. I need to put habtm roles relation in the User class.

What I am missing ?

Failure to restrict access if object instance is nil

Example:

class Post < ActiveRecord::Base
  access_control do
    allow :owner, :of => :post
  end
end

Note that @post has not been assigned, and is nil.This will allow any subject that has an :owner role on any object. The obvious fix is to check for instance variable existence before checking if the role exists, but I think a more appropriate fix is to adjust the way role checking is done. I find the current implementation to be poorly designed:

user.has_role! :owner, @post
user.has_role? :owner  # => true
@post = nil
user.has_role? :owner, @post  # => true

I had to change a general site-admin level role to :superadmin so I could have both an :owner and an :admin for a given object in one of my applications that I added ACL9 to.

I understand that there is some convenience to being able to query a subject for a role, regardless of the object, but a different API would avoid errors. Potentially: user.has_role? :owner, :any.

Role names are case sensitive on PostgreSQL

Using the pg gem (version 0.13.2) on Heroku Celadon Cedar with the Ronen database I'm experiencing issues related to case-sensitive roles. Notably:

user.has_role? 'User', some_project  #=> false
user.has_role? 'user', some_project  #=> true

I was under the impression ACL9 did case-normalization or ran case-insensitive queries, but that doesn't appear to be the case. I'll probably submit a patch that simply downcases roles anytime they are received from the user — I'm not aware of another way of handling this given all the custom queries ACL9 generates.

Thoughts?

1 role 2 users

unable to create 1 role for 2 different users

>> u = User.first :order => 'rand()'
>> u.has_role! :bla
=> [#<Role id: 4, name: "bla", authorizable_type: nil, authorizable_id: nil, created_at: "2009-07-28 12:00:17", updated_at: "2009-07-28 12:00:17">]
>> u = User.first :order => 'rand()'
>> u.has_role! :bla
ActiveRecord::StatementInvalid: Mysql::Error: Duplicate entry '4' for key 1: INSERT INTO `roles_users` (`created_at`, `updated_at`, `role_id`, `id`, `user_id`) VALUES ('2009-07-28 12:00:17', '2009-07-28 12:00:17', 4, 4, 7599)

rails 2.3.3

Improve README

After the rest of the issues are done we need to update the README accordingly.

Improve the docs

I've seen the acl9 documentation referred to as "confusing" or "don't read the docs, just use the thing".

Currently the only doc is the huge README file. Actually it's more of a description what and how acl9 does. Would be enough for me if I weren't the creator, but... Different people learn things different way.

So, do you see any ways of improving the docs? What are the most unclear aspects? Should it be tutorials, or...?

Looking forward to your comments here.

Allow to use methods instead of @ivars in role checking

Idea 1. Query methods.

allow :manager, :of => :project

...which results now in:

current_user.has_role?(:manager, @project)

...will turn into:

current_user.has_role?(:manager, (controller.respond_to?(:project) && controller.send(:project)) || @project)

Or be it _project?

Idea 2. :but_before option.

allow :manager, :of => :project, :but_before => :load_project

will turn into:

controller.send(:load_project); current_user.has_role?(:manager, @project)

This will free us from unnecessary :before_filters

NB: this is semi-available right now, with

allow :manager, :of => :project, :if => :load_project

Normal load_project like

def load_project
  @project ||= Project.find(params[:id])
end

will return trueish value and work.

Idea 3. More explicit before

access_control do
  allow :superadmin
  call :load_project
  allow :manager, :of => :project
end

Access rules are evaluated in the same order they have been specified in ACL, so
controller.send(:load_project) will occur only if :superadmin check failed, but before :manager check.

Administration Subsystem

Sorry for posting this here...maybe someone can create a Google Group for acl9?

Can someone recommend a gem/plugin for administration of users, roles, preferences, etc.? I know various CMS's like Radiant and BrowserCMS have this, but I don't necessarily want to build all my apps on top of them. I'm using Authlogic for authentication and acl9 for authorization. I was more curious about user interface options. I'm tired of building out my own, and was wondering if there were an easy drop-in option. I may actually be better off building on top of a framework like Radiant. It just has to be extensible enough to add my custom models and workflow. Thoughts?

Thanks,
Mark

More than one deny/allow call inside action block breaks access control

In a larger access_control block any action block using more than one allow/deny call breaks all following action blocks. In the example due to the allow_all in the second block the third action is open to everybody instead of being limited to the owner.

action :works do
  allow logged_in
end

action :breaks_access_control do
  allow all #this one is no longer limited to the action!
  allow :viewer #this one is okay
end

action :broken_by_above do
  allow :owner
end

Depending on the allow/deny call the remaining action control is influenced - even worse if one was to call allow all as in the example above the default deny rule is ignored for all actions not listed or following the breaking action block.

This issue seems to be releated to Issue 25 but as it seems to be a lot more than only the logged_in call i submited this new issue.

Privilege revocation for deleted objects

Currently there seems to be privilege revocation missing which results in orphaned data rows.
Example:

@user.has_role! :provider, @service

If @service or @user is deleted, corresponding privileges need to be revoked. Maybe this could be implemented inside an after_destroy callback.

object-to-subject association assumes a table name that might not be correct

acts_as_authorization_object generates a string called "sql_tables" that hard-codes a join table name of, effectively, "roles_subjects". This isn't necessarily the right table name, particularly not when the subject table name comes lexicographically before the role table name.

For example, in my acl9 app, I don't use "user" as the authorization subject, I use "person". That makes my join table name "people_roles". Unfortunately, that means that if I have a Post model that is an authorization object, @post.people breaks with the following error:

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: roles_people: SELECT COUNT(DISTINCT people.id)  e
INNER JOIN roles_people ON person_id = people.id
INNER JOIN roles               ON roles.id = role_id
WHERE authorizable_type = 'Post'
AND authorizable_id = 1

Weird behavior with :has_method

Hello,

I'm trying to implement acl9. But I see some strange behavior.

The following works well :

access_control do
    allow :staff

    action :edit, :update do
        allow :owner, :of => :object
    end

    action :show do
        allow all
    end

    action :new, :create do
        allow logged_in
end

But I'd like to be able to see, in my views, if a user can edit the object or not (without repeating the permission).
So I though I'd generate an edit? method, accessible in my views.

But with the following :

access_control :can_edit? do
    action :edit, :update do
        allow :owner, :of => :object
    end
end

access_control do
    allow :staff

    action :show do
        allow all
    end

    action :new, :create do
        allow logged_in
    end
end

My permissions doesn't works anymore. It seems anyone who is not owner of :object can't access anything.

This seems like an anormal behavior to me.

acts_as_authorization_subject error

I had an error when trying to implement acl9 and I hadn´t found nothing related to it.

undefined local variable or method `acts_as_authorization_subject' for #Class:0x5d0ceec

It seems like acts_as_authorization gem or plugin is missing. Any idea?

PS: It would be great if you could make (or an tutorial) of an example app combining authlogic with acl9. I know that authentication is out of the scope of this plugin but everyone seems to be migrating to authlogic.

Has and belongs to many deprecation warning.

Every time my app accesses the roles_users table I get a deprecation warning similar to this:

DEPRECATION WARNING: Having additional attributes on the join table of a has_and_belongs_to_many association is deprecated and will be removed in Rails 3.1. Please use a has_many :through association instead. (called from assign_to_user at /home/lee/Dropbox/works/rails/cureher/app/models/scrapbook.rb:10)

I get dozens of these warnings every time I run my tests.

I'm using Rails 3.0.7 and acl9 0.12.0

Why i can't use role name as :admin_translators

controller:


  access_control do
    allow :admin_translators
    allow :translator
  end

and user has this role assigned


user.has_role? :admin_translators
=> true

I got all the time access denied - spend for this a lot of hours, when i remove the 's' from the end (role name is now :admin_translator)

for translator it works fine all the time.

is there somewhere directive what the name of role can't be ?

access control fails !

I have controller with :

access_control :debug=>true do allow :admin allow :owner, :of => :account, :except => [:index, :destroy] end

When I go to the page I would like to protect I see this debug line:

Acl9 access_control expression dump (AccountsController) ((!controller.send(:current_user).nil? && controller.send(:current_user).has_role?('admin', nil)) || ((!controller.send(:current_user).nil? && controller.send(:current_user).has_role?('owner', controller.instance_variable_get('@account'))) && !Set.new(['index','destroy']).include?(controller.action_name))) && (true)

Not the last part... &&(true) will always return true..is this correct??

Because when I go to a page where the current_user has no :owner role for I just see the page.. No error is given..

activerecord updates everything after enable acl9

I'm using rails 2.3.5 with authlogic
After I install acl9 as plugin and I try to update something with activerecord, it updates every single attributes instead of those I submitted in the form.
For example, before I enable acl9 when I update the field phone and submit the form, it executes the sql UPDATE businesses SET phone = '2222222222', updated_at = '2010-01-03 07:14:16', WHERE id = 37
but after enable acl9 and i do the same thing again, the follwing sql is executed instead: UPDATE businesses SET created_at = '2010-01-03 02:24:12', business_cat_id = 3, phone = '2222222222', annualIncome = NULL, business_type_id = 4, phoneExt = '', fax = '', businessName = 'business999999', franchise = 0, monthlyRent = NULL, operateTime = '', items = '', numEmployee = NULL, user_id = 1, rating = 0.0, email = '', description = '', address_id = 142, rnumber = 22222222, capitalQuota = NULL, monthlySalary = NULL, website = '', updated_at = '2010-01-03 07:14:16', logo = NULL WHERE id = 37

Add a method to auth objects to query about auth subjects with particular role

Quote from Jaryl Sim:

is there any way we can retrieve users who happen to have role access to an object? For example, an object has 3 managers. Can we do something like object.managers? I know that this is beyond the scope of access control, but I think that this use case might happen often enough to be addressed in Acl9.

Undefined method error for 'join_table_name'

When creating a new project (using Rails 3.1) and doing the most basic of setups, you run into these errors.
You're able to work around it by explicitly supplying the join_table_name option with every acts_as_... call, but that's not ideal.

Here's the code i've used to work around:
acts_as_authorization_object subject_class_name: "User", join_table_name: "roles_users"

AJAX requests breaks after upgrade rails from 2.3.8. to 2.3.11

I have role names in russian, for example:

access_control do
allow :Администратор
allow :Заказчик
allow :Исполнитель
deny anonymous
end

and after upgrade rails from 2.3.8. to 2.3.11 a became FilterSyntaxError in generators.rb only by AJAX requests here :

    def to_proc
      code = <<-RUBY
        lambda do |controller|
          unless #{allowance_expression}
            #{_access_denied}
          end
        end
      RUBY

      self.instance_eval(code, __FILE__, __LINE__)
    rescue SyntaxError
      raise FilterSyntaxError, code
    end

undefined method `quoted_table_name' for Acl9::ModelExtensions::Subject:Module

One of my models is throwing this error and I cannot figure out why. I'm using non-standard naming (groups for roles).

tutoring.rb:
# Search
def self.search(search, start_date, end_date, page, sort_on='time_in', sort_dir='DESC')
conditions = ""
order = "#{sort_on} #{sort_dir}"
order = "time_in DESC" if order.blank?

    unless start_date.blank? || start_date == "Start date"
        conditions = conditions + " AND " unless conditions.blank?
        conditions = conditions + "tutorings.time_in >= '#{Date.parse(start_date)}'"
    end

    unless end_date.blank? || end_date == "End date"
        conditions = conditions + " AND " unless conditions.blank?
        conditions = conditions + "tutorings.time_in <= '#{Date.parse(end_date)+1.day}'"
    end

    unless search.blank? || search == "Search terms"
        conditions_was = conditions
        conditions = conditions + " AND (" unless conditions.blank?
        # Split the search query and remove extra spaces
        terms = search.split(/\s+/)
        conditions = conditions + terms.collect do |term|
         "users.pawsid LIKE '#{term}' OR subjects.subject LIKE '%#{term}%'"
        end.join(" OR ")
        conditions = conditions + ")" unless conditions_was.blank?
    end

    per_page = 30
    if page == "ALL"
        per_page = 99999
        page = 1
    end
    # Pass the paginate values
    paginate :per_page => per_page, :page => page,
        :conditions => conditions, :order => order, :include => [ :subject, :user ]
end

Trace:
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:323:in preload_belongs_to_association' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:318:ineach'
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:318:in preload_belongs_to_association' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:120:insend'
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:120:in preload_one_association' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/ordered_hash.rb:69:ineach'
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/ordered_hash.rb:69:in each' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:114:inpreload_one_association'
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:91:in preload_associations' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:90:inpreload_associations'
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:90:in each' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/association_preload.rb:90:inpreload_associations'
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1555:in find_every' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:615:infind'
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/mislav-will_paginate-2.3.8/lib/will_paginate/finder.rb:82:in send' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/mislav-will_paginate-2.3.8/lib/will_paginate/finder.rb:82:inpaginate'
/opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/mislav-will_paginate-2.3.8/lib/will_paginate/collection.rb:87:in create' /opt/ruby-enterprise-1.8.6/lib/ruby/gems/1.8/gems/mislav-will_paginate-2.3.8/lib/will_paginate/finder.rb:76:inpaginate'
/var/www/development/jlee/mehmry/app/models/tutoring.rb:54:in search' /var/www/development/jlee/mehmry/app/controllers/tutorings_controller.rb:10:inindex'

Check in gemspec to the repository

As it seems that the latest gem release was a while back, you should check in the gemspec so we could use the repo as a gem with Bundler until you push out the next gem release.

logged_in generates wrong clause in action

Hi!

At first of all, thank you for great stuff!

Seems I found wrong clause generation by logged_in conditions in action.
For instance:

    action :favorite do
      allow logged_in, :if => :public?
      allow :subscriber, :of => :obj
    end

will generate (stripped):

(
  (!controller.send(:current_user).nil?) &&
  controller.send(:public? )
) ||

(
  !controller.send(:current_user).nil? &&
  controller.send(:current_user).has_role?('subscriber', controller.instance_variable_get('@obj'))
) &&
(
  controller.action_name == 'favorite'
)

The controller.action_name == 'favorite' condition stands outside condition generatied by allow logged_in, :if => :public? and as result logged_in condition touches all other actions!

Hope it's clearly. I ready to get more info.

roles_users created_at column issue

Hi, I'm trying to figure out why the created_at column of roles_users' table seems to take the user one when assigning a role to a user. It should not have its own creation date? Any helps?

ruby-1.8.7-p174 > Time.now => Thu Feb 24 15:50:11 +0100 2011
ruby-1.8.7-p174 > User.last.has_role! "installer"
User Load (0.5ms) SELECT * FROM "users" ORDER BY users.id DESC LIMIT 1
Country Load (0.2ms) SELECT * FROM "countries" WHERE ("countries"."id" = 106)
Role Load (0.2ms) SELECT * FROM "roles" WHERE (name = 'installer' and authorizable_type IS NULL and authorizable_id IS NULL) LIMIT 1
Role Load (0.1ms) SELECT "roles".id FROM "roles" INNER JOIN "roles_users" ON "roles".id = "roles_users".role_id WHERE ("roles"."id" = 2) AND ("roles_users".user_id = 31 ) LIMIT 1
SQL (0.3ms) INSERT INTO "roles_users" ("created_at", "updated_at", "role_id", "user_id") VALUES ('2010-09-16 14:11:24', '2010-09-16 14:11:24', 2, 31)
Role Load (0.5ms) SELECT * FROM "roles" INNER JOIN "roles_users" ON "roles".id = "roles_users".role_id WHERE ("roles_users".user_id = 31 )
=> [#Role id: 2, name: "installer", authorizable_type: nil, authorizable_id: nil, created_at: "2010-09-16 14:11:24", updated_at: "2010-09-16 14:11:24">]
ruby-1.8.7-p174 > Role.find_by_name("installer")
Role Load (0.3ms) SELECT * FROM "roles" WHERE ("roles"."name" = 'installer') LIMIT 1
=> #Role id: 2, name: "installer", authorizable_type: nil, authorizable_id: nil, created_at: "2010-09-16 14:11:24", updated_at: "2010-09-16 14:11:24">

Test rewrite

Our current tests are hard to read and the gem how it's written is hard to test.

Rails3 problem with acts_as_authorization_object

I have organisation which acts as acts_as_authorization_object and when i query current_org.users.all
It gives me following mysql error and if I comment it works fine
acl9 version acl9 (0.12.0)

Mysql::Error: Operand should contain 1 column(s): SELECT users.* FROM users WHERE (SELECT DISTINCT users.* FROM users
INNER JOIN roles_users ON user_id = users.id
INNER JOIN roles ON roles.id = role_id
WHERE authorizable_type = 'Organisation'
AND authorizable_id = 10
)

Rspec + Mocha + acl9

This is a request for help more than an issue if anyone else has run into this.
Given the code in the following gist: http://gist.github.com/120833

I have a pretty standard restful controller and a a spec file for testing it. In the spec file I have two ways of creating an authlogic/acl9 powered admin user session so far.

One method is to just use a factory_girl factory to create a valid user, assign the role and that is that. (The two commented out lines in the before :each) This method WORKS.

However I don't want to be hitting the DB with any of these controller specs so I am stubbing the User model and instead of using has_role!(:admin) I instead stub out has_role?(:admin) to always return true (The uncommented lines in the before :each). However when I use this method I get the following error

Acl9::AccessDenied in 'CommitteesController new action should render new template'
Acl9::AccessDenied
/home/jjones/Projects/Web/opensourcecountry/vendor/gems/be9-acl9-0.10.0/lib/acl9/controller_extensions/generators.rb:82:in `to_proc'
/home/jjones/Projects/Web/opensourcecountry/vendor/gems/haml-2.0.9/rails/../lib/sass/plugin/rails.rb:19:in `process'
./spec/controllers/committees_controller_spec.rb:39:

and the debug dump

=== Acl9 access_control expression dump (CommitteesController)
((!controller.send(:current_user).nil? && controller.send(:current_user).has_role?('admin', nil)) || ((true) && Set.new(['index','show']).include?(controller.action_name)) || ((!controller.send(:current_user).nil?) && (controller.action_name == 'join')) || ((!controller.send(:current_user).nil? && controller.send(:current_user).has_role?('member', controller.instance_variable_get('@committee'))) && (controller.action_name == 'leave'))) && (!((!controller.send(:current_user).nil? && controller.send(:current_user).has_role?('member', controller.instance_variable_get('@committee'))) && (controller.action_name == 'join')))

However if I drop to script/console in the test environment and create the user using the two methods above and run user.has_role?(:admin) then both methods return true. I am not sure why it isn't working when running the specs.

Any help would be much appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.