diff --git a/Gemfile b/Gemfile index 68272c056..69cecca3a 100644 --- a/Gemfile +++ b/Gemfile @@ -89,6 +89,7 @@ group :test do gem 'capybara' gem 'database_cleaner' gem 'minitest', '~> 5.17' + gem 'minitest-stub_any_instance' gem 'simplecov', '0.17.1', require: false # CC last supported v0.17 gem 'spy' gem 'webdrivers' diff --git a/Gemfile.lock b/Gemfile.lock index 7e1dd7d1d..db74c3f63 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -311,6 +311,7 @@ GEM mini_mime (1.1.2) mini_portile2 (2.8.2) minitest (5.18.1) + minitest-stub_any_instance (1.0.3) monetize (1.9.4) money (~> 6.12) money (6.13.8) @@ -571,6 +572,7 @@ DEPENDENCIES mime-types-data mimemagic (= 0.4.3) minitest (~> 5.17) + minitest-stub_any_instance money-rails newrelic-infinite_tracing newrelic_rpm @@ -606,4 +608,4 @@ DEPENDENCIES wkhtmltopdf-binary (~> 0.12.6.1) BUNDLED WITH - 2.4.13 + 2.4.14 diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 88afec72d..36de86a2c 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -1,6 +1,7 @@ module Admin class BaseController < ApplicationController before_action :authenticate_admin_user! + before_action :set_locale helper_method :head_title_sufix before_action :set_paper_trail_whodunnit @@ -33,5 +34,9 @@ module Admin end end end + + def set_locale + I18n.locale = params[:locale] || I18n.default_locale + end end end diff --git a/app/controllers/admin/certificates_controller.rb b/app/controllers/admin/certificates_controller.rb index 3f1113b0f..56e30f26a 100644 --- a/app/controllers/admin/certificates_controller.rb +++ b/app/controllers/admin/certificates_controller.rb @@ -41,7 +41,7 @@ module Admin def sign if @certificate.sign!(password: certificate_params[:password]) flash[:notice] = I18n.t('record_updated') - notify_api_user + notify_registrar redirect_to [:admin, @api_user, @certificate] else flash.now[:alert] = I18n.t('failed_to_update_record') @@ -88,10 +88,10 @@ module Admin end end - def notify_api_user - api_user_email = @api_user.registrar.email + def notify_registrar + email = @api_user.registrar.email - CertificateMailer.signed(email: api_user_email, api_user: @api_user, + CertificateMailer.signed(email: email, api_user: @api_user, crt: OpenSSL::X509::Certificate.new(@certificate.crt)) .deliver_now end diff --git a/app/controllers/admin/white_ips_controller.rb b/app/controllers/admin/white_ips_controller.rb index 8554774d3..13867606e 100644 --- a/app/controllers/admin/white_ips_controller.rb +++ b/app/controllers/admin/white_ips_controller.rb @@ -2,17 +2,15 @@ module Admin class WhiteIpsController < BaseController load_and_authorize_resource - before_action :set_registrar, only: [:new, :show, :edit, :destroy, :update] + before_action :set_registrar, only: %i[new show edit destroy update] def new @white_ip = WhiteIp.new(registrar: @registrar) end - def show; - end + def show; end - def edit; - end + def edit; end def destroy if @white_ip.destroy @@ -38,7 +36,11 @@ module Admin end def update + previously_committed = @white_ip.committed + if @white_ip.update(white_ip_params) + notify_registrar if !previously_committed && @white_ip.committed + flash[:notice] = I18n.t('record_updated') redirect_to [:admin, @registrar, @white_ip] else @@ -54,7 +56,14 @@ module Admin end def white_ip_params - params.require(:white_ip).permit(:ipv4, :ipv6, :registrar_id, { interfaces: [] }) + params.require(:white_ip).permit(:ipv4, :ipv6, :registrar_id, :committed, { interfaces: [] }) + end + + def notify_registrar + email = @white_ip.registrar.email + + WhiteIpMailer.committed(email: email, ip: @white_ip) + .deliver_now end end end diff --git a/app/controllers/repp/v1/accounts_controller.rb b/app/controllers/repp/v1/accounts_controller.rb index 8aee2d294..2fe716e9c 100644 --- a/app/controllers/repp/v1/accounts_controller.rb +++ b/app/controllers/repp/v1/accounts_controller.rb @@ -174,7 +174,7 @@ module Repp end def serialized_ips(ips) - ips.as_json(only: %i[id ipv4 ipv6 interfaces]) + ips.as_json(only: %i[id ipv4 ipv6 interfaces committed]) end end end diff --git a/app/controllers/repp/v1/base_controller.rb b/app/controllers/repp/v1/base_controller.rb index 464be249a..d2057599e 100644 --- a/app/controllers/repp/v1/base_controller.rb +++ b/app/controllers/repp/v1/base_controller.rb @@ -5,6 +5,7 @@ module Repp around_action :log_request before_action :authenticate_user + before_action :set_locale before_action :validate_webclient_ca before_action :validate_client_certs before_action :check_ip_restriction @@ -121,18 +122,36 @@ module Repp end def check_ip_restriction - return if webclient_request? - return if @current_user.registrar.api_ip_white?(request.ip) + ip = webclient_request? ? request.headers['X-Client-IP'] : request.ip + return if registrar_ip_white?(ip) && webclient_request? + return if api_ip_white?(ip) && !webclient_request? - @response = { code: 2202, - message: I18n.t('registrar.authorization.ip_not_allowed', ip: request.ip) } - render(json: @response, status: :unauthorized) + render_unauthorized_response(ip) + end + + def registrar_ip_white?(ip) + return true unless ip + + @current_user.registrar.registrar_ip_white?(ip) + end + + def api_ip_white?(ip) + @current_user.registrar.api_ip_white?(ip) + end + + def render_unauthorized_response(ip) + @response = { code: 2202, message: I18n.t('registrar.authorization.ip_not_allowed', ip: ip) } + render json: @response, status: :unauthorized end def webclient_request? return false if Rails.env.test? || Rails.env.development? - ENV['webclient_ips'].split(',').map(&:strip).include?(request.ip) + webclient_ips.include?(request.ip) + end + + def webclient_ips + ENV['webclient_ips'].to_s.split(',').map(&:strip) end def validate_webclient_ca @@ -143,8 +162,7 @@ module Repp webclient_cn = ENV['webclient_cert_common_name'] || 'webclient' return if request_name == webclient_cn - @response = { code: 2202, - message: I18n.t('registrar.authorization.ip_not_allowed', ip: request.ip) } + @response = { code: 2202, message: 'Invalid webclient certificate' } render(json: @response, status: :unauthorized) end @@ -176,6 +194,10 @@ module Repp authorize!(:throttled_user, @domain) unless current_user || action_name == 'tara_callback' current_user end + + def set_locale + I18n.locale = current_user&.try(:locale) || params[:locale] || I18n.default_locale + end end end end diff --git a/app/controllers/repp/v1/white_ips_controller.rb b/app/controllers/repp/v1/white_ips_controller.rb index 4cb8d8987..c7ab1dc84 100644 --- a/app/controllers/repp/v1/white_ips_controller.rb +++ b/app/controllers/repp/v1/white_ips_controller.rb @@ -31,39 +31,63 @@ module Repp return end + uncommit_and_notify_admins if api_interface?(@white_ip) render_success(data: { ip: { id: @white_ip.id } }) end api :PUT, '/repp/v1/white_ips/:id' desc 'Update whitelisted IP address' def update + previously_api = api_interface?(@white_ip) unless @white_ip.update(white_ip_params) handle_non_epp_errors(@white_ip) return end + uncommit_and_notify_admins if api_interface?(@white_ip) + uncommit_and_notify_admins if previously_api && !api_interface?(@white_ip) render_success(data: { ip: { id: @white_ip.id } }) end api :DELETE, '/repp/v1/white_ips/:id' desc 'Delete a specific whitelisted IP address' def destroy + ip = @white_ip unless @white_ip.destroy handle_non_epp_errors(@white_ip) return end + uncommit_and_notify_admins(ip: ip, action: 'deleted') if api_interface?(ip) render_success end private + def api_interface?(ip) + ip.interfaces.include? WhiteIp::API + end + def find_white_ip @white_ip = current_user.registrar.white_ips.find(params[:id]) end def white_ip_params - params.require(:white_ip).permit(:ipv4, :ipv6, interfaces: []) + params.require(:white_ip).permit(:address, interfaces: []) + end + + def uncommit_and_notify_admins(ip: @white_ip, action: 'updated') + @white_ip.update(committed: false) if action == 'updated' + admin_users_emails = User.admin.pluck(:email).reject(&:blank?) + + return if admin_users_emails.empty? + + admin_users_emails.each do |email| + WhiteIpMailer.with(email: email, api_user: current_user, + white_ip: ip) + .send("api_ip_address_#{action}") + .deliver_now + end end end end diff --git a/app/mailers/white_ip_mailer.rb b/app/mailers/white_ip_mailer.rb new file mode 100644 index 000000000..8b7984ba8 --- /dev/null +++ b/app/mailers/white_ip_mailer.rb @@ -0,0 +1,23 @@ +class WhiteIpMailer < ApplicationMailer + def api_ip_address_updated + email = params[:email] + @api_user = params[:api_user] + @white_ip = params[:white_ip] + subject = '[Important] Whitelisted IP Address Change Notification' + mail(to: email, subject: subject) + end + + def api_ip_address_deleted + email = params[:email] + @api_user = params[:api_user] + @white_ip = params[:white_ip] + subject = '[Important] Whitelisted IP Address Removal Notification' + mail(to: email, subject: subject) + end + + def committed(email:, ip:) + @white_ip = ip + subject = 'Whitelisted IP Address Activation Confirmation' + mail(to: email, subject: subject) + end +end diff --git a/app/models/concerns/white_ip/white_ip_concern.rb b/app/models/concerns/white_ip/white_ip_concern.rb new file mode 100644 index 000000000..f44af0825 --- /dev/null +++ b/app/models/concerns/white_ip/white_ip_concern.rb @@ -0,0 +1,53 @@ +# app/models/concerns/white_ip_concern.rb +module WhiteIp::WhiteIpConcern + extend ActiveSupport::Concern + + class_methods do # rubocop:disable Metrics/BlockLength + def include_ip?(ip) + return false if ip.blank? + + where(id: ids_including(ip)).any? + end + + def ids_including(ip) + ipv4 = select_ipv4(ip) + ipv6 = select_ipv6(ip) + + (ipv4 + ipv6).pluck(:id).flatten.uniq + end + + # rubocop:disable Style/CaseEquality + def select_ipv4(ip) + return [] if check_ip4(ip).blank? + + select { |white_ip| check_ip4(white_ip.ipv4) === check_ip4(ip) } + end + + def select_ipv6(ip) + return [] if check_ip6(ip).blank? + + select { |white_ip| check_ip6(white_ip.ipv6) === check_ip6(ip) } + end + # rubocop:enable Style/CaseEquality + + def csv_header + %w[IPv4 IPv6 Interfaces Created Updated] + end + + def ransackable_attributes(*) + authorizable_ransackable_attributes + end + + def check_ip4(ip) + IPAddr.new(ip, Socket::AF_INET) + rescue StandardError => _e + nil + end + + def check_ip6(ip) + IPAddr.new(ip, Socket::AF_INET6) + rescue StandardError => _e + nil + end + end +end diff --git a/app/models/registrar.rb b/app/models/registrar.rb index cdcdbcc7b..71dddaa7f 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -200,6 +200,12 @@ class Registrar < ApplicationRecord # rubocop:disable Metrics/ClassLength white_ips.api.include_ip?(ip) end + def registrar_ip_white?(ip) + return true unless Setting.registrar_ip_whitelist_enabled + + white_ips.registrar_area.include_ip?(ip) + end + def accredited? api_users.any? do |a| return true unless a.accreditation_date.nil? diff --git a/app/models/white_ip.rb b/app/models/white_ip.rb index fb638c631..02840263f 100644 --- a/app/models/white_ip.rb +++ b/app/models/white_ip.rb @@ -1,11 +1,15 @@ class WhiteIp < ApplicationRecord include Versions + include WhiteIp::WhiteIpConcern + belongs_to :registrar + attr_accessor :address + + validate :validate_address_format + validate :validate_only_one_ip validate :valid_ipv4? validate :valid_ipv6? - validate :validate_ipv4_and_ipv6 - validate :validate_only_one_ip validate :validate_max_ip_count before_save :normalize_blank_values @@ -13,16 +17,35 @@ class WhiteIp < ApplicationRecord %i[ipv4 ipv6].each { |c| self[c].present? || self[c] = nil } end - def validate_ipv4_and_ipv6 - return if ipv4.present? || ipv6.present? + def validate_address_format + return if address.blank? - errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present)) + ip_address = IPAddr.new(address) + ip_version = determine_ip_version(ip_address) + + assign_ip_attributes(ip_version) + rescue IPAddr::InvalidAddressError + errors.add(:base, :address_invalid) end def validate_only_one_ip - return unless ipv4.present? && ipv6.present? + if ipv4.present? && ipv6.present? + errors.add(:base, :ip_must_be_one) + elsif ipv4.blank? && ipv6.blank? + errors.add(:base, :ipv4_or_ipv6_must_be_present) + end + end - errors.add(:base, I18n.t(:ip_must_be_one)) + def validate_max_ip_count + return if errors.any? + + total_exist = calculate_total_network_addresses(registrar.white_ips) + total_current = calculate_total_network_addresses([self]) + total = total_exist + total_current + limit = Setting.ip_whitelist_max_count + return unless total >= limit + + errors.add(:base, :ip_limit_exceeded, total: total, limit: limit) end def valid_ipv4? @@ -41,34 +64,9 @@ class WhiteIp < ApplicationRecord errors.add(:ipv6, :invalid) end - def validate_max_ip_count - return if errors.any? - - ip_addresses = registrar.white_ips - total = ip_addresses.size + count_network_addresses(ipv4.presence || ipv6) - limit = Setting.ip_whitelist_max_count - return unless total >= limit - - errors.add(:base, I18n.t(:ip_limit_exceeded, total: total, limit: limit)) - end - - def count_network_addresses(ip) - address = IPAddr.new(ip) - - if address.ipv4? - subnet_mask = address.prefix - 2**(32 - subnet_mask) - 2 - elsif address.ipv6? - subnet_mask = address.prefix - 2**(128 - subnet_mask) - 2 - else - 0 - end - end - API = 'api'.freeze REGISTRAR = 'registrar'.freeze - INTERFACES = [API, REGISTRAR].freeze + INTERFACES = [REGISTRAR, API].freeze scope :api, -> { where('interfaces @> ?::varchar[]', "{#{API}}") } scope :registrar_area, -> { where('interfaces @> ?::varchar[]', "{#{REGISTRAR}}") } @@ -77,52 +75,52 @@ class WhiteIp < ApplicationRecord super(interfaces.reject(&:blank?)) end - class << self - # rubocop:disable Style/CaseEquality - # rubocop:disable Metrics/AbcSize - def include_ip?(ip) - return false if ip.blank? - - where(id: ids_including(ip)).any? - end - - def ids_including(ip) - ipv4 = ipv6 = [] - ipv4 = select { |white_ip| check_ip4(white_ip.ipv4) === check_ip4(ip) } if check_ip4(ip).present? - ipv6 = select { |white_ip| check_ip6(white_ip.ipv6) === check_ip6(ip) } if check_ip6(ip).present? - (ipv4 + ipv6).pluck(:id).flatten.uniq - end - # rubocop:enable Style/CaseEquality - # rubocop:enable Metrics/AbcSize - - def check_ip4(ip) - IPAddr.new(ip, Socket::AF_INET) - rescue StandardError => _e - nil - end - - def check_ip6(ip) - IPAddr.new(ip, Socket::AF_INET6) - rescue StandardError => _e - nil - end - - def csv_header - %w[IPv4 IPv6 Interfaces Created Updated] - end - - def ransackable_attributes(*) - authorizable_ransackable_attributes - end - end - def as_csv_row [ - ipv4, - ipv6, + ipv4, ipv6, interfaces.join(', ').upcase, created_at, - updated_at, + updated_at ] end + + private + + def determine_ip_version(ip_address) + return :ipv4 if ip_address.ipv4? + return :ipv6 if ip_address.ipv6? + + nil + end + + def assign_ip_attributes(ip_version) + case ip_version + when :ipv4 + self.ipv4 = address + self.ipv6 = nil + when :ipv6 + self.ipv6 = address + self.ipv4 = nil + else + errors.add(:base, :address_invalid) + end + end + + def count_network_addresses(ip) + address = IPAddr.new(ip) + + if address.ipv4? + subnet_mask = address.prefix + (2**(32 - subnet_mask) - 2).abs + elsif address.ipv6? + subnet_mask = address.prefix + (2**(128 - subnet_mask) - 2).abs + else + 0 + end + end + + def calculate_total_network_addresses(ips) + ips.sum { |ip| count_network_addresses(ip.ipv4.presence || ip.ipv6) } + end end diff --git a/app/views/admin/registrars/show/_white_ips.html.erb b/app/views/admin/registrars/show/_white_ips.html.erb index 5de3066c0..df59c8b63 100644 --- a/app/views/admin/registrars/show/_white_ips.html.erb +++ b/app/views/admin/registrars/show/_white_ips.html.erb @@ -9,6 +9,7 @@
This email is to inform you that an API Whitelisted IP address was deleted by Registrar Portal API user. Please review the details below:
+ +Please take the necessary actions to ensure the security and integrity of the application's API access.
diff --git a/app/views/mailers/white_ip_mailer/api_ip_address_deleted.text.erb b/app/views/mailers/white_ip_mailer/api_ip_address_deleted.text.erb new file mode 100644 index 000000000..73eca3594 --- /dev/null +++ b/app/views/mailers/white_ip_mailer/api_ip_address_deleted.text.erb @@ -0,0 +1,8 @@ +This email is to inform you about an API Whitelisted IP address change by Registrar Portal API user. Please review the details below: + +Registrar: <%= @api_user.registrar.name %> +API User: <%= @api_user.username %> +IP Address: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> +Interface: <%= @white_ip.interfaces.join(', ') %> + +Please take the necessary actions to ensure the security and integrity of the application's API access. diff --git a/app/views/mailers/white_ip_mailer/api_ip_address_updated.html.erb b/app/views/mailers/white_ip_mailer/api_ip_address_updated.html.erb new file mode 100644 index 000000000..927adc50f --- /dev/null +++ b/app/views/mailers/white_ip_mailer/api_ip_address_updated.html.erb @@ -0,0 +1,10 @@ +This email is to inform you about an API Whitelisted IP address change by Registrar Portal API user. Please review the details below:
+ +Please take the necessary actions to ensure the security and integrity of the application's API access.
diff --git a/app/views/mailers/white_ip_mailer/api_ip_address_updated.text.erb b/app/views/mailers/white_ip_mailer/api_ip_address_updated.text.erb new file mode 100644 index 000000000..73eca3594 --- /dev/null +++ b/app/views/mailers/white_ip_mailer/api_ip_address_updated.text.erb @@ -0,0 +1,8 @@ +This email is to inform you about an API Whitelisted IP address change by Registrar Portal API user. Please review the details below: + +Registrar: <%= @api_user.registrar.name %> +API User: <%= @api_user.username %> +IP Address: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> +Interface: <%= @white_ip.interfaces.join(', ') %> + +Please take the necessary actions to ensure the security and integrity of the application's API access. diff --git a/app/views/mailers/white_ip_mailer/committed.html.erb b/app/views/mailers/white_ip_mailer/committed.html.erb new file mode 100644 index 000000000..2cc853ea3 --- /dev/null +++ b/app/views/mailers/white_ip_mailer/committed.html.erb @@ -0,0 +1,43 @@ +Tere, ++Anname teada, et Teie konto juurde kuuluv lubatud IP-aadress on edukalt aktiveeritud. +
++Päringud IP-aadressist <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> jõuavad nüüd .ee registrisüsteemini. +Palun hoidke selle IP-aadressi turvalisust ja konfidentsiaalsust, et vältida volitamata juurdepääsu. +
+Kui Teil on küsimusi seoses Teie lubatud IP-aadressi aktiveerimisega, võtke meiega ühendust. + ++Parimate soovidega, +
+<%= render 'mailers/shared/signatures/signature.et.html' %> ++We would like to inform you that the whitelisted IP address associated with your account has been successfully activated. +
++All requests originating from the IP address <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> will now have access to our system. +Please ensure the security and confidentiality of this IP address to prevent unauthorized access. +
+If you have any questions regarding the activation of your whitelisted IP address, please contact us. + ++Best regards, +
+<%= render 'mailers/shared/signatures/signature.en.html' %> \ No newline at end of file diff --git a/app/views/mailers/white_ip_mailer/committed.text.erb b/app/views/mailers/white_ip_mailer/committed.text.erb new file mode 100644 index 000000000..8c8928485 --- /dev/null +++ b/app/views/mailers/white_ip_mailer/committed.text.erb @@ -0,0 +1,32 @@ +Tere, + +Anname teada, et Teie konto juurde kuuluv lubatud IP-aadress on edukalt aktiveeritud. + +IP-aadressi andmed: +- IP-aadress: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> +- Liidesed: <%= @white_ip.interfaces.join(', ') %> + +Päringud IP-aadressist <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> jõuavad nüüd .ee registrisüsteemini. +Palun hoidke selle IP-aadressi turvalisust ja konfidentsiaalsust, et vältida volitamata juurdepääsu. + +Kui Teil on küsimusi seoses Teie lubatud IP-aadressi aktiveerimisega, võtke meiega ühendust. + +Parimate soovidega, +<%= render 'mailers/shared/signatures/signature.et.html' %> +--- + +Hi, + +We would like to inform you that the whitelisted IP address associated with your account has been successfully activated. + +IP address Details: +- IP address: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> +- Interfaces: <%= @white_ip.interfaces.join(', ') %> + +All requests originating from the IP address <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> will now have access to our system. +Please ensure the security and confidentiality of this IP address to prevent unauthorized access. + +If you have any questions regarding the activation of your whitelisted IP address, please contact us. + +Best regards, +<%= render 'mailers/shared/signatures/signature.en.html' %> \ No newline at end of file diff --git a/config/locales/devise.et.yml b/config/locales/devise.et.yml new file mode 100644 index 000000000..051ad2ea2 --- /dev/null +++ b/config/locales/devise.et.yml @@ -0,0 +1,64 @@ +# Additional translations at https://github.com/plataformatec/devise/wiki/I18n + +et: + devise: + confirmations: + confirmed: "Your email address has been successfully confirmed." + send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." + send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." + failure: + already_authenticated: "You are already signed in." + inactive: "Your account is not activated yet." + invalid: "Invalid %{authentication_keys} or password." + locked: "Your account is locked." + last_attempt: "You have one more attempt before your account is locked." + not_found_in_database: "Invalid %{authentication_keys} or password." + timeout: "Your session expired. Please sign in again to continue." + unauthenticated: "You need to sign in before continuing." + unconfirmed: "You have to confirm your email address before continuing." + mailer: + confirmation_instructions: + subject: "Confirmation instructions" + reset_password_instructions: + subject: "Reset password instructions" + unlock_instructions: + subject: "Unlock instructions" + email_changed: + subject: "Email Changed" + password_change: + subject: "Password Changed" + omniauth_callbacks: + failure: "Could not authenticate you from %{kind} because \"%{reason}\"." + success: "Successfully authenticated from %{kind} account." + passwords: + no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." + send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." + send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." + updated: "Your password has been changed successfully. You are now signed in." + updated_not_active: "Your password has been changed successfully." + registrations: + destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." + signed_up: "Welcome! You have signed up successfully." + signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." + signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." + signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." + update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." + updated: "Your account has been updated successfully." + sessions: + signed_in: "Signed in successfully." + signed_out: "Signed out successfully." + already_signed_out: "Signed out successfully." + unlocks: + send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." + send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." + unlocked: "Your account has been unlocked successfully. Please sign in to continue." + errors: + messages: + already_confirmed: "was already confirmed, please try signing in" + confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" + expired: "has expired, please request a new one" + not_found: "not found" + not_locked: "was not locked" + not_saved: + one: "1 error prohibited this %{resource} from being saved:" + other: "%{count} errors prohibited this %{resource} from being saved:" diff --git a/config/locales/en.yml b/config/locales/en.yml index 32f122924..e9553aa20 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -147,6 +147,18 @@ en: length_more_than: 'Parameter value policy error: Legaldoc size is less than minimum allowed size of 3kB' length_less_than: 'Parameter value policy error: Legaldoc size exceeds maximum allowed size of 8mB' + white_ip: + attributes: + base: + address_invalid: 'IP Address is invalid' + ipv4_or_ipv6_must_be_present: 'IPv4 or IPv6 must be present' + ip_must_be_one: 'Please enter only one IP address' + ip_limit_exceeded: 'IP address limit exceeded. Total addresses: %{total}. Limit: %{limit}.' + ipv4: + taken: 'has already been taken' + ipv6: + taken: 'has already been taken' + attributes: epp_domain: &epp_domain_attributes @@ -548,9 +560,6 @@ en: not_valid_domain_verification_body: This could mean your verification has been expired or done already.