allowance 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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