apiphobic-authorization 1.1.0 → 1.2.0
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
- checksums.yaml.gz.sig +0 -0
- data/lib/apiphobic/authorization/authorizer.rb +9 -9
- data/lib/apiphobic/authorization/authorizers/parameters.rb +96 -64
- data/lib/apiphobic/authorization/{authorizable_resource.rb → resource.rb} +17 -9
- data/lib/apiphobic/authorization/version.rb +1 -1
- data/lib/apiphobic/rails/api_controller_compatibility.rb +22 -0
- data/lib/apiphobic/rails/controller.rb +19 -0
- data/lib/apiphobic-authorization.rb +4 -0
- data.tar.gz.sig +0 -0
- metadata +27 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae49ad16d7ccee68ad832094f557149dffe1b98c82975f31aba512b9f2cec00c
|
4
|
+
data.tar.gz: 6ee28b1abc416e418e27db5d722f8f5d24fc255245f639cc0fc4925c539ff01b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 387c64f4a04f2028fd6ed326b5e855902388054589d7d56db872dad926d8d3506b2eba771704ba6563d3749978a9fd625420b3753aaa36ab5a9e020f00bfd2c5
|
7
|
+
data.tar.gz: 2a60f92f107dbfcdc7d2bdb7008b2df9d0bf1fc63acea278116f923979e041a4ebea5ee41ecce6f6da5372f3322a5d559f6e15890471c56da75b541d6479d611
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -4,18 +4,18 @@ module Apiphobic
|
|
4
4
|
module Authorization
|
5
5
|
class Authorizer
|
6
6
|
attr_accessor :action,
|
7
|
+
:parameters,
|
8
|
+
:resource,
|
7
9
|
:token,
|
8
|
-
:user
|
9
|
-
:params,
|
10
|
-
:resource
|
10
|
+
:user
|
11
11
|
|
12
12
|
# rubocop:disable Metrics/ParameterLists
|
13
|
-
def initialize(action:, token:, user:, issuer:,
|
14
|
-
self.action
|
15
|
-
self.token
|
16
|
-
self.user
|
17
|
-
self.
|
18
|
-
self.resource
|
13
|
+
def initialize(action:, token:, user:, issuer:, parameters:, resource:, **other)
|
14
|
+
self.action = action
|
15
|
+
self.token = token
|
16
|
+
self.user = user
|
17
|
+
self.parameters = parameters
|
18
|
+
self.resource = resource
|
19
19
|
|
20
20
|
other.each do |name, value|
|
21
21
|
public_send("#{name}=", value)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'apple_core/refinements/deep_dup'
|
3
4
|
require 'apiphobic/errors/unpermitted_inclusions'
|
4
5
|
require 'apiphobic/errors/unpermitted_sorts'
|
5
6
|
|
@@ -8,12 +9,12 @@ module Apiphobic
|
|
8
9
|
module Authorization
|
9
10
|
module Authorizers
|
10
11
|
class Parameters
|
11
|
-
|
12
|
+
using ::AppleCore::Refinements::DeepDup
|
12
13
|
|
13
14
|
attr_accessor :action,
|
15
|
+
:parameters,
|
14
16
|
:token,
|
15
|
-
:user
|
16
|
-
:raw_parameters
|
17
|
+
:user
|
17
18
|
|
18
19
|
attr_writer :authorized_attributes,
|
19
20
|
:authorized_filters,
|
@@ -24,10 +25,10 @@ class Parameters
|
|
24
25
|
|
25
26
|
# rubocop:disable Metrics/ParameterLists
|
26
27
|
def initialize(action:, token:, user:, issuer:, parameters:, **other)
|
27
|
-
self.action
|
28
|
-
self.
|
29
|
-
self.
|
30
|
-
self.
|
28
|
+
self.action = action
|
29
|
+
self.parameters = parameters.deep_dup
|
30
|
+
self.token = token
|
31
|
+
self.user = user
|
31
32
|
|
32
33
|
other.each do |name, value|
|
33
34
|
public_send("#{name}=", value)
|
@@ -35,6 +36,38 @@ class Parameters
|
|
35
36
|
end
|
36
37
|
# rubocop:enable Metrics/ParameterLists
|
37
38
|
|
39
|
+
def authorized_parameters
|
40
|
+
@authorized_parameters || [
|
41
|
+
:include,
|
42
|
+
:sort,
|
43
|
+
{
|
44
|
+
name: :data,
|
45
|
+
authorization_value: [
|
46
|
+
:type,
|
47
|
+
:id,
|
48
|
+
{
|
49
|
+
attributes: nil,
|
50
|
+
relationships: nil,
|
51
|
+
},
|
52
|
+
],
|
53
|
+
},
|
54
|
+
{
|
55
|
+
name: :filter,
|
56
|
+
authorization_value: [{}],
|
57
|
+
},
|
58
|
+
{
|
59
|
+
name: :page,
|
60
|
+
authorization_value: %i{
|
61
|
+
number
|
62
|
+
size
|
63
|
+
offset
|
64
|
+
limit
|
65
|
+
cursor
|
66
|
+
},
|
67
|
+
},
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
38
71
|
def authorized_attributes
|
39
72
|
@authorized_attributes || []
|
40
73
|
end
|
@@ -59,7 +92,21 @@ class Parameters
|
|
59
92
|
@ignored_attributes || []
|
60
93
|
end
|
61
94
|
|
95
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
62
96
|
def call
|
97
|
+
sliced_parameters = authorized_parameters.map { |v| v.is_a?(::Hash) ? v[:name] : v }
|
98
|
+
|
99
|
+
parameters.slice!(*sliced_parameters)
|
100
|
+
|
101
|
+
authorized_parameters.each do |parameter|
|
102
|
+
parameter = { name: parameter } unless parameter.is_a?(::Hash)
|
103
|
+
|
104
|
+
authorize_parameter(value: parameters[parameter],
|
105
|
+
authorization_parameters: authorization,
|
106
|
+
raw_parameters: parameters,
|
107
|
+
**parameter)
|
108
|
+
end
|
109
|
+
|
63
110
|
authorized_attributes.each do |attribute|
|
64
111
|
attribute = { name: attribute } unless attribute.is_a?(::Hash)
|
65
112
|
|
@@ -87,46 +134,32 @@ class Parameters
|
|
87
134
|
authorize_inclusions(names: authorized_inclusions)
|
88
135
|
authorize_sorts(names: authorized_sorts)
|
89
136
|
|
90
|
-
|
137
|
+
parameters.permit(*authorization)
|
91
138
|
end
|
139
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
92
140
|
|
93
141
|
private
|
94
142
|
|
95
|
-
def
|
96
|
-
@
|
97
|
-
{
|
98
|
-
data: [
|
99
|
-
:type,
|
100
|
-
:id,
|
101
|
-
{
|
102
|
-
attributes: nil,
|
103
|
-
relationships: nil,
|
104
|
-
},
|
105
|
-
],
|
106
|
-
filter: nil,
|
107
|
-
page: %i{
|
108
|
-
number
|
109
|
-
size
|
110
|
-
offset
|
111
|
-
limit
|
112
|
-
cursor
|
113
|
-
},
|
114
|
-
},
|
115
|
-
]
|
143
|
+
def authorization
|
144
|
+
@authorization ||= [{}]
|
116
145
|
end
|
117
146
|
|
118
147
|
def authorize_attribute(**args)
|
119
|
-
authorize_parameter(
|
120
|
-
|
121
|
-
|
122
|
-
|
148
|
+
authorize_parameter(
|
149
|
+
value: raw_parameter_attribute_value(args[:name]),
|
150
|
+
authorization_parameters: authorized_parameter_attributes,
|
151
|
+
raw_parameters: raw_parameter_attributes,
|
152
|
+
**args,
|
153
|
+
)
|
123
154
|
end
|
124
155
|
|
125
156
|
def authorize_filter(**args)
|
126
|
-
authorize_parameter(
|
127
|
-
|
128
|
-
|
129
|
-
|
157
|
+
authorize_parameter(
|
158
|
+
value: raw_parameter_filter_value(args[:name]),
|
159
|
+
authorization_parameters: authorized_parameter_filters,
|
160
|
+
raw_parameters: raw_parameter_filters,
|
161
|
+
**args,
|
162
|
+
)
|
130
163
|
end
|
131
164
|
|
132
165
|
def authorize_inclusions(names:)
|
@@ -141,8 +174,6 @@ class Parameters
|
|
141
174
|
|
142
175
|
fail Errors::UnpermittedInclusions.new(inclusions: raw_parameter_inclusions) \
|
143
176
|
unless all_requested_inclusions_authorized
|
144
|
-
|
145
|
-
authorized_parameters << :include
|
146
177
|
end
|
147
178
|
|
148
179
|
def authorize_sorts(names:)
|
@@ -158,27 +189,30 @@ class Parameters
|
|
158
189
|
|
159
190
|
fail Errors::UnpermittedSorts.new(sorts: raw_parameter_sorts) \
|
160
191
|
unless all_requested_sorts_authorized
|
161
|
-
|
162
|
-
authorized_parameters << :sort
|
163
192
|
end
|
164
193
|
|
194
|
+
# rubocop:disable Metrics/ParameterLists
|
165
195
|
def authorize_parameter(name:,
|
166
196
|
value:,
|
167
|
-
|
197
|
+
authorization_parameters:,
|
198
|
+
authorization_value: nil,
|
168
199
|
raw_parameters:,
|
169
|
-
override: {
|
200
|
+
override: {})
|
170
201
|
|
171
202
|
value = override_parameter(name: name,
|
172
203
|
value: value,
|
173
204
|
hash: raw_parameters,
|
174
205
|
override: override)
|
175
206
|
|
176
|
-
if
|
177
|
-
|
207
|
+
if authorization_value
|
208
|
+
authorization_parameters[0][name] = authorization_value
|
209
|
+
elsif value.class == ::Array
|
210
|
+
authorization_parameters[0][name] = []
|
178
211
|
else
|
179
|
-
|
212
|
+
authorization_parameters << name
|
180
213
|
end
|
181
214
|
end
|
215
|
+
# rubocop:enable Metrics/ParameterLists
|
182
216
|
|
183
217
|
def authorize_relationship(name:, embedded_attributes: [])
|
184
218
|
relationship_data = raw_parameter_relationship_data(name)
|
@@ -212,18 +246,24 @@ class Parameters
|
|
212
246
|
raw_parameter_attributes.delete(name)
|
213
247
|
end
|
214
248
|
|
249
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
215
250
|
def override_parameter(name:, value:, hash:, override:)
|
251
|
+
override = { with: nil, if_admin: false, if_absent: true, if_blank: true }
|
252
|
+
.merge(override)
|
253
|
+
|
216
254
|
return value unless override[:with] &&
|
217
255
|
(!token.admin? || override[:if_admin]) &&
|
218
|
-
(
|
256
|
+
(hash.has_key?(name) || override[:if_absent]) &&
|
257
|
+
(!hash.has_key?(name) || !value.nil? || override[:if_blank])
|
219
258
|
|
220
259
|
hash[name] = override[:with]
|
221
260
|
|
222
261
|
override[:with]
|
223
262
|
end
|
263
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
224
264
|
|
225
265
|
def authorized_data_parameter
|
226
|
-
|
266
|
+
authorization[0][:data][2]
|
227
267
|
end
|
228
268
|
|
229
269
|
def authorized_parameter_attributes
|
@@ -235,44 +275,36 @@ class Parameters
|
|
235
275
|
end
|
236
276
|
|
237
277
|
def authorized_parameter_filters
|
238
|
-
|
239
|
-
end
|
240
|
-
|
241
|
-
def authorized_parameter_inclusions
|
242
|
-
authorized_parameters[0][:include] ||= ''
|
243
|
-
end
|
244
|
-
|
245
|
-
def authorized_parameter_sorts
|
246
|
-
authorized_parameters[0][:sort] ||= ''
|
278
|
+
authorization[0][:filter] ||= [{}]
|
247
279
|
end
|
248
280
|
|
249
281
|
# rubocop:disable Layout/ExtraSpacing
|
250
282
|
def raw_parameter_attributes
|
251
283
|
@raw_parameter_attributes ||= begin
|
252
|
-
|
253
|
-
|
284
|
+
parameters[:data] ||= {}
|
285
|
+
parameters[:data][:attributes] ||= {}
|
254
286
|
|
255
|
-
|
287
|
+
parameters[:data][:attributes]
|
256
288
|
end
|
257
289
|
end
|
258
290
|
# rubocop:enable Layout/ExtraSpacing
|
259
291
|
|
260
292
|
def raw_parameter_filters
|
261
|
-
@raw_parameter_filters ||=
|
293
|
+
@raw_parameter_filters ||= parameters[:filter] ||= {}
|
262
294
|
end
|
263
295
|
|
264
296
|
def raw_parameter_inclusions
|
265
|
-
@raw_parameter_inclusions ||=
|
297
|
+
@raw_parameter_inclusions ||= parameters[:include]
|
266
298
|
end
|
267
299
|
|
268
300
|
def raw_parameter_relationships
|
269
|
-
@raw_parameter_relationships ||=
|
301
|
+
@raw_parameter_relationships ||= parameters
|
270
302
|
.fetch(:data, {})
|
271
303
|
.fetch(:relationships, {})
|
272
304
|
end
|
273
305
|
|
274
306
|
def raw_parameter_sorts
|
275
|
-
@raw_parameter_sorts ||=
|
307
|
+
@raw_parameter_sorts ||= parameters[:sort]
|
276
308
|
end
|
277
309
|
|
278
310
|
def raw_parameter_attribute_value(name)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'apple_core/action_controller/resource_naming'
|
4
|
+
require 'apiphobic/authorization/transformers/json_api_to_rails_attributes'
|
5
|
+
require 'apiphobic/resource/collection'
|
4
6
|
require 'apiphobic/resource/model'
|
5
7
|
|
6
8
|
module Apiphobic
|
@@ -54,15 +56,17 @@ module Resource
|
|
54
56
|
return if authorizer.public_send(authorization_query)
|
55
57
|
|
56
58
|
Erratum.fail(
|
57
|
-
'
|
58
|
-
resource_name: self.class.
|
59
|
+
'Forbidden',
|
60
|
+
resource_name: self.class.singular_underscored_base_resource_name,
|
59
61
|
resource_id: [params[:id]],
|
60
62
|
action: action_name,
|
61
63
|
)
|
62
64
|
end
|
63
65
|
|
64
66
|
def authorized_parameters
|
65
|
-
@authorized_parameters ||=
|
67
|
+
@authorized_parameters ||= self
|
68
|
+
.class
|
69
|
+
.authorizer_parameters_class
|
66
70
|
.new(action: action_name,
|
67
71
|
token: token,
|
68
72
|
user: authorized_user,
|
@@ -71,6 +75,10 @@ module Resource
|
|
71
75
|
.call
|
72
76
|
end
|
73
77
|
|
78
|
+
def authorized_inclusions
|
79
|
+
@authorized_inclusions ||= authorized_parameters[:include]
|
80
|
+
end
|
81
|
+
|
74
82
|
def authorized_scope
|
75
83
|
@authorized_scope ||= self
|
76
84
|
.class
|
@@ -80,7 +88,7 @@ module Resource
|
|
80
88
|
user: authorized_user,
|
81
89
|
issuer: authorized_issuer,
|
82
90
|
parameters: authorized_parameters,
|
83
|
-
scope_root: authorized_scope_root_class)
|
91
|
+
scope_root: self.class.authorized_scope_root_class)
|
84
92
|
.call
|
85
93
|
end
|
86
94
|
|
@@ -99,15 +107,15 @@ module Resource
|
|
99
107
|
user: authorized_user,
|
100
108
|
issuer: authorized_issuer,
|
101
109
|
parameters: authorized_parameters,
|
102
|
-
resource: authorized_resource)
|
110
|
+
resource: authorized_resource&.processed)
|
103
111
|
end
|
104
112
|
|
105
113
|
def authorized_resource
|
106
114
|
return if RESOURCE_COLLECTION_ACTIONS.include?(action_name)
|
107
115
|
|
108
116
|
@authorized_resource ||= \
|
109
|
-
Resource::Model
|
110
|
-
.new(resource: public_send(self.class.
|
117
|
+
::Apiphobic::Resource::Model
|
118
|
+
.new(resource: public_send(self.class.singular_underscored_base_resource_name),
|
111
119
|
parameters: authorized_parameters)
|
112
120
|
end
|
113
121
|
|
@@ -115,8 +123,8 @@ module Resource
|
|
115
123
|
return unless RESOURCE_COLLECTION_ACTIONS.include?(action_name)
|
116
124
|
|
117
125
|
@authorized_collection ||= \
|
118
|
-
Resource::Collection
|
119
|
-
.new(resource: public_send(self.class.
|
126
|
+
::Apiphobic::Resource::Collection
|
127
|
+
.new(resource: public_send(self.class.plural_underscored_base_resource_name),
|
120
128
|
parameters: authorized_parameters)
|
121
129
|
end
|
122
130
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apiphobic
|
4
|
+
module Rails
|
5
|
+
module ApiControllerCompatibility
|
6
|
+
def cache_store; end
|
7
|
+
def cache_store=(*); end
|
8
|
+
def assets_dir=(*); end
|
9
|
+
def javascripts_dir=(*); end
|
10
|
+
def stylesheets_dir=(*); end
|
11
|
+
def page_cache_directory=(*); end
|
12
|
+
def asset_path=(*); end
|
13
|
+
def asset_host=(*); end
|
14
|
+
def relative_url_root=(*); end
|
15
|
+
def perform_caching=(*); end
|
16
|
+
def helpers_path=(*); end
|
17
|
+
def allow_forgery_protection=(*); end
|
18
|
+
def helper_method(*); end
|
19
|
+
def helper(*); end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apiphobic/authorization/resource'
|
4
|
+
require 'apiphobic/rails/api_controller_compatibility'
|
5
|
+
require 'erratum/rescuable_resource'
|
6
|
+
require 'erratum/verifiable_resource'
|
7
|
+
|
8
|
+
module Apiphobic
|
9
|
+
module Rails
|
10
|
+
module Controller
|
11
|
+
def self.included(base)
|
12
|
+
base.include Erratum::RescuableResource
|
13
|
+
base.include Erratum::VerifiableResource
|
14
|
+
base.include Apiphobic::Authorization::Resource
|
15
|
+
base.include Apiphobic::Rails::ApiControllerCompatibility
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,3 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'apiphobic/authorization/authorizer'
|
4
|
+
require 'apiphobic/authorization/authorizers/parameters'
|
5
|
+
require 'apiphobic/authorization/authorizers/scope'
|
3
6
|
require 'apiphobic/authorization/version'
|
7
|
+
require 'apiphobic/rails/controller'
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apiphobic-authorization
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thegranddesign
|
@@ -31,26 +31,43 @@ cert_chain:
|
|
31
31
|
Y2GAoHKstmfIVhc4XHOPpmTd2o/C29O9oaRgjrkfQEhF/KvJ/PhoV5hvokzsCyI5
|
32
32
|
iUeXPfvrGD/itYIBCgk+fnzyQQ4QtE5hTQaWQ3o2
|
33
33
|
-----END CERTIFICATE-----
|
34
|
-
date: 2018-05-
|
34
|
+
date: 2018-05-03 00:00:00.000000000 Z
|
35
35
|
dependencies:
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: apiphobic-resource
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1.0'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.0'
|
36
50
|
- !ruby/object:Gem::Dependency
|
37
51
|
name: apple_core
|
38
52
|
requirement: !ruby/object:Gem::Requirement
|
39
53
|
requirements:
|
40
54
|
- - "~>"
|
41
55
|
- !ruby/object:Gem::Version
|
42
|
-
version: '1.
|
56
|
+
version: '1.3'
|
43
57
|
type: :runtime
|
44
58
|
prerelease: false
|
45
59
|
version_requirements: !ruby/object:Gem::Requirement
|
46
60
|
requirements:
|
47
61
|
- - "~>"
|
48
62
|
- !ruby/object:Gem::Version
|
49
|
-
version: '1.
|
63
|
+
version: '1.3'
|
50
64
|
- !ruby/object:Gem::Dependency
|
51
65
|
name: erratum
|
52
66
|
requirement: !ruby/object:Gem::Requirement
|
53
67
|
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 3.1.1
|
54
71
|
- - "~>"
|
55
72
|
- !ruby/object:Gem::Version
|
56
73
|
version: '3.1'
|
@@ -58,6 +75,9 @@ dependencies:
|
|
58
75
|
prerelease: false
|
59
76
|
version_requirements: !ruby/object:Gem::Requirement
|
60
77
|
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 3.1.1
|
61
81
|
- - "~>"
|
62
82
|
- !ruby/object:Gem::Version
|
63
83
|
version: '3.1'
|
@@ -127,15 +147,17 @@ files:
|
|
127
147
|
- LICENSE.txt
|
128
148
|
- README.md
|
129
149
|
- lib/apiphobic-authorization.rb
|
130
|
-
- lib/apiphobic/authorization/authorizable_resource.rb
|
131
150
|
- lib/apiphobic/authorization/authorizer.rb
|
132
151
|
- lib/apiphobic/authorization/authorizers/parameters.rb
|
133
152
|
- lib/apiphobic/authorization/authorizers/scope.rb
|
153
|
+
- lib/apiphobic/authorization/resource.rb
|
134
154
|
- lib/apiphobic/authorization/transformers/json_api_to_rails_attributes.rb
|
135
155
|
- lib/apiphobic/authorization/version.rb
|
136
156
|
- lib/apiphobic/errors/unpermitted_inclusions.rb
|
137
157
|
- lib/apiphobic/errors/unpermitted_sorts.rb
|
138
158
|
- lib/apiphobic/json_api/relationship.rb
|
159
|
+
- lib/apiphobic/rails/api_controller_compatibility.rb
|
160
|
+
- lib/apiphobic/rails/controller.rb
|
139
161
|
homepage: ''
|
140
162
|
licenses:
|
141
163
|
- MIT
|
metadata.gz.sig
CHANGED
Binary file
|