Uses version 0.3.1 of cancan-permits.
- Create User model with a :role attribute
- Create Article model
- Let a User have many Articles
$ rails g scaffold user name:string role:string
class Article < ActiveRecord::Base
belongs_to :user
end
$ rails g scaffold article user_id:integer name:string body:string
class User < ActiveRecord::Base
has_many :articles
end
$ rails g permits --roles editor
create app/permits/guest_permit.rb
create app/permits/admin_permit.rb
create app/permits/editor_permit.rb
create app/permits/any_permit.rb
create app/permits/system_permit.rb
create app/licenses/user_admin_license.rb
create app/licenses/blogging_license.rb
To avoid generating deault licenses:
$ rails g permits --roles editor --no-default-licenses
To get list of all generator options
$ rails g permits
Admin permit:
def permit?(user, options = {})
return if !role_match? user
can :manage, :all
end
Any permit:
def permit?(user, options = {})
super
end
Editor permit:
def permit?(user, options = {})
super
return if !role_match? user
owns(user, Article)
end
Guest permit:
def permit?(user, options = {})
super
return if !role_match? user
can :create, Article
end
System permit:
def permit?(user, options = {})
super
request = options[:request]
if request && request.host.localhost? && localhost_manager?
can(:manage, :all)
return :break
end
end
The system permit illustrates an example of how custom data can be sent into the options hash to be used for considering whether to give permission. Here it is assumed that the :request key can optionally have a request object to be used to determine if the user is accessing the app from localhost.
Migrate the DB (Development mode)
$ rake db:migrate
Seed the database with initial data (optional)
rake db:seed
Make the Test DB reflect the evelopment DB
rake db:test:prepare
The main spec is in spec/models/user_spec.rb
$ rspec models/user_spec.rb
Gemfile
gem 'cancan', '
> 1.4.0' # not sure this one is needed, but ...> 0.1.6'
gem 'cream', '
gem 'cancan-rest-links', '> 0.7.4'> 1.2.0'
gem 'devise', '
Run bundler
$ bundle install
$ rails generate devise:install
$ rails generate devise User
Fix the devise user migration:
class DeviseCreateUsers < ActiveRecord::Migration
def self.up
drop_table :users # <----- temporary hack, remove after migration is run
create_table(:users) do |t|
t.string :name # <-----
t.string :role # <-----
t.database_authenticatable :null => false
...
Update the Database!
$ rake db:migrate
rake db:test:prepare
Create a Rails initializer 'initializers/rest_links.rb'
We need to define the available roles in a central location.
module Cream
def self.available_roles
[:guest, :admin, :editor]
end
end
We should also modify the User model in 'models/user.rb' to reference this and add a #has_role? method
class User
def self.roles
Cream.available_roles # [:guest, :admin, :editor]
end
def has_role? role
(self.role || 'guest').to_sym == role.to_sym
end
end
Make all pages require login
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate_user!
end
This will ensure that current_user is set, which is fx used by CanCan's #can? and #cannot? methods
Now we need to configure the sign up form:
$ rails generate devise:views
in 'views/devise/registrations/new.html.erb'
We insert some code to create a text field to enter the role of a user
<%= f.label :role %>
<%= f.text_field :role %>
$ rails server
Now when we go to localhost:3000/articles, we will be sent to a page asking us to login or signup. If we signup we can create a user and experiment with different roles, then edit the permission files and see which links will be active or not for a given user with a given role. Nice!
In order to contribute to and improve the framework, I suggest you start by cloning the gems used:
$ git clone git://github.com/kristianmandrup/cancan-rest-links.git
$ git clone git://github.com/kristianmandrup/cream.git
$ git clone git://github.com/kristianmandrup/cancan-permits.git
Then configure the Gemfile to point to your local gem copy
Gemfile
gem 'cancan-permits', '
> 0.3.1', :path => '/...//cancan-permits'
gem 'cancan-rest-links', '> 0.1.6', :path => '...//cancan-rest-links'
gem 'cream', '~> 0.7.4', :path => '/...//cancan-permits'
Then you are free to put whatever debugging code (p puts and ... statetement?) in your local copy of the gems.
If you have problem with the rspec executable version, reinstall any rspec > 2.0.1 and try again.
$ gem list rspec
$ gem install rspec -v 2.1.0