abilities 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +85 -0
- data/Rakefile +32 -0
- data/lib/abilities.rb +25 -0
- data/lib/abilities/action_controller/base.rb +20 -0
- data/lib/abilities/action_view/base.rb +14 -0
- data/lib/abilities/concern.rb +12 -0
- data/lib/abilities/definitions.rb +54 -0
- data/lib/abilities/exceptions.rb +3 -0
- data/lib/abilities/proxy.rb +23 -0
- data/lib/abilities/railtie.rb +14 -0
- data/lib/abilities/version.rb +5 -0
- data/lib/generators/abilities/install_generator.rb +13 -0
- data/lib/generators/abilities/templates/abilities.rb +2 -0
- data/test/changes_test.rb +12 -0
- data/test/checking_test.rb +52 -0
- data/test/controller_test.rb +38 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/post.rb +3 -0
- data/test/dummy/app/models/user.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +83 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/abilities.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/secret_token.rb +1 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/migrate/20140629203344_create_users.rb +11 -0
- data/test/dummy/db/migrate/20140629203412_create_posts.rb +10 -0
- data/test/dummy/db/schema.rb +31 -0
- data/test/dummy/log/development.log +80 -0
- data/test/dummy/log/test.log +4543 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/generator_test.rb +18 -0
- data/test/test_helper.rb +24 -0
- data/test/view_test.rb +23 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8dcaf769f98c1072413ffbd18e8a14668ce4d757
|
4
|
+
data.tar.gz: b6d76bf41fc236ab00c23e12d04313047761b5d3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 833a56e60b6484581beef76c1ea9894b2dec1b6418a3b85a9d65148a9f590cbdfa9b574221c7994501778677a1dd36bdb7b221ca81ab91c776cbcb3ec410e8cc
|
7
|
+
data.tar.gz: 59edbc899675ac1cadc1d3b9edb84898302c01ba958e838410f2aeab1542fc747578b6f71835b3f1c979f0b8440ce531e10e70a97344c57a4238680baa1510d7
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 Museways
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
{<img src="https://badge.fury.io/rb/abilities.png" alt="Gem Version" />}[http://badge.fury.io/rb/abilities] {<img src="https://codeclimate.com/github/museways/abilities.png" />}[https://codeclimate.com/github/museways/abilities] {<img src="https://travis-ci.org/museways/abilities.png?branch=master" alt="Build Status" />}[https://travis-ci.org/museways/abilities]
|
2
|
+
|
3
|
+
= Abilities
|
4
|
+
|
5
|
+
Minimalistic cancan alternative for rails.
|
6
|
+
|
7
|
+
= Install
|
8
|
+
|
9
|
+
Put this line in your Gemfile:
|
10
|
+
gem 'abilities'
|
11
|
+
|
12
|
+
Then bundle:
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
= Configuration
|
16
|
+
|
17
|
+
Generate the abilities initializer:
|
18
|
+
bundle exec rails g abilities:install
|
19
|
+
|
20
|
+
Ensure there is a current_user helper available in your controllers and views:
|
21
|
+
class ApplicationController < ActionController::Base
|
22
|
+
helper :current_user
|
23
|
+
def current_user
|
24
|
+
@current_user ||= User.find_by(id: session[:user_id])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
= Usage
|
29
|
+
|
30
|
+
== Defining
|
31
|
+
|
32
|
+
All the abilities are defined in config/initializers/abilities.rb by can and cannot methods:
|
33
|
+
Abilities.define do
|
34
|
+
can :create, Post
|
35
|
+
cannot :destroy, User unless admin?
|
36
|
+
can :edit, Post do |post|
|
37
|
+
post.user == self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
== Loading
|
42
|
+
|
43
|
+
If you want to load the abilities from the database you may do something like this:
|
44
|
+
permissions.each do |permission|
|
45
|
+
can premissions.action, permissions.subject
|
46
|
+
end
|
47
|
+
|
48
|
+
== Checking
|
49
|
+
|
50
|
+
=== Controllers
|
51
|
+
|
52
|
+
With the authorize! method Abilities::AccessDenied is raised if authorization fails:
|
53
|
+
class PostsController < ApplicationController
|
54
|
+
def edit
|
55
|
+
@post = Post.find(params[:id])
|
56
|
+
authorize! :edit, @post
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
If you don't want an exception to be raised use can? and cannot? helpers:
|
61
|
+
class UsersController < ApplicationController
|
62
|
+
def edit
|
63
|
+
@post = Post.find(params[:id])
|
64
|
+
if can? :edit, @post
|
65
|
+
@post.update post_params
|
66
|
+
else
|
67
|
+
# handle access denied
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
=== Views
|
73
|
+
|
74
|
+
The helpers can? and cannot? are available:
|
75
|
+
<% if can? :create, Post %>
|
76
|
+
<%= link_to new_post_path %>
|
77
|
+
<% end %>
|
78
|
+
|
79
|
+
= Credits
|
80
|
+
|
81
|
+
This gem is maintained and funded by museways[http://museways.com].
|
82
|
+
|
83
|
+
= License
|
84
|
+
|
85
|
+
It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Abilities'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
Bundler::GemHelper.install_tasks
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
|
24
|
+
Rake::TestTask.new(:test) do |t|
|
25
|
+
t.libs << 'lib'
|
26
|
+
t.libs << 'test'
|
27
|
+
t.pattern = 'test/**/*_test.rb'
|
28
|
+
t.verbose = false
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
task default: :test
|
data/lib/abilities.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'abilities/action_controller/base'
|
2
|
+
require 'abilities/action_view/base'
|
3
|
+
require 'abilities/proxy'
|
4
|
+
require 'abilities/definitions'
|
5
|
+
require 'abilities/exceptions'
|
6
|
+
require 'abilities/concern'
|
7
|
+
require 'abilities/railtie'
|
8
|
+
|
9
|
+
module Abilities
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def define(&block)
|
13
|
+
@block = block
|
14
|
+
end
|
15
|
+
|
16
|
+
def can?(actor, action, subject)
|
17
|
+
Definitions.new(actor, &@block).can?(action, subject)
|
18
|
+
end
|
19
|
+
|
20
|
+
def cannot?(*args)
|
21
|
+
!can?(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Abilities
|
2
|
+
module ActionController
|
3
|
+
module Base
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
%w(can? cannot?).each do |name|
|
9
|
+
define_method name do |action, subject|
|
10
|
+
Abilities.send name, current_user, action, subject
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def authorize!(action, subject)
|
15
|
+
raise Abilities::AccessDenied unless can? action, subject
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Abilities
|
2
|
+
class Definitions
|
3
|
+
|
4
|
+
def initialize(actor, &block)
|
5
|
+
@actor = actor
|
6
|
+
Proxy.new(actor, self, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(actions, subjects, behavior, &block)
|
10
|
+
actions = [actions] unless actions.is_a? Array
|
11
|
+
subjects = [subjects] unless subjects.is_a? Array
|
12
|
+
subjects.each do |subject|
|
13
|
+
actions.each do |action|
|
14
|
+
(all[find_subject_class(subject)] ||= {})[action.to_s] = block_given? ? block : behavior
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def can?(action, subject)
|
20
|
+
if actions = all[find_subject_class(subject)]
|
21
|
+
if behavior = actions[action.to_s]
|
22
|
+
if behavior.is_a? Proc
|
23
|
+
@actor.instance_exec subject, &behavior
|
24
|
+
else
|
25
|
+
behavior
|
26
|
+
end
|
27
|
+
else
|
28
|
+
false
|
29
|
+
end
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def cannot?(*args)
|
36
|
+
!can?(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def all
|
42
|
+
@all ||= {}
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_subject_class(subject)
|
46
|
+
if subject.is_a? Class
|
47
|
+
subject.name
|
48
|
+
else
|
49
|
+
subject.class.name
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Abilities
|
2
|
+
class Proxy
|
3
|
+
|
4
|
+
def initialize(actor, definitions, &block)
|
5
|
+
@actor = actor
|
6
|
+
@definitions = definitions
|
7
|
+
instance_eval &block
|
8
|
+
end
|
9
|
+
|
10
|
+
def can(actions, subjects, &block)
|
11
|
+
@definitions.add actions, subjects, true, &block
|
12
|
+
end
|
13
|
+
|
14
|
+
def cannot(actions, subjects, &block)
|
15
|
+
@definitions.add actions, subjects, false, &block
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_missing(name, *args, &block)
|
19
|
+
@actor.send name, *args, &block
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Abilities
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
|
4
|
+
initializer 'abilites' do
|
5
|
+
User rescue {}
|
6
|
+
if defined? User
|
7
|
+
User.send :include, Abilities::Concern
|
8
|
+
end
|
9
|
+
::ActionView::Base.send :include, Abilities::ActionView::Base
|
10
|
+
::ActionController::Base.send :include, Abilities::ActionController::Base
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Abilities
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
|
8
|
+
def create_capable_concern
|
9
|
+
copy_file 'abilities.rb', 'config/initializers/abilities.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CheckingTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "can definition with model" do
|
6
|
+
assert user.can?(:create, Post)
|
7
|
+
assert !user.cannot?(:create, Post)
|
8
|
+
end
|
9
|
+
|
10
|
+
test "can definition with instance" do
|
11
|
+
assert user.can?(:create, post)
|
12
|
+
assert !user.cannot?(:create, post)
|
13
|
+
end
|
14
|
+
|
15
|
+
test "cannot definition" do
|
16
|
+
assert user.cannot?('read', post)
|
17
|
+
assert !user.can?('read', post)
|
18
|
+
end
|
19
|
+
|
20
|
+
test "ability conditions" do
|
21
|
+
assert admin_user.can?(:destroy, post)
|
22
|
+
assert user.cannot?(:destroy, post)
|
23
|
+
end
|
24
|
+
|
25
|
+
test "ability block" do
|
26
|
+
assert user.can?(:update, post_with_user)
|
27
|
+
end
|
28
|
+
|
29
|
+
test "undefined definition" do
|
30
|
+
assert user.cannot?(:other, post)
|
31
|
+
assert user.cannot?(:other, post)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def post_with_user
|
37
|
+
@post_with_user ||= Post.new(user: user)
|
38
|
+
end
|
39
|
+
|
40
|
+
def post
|
41
|
+
@post ||= Post.new
|
42
|
+
end
|
43
|
+
|
44
|
+
def user
|
45
|
+
@user ||= User.new
|
46
|
+
end
|
47
|
+
|
48
|
+
def admin_user
|
49
|
+
@admin_user ||= User.new(admin: true)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ControllerTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "can helper" do
|
6
|
+
assert controller.send(:can?, :create, post)
|
7
|
+
end
|
8
|
+
|
9
|
+
test "cannot helper" do
|
10
|
+
assert controller.send(:cannot?, :read, post)
|
11
|
+
end
|
12
|
+
|
13
|
+
test "authorize helper" do
|
14
|
+
assert_nothing_raised do
|
15
|
+
controller.send :authorize!, :create, post
|
16
|
+
end
|
17
|
+
assert_raises Abilities::AccessDenied do
|
18
|
+
controller.send :authorize!, :read, post
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def controller
|
25
|
+
@controller ||= ActionController::Base.new.tap do |controller|
|
26
|
+
controller.class_eval do
|
27
|
+
define_method :current_user do
|
28
|
+
@user ||= User.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def post
|
35
|
+
@post ||= Post.new
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|