Control control - Better Permissions and Roles

**THIS IS DEFINITELY NOT READY YET** I've still got to a bunch of testing and need to revise the rest of the existing code to use this. This will close #69, when it's merged. 

I want to give a quick high-level overview about what I'm doing to get a bit of feedback, even if it's "Ed this is crazy why would we ever do things that way". I'll also add this to the wiki for documentation if we merge this. 

This PR introduces two new namespaces `ControlControl` and `RoleControl` (they're separated so eventually I can turn them into gems). 

### `ControlControl`
This is a generic library for determining if one object is allowed to take actions on another object. It has two main modules `Resource` and `Actor`

The `Resource` Module defines the class method `can(action, filter=nil, &block)`, it defines an action type an actor object can take on a Resource (something abstract like `:edit` or `:read`), and then either takes a symbol name of an instance method, or a proc that is `instance_eval`ed. It also creates an instance method called `can_#{ action }?` that runs the supplied method or proc against an actor object to determine if it's allowed to take an action.

You can call `can` with the same action multiple times to build a chain of filters. An example resource class could look like. 

```ruby
class Thing
  extends ControlControl::Resource

  attr_accessible :favorite_thing

  can :read, { |actor| actor.is_admin? }
  can :read, :has_permissions
  can :edit, :has_permissions

  def has_permissions(actor)
    actor.has_grail?
  end
end
```

There is also a small extension of `Resource` called `ActAs` for objects that are both resources and actors that adds a `can_as` class method that acts similarly to `can`. It address #69. 

Instances of this class will have methods `can_read?` and `can_edit?`. `can_read?` will be true if the actor object `has_grail?` or `is_admin?`. 

The `Actor` module is included adds a single method to a class it's included in. `do_to_resource(resource, action, as: nil, &block)`. This method simply tests the actor object against the `can_#{ action }?` method on the supplied resource object, and either raises a `ControlControl::AccessDenied` exception or executes the supplied proc with actor and resource as its arguments. 

An example:

```ruby
Class ActingThing 
  include ControlControl::Actor

  def has_grail?
    true
  end
end

thing = Thing.new
at = ActingThing.new

at.do_to_resource(thing, :edit) do |actor, resource|
  resource.favorite_thing = actor
end
```

It also includes an optional keyword argument `as` that accepts another object that extends the `ActAs` method. When that argument is used the calling object is tested against the `can_#{ action }_as?` method of the `as` object. If that test sucess it, then does a `as_object.do_to_resource(resource, action, &block)` call. If that test fails, a `ControlControl::AccessDenied` exception is raise. 

### `RoleControl`
RoleControl includes `Enrolled`, `Controlled`, and `VisibilityControlled` that sit on top of ControlControl and implement logic for accessing by user roles. 

`Enrolled` is implemented on top of Actor and adds a `roles_for(klass, association)` class method. It's used with the instance method `roles_query_for` that produces an ActiveRecord::Relation based on the supplied association for an instance of the given named class. 

I feel like that was a bad explanation so here's an example:

```ruby
class User < ActiveRecord::Base
  include ControlControl::Enrolled
  has_many :user_project_preferences

  roles_for Project, :user_project_preferences
end

p = project.create!
p.save!
u = User.create!
u.save!
UserProjectPreference.create(user: u, project: p, roles: ['collaborator']).save!
u.roles_query_for(p) #=> ActiveRecord::Relation<[UserProjectPreference(project_id: 1, roles: ['collaborator'])]>
```

`Controlled` is implemented on top of `Resource` and adds a `can_by_role(action, *permitted_roles)` method. Basically you give a can action name as in `Resource` and then a list of permitted roles. When you call `can_#{ action }?` it compares the supplied roles against the result of `enrolled_actor.roles_query_for(controlled_resource)`. 

Example: (assuming the above User is still defined).

```ruby
class Project < ActiveRecord::Base
  extend RoleControl::Controlled

  can_by_role :edit, :collaborator, :translator
end

p = Project.new(name: "blad!")
p.save!
u = User.new(name: "grrr!")
u.save!
upp = UserProjectPreferences.new(user: u, project: p, roles: ['collaborator'])
upp.save!

u.do_to_resource(p, :edit) do |user, project|
  project.favorite_user = u
  project.save!
end
```

`VisibilityControlled` is a further extenion of `Controlled` that allows the permitted roles to be serialized to the Database instead of declared in code. Right now is only implemented as in a `can_read?` predicate, and a `visible_to` class_method that returns a scope of objects that are visible to an actor. 

This does change how visibility is handled from how it was previously. Instead of having a visibility state, we're instead going to let users decide what roles a project will be visible to at a given time. (The state bit could still be faked in the front end if we want to keep similar functionality). 

Let me know if there any other questions about how stuff works in this. I know there are still a few more TODOs before this is ready to merge. Off the top of my head I can think of:

- [x] Specs for `RoleControl` and `ControlControl`
- [x] Conditional inclusion of ownership test in `VisibilityControl
- [x] Conversion of Controllers to use this.
- [x] Constrain and Validate the names of assignable roles. 
- [x] Override for Admin Users
- [ ] RSpec Helpers for Testing Correct Scopes

And I'm sure there will be more. Also apologies for the numerous spelling errors that are undoubtedly in here. 
Sorry they're not being tested yet. I can add specs. They validate roles
set in them, but I think that's the only behaviour that needs tests.
On Aug 21, 2014 8:37 AM, "Campbell Allen" <notifications@github.com> wrote:

> In spec/models/user_collection_preference_spec.rb:
>
> > @@ -0,0 +1,5 @@
> > +require 'spec_helper'
> > +
> > +RSpec.describe UserCollectionPreference, :type => :model do
>
> I see this is the only *_preference spec. How should we test these
> preferences OR are they being tested already?
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/zooniverse/Panoptes/pull/132/files#r16538636>.
>