strong_attributes 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.
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