fun_with_json_api 0.0.10.4 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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