diff --git a/app/controllers/epp/keyrelays_controller.rb b/app/controllers/epp/keyrelays_controller.rb index 8b2b4480c..97944b29e 100644 --- a/app/controllers/epp/keyrelays_controller.rb +++ b/app/controllers/epp/keyrelays_controller.rb @@ -14,7 +14,14 @@ class Epp::KeyrelaysController < EppController private def validate_keyrelay - epp_request_valid?('pubKey', 'flags', 'protocol', 'alg', 'name', 'pw') + @prefix = 'keyrelay >' + epp_request_valid?( + 'name', + 'keyData', 'keyData > pubKey', 'keyData > flags', 'keyData > protocol', 'keyData > alg', + 'authInfo', 'authInfo > pw' + ) + + exactly_one_of 'expiry > relative', 'expiry > absolute' begin abs_datetime = params[:parsed_frame].css('absolute').text @@ -26,8 +33,6 @@ class Epp::KeyrelaysController < EppController value: { obj: 'expiry_absolute', val: abs_datetime } } end - - epp_errors.empty? end # rubocop: enable Metrics/PerceivedComplexity # rubocop: enable Metrics/CyclomaticComplexity diff --git a/app/controllers/epp_controller.rb b/app/controllers/epp_controller.rb index 2a7733c5e..26bbd571b 100644 --- a/app/controllers/epp_controller.rb +++ b/app/controllers/epp_controller.rb @@ -75,6 +75,23 @@ class EppController < ApplicationController epp_errors.empty? end + # let's follow grape's validations: https://github.com/intridea/grape/#parameter-validation-and-coercion + def exactly_one_of(*selectors) + present_count = 0 + selectors.each do |selector| + full_selector = [@prefix, selector].join(' ') + el = params[:parsed_frame].css(full_selector).first + present_count += 1 if el && el.text.present? + end + + return if present_count == 1 + + epp_errors << { + code: '2003', + msg: I18n.t(:exactly_one_parameter_required, params: selectors.join(' or ')) + } + end + def xml_attrs_present?(ph, attributes) # TODO: THIS IS DEPRECATED AND WILL BE REMOVED IN FUTURE attributes.each do |x| epp_errors << { diff --git a/app/models/keyrelay.rb b/app/models/keyrelay.rb index 95e6946c7..e6be8ccd4 100644 --- a/app/models/keyrelay.rb +++ b/app/models/keyrelay.rb @@ -19,6 +19,7 @@ class Keyrelay < ActiveRecord::Base [:expiry_relative, :unknown_pattern, { value: { obj: 'relative', val: expiry_relative } }] ], '2003' => [ + # TODO: Remove only_one_parameter_allowed and other params that are validated in controller? [:base, :only_one_parameter_allowed, { param_1: 'relative', param_2: 'absolute' }], [:key_data_public_key, :blank], [:key_data_flags, :blank], diff --git a/config/locales/en.yml b/config/locales/en.yml index 3f208027f..900940cad 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -444,6 +444,7 @@ en: generate_zonefile: 'Generate zonefile' zonefile: 'Zonefile' only_one_parameter_allowed: 'Only one parameter allowed: %{param_1} or %{param_2}' + exactly_one_parameter_required: 'Exactly one parameter required: %{params}' required_parameter_missing_choice: 'Required parameter missing: %{param_1} or %{param_2}' transfer_wait_time: 'Transfer wait time' ns_min_count: 'Nameserver minimum count' diff --git a/spec/epp/keyrelay_spec.rb b/spec/epp/keyrelay_spec.rb index 6fb42d336..f8e35befc 100644 --- a/spec/epp/keyrelay_spec.rb +++ b/spec/epp/keyrelay_spec.rb @@ -131,7 +131,7 @@ describe 'EPP Keyrelay', epp: true do }) response = epp_request(xml, :xml, :elkdata) - expect(response[:msg]).to eq('Only one parameter allowed: relative or absolute') + expect(response[:msg]).to eq('Exactly one parameter required: expiry > relative or expiry > absolute') expect(zone.messages.queued.count).to eq(0) end