fun_with_json_api 0.0.10.4 → 0.0.11

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: 54c93718f1cb92ae625dcd73d881f2cecbf44337
4
- data.tar.gz: 07c36b9edb2e9c2a75f087ec50f3ff400c1afbc0
3
+ metadata.gz: 1328b91ef284a304fd92db41e7a2aadb2a095e2a
4
+ data.tar.gz: 0f457c751fa862274f6a164bc0f4a99896e99bb8
5
5
  SHA512:
6
- metadata.gz: 037d0ef8274786cbbd68f8d7dae99bf44fed9b0e2e66e54471bb5439435dccbc9f7f893b6ce217cb08f002824d94fc58c22099d804d909bbe7b0826e64cf73a8
7
- data.tar.gz: 732c3c878bc211b460fc5d2160e49d10af538d8848eecf70aadff0d15fcdedac1d4bda2cf308a6e645e36656de08885a64c1035c782be70f817701bb6d7c97f0
6
+ metadata.gz: 2901cbad60ecfb0558f25561f00953f99b898930e9812f28ee71e6984b7abb49bbecc96747451485b88923edc3696edf84a381dccfb52c0912c3aae759b205a0
7
+ data.tar.gz: 3c1a3fec849e9b3a93a030c3c6d767f21ff3e37c62efbb9dc8b8375276a4ad811c66f8732d3286b5972f9c013718f75da9511385e77eeb5c7c69bd883fc6d01a
@@ -1,6 +1,7 @@
1
1
  en:
2
2
  fun_with_json_api:
3
3
  exceptions:
4
+ invalid_request_body: 'Request json_api body could not be parsed'
4
5
  invalid_document: 'Request json_api document is invalid'
5
6
  invalid_document_identifier: 'Request json_api data id is invalid'
6
7
  invalid_client_generated_identifier: 'Request json_api data id has already been used for an existing resource'
@@ -27,6 +28,7 @@ en:
27
28
  invalid_uuid_v4_attribute: 'UUID value must be RFC 4122 Version 4 UUID (i.e. "f47ac10b-58cc-4372-a567-0e02b2c3d479")'
28
29
  collection_method_not_supported: 'The current relationship does not support this action'
29
30
  schema_validators:
31
+ document_id_is_not_a_string_message: data id value must be a JSON String (i.e. "1234")
30
32
  document_id_does_not_match_resource: "Expected data id to match resource at endpoint: %{expected}"
31
33
  document_type_does_not_match_endpoint: "Expected data type to be a '%{expected}' resource"
32
34
  invalid_relationship_type_in_array: "Expected '%{relationship}' relationship to be an Array of '%{relationship_type}' resource identifiers"
@@ -0,0 +1,10 @@
1
+ module FunWithJsonApi
2
+ class Configuration
3
+ attr_accessor :force_render_parse_errors_as_json_api
4
+ alias force_render_parse_errors_as_json_api? force_render_parse_errors_as_json_api
5
+
6
+ def initialize
7
+ @force_render_parse_errors_as_json_api = false
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,36 @@
1
+ module FunWithJsonApi
2
+ module Middleware
3
+ class CatchJsonApiParseErrors
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ @app.call(env)
10
+ rescue ActionDispatch::ParamsParser::ParseError => error
11
+ if env['CONTENT_TYPE'] == FunWithJsonApi::MEDIA_TYPE && respond_with_json_api_error?(env)
12
+ build_json_api_parse_error_response
13
+ else
14
+ raise error
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def build_json_api_parse_error_response
21
+ title = I18n.t('fun_with_json_api.exceptions.invalid_request_body')
22
+ [
23
+ 400, { 'Content-Type' => FunWithJsonApi::MEDIA_TYPE },
24
+ [
25
+ { errors: [{ code: 'invalid_request_body', title: title, status: '400' }] }.to_json
26
+ ]
27
+ ]
28
+ end
29
+
30
+ def respond_with_json_api_error?(env)
31
+ FunWithJsonApi.configuration.force_render_parse_errors_as_json_api? ||
32
+ env['HTTP_ACCEPT'] =~ %r{application\/vnd\.api\+json}
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,12 +1,15 @@
1
1
  require 'fun_with_json_api/controller_methods'
2
2
  require 'fun_with_json_api/action_controller_extensions/serialization'
3
+ require 'fun_with_json_api/middleware/catch_json_api_parse_errors'
3
4
 
4
5
  Mime::Type.register FunWithJsonApi::MEDIA_TYPE, :json_api
5
6
 
6
7
  module FunWithJsonApi
7
8
  # Mountable engine for fun with json_api
8
9
  class Railtie < Rails::Railtie
9
- initializer :register_json_api_mime_type do
10
+ class ParseError < ::StandardError; end
11
+
12
+ initializer :register_json_api_parser do |app|
10
13
  parsers =
11
14
  if Rails::VERSION::MAJOR >= 5
12
15
  ActionDispatch::Http::Parameters
@@ -19,6 +22,18 @@ module FunWithJsonApi
19
22
  data = { _json: data } unless data.is_a?(Hash)
20
23
  data.with_indifferent_access
21
24
  end
25
+
26
+ # Add Middleware for catching parser errors
27
+ if Rails::VERSION::MAJOR >= 5
28
+ ActionDispatch::Request.parameter_parsers = parsers::DEFAULT_PARSERS
29
+ app.config.middleware.use(
30
+ 'FunWithJsonApi::Middleware::CatchJsonApiParseErrors'
31
+ )
32
+ else
33
+ app.config.middleware.insert_before(
34
+ parsers, 'FunWithJsonApi::Middleware::CatchJsonApiParseErrors'
35
+ )
36
+ end
22
37
  end
23
38
  initializer :register_json_api_renderer do
24
39
  ActionController::Renderers.add :json_api do |json, options|
@@ -20,14 +20,27 @@ module FunWithJsonApi
20
20
  def call
21
21
  if resource.try(:persisted?)
22
22
  # Ensure correct update document is being sent
23
+ check_resource_id_is_a_string
23
24
  check_resource_id_matches_document_id
24
25
  elsif document_id
25
26
  # Ensure correct create document is being sent
27
+ check_resource_id_is_a_string
26
28
  check_resource_id_can_be_client_generated
27
29
  check_resource_id_has_not_already_been_used
28
30
  end
29
31
  end
30
32
 
33
+ def check_resource_id_is_a_string
34
+ unless document_id.is_a?(String)
35
+ payload = ExceptionPayload.new(
36
+ detail: document_id_is_not_a_string_message,
37
+ pointer: '/data/id'
38
+ )
39
+ message = "document id is not a string: #{document_id.class.name}"
40
+ raise Exceptions::InvalidDocumentIdentifier.new(message, payload)
41
+ end
42
+ end
43
+
31
44
  def check_resource_id_matches_document_id
32
45
  if document_id != resource_id
33
46
  message = "resource id '#{resource_id}' does not match the expected id for"\
@@ -67,6 +80,13 @@ module FunWithJsonApi
67
80
 
68
81
  private
69
82
 
83
+ def document_id_is_not_a_string_message
84
+ I18n.t(
85
+ :document_id_is_not_a_string_message,
86
+ scope: 'fun_with_json_api.schema_validators'
87
+ )
88
+ end
89
+
70
90
  def document_id_does_not_match_resource_message
71
91
  I18n.t(
72
92
  :document_id_does_not_match_resource,
@@ -1,3 +1,3 @@
1
1
  module FunWithJsonApi
2
- VERSION = '0.0.10.4'.freeze
2
+ VERSION = '0.0.11'.freeze
3
3
  end
@@ -1,6 +1,7 @@
1
1
  require 'fun_with_json_api/exception'
2
2
  require 'fun_with_json_api/attribute'
3
3
 
4
+ require 'fun_with_json_api/configuration'
4
5
  require 'fun_with_json_api/pre_deserializer'
5
6
  require 'fun_with_json_api/deserializer'
6
7
  require 'fun_with_json_api/schema_validator'
@@ -14,6 +15,16 @@ module FunWithJsonApi
14
15
 
15
16
  module_function
16
17
 
18
+ attr_writer :configuration
19
+
20
+ def configuration
21
+ @configuration ||= Configuration.new
22
+ end
23
+
24
+ def configure
25
+ yield(configuration)
26
+ end
27
+
17
28
  def deserialize(document, deserializer_class, resource = nil, options = {})
18
29
  # Prepare the deserializer and the expected config
19
30
  deserializer = deserializer_class.create(options)
@@ -1,5 +1,13 @@
1
1
  class ApplicationController < ActionController::Base
2
+ include FunWithJsonApi::ControllerMethods
3
+
4
+ rescue_from FunWithJsonApi::Exception, with: :render_fun_with_json_api_exception
5
+
2
6
  # Prevent CSRF attacks by raising an exception.
3
7
  # For APIs, you may want to use :null_session instead.
4
8
  protect_from_forgery with: :exception
9
+
10
+ def echo
11
+ render json: params.slice(:data)
12
+ end
5
13
  end
@@ -20,6 +20,6 @@ module Dummy
20
20
  # config.i18n.default_locale = :de
21
21
 
22
22
  # Do not swallow errors in after_commit/after_rollback callbacks.
23
- config.active_record.raise_in_transactional_callbacks = true
23
+ # config.active_record.raise_in_transactional_callbacks = true
24
24
  end
25
25
  end
@@ -13,8 +13,13 @@ Rails.application.configure do
13
13
  config.eager_load = false
14
14
 
15
15
  # Configure static file server for tests with Cache-Control for performance.
16
- config.serve_static_files = true
17
- config.static_cache_control = 'public, max-age=3600'
16
+ if config.respond_to?(:public_file_server)
17
+ config.public_file_server.enabled = true
18
+ config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
19
+ else
20
+ config.serve_static_files = true
21
+ config.static_cache_control = 'public, max-age=3600'
22
+ end
18
23
 
19
24
  # Show full error reports and disable caching.
20
25
  config.consider_all_requests_local = true
@@ -53,4 +53,7 @@ Rails.application.routes.draw do
53
53
  # # (app/controllers/admin/products_controller.rb)
54
54
  # resources :products
55
55
  # end
56
+
57
+ # Takes a valid json_api request, and echos the payload back as json
58
+ post :echo, to: 'application#echo'
56
59
  end