From 1dbaa6461aa3e78b00cf0a784dcc7e4128ba283f Mon Sep 17 00:00:00 2001 From: dharmon Date: Fri, 10 May 2013 21:50:55 -0600 Subject: [PATCH] Validate parameter keys. Only allow parameters that are defined in the api method definition if the validate_keys option is set to true for the config. If unknown params are passed in an UnknownParam exception will be raised. --- README.rst | 3 +++ lib/apipie/configuration.rb | 8 +++++++- lib/apipie/dsl_definition.rb | 9 +++++++++ lib/apipie/errors.rb | 6 ++++++ spec/controllers/users_controller_spec.rb | 18 +++++++++++++++++- 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 77de9ccd..749e418d 100644 --- a/README.rst +++ b/README.rst @@ -506,6 +506,9 @@ validate_value validate_presence Check the params presence against the documentation. +validate_keys + Check the sent in params to ensure they are defined in the api. (false by default) + process_params Process and extract parameter defined from the params of the request to the api_params variable diff --git a/lib/apipie/configuration.rb b/lib/apipie/configuration.rb index d772e2fb..834e3480 100644 --- a/lib/apipie/configuration.rb +++ b/lib/apipie/configuration.rb @@ -4,7 +4,7 @@ class Configuration attr_accessor :app_name, :app_info, :copyright, :markup, :disqus_shortname, :api_base_url, :doc_base_url, :required_by_default, :layout, :default_version, :debug, :version_in_url, :namespaced_resources, - :validate, :validate_value, :validate_presence, :authenticate, :doc_path, + :validate, :validate_value, :validate_presence, :validate_key, :authenticate, :doc_path, :show_all_examples, :process_params, :update_checksum, :checksum_path, :link_extension, :record, :languages, :translate, :locale, :default_locale @@ -42,6 +42,11 @@ def validate_presence end alias_method :validate_presence?, :validate_presence + def validate_key + return (validate? && @validate_key) + end + alias_method :validate_key?, :validate_key + def process_value? @process_params end @@ -127,6 +132,7 @@ def initialize @validate = true @validate_value = true @validate_presence = true + @validate_key = false @required_by_default = false @api_base_url = HashWithIndifferentAccess.new @doc_base_url = "/apipie" diff --git a/lib/apipie/dsl_definition.rb b/lib/apipie/dsl_definition.rb index 5a254d7c..2c59c9ff 100644 --- a/lib/apipie/dsl_definition.rb +++ b/lib/apipie/dsl_definition.rb @@ -212,6 +212,15 @@ def _apipie_define_validators(description) end end + # Only allow params passed in that are defined keys in the api + # Auto skip the default params (format, controller, action) + if Apipie.configuration.validate_key? + params.reject{|k,_| [:format, :controller, :action].include?(k.to_sym) }.each_key do |param| + # params allowed + raise UnknownParam.new(param) unless description.params.select {|_,p| p.name == param.to_sym}.size > 0 + end + end + if Apipie.configuration.process_value? @api_params = {} diff --git a/lib/apipie/errors.rb b/lib/apipie/errors.rb index fb124f53..f08195ab 100644 --- a/lib/apipie/errors.rb +++ b/lib/apipie/errors.rb @@ -21,6 +21,12 @@ def to_s end end + class UnknownParam < DefinedParamError + def to_s + "Unknown parameter #{@param}" + end + end + class ParamInvalid < DefinedParamError attr_accessor :value, :error diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 7021ea29..25e7ec8d 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -94,9 +94,25 @@ def compare_hashes(h1, h2) lambda { get :show, :id => 5, :session => "secret_hash" }.should_not raise_error lambda { get :show, :id => "ten", :session => "secret_hash" }.should_not raise_error end - end + context "key validations are enabled" do + before do + Apipie.configuration.validate = true + Apipie.configuration.validate_value = false + Apipie.configuration.validate_presence = true + Apipie.configuration.validate_key = true + end + + it "should reply to valid request" do + lambda { get :show, :id => 5, :session => "secret_hash" }.should_not raise_error + assert_response :success + end + + it "should fail if extra parameter is passed in" do + lambda { get :show, :id => 5, :session => "secret_hash", :badparam => 'badfoo' }.should raise_error(Apipie::UnknownParam, /\bbadparam\b/) + end + end context "validations are enabled" do before do