JSONAPI-Resources / JSONAPI-Resources/jsonapi-resources
[0.9.12] Need to add handle the invalid request
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 2.3k
- Forks
- 546
- PR merge metrics
- No merged PRs in 30d
Description
Need to add handle the invalid request
The bug report below shows the necessary cases
begin
require 'bundler/inline'
require 'bundler'
rescue LoadError => e
STDERR.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true, ui: ENV['SILENT'] ? Bundler::UI::Silent.new : Bundler::UI::Shell.new) do
source 'https://rubygems.org'
gem 'rails', require: false
gem 'sqlite3', platform: :mri
gem 'byebug'
gem 'activerecord-jdbcsqlite3-adapter',
git: 'https://github.com/jruby/activerecord-jdbc-adapter',
platform: :jruby
if ENV['JSONAPI_RESOURCES_PATH']
gem 'jsonapi-resources', path: ENV['JSONAPI_RESOURCES_PATH'], require: false
else
gem 'jsonapi-resources', git: 'https://github.com/cerebris/jsonapi-resources', require: false
end
end
# prepare active_record database
require 'active_record'
class NullLogger < Logger
def initialize(*_args) end
def add(*_args, &_block) end
end
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = ENV['SILENT'] ? NullLogger.new : Logger.new(STDOUT)
ActiveRecord::Migration.verbose = !ENV['SILENT']
ActiveRecord::Schema.define do
# Add your schema here
create_table :authors, force: true do |t|
t.string :name
end
create_table :books, force: true do |t|
t.string :text
t.references :author
end
end
# create models
class Author < ActiveRecord::Base
has_many :books
end
class Comment < ActiveRecord::Base
belongs_to :author
end
# prepare rails app
require 'action_controller/railtie'
# require 'action_view/railtie'
require 'jsonapi-resources'
class ApplicationController < ActionController::Base
end
# prepare jsonapi resources and controllers
class AuthorsController < ApplicationController
include JSONAPI::ActsAsResourceController
end
class BooksController < ApplicationController
include JSONAPI::ActsAsResourceController
end
class AuthorResource < JSONAPI::Resource
attribute :name
has_many :books, polymorphic: true, class_name: 'Book'
end
class BookResource < JSONAPI::Resource
attribute :text
end
class TestApp < Rails::Application
config.root = File.dirname(__FILE__)
config.logger = ENV['SILENT'] ? NullLogger.new : Logger.new(STDOUT)
Rails.logger = config.logger
secrets.secret_token = 'secret_token'
secrets.secret_key_base = 'secret_key_base'
config.eager_load = false
end
Rails.application.configure do
config.hosts << 'example.org'
end
# initialize app
Rails.application.initialize!
JSONAPI.configure do |config|
config.json_key_format = :underscored_key
config.route_format = :underscored_key
end
# draw routes
Rails.application.routes.draw do
jsonapi_resources :authors, only: [:show, :update]
end
# prepare tests
require 'minitest/autorun'
require 'rack/test'
# Replace this with the code necessary to make your test fail.
class BugTest < Minitest::Test
include Rack::Test::Methods
def json_api_headers
{ 'Accept' => JSONAPI::MEDIA_TYPE, 'CONTENT_TYPE' => JSONAPI::MEDIA_TYPE }
end
def test_relationships_as_array
author = Author.create!
json_request = {
data: {
id: author.id.to_s,
type: 'authors',
relationships: []
}
}
patch "/authors/#{author.id}", json_request.to_json, json_api_headers
assert last_response.bad_request?
end
def test_relationships_as_nil
author = Author.create!
json_request = {
data: {
id: author.id.to_s,
type: 'authors',
relationships: nil
}
}
patch "/authors/#{author.id}", json_request.to_json, json_api_headers
assert last_response.bad_request?
end
def test_attributes_as_nil
author = Author.create!
json_request = {
data: {
id: author.id.to_s,
type: 'authors',
attributes: nil
}
}
patch "/authors/#{author.id}", json_request.to_json, json_api_headers
assert last_response.bad_request?
end
def test_relationship_name_in_attributes
author = Author.create!
json_request = {
data: {
id: author.id.to_s,
type: 'authors',
attributes: {
books: []
}
}
}
patch "/authors/#{author.id}", json_request.to_json, json_api_headers
assert last_response.bad_request?
end
private
def app
Rails.application
end
end
Solution:
Need update method verify_permitted_params
https://github.com/cerebris/jsonapi-resources/blob/dc96280141715fa531665faada63e88ce356dc92/lib/jsonapi/request_parser.rb#L583
def verify_permitted_params(params, allowed_fields)
formatted_allowed_fields = allowed_fields.collect { |field| format_key(field).to_sym }
params_not_allowed = []
params.each do |key, value|
case key.to_s
when 'relationships'
raise JSONAPI::Exceptions::TypeMismatch.new(nil) unless value.is_a?(ActionController::Parameters) # ADDED THIS LINE
value.keys.each do |links_key|
unless formatted_allowed_fields.include?(links_key.to_sym)
if JSONAPI.configuration.raise_if_parameters_not_allowed
fail JSONAPI::Exceptions::ParameterNotAllowed.new(links_key)
else
params_not_allowed.push(links_key)
value.delete links_key
end
end
end
when 'attributes'
raise JSONAPI::Exceptions::TypeMismatch.new(nil) unless value.is_a?(ActionController::Parameters) # ADDED THIS LINE
attributes = formatted_allowed_fields - resource_klass._relationships.keys # ADDED THIS LINE
value.each do |attr_key, attr_value|
unless formatted_allowed_fields.include?(attr_key.to_sym)
if JSONAPI.configuration.raise_if_parameters_not_allowed
fail JSONAPI::Exceptions::ParameterNotAllowed.new(attr_key)
else
params_not_allowed.push(attr_key)
value.delete attr_key
end
end
end
when 'type'
when 'id'
unless formatted_allowed_fields.include?(:id)
if JSONAPI.configuration.raise_if_parameters_not_allowed
fail JSONAPI::Exceptions::ParameterNotAllowed.new(:id)
else
params_not_allowed.push(:id)
params.delete :id
end
end
else
if JSONAPI.configuration.raise_if_parameters_not_allowed
fail JSONAPI::Exceptions::ParameterNotAllowed.new(key)
else
params_not_allowed.push(key)
params.delete key
end
end
end
if params_not_allowed.length > 0
params_not_allowed_warnings = params_not_allowed.map do |param|
JSONAPI::Warning.new(code: JSONAPI::PARAM_NOT_ALLOWED,
title: 'Param not allowed',
detail: "#{param} is not allowed.")
end
self.warnings.concat(params_not_allowed_warnings)
end
end
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with verify_permitted_params in lib/jsonapi/request_parser.rb around line 583, then run the inline Minitest BugTest reproducer from the issue. The change is complete when the four malformed PATCH payloads are rejected as bad requests without causing an unintended exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rails, ruby, sqlite
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100