From e6b36c409dafeb7b711c3895d125efafa74f9500 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Fri, 23 Jan 2015 13:08:35 +0200 Subject: [PATCH] Introduce 'optional' validator to epp controllers --- app/controllers/epp/keyrelays_controller.rb | 13 ++------ app/controllers/epp_controller.rb | 13 ++++++++ app/validators/date_time_iso8601_validator.rb | 30 +++++++++++++++++++ app/validators/duration_iso8601_validator.rb | 29 +++++++++++++++--- config/locales/en.yml | 3 +- spec/epp/keyrelay_spec.rb | 24 +++++++++++++++ 6 files changed, 96 insertions(+), 16 deletions(-) create mode 100644 app/validators/date_time_iso8601_validator.rb diff --git a/app/controllers/epp/keyrelays_controller.rb b/app/controllers/epp/keyrelays_controller.rb index 97944b29e..91e2a215b 100644 --- a/app/controllers/epp/keyrelays_controller.rb +++ b/app/controllers/epp/keyrelays_controller.rb @@ -21,18 +21,9 @@ class Epp::KeyrelaysController < EppController 'authInfo', 'authInfo > pw' ) + optional 'expiry > relative', duration_iso8601: true + optional 'expiry > absolute', date_time_iso8601: true exactly_one_of 'expiry > relative', 'expiry > absolute' - - begin - abs_datetime = params[:parsed_frame].css('absolute').text - abs_datetime = DateTime.parse(abs_datetime) if abs_datetime.present? - rescue => _e - epp_errors << { - code: '2005', - msg: I18n.t('unknown_expiry_absolute_pattern'), - value: { obj: 'expiry_absolute', val: abs_datetime } - } - end end # rubocop: enable Metrics/PerceivedComplexity # rubocop: enable Metrics/CyclomaticComplexity diff --git a/app/controllers/epp_controller.rb b/app/controllers/epp_controller.rb index 26bbd571b..3e3372ac7 100644 --- a/app/controllers/epp_controller.rb +++ b/app/controllers/epp_controller.rb @@ -92,6 +92,19 @@ class EppController < ApplicationController } end + def optional(selector, *validations) + full_selector = [@prefix, selector].join(' ') + el = params[:parsed_frame].css(full_selector).first + return unless el && el.text.present? + value = el.text + + validations.each do |x| + validator = "#{x.first[0]}_validator".camelize.constantize + err = validator.validate_epp(selector.split(' ').last, value) + epp_errors << err if err + end + 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/validators/date_time_iso8601_validator.rb b/app/validators/date_time_iso8601_validator.rb new file mode 100644 index 000000000..d764620e8 --- /dev/null +++ b/app/validators/date_time_iso8601_validator.rb @@ -0,0 +1,30 @@ +class DateTimeIso8601Validator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return if self.class.validate(value) + record.errors[attribute] << (options[:message] || I18n.t('unknown_expiry_absolute_pattern')) + end + + class << self + def validate(value) + return true if value.empty? + + begin + DateTime.parse(value) + rescue => _e + return false + end + + true + end + + def validate_epp(obj, value) + return if validate(value) + + { + code: '2005', + msg: I18n.t(:unknown_expiry_absolute_pattern), + value: { obj: obj, val: value } + } + end + end +end diff --git a/app/validators/duration_iso8601_validator.rb b/app/validators/duration_iso8601_validator.rb index ceffb92ee..9c02fc780 100644 --- a/app/validators/duration_iso8601_validator.rb +++ b/app/validators/duration_iso8601_validator.rb @@ -1,9 +1,30 @@ class DurationIso8601Validator < ActiveModel::EachValidator def validate_each(record, attribute, value) - return unless value.present? + return if self.class.validate(value) + record.errors[attribute] << (options[:message] || record.errors.generate_message(attribute, :unknown_pattern)) + end - ISO8601::Duration.new(value) - rescue => _e - record.errors[attribute] << (options[:message] || record.errors.generate_message(attribute, :unknown_pattern)) + class << self + def validate(value) + return true if value.empty? + + begin + ISO8601::Duration.new(value) + rescue => _e + return false + end + + true + end + + def validate_epp(obj, value) + return if validate(value) + + { + code: '2003', + msg: I18n.t(:unknown_expiry_relative_pattern), + value: { obj: obj, val: value } + } + end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 900940cad..677c8de96 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -472,7 +472,6 @@ en: requester: 'Requester' accepter: 'Accepter' keyrelay_details: 'Keyrelay details' - unknown_expiry_absolute_pattern: 'Expiry absolute must be compatible to ISO 8601' domain_name: 'Domain name' created_at: 'Created at' type: 'Type' @@ -500,3 +499,5 @@ en: repp_log: 'REPP log' repp_logs: 'REPP logs' 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' diff --git a/spec/epp/keyrelay_spec.rb b/spec/epp/keyrelay_spec.rb index f8e35befc..62d5bc300 100644 --- a/spec/epp/keyrelay_spec.rb +++ b/spec/epp/keyrelay_spec.rb @@ -112,6 +112,30 @@ describe 'EPP Keyrelay', epp: true do expect(zone.messages.queued.count).to eq(0) end + it 'returns an error on invalid absolute expiry' do + xml = epp_xml.keyrelay({ + name: { value: 'example.ee' }, + keyData: { + flags: { value: '256' }, + protocol: { value: '3' }, + alg: { value: '8' }, + pubKey: { value: 'cmlraXN0aGViZXN0' } + }, + authInfo: { + pw: { value: domain.auth_info } + }, + expiry: { + absolute: { value: 'Invalid Absolute' } + } + }) + + response = epp_request(xml, :xml, :elkdata) + expect(response[:msg]).to eq('Expiry absolute must be compatible to ISO 8601') + expect(response[:results][0][:value]).to eq('Invalid Absolute') + + expect(zone.messages.queued.count).to eq(0) + end + it 'does not allow both relative and absolute' do xml = epp_xml.keyrelay({ name: { value: 'example.ee' },