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 +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
|