diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb index 84ad12d85..c47e0d69f 100644 --- a/app/controllers/epp/domains_controller.rb +++ b/app/controllers/epp/domains_controller.rb @@ -126,13 +126,12 @@ class Epp::DomainsController < EppController end def validate_create - if params[:parsed_frame].css('dsData').count > 0 && params[:parsed_frame].css('create > keyData').count > 0 - epp_errors << { code: '2306', msg: I18n.t('ds_data_and_key_data_must_not_exists_together') } - end - @prefix = 'create > create >' requires('name', 'ns', 'registrant', 'ns > hostAttr') + @prefix = 'extension > create >' + mutually_exclusive 'keyData', 'dsData' + @prefix = nil requires('extension > extdata > legalDocument') end diff --git a/app/controllers/epp_controller.rb b/app/controllers/epp_controller.rb index 32ffaf156..6d38a5225 100644 --- a/app/controllers/epp_controller.rb +++ b/app/controllers/epp_controller.rb @@ -75,6 +75,22 @@ class EppController < ApplicationController epp_errors.empty? end + def mutually_exclusive(*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: '2306', + msg: I18n.t(:are_mutally_exclusive, params: selectors.join(', ')) + } + end + # let's follow grape's validations: https://github.com/intridea/grape/#parameter-validation-and-coercion def exactly_one_of(*selectors) present_count = 0 @@ -87,7 +103,7 @@ class EppController < ApplicationController return if present_count == 1 epp_errors << { - code: '2003', + code: '2306', msg: I18n.t(:exactly_one_parameter_required, params: selectors.join(' or ')) } end diff --git a/config/locales/en.yml b/config/locales/en.yml index 677c8de96..15236335a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -433,7 +433,6 @@ en: failed_to_delete_record: 'Failed to delete record' authentication_error: 'Authentication error' - ds_data_and_key_data_must_not_exists_together: 'dsData and keyData objects must not exists together' setting: 'Setting' @@ -501,3 +500,4 @@ en: could_not_determine_object_type_check_xml_format_and_namespaces: 'Could not determine object type. Check XML format and namespaces.' unknown_expiry_relative_pattern: 'Expiry relative must be compatible to ISO 8601' unknown_expiry_absolute_pattern: 'Expiry absolute must be compatible to ISO 8601' + are_mutally_exclusive: '%{params} are mutually exclusive' diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb index 8aa44f1ba..e810585ba 100644 --- a/spec/epp/domain_spec.rb +++ b/spec/epp/domain_spec.rb @@ -606,6 +606,32 @@ describe 'EPP Domain', epp: true do create_settings end + + it 'prohibits dsData and keyData when they exists together' do + xml = domain_create_xml({}, { + _anonymus: [ + { + dsData: { + keyTag: { value: '12345' }, + alg: { value: '3' }, + digestType: { value: '1' }, + digest: { value: '49FD46E6C4B45C55D4AC' } + } + }, + { + keyData: { + flags: { value: '0' }, + protocol: { value: '3' }, + alg: { value: '5' }, + pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' } + } + }] + }) + + response = epp_plain_request(xml, :xml) + response[:msg].should == 'keyData, dsData are mutually exclusive' + response[:result_code].should == '2306' + end end context 'with juridical persion as an owner' do