From aa8d8c35e8c7068f687d14e4a12ab24c83f0e7a5 Mon Sep 17 00:00:00 2001 From: Sergei Tsoganov Date: Thu, 6 Apr 2023 13:54:03 +0300 Subject: [PATCH] Fixed ransack admin search --- app/controllers/admin/base_controller.rb | 2 +- app/controllers/admin/domains_controller.rb | 14 ++++---------- app/models/contact.rb | 2 +- app/models/domain.rb | 16 +++++++++++----- app/models/nameserver.rb | 4 ++++ app/models/registrar.rb | 8 ++++++++ app/services/partial_search_formatter.rb | 2 +- app/validators/domain_name_validator.rb | 4 +++- app/views/admin/domains/_domain.html.erb | 2 +- 9 files changed, 34 insertions(+), 20 deletions(-) diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 56806ba3e..f30b6834f 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -26,7 +26,7 @@ module Admin respond_to do |format| format.html { render page } format.csv do - raw_csv = CsvGenerator.generate_csv(@q.result) + raw_csv = CsvGenerator.generate_csv(@q.result(distinct: true)) send_data raw_csv, filename: "#{filename}_#{Time.zone.now.to_formatted_s(:number)}.csv", type: "#{Mime[:csv]}; charset=utf-8" diff --git a/app/controllers/admin/domains_controller.rb b/app/controllers/admin/domains_controller.rb index 0b3a8b785..a5b4341af 100644 --- a/app/controllers/admin/domains_controller.rb +++ b/app/controllers/admin/domains_controller.rb @@ -5,27 +5,21 @@ module Admin before_action :set_domain, only: %i[show edit update download keep] authorize_resource - # rubocop:disable Metrics/MethodLength def index params[:q] ||= {} - domains = if params[:statuses_contains] - Domain.includes(:registrar, :registrant).where( - "domains.statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}" - ) - else - Domain.includes(:registrar, :registrant) - end + domains = Domain.includes(:registrar, :registrant).joins(:registrar, :registrant) + p = params[:statuses_contains] + domains = domains.where('domains.statuses @> ?::varchar[]', "{#{p.join(',')}}") if p.present? normalize_search_parameters do @q = domains.ransack(PartialSearchFormatter.format(params[:q])) - @domains = @q.result.page(params[:page]) + @domains = @q.result(distinct: true).page(params[:page]) end @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? render_by_format('admin/domains/index', 'domains') end - # rubocop:enable Metrics/MethodLength def show # Validation is needed to warn users diff --git a/app/models/contact.rb b/app/models/contact.rb index 2ab986aee..6222f8c3e 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -188,7 +188,7 @@ class Contact < ApplicationRecord end def ransackable_attributes(auth_object = nil) - super + authorizable_ransackable_attributes end def search_by_query(query) diff --git a/app/models/domain.rb b/app/models/domain.rb index df9f10d22..883b7205b 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -246,11 +246,11 @@ class Domain < ApplicationRecord class << self def ransackable_associations(auth_object = nil) - super + authorizable_ransackable_associations end def ransackable_attributes(auth_object = nil) - super + authorizable_ransackable_attributes end def nameserver_required? @@ -755,12 +755,14 @@ class Domain < ApplicationRecord def as_csv_row [ name, - registrant_name, + "#{registrant_name}, #{registrant_ident_info}", valid_to.to_formatted_s(:db), registrar, created_at.to_formatted_s(:db), statuses, - contacts.pluck(:code), + admin_contacts.map { |c| "#{c.name}, #{c.code}, #{ApplicationController.helpers.ident_for(c)}" }, + tech_contacts.map { |c| "#{c.name}, #{c.code}, #{ApplicationController.helpers.ident_for(c)}" }, + nameservers.pluck(:hostname), force_delete_date, force_delete_data, ] @@ -783,10 +785,14 @@ class Domain < ApplicationRecord contact.try(:name) || 'Deleted' end + def registrant_ident_info + return ApplicationController.helpers.ident_for(registrant) if registrant + end + def self.csv_header [ 'Domain', 'Registrant', 'Valid to', 'Registrar', 'Created at', - 'Statuses', 'Contacts code', 'Force delete date', 'Force delete data' + 'Statuses', 'Admin. contacts', 'Tech. contacts', 'Nameservers', 'Force delete date', 'Force delete data' ] end diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index ababd84cf..4e071642c 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -86,6 +86,10 @@ class Nameserver < ApplicationRecord def hostnames pluck(:hostname) end + + def ransackable_attributes(auth_object = nil) + authorizable_ransackable_attributes + end end private diff --git a/app/models/registrar.rb b/app/models/registrar.rb index cc97f11e1..83d9ca4e4 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -51,6 +51,14 @@ class Registrar < ApplicationRecord # rubocop:disable Metrics/ClassLength self.ignored_columns = %w[legacy_id] class << self + def ransackable_associations(auth_object = nil) + super + end + + def ransackable_attributes(auth_object = nil) + authorizable_ransackable_attributes + end + def ordered order(name: :asc) end diff --git a/app/services/partial_search_formatter.rb b/app/services/partial_search_formatter.rb index 268cd75fb..a8d402d3b 100644 --- a/app/services/partial_search_formatter.rb +++ b/app/services/partial_search_formatter.rb @@ -5,7 +5,7 @@ class PartialSearchFormatter search_params.each do |key, value| next unless key.include?('matches') && value.present? - search_params[key] = "%#{value}%" + search_params[key] = value =~ /\A\*.*\*\z/ ? value.gsub(/\A\*|\*\z/, '') : "%#{value}%" end search_params diff --git a/app/validators/domain_name_validator.rb b/app/validators/domain_name_validator.rb index 3372bb952..5ca4e93a7 100644 --- a/app/validators/domain_name_validator.rb +++ b/app/validators/domain_name_validator.rb @@ -3,7 +3,7 @@ class DomainNameValidator < ActiveModel::EachValidator # rubocop:disable Metrics/LineLength def validate_each(record, attribute, value) if !self.class.validate_format(value) - record.errors[attribute] << (options[:message] || record.errors.generate_message(attribute, :invalid)) + record.errors.add(attribute, options[:message] || record.errors.generate_message(attribute, :invalid)) elsif !self.class.validate_blocked(value) record.errors.add(:base, :domain_name_blocked) end @@ -12,6 +12,7 @@ class DomainNameValidator < ActiveModel::EachValidator class << self def validate_format(value) return true unless value + value = value.mb_chars.downcase.strip origins = DNS::Zone.origins @@ -25,6 +26,7 @@ class DomainNameValidator < ActiveModel::EachValidator if value[2] == '-' && value[3] == '-' regexp = /\Axn--[a-zA-Z0-9-]{0,59}\.#{general_domains}\z/ return false unless value.match?(regexp) + value = SimpleIDN.to_unicode(value).mb_chars.downcase.strip end diff --git a/app/views/admin/domains/_domain.html.erb b/app/views/admin/domains/_domain.html.erb index 8b69f9010..73f46a9ed 100644 --- a/app/views/admin/domains/_domain.html.erb +++ b/app/views/admin/domains/_domain.html.erb @@ -1,5 +1,5 @@ - <%= link_to domain, admin_domain_path(domain) %> + <%= link_to domain, admin_domain_path(domain) %> <%= link_to domain.registrant, admin_contact_path(domain.registrant) %> <%= l domain.expire_time %> <%= link_to domain.registrar, admin_registrar_path(domain.registrar) %>