access-granted 0.0.2 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 990382c04aeeeb43c67adcd3adc1fc0e4ac6b7ac
4
- data.tar.gz: d9970ae5c29e073953f41ec55c3f19b8a0d18225
3
+ metadata.gz: e569e46f4095287086e980979eb59cb48bb8d671
4
+ data.tar.gz: 12579f6c1242101c5dfdab73bda111170fd719be
5
5
  SHA512:
6
- metadata.gz: 6ddcadc2b5e812ae350e91479047c344d705e6cb7f3011f35e695aab0ca545402a550c1e9f8c45661e64cce0228b0f44334c384615721eb2eca38938d0ea501e
7
- data.tar.gz: 9060e6c5d8243a43f33dfe9a4b6274a68edd748d1e32930939c5c7097db0679be03f21a168ae98f031806696da654a4806c3844f866ac2aadc4ccde6f5102b51
6
+ metadata.gz: b3bdef4853790d402a621cc1eae254d4fed2dc12a2273c704379bb84d7dce6f4a03d6c7b071a6b1a74d27bdf319cc98b0372490b164dd8ef3eaaa7edc2af3fe8
7
+ data.tar.gz: 4baac040d13e99a97aae7c3e160a3dc6e506350195b148e6c2737c8ee5b51c141b45e6e6f1e4b791a07e077abdf7552cfda87eab22c1a9c2b162fd14f7e6a2c2
@@ -2,3 +2,9 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1.0
6
+ - rbx-2.1.1
7
+ - rbx-2.2.3
8
+ - rbx
9
+ - jruby-1.7.6
10
+ - jruby
data/Gemfile CHANGED
@@ -3,7 +3,13 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in access-granted.gemspec
4
4
  gemspec
5
5
 
6
- group :test do
6
+ group :test, :development do
7
+ gem 'rb-readline'
7
8
  gem 'simplecov', require: false
8
9
  gem 'rake'
10
+ gem 'pry'
11
+ end
12
+
13
+ platforms :rbx do
14
+ gem 'rubysl', '~> 2.0'
9
15
  end
data/README.md CHANGED
@@ -2,14 +2,18 @@
2
2
 
3
3
  Multi-role and whitelist based authorization gem for Rails. And it's lightweight (~300 lines of code)!
4
4
 
5
+ ### Supported Ruby versions
6
+
7
+ Guaranteed to work on MRI 1.9.3/2.0/2.1, Rubinius >= 2.1.1 and JRuby >= 1.7.6.
8
+
5
9
  # Summary
6
10
 
7
11
  AccessGranted is meant as replacement for CanCan to solve three major problems:
8
12
 
9
13
  1. built-in support for roles
10
14
 
11
- Easy to read acess policy code where permissions are cleanly grouped into roles which may or may not apply to a user.
12
- Additionally permissions are forced to be unique in the scope a role greatly simplifying the
15
+ Easy to read access policy code where permissions are cleanly grouped into roles which may or may not apply to a user.
16
+ Additionally permissions are forced to be unique in the scope a role. Thus greatly simplifying the
13
17
  permission resolving and extremely reducing the code-base.
14
18
 
15
19
  2. white-list based
@@ -17,23 +21,34 @@ AccessGranted is meant as replacement for CanCan to solve three major problems:
17
21
  This means that you define what a role **can** do,
18
22
  not overidding permissions with `cannot` in a specific order which results in an ugly and unmaintainable code.
19
23
 
24
+ **Note**: `cannot` is still possible, but has a specifc use. See [Usage](#usage) below.
25
+
20
26
  3. Permissions can work on basically any object and AccessGranted is framework-agnostic,
21
- (the only Rails-specific methods are `can?`/`cannot?`/`authorize!` helpers injected
27
+ (the Rails-specific methods are `can?`/`cannot?`/`authorize!` helpers injected
22
28
  into the framework only when it's present).
23
29
 
24
30
  See [Usage](#usage) for an example of a complete AccessPolicy file.
25
31
 
26
- ## Compatibility
32
+ ## Compatibility with CanCan
27
33
 
28
34
  This gem was created as a replacement for CanCan and therefore it requires minimum work to switch.
29
35
 
30
- 1. Both `can?`/`cannot?` and `authorize!` methods work in Rails controllers and views, so
31
- **you don't have to adjust your views at all**.
32
- 2. Syntax for defining permissions in AccessPolicy file (Ability in CanCan) is exactly the same,
36
+ ### Main differences
37
+
38
+ 1. AccessGranted does not extend ActiveRecord in any way, so it does not have the `accessible_by?`
39
+ method which could be used for querying objects available to current user.
40
+ This was very complex and only worked with permissions defined using hash conditions, so
41
+ I decided to not implement this functionality as it was mostly ignored by CanCan users.
42
+
43
+ 2. Both `can?`/`cannot?` and `authorize!` methods work in Rails controllers and views, just like in CanCan.
44
+ The only change you have to make is replace all `can? :manage, Class` with precise action.
45
+ `can :manage` is stil available for **defining** methods and serves as a shortcut for defining `:read`, `:create`, `:update`, `:destroy`
46
+ in one line.
47
+
48
+ Due to introduction of Roles checking for generic `:manage` permission is very complicated and also confusing for developers.
49
+
50
+ 3. Syntax for defining permissions in AccessPolicy file (Ability in CanCan) is exactly the same,
33
51
  with added roles on top. See [Usage](#usage) below.
34
- 3. **Main difference**: AccessGranted does not extend ActiveRecord in any way, so it does not have the `accessible_by?`
35
- method to keep the code as simple as possible.
36
- That is because `accessible_by?` was very limited making it useless in most cases (complex permissions with lambdas).
37
52
 
38
53
 
39
54
  ## Installation
@@ -70,12 +85,12 @@ class Policy
70
85
  cannot [:create, :update, :destroy], Post
71
86
 
72
87
  # same as above, :manage is just a shortcut for
73
- # `[:create, :update, :destroy]`
88
+ # `[:read, :create, :update, :destroy]`
74
89
  cannot :manage, Comment
75
90
  end
76
91
 
77
92
  # Takes precedences over roles placed lower
78
- # and explicitly lets admin mamange everything.
93
+ # and explicitly lets admin manage everything.
79
94
  role :admin, { is_admin: true } do
80
95
  can :manage, Post
81
96
  can :manage, Comment
@@ -84,7 +99,8 @@ class Policy
84
99
  # You can also use Procs to determine
85
100
  # if the role should apply to a given user.
86
101
  role :moderator, proc {|u| u.moderator? } do
87
- # overwrites permission that only allows removing own content in :member
102
+ # takes precedence over :update/:destroy
103
+ # permissions defined in member role below
88
104
  # and lets moderators edit and delete all posts
89
105
  can [:update, :destroy], Post
90
106
 
@@ -93,8 +109,8 @@ class Policy
93
109
  can :update, User
94
110
  end
95
111
 
96
- # Applies to everyone logged in.
97
112
  # The basic role.
113
+ # Applies to everyone logged in.
98
114
  role :member do
99
115
  can :create, Post
100
116
 
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = AccessGranted::VERSION
9
9
  spec.authors = ["Piotrek Okoński"]
10
10
  spec.email = ["piotrek@okonski.org"]
11
- spec.description = %q{Whitelist and role based authorization gem}
11
+ spec.description = %q{Role based authorization gem}
12
12
  spec.summary = %q{Elegant whitelist and role based authorization with ability to prioritize roles.}
13
13
  spec.homepage = "https://github.com/pokonski/access-granted"
14
14
  spec.license = "MIT"
@@ -19,8 +19,5 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
23
22
  spec.add_development_dependency "rspec"
24
- spec.add_development_dependency "pry"
25
- spec.add_development_dependency "text-table"
26
23
  end
@@ -5,7 +5,7 @@ module AccessGranted
5
5
  end
6
6
 
7
7
  def self.included(base)
8
- base.helper_method :can?, :cannot?, :current_ability
8
+ base.helper_method :can?, :cannot?, :current_policy
9
9
  end
10
10
 
11
11
  def can?(*args)
@@ -35,9 +35,9 @@ module AccessGranted
35
35
 
36
36
  def eql?(other)
37
37
  other.class == self.class &&
38
- @action == other.action &&
39
- @subject == other.subject &&
40
- @granted == other.granted
38
+ @action == other.action &&
39
+ @subject == other.subject &&
40
+ @granted == other.granted
41
41
  end
42
42
 
43
43
  def ==(other)
@@ -28,11 +28,6 @@ module AccessGranted
28
28
  add_permission(false, action, subject, conditions, block)
29
29
  end
30
30
 
31
- def can?(action, subject)
32
- permission = find_permission(action, subject)
33
- permission ? permission.granted : false
34
- end
35
-
36
31
  def find_permission(action, subject)
37
32
  relevant_permissions(action, subject).detect do |permission|
38
33
  permission.matches_conditions?(subject)
@@ -42,7 +37,7 @@ module AccessGranted
42
37
  def applies_to?(user)
43
38
  case @conditions
44
39
  when Hash
45
- matches_hash(user, @conditions)
40
+ matches_hash?(user, @conditions)
46
41
  when Proc
47
42
  @conditions.call(user)
48
43
  else
@@ -57,7 +52,7 @@ module AccessGranted
57
52
  end
58
53
  end
59
54
 
60
- def matches_hash(user, conditions = {})
55
+ def matches_hash?(user, conditions = {})
61
56
  conditions.all? do |name, value|
62
57
  user.send(name) == value
63
58
  end
@@ -76,7 +71,7 @@ module AccessGranted
76
71
 
77
72
  def prepare_actions(action)
78
73
  if action == :manage
79
- actions = [:create, :update, :destroy]
74
+ actions = [:read, :create, :update, :destroy]
80
75
  else
81
76
  actions = [action].flatten
82
77
  end
@@ -1,3 +1,3 @@
1
1
  module AccessGranted
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -5,7 +5,7 @@ describe AccessGranted::ControllerMethods do
5
5
  @current_user = double("User")
6
6
  @controller_class = Class.new
7
7
  @controller = @controller_class.new
8
- @controller_class.stub(:helper_method).with(:can?, :cannot?, :current_ability)
8
+ @controller_class.stub(:helper_method).with(:can?, :cannot?, :current_policy)
9
9
  @controller_class.send(:include, AccessGranted::ControllerMethods)
10
10
  @controller.stub(:current_user).and_return(@current_user)
11
11
  end
@@ -9,10 +9,10 @@ describe AccessGranted::Policy do
9
9
 
10
10
  describe "#configure" do
11
11
  before :each do
12
- @member = double("member", is_moderator: false, is_admin: false, is_banned: false)
13
- @mod = double("moderator", is_moderator: true, is_admin: false, is_banned: false)
14
- @admin = double("administrator", is_moderator: false, is_admin: true, is_banned: false)
15
- @banned = double("banned", is_moderator: false, is_admin: true, is_banned: true)
12
+ @member = double("member", id: 1, is_moderator: false, is_admin: false, is_banned: false)
13
+ @mod = double("moderator", id: 2, is_moderator: true, is_admin: false, is_banned: false)
14
+ @admin = double("administrator", id: 3, is_moderator: false, is_admin: true, is_banned: false)
15
+ @banned = double("banned", id: 4, is_moderator: false, is_admin: true, is_banned: true)
16
16
  end
17
17
 
18
18
  it "selects permission based on role priority" do
@@ -20,27 +20,55 @@ describe AccessGranted::Policy do
20
20
  include AccessGranted::Policy
21
21
 
22
22
  def configure(user)
23
- role :member do
24
- can :read, String
23
+ role :administrator, { is_admin: true } do
24
+ can :destroy, String
25
25
  end
26
26
 
27
27
  role :moderator, { is_moderator: true } do
28
- can :edit, String
28
+ can :update, String
29
29
  end
30
30
 
31
- role :administrator, { is_admin: true } do
32
- can :destroy, String
31
+ role :member do
32
+ can :read, String
33
33
  end
34
34
  end
35
35
  end
36
- klass.new(@member).cannot?(:destroy, String).should be_true
37
36
  klass.new(@admin).can?(:destroy, String).should be_true
38
37
  klass.new(@admin).can?(:read, String).should be_true
38
+
39
+ klass.new(@member).cannot?(:destroy, String).should be_true
40
+ klass.new(@member).can?(:read, String).should be_true
41
+
42
+ klass.new(@mod).can?(:read, String).should be_true
39
43
  klass.new(@mod).cannot?(:destroy, String).should be_true
40
44
  end
41
45
 
46
+ context "when multiple roles define the same permission" do
47
+ it "checks all roles until conditions are met" do
48
+ user_post = FakePost.new(@member.id)
49
+ other_post = FakePost.new(66)
50
+
51
+ klass = Class.new do
52
+ include AccessGranted::Policy
53
+
54
+ def configure(user)
55
+ role :administrator, { is_admin: true } do
56
+ can :destroy, FakePost
57
+ end
58
+
59
+ role :member do
60
+ can :destroy, FakePost, user_id: user.id
61
+ end
62
+ end
63
+ end
64
+
65
+ klass.new(@admin).can?(:destroy, user_post).should be_true
66
+ klass.new(@member).can?(:destroy, user_post).should be_true
67
+ klass.new(@member).cannot?(:destroy, other_post).should be_true
68
+ end
69
+ end
42
70
  describe "#cannot" do
43
- it "forbids action when used in higher role" do
71
+ it "forbids action when used in superior role" do
44
72
  klass = Class.new do
45
73
  include AccessGranted::Policy
46
74
 
@@ -54,8 +82,8 @@ describe AccessGranted::Policy do
54
82
  end
55
83
  end
56
84
  end
57
- klass.new(@member).can?(:create, String).should be_true
58
- klass.new(@banned).can?(:create, String).should be_false
85
+ klass.new(@member).can?(:create, String).should be_true
86
+ klass.new(@banned).cannot?(:create, String).should be_true
59
87
  end
60
88
  end
61
89
  end
@@ -86,7 +114,7 @@ describe AccessGranted::Policy do
86
114
  can :read, String
87
115
  end
88
116
 
89
- role.can?(:read, String).should be_true
117
+ role.find_permission(:read, String).granted.should be_true
90
118
  end
91
119
  end
92
120
 
@@ -62,7 +62,7 @@ describe AccessGranted::Role do
62
62
 
63
63
  it "accepts :manage shortcut for CRUD actions" do
64
64
  @role.can :manage, String
65
- @role.permissions.map(&:action).should include(:create, :update, :destroy)
65
+ @role.permissions.map(&:action).should include(:read, :create, :update, :destroy)
66
66
  end
67
67
 
68
68
  describe "when action is an Array" do
@@ -75,12 +75,12 @@ describe AccessGranted::Role do
75
75
  describe "when no conditions given" do
76
76
  it "should be able to read a class" do
77
77
  @role.can :read, String
78
- @role.can?(:read, String).should be_true
78
+ @role.find_permission(:read, String).should be_true
79
79
  end
80
80
 
81
81
  it "should be able to read instance of class" do
82
82
  @role.can :read, String
83
- @role.can?(:read, "text").should be_true
83
+ @role.find_permission(:read, "text").should be_true
84
84
  end
85
85
  end
86
86
 
@@ -88,7 +88,7 @@ describe AccessGranted::Role do
88
88
  it "should be able to read when conditions match" do
89
89
  sub = double("Element", published: true)
90
90
  @role.can :read, sub.class, { published: true }
91
- @role.can?(:read, sub).should be_true
91
+ @role.find_permission(:read, sub).should be_true
92
92
  end
93
93
  end
94
94
  end
@@ -1,7 +1,9 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
- require 'simplecov'
4
- SimpleCov.start
3
+ if ENV["COV"]
4
+ require 'simplecov'
5
+ SimpleCov.start
6
+ end
5
7
  require 'pry'
6
8
 
7
9
  RSpec.configure do |config|
@@ -20,6 +22,9 @@ module ActionController
20
22
  end
21
23
  require 'access-granted'
22
24
 
25
+ class FakePost < Struct.new(:user_id)
26
+ end
27
+
23
28
  class Policy
24
29
  include AccessGranted::Policy
25
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: access-granted
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotrek Okoński
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-17 00:00:00.000000000 Z
11
+ date: 2014-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rspec
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,35 +38,7 @@ dependencies:
52
38
  - - '>='
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: pry
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - '>='
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: text-table
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - '>='
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - '>='
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- description: Whitelist and role based authorization gem
41
+ description: Role based authorization gem
84
42
  email:
85
43
  - piotrek@okonski.org
86
44
  executables: []
@@ -127,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
85
  version: '0'
128
86
  requirements: []
129
87
  rubyforge_project:
130
- rubygems_version: 2.0.3
88
+ rubygems_version: 2.1.11
131
89
  signing_key:
132
90
  specification_version: 4
133
91
  summary: Elegant whitelist and role based authorization with ability to prioritize