strong_attributes 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: da121740cc4a0a6f17cb4f4c60d330c830a7b4de
4
- data.tar.gz: 81639530a105615c335f1bda7bb9bc3d8640b0d3
3
+ metadata.gz: c16f8c67c4ade076c784776b24f742121a9849d4
4
+ data.tar.gz: 08273a443123e27eec2ff657ab62f23379e10511
5
5
  SHA512:
6
- metadata.gz: c4f2d82dede1d5bbbb52bdf4e217eeac317b1840a17c1e2ed78965a23356a1b8a82b0bbe8b7f9f9b67764cdd91d8d84383c9294ba924ee405770765edf5782b1
7
- data.tar.gz: d18af71fbf9a1e071cc16ad255b790ff3e774cd16faa2c485a5b850d0a4e6e26aa1fad49d9cea7387e0144ed269d89bb3bab6b79f0a85696b130f3b4afbc68da
6
+ metadata.gz: a8e313f21c846d34479baae0b5cf2b7635c5d8a4da653a6d73909c24b470377b75eea58a33cf5cf9341a5ba930b40a971492f19ab5575a6a765c0594a6c6ab02
7
+ data.tar.gz: 5e1f356c3ef40603cb0f53c1898ad61e385f97ab3052d07529e8b510cc7e606a5881ea25de674fa39f11859f11c8e7c8631ebd7d9a1d6b3094a7ec85ac6a47c0
@@ -1,5 +1,4 @@
1
1
  require 'active_support/concern'
2
- #require 'active_support/core_ext/hash/keys'
3
2
 
4
3
  require "strong_attributes/version"
5
4
  require "strong_attributes/permissions"
@@ -8,49 +8,39 @@ module StrongAttributes
8
8
  # Calls and returns the result of each method call in the argument list. If a block is given, then each result
9
9
  # is passed to the block.
10
10
  #
11
- # user.displays :username, :email # returns [user.username, user.email]
11
+ # user.presents :username, :email # returns [user.username, user.email]
12
12
  #
13
13
  # Or with two arguments, the name of the field is passed first:
14
14
  #
15
15
  # <ul>
16
- # <% user.displays :username, :email, :address do |field, value| %>
16
+ # <% user.presents :username, :email, :address do |field, value| %>
17
17
  # <li><%= field.capitalize %>: <% value %></li>
18
18
  # <% end %>
19
19
  # </ul>
20
20
  #
21
21
  # If only the presented value is desired, use `each`:
22
22
  #
23
- # <% user.displays(:username, :email).each do |value| %>
23
+ # <% user.presents(:username, :email).each do |value| %>
24
24
  # <td><%= value %></td>
25
25
  # <% end %>
26
26
  #
27
27
  # Arguments can be included in an array:
28
28
  #
29
- # user.displays :username, [:notifications, :unread] # returns [user.username, user.notifications(:unread)]
30
- #
31
- def displays *attributes
32
- select_permitted(*attributes).map do |attribute|
33
- args = Array(attribute).dup
34
- value = self
35
- until args.empty? do
36
- arity = value.method(args[0]).arity
37
- if arity >= 0
38
- value = value.public_send *args.slice!(0, arity+1)
39
- else
40
- value = value.public_send *args
41
- break
42
- end
43
- end
44
- yield attribute, value if block_given?
29
+ # user.presents :username, [:notifications, :unread] # returns [user.username, user.notifications(:unread)]
30
+ #
31
+ def presents *attributes
32
+ select_permitted(*attributes).map do |attribute_path|
33
+ value = Array(attribute_path).inject(self) { |obj, args| obj.public_send *args }
34
+ yield attribute_path, value if block_given?
45
35
  value
46
36
  end
47
37
  end
48
38
 
49
- # Same as displays, but for a single attribute. The differences are:
39
+ # Same as presents, but for a single attribute. The differences are:
50
40
  # - the return value is not in an Array
51
41
  # - passes the value only (without attribute key as the 1st argument) to a block
52
- def display field
53
- displays field do |key, value|
42
+ def present field
43
+ presents field do |key, value|
54
44
  yield value if block_given?
55
45
  end.first
56
46
  end
@@ -37,12 +37,12 @@ module StrongAttributes
37
37
  @permitted_attributes ||= StrongAttributes::Permissions.new
38
38
  end
39
39
 
40
- # Links presenter to permissions group of given presenter.
41
- # @param [Presenter] parent_presenter
40
+ # Links permissions to that of the parent.
41
+ # @param [Permissible] parent
42
42
  # @param [Array<Symbol>] relative_path
43
- # The prefix prepended before every permission check relative to parent presenter.
44
- def link_permissions parent_presenter, relative_path = []
45
- @permitted_attributes = StrongAttributes::Permissions.new(parent_presenter.permitted_attributes, relative_path)
43
+ # The prefix prepended before every permission check relative to parent.
44
+ def link_permissions parent, relative_path = []
45
+ @permitted_attributes = StrongAttributes::Permissions.new(parent.permitted_attributes, relative_path)
46
46
  end
47
47
 
48
48
  end
@@ -19,6 +19,7 @@ module StrongAttributes
19
19
  def initialize(permissions = nil, prefix_path = [])
20
20
  unless permissions.nil?
21
21
  @permitted_paths = permissions.permitted_paths
22
+ @permittable_paths = permissions.permittable_paths
22
23
  @prefix_path = permissions.prefix_path + canonicalize(prefix_path) # copy on write
23
24
  end
24
25
  end
@@ -49,6 +50,11 @@ module StrongAttributes
49
50
  !path_tainted?(attribute_path) and permitted_by_wildcard?(prefix_path + attribute_path) # wildcard match only if not tainted
50
51
  end
51
52
 
53
+ def permittable? attribute_path
54
+ attribute_path = canonicalize(attribute_path)
55
+ permittable_paths.include?(prefix_path + attribute_path)
56
+ end
57
+
52
58
  # Selects the attribute paths which are permitted.
53
59
  # @param [Array] prefix_path
54
60
  # namespace in which each of the given attribute paths are in
@@ -81,17 +87,37 @@ module StrongAttributes
81
87
  attribute_paths = attribute_paths.map{|path|canonicalize(path).taint} # exact match
82
88
  reject_permitted(*attribute_paths).each do |attribute_path| # don't permit if already permitted
83
89
  permitted_paths << attribute_path # prefix_path = [] because of copy on write
90
+ raw_permittable(attribute_path.slice(0...-1))
84
91
  end
85
92
  self
86
93
  end
87
94
 
95
+ def permittable *attribute_paths
96
+ copy_on_write!
97
+ attribute_paths.each { |attribute_path| raw_permittable(canonicalize(attribute_path)) }
98
+ self
99
+ end
100
+
88
101
  protected
89
102
 
90
103
  def permitted_paths
91
104
  @permitted_paths ||= Set.new
92
105
  end
93
106
 
107
+ # some subpaths may be permitted
108
+ def permittable_paths
109
+ @permittable_paths ||= Set.new
110
+ end
111
+
94
112
  private
113
+ # will mutate attribute_path
114
+ def raw_permittable attribute_path
115
+ until attribute_path.empty? || permittable_paths.include?(attribute_path) do
116
+ permittable_paths << attribute_path.dup
117
+ attribute_path.pop
118
+ end
119
+ end
120
+
95
121
  # Is this still referencing another objects permissions?
96
122
  def reference?
97
123
  !@prefix_path.nil?
@@ -101,15 +127,22 @@ module StrongAttributes
101
127
  def copy_on_write!
102
128
  if prefix_path == []
103
129
  @permitted_paths = permitted_paths.dup
130
+ @permittable_paths = permittable_paths.dup
104
131
  elsif reference?
105
- @permitted_paths, old_set = Set.new, permitted_paths
106
- old_set.each do |path|
107
- @permitted_paths << path[prefix_path.size...path.size] if path[0...prefix_path.size] == prefix_path
108
- end
132
+ @permitted_paths = dup_paths permitted_paths, prefix_path
133
+ @permittable_paths = dup_paths permittable_paths, prefix_path
109
134
  end
110
135
  @prefix_path = nil
111
136
  end
112
137
 
138
+ def dup_paths old_set, prefix_path
139
+ new_set = Set.new
140
+ old_set.each do |path|
141
+ new_set << path[prefix_path.size...path.size] if path[0...prefix_path.size] == prefix_path
142
+ end
143
+ new_set
144
+ end
145
+
113
146
  def path_tainted? attribute_path
114
147
  attribute_path.tainted? or attribute_path.any? { |element| element.tainted? }
115
148
  end
@@ -120,19 +153,14 @@ module StrongAttributes
120
153
  path[-1] = :*
121
154
  return true if permitted_paths.include? path
122
155
  end
123
- until path.empty?
124
- path[-1] = :**
125
- return true if permitted_paths.include? path
126
- path.pop
127
- end
128
156
  false
129
157
  end
130
158
 
131
159
  # Converts symbols to strings (except for wildcard symbol)
132
160
  def canonicalize array
133
161
  array = Array(array)
134
- canonical_array = array.map{|e|e.is_a?(Symbol) ? e.to_s : e}
135
- canonical_array[-1] = array.last if [:*, :**].include? array.last
162
+ canonical_array = array.map{|e| (e.is_a?(Array) ? e.first : e).instance_eval{ self.is_a?(Symbol) ? e.to_s : e } }
163
+ canonical_array[-1] = array.last if array.last == :*
136
164
  canonical_array.taint if array.tainted?
137
165
  canonical_array
138
166
  end
@@ -1,3 +1,3 @@
1
1
  module StrongAttributes
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -47,18 +47,13 @@ module StrongAttributes
47
47
  describe "#permitted?" do
48
48
  context 'with some attributes permitted' do
49
49
  before(:all) do
50
- @permissions = Permissions.new.permit([:another, :array], [:attr, :array], :attr2, :attr3, [:a, :wildcard, :*], [:wild, :**])
50
+ @permissions = Permissions.new.permit([:another, :array], [:attr, :array], :attr2, :attr3, [:a, :wildcard, :*])
51
51
  end
52
52
 
53
53
  it 'permits single wildcard' do
54
54
  expect(@permissions.permitted?([:a, :wildcard, :irrelevant])).to be true
55
55
  end
56
56
 
57
- it 'permits full wildcard' do
58
- expect(@permissions.permitted?([:wild, :wildcard, :irrelevant])).to be true
59
- expect(@permissions.permitted?([:wild, :irrelevant])).to be true
60
- end
61
-
62
57
  it 'does not permit un-prefixed path' do
63
58
  permissions = Permissions.new(@permissions, :attr)
64
59
  expect(permissions.permitted?(:attr2)).to be false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strong_attributes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ronald Chan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-30 00:00:00.000000000 Z
11
+ date: 2013-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport