allowance 0.0.1 → 0.0.2
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.
- data/.rspec +1 -0
- data/.travis.yml +10 -0
- data/.watchr +15 -0
- data/allowance.gemspec +2 -0
- data/lib/allowance/permissions.rb +20 -39
- data/lib/allowance/version.rb +1 -1
- data/spec/permissions_spec.rb +84 -1
- data/spec/spec_helper.rb +8 -0
- metadata +28 -3
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/.watchr
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
def run(cmd, msg = nil)
|
2
|
+
puts "=== %s" % msg if msg
|
3
|
+
puts "=== %s" % cmd
|
4
|
+
system cmd
|
5
|
+
puts "\n"
|
6
|
+
end
|
7
|
+
|
8
|
+
watch("spec/.*_spec\.rb") { |m| run("bundle exec rspec %s" % m[0]) }
|
9
|
+
watch("lib/allowance/(.*)\.rb") { |m| run("bundle exec rspec spec/%s_spec.rb" % m[1]) }
|
10
|
+
watch('^spec/(spec_helper|factories)\.rb') { |f| run "bundle exec rake spec", "%s.rb has been modified" % f }
|
11
|
+
|
12
|
+
# Ctrl-\
|
13
|
+
Signal.trap('QUIT') { run("bundle exec rake spec") }
|
14
|
+
# Ctrl-C
|
15
|
+
Signal.trap('INT') { abort("\nQuitting.") }
|
data/allowance.gemspec
CHANGED
@@ -1,41 +1,40 @@
|
|
1
1
|
module Allowance
|
2
2
|
class Permissions
|
3
|
-
def initialize(context, &blk)
|
3
|
+
def initialize(context = nil, &blk)
|
4
4
|
@permissions = {}
|
5
5
|
@context = context
|
6
6
|
instance_exec(context, &blk)
|
7
7
|
end
|
8
8
|
|
9
|
-
def can?(
|
10
|
-
if
|
11
|
-
thing = args.pop
|
12
|
-
args.push(thing.class)
|
13
|
-
end
|
9
|
+
def can?(verb, object = nil)
|
10
|
+
return true if @permissions[[verb, object]]
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
# If object is a resource instance, try its class
|
13
|
+
if object.class.respond_to?(:find)
|
14
|
+
if can?(verb, object.class)
|
15
|
+
# See if the object is part of the defined scope
|
16
|
+
return !scoped_model(verb, object.class).
|
17
|
+
find(:first, :conditions => { :id => object.id }).nil?
|
18
|
+
end
|
19
19
|
end
|
20
|
-
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
object = args.pop unless args.last.is_a?(Symbol)
|
21
|
+
false
|
22
|
+
end
|
25
23
|
|
26
|
-
|
27
|
-
|
24
|
+
def can(verbs, objects = nil, scope = true, &blk)
|
25
|
+
expand_permissions(verbs).each do |verb|
|
26
|
+
[objects].flatten.each do |object|
|
27
|
+
@permissions[[verb, object]] = scope # TODO: add blk, too
|
28
|
+
end
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
31
|
-
def scoped_model(
|
32
|
-
|
33
|
-
|
34
|
-
if p = find_permission(*args)
|
32
|
+
def scoped_model(verb, model)
|
33
|
+
if p = @permissions[[verb, model]]
|
35
34
|
if p.is_a?(Hash)
|
36
35
|
model.where(p)
|
37
36
|
elsif p.is_a?(Proc)
|
38
|
-
|
37
|
+
model.instance_exec(&p)
|
39
38
|
else
|
40
39
|
model
|
41
40
|
end
|
@@ -44,17 +43,6 @@ module Allowance
|
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
47
|
-
def find_permission(*args)
|
48
|
-
object = args.pop unless args.last.is_a?(Symbol)
|
49
|
-
|
50
|
-
args.flatten.each do |verb|
|
51
|
-
if p = permissions[permission_identifier(verb, object)]
|
52
|
-
return p
|
53
|
-
end
|
54
|
-
end
|
55
|
-
nil
|
56
|
-
end
|
57
|
-
|
58
46
|
private
|
59
47
|
|
60
48
|
def expand_permissions(*permissions)
|
@@ -66,12 +54,5 @@ module Allowance
|
|
66
54
|
end
|
67
55
|
end.flatten
|
68
56
|
end
|
69
|
-
|
70
|
-
def permission_identifier(verb, object)
|
71
|
-
raise "Can't use enumerables as verbs" if verb.is_a?(Enumerable)
|
72
|
-
[verb.to_sym, object].compact
|
73
|
-
end
|
74
|
-
|
75
|
-
attr_reader :permissions
|
76
57
|
end
|
77
58
|
end
|
data/lib/allowance/version.rb
CHANGED
data/spec/permissions_spec.rb
CHANGED
@@ -1,4 +1,87 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
module Allowance
|
4
|
+
describe Permissions do
|
5
|
+
SomeClass = Class.new
|
6
|
+
SomeOtherClass = Class.new
|
7
|
+
|
8
|
+
it "should allow simple permissions to be specified" do
|
9
|
+
p = Permissions.new do
|
10
|
+
can :moo
|
11
|
+
end
|
12
|
+
|
13
|
+
insist p.can?(:moo)
|
14
|
+
refuse p.can?(:quack)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should allow verbs and objects" do
|
18
|
+
p = Permissions.new do
|
19
|
+
can :update, SomeClass
|
20
|
+
end
|
21
|
+
|
22
|
+
insist p.can?(:update, SomeClass)
|
23
|
+
refuse p.can?(:destroy, SomeClass)
|
24
|
+
refuse p.can?(:update, SomeOtherClass)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should run the permission definition block against the provided context" do
|
28
|
+
skills = mock(:singing => :good)
|
29
|
+
|
30
|
+
p = Permissions.new(skills) do |skills|
|
31
|
+
can :sing if skills.singing == :good
|
32
|
+
end
|
33
|
+
|
34
|
+
insist p.can? :sing
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should expand :view to include :index and :show" do
|
38
|
+
p = Permissions.new do
|
39
|
+
can :view, SomeClass
|
40
|
+
end
|
41
|
+
|
42
|
+
insist p.can?(:view, SomeClass)
|
43
|
+
insist p.can?(:index, SomeClass)
|
44
|
+
insist p.can?(:show, SomeClass)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should verify permissions against model instances" do
|
48
|
+
model_class = Class.new
|
49
|
+
model_class.should_receive(:some_scope).and_return(model_class)
|
50
|
+
|
51
|
+
model_instance = model_class.new
|
52
|
+
model_instance.stub!(:id => 123)
|
53
|
+
|
54
|
+
model_class.should_receive(:find).and_return(model_instance)
|
55
|
+
|
56
|
+
p = Permissions.new do
|
57
|
+
can :view, model_class, lambda { some_scope }
|
58
|
+
end
|
59
|
+
|
60
|
+
insist p.can?(:view, model_instance)
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#scoped_model" do
|
64
|
+
it "should allow scopes to be defined through lambdas" do
|
65
|
+
model = mock
|
66
|
+
model.should_receive(:some_scope).and_return(scoped_model = mock)
|
67
|
+
|
68
|
+
p = Permissions.new do
|
69
|
+
can :view, model, lambda { some_scope }
|
70
|
+
end
|
71
|
+
|
72
|
+
p.scoped_model(:view, model).should == scoped_model
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should allow scopes to be defined through where conditions" do
|
76
|
+
model = mock
|
77
|
+
model.should_receive(:where).with(:awesome => true).and_return(scoped_model = mock)
|
78
|
+
|
79
|
+
p = Permissions.new do
|
80
|
+
can :view, model, :awesome => true
|
81
|
+
end
|
82
|
+
|
83
|
+
p.scoped_model(:view, model).should == scoped_model
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
4
87
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: allowance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,9 +11,31 @@ bindir: bin
|
|
11
11
|
cert_chain: []
|
12
12
|
date: 2012-05-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &70146150823900 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70146150823900
|
14
25
|
- !ruby/object:Gem::Dependency
|
15
26
|
name: rspec
|
16
|
-
requirement: &
|
27
|
+
requirement: &70146150819460 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70146150819460
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: watchr
|
38
|
+
requirement: &70146150838720 !ruby/object:Gem::Requirement
|
17
39
|
none: false
|
18
40
|
requirements:
|
19
41
|
- - ! '>='
|
@@ -21,7 +43,7 @@ dependencies:
|
|
21
43
|
version: '0'
|
22
44
|
type: :development
|
23
45
|
prerelease: false
|
24
|
-
version_requirements: *
|
46
|
+
version_requirements: *70146150838720
|
25
47
|
description: A generic, but decidedly awesome authorization control layer.
|
26
48
|
email:
|
27
49
|
- hendrik@mans.de
|
@@ -30,6 +52,9 @@ extensions: []
|
|
30
52
|
extra_rdoc_files: []
|
31
53
|
files:
|
32
54
|
- .gitignore
|
55
|
+
- .rspec
|
56
|
+
- .travis.yml
|
57
|
+
- .watchr
|
33
58
|
- Gemfile
|
34
59
|
- LICENSE
|
35
60
|
- README.md
|