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 +4 -4
- data/lib/strong_attributes.rb +0 -1
- data/lib/strong_attributes/displayable.rb +12 -22
- data/lib/strong_attributes/permissible.rb +5 -5
- data/lib/strong_attributes/permissions.rb +39 -11
- data/lib/strong_attributes/version.rb +1 -1
- data/spec/strong_attributes/permissions_spec.rb +1 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c16f8c67c4ade076c784776b24f742121a9849d4
|
4
|
+
data.tar.gz: 08273a443123e27eec2ff657ab62f23379e10511
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8e313f21c846d34479baae0b5cf2b7635c5d8a4da653a6d73909c24b470377b75eea58a33cf5cf9341a5ba930b40a971492f19ab5575a6a765c0594a6c6ab02
|
7
|
+
data.tar.gz: 5e1f356c3ef40603cb0f53c1898ad61e385f97ab3052d07529e8b510cc7e606a5881ea25de674fa39f11859f11c8e7c8631ebd7d9a1d6b3094a7ec85ac6a47c0
|
data/lib/strong_attributes.rb
CHANGED
@@ -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.
|
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.
|
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.
|
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.
|
30
|
-
#
|
31
|
-
def
|
32
|
-
select_permitted(*attributes).map do |
|
33
|
-
|
34
|
-
value
|
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
|
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
|
53
|
-
|
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
|
41
|
-
# @param [
|
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
|
44
|
-
def link_permissions
|
45
|
-
@permitted_attributes = StrongAttributes::Permissions.new(
|
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
|
106
|
-
|
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
|
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
|
@@ -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, :*]
|
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.
|
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-
|
11
|
+
date: 2013-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|