allowy 0.5.0 → 1.0.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: 6226c1034c094d096ce0d675ece0e96742691b35
4
- data.tar.gz: 7996daebd96790d93fdf834e5a31a6fd94757600
3
+ metadata.gz: 6e70d04247b27e11e8d0d39d0ce3ae32c2c873ad
4
+ data.tar.gz: d8d7186771b7dd8ce1176ce9fe082b9bf6fd205f
5
5
  SHA512:
6
- metadata.gz: c3afa5620c56fee9b6d539542ea6a2e37019fe30f19e0dafe2fa04ede0b2dabfc994b5c8cb3782dc33f996db10ffe2aa77db7c3258e4dd73399f4cbfb8ebe417
7
- data.tar.gz: d9237a944aba5343928381310eff16abd08369f8085067fa78fc037b0196ec6e497cfafebe5eddfdebdce50b93eefda92db7395a1e1be772f8420345386d6a3c
6
+ metadata.gz: 8c0870403d5852d0d0dbff52004ffec7fb88da6378fdefd81c60c73cfd366c104ebe964ecc1191f079712e99e054f21712cac19f5c5e270586d637028675ebf3
7
+ data.tar.gz: 9e571abf64019ca7aa3bcf5d1cb4bf344b142c1db220ca5de0522dd10d5e8bafbc2772ed369d4e8e1d94a3fbf460f9cfc99fe189cfaf2b5505fb032f7396660d
data/README.md CHANGED
@@ -130,6 +130,38 @@ end
130
130
 
131
131
  ```
132
132
 
133
+ # Early termination
134
+
135
+ If you have a pre-condition for any permission checks you can abort more complex logic by
136
+ calling `deny!('my reason to deny')`.
137
+
138
+ For example:
139
+
140
+ ```ruby
141
+ class PageAccess < DefaultAccess
142
+ def view?(page)
143
+ deny!(:no_user) unless current_user
144
+ page and page.published? and domain_name =~ /^www\./i
145
+ end
146
+ end
147
+ ```
148
+
149
+ This is very similar to:
150
+
151
+ ```ruby
152
+ class PageAccess < DefaultAccess
153
+ def view?(page)
154
+ return false unless current_user
155
+ page and page.published? and domain_name =~ /^www\./i
156
+ end
157
+ end
158
+ ```
159
+
160
+ Except that additional information on the exception will be available when calling `authorize!`.
161
+
162
+ This information is available from the ` Allowy::AccessDenied#payload`.
163
+
164
+
133
165
  ## More comprehensive example
134
166
 
135
167
  You probably have multiple classes that you want to protect.
@@ -190,7 +222,8 @@ class PagesController < ApplicationController
190
222
  # Add this to the ApplicationController to handle it globally
191
223
  rescue_from Allowy::AccessDenied do |exception|
192
224
  logger.debug "Access denied on #{exception.action} #{exception.subject.inspect}"
193
- redirect_to new_user_session_url, :alert => exception.message
225
+ redirect_to new_user_session_url if no_access.payload == :no_user
226
+ render('shared/no_permission', message: exception.message)
194
227
  end
195
228
  end
196
229
  ```
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext'
1
2
  require 'active_support/concern'
2
3
  require 'active_support/inflector'
3
4
 
@@ -12,12 +13,13 @@ module Allowy
12
13
  class UndefinedAction < StandardError; end
13
14
 
14
15
  class AccessDenied < StandardError
15
- attr_reader :action, :subject
16
+ attr_reader :action, :subject, :payload
16
17
 
17
- def initialize(message, action, subject)
18
+ def initialize(message, action, subject, payload=nil)
18
19
  @message = message
19
20
  @action = action
20
21
  @subject = subject
22
+ @payload = payload
21
23
  end
22
24
  end
23
25
  end
@@ -47,18 +47,32 @@ module Allowy
47
47
  @context = ctx
48
48
  end
49
49
 
50
- def can?(action, *args)
51
- m = "#{action}?"
52
- raise UndefinedAction.new("The #{self.class.name} needs to have #{m} method. Please define it.") unless self.respond_to? m
53
- send(m, *args)
50
+ def can?(action, subject, *params)
51
+ allowing, _ = check_permission(action, subject, *params)
52
+ allowing
54
53
  end
55
54
 
56
55
  def cannot?(*args)
57
56
  not can?(*args)
58
57
  end
59
58
 
60
- def authorize!(*args)
61
- raise AccessDenied.new("Not authorized", args.first, args[1]) unless can?(*args)
59
+ def authorize!(action, subject, *params)
60
+ allowing, payload = check_permission(action, subject, *params)
61
+ raise AccessDenied.new("Not authorized", action, subject, payload) if not allowing
62
+ end
63
+
64
+ def deny!(payload)
65
+ throw(:deny, payload)
66
+ end
67
+
68
+ private
69
+
70
+ def check_permission(action, subject, *params)
71
+ m = "#{action}?"
72
+ raise UndefinedAction.new("The #{self.class.name} needs to have #{m} method. Please define it.") unless self.respond_to? m
73
+ allowing = false
74
+ payload = catch(:deny) { allowing = send(m, subject, *params) }
75
+ [allowing, payload]
62
76
  end
63
77
  end
64
78
 
@@ -1,3 +1,3 @@
1
1
  module Allowy
2
- VERSION = "0.5.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -15,12 +15,12 @@ module Allowy
15
15
  end
16
16
  end
17
17
 
18
- it "should allow" do
19
- subject.should be_able_to :read, 'allow'
20
- end
18
+ it { should be_able_to :read, 'allow' }
19
+ it { should_not be_able_to :read, 'deny' }
21
20
 
22
- it "should deny" do
23
- subject.should_not be_able_to :read, 'deny'
21
+ it "should deny with early termination" do
22
+ access.should_not be_able_to :early_deny, 'foo'
23
+ access.can?(:early_deny, 'xx').should == false
24
24
  end
25
25
 
26
26
  it "should raise if no permission defined" do
@@ -42,6 +42,16 @@ module Allowy
42
42
  it "should not raise error" do
43
43
  expect { subject.authorize! :read, 'allow' }.not_to raise_error
44
44
  end
45
+
46
+ it "should raise early termination error with payload" do
47
+ expect { subject.authorize! :early_deny, 'subject' }.to raise_error AccessDenied do |err|
48
+ err.message.should_not be_blank
49
+ err.action.should == :early_deny
50
+ err.subject.should == 'subject'
51
+ err.payload.should == 'early terminate: subject'
52
+ end
53
+ end
54
+
45
55
  end
46
56
 
47
57
  end
@@ -14,6 +14,10 @@ class SampleAccess
14
14
  str == 'allow'
15
15
  end
16
16
 
17
+ def early_deny?(str)
18
+ deny! "early terminate: #{str}"
19
+ end
20
+
17
21
  def context_is_123?(*whatever)
18
22
  context === 123
19
23
  end
metadata CHANGED
@@ -1,97 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: allowy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmytrii Nagirniak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-26 00:00:00.000000000 Z
11
+ date: 2014-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: guard-rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  description: Allowy provides CanCan-like way of checking permission but doesn't enforce
@@ -102,8 +102,8 @@ executables: []
102
102
  extensions: []
103
103
  extra_rdoc_files: []
104
104
  files:
105
- - .gitignore
106
- - .rspec
105
+ - ".gitignore"
106
+ - ".rspec"
107
107
  - Gemfile
108
108
  - Guardfile
109
109
  - README.md
@@ -131,17 +131,17 @@ require_paths:
131
131
  - lib
132
132
  required_ruby_version: !ruby/object:Gem::Requirement
133
133
  requirements:
134
- - - '>='
134
+ - - ">="
135
135
  - !ruby/object:Gem::Version
136
136
  version: '0'
137
137
  required_rubygems_version: !ruby/object:Gem::Requirement
138
138
  requirements:
139
- - - '>='
139
+ - - ">="
140
140
  - !ruby/object:Gem::Version
141
141
  version: '0'
142
142
  requirements: []
143
143
  rubyforge_project: allowy
144
- rubygems_version: 2.0.3
144
+ rubygems_version: 2.2.2
145
145
  signing_key:
146
146
  specification_version: 4
147
147
  summary: Authorization with simplicity and explicitness in mind