jpie 3.1.3 → 3.1.4
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/Gemfile.lock +1 -1
- data/lib/json_api/controllers/concerns/resource_actions/crud_helpers.rb +3 -3
- data/lib/json_api/controllers/concerns/resource_actions/resource_loading.rb +2 -2
- data/lib/json_api/controllers/relationships_controller.rb +4 -0
- data/lib/json_api/resources/concerns/attributes_dsl.rb +15 -0
- data/lib/json_api/serialization/concerns/deserialization_helpers.rb +2 -1
- data/lib/json_api/serialization/deserializer.rb +6 -2
- data/lib/json_api/support/relationship_guard.rb +6 -1
- data/lib/json_api/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a865a73571e8287482862cc1bda700a579b036108f3c9bb2c752e197ed6b2793
|
|
4
|
+
data.tar.gz: 03b2fe7e47c5712440053ddabe9d131499c34db1a730a2b88b9970900ecda76a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f397a98e0ef1b4759761f84d271694102f181b805d0619a4efca42f1bc4fc407870019bf179a5bcf93e3c5745f0998e9b665c266da8fad496e9a8bbb7240b6d1
|
|
7
|
+
data.tar.gz: 4261ae97d8e83de26145b5d85d62da266d933148d154088f57c54066e71b77c7761d1d6e0d6bf64dd8258fdca34c6547c2ba853dbbf85bbedf6bdffa2dac0b76
|
data/Gemfile.lock
CHANGED
|
@@ -8,7 +8,7 @@ module JSONAPI
|
|
|
8
8
|
private
|
|
9
9
|
|
|
10
10
|
def prepare_create_params(sti_class)
|
|
11
|
-
hash = deserialize_params(:create, model_class: sti_class)
|
|
11
|
+
hash = deserialize_params(:create, model_class: sti_class, definition: determine_sti_resource_class)
|
|
12
12
|
attachments = extract_active_storage_params_from_hash(hash, sti_class)
|
|
13
13
|
clean_params(hash, attachments)
|
|
14
14
|
apply_sti_type(sti_class, hash)
|
|
@@ -16,7 +16,7 @@ module JSONAPI
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def prepare_create_params_from_data(sti_class, data)
|
|
19
|
-
hash = deserialize_params(:create, model_class: sti_class, data:)
|
|
19
|
+
hash = deserialize_params(:create, model_class: sti_class, data:, definition: determine_sti_resource_class)
|
|
20
20
|
attachments = extract_active_storage_params_from_hash(hash, sti_class)
|
|
21
21
|
clean_params(hash, attachments)
|
|
22
22
|
apply_sti_type(sti_class, hash)
|
|
@@ -24,7 +24,7 @@ module JSONAPI
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def prepare_update_params
|
|
27
|
-
hash = deserialize_params(:update)
|
|
27
|
+
hash = deserialize_params(:update, definition: @resource_class)
|
|
28
28
|
attachments = extract_active_storage_params_from_hash(hash, model_class)
|
|
29
29
|
clean_params(hash, attachments)
|
|
30
30
|
[hash, attachments]
|
|
@@ -51,10 +51,10 @@ module JSONAPI
|
|
|
51
51
|
JSONAPI::ParamHelpers.deep_symbolize_params(data)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
def deserialize_params(action = :update, model_class: nil, data: nil)
|
|
54
|
+
def deserialize_params(action = :update, model_class: nil, data: nil, definition: nil)
|
|
55
55
|
target = model_class || self.model_class
|
|
56
56
|
payload = data.nil? ? raw_jsonapi_data : symbolize_data(data)
|
|
57
|
-
JSONAPI::Deserializer.new(payload, model_class: target, action:).to_model_attributes
|
|
57
|
+
JSONAPI::Deserializer.new(payload, model_class: target, action:, definition:).to_model_attributes
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def resource_url(resource)
|
|
@@ -90,6 +90,10 @@ module JSONAPI
|
|
|
90
90
|
def ensure_relationship_writable!(association)
|
|
91
91
|
return if active_storage_writable?(association)
|
|
92
92
|
|
|
93
|
+
unless @resource_class.relationship_field_writable?(@relationship_name, :update)
|
|
94
|
+
raise JSONAPI::AuthorizationError, "Relationship '#{@relationship_name}' is not updatable"
|
|
95
|
+
end
|
|
96
|
+
|
|
93
97
|
relationship_def = find_relationship_definition
|
|
94
98
|
readonly = relationship_def && (relationship_def[:options] || {})[:readonly] == true
|
|
95
99
|
|
|
@@ -41,6 +41,21 @@ module JSONAPI
|
|
|
41
41
|
resolve_field_list(:@updatable_fields, :permitted_updatable_fields)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
# Whether a relationship may be written for the given action (:create or :update).
|
|
45
|
+
# A relationship is gated by the creatable_fields/updatable_fields allow-list only when
|
|
46
|
+
# the resource opted it in by naming it in one of those lists; relationships named in
|
|
47
|
+
# neither keep the default (readonly-only) behavior. This lets a resource make a
|
|
48
|
+
# relationship create-only — name it in creatable_fields, omit it from updatable_fields —
|
|
49
|
+
# the same way it restricts attributes.
|
|
50
|
+
def relationship_field_writable?(name, action)
|
|
51
|
+
name = name.to_sym
|
|
52
|
+
creatable = permitted_creatable_fields.map(&:to_sym)
|
|
53
|
+
updatable = permitted_updatable_fields.map(&:to_sym)
|
|
54
|
+
return true unless creatable.include?(name) || updatable.include?(name)
|
|
55
|
+
|
|
56
|
+
(action == :create ? creatable : updatable).include?(name)
|
|
57
|
+
end
|
|
58
|
+
|
|
44
59
|
def resolve_field_list(ivar, method)
|
|
45
60
|
return (instance_variable_get(ivar) || []).uniq if instance_variable_defined?(ivar)
|
|
46
61
|
return superclass.public_send(method).uniq if inherits_field?(ivar, method)
|
|
@@ -129,7 +129,8 @@ module JSONAPI
|
|
|
129
129
|
|
|
130
130
|
association = @model_class.reflect_on_association(association_name.to_sym)
|
|
131
131
|
readonly = relationship_options_for(association_name)[:readonly] == true
|
|
132
|
-
|
|
132
|
+
field_writable = @definition.relationship_field_writable?(association_name, @action)
|
|
133
|
+
JSONAPI::RelationshipGuard.ensure_writable!(association, association_name, readonly:, field_writable:)
|
|
133
134
|
end
|
|
134
135
|
|
|
135
136
|
def relationship_options_for(association_name)
|
|
@@ -16,10 +16,14 @@ module JSONAPI
|
|
|
16
16
|
include Serialization::RelationshipProcessing
|
|
17
17
|
include Serialization::DeserializationHelpers
|
|
18
18
|
|
|
19
|
-
def initialize(params, model_class:, action: :create)
|
|
19
|
+
def initialize(params, model_class:, action: :create, definition: nil)
|
|
20
20
|
@params = ParamHelpers.deep_symbolize_params(params)
|
|
21
21
|
@model_class = model_class
|
|
22
|
-
|
|
22
|
+
# Prefer the resource the request is addressing (resolved by type/route). Resolving
|
|
23
|
+
# from the model alone is ambiguous when several resources share one model
|
|
24
|
+
# (e.g. RestrictedPostResource and PostResource both back Post), which would gate
|
|
25
|
+
# relationships against the wrong resource's creatable_fields/updatable_fields.
|
|
26
|
+
@definition = definition || ResourceLoader.find_for_model(model_class)
|
|
23
27
|
@action = action.to_sym
|
|
24
28
|
end
|
|
25
29
|
end
|
|
@@ -6,7 +6,12 @@ module JSONAPI
|
|
|
6
6
|
module RelationshipGuard
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
|
-
def ensure_writable!(association, error_target, readonly: false)
|
|
9
|
+
def ensure_writable!(association, error_target, readonly: false, field_writable: true)
|
|
10
|
+
# A relationship excluded from the resource's creatable_fields/updatable_fields
|
|
11
|
+
# allow-list is not writable for this action, on either the main-body path or the
|
|
12
|
+
# dedicated endpoint. This gate is independent of the AR reflection.
|
|
13
|
+
raise JSONAPI::AuthorizationError, "Relationship '#{error_target}' is not writable" unless field_writable
|
|
14
|
+
|
|
10
15
|
return unless association
|
|
11
16
|
return unless readonly
|
|
12
17
|
|
data/lib/json_api/version.rb
CHANGED