diff --git a/.codeclimate.yml b/.codeclimate.yml index 03f849185..21ab3742c 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -27,6 +27,7 @@ engines: - HACK rubocop: enabled: true + channel: rubocop-0-51 reek: enabled: true checks: diff --git a/.reek b/.reek index d94291666..060f76785 100644 --- a/.reek +++ b/.reek @@ -1,3 +1,1171 @@ exclude_paths: - db/migrate/ - db/data/ +UncommunicativeModuleName: + exclude: + - Repp::AccountV1 + - Repp::ContactV1 + - Repp::DomainV1 +UncommunicativeVariableName: + exclude: + - Repp::DomainV1 + - Admin::AccountActivitiesController + - Admin::AdminUsersController + - Admin::ApiUsersController + - Admin::BankStatementsController + - Admin::Billing::PricesController + - Admin::BlockedDomainsController + - Admin::ContactVersionsController + - Admin::ContactVersionsController#index + - Admin::ContactsController + - Admin::DomainVersionsController + - Admin::DomainVersionsController#index + - Admin::DomainsController + - Admin::DomainsController#build_associations + - Admin::EppLogsController + - Admin::InvoicesController + - Admin::InvoicesController#create + - Admin::KeyrelaysController + - Admin::MailTemplatesController + - Admin::RegistrarsController + - Admin::ReppLogsController + - Admin::ReservedDomainsController + - Admin::SettingsController#casted_settings + - Admin::SettingsController#create + - Epp::DomainsController#renew + - Epp::DomainsController#update + - Epp::SessionsController#connection_limit_ok? + - Epp::SessionsController#login + - EppController + - EppController#create_full_selectors + - EppController#optional + - EppController#xml_attrs_present? + - Registrant::DomainsController + - Registrar::AccountActivitiesController + - Registrar::ContactsController + - Registrar::ContactsController#download_list + - Registrar::ContactsController#index + - Registrar::DeppController#response_ok? + - Registrar::DomainsController + - Registrar::DomainsController#index + - Registrar::DomainsController#search_contacts + - Registrar::InvoicesController + - ContactMailer#email_updated + - Ability#billing + - Ability#epp + - AccountActivity#to_csv + - AccountActivity#types_for_select + - ApiUser#api_pki_ok? + - ApiUser#registrar_pki_ok? + - BankLink::Request#calc_mac + - BankLink::Response#validate_cancel + - BankLink::Response#validate_success + - BankStatement#import_th6_file + - BlockedDomain#generate_json + - Concerns::Domain::ForceDelete#cancel_force_delete + - EppErrors#add_epp_error + - EppErrors#collect_child_errors + - EppErrors#find_epp_code_and_value + - Versions::ClassMethods#all_versions_for + - Contact + - Contact#all_domains + - Contact#all_registrant_domains + - Contact#manage_emails + - Contact#search_by_query + - Contact#status_notes_array= + - Depp::Contact#construct_create_disclosure_xml + - Depp::Contact#extract_disclosure_hash + - Depp::Contact#extract_info_disclosure + - Depp::Contact#find_by_id + - Depp::Contact#handle_errors + - Depp::Contact#type_string + - Depp::Domain#construct_params_from_server_data + - Depp::Domain#create_contacts_hash + - Depp::Domain#create_dnskeys_hash + - Depp::Domain#create_nameservers_hash + - Depp::Domain#default_params + - Depp::User#initialize + - Depp::User#request + - Depp::User#validate_existance_in_server + - Directo#self.send_monthly_invoices + - DNS::Zone#self.generate_zonefile + - Dnskey#bin_to_hex + - Dnskey#generate_ds_key_tag + - Dnskey#int_to_hex + - Domain#admin_status_update + - Domain#delegated_nameservers + - Domain#name_in_wire_format + - Domain#parent_valid? + - Domain#status_notes_array= + - Domain#subordinate_nameservers + - DomainCron#self.destroy_delete_candidates + - DomainMailModel#admins + - Epp::Contact#attrs_from + - Epp::Contact#check_availability + - Epp::Domain#check_availability + - Epp::Domain#copy_and_transfer_contact + - Epp::Domain#domain_contact_attrs_from + - Epp::Domain#domain_status_list_from + - Epp::Domain#domain_statuses_attrs + - Epp::Domain#nameservers_from + - Epp::Domain#parse_period_unit_from_frame + - Epp::Domain#transfer_domain_contacts + - Epp::Domain#validate_contacts + - Invoice#cancel_overdue_invoices + - Legacy::Db + - LegalDocument#save_to_filesystem + - Nameserver#replace_hostname_ends + - RegistrantUser#find_or_create_by_idc_data + - RegistrantUser#find_or_create_by_mid_data + - Registrar + - Registrar#search_by_query + - ReservedDomain#generate_json + - WhoisRecord#generate_json + - UniquenessMultiValidator#validate_each + - Registry::Application + - ActiveRecord::Base + - Ransack::Adapters::ActiveRecord::Context#evaluate + - EppConstraint#matches? + - Iptable#counter_update +DuplicateMethodCall: + exclude: + - Admin::AccountActivitiesController#index + - Admin::AccountActivitiesController#set_default_dates + - Admin::AdminUsersController#update + - Admin::ApiUsersController#update + - Admin::BankStatementsController#download_import_file + - Admin::Billing::PricesController#index + - Admin::BlockedDomainsController#delete + - Admin::BlockedDomainsController#index + - Admin::CertificatesController#create + - Admin::CertificatesController#set_certificate + - Admin::ContactVersionsController#index + - Admin::ContactVersionsController#show + - Admin::ContactsController#index + - Admin::ContactsController#normalize_search_parameters + - Admin::DomainVersionsController#index + - Admin::DomainVersionsController#show + - Admin::DomainsController#build_associations + - Admin::DomainsController#index + - Admin::DomainsController#normalize_search_parameters + - Admin::DomainsController#schedule_force_delete + - Admin::EppLogsController#index + - Admin::EppLogsController#set_default_dates + - Admin::LegalDocumentsController#show + - Admin::PendingDeletesController#destroy + - Admin::PendingDeletesController#update + - Admin::PendingUpdatesController#destroy + - Admin::PendingUpdatesController#update + - Admin::ReppLogsController#index + - Admin::ReppLogsController#set_default_dates + - Admin::ReservedDomainsController#delete + - Admin::ReservedDomainsController#index + - Admin::SessionsController#create + - Admin::SettingsController#casted_settings + - Admin::ZonefilesController#create + - ApplicationController#comma_support_for + - Epp::ContactsController#validate_create + - Epp::DomainsController#create + - Epp::DomainsController#delete + - Epp::DomainsController#renew + - Epp::DomainsController#transfer + - Epp::DomainsController#update + - Epp::KeyrelaysController#keyrelay + - Epp::PollsController#ack_poll + - Epp::PollsController#poll + - Epp::PollsController#req_poll + - Epp::SessionsController#connection_limit_ok? + - Epp::SessionsController#ip_white? + - Epp::SessionsController#login + - Epp::SessionsController#login_params + - EppController#current_user + - EppController#handle_errors + - EppController#iptables_counter_update + - EppController#latin_only + - EppController#optional + - EppController#update_epp_session + - EppController#write_to_epp_log + - Registrant::DomainDeleteConfirmsController#update + - Registrant::DomainUpdateConfirmsController#update + - Registrant::DomainsController#domain_verification_url + - Registrant::DomainsController#download_list + - Registrant::DomainsController#get_confirm_path + - Registrant::DomainsController#index + - Registrant::DomainsController#normalize_search_parameters + - Registrant::SessionsController#id + - Registrant::SessionsController#mid + - Registrant::SessionsController#mid_status + - Registrant::WhoisController#index + - Registrar::AccountActivitiesController#index + - Registrar::BaseController#check_ip + - Registrar::ContactsController#download_list + - Registrar::ContactsController#index + - Registrar::ContactsController#normalize_search_parameters + - Registrar::ContactsController#update + - Registrar::DomainsController#check + - Registrar::DomainsController#destroy + - Registrar::DomainsController#index + - Registrar::DomainsController#info + - Registrar::DomainsController#normalize_search_parameters + - Registrar::DomainsController#renew + - Registrar::DomainsController#search_contacts + - Registrar::DomainsController#transfer + - Registrar::DomainsController#update + - Registrar::InvoicesController#index + - Registrar::InvoicesController#normalize_search_parameters + - Registrar::PaymentsController#back + - Registrar::SessionsController#create + - Registrar::SessionsController#mid + - Registrar::SessionsController#mid_status + - ApplicationHelper#changing_css_class + - ApplicationHelper#creator_link + - ApplicationHelper#custom_sort_link + - ApplicationHelper#unstable_env + - ApplicationHelper#updator_link + - Registrant::ApplicationHelper#pagination_details + - Registrar::ApplicationHelper#pagination_details + - DomainDeleteConfirmJob#raise_errors! + - DomainDeleteConfirmJob#run + - DomainUpdateConfirmJob#raise_errors! + - DomainUpdateConfirmJob#run + - UpdateWhoisRecordJob#update_domain + - ApplicationMailer#whitelist_blocked? + - DomainExpireMailer#expired + - DomainMailer#compose_from + - DomainMailer#delete_confirmation + - DomainMailer#pending_delete_expired_notification + - DomainMailer#pending_delete_rejected_notification + - InvoiceMailer#invoice_email + - Ability#epp + - Ability#initialize + - BankLink::Request#fields + - BankLink::Response#initialize + - BankStatement#import_th6_file + - BankStatement#parse_th6_row + - BankStatement#status + - Billing::Price#self.effective + - Billing::Price#self.valid + - BusinessRegistryCache#fetch_by_ident_and_cc + - BusinessRegistryCache#purge + - Certificate#parse_metadata + - Certificate#reload_apache + - Certificate#revoke! + - Certificate#status + - Certificate#update_id_crl + - Certificate#update_registry_crl + - EppErrors#add_epp_error + - UserEvents#cr_id + - Versions#user_from_id_role_username + - Versions::ClassMethods#all_versions_for + - Contact#all_domains + - Contact#all_registrant_domains + - Contact#destroy_orphans + - Contact#domain_names_with_roles + - Contact#generate_code + - Contact#related_domain_descriptions + - Contact#val_ident_valid_format? + - Deposit#validate_amount + - Depp::Contact#construct_check_hash_from_data + - Depp::Contact#construct_create_disclosure_xml + - Depp::Contact#extension_xml + - Depp::Contact#extract_info_disclosure + - Depp::Contact#find_by_id + - Depp::Contact#new_from_params + - Depp::Contact#update_attributes + - Depp::Domain#confirm_transfer + - Depp::Domain#construct_custom_params_hash + - Depp::Domain#construct_edit_hash + - Depp::Domain#construct_ext_edit_hash + - Depp::Domain#construct_params_from_server_data + - Depp::Domain#create + - Depp::Domain#create_contacts_hash + - Depp::Domain#create_dnskeys_hash + - Depp::Domain#create_key_data_hash + - Depp::Domain#create_nameservers_hash + - Depp::Domain#default_params + - Depp::Domain#renew + - Depp::Keyrelay#keyrelay + - Depp::User#repp_request + - Depp::User#validate_existance_in_server + - Directo#self.dump_result_to_db + - Directo#self.load_price + - Directo#self.send_monthly_invoices + - Directo#self.send_receipts + - DNS::Zone#self.generate_zonefile + - Dnskey#generate_digest + - Domain#manage_automatic_statuses + - Domain#parent_valid? + - Domain#pending_registrant + - Domain#renewable? + - Domain#set_graceful_expired + - DomainCron#self.clean_expired_pendings + - DomainCron#self.delete_legal_doc_duplicates + - DomainCron#self.destroy_delete_candidates + - DomainCron#self.start_expire_period + - DomainCron#self.start_redemption_grace_period + - DomainMailModel#registrant_pending + - DomainMailModel#subject + - DomainMailModel#verification_token + - Epp::Contact#attrs_from + - Epp::Contact#legal_document_attrs + - Epp::Contact#status_list_from + - Epp::Contact#update_attributes + - Epp::Domain#apply_pending_update! + - Epp::Domain#attrs_from + - Epp::Domain#dnskeys_attrs + - Epp::Domain#domain_contact_attrs_from + - Epp::Domain#domain_status_list_from + - Epp::Domain#new_from_epp + - Epp::Domain#parse_legal_document_from_frame + - Epp::Domain#query_transfer + - Epp::Domain#renew + - Epp::Domain#transfer_domain_contacts + - Epp::Domain#update + - Epp::Domain#validate_contacts + - Epp::Domain#validate_exp_dates + - Invoice#cancel_overdue_invoices + - Invoice#set_invoice_number + - LegalDocument#save_to_filesystem + - LegalDocument#self.remove_duplicates + - Nameserver#replace_hostname_ends + - Setting#self.params_errors + - Setting#self.reload_settings! + - Soap::Arireg#associated_businesses + - Soap::Arireg#body + - Soap::Arireg#debug + - Soap::Arireg#initialize + - WhoisRecord#generate_json + - DomainPresenter#delete_date + - DomainPresenter#force_delete_date + - DomainPresenter#on_hold_date + - DomainNameValidator#validate_each + - DomainNameValidator#validate_format + - DurationIso8601Validator#validate_each + - UniquenessMultiValidator#validate_each + - ActionView::Helpers::FormBuilder#label + - ActionDispatch::Flash#call + - Rack::Request#trusted_proxy? + - Ransack::Adapters::ActiveRecord::Context#evaluate + - DeviseCustomFailure#redirect_url + - EppConstraint#matches? + - PhoneValidator#validate_each +InstanceVariableAssumption: + exclude: + - Admin::AccountActivitiesController + - Admin::AdminUsersController + - Admin::ApiUsersController + - Admin::BankStatementsController + - Admin::BankTransactionsController + - Admin::Billing::PricesController + - Admin::BlockedDomainsController + - Admin::CertificatesController + - Admin::ContactVersionsController + - Admin::ContactsController + - Admin::DNS::ZonesController + - Admin::DomainVersionsController + - Admin::DomainsController + - Admin::EppLogsController + - Admin::InvoicesController + - Admin::KeyrelaysController + - Admin::LegalDocumentsController + - Admin::MailTemplatesController + - Admin::PendingDeletesController + - Admin::PendingUpdatesController + - Admin::RegistrarsController + - Admin::ReppLogsController + - Admin::ReservedDomainsController + - Admin::SessionsController + - Admin::SettingsController + - Admin::WhiteIpsController + - Admin::ZonefilesController + - Epp::ContactsController + - Epp::DomainsController + - Epp::KeyrelaysController + - Epp::PollsController + - Epp::SessionsController + - EppController + - Registrant::ContactsController + - Registrant::DomainDeleteConfirmsController + - Registrant::DomainUpdateConfirmsController + - Registrant::DomainsController + - Registrant::RegistrarsController + - Registrant::SessionsController + - Registrar::AccountActivitiesController + - Registrar::ContactsController + - Registrar::DepositsController + - Registrar::DeppController + - Registrar::DomainsController + - Registrar::InvoicesController + - Registrar::PaymentsController + - Registrar::PollsController + - Registrar::SessionsController + - DefaultFormBuilder + - ContactMailer + - DomainMailer + - InvoiceMailer + - ApiUser + - BankTransaction + - Certificate + - Contact + - Deposit + - Depp::Contact + - Domain + - DomainContact + - WhoisRecord + - ActiveModel::Errors + - ActionDispatch::Flash + - Ransack::Adapters::ActiveRecord::Context +IrresponsibleModule: + exclude: + - Admin::AccountActivitiesController + - Admin::AdminUsersController + - Admin::ApiUsersController + - Admin::BankStatementsController + - Admin::BankTransactionsController + - Admin::Billing::PricesController + - Admin::BlockedDomainsController + - Admin::CertificatesController + - Admin::ContactVersionsController + - Admin::ContactsController + - Admin::DashboardsController + - Admin::DelayedJobsController + - Admin::DNS::ZonesController + - Admin::DomainVersionsController + - Admin::DomainsController + - Admin::EppLogsController + - Admin::InvoicesController + - Admin::KeyrelaysController + - Admin::LegalDocumentsController + - Admin::MailTemplatesController + - Admin::PendingDeletesController + - Admin::PendingUpdatesController + - Admin::RegistrarsController + - Admin::ReppLogsController + - Admin::ReservedDomainsController + - Admin::SessionsController + - Admin::SettingsController + - Admin::WhiteIpsController + - Admin::ZonefilesController + - AdminController + - ApplicationController + - Epp::ContactsController + - Epp::DomainsController + - Epp::ErrorsController + - Epp::KeyrelaysController + - Epp::PollsController + - Epp::SessionsController + - EppController + - Registrant::ContactsController + - Registrant::DomainDeleteConfirmsController + - Registrant::DomainUpdateConfirmsController + - Registrant::DomainsController + - Registrant::RegistrarsController + - Registrant::SessionsController + - Registrant::WhoisController + - RegistrantController + - Registrar::AccountActivitiesController + - Registrar::BaseController + - Registrar::ContactsController + - Registrar::DashboardController + - Registrar::DepositsController + - Registrar::DeppController + - Registrar::DomainsController + - Registrar::InvoicesController + - Registrar::KeyrelaysController + - Registrar::PaymentsController + - Registrar::PollsController + - Registrar::SessionsController + - Registrar::XmlConsolesController + - ApplicationHelper + - DefaultFormBuilder + - FormHelper + - FormTagHelper + - Registrant::ApplicationHelper + - Registrar::ApplicationHelper + - DomainDeleteConfirmEmailJob + - DomainDeleteConfirmJob + - DomainDeleteForcedEmailJob + - DomainDeleteJob + - DomainExpireEmailJob + - DomainUpdateConfirmJob + - RegenerateRegistrarWhoisesJob + - RegistrantChangeConfirmEmailJob + - RegistrantChangeExpiredEmailJob + - RegistrantChangeNoticeEmailJob + - UpdateWhoisRecordJob + - ApplicationMailer + - ContactMailer + - DomainDeleteMailer + - DomainExpireMailer + - DomainMailer + - InvoiceMailer + - RegistrantChangeMailer + - Ability + - Account + - AccountActivity + - AdminDomainContact + - AdminUser + - ApiLog::EppLog + - ApiLog::ReppLog + - ApiUser + - BankLink::Base + - BankLink::Request + - BankLink::Response + - BankStatement + - BankTransaction + - Billing::Price + - Billing + - BlockedDomain + - Certificate + - Concerns::Billing::Price::Expirable + - DisableHtml5Validation + - Concerns::Domain::Activatable + - Concerns::Domain::Deletable + - Concerns::Domain::Expirable + - Concerns::Domain::ForceDelete + - EppErrors + - UserEvents + - VersionSession + - Versions::ClassMethods + - Contact + - Counter + - Deposit + - Depp::Contact + - Depp::Domain + - Depp::Keyrelay + - Depp::User + - Directo + - DNS::Zone + - DNS + - Dnskey + - DomainContact + - DomainCron + - DomainMailModel + - DomainStatus + - DomainTransfer + - Epp::Contact + - EppSession + - Invoice + - InvoiceItem + - Keyrelay + - Legacy::Db + - Legacy::Object + - Legacy::ObjectHistory + - Legacy::ObjectState + - Legacy::Registrar + - LegalDocument + - Message + - Nameserver + - Registrant + - RegistrantUser + - Registrar + - ReservedDomain + - Setting + - Soap::Arireg + - Soap::Arireg::NotAvailableError + - TechDomainContact + - User + - WhiteIp + - WhoisRecord + - DomainPresenter + - RegistrantPresenter + - Registrar::DomainListCSVPresenter + - RegistrarPresenter + - RegistrantChange + - DateTimeIso8601Validator + - DomainNameValidator + - DomainNameserverValidator + - DurationIso8601Validator + - ObjectCountValidator + - UniquenessMultiValidator + - PaperSession + - Array + - ActionView::Helpers::FormBuilder + - ActiveModel::Errors + - ActionDispatch::Flash + - Rack::Request + - Ransack::Adapters::ActiveRecord::Context + - DeviseCustomFailure + - EppConstraint + - Builder::XmlMarkup + - VersionGenerator + - Iptable + - SortedCountry + - EmailValidator + - PhoneValidator + - FakeDeppContact + - Features::SessionHelpers + - CapybaraViewMacros + - Matchers::EPP::Code + - Requests::EPPHelpers + - Requests::SessionHelpers +NilCheck: + exclude: + - Admin::AccountActivitiesController#set_default_dates + - Admin::EppLogsController#set_default_dates + - Admin::ReppLogsController#set_default_dates + - ApplicationController#user_log_str + - EppController#requires + - ApplicationHelper#env_style + - Registrant::ApplicationHelper#env_style + - Registrar::ApplicationHelper#env_style + - UserEvents#cr_id + - Depp::Contact#handle_errors + - Directo#self.send_receipts + - DomainMailModel#format + - LegalDocument#val_body_length + - Soap::Arireg#body + - Soap::Arireg#country_code_3 + - Soap::Arireg#initialize + - ActionDispatch::Flash#call +TooManyStatements: + exclude: + - initialize + - Admin::AccountActivitiesController#index + - Admin::AdminUsersController#update + - Admin::BankTransactionsController#create + - Admin::Billing::PricesController#index + - Admin::CertificatesController#create + - Admin::ContactVersionsController#index + - Admin::ContactVersionsController#show + - Admin::ContactsController#index + - Admin::ContactsController#normalize_search_parameters + - Admin::DomainVersionsController#index + - Admin::DomainVersionsController#show + - Admin::DomainsController#index + - Admin::DomainsController#normalize_search_parameters + - Admin::DomainsController#schedule_force_delete + - Admin::DomainsController#update + - Admin::EppLogsController#index + - Admin::InvoicesController#create + - Admin::InvoicesController#forward + - Admin::RegistrarsController#create + - Admin::ReppLogsController#index + - Admin::SessionsController#create + - Admin::SettingsController#casted_settings + - Admin::SettingsController#create + - Admin::WhiteIpsController#create + - Epp::ContactsController#create + - Epp::ContactsController#update + - Epp::ContactsController#validate_create + - Epp::ContactsController#validate_update + - Epp::DomainsController#balance_ok? + - Epp::DomainsController#create + - Epp::DomainsController#delete + - Epp::DomainsController#info + - Epp::DomainsController#renew + - Epp::DomainsController#transfer + - Epp::DomainsController#update + - Epp::DomainsController#validate_create + - Epp::DomainsController#validate_transfer + - Epp::PollsController#req_poll + - Epp::SessionsController#login + - EppController#catch_epp_errors + - EppController#element_count + - EppController#handle_errors + - EppController#optional + - EppController#optional_attribute + - EppController#requires + - EppController#requires_attribute + - EppController#update_epp_session + - EppController#validate_request + - EppController#write_to_epp_log + - Registrant::DomainDeleteConfirmsController#update + - Registrant::DomainUpdateConfirmsController#update + - Registrant::DomainsController#domain_verification_url + - Registrant::DomainsController#domains + - Registrant::DomainsController#download_list + - Registrant::DomainsController#index + - Registrant::DomainsController#normalize_search_parameters + - Registrant::SessionsController#id + - Registrant::SessionsController#mid + - Registrant::SessionsController#mid_status + - Registrar::AccountActivitiesController#index + - Registrar::BaseController#check_ip + - Registrar::ContactsController#download_list + - Registrar::ContactsController#index + - Registrar::ContactsController#normalize_search_parameters + - Registrar::DepositsController#create + - Registrar::DomainsController#destroy + - Registrar::DomainsController#index + - Registrar::DomainsController#normalize_search_parameters + - Registrar::DomainsController#search_contacts + - Registrar::DomainsController#update + - Registrar::InvoicesController#forward + - Registrar::InvoicesController#index + - Registrar::InvoicesController#normalize_search_parameters + - Registrar::KeyrelaysController#create + - Registrar::PaymentsController#back + - Registrar::SessionsController#create + - Registrar::SessionsController#mid + - Registrar::SessionsController#mid_status + - ApplicationHelper#ident_for + - DomainDeleteConfirmJob#run + - DomainDeleteJob#run + - DomainUpdateConfirmJob#run + - UpdateWhoisRecordJob#run + - ApplicationMailer#whitelist_blocked? + - ContactMailer#email_updated + - DomainDeleteMailer#forced + - DomainExpireMailer#expired + - DomainMailer#compose_from + - DomainMailer#pending_delete_rejected_notification + - InvoiceMailer#invoice_email + - RegistrantChangeMailer#confirm + - RegistrantChangeMailer#notice + - Ability#admin + - Ability#epp + - AccountActivity#to_csv + - ApiUser#api_pki_ok? + - ApiUser#registrar_pki_ok? + - BankLink::Request#fields + - BankLink::Response#complete_payment + - BankStatement#import_th6_file + - BankTransaction#autobind_invoice + - BankTransaction#bind_invoice + - BusinessRegistryCache#fetch_by_ident_and_cc + - Certificate#parse_md_from_string + - Certificate#parse_metadata + - Certificate#revoke! + - Certificate#sign! + - Certificate#status + - Concerns::Domain::ForceDelete#cancel_force_delete + - Concerns::Domain::ForceDelete#schedule_force_delete + - EppErrors#add_epp_error + - EppErrors#collect_child_errors + - EppErrors#collect_parent_errors + - EppErrors#construct_epp_errors + - EppErrors#construct_msg_args_and_value + - EppErrors#find_epp_code_and_value + - UserEvents#cr_id + - Versions::ClassMethods#all_versions_for + - Contact#all_domains + - Contact#all_registrant_domains + - Contact#destroy_and_clean + - Contact#destroy_orphans + - Contact#domain_names_with_roles + - Contact#filter_by_states + - Contact#generate_code + - Contact#manage_emails + - Contact#related_domain_descriptions + - Contact#statuses + - Contact#validate_html + - Depp::Contact#construct_check_hash_from_data + - Depp::Contact#construct_create_disclosure_xml + - Depp::Contact#extension_xml + - Depp::Contact#extract_info_disclosure + - Depp::Contact#handle_errors + - Depp::Contact#save + - Depp::Contact#update_attributes + - Depp::Domain#construct_edit_hash + - Depp::Domain#construct_ext_edit_hash + - Depp::Domain#construct_params_from_server_data + - Depp::Domain#create + - Depp::Domain#create_dnskeys_hash + - Depp::Domain#create_nameservers_hash + - Depp::Domain#default_params + - Depp::Domain#transfer + - Depp::User#repp_request + - Depp::User#validate_existance_in_server + - Directo#self.send_monthly_invoices + - Directo#self.send_receipts + - DNS::Zone#self.generate_zonefile + - Dnskey#generate_digest + - Dnskey#generate_ds_key_tag + - Domain#children_log + - Domain#clean_pendings! + - Domain#clean_pendings_lowlevel + - Domain#manage_automatic_statuses + - Domain#name_in_wire_format + - Domain#pending_delete! + - Domain#pending_update! + - Domain#pricelist + - DomainCron#self.clean_expired_pendings + - DomainCron#self.destroy_delete_candidates + - DomainCron#self.start_expire_period + - DomainCron#self.start_redemption_grace_period + - DomainMailModel#domain_info + - DomainTransfer#approve_as_client + - Epp::Contact#add_legal_file_to_new + - Epp::Contact#attrs_from + - Epp::Contact#check_availability + - Epp::Contact#status_list_from + - Epp::Contact#statuses_attrs + - Epp::Contact#update_attributes + - Epp::Domain#add_legal_file_to_new + - Epp::Domain#apply_pending_delete! + - Epp::Domain#apply_pending_update! + - Epp::Domain#approve_transfer + - Epp::Domain#attrs_from + - Epp::Domain#check_availability + - Epp::Domain#copy_and_transfer_contact + - Epp::Domain#destroy_attrs + - Epp::Domain#dnskeys_attrs + - Epp::Domain#domain_contact_attrs_from + - Epp::Domain#domain_status_list_from + - Epp::Domain#domain_statuses_attrs + - Epp::Domain#epp_destroy + - Epp::Domain#keyrelay + - Epp::Domain#manage_permissions + - Epp::Domain#nameservers_attrs + - Epp::Domain#nameservers_from + - Epp::Domain#new_from_epp + - Epp::Domain#query_transfer + - Epp::Domain#reject_transfer + - Epp::Domain#renew + - Epp::Domain#transfer + - Epp::Domain#transfer_domain_contacts + - Epp::Domain#update + - Epp::Domain#validate_contacts + - Invoice#cancel + - Invoice#cancel_overdue_invoices + - Invoice#set_invoice_number + - LegalDocument#save_to_filesystem + - LegalDocument#self.remove_duplicates + - Nameserver#replace_hostname_ends + - RegistrantUser#find_or_create_by_idc_data + - Registrar#generate_iso_11649_reference_no + - Soap::Arireg#associated_businesses + - WhoisRecord#generate_json + - Registrar::DomainListCSVPresenter#domain_to_row + - DomainNameValidator#validate_format + - DomainNameserverValidator#validate_each + - DurationIso8601Validator#validate + - UniquenessMultiValidator#validate_each + - ActionDispatch::Flash#call + - Ransack::Adapters::ActiveRecord::Context#evaluate + - EppConstraint#matches? + - Iptable#counter_update + - fill_form +TooManyInstanceVariables: + exclude: + - Admin::BankStatementsController + - Admin::DomainsController + - Admin::MailTemplatesController + - Epp::ContactsController + - Epp::DomainsController + - EppController + - Registrar::DomainsController + - DomainDeleteMailer + - RegistrantChangeMailer +UtilityFunction: + exclude: + - Admin::Billing::PricesController#durations + - Admin::Billing::PricesController#operation_categories + - Admin::Billing::PricesController#statuses + - Admin::Billing::PricesController#zones + - ApplicationController#user_log_str + - Epp::ContactsController#address_processing? + - EppController#has_attribute + - Registrant::DomainsController#get_confirm_path + - Registrant::SessionsController#find_user_by_idc + - Registrar::ContactsController#address_processing? + - Registrar::PaymentsController#banks + - Registrar::SessionsController#find_user_by_idc + - ApplicationHelper#changing_css_class + - ApplicationHelper#ident_for + - ApplicationHelper#legal_document_types + - ApplicationHelper#plain_username + - ApplicationHelper#unstable_env + - DomainDeleteConfirmEmailJob#logger + - DomainDeleteForcedEmailJob#logger + - DomainExpireEmailJob#run + - RegenerateRegistrarWhoisesJob#run + - RegistrantChangeConfirmEmailJob#logger + - RegistrantChangeExpiredEmailJob#logger + - RegistrantChangeNoticeEmailJob#logger + - UpdateWhoisRecordJob#delete_domain + - UpdateWhoisRecordJob#delete_reserved + - UpdateWhoisRecordJob#update_domain + - UpdateWhoisRecordJob#update_reserved + - ApplicationMailer#format + - ContactMailer#address_processing + - RegistrantChangeMailer#address_processing + - EppErrors#construct_msg_args_and_value + - Versions#user_from_id_role_username + - Depp::Keyrelay#expiry + - Epp::Domain#copy_and_transfer_contact + - Epp::Domain#nameservers_from + - Epp::Domain::DnsSecKeys#mark + - Epp::Domain::DnsSecKeys#xm_copy + - Invoice#pdf + - Soap::Arireg#extract + - Soap::Arireg#items + - Registrar::DomainListCSVPresenter#domain_to_row + - Rack::Request#trusted_proxy? + - PhoneValidator#zeros_only? + - Requests::EPPHelpers#have_code_of + - Requests::EPPHelpers#valid_legal_document +FeatureEnvy: + exclude: + - Admin::SettingsController#casted_settings + - ApplicationHelper#creator_link + - ApplicationHelper#updator_link + - FormHelper#legal_document_field + - FormHelper#money_field + - FormTagHelper#legal_document_field_tag + - DomainDeleteConfirmEmailJob#log + - DomainDeleteConfirmEmailJob#run + - DomainDeleteConfirmJob#raise_errors! + - DomainDeleteConfirmJob#run + - DomainDeleteForcedEmailJob#log + - DomainDeleteForcedEmailJob#run + - DomainDeleteJob#run + - DomainUpdateConfirmJob#raise_errors! + - DomainUpdateConfirmJob#run + - RegistrantChangeConfirmEmailJob#log + - RegistrantChangeConfirmEmailJob#run + - RegistrantChangeExpiredEmailJob#log + - RegistrantChangeExpiredEmailJob#run + - RegistrantChangeNoticeEmailJob#log + - RegistrantChangeNoticeEmailJob#run + - ApplicationMailer#whitelist_blocked? + - DomainExpireMailer#filter_invalid_emails + - AccountActivity#to_csv + - ApiUser#api_pki_ok? + - ApiUser#find_by_idc_data + - ApiUser#registrar_pki_ok? + - BankLink::Base#prepend_size + - BankLink::Request#fields + - BankStatement#parse_th6_row + - BusinessRegistryCache#fetch_by_ident_and_cc + - EppErrors#collect_parent_errors + - Contact#all_domains + - Contact#all_registrant_domains + - Contact#destroy_orphans + - Contact#domain_names_with_roles + - Contact#filter_by_states + - Contact#search_by_query + - Contact#statuses + - Depp::Contact#construct_check_hash_from_data + - Depp::Contact#find_by_id + - Depp::Contact#handle_errors + - Depp::Contact#new_from_params + - Depp::Domain#construct_params_from_server_data + - Depp::Domain#create + - Depp::Domain#create_dnskeys_hash + - Depp::Domain#renew + - Depp::Domain#transfer + - Depp::Keyrelay#keyrelay + - Depp::User#repp_request + - DomainMailModel#format + - Epp::Contact#attach_legal_document + - Epp::Contact#attrs_from + - Epp::Contact#check_availability + - Epp::Contact#ident_attrs + - Epp::Contact#status_list_from + - Epp::Domain#attach_legal_document + - Epp::Domain#attrs_from + - Epp::Domain#destroy_attrs + - Epp::Domain#domain_contact_attrs_from + - Epp::Domain#domain_status_list_from + - Epp::Domain#transfer_domain_contacts + - LegalDocument#calc_checksum + - Nameserver#find_by_hash_params + - RegistrantUser#find_or_create_by_idc_data + - RegistrantUser#find_or_create_by_mid_data + - Registrar#debit! + - Registrar#search_by_query + - ReservedDomain#new_password_for + - Soap::Arireg#country_code_3 + - WhoisRecord#generate_json + - RegistrantPresenter#domain_names_with_roles + - ActionDispatch::Flash#call + - Ransack::Adapters::ActiveRecord::Context#evaluate + - EppConstraint#matches? + - Requests::SessionHelpers#sign_in_to_epp_area +TooManyMethods: + exclude: + - Epp::ContactsController + - Epp::DomainsController + - EppController + - Contact + - Depp::Contact + - Depp::Domain + - Domain + - DomainMailModel + - Epp::Domain + - Invoice + - Registrar +RepeatedConditional: + exclude: + - Epp::DomainsController + - EppController + - Registrar::DomainsController + - DomainMailer + - BankTransaction + - Certificate + - Contact + - Depp::Contact + - Domain + - DomainCron + - Epp::Domain + - Invoice + - RegistrantVerification +ManualDispatch: + exclude: + - EppController#has_attribute + - EppController#validate_request + - ActionView::Helpers::FormBuilder#label + - ActionDispatch::Flash#call + - Ransack::Adapters::ActiveRecord::Context#evaluate +NestedIterators: + exclude: + - Registrar::DomainsController#index + - AccountActivity#to_csv + - EppErrors#collect_child_errors + - EppErrors#find_epp_code_and_value + - Versions::ClassMethods#all_versions_for + - Contact#destroy_orphans + - Contact#to_csv + - Depp::Contact#extract_info_disclosure + - Depp::Domain#create_nameservers_hash + - Directo#self.send_monthly_invoices + - Directo#self.send_receipts + - Domain#name_in_wire_format + - Domain#self.to_csv + - Epp::Domain#nameservers_from + - LegalDocument#self.remove_duplicates + - Nameserver#replace_hostname_ends + - RegistrantPresenter#domain_names_with_roles + - UniquenessMultiValidator#validate_each +UnusedParameters: + exclude: + - Registrar::PollsController#show#@data.css +PrimaDonnaMethod: + exclude: + - DomainDeleteConfirmJob + - DomainUpdateConfirmJob + - Certificate + - Contact + - Domain + - Epp::Domain + - EppSession + - RegistrantVerification + - Registrar +BooleanParameter: + exclude: + - ApplicationMailer#delivery_off? + - Directo#self.send_monthly_invoices + - Epp::Contact#attrs_from + - Epp::Domain#update +ControlParameter: + exclude: + - ApplicationMailer#delivery_off? + - Ability#initialize + - EppErrors#find_epp_code_and_value + - Depp::Contact#extension_xml + - Directo#self.send_monthly_invoices + - Domain#registrant_delete_confirmable? + - Domain#registrant_update_confirmable? + - Epp::Contact#attrs_from + - Epp::Contact#statuses_attrs + - Epp::Domain#authenticate + - Epp::Domain#dnskeys_attrs + - Epp::Domain#domain_contact_attrs_from + - Epp::Domain#domain_statuses_attrs + - Epp::Domain#nameservers_attrs + - Epp::Domain#transfer + - Epp::Domain#update + - Legacy::Object#self.instance_method_already_implemented? + - Legacy::ObjectHistory#self.instance_method_already_implemented? + - RegistrantUser#find_or_create_by_idc_data +LongParameterList: + exclude: + - ContactMailer#email_updated + - DomainDeleteMailer#forced + - RegistrantChangeMailer#confirm + - RegistrantChangeMailer#notice + - EppErrors#add_epp_error + - Contact#all_registrant_domains +DataClump: + exclude: + - DomainMailer + - Epp::Domain +Attribute: + exclude: + - ApiUser#registrar_typeahead + - BankLink::Request#controller + - BankLink::Request#invoice + - BankLink::Request#type + - BankLink::Response#invoice + - BankLink::Response#params + - BankLink::Response#type + - BankStatement#th6_file + - Versions#version_loader + - Contact#deliver_emails + - Contact#domain_transfer + - Contact#domains_present + - Contact#legal_document_id + - Counter#value + - Deposit#amount + - Deposit#description + - Deposit#registrar + - Deposit#registrar_id + - Depp::Contact#city + - Depp::Contact#code + - Depp::Contact#country_code + - Depp::Contact#email + - Depp::Contact#id + - Depp::Contact#ident + - Depp::Contact#ident_country_code + - Depp::Contact#ident_type + - Depp::Contact#legal_document + - Depp::Contact#name + - Depp::Contact#org_name + - Depp::Contact#password + - Depp::Contact#phone + - Depp::Contact#state + - Depp::Contact#statuses + - Depp::Contact#street + - Depp::Contact#zip + - Depp::Domain#current_user + - Depp::Domain#epp_xml + - Depp::Domain#name + - Depp::Keyrelay#current_user + - Depp::Keyrelay#epp_xml + - Depp::User#password + - Depp::User#pki + - Depp::User#tag + - Domain#deliver_emails + - Domain#epp_pending_delete + - Domain#epp_pending_update + - Domain#is_admin + - Domain#legal_document_id + - Domain#registrant_typeahead + - Domain#reserved_pw + - Domain#roles + - Domain#update_me + - DomainContact#value_typeahead + - Epp::Domain#is_renewal + - Epp::Domain#is_transfer + - Invoice#billing_email + - LegalDocument#body + - RegistrantUser#idc_data + - Soap::Arireg#host + - Soap::Arireg#password + - Soap::Arireg#username + - Soap::Arireg#wsdl + - Soap::Arireg::NotAvailableError#json + - User#phone + - PaperSession#session +TooManyConstants: + exclude: + - Certificate + - Contact + - DomainStatus + - DomainTransfer +UncommunicativeParameterName: + exclude: + - Counter#next + - Counter#prev + - Depp::Domain#array_difference + - Dnskey#bin_to_hex + - Dnskey#hex_to_bin + - Dnskey#int_to_hex +UncommunicativeMethodName: + exclude: + - Nameserver#val_ipv4 + - Nameserver#val_ipv6 + - Soap::Arireg#country_code_3 + - WhiteIp#validate_ipv4_and_ipv6 diff --git a/Gemfile b/Gemfile index 9b65f92a9..fe8498495 100644 --- a/Gemfile +++ b/Gemfile @@ -10,7 +10,6 @@ source 'https://rubygems.org' # core gem 'SyslogLogger', '2.0', require: 'syslog/logger' -gem 'hashie-forbidden_attributes', '0.1.1' gem 'iso8601', '0.8.6' # for dates and times gem 'rails', '4.2.7.1' # when update, all initializers eis_custom files needs check/update gem 'rest-client' @@ -60,6 +59,7 @@ gem 'devise', '3.5.4' # authenitcation # rest api gem 'grape', '0.12.0' +gem 'hashie-forbidden_attributes', '0.1.1' # For grape, https://github.com/ruby-grape/grape#rails gem 'jbuilder', '2.2.16' # json api # registry specfic @@ -104,6 +104,7 @@ gem 'activerecord-import', '0.7.0' # for inserting dummy data # for generating pdf gem 'pdfkit', '0.6.2' gem 'jquery-ui-rails', '5.0.5' +gem 'active_model-errors_details' # Backport from Rails 5, https://github.com/rails/rails/pull/18322 group :development do gem 'spring' @@ -119,10 +120,7 @@ group :development, :test do gem 'factory_bot_rails' gem 'capybara' gem 'rspec-rails', '~> 3.6' - gem 'phantomjs-binaries' - gem 'phantomjs' gem 'poltergeist' - gem 'launchy', '2.4.3' # for opening browser automatically # debug gem 'pry', '0.10.1' diff --git a/Gemfile.lock b/Gemfile.lock index f21d432ab..d4f0cf9fd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -79,6 +79,9 @@ GEM erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) + active_model-errors_details (1.3.1) + activemodel (>= 3.2.13, < 5.0.0) + activesupport activejob (4.2.7.1) activesupport (= 4.2.7.1) globalid (>= 0.3.0) @@ -187,7 +190,6 @@ GEM factory_bot_rails (4.8.2) factory_bot (~> 4.8.2) railties (>= 3.0.0) - ffi (1.9.18) figaro (1.1.1) thor (~> 0.14) globalid (0.3.7) @@ -250,8 +252,6 @@ GEM kaminari (0.16.3) actionpack (>= 3.0.0) activesupport (>= 3.0.0) - launchy (2.4.3) - addressable (~> 2.3) libxml-ruby (3.0.0) liquid (3.0.6) loofah (2.0.3) @@ -291,9 +291,6 @@ GEM ast (~> 2.2) pdfkit (0.6.2) pg (0.19.0) - phantomjs (1.9.8.0) - phantomjs-binaries (2.1.1.1) - sys-uname (= 0.9.0) poltergeist (1.14.0) capybara (~> 2.1) cliver (~> 0.3.1) @@ -443,8 +440,6 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sys-uname (0.9.0) - ffi (>= 1.0.0) thor (0.19.4) thread_safe (0.3.6) tilt (1.4.1) @@ -488,6 +483,7 @@ PLATFORMS DEPENDENCIES SyslogLogger (= 2.0) + active_model-errors_details activerecord-import (= 0.7.0) airbrake autodoc @@ -523,7 +519,6 @@ DEPENDENCIES jquery-ui-rails (= 5.0.5) jquery-validation-rails (= 1.13.1) kaminari (= 0.16.3) - launchy (= 2.4.3) liquid (= 3.0.6) mina (= 0.3.1) money-rails @@ -532,8 +527,6 @@ DEPENDENCIES paper_trail! pdfkit (= 0.6.2) pg (= 0.19.0) - phantomjs - phantomjs-binaries poltergeist pry (= 0.10.1) puma diff --git a/app/controllers/admin/contacts_controller.rb b/app/controllers/admin/contacts_controller.rb index e930a511f..6402d09ae 100644 --- a/app/controllers/admin/contacts_controller.rb +++ b/app/controllers/admin/contacts_controller.rb @@ -2,6 +2,7 @@ module Admin class ContactsController < BaseController load_and_authorize_resource before_action :set_contact, only: [:show] + helper_method :ident_types def index params[:q] ||= {} @@ -79,5 +80,9 @@ module Admin params[:q][:created_at_lteq] = ca_cache end + + def ident_types + Contact::Ident.types + end end end diff --git a/app/controllers/epp_controller.rb b/app/controllers/epp_controller.rb index 4a0a0d9d0..8eb6fbc96 100644 --- a/app/controllers/epp_controller.rb +++ b/app/controllers/epp_controller.rb @@ -152,9 +152,6 @@ class EppController < ApplicationController code: '1', msg: 'handle_errors was executed when there were actually no errors' } - # rubocop:disable Rails/Output - puts "FULL MESSAGE: #{obj.errors.full_messages} #{obj.errors.inspect}" if Rails.env.test? - # rubocop: enable Rails/Output end @errors.uniq! diff --git a/app/controllers/registrar/contacts_controller.rb b/app/controllers/registrar/contacts_controller.rb index b927df1a8..4d0de5389 100644 --- a/app/controllers/registrar/contacts_controller.rb +++ b/app/controllers/registrar/contacts_controller.rb @@ -2,6 +2,7 @@ class Registrar class ContactsController < DeppController before_action :init_epp_contact helper_method :address_processing? + helper_method :ident_types def index authorize! :view, Depp::Contact @@ -140,5 +141,9 @@ class Registrar def address_processing? Contact.address_processing? end + + def ident_types + Contact::Ident.types + end end end diff --git a/app/controllers/registrar/sessions_controller.rb b/app/controllers/registrar/sessions_controller.rb index 4ba6501f1..1a8b195ee 100644 --- a/app/controllers/registrar/sessions_controller.rb +++ b/app/controllers/registrar/sessions_controller.rb @@ -53,7 +53,7 @@ class Registrar end def id - @user = ApiUser.find_by_idc_data(request.env['SSL_CLIENT_S_DN']) + @user = ApiUser.find_by_idc_data_and_allowed(request.env['SSL_CLIENT_S_DN'], request.ip) if @user sign_in(@user, event: :authentication) @@ -87,7 +87,11 @@ class Registrar return end - @user = find_user_by_idc(response.user_id_code) + if Setting.registrar_ip_whitelist_enabled + @user = find_user_by_idc_and_allowed(response.user_id_code) + else + @user = find_user_by_idc(response.user_id_code) + end if @user.persisted? session[:user_id_code] = response.user_id_code @@ -112,7 +116,7 @@ class Registrar when 'OUTSTANDING_TRANSACTION' render json: { message: t(:check_your_phone_for_confirmation_code) }, status: :ok when 'USER_AUTHENTICATED' - @user = find_user_by_idc(session[:user_id_code]) + @user = find_user_by_idc_and_allowed(session[:user_id_code]) sign_in @user flash[:notice] = t(:welcome) flash.keep(:notice) @@ -149,6 +153,18 @@ class Registrar ApiUser.find_by(identity_code: idc) || User.new end + def find_user_by_idc_and_allowed(idc) + return User.new unless idc + possible_users = ApiUser.where(identity_code: idc) || User.new + possible_users.each do |selected_user| + if selected_user.registrar.white_ips.registrar_area.include_ip?(request.ip) + return selected_user + end + end + end + + + def check_ip_restriction ip_restriction = Authorization::RestrictedIP.new(request.ip) allowed = ip_restriction.can_access_registrar_area_sign_in_page? diff --git a/app/models/api_user.rb b/app/models/api_user.rb index 5e20db24a..ce32c4045 100644 --- a/app/models/api_user.rb +++ b/app/models/api_user.rb @@ -51,6 +51,20 @@ class ApiUser < User find_by(identity_code: identity_code) end + + def find_by_idc_data_and_allowed(idc_data, ip) + return false if idc_data.blank? + identity_code = idc_data.scan(/serialNumber=(\d+)/).flatten.first + + return false if ip.blank? + possible_users = where(identity_code: identity_code) + possible_users.each do |selected_user| + if selected_user.registrar.white_ips.registrar_area.include_ip?(ip) + return selected_user + end + end + end + end def registrar_typeahead diff --git a/app/models/concerns/epp_errors.rb b/app/models/concerns/epp_errors.rb index cf3824260..7395732ca 100644 --- a/app/models/concerns/epp_errors.rb +++ b/app/models/concerns/epp_errors.rb @@ -11,6 +11,12 @@ module EppErrors epp_errors << collect_child_errors(attr) end + if self.class.reflect_on_aggregation(attr) + aggregation = send(attr) + epp_errors << collect_aggregation_errors(aggregation) + next + end + epp_errors << collect_parent_errors(attr, errors) end @@ -46,6 +52,31 @@ module EppErrors epp_errors end + def collect_aggregation_errors(aggregation) + epp_errors = [] + + aggregation.errors.details.each do |attr, error_details| + error_details.each do |error_detail| + aggregation.class.epp_code_map.each do |epp_code, attr_to_error| + epp_code_found = attr_to_error.any? { |i| i == [attr, error_detail[:error]] } + + next unless epp_code_found + + message = aggregation.errors.generate_message(attr, error_detail[:error], error_detail) + message = aggregation.errors.full_message(attr, message) + + if attr != :base + message = "#{aggregation.model_name.human} #{message.camelize(:lower)}" + end + + epp_errors << { code: epp_code, msg: message } + end + end + end + + epp_errors + end + def find_epp_code_and_value(msg) epp_code_map.each do |code, values| values.each do |x| diff --git a/app/models/contact.rb b/app/models/contact.rb index 732d25e97..61a82ae0a 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -19,27 +19,22 @@ class Contact < ActiveRecord::Base accepts_nested_attributes_for :legal_documents - validates :name, :phone, :email, :ident, :ident_type, presence: true + validates :name, :email, presence: true validates :street, :city, :zip, :country_code, presence: true, if: 'self.class.address_processing?' - validates :phone, format: /\+[0-9]{1,3}\.[0-9]{1,14}?/, phone: true + validates :phone, presence: true, e164: true, phone: true validates :email, format: /@/ validates :email, email_format: { message: :invalid }, if: proc { |c| c.email_changed? } - validates :ident, - format: { with: /\d{4}-\d{2}-\d{2}/, message: :invalid_birthday_format }, - if: proc { |c| c.ident_type == 'birthday' } - validates :ident_country_code, presence: true, if: proc { |c| %w(org priv).include? c.ident_type }, on: :create + validates :code, uniqueness: { message: :epp_id_taken }, format: { with: /\A[\w\-\:\.\_]*\z/i, message: :invalid }, length: { maximum: 100, message: :too_long_contact_code } + validates_associated :identifier - validate :val_ident_type - validate :val_ident_valid_format? validate :validate_html validate :validate_country_code - validate :validate_ident_country_code after_initialize do self.status_notes = {} if status_notes.nil? @@ -49,8 +44,15 @@ class Contact < ActiveRecord::Base before_validation :to_upcase_country_code before_validation :strip_email before_create :generate_auth_info - before_update :manage_emails + + composed_of :identifier, + class_name: 'Contact::Ident', + constructor: proc { |code, type, country_code| Contact::Ident.new(code: code, + type: type, + country_code: country_code) }, + mapping: [%w[ident code], %w[ident_type type], %w[ident_country_code country_code]] + def manage_emails return nil unless email_changed? return nil unless deliver_emails == true @@ -76,12 +78,6 @@ class Contact < ActiveRecord::Base BIRTHDAY = 'birthday'.freeze PASSPORT = 'passport' - IDENT_TYPES = [ - ORG, # Company registry code (or similar) - PRIV, # National idendtification number - BIRTHDAY # Birthday date - ] - attr_accessor :deliver_emails attr_accessor :domain_transfer # hack but solves problem faster @@ -219,10 +215,6 @@ class Contact < ActiveRecord::Base STDOUT << "#{Time.zone.now.utc} - Successfully destroyed #{counter} orphaned contacts\n" unless Rails.env.test? end - def privs - where("ident_type = '#{PRIV}'") - end - def admin_statuses [ SERVER_UPDATE_PROHIBITED, @@ -299,28 +291,6 @@ class Contact < ActiveRecord::Base name || '[no name]' end - def val_ident_type - errors.add(:ident_type, :epp_ident_type_invalid, code: code) if !%w(org priv birthday).include?(ident_type) - end - - def val_ident_valid_format? - case ident_country_code - when 'EE'.freeze - err_msg = "invalid_EE_identity_format#{"_update" if id}".to_sym - case ident_type - when 'priv'.freeze - errors.add(:ident, err_msg) unless Isikukood.new(ident).valid? - when 'org'.freeze - # !%w(1 7 8 9).freeze.include?(ident.first) || - if ident.size != 8 || !(ident =~/\A[0-9]{8}\z/) - errors.add(:ident, err_msg) - end - when BIRTHDAY - errors.add(:ident, err_msg) if id.blank? # only for create action right now. Later for all of them - end - end - end - def validate_html self.class.columns.each do |column| next unless column.type == :string @@ -334,7 +304,6 @@ class Contact < ActiveRecord::Base end end - def org? ident_type == ORG end @@ -344,10 +313,6 @@ class Contact < ActiveRecord::Base !org? end - def birthday? - ident_type == BIRTHDAY - end - def generate_auth_info return if @generate_auth_info_disabled return if auth_info.present? @@ -420,10 +385,6 @@ class Contact < ActiveRecord::Base errors.add(:country_code, :invalid) unless Country.new(country_code) end - def validate_ident_country_code - errors.add(:ident, :invalid_country_code) unless Country.new(ident_country_code) - end - def related_domain_descriptions ActiveSupport::Deprecation.warn('Use #domain_names_with_roles') @@ -568,7 +529,7 @@ class Contact < ActiveRecord::Base return if changes.slice(*(self.class.column_names - ["updated_at", "created_at", "statuses", "status_notes"])).empty? names = related_domain_descriptions.keys - UpdateWhoisRecordJob.enqueue(names, :domain) if names.present? + UpdateWhoisRecordJob.enqueue(names, 'domain') if names.present? end def children_log diff --git a/app/models/contact/ident.rb b/app/models/contact/ident.rb new file mode 100644 index 000000000..d531b833c --- /dev/null +++ b/app/models/contact/ident.rb @@ -0,0 +1,74 @@ +class Contact::Ident + include ActiveModel::Model + + attr_accessor :code + attr_accessor :type + attr_accessor :country_code + + validates :code, presence: true + validates :code, national_id: true, if: :national_id? + validates :code, reg_no: true, if: :reg_no? + validates :code, iso8601: { date_only: true }, if: :birthday? + + validates :type, presence: true, inclusion: { in: proc { types } } + validates :country_code, presence: true, iso31661_alpha2: true + validates_with MismatchValidator + + def self.epp_code_map + { + '2003' => [ + [:code, :blank], + [:type, :blank], + [:country_code, :blank] + ], + '2005' => [ + [:base, :mismatch], + [:code, :invalid_national_id], + [:code, :invalid_reg_no], + [:code, :invalid_iso8601_date], + [:country_code, :invalid_iso31661_alpha2] + ] + } + end + + def self.types + %w[org priv birthday] + end + + def marked_for_destruction? + false + end + + def birthday? + type == 'birthday' + end + + def national_id? + type == 'priv' + end + + def reg_no? + type == 'org' + end + + def country + Country.new(country_code) + end + + def ==(other_ident) + if other_ident.is_a?(self.class) + (code == other_ident.code) && + (type == other_ident.type) && + (country_code == other_ident.country_code) + else + false + end + end + + private + + # https://github.com/rails/rails/issues/1513 + def validation_context=(_value) + ; + end +end diff --git a/app/models/epp/contact.rb b/app/models/epp/contact.rb index 53ebb2ee8..b280ceea6 100644 --- a/app/models/epp/contact.rb +++ b/app/models/epp/contact.rb @@ -109,7 +109,7 @@ class Epp::Contact < Contact end delegate :ident_attr_valid?, to: :class - def epp_code_map # rubocop:disable Metrics/MethodLength + def epp_code_map { '2003' => [ # Required parameter missing [:name, :blank], @@ -124,31 +124,19 @@ class Epp::Contact < Contact [:name, :invalid], [:phone, :invalid], [:email, :invalid], - [:ident, :invalid], - [:ident, :invalid_EE_identity_format], - [:ident, :invalid_EE_identity_format_update], - [:ident, :invalid_birthday_format], - [:ident, :invalid_country_code], [:country_code, :invalid], - [:ident_type, :missing], [:code, :invalid], [:code, :too_long_contact_code] ], '2302' => [ # Object exists [:code, :epp_id_taken] ], - '2304' => [ # Object status prohibits operation - [:ident_type, :epp_ident_type_invalid, { value: { obj: 'code', val: code}, interpolation: {code: code}}] - ], '2305' => [ # Association exists [:domains, :exist] - ], - '2306' => [ # Parameter policy error ] } end - # rubocop:disable Metrics/AbcSize def update_attributes(frame, current_user) return super if frame.blank? at = {}.with_indifferent_access @@ -158,9 +146,6 @@ class Epp::Contact < Contact at[:statuses] = statuses - statuses_attrs(frame.css('rem'), 'rem') + statuses_attrs(frame.css('add'), 'add') end - # legal_frame = frame.css('legalDocument').first - # at[:legal_documents_attributes] = self.class.legal_document_attrs(legal_frame) - if doc = attach_legal_document(Epp::Domain.parse_legal_document_from_frame(frame)) frame.css("legalDocument").first.content = doc.path if doc && doc.persisted? self.legal_document_id = doc.id @@ -168,29 +153,28 @@ class Epp::Contact < Contact self.deliver_emails = true # turn on email delivery for epp + ident_frame = frame.css('ident').first - # allow to update ident code for legacy contacts - if frame.css('ident').first - self.ident_updated_at ||= Time.zone.now # not in use - ident_frame = frame.css('ident').first + # https://github.com/internetee/registry/issues/576 + if ident_frame + if identifier.valid? + submitted_ident = Ident.new(code: ident_frame.text, + type: ident_frame.attr('type'), + country_code: ident_frame.attr('cc')) - if ident_frame && ident_attr_valid?(ident_frame) - org_priv = %w(org priv).freeze - if ident_country_code.blank? && org_priv.include?(ident_type) && org_priv.include?(ident_frame.attr('type')) - at.merge!(ident_country_code: ident_frame.attr('cc'), ident_type: ident_frame.attr('type')) - elsif ident_type == "birthday" && !ident[/\A\d{4}-\d{2}-\d{2}\z/] && (Date.parse(ident) rescue false) - at.merge!(ident: ident_frame.text) - at.merge!(ident_country_code: ident_frame.attr('cc')) if ident_frame.attr('cc').present? - elsif ident_type == "birthday" && ident_country_code.blank? - at.merge!(ident_country_code: ident_frame.attr('cc')) - elsif ident_type.blank? && ident_country_code.blank? - at.merge!(ident_type: ident_frame.attr('type')) - at.merge!(ident_country_code: ident_frame.attr('cc')) if ident_frame.attr('cc').present? - else - throw :epp_error, {code: '2306', msg: I18n.t(:ident_update_error)} - end + report_valid_ident_error if submitted_ident != identifier else - throw :epp_error, {code: '2306', msg: I18n.t(:ident_update_error)} + ident_update_attempt = ident_frame.text.present? && (ident_frame.text != ident) + report_ident_update_error if ident_update_attempt + + identifier = Ident.new(code: ident, + type: ident_frame.attr('type'), + country_code: ident_frame.attr('cc')) + + identifier.validate + + self.identifier = identifier + self.ident_updated_at ||= Time.zone.now end end @@ -199,7 +183,6 @@ class Epp::Contact < Contact super(at) end - # rubocop:enable Metrics/AbcSize def statuses_attrs(frame, action) status_list = status_list_from(frame) @@ -259,4 +242,13 @@ class Epp::Contact < Contact self.legal_document_id = doc.id end + private + + def report_valid_ident_error + throw :epp_error, { code: '2308', msg: I18n.t('epp.contacts.errors.valid_ident') } + end + + def report_ident_update_error + throw :epp_error, { code: '2308', msg: I18n.t('epp.contacts.errors.ident_update') } + end end diff --git a/app/models/epp/response.rb b/app/models/epp/response.rb new file mode 100644 index 000000000..c9a5d8bb4 --- /dev/null +++ b/app/models/epp/response.rb @@ -0,0 +1,22 @@ +module EPP + class Response + attr_accessor :results + + def self.from_xml(xml) + xml_doc = Nokogiri::XML(xml) + response = new + + result_elements = xml_doc.css('result') + + result_elements.each do |result_element| + response.results << Result.new(result_element[:code].to_s, result_element.text.strip) + end + + response + end + + def initialize + @results = [] + end + end +end diff --git a/app/models/epp/response/result.rb b/app/models/epp/response/result.rb new file mode 100644 index 000000000..5c870c830 --- /dev/null +++ b/app/models/epp/response/result.rb @@ -0,0 +1,28 @@ +module EPP + class Response + class Result + CODE_TO_TYPE = { + '1000' => :success, + '1001' => :success_pending, + '1300' => :success_empty_queue, + '1301' => :success_dequeue, + '2001' => :syntax_error, + '2003' => :required_param_missing, + '2005' => :param_syntax_error, + '2308' => :data_management_policy_violation + } + + attr_accessor :code + attr_accessor :message + + def initialize(code, message) + @code = code + @message = message + end + + def self.codes + CODE_TO_TYPE + end + end + end +end diff --git a/app/models/registrar.rb b/app/models/registrar.rb index 97ecfa32a..b410a1c76 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -9,7 +9,6 @@ class Registrar < ActiveRecord::Base has_many :accounts has_many :nameservers, through: :domains has_many :whois_records - has_many :priv_contacts, -> { privs }, class_name: 'Contact' has_many :white_ips, dependent: :destroy delegate :balance, to: :cash_account, allow_nil: true diff --git a/app/validators/contact/ident/mismatch_validator.rb b/app/validators/contact/ident/mismatch_validator.rb new file mode 100644 index 000000000..d20bb82cf --- /dev/null +++ b/app/validators/contact/ident/mismatch_validator.rb @@ -0,0 +1,20 @@ +class Contact::Ident::MismatchValidator < ActiveModel::Validator + Mismatch = Struct.new(:type, :country) + + def self.mismatches + [ + Mismatch.new('birthday', Country.new('EE')), + ] + end + + def validate(record) + record.errors.add(:base, :mismatch, type: record.type, country: record.country) if mismatched?(record) + end + + private + + def mismatched?(record) + mismatch = Mismatch.new(record.type, record.country) + self.class.mismatches.include?(mismatch) + end +end diff --git a/app/validators/contact/ident/national_id_validator.rb b/app/validators/contact/ident/national_id_validator.rb new file mode 100644 index 000000000..2fcf019b1 --- /dev/null +++ b/app/validators/contact/ident/national_id_validator.rb @@ -0,0 +1,22 @@ +class Contact::Ident::NationalIdValidator < ActiveModel::EachValidator + def self.country_specific_validations + { + Country.new('EE') => proc { |code| Isikukood.new(code).valid? }, + } + end + + def validate_each(record, attribute, value) + validation = validation_for(record.country) + + return unless validation + + valid = validation.call(value) + record.errors.add(attribute, :invalid_national_id, country: record.country) unless valid + end + + private + + def validation_for(country) + self.class.country_specific_validations[country] + end +end diff --git a/app/validators/contact/ident/reg_no_validator.rb b/app/validators/contact/ident/reg_no_validator.rb new file mode 100644 index 000000000..611d13301 --- /dev/null +++ b/app/validators/contact/ident/reg_no_validator.rb @@ -0,0 +1,21 @@ +class Contact::Ident::RegNoValidator < ActiveModel::EachValidator + def self.country_specific_formats + { + Country.new('EE') => /\A[0-9]{8}\z/, + } + end + + def validate_each(record, attribute, value) + format = format_for(record.country) + + return unless format + + record.errors.add(attribute, :invalid_reg_no, country: record.country) unless value =~ format + end + + private + + def format_for(country) + self.class.country_specific_formats[country] + end +end diff --git a/app/views/admin/contacts/index.haml b/app/views/admin/contacts/index.haml index d9f60c13b..cc80ac744 100644 --- a/app/views/admin/contacts/index.haml +++ b/app/views/admin/contacts/index.haml @@ -19,7 +19,7 @@ .col-md-3 .form-group = label_tag t(:ident_type) - = select_tag '[q][ident_type_eq]', options_for_select(Contact::IDENT_TYPES, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' } + = select_tag '[q][ident_type_eq]', options_for_select(ident_types, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' } .row .col-md-3 .form-group @@ -75,7 +75,7 @@ .row .col-md-12 .table-responsive - %table.table.table-hover.table-bordered.table-condensed + %table.table.table-hover.table-bordered.table-condensed.contacts %thead %tr %th{class: 'col-xs-2'} diff --git a/app/views/registrar/contacts/index.haml b/app/views/registrar/contacts/index.haml index fd4672350..5f5a667c0 100644 --- a/app/views/registrar/contacts/index.haml +++ b/app/views/registrar/contacts/index.haml @@ -21,7 +21,7 @@ .col-md-3 .form-group = label_tag t(:ident_type) - = select_tag '[q][ident_type_eq]', options_for_select(Contact::IDENT_TYPES, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' } + = select_tag '[q][ident_type_eq]', options_for_select(ident_types, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' } .row .col-md-3 .form-group @@ -85,7 +85,7 @@ .row .col-md-12 .table-responsive - %table.table.table-hover.table-bordered.table-condensed + %table.table.table-hover.table-bordered.table-condensed.contacts %thead %tr %th{class: 'col-xs-2'} diff --git a/config/application-example.yml b/config/application-example.yml index f54557828..caedd83cc 100644 --- a/config/application-example.yml +++ b/config/application-example.yml @@ -129,3 +129,5 @@ payments_lhv_seller_private: 'kaupmees_priv.pem' payments_lhv_seller_account: 'testvpos' user_session_timeout: '3600' # 1 hour +secure_session_cookies: 'false' # true|false +same_site_session_cookies: 'false' # false|strict|lax diff --git a/config/initializers/eis_custom_active_model.rb b/config/initializers/eis_custom_active_model.rb deleted file mode 100644 index ba5f29b06..000000000 --- a/config/initializers/eis_custom_active_model.rb +++ /dev/null @@ -1,20 +0,0 @@ -# Log all active model user errors -# rubocop: disable Lint/AssignmentInCondition -# rubocop: disable Style/SignalException -module ActiveModel - class Errors - def add(attribute, message = :invalid, options = {}) - message = normalize_message(attribute, message, options) - if exception = options[:strict] - exception = ActiveModel::StrictValidationFailed if exception == true - raise exception, full_message(attribute, message) - end - - # CUSTOM logging - Rails.logger.info "USER MSG: ACTIVEMODEL: #{@base.try(:class)} [#{attribute}] #{message}" if message.present? - # END of CUSTOM logging - - self[attribute] << message - end - end -end diff --git a/config/initializers/eis_custom_flash.rb b/config/initializers/eis_custom_flash.rb deleted file mode 100644 index 4e4d359b5..000000000 --- a/config/initializers/eis_custom_flash.rb +++ /dev/null @@ -1,31 +0,0 @@ -# Log all flash messages -# rubocop: disable Metrics/CyclomaticComplexity -# rubocop: disable Metrics/LineLength -module ActionDispatch - class Flash - # rubocop: disable Metrics/PerceivedComplexity - # rubocop: disable Style/MultilineOperationIndentation - def call(env) - @app.call(env) - ensure - session = Request::Session.find(env) || {} - flash_hash = env[KEY] - - if flash_hash && (flash_hash.present? || session.key?('flash')) - session["flash"] = flash_hash.to_session_value - - # EIS custom logging - Rails.logger.info "USER MSG: FLASH: #{session['flash']['flashes'].inspect}" if session['flash'] - # END OF EIS custom logging - - env[KEY] = flash_hash.dup - end - - if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?) - session.key?('flash') && session['flash'].nil? - session.delete('flash') - end - end - end -end - diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 480996245..d063123a4 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,3 +1,9 @@ # Be sure to restart your server when you modify this file. -Rails.application.config.session_store :cookie_store, key: '_registry_session' +secure_cookies = ENV['secure_session_cookies'] == 'true' +same_site_cookies = ENV['same_site_session_cookies'] != 'false' ? ENV['same_site_session_cookies'].to_sym : false + +Rails.application.config.session_store :cookie_store, + key: '_registry_session', + secure: secure_cookies, + same_site: same_site_cookies diff --git a/config/locales/contacts.en.yml b/config/locales/contacts.en.yml index 2061d2abd..0c3c1fe29 100644 --- a/config/locales/contacts.en.yml +++ b/config/locales/contacts.en.yml @@ -9,5 +9,20 @@ en: models: contact: attributes: + code: + blank: "Required parameter missing - code" + too_long_contact_code: "Contact code is too long, max 100 characters" + name: + blank: "Required parameter missing - name" + phone: + blank: "Required parameter missing - phone" + invalid: "Phone nr is invalid" + email: + blank: "Required parameter missing - email" + invalid: "Email is invalid" + domains: + exist: 'Object association prohibits operation' + statuses: + not_uniq: 'not uniq' country_code: invalid: Country code is not valid, should be in ISO_3166-1 alpha 2 format diff --git a/config/locales/en.yml b/config/locales/en.yml index ef8762917..0a4a83c98 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -34,33 +34,6 @@ en: activerecord: errors: models: - contact: - attributes: - code: - blank: "Required parameter missing - code" - too_long_contact_code: "Contact code is too long, max 100 characters" - name: - blank: "Required parameter missing - name" - phone: - blank: "Required parameter missing - phone" - invalid: "Phone nr is invalid" - email: - blank: "Required parameter missing - email" - invalid: "Email is invalid" - ident: - blank: "Required parameter missing - ident" - invalid_EE_identity_format: "Ident not in valid Estonian identity format." - invalid_EE_identity_format_update: "Ident not in valid Estonian identity format. Please create new contact" - invalid_birthday_format: "Ident not in valid birthady format, should be YYYY-MM-DD" - invalid_country_code: "Ident country code is not valid, should be in ISO_3166-1 alpha 2 format" - ident_type: - ident_type_invalid: 'Ident type is invalid' - epp_ident_type_invalid: 'Object status prohibits operation: ident_type of contact %{code} is invalid' - domains: - exist: 'Object association prohibits operation' - statuses: - not_uniq: 'not uniq' - epp_domain: &epp_domain_ar_attributes attributes: base: @@ -262,6 +235,8 @@ en: unimplemented_command: 'Unimplemented command' domain_exists_but_belongs_to_other_registrar: 'Domain exists but belongs to other registrar' required_ident_attribute_missing: "Required ident attribute missing: %{key}" + invalid_iso31661_alpha2: does not conform to ISO 3166-1 alpha-2 standard + invalid_iso8601_date: has invalid date format YYYY-MM-DD (ISO 8601) code: 'Code' action: 'Action' @@ -487,7 +462,6 @@ en: crt_revoked: 'CRT (revoked)' contact_org_error: 'Parameter value policy error. Org must be blank' contact_fax_error: 'Parameter value policy error. Fax must be blank' - ident_update_error: 'Parameter value policy error. Update of ident data not allowed [ident]' invoices: 'Invoices' no_such_user: 'No such user' phone_no: 'Phone number' diff --git a/config/locales/epp/contacts.en.yml b/config/locales/epp/contacts.en.yml index a669310ab..fe4ed7ccf 100644 --- a/config/locales/epp/contacts.en.yml +++ b/config/locales/epp/contacts.en.yml @@ -3,3 +3,11 @@ en: contacts: completed: Command completed successfully completed_without_address: Command completed successfully; Postal address data discarded + + errors: + valid_ident: >- + Ident update is not allowed. + Consider creating new contact object + ident_update: >- + Only ident type and country can be updated in case of invalid ident. + Please create new contact object to update ident code diff --git a/config/locales/idents.yml b/config/locales/idents.yml new file mode 100644 index 000000000..33b935833 --- /dev/null +++ b/config/locales/idents.yml @@ -0,0 +1,11 @@ +en: + activemodel: + errors: + models: + contact/ident: + attributes: + base: + mismatch: Ident type "%{type}" is invalid for %{country} + code: + invalid_national_id: does not conform to national identification number format of %{country} + invalid_reg_no: does not conform to registration number format of %{country} diff --git a/doc/docker/apache2/epp-tester.conf b/doc/docker/apache2/epp-tester.conf deleted file mode 100644 index 140785385..000000000 --- a/doc/docker/apache2/epp-tester.conf +++ /dev/null @@ -1,18 +0,0 @@ -Listen 8888 - - ServerName registry.gitlab.eu - ServerAdmin info@gitlab.eu - - PassengerEnabled on - RailsEnv production - DocumentRoot /home/app/epp-tester/current/public - - ErrorLog /var/log/apache2/epp-tester.error.log - LogLevel info ssl:warn - CustomLog /var/log/apache2/epp-tester.access.log combined - - - Require all granted - Options -MultiViews - - diff --git a/doc/docker/apache2/epp.conf b/doc/docker/apache2/epp.conf deleted file mode 100644 index 33ef057aa..000000000 --- a/doc/docker/apache2/epp.conf +++ /dev/null @@ -1,21 +0,0 @@ - - Listen 700 - - SSLEngine on - SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL - SSLCertificateFile /etc/apache2/ssl/apache.crt - SSLCertificateKeyFile /etc/apache2/ssl/apache.key - - SSLVerifyClient optional_no_ca - - EPPEngine On - EPPCommandRoot /proxy/command - EPPSessionRoot /proxy/session - EPPErrorRoot /proxy/error - - ProxyPass /proxy/ http://localhost:80/epp/ - - EPPAuthURI implicit - EPPReturncodeHeader X-EPP-Returncode - - diff --git a/doc/docker/apache2/registry-test.conf b/doc/docker/apache2/registry-test.conf deleted file mode 100644 index dc4b0cc26..000000000 --- a/doc/docker/apache2/registry-test.conf +++ /dev/null @@ -1,39 +0,0 @@ -Listen 81 - - ServerAdmin info@gitlab.eu - - PassengerEnabled on - RailsEnv test - DocumentRoot /home/app/registry-test/public - - ErrorLog /var/log/apache2/registry-test.error.log - LogLevel info ssl:warn - CustomLog /var/log/apache2/registry-test.access.log combined - - - Require all granted - Options -MultiViews - - - - - Listen 701 - - SSLEngine on - SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL - SSLCertificateFile /etc/apache2/ssl/apache.crt - SSLCertificateKeyFile /etc/apache2/ssl/apache.key - - SSLVerifyClient optional_no_ca - - EPPEngine On - EPPCommandRoot /proxy/command - EPPSessionRoot /proxy/session - EPPErrorRoot /proxy/error - - ProxyPass /proxy/ http://localhost:81/epp/ - - EPPAuthURI implicit - EPPReturncodeHeader X-EPP-Returncode - - diff --git a/doc/docker/apache2/registry.conf b/doc/docker/apache2/registry.conf deleted file mode 100644 index b01ec745d..000000000 --- a/doc/docker/apache2/registry.conf +++ /dev/null @@ -1,17 +0,0 @@ - - ServerName registry.gitlab.eu - ServerAdmin info@gitlab.eu - - PassengerEnabled on - RailsEnv production - DocumentRoot /home/app/registry/current/public - - ErrorLog /var/log/apache2/registry.error.log - LogLevel info ssl:warn - CustomLog /var/log/apache2/registry.access.log combined - - - Require all granted - Options -MultiViews - - diff --git a/doc/docker/ssh/authorized_keys b/doc/docker/ssh/authorized_keys deleted file mode 100755 index 9266ca452..000000000 --- a/doc/docker/ssh/authorized_keys +++ /dev/null @@ -1,3 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAz+n4Sln0oxme+9hyrgPud9k0C00Nm0T2YufHcQUAdtJssCfeKp2qo/gy0LmOXTB8efyavFn4NW2GZs8gxJ0BV5GoHLmnERAWDOi/wg3KLl4r/ei+HQX6Po/V7WOMHWzKPSSGtqW7cZc1g0y2ci571ZUmgEBoGoGPfoQToGEn2yV4hQmHIjbwtfNNCHx/i12DCoJnD+3cIvhHf4FbZRBW9Wu0I24iqLcxLOAwGWVsnzi0OqN+rj3DenPQfjcPhSsmTu+8mn2AIwMxWeLZSslEYfyBeo9dLBntj3dnxWpw/MJEfMmWgWKGqMaVGB731ZWDOrRrzgl5+s24YBv9LyYWyQ== -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXF8qkkQg8We6c2eCRQTuQUAffuDcYijlnVNAH0V7eUMxKC/9aPIhHaM9JVY4exXDVEQOK0+KsF6twTtewK8XBFfHXcOV3k+11KOJ1LsfphQIbwS9Qufw2maxCWJHxQwKGViGLqePuecQhfQ3UAVXZ1ZO7qGrLB9JBlRimbItJsG3F2o1T7pJAMucf+zCv5KmMeeddDyhAg2ufQHnuPKIMAgr4XH/TD4mg5tqORXCdk/2apuqUz35WqAyRNt/J66bTJOJ39QJv50cyT6/Bb74MNfJSejsM5EUnKF4Nq7edR8F8tlnXmL/wvvVs81oHywCnMqP8eEISLumy1nhNpgbn martin@gitlab.eu -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC13V94raEKiCzg4sACsIFxiHPcRSUryUHxXpcyHMi7OJvTtszOPR3hZnB36c0NxnznD0t3rH2n5vIX+tBmX+JND7bvM+YKgTGcGN+HvS08nSsvwHLie/UAHkWy/4xFvyKnq8MIZtYxkPdIGph6hFMr5LljJu05V08hZF09HutBsjXw5wmZRUJoD/Jl0FO/pf6WxH1VHjhz0kGuM8VREU2SC8uzV1AIZ86zsaxJld1m0doyt+arnJkPYgjXHHpu/IWzIHYjbVo5W8JmYagDCYxaPHN7EesHAEzFi1LDtq1aIrqWrczKaJGSryxSba6pnYiK69MTojF/SAXMsJ1u5q1P andres.kesk@gmail.com diff --git a/doc/epp/contact.md b/doc/epp/contact.md index 3ec314b9e..b1f00aedf 100644 --- a/doc/epp/contact.md +++ b/doc/epp/contact.md @@ -36,7 +36,7 @@ More info: https://en.wikipedia.org/wiki/Latin_script_in_Unicode 1 E-mail 1 1 Attribute: xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd" - 1 Contact identificator + 1 Identifier Attribute: "type" "org" # Business registry code "priv" # National identification number @@ -73,7 +73,7 @@ More info: https://en.wikipedia.org/wiki/Latin_script_in_Unicode 1 Contact password. Attribute: roid="String" 0-1 0-1 Attribute: xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd" - 0-1 Contact identificator + 0-1 Identifier Attribute: "type" "org" # Business registry code "priv" # National identification number diff --git a/doc/models_brief.svg b/doc/models_brief.svg index 76dd9a83f..22d63cfe7 100644 --- a/doc/models_brief.svg +++ b/doc/models_brief.svg @@ -1031,25 +1031,11 @@ -Registrar->Contact - - - -priv_contacts - - Registrar->Contact - -Registrar->Contact - - - -priv_contacts - Registrar->Domain diff --git a/doc/models_complete.svg b/doc/models_complete.svg index 3c64e4a34..a4b16517f 100644 --- a/doc/models_complete.svg +++ b/doc/models_complete.svg @@ -1642,25 +1642,11 @@ -Registrar->Contact - - - -priv_contacts - - Registrar->Contact - -Registrar->Contact - - - -priv_contacts - Registrar->Domain diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake index 2bfb5c5ae..c624b3c95 100644 --- a/lib/tasks/dev.rake +++ b/lib/tasks/dev.rake @@ -173,6 +173,8 @@ namespace :dev do end end + Setting.api_ip_whitelist_enabled = false + Setting.address_processing = false Setting.registrar_ip_whitelist_enabled = false ActiveRecord::Base.transaction do diff --git a/lib/validators/e164_validator.rb b/lib/validators/e164_validator.rb new file mode 100644 index 000000000..e5807e585 --- /dev/null +++ b/lib/validators/e164_validator.rb @@ -0,0 +1,12 @@ +class E164Validator < ActiveModel::EachValidator + def validate_each(record, attribute, _value) + length_validator = ActiveModel::Validations:: + LengthValidator.new(maximum: 17, attributes: attribute) + length_validator.validate(record) + + format_validator = ActiveModel::Validations:: + FormatValidator.new(with: /\+[0-9]{1,3}\.[0-9]{1,14}?/, + attributes: attribute) + format_validator.validate(record) + end +end diff --git a/lib/validators/iso31661_alpha2_validator.rb b/lib/validators/iso31661_alpha2_validator.rb new file mode 100644 index 000000000..6535e11d4 --- /dev/null +++ b/lib/validators/iso31661_alpha2_validator.rb @@ -0,0 +1,11 @@ +class Iso31661Alpha2Validator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + record.errors.add(attribute, :invalid_iso31661_alpha2) unless valid_country_code?(value) + end + + private + + def valid_country_code?(country_code) + Country.new(country_code) + end +end diff --git a/lib/validators/iso8601_validator.rb b/lib/validators/iso8601_validator.rb new file mode 100644 index 000000000..bbcf63798 --- /dev/null +++ b/lib/validators/iso8601_validator.rb @@ -0,0 +1,13 @@ +class Iso8601Validator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + if options[:date_only] + record.errors.add(attribute, :invalid_iso8601_date) unless value =~ date_format + end + end + + private + + def date_format + /\d{4}-\d{2}-\d{2}/ + end +end diff --git a/lib/validators/phone_validator.rb b/lib/validators/phone_validator.rb index d0bf94f1b..a2a91e9f7 100644 --- a/lib/validators/phone_validator.rb +++ b/lib/validators/phone_validator.rb @@ -2,11 +2,11 @@ class PhoneValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) return if record.errors[:phone].any? - splitted_phone = value.split('.') - country_code = splitted_phone.first - phone_number = splitted_phone.second + phone_parts = value.split('.') + country_code = phone_parts.first + subscriber_no = phone_parts.second - if zeros_only?(country_code) || zeros_only?(phone_number) + if zeros_only?(country_code) || zeros_only?(subscriber_no) record.errors.add(attribute, :invalid) end end diff --git a/spec/features/admin/contacts/list_spec.rb b/spec/features/admin/contacts/list_spec.rb new file mode 100644 index 000000000..80312fb17 --- /dev/null +++ b/spec/features/admin/contacts/list_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +RSpec.feature 'Contact list', settings: false do + background do + sign_in_to_admin_area + end + + it 'is visible' do + visit admin_contacts_path + expect(page).to have_css('.contacts') + end +end diff --git a/spec/features/registrar/contacts/list_spec.rb b/spec/features/registrar/contacts/list_spec.rb new file mode 100644 index 000000000..96f1f2c98 --- /dev/null +++ b/spec/features/registrar/contacts/list_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +RSpec.feature 'Contact list', settings: false do + given!(:registrar) { create(:registrar) } + given!(:contact) { create(:contact, registrar: registrar) } + + background do + sign_in_to_registrar_area(user: create(:api_user_with_unlimited_balance, registrar: registrar)) + end + + it 'is visible' do + visit registrar_contacts_path + expect(page).to have_css('.contacts') + end +end diff --git a/spec/lib/validators/e164.rb b/spec/lib/validators/e164.rb new file mode 100644 index 000000000..bfb4914a3 --- /dev/null +++ b/spec/lib/validators/e164.rb @@ -0,0 +1,29 @@ +# https://en.wikipedia.org/wiki/E.164 + +RSpec.shared_examples 'e164' do + describe 'validation' do + it 'rejects invalid format' do + model.send("#{attribute}=", '+.1') + model.validate + expect(model.errors).to be_added(attribute, :invalid) + end + + it 'rejects longer than max length' do + model.send("#{attribute}=", '1' * 18) + model.validate + expect(model.errors).to be_added(attribute, :too_long, count: 17) + end + + it 'accepts valid format' do + model.send("#{attribute}=", '+123.4') + model.validate + expect(model.errors).to_not be_added(attribute, :invalid) + end + + it 'accepts max length' do + model.send("#{attribute}=", '1' * 17) + model.validate + expect(model.errors).to_not be_added(attribute, :too_long, count: 17) + end + end +end diff --git a/spec/lib/validators/iso31661_alpha2.rb b/spec/lib/validators/iso31661_alpha2.rb new file mode 100644 index 000000000..618a68cfb --- /dev/null +++ b/spec/lib/validators/iso31661_alpha2.rb @@ -0,0 +1,17 @@ +# https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 + +RSpec.shared_examples 'iso31661_alpha2' do + describe 'validation' do + it 'rejects invalid' do + model.send("#{attribute}=", 'invalid') + model.validate + expect(model.errors).to be_added(attribute, :invalid_iso31661_alpha2) + end + + it 'accepts valid' do + model.send("#{attribute}=", 'US') + model.validate + expect(model.errors).to_not be_added(attribute, :invalid_iso31661_alpha2) + end + end +end diff --git a/spec/lib/validators/iso8601.rb b/spec/lib/validators/iso8601.rb new file mode 100644 index 000000000..78d8f2c4a --- /dev/null +++ b/spec/lib/validators/iso8601.rb @@ -0,0 +1,17 @@ +# https://en.wikipedia.org/wiki/ISO_8601 + +RSpec.shared_examples 'iso8601' do + describe 'validation' do + it 'rejects invalid' do + model.send("#{attribute}=", '2010-07-0') + model.validate + expect(model.errors).to be_added(attribute, :invalid_iso8601_date) + end + + it 'accepts valid' do + model.send("#{attribute}=", '2010-07-05') + model.validate + expect(model.errors).to_not be_added(attribute, :invalid_iso8601_date) + end + end +end diff --git a/spec/models/contact/contact_phone_spec.rb b/spec/models/contact/contact_phone_spec.rb new file mode 100644 index 000000000..cc1ecbec0 --- /dev/null +++ b/spec/models/contact/contact_phone_spec.rb @@ -0,0 +1,33 @@ +require 'rails_helper' +require 'lib/validators/e164' + +RSpec.describe Contact do + let(:contact) { described_class.new } + + describe 'phone', db: false do + it_behaves_like 'e164' do + let(:model) { contact } + let(:attribute) { :phone } + end + end + + describe 'phone validation', db: false do + it 'rejects absent' do + contact.phone = nil + contact.validate + expect(contact.errors).to be_added(:phone, :blank) + end + + it 'rejects all zeros in country code' do + contact.phone = '+000.1' + contact.validate + expect(contact.errors).to be_added(:phone, :invalid) + end + + it 'rejects all zeros in subscriber number' do + contact.phone = '+123.0' + contact.validate + expect(contact.errors).to be_added(:phone, :invalid) + end + end +end diff --git a/spec/models/contact/ident_spec.rb b/spec/models/contact/ident_spec.rb new file mode 100644 index 000000000..d26f76d0f --- /dev/null +++ b/spec/models/contact/ident_spec.rb @@ -0,0 +1,227 @@ +require 'active_model' +require 'lib/validators/iso31661_alpha2' +require 'lib/validators/iso8601' + +RSpec.describe Contact::Ident, db: false do + let(:ident) { described_class.new } + + describe 'country code' do + it_behaves_like 'iso31661_alpha2' do + let(:model) { ident } + let(:attribute) { :country_code } + end + end + + describe 'code validation' do + it 'rejects absent' do + ident.code = nil + ident.validate + expect(ident.errors).to be_added(:code, :blank) + end + + context 'when type is :birthday' do + let(:ident) { described_class.new(type: 'birthday') } + + it_behaves_like 'iso8601' do + let(:model) { ident } + let(:attribute) { :code } + end + end + + context 'when type is not :birthday' do + let(:ident) { described_class.new(type: 'priv') } + + it 'accepts any' do + ident.code = '%123456789%' + ident.validate + expect(ident.errors).to_not include(:code) + end + end + + context 'when country code is EE' do + context 'when type is :priv' do + let(:ident) { described_class.new(country_code: 'EE', type: 'priv') } + + it 'rejects invalid' do + ident.code = 'invalid' + ident.validate + expect(ident.errors).to be_added(:code, :invalid_national_id, country: 'Estonia') + end + + it 'accepts valid' do + ident.code = '47101010033' + ident.validate + expect(ident.errors).to_not be_added(:code, :invalid_national_id, country: 'Estonia') + end + end + + context 'when ident type is :org' do + let(:ident) { described_class.new(country_code: 'EE', type: 'org') } + + it 'rejects invalid' do + ident.code = '1' * 7 + ident.validate + expect(ident.errors).to be_added(:code, :invalid_reg_no, country: 'Estonia') + end + + it 'accepts valid length' do + ident.code = '1' * 8 + ident.validate + expect(ident.errors).to_not be_added(:code, :invalid_reg_no, country: 'Estonia') + end + end + end + + context 'when ident country code is not EE' do + let(:ident) { described_class.new(country_code: 'US') } + + it 'accepts any' do + ident.code = 'test-123456789' + ident.validate + expect(ident.errors).to_not include(:code) + end + end + + it 'translates :invalid_national_id error message' do + expect(ident.errors.generate_message(:code, :invalid_national_id, country: 'Germany')) + .to eq('does not conform to national identification number format of Germany') + end + + it 'translates :invalid_reg_no error message' do + expect(ident.errors.generate_message(:code, :invalid_reg_no, country: 'Germany')) + .to eq('does not conform to registration number format of Germany') + end + end + + describe 'type validation' do + before do + allow(described_class).to receive(:types).and_return(%w(valid)) + end + + it 'rejects absent' do + ident.type = nil + ident.validate + expect(ident.errors).to be_added(:type, :blank) + end + + it 'rejects invalid' do + ident.type = 'invalid' + ident.validate + expect(ident.errors).to be_added(:type, :inclusion) + end + + it 'accepts valid' do + ident.type = 'valid' + ident.validate + expect(ident.errors).to_not be_added(:type, :inclusion) + end + end + + describe 'country code validation' do + it 'rejects absent' do + ident.country_code = nil + ident.validate + expect(ident.errors).to be_added(:country_code, :blank) + end + end + + describe 'mismatch validation' do + let(:ident) { described_class.new(type: 'test', country_code: 'DE') } + + before do + mismatches = [Contact::Ident::MismatchValidator::Mismatch.new('test', Country.new('DE'))] + allow(Contact::Ident::MismatchValidator).to receive(:mismatches).and_return(mismatches) + end + + it 'rejects mismatched' do + ident.validate + expect(ident.errors).to be_added(:base, :mismatch, type: 'test', country: 'Germany') + end + + it 'accepts matched' do + ident.validate + expect(ident.errors).to_not be_added(:base, :mismatch, type: 'another-test', country: 'Germany') + end + + it 'translates :mismatch error message' do + expect(ident.errors.generate_message(:base, :mismatch, type: 'test', country: 'Germany')) + .to eq('Ident type "test" is invalid for Germany') + end + end + + describe '::types' do + it 'returns types' do + types = %w[ + org + priv + birthday + ] + + expect(described_class.types).to eq(types) + end + end + + describe '#birthday?' do + context 'when type is birthday' do + subject(:ident) { described_class.new(type: 'birthday') } + it { is_expected.to be_birthday } + end + + context 'when type is not birthday' do + subject(:ident) { described_class.new(type: 'priv') } + it { is_expected.to_not be_birthday } + end + end + + describe '#national_id?' do + context 'when type is priv' do + subject(:ident) { described_class.new(type: 'priv') } + it { is_expected.to be_national_id } + end + + context 'when type is not' do + subject(:ident) { described_class.new(type: 'org') } + it { is_expected.to_not be_national_id } + end + end + + describe '#reg_no?' do + context 'when type is birthday' do + subject(:ident) { described_class.new(type: 'org') } + it { is_expected.to be_reg_no } + end + + context 'when type is not birthday' do + subject(:ident) { described_class.new(type: 'priv') } + it { is_expected.to_not be_reg_no } + end + end + + describe '#country' do + let(:ident) { described_class.new(country_code: 'US') } + + it 'returns country' do + expect(ident.country).to eq(Country.new('US')) + end + end + + describe '#==' do + let(:ident) { described_class.new(code: 'test', type: 'test', country_code: 'US') } + + context 'when code, type and country code are the same' do + let(:another_ident) { described_class.new(code: 'test', type: 'test', country_code: 'US') } + + it 'returns true' do + expect(ident).to eq(another_ident) + end + end + + context 'when code, type and country code are not the same' do + let(:another_ident) { described_class.new(code: 'another-test', type: 'test', country_code: 'US') } + + it 'returns false' do + expect(ident).to_not eq(another_ident) + end + end + end +end diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb index e16ef2973..80dfb47ad 100644 --- a/spec/models/contact_spec.rb +++ b/spec/models/contact_spec.rb @@ -28,45 +28,6 @@ RSpec.describe Contact do @contact.updator.should == nil end - it 'should require country code when org' do - @contact.ident_type = 'org' - @contact.valid? - @contact.errors[:ident_country_code].should == ['is missing'] - end - - it 'should require country code when priv' do - @contact.ident_type = 'priv' - @contact.valid? - @contact.errors[:ident_country_code].should == ['is missing'] - end - - it 'should validate correct country code' do - @contact.ident = 1 - @contact.ident_type = 'org' - @contact.ident_country_code = 'EE' - @contact.valid? - - @contact.errors[:ident_country_code].should == [] - end - - it 'should require valid country code' do - @contact.ident = '123' - @contact.ident_type = 'org' - @contact.ident_country_code = 'INVALID' - @contact.valid? - - expect(@contact.errors).to have_key(:ident) - end - - it 'should convert to alpha2 country code' do - @contact.ident = 1 - @contact.ident_type = 'org' - @contact.ident_country_code = 'ee' - @contact.validate - - @contact.ident_country_code.should == 'EE' - end - it 'should not have any versions' do @contact.versions.should == [] end @@ -119,14 +80,6 @@ RSpec.describe Contact do @contact.domains_present?.should == false end - it 'org should be valid' do - contact = build(:contact, ident_type: 'org', ident: '1' * 8) - - contact.validate - - contact.errors.full_messages.should match_array([]) - end - it 'should not overwrite code' do old_code = @contact.code @contact.code = 'CID:REG1:should-not-overwrite-old-code-12345' @@ -217,31 +170,6 @@ RSpec.describe Contact do end end - context 'as birthday' do - before :example do - @contact.ident_type = 'birthday' - end - - it 'birthday should be valid' do - valid = ['2012-12-11', '1990-02-16'] - valid.each do |date| - @contact.ident = date - @contact.valid? - @contact.errors.full_messages.should match_array([]) - end - end - - it 'birthday should be invalid' do - invalid = ['123' '12/12/2012', 'aaaa', '12/12/12', '02-11-1999'] - invalid.each do |date| - @contact.ident = date - @contact.valid? - @contact.errors.full_messages.should == - ["Ident Ident not in valid birthady format, should be YYYY-MM-DD"] - end - end - end - context 'with callbacks' do before :example do # Ensure callbacks are not taken out from other specs @@ -445,7 +373,7 @@ RSpec.describe Contact do end end - describe 'country code validation' do + describe 'country code validation', db: false do let(:contact) { described_class.new(country_code: 'test') } it 'rejects invalid' do @@ -455,37 +383,25 @@ RSpec.describe Contact do end end - describe 'phone validation', db: false do + describe 'identifier validation', db: false do let(:contact) { described_class.new } - it 'rejects absent' do - contact.phone = nil + it 'rejects invalid' do + ident = Contact::Ident.new + ident.validate + contact.identifier = ident contact.validate - expect(contact.errors).to have_key(:phone) - end - it 'rejects invalid format' do - contact.phone = '123' - contact.validate - expect(contact.errors).to have_key(:phone) - end - - it 'rejects all zeros in country code' do - contact.phone = '+000.1' - contact.validate - expect(contact.errors).to have_key(:phone) - end - - it 'rejects all zeros in phone number' do - contact.phone = '+123.0' - contact.validate - expect(contact.errors).to have_key(:phone) + expect(contact.errors).to be_added(:identifier, :invalid) end it 'accepts valid' do - contact.phone = '+123.4' + ident = Contact::Ident.new(code: 'test', type: 'priv', country_code: 'US') + ident.validate + contact.identifier = ident contact.validate - expect(contact.errors).to_not have_key(:phone) + + expect(contact.errors).to_not be_added(:identifier, :invalid) end end @@ -595,4 +511,13 @@ RSpec.describe Contact do expect(domain_names).to eq({ 'test.com' => %i[admin_domain_contact].to_set }) end end + + it 'normalizes ident country code', db: false do + contact = described_class.new + + contact.ident_country_code = 'ee' + contact.validate + + expect(contact.ident_country_code).to eq('EE') + end end diff --git a/spec/models/epp/response/result_spec.rb b/spec/models/epp/response/result_spec.rb new file mode 100644 index 000000000..606a4c2de --- /dev/null +++ b/spec/models/epp/response/result_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +RSpec.describe EPP::Response::Result, db: false do + # https://tools.ietf.org/html/rfc5730#section-3 + describe '::codes' do + it 'returns codes' do + codes = { + '1000' => :success, + '1001' => :success_pending, + '1300' => :success_empty_queue, + '1301' => :success_dequeue, + '2001' => :syntax_error, + '2003' => :required_param_missing, + '2005' => :param_syntax_error, + '2308' => :data_management_policy_violation + } + + expect(described_class.codes).to eq(codes) + end + end +end diff --git a/spec/models/registrar_spec.rb b/spec/models/registrar_spec.rb index 1403ee72c..4a8110d45 100644 --- a/spec/models/registrar_spec.rb +++ b/spec/models/registrar_spec.rb @@ -35,10 +35,6 @@ describe Registrar do @registrar.reference_no.should_not be_blank @registrar.reference_no.last(10).to_i.should_not == 0 end - - it 'should not have priv contacts' do - @registrar.priv_contacts.size.should == 0 - end end context 'with valid attributes' do @@ -118,9 +114,5 @@ describe Registrar do registrar.valid? registrar.errors.full_messages.should == ['Code is forbidden to use'] end - - it 'should not have priv contacts' do - @registrar.priv_contacts.size.should == 0 - end end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 966d68b60..f4dcd9cb3 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -10,6 +10,7 @@ require 'support/requests/epp_helpers' require 'support/features/session_helpers' require 'support/matchers/alias_attribute' require 'support/matchers/epp/code' +require 'support/matchers/epp/have_result' require 'support/capybara' require 'support/devise' @@ -28,7 +29,8 @@ RSpec.configure do |config| config.include AbstractController::Translation, type: :request config.include AbstractController::Translation, type: :feature config.include AbstractController::Translation, type: :mailer - config.include Requests::EPPHelpers, type: :request + config.include Requests::EPPHelpers, epp: true + config.include Matchers::EPP, epp: true config.define_derived_metadata(file_path: %r[/spec/features/]) do |metadata| metadata[:db] = true if metadata[:db].nil? diff --git a/spec/requests/epp/contact/create/ident_spec.rb b/spec/requests/epp/contact/create/ident_spec.rb new file mode 100644 index 000000000..e112e2618 --- /dev/null +++ b/spec/requests/epp/contact/create/ident_spec.rb @@ -0,0 +1,289 @@ +require 'rails_helper' + +RSpec.describe 'EPP contact:create' do + let(:request) { post '/epp/command/create', frame: request_xml } + + before do + Setting.address_processing = false + sign_in_to_epp_area + end + + context 'when all ident params are valid' do + let(:ident) { Contact.first.identifier } + let(:request_xml) { <<-XML + + + + + + + test + + +1.2 + test@test.com + + + + + test + + + + + XML + } + + it 'creates a contact' do + expect { request }.to change { Contact.count }.from(0).to(1) + end + + it 'saves ident type' do + request + expect(ident.type).to eq('priv') + end + + it 'saves ident country code' do + request + expect(ident.country_code).to eq('US') + end + + specify do + request + expect(epp_response).to have_result(:success) + end + end + + context 'when code is blank' do + let(:request_xml) { <<-XML + + + + + + + test + + +1.2 + test@test.com + + + + + + + + + + XML + } + + it 'does not create a contact' do + expect { request }.to_not change { Contact.count } + end + + specify do + request + expect(epp_response).to have_result(:required_param_missing, + 'Required parameter missing: extension > extdata > ident [ident]') + end + end + + context 'when code is not valid national id' do + let(:request_xml) { <<-XML + + + + + + + test + + +1.2 + test@test.com + + + + + invalid + + + + + XML + } + + before do + country_specific_validations = { + Country.new('DE') => proc { false }, + } + + allow(Contact::Ident::NationalIdValidator).to receive(:country_specific_validations) + .and_return(country_specific_validations) + end + + it 'does not create a contact' do + expect { request }.to_not change { Contact.count } + end + + specify do + request + + message = 'Ident code does not conform to national identification number format of Germany' + expect(epp_response).to have_result(:param_syntax_error, message) + end + end + + context 'when code is not valid registration number' do + let(:request_xml) { <<-XML + + + + + + + test + + +1.2 + test@test.com + + + + + invalid + + + + + XML + } + + before do + country_specific_formats = { + Country.new('DE') => /\Avalid\z/, + } + + allow(Contact::Ident::RegNoValidator).to receive(:country_specific_formats).and_return(country_specific_formats) + end + + it 'does not create a contact' do + expect { request }.to_not change { Contact.count } + end + + specify do + request + expect(epp_response).to have_result(:param_syntax_error, + 'Ident code does not conform to registration number format of Germany') + end + end + + context 'when country code is absent' do + let(:request_xml) { <<-XML + + + + + + + test + + +1.2 + test@test.com + + + + + test + + + + + XML + } + + it 'does not create a contact' do + expect { request }.to_not change { Contact.count } + end + + specify do + request + expect(epp_response).to have_result(:required_param_missing, + 'Required ident attribute missing: cc') + end + end + + context 'when country code is blank' do + let(:request_xml) { <<-XML + + + + + + + test + + +1.2 + test@test.com + + + + + test + + + + + XML + } + + it 'does not create a contact' do + expect { request }.to_not change { Contact.count } + end + + specify do + request + expect(epp_response).to have_result(:syntax_error) + end + end + + context 'when mismatches' do + let(:request_xml) { <<-XML + + + + + + + test + + +1.2 + test@test.com + + + + + test + + + + + XML + } + + before do + mismatches = [ + Contact::Ident::MismatchValidator::Mismatch.new('priv', Country.new('DE')) + ] + allow(Contact::Ident::MismatchValidator).to receive(:mismatches).and_return(mismatches) + end + + it 'does not create a contact' do + expect { request }.to_not change { Contact.count } + end + + specify do + request + expect(epp_response).to have_result(:param_syntax_error, + 'Ident type "priv" is invalid for Germany') + end + end +end diff --git a/spec/requests/epp/contact/update/ident_spec.rb b/spec/requests/epp/contact/update/ident_spec.rb new file mode 100644 index 000000000..c93ba6390 --- /dev/null +++ b/spec/requests/epp/contact/update/ident_spec.rb @@ -0,0 +1,196 @@ +require 'rails_helper' + +# https://github.com/internetee/registry/issues/576 + +RSpec.describe 'EPP contact:update' do + let(:ident) { contact.identifier } + let(:request) { post '/epp/command/update', frame: request_xml } + let(:request_xml) { <<-XML + + + + + + TEST + + + test + + + + + + + test + + + + + XML + } + + before do + sign_in_to_epp_area + end + + context 'when contact ident is valid' do + context 'when submitted ident matches current one' do + let!(:contact) { create(:contact, code: 'TEST', + ident: 'test', + ident_type: 'priv', + ident_country_code: 'US') } + + specify do + request + expect(epp_response).to have_result(:success) + end + end + + context 'when submitted ident does not match current one' do + let!(:contact) { create(:contact, code: 'TEST', + ident: 'another-test', + ident_type: 'priv', + ident_country_code: 'US') } + + it 'does not update code' do + expect do + request + contact.reload + end.to_not change { ident.code } + end + + it 'does not update type' do + expect do + request + contact.reload + end.to_not change { ident.type } + end + + it 'does not update country code' do + expect do + request + contact.reload + end.to_not change { ident.country_code } + end + + specify do + request + + expect(epp_response).to have_result(:data_management_policy_violation, + t('epp.contacts.errors.valid_ident')) + end + end + end + + context 'when contact ident is invalid' do + let(:contact) { build(:contact, code: 'TEST', ident: 'test', ident_type: nil, ident_country_code: nil) } + + before do + contact.save(validate: false) + end + + context 'when submitted ident is the same as current one' do + let(:request_xml) { <<-XML + + + + + + TEST + + + test + + + + + + + test + + + + + XML + } + + it 'does not update code' do + expect do + request + contact.reload + end.to_not change { ident.code } + end + + it 'updates type' do + request + contact.reload + expect(ident.type).to eq('priv') + end + + it 'updates country code' do + request + contact.reload + expect(ident.country_code).to eq('US') + end + + specify do + request + expect(epp_response).to have_result(:success) + end + end + + context 'when submitted ident is different from current one' do + let(:request_xml) { <<-XML + + + + + + TEST + + + test + + + + + + + another-test + + + + + XML + } + + it 'does not update code' do + expect do + request + contact.reload + end.to_not change { ident.code } + end + + it 'does not update type' do + expect do + request + contact.reload + end.to_not change { ident.type } + end + + it 'does not update country code' do + expect do + request + contact.reload + end.to_not change { ident.country_code } + end + + specify do + request + + expect(epp_response).to have_result(:data_management_policy_violation, + t('epp.contacts.errors.ident_update')) + end + end + end +end diff --git a/spec/support/matchers/epp/have_result.rb b/spec/support/matchers/epp/have_result.rb new file mode 100644 index 000000000..7850082dd --- /dev/null +++ b/spec/support/matchers/epp/have_result.rb @@ -0,0 +1,37 @@ +module Matchers + module EPP + class HaveResultMatcher + def initialize(expected) + @expected = expected + end + + def matches?(target) + @target = target + + if @expected.message.present? + @target.results.any? { |result| result.code == @expected.code && result.message == @expected.message } + else + @target.results.any? { |result| result.code == @expected.code } + end + end + + def failure_message + "expected #{@target.results} to have result #{@expected.inspect}" + end + + def failure_message_when_negated + "expected #{@target.results} not to have result #{@expected.inspect}" + end + + def description + "should have EPP code of #{@expected}" + end + end + + def have_result(type, message = nil) + code = ::EPP::Response::Result.codes.key(type) + result = ::EPP::Response::Result.new(code, message) + HaveResultMatcher.new(result) + end + end +end diff --git a/spec/support/requests/epp_helpers.rb b/spec/support/requests/epp_helpers.rb index beb8ca2c2..fb0175df1 100644 --- a/spec/support/requests/epp_helpers.rb +++ b/spec/support/requests/epp_helpers.rb @@ -7,5 +7,9 @@ module Requests def valid_legal_document Base64.encode64('a' * 5000) end + + def epp_response + EPP::Response.from_xml(response.body) + end end end diff --git a/spec/validators/contact/ident/mismatch_validator_spec.rb b/spec/validators/contact/ident/mismatch_validator_spec.rb new file mode 100644 index 000000000..dfb30fe09 --- /dev/null +++ b/spec/validators/contact/ident/mismatch_validator_spec.rb @@ -0,0 +1,13 @@ +require 'rails_helper' + +RSpec.describe Contact::Ident::MismatchValidator do + describe '::mismatches' do + it 'returns mismatches' do + mismatches = [ + Contact::Ident::MismatchValidator::Mismatch.new('birthday', Country.new('EE')) + ] + + expect(described_class.mismatches).to eq(mismatches) + end + end +end