access_schema 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -5,8 +5,6 @@ to define ACL schemas with realy simple DSL.
5
5
 
6
6
  Inspired by [ya_acl](https://github.com/kaize/ya_acl)
7
7
 
8
- With a couple of aliases in DSL it enables you to deal with tariff plans. Plan and role, feature and privilege are synonyms.
9
-
10
8
  ```
11
9
  gem install access_schema
12
10
  ```
@@ -24,9 +22,9 @@ add some default options in helpers:
24
22
 
25
23
  class AccessSchemaHelper
26
24
 
27
- def plan
25
+ def role
28
26
  AccessSchema.schema(:plans).with_options({
29
- :plan => Rails.development? && params[:debug_plan] || current_user.try(:plan) || :none
27
+ :role => Rails.development? && params[:debug_role] || current_user.try(:role) || :none
30
28
  })
31
29
  end
32
30
 
@@ -45,14 +43,14 @@ So at may be used in controllers:
45
43
 
46
44
  ```ruby
47
45
  acl.require! review, :edit
48
- plan.require! review, :mark_featured
46
+ role.require! review, :mark_privileged
49
47
 
50
48
  ```
51
49
 
52
50
  Or views:
53
51
 
54
52
  ```ruby
55
- - if plan.allow? review, :add_photo
53
+ - if role.allow? review, :add_photo
56
54
  = render :partial => "add_photo"
57
55
  ```
58
56
 
@@ -66,17 +64,17 @@ example. So we have to pass extra options:
66
64
 
67
65
  class ReviewService < BaseSevice
68
66
 
69
- def mark_featured(review_id, options)
67
+ def mark_privileged(review_id, options)
70
68
 
71
69
  review = Review.find(review_id)
72
70
 
73
- acl = AccessSchema.schema(:acl).with_options(:role => options[:actor].roles)
74
- acl.require! review, :mark_featured
71
+ acl = AccessSchema.schema(:acl).with_options(:roles => options[:actor].roles)
72
+ acl.require! review, :mark_privileged
75
73
 
76
- plans = AccessSchema.schema(:plans).with_options(:plan => options[:actor].plan)
77
- plans.require! review, :mark_featured
74
+ plans = AccessSchema.schema(:plans).with_options(:plans => options[:actor].plans)
75
+ plans.require! review, :mark_privileged
78
76
 
79
- review.featured = true
77
+ review.privileged = true
80
78
  review.save!
81
79
 
82
80
  end
@@ -85,10 +83,10 @@ example. So we have to pass extra options:
85
83
 
86
84
  review = Review.find(review_id)
87
85
 
88
- acl = AccessSchema.schema(:acl).with_options(:role => options[:actor].roles)
86
+ acl = AccessSchema.schema(:acl).with_options(:roles => options[:actor].roles)
89
87
  acl.require! review, :edit
90
88
 
91
- plans = AccessSchema.schema(:plans).with_options(:plan => options[:actor].plan)
89
+ plans = AccessSchema.schema(:plan).with_options(:plan => options[:actor].plan)
92
90
  plans.require! review, :edit, :new_attrs => attrs
93
91
 
94
92
  review.update_attributes(attrs)
@@ -102,13 +100,13 @@ example. So we have to pass extra options:
102
100
  ### Definition
103
101
 
104
102
  ```ruby
105
- # config/plans.rb
103
+ # config/roles.rb
106
104
 
107
- plans do
108
- plan :none
109
- plan :bulb
110
- plan :flower
111
- plan :bouquet
105
+ roles do
106
+ role :none
107
+ role :bulb
108
+ role :flower
109
+ role :bouquet
112
110
  end
113
111
 
114
112
  asserts do
@@ -123,22 +121,17 @@ example. So we have to pass extra options:
123
121
 
124
122
  end
125
123
 
126
- namespace "Review" do
124
+ resource "Review" do
127
125
 
128
- feature :mark_featured, [:flower, :bouquet]
126
+ privilege :mark_privileged, [:flower, :bouquet]
129
127
 
130
- feature :add_photo, [:bouquet] do
128
+ privilege :add_photo, [:bouquet] do
131
129
  assert :photo_limit, [:none], :limit => 1
132
130
  assert :photo_limit, [:bulb], :limit => 5
133
131
  assert :photo_limit, [:flower], :limit => 10
134
132
  end
135
133
 
136
- # Important fields from plans aspect:
137
- # greeting
138
- # logo
139
- # site_url
140
- #
141
- feature :edit, [:bouquet] do
134
+ privilege :edit, [:bouquet] do
142
135
  assert :attrs, [:bulb], :disallow => [:greeting, :logo, :site_url]
143
136
  assert :attrs, [:flower], :disallow => [:site_url]
144
137
  end
@@ -161,7 +154,7 @@ example. So we have to pass extra options:
161
154
 
162
155
  end
163
156
 
164
- namespace "Review" do
157
+ resource "Review" do
165
158
 
166
159
  privilege :edit, [:admin] do
167
160
  assert :owner, [:none]
data/lib/access_schema.rb CHANGED
@@ -4,8 +4,8 @@ require 'access_schema/exceptions'
4
4
  require 'access_schema/config'
5
5
  require 'access_schema/schema'
6
6
  require 'access_schema/assert'
7
- require 'access_schema/namespace'
8
- require 'access_schema/element'
7
+ require 'access_schema/resource'
8
+ require 'access_schema/privilege'
9
9
  require 'access_schema/expectation'
10
10
 
11
11
  require 'access_schema/loggers/proxy_logger'
@@ -16,8 +16,8 @@ require 'access_schema/builders/config_builder'
16
16
  require 'access_schema/builders/basic_builder'
17
17
  require 'access_schema/builders/roles_builder'
18
18
  require 'access_schema/builders/asserts_builder'
19
- require 'access_schema/builders/namespace_builder'
20
- require 'access_schema/builders/element_builder'
19
+ require 'access_schema/builders/resource_builder'
20
+ require 'access_schema/builders/privilege_builder'
21
21
  require 'access_schema/builders/schema_builder'
22
22
 
23
23
  require 'access_schema/proxy'
@@ -1,5 +1,5 @@
1
1
  module AccessSchema
2
- class ElementBuilder < BasicBuilder
2
+ class PrivilegeBuilder < BasicBuilder
3
3
 
4
4
  def assert(name, roles = [], options = {})
5
5
  expectation = Expectation.new(name.to_sym, roles.map(&:to_sym), options)
@@ -0,0 +1,14 @@
1
+ module AccessSchema
2
+ class ResourceBuilder < BasicBuilder
3
+
4
+ def privilege(name, roles = [], &block)
5
+ privilege = Privilege.new(name.to_sym, roles.map(&:to_sym))
6
+ if block_given?
7
+ builder = PrivilegeBuilder.new(privilege)
8
+ builder.instance_eval(&block)
9
+ end
10
+ schema.add_privilege(privilege)
11
+ end
12
+
13
+ end
14
+ end
@@ -5,7 +5,5 @@ module AccessSchema
5
5
  schema.add_role(role.to_sym)
6
6
  end
7
7
 
8
- alias :plan :role
9
-
10
8
  end
11
9
  end
@@ -18,21 +18,17 @@ module AccessSchema
18
18
  builder.instance_eval(&block)
19
19
  end
20
20
 
21
- alias :plans :roles
22
-
23
21
  def asserts(&block)
24
22
  builder = AssertsBuilder.new(schema)
25
23
  builder.instance_eval(&block)
26
24
  end
27
25
 
28
- def namespace(name, &block)
29
- namespace = Namespace.new(name.to_sym)
30
- builder = NamespaceBuilder.new(namespace)
26
+ def resource(name, &block)
27
+ resource = Resource.new(name.to_sym)
28
+ builder = ResourceBuilder.new(resource)
31
29
  builder.instance_eval(&block)
32
- schema.add_namespace(namespace)
30
+ schema.add_resource(resource)
33
31
  end
34
32
 
35
- alias :resource :namespace
36
-
37
33
  end
38
34
  end
@@ -1,5 +1,5 @@
1
1
  module AccessSchema
2
- class Element
2
+ class Privilege
3
3
  attr_reader :name
4
4
 
5
5
  def initialize(name, roles, &block)
@@ -29,8 +29,8 @@ module AccessSchema
29
29
  private
30
30
 
31
31
  def normalize_args(args)
32
- namespace = args[0]
33
- feature = args[1]
32
+ resource = args[0]
33
+ privilege = args[1]
34
34
 
35
35
  roles, options = case args[2]
36
36
  when Hash, nil
@@ -43,7 +43,7 @@ module AccessSchema
43
43
  options_to_pass.delete :plan
44
44
  options_to_pass.delete :role
45
45
 
46
- [namespace, feature, roles, options_to_pass.merge(options)]
46
+ [resource, privilege, roles, options_to_pass.merge(options)]
47
47
  end
48
48
 
49
49
  end
@@ -0,0 +1,23 @@
1
+ module AccessSchema
2
+ class Resource
3
+ attr_reader :name
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ @privileges = {}
8
+ end
9
+
10
+ def privileges
11
+ @privileges.values
12
+ end
13
+
14
+ def add_privilege(privilege)
15
+ @privileges[privilege.name] = privilege
16
+ end
17
+
18
+ def get_privilege(name)
19
+ @privileges[name]
20
+ end
21
+
22
+ end
23
+ end
@@ -7,7 +7,7 @@ module AccessSchema
7
7
  def initialize
8
8
  @roles = []
9
9
  @asserts = {}
10
- @namespaces = {}
10
+ @resources = {}
11
11
  end
12
12
 
13
13
  def add_role(role)
@@ -18,8 +18,8 @@ module AccessSchema
18
18
  @asserts[assert.name] = assert
19
19
  end
20
20
 
21
- def add_namespace(namespace)
22
- @namespaces[namespace.name] = namespace
21
+ def add_resource(resource)
22
+ @resources[resource.name] = resource
23
23
  end
24
24
 
25
25
  def allow?(*args)
@@ -46,43 +46,61 @@ module AccessSchema
46
46
 
47
47
  raise NoRoleError.new if (self.roles & roles).empty?
48
48
 
49
+ roles = normalize_roles_order(roles)
49
50
 
50
51
  case args[0]
51
52
  when String, Symbol
52
- namespace = args[0].to_sym
53
- [namespace, privilege, roles, options]
53
+ resource = args[0].to_sym
54
+ [resource, privilege, roles, options]
54
55
  else
55
- namespace = args[0].class.name.to_sym
56
- [namespace, privilege, roles, options.merge(:subject => args[0])]
56
+ resource = args[0].class.name.to_sym
57
+ [resource, privilege, roles, options.merge(:subject => args[0])]
57
58
  end
58
59
 
59
60
  end
60
61
 
61
- def check!(namespace_name, element_name, roles, options)
62
+ def normalize_roles_order(roles)
63
+ @roles.select do |role|
64
+ roles.include? role
65
+ end
66
+ end
67
+
68
+ def check!(resource_name, privilege_name, roles, options)
69
+
70
+ resouce_name = resource_name.to_sym
71
+ privilege_name = privilege_name.to_sym
72
+
73
+ resource = @resources[resource_name]
74
+
75
+ if resource.nil?
76
+ raise NoResourceError.new(:resource => resource_name)
77
+ end
78
+
79
+ privilege = resource.get_privilege(privilege_name)
80
+
81
+ if privilege.nil?
82
+ raise NoPrivilegeError.new(:resource => resource_name, :privilege => privilege_name)
83
+ end
62
84
 
63
- existent_element = false
64
- failed_asserts = []
85
+ failed_asserts = Hash.new{|h, k| h[k] = []}
65
86
 
66
- allowed = for_element(namespace_name, element_name) do |element|
67
- existent_element = true
68
- element.allow?(roles) do |expectation|
69
- check_assert(expectation, options).tap do |result|
70
- failed_asserts << expectation unless result
87
+ roles_checks = roles.map do |role|
88
+ privilege.allow?([role]) do |expectation|
89
+ @asserts[expectation.name].check?(expectation.options.merge(options)).tap do |result|
90
+ failed_asserts[role] << expectation.name unless result
71
91
  end
72
92
  end
73
93
  end
74
94
 
75
- raise NoPrivilegeError.new(:privilege => element_name.to_sym) unless existent_element
76
-
77
95
  log_payload = {
78
- :resource => namespace_name,
79
- :privilege => element_name,
96
+ :resource => resource_name,
97
+ :privilege => privilege_name,
80
98
  :roles => roles,
81
99
  :options => options
82
100
  }
83
101
 
84
- unless allowed
85
- log_payload[:failed_asserts] = failed_asserts.map(&:name)
102
+ unless roles_checks.any?
103
+ log_payload[:failed_asserts] = failed_asserts
86
104
  logger.info{ "check FAILED: #{log_payload.inspect}" }
87
105
  raise NotAllowedError.new(log_payload)
88
106
  else
@@ -92,30 +110,6 @@ module AccessSchema
92
110
 
93
111
  end
94
112
 
95
- def check_assert(expectation, options)
96
- @asserts[expectation.name].check?(expectation.options.merge(options))
97
- end
98
-
99
- def for_element(namespace, element)
100
- ns = namespace.to_sym
101
- en = element.to_sym
102
-
103
- elements_for(ns).any? do |element|
104
- if element.name == en
105
- yield(element)
106
- end
107
- end
108
-
109
- end
110
-
111
- def elements_for(namespace)
112
- if @namespaces.has_key?(namespace)
113
- @namespaces[namespace].elements
114
- else
115
- raise NoResourceError.new(:resource => namespace)
116
- end
117
- end
118
-
119
113
  private
120
114
 
121
115
  def logger
@@ -1,3 +1,3 @@
1
1
  module AccessSchema
2
- VERSION = "0.3.5"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -9,7 +9,7 @@ describe AccessSchema::ConfigBuilder do
9
9
  schema :acl, :file => 'spec/schema_example.rb'
10
10
  end
11
11
 
12
- config.schema(:acl).plans.should_not be_nil
12
+ config.schema(:acl).roles.should_not be_nil
13
13
  end
14
14
 
15
15
  it "can specify logger" do
@@ -7,8 +7,8 @@ describe AccessSchema::SchemaBuilder do
7
7
 
8
8
  it "builds schema from block" do
9
9
  @schema = AccessSchema::SchemaBuilder.build do
10
- plans do
11
- plan :none
10
+ roles do
11
+ role :none
12
12
  end
13
13
  end
14
14
  @schema.should be
@@ -36,8 +36,8 @@ describe AccessSchema::SchemaBuilder, "produced schema example" do
36
36
  @schema = AccessSchema::SchemaBuilder.build_file('spec/schema_example.rb')
37
37
  end
38
38
 
39
- it "creates plans" do
40
- @schema.plans.should == [:none, :bulb, :flower, :bouquet]
39
+ it "creates roles" do
40
+ @schema.roles.should == [:none, :bulb, :flower, :bouquet, :admin, :user]
41
41
  end
42
42
 
43
43
  context "when checking against plan 'none'" do
@@ -28,7 +28,7 @@ describe AccessSchema::Schema, "errors rising" do
28
28
 
29
29
  describe "#allow?" do
30
30
 
31
- it "raises exception on invalid namespace" do
31
+ it "raises exception on invalid resource" do
32
32
  lambda {
33
33
  @schema.allow? "Invalid", :mark_featured, :none
34
34
  }.should raise_error(AccessSchema::NoResourceError)
@@ -48,6 +48,26 @@ describe AccessSchema::Schema, "errors rising" do
48
48
 
49
49
  end
50
50
 
51
+ describe "privilege union for multiple roles" do
52
+
53
+ context "when checking privilege :update for Review in example schema" do
54
+
55
+ it "passes for admin" do
56
+ @schema.should be_allow("Review", :update, [:admin])
57
+ end
58
+
59
+ it "fails for user" do
60
+ @schema.should_not be_allow("Review", :update, [:user])
61
+ end
62
+
63
+ it "passes for admin and user" do
64
+ @schema.should be_allow("Review", :update, [:admin, :user])
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
51
71
  describe "#require!" do
52
72
 
53
73
  it "raises en error is feature is nt allowed"
@@ -70,7 +90,7 @@ describe AccessSchema::Schema, "errors rising" do
70
90
  it "logs check fail with info level" do
71
91
  @logger.log_only_level = "info"
72
92
  @schema.allow? "Review", :mark_featured, :none
73
- @logger.output.should == "AccessSchema: check FAILED: {:resource=>:Review, :privilege=>:mark_featured, :roles=>[:none], :options=>{}, :failed_asserts=>[]}"
93
+ @logger.output.should == "AccessSchema: check FAILED: {:resource=>:Review, :privilege=>:mark_featured, :roles=>[:none], :options=>{}, :failed_asserts=>{}}"
74
94
  end
75
95
  end
76
96
 
@@ -1,9 +1,12 @@
1
1
 
2
- plans do
3
- plan :none
4
- plan :bulb
5
- plan :flower
6
- plan :bouquet
2
+ roles do
3
+ role :none
4
+ role :bulb
5
+ role :flower
6
+ role :bouquet
7
+
8
+ role :admin
9
+ role :user
7
10
  end
8
11
 
9
12
  asserts do
@@ -12,16 +15,24 @@ asserts do
12
15
  subject.photos_count < limit
13
16
  end
14
17
 
18
+ assert :false do
19
+ false
20
+ end
21
+
15
22
  end
16
23
 
17
- namespace "Review" do
24
+ resource "Review" do
18
25
 
19
- feature :mark_featured, [:flower, :bouquet]
26
+ privilege :mark_featured, [:flower, :bouquet]
20
27
 
21
- feature :add_photo, [:bouquet] do
28
+ privilege :add_photo, [:bouquet] do
22
29
  assert :photo_limit, [:none], :limit => 1
23
30
  assert :photo_limit, [:bulb], :limit => 5
24
31
  assert :photo_limit, [:flower], :limit => 10
25
32
  end
26
33
 
34
+ privilege :update, [:admin] do
35
+ assert :false, [:user]
36
+ end
37
+
27
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: access_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-23 00:00:00.000000000 Z
12
+ date: 2012-03-26 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: AccessSchema is a tool for ACL or tariff plans schema definition and
15
15
  checks
@@ -32,19 +32,19 @@ files:
32
32
  - lib/access_schema/builders/asserts_builder.rb
33
33
  - lib/access_schema/builders/basic_builder.rb
34
34
  - lib/access_schema/builders/config_builder.rb
35
- - lib/access_schema/builders/element_builder.rb
36
- - lib/access_schema/builders/namespace_builder.rb
35
+ - lib/access_schema/builders/privilege_builder.rb
36
+ - lib/access_schema/builders/resource_builder.rb
37
37
  - lib/access_schema/builders/roles_builder.rb
38
38
  - lib/access_schema/builders/schema_builder.rb
39
39
  - lib/access_schema/config.rb
40
- - lib/access_schema/element.rb
41
40
  - lib/access_schema/exceptions.rb
42
41
  - lib/access_schema/expectation.rb
43
42
  - lib/access_schema/loggers/proxy_logger.rb
44
43
  - lib/access_schema/loggers/stub_logger.rb
45
44
  - lib/access_schema/loggers/test_logger.rb
46
- - lib/access_schema/namespace.rb
45
+ - lib/access_schema/privilege.rb
47
46
  - lib/access_schema/proxy.rb
47
+ - lib/access_schema/resource.rb
48
48
  - lib/access_schema/schema.rb
49
49
  - lib/access_schema/version.rb
50
50
  - spec/access_schema/config_builder_spec.rb
@@ -69,7 +69,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
69
  version: '0'
70
70
  segments:
71
71
  - 0
72
- hash: -1329279297250315893
72
+ hash: -3729396007705609250
73
73
  required_rubygems_version: !ruby/object:Gem::Requirement
74
74
  none: false
75
75
  requirements:
@@ -78,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
78
  version: '0'
79
79
  segments:
80
80
  - 0
81
- hash: -1329279297250315893
81
+ hash: -3729396007705609250
82
82
  requirements: []
83
83
  rubyforge_project: access_schema
84
84
  rubygems_version: 1.8.16
@@ -1,16 +0,0 @@
1
- module AccessSchema
2
- class NamespaceBuilder < BasicBuilder
3
-
4
- def privilege(name, roles = [], &block)
5
- element = Element.new(name.to_sym, roles.map(&:to_sym))
6
- if block_given?
7
- builder = ElementBuilder.new(element)
8
- builder.instance_eval(&block)
9
- end
10
- schema.add_element(element)
11
- end
12
-
13
- alias :feature :privilege
14
-
15
- end
16
- end
@@ -1,16 +0,0 @@
1
- module AccessSchema
2
- class Namespace
3
- attr_reader :name
4
- attr_reader :elements
5
-
6
- def initialize(name)
7
- @name = name
8
- @elements = []
9
- end
10
-
11
- def add_element(element)
12
- @elements << element
13
- end
14
-
15
- end
16
- end