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 ADDED
@@ -0,0 +1 @@
1
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-18mode # JRuby in 1.9 mode
7
+ - rbx-18mode
8
+ - jruby-19mode # JRuby in 1.9 mode
9
+ - rbx-19mode
10
+ script: bundle exec rake
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
@@ -15,5 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Allowance::VERSION
17
17
 
18
+ gem.add_development_dependency 'rake'
18
19
  gem.add_development_dependency 'rspec'
20
+ gem.add_development_dependency 'watchr'
19
21
  end
@@ -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?(*args)
10
- if ![Symbol, Class].include?(args.last.class)
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
- if (p = find_permission(*args)).present?
16
- thing ? scoped_model(*args).find(:first, conditions: { id: thing.id }).present? : true
17
- else
18
- false
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
- def can(*args)
23
- options = args.pop if args.last.is_a?(Hash) || args.last.is_a?(Proc)
24
- object = args.pop unless args.last.is_a?(Symbol)
21
+ false
22
+ end
25
23
 
26
- expand_permissions(args).each do |verb|
27
- permissions[permission_identifier(verb, object)] ||= options || true
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(*args)
32
- model = args.last # TODO: check that model is a class
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
- (p.arity == 0 ? model.instance_exec(&p) : model.call(r))
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
@@ -1,3 +1,3 @@
1
1
  module Allowance
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,4 +1,87 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Allowance::Permissions do
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
@@ -3,3 +3,11 @@ lib_path = File.expand_path("#{SPEC_DIR}/../lib")
3
3
  $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
4
4
 
5
5
  require 'allowance'
6
+
7
+ def insist(what)
8
+ what.should == true
9
+ end
10
+
11
+ def refuse(what)
12
+ what.should == false
13
+ end
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.1
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: &70332184433920 !ruby/object:Gem::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: *70332184433920
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