Merge pull request #2555 from internetee/2553-admin-domain-filter

Fixed ransack admin search
This commit is contained in:
Timo Võhmar 2023-04-18 14:40:17 +03:00 committed by GitHub
commit 3126973f24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 172 additions and 128 deletions

View file

@ -4,7 +4,8 @@ module Admin
def index
@q = Account.includes(:registrar).ransack(params[:q])
@accounts = @q.result.page(params[:page])
@result = @q.result
@accounts = @result.page(params[:page])
@accounts = @accounts.per(params[:results_per_page]) if paginate?
render_by_format('admin/accounts/index', 'accounts')

View file

@ -15,7 +15,8 @@ module Admin
normalize_search_parameters do
@q = @auctions.ransack(PartialSearchFormatter.format(params[:q]))
@auctions = @q.result.page(params[:page])
@result = @q.result
@auctions = @result.page(params[:page])
end
@auctions = @auctions.per(params[:results_per_page_auction]) if params[:results_per_page_auction].to_i.positive?

View file

@ -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(@result)
send_data raw_csv,
filename: "#{filename}_#{Time.zone.now.to_formatted_s(:number)}.csv",
type: "#{Mime[:csv]}; charset=utf-8"

View file

@ -6,7 +6,8 @@ module Admin
params[:q] ||= {}
domains = BlockedDomain.all.order(:name)
@q = domains.ransack(PartialSearchFormatter.format(params[:q]))
@domains = @q.result.page(params[:page])
@result = @q.result
@domains = @result.page(params[:page])
@domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i.positive?
render_by_format('admin/blocked_domains/index', 'blocked_domains')

View file

@ -10,8 +10,8 @@ module Admin
search_params = PartialSearchFormatter.format(fix_date_params)
versions = Version::ContactVersion.includes(:item).order(created_at: :desc, id: :desc)
@q = versions.ransack(polymorphic_association(search_params))
@versions = @q.result.page(params[:page])
@result = @q.result
@versions = @result.page(params[:page])
@versions = @versions.per(params[:results_per_page]) if params[:results_per_page].to_i.positive?
render_by_format('admin/contact_versions/index', 'contact_history')
@ -24,7 +24,7 @@ module Admin
@versions_map = @versions.all.map(&:id)
# what we do is calc amount of results until needed version
# then we cacl which page it is
# then we calc which page it is
if params[:page].blank?
counter = @versions_map.index(@version.id) + 1
page = counter / per_page

View file

@ -19,7 +19,8 @@ module Admin
normalize_search_parameters do
@q = contacts.ransack(PartialSearchFormatter.format(search_params))
@contacts = @q.result.distinct.page(params[:page])
@result = @q.result.distinct
@contacts = @result.page(params[:page])
end
@contacts = @contacts.per(params[:results_per_page]) if params[:results_per_page].to_i.positive?

View file

@ -57,7 +57,8 @@ module Admin
def sortable_dispute_query_for(disputes, query, closed: false)
@q = disputes.order(:domain_name).ransack(query)
disputes = @q.result.page(closed ? params[:closed_page] : params[:page])
@result = @q.result
disputes = @result.page(closed ? params[:closed_page] : params[:page])
return disputes.per(params[:results_per_page]) if params[:results_per_page].present?
disputes

View file

@ -47,8 +47,8 @@ module Admin
versions = Version::DomainVersion.includes(:item).where(where_s).order(created_at: :desc, id: :desc)
@q = versions.ransack(fix_date_params)
@versions = @q.result.page(params[:page])
@result = @q.result
@versions = @result.page(params[:page])
@versions = @versions.per(params[:results_per_page]) if params[:results_per_page].to_i.positive?
render_by_format('admin/domain_versions/archive', 'domain_history')

View file

@ -8,35 +8,21 @@ module Admin
# 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])
@result = @q.result.distinct
@domains = @result.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
@domain.validate
end
def edit
build_associations
end
# rubocop:disable Metrics/MethodLength
def update
rollback_history = @domain.json_statuses_history&.[]('admin_store_statuses_history')
dp = ignore_empty_statuses
@ -56,6 +42,15 @@ module Admin
end
# rubocop:enable Metrics/MethodLength
def show
# Validation is needed to warn users
@domain.validate
end
def edit
build_associations
end
def versions
@domain = Domain.where(id: params[:domain_id]).includes({ versions: :item }).first
@versions = @domain.versions

View file

@ -6,9 +6,10 @@ module Admin
# rubocop:disable Metrics/MethodLength
def index
@q = ApiLog::EppLog.ransack(PartialSearchFormatter.format(params[:q]))
@result = @q.result
@q.sorts = 'id desc' if @q.sorts.empty?
@epp_logs = @q.result
@epp_logs = @result
if params[:q][:created_at_gteq].present?
@epp_logs = @epp_logs.where("extract(epoch from created_at) >= extract(epoch from ?::timestamp)",
Time.parse(params[:q][:created_at_gteq]))

View file

@ -39,7 +39,8 @@ module Admin
@q = invoices.ransack(params[:q])
@q.sorts = 'number desc' if @q.sorts.empty?
@invoices = @q.result.page(params[:page])
@result = @q.result
@invoices = @result.page(params[:page])
@invoices = @invoices.per(params[:results_per_page]) if paginate?
render_by_format('admin/invoices/index', 'invoices')

View file

@ -7,8 +7,8 @@ module Admin
def index
@q = ApiLog::ReppLog.ransack(PartialSearchFormatter.format(params[:q]))
@q.sorts = 'id desc' if @q.sorts.empty?
@repp_logs = @q.result
@result = @q.result
@repp_logs = @result
if params[:q][:created_at_gteq].present?
@repp_logs = @repp_logs.where("extract(epoch from created_at) >= extract(epoch from ?::timestamp)",
Time.parse(params[:q][:created_at_gteq]))

View file

@ -7,7 +7,8 @@ module Admin
params[:q] ||= {}
domains = ReservedDomain.all.order(:name)
@q = domains.ransack(PartialSearchFormatter.format(params[:q]))
@domains = @q.result.page(params[:page])
@result = @q.result
@domains = @result.page(params[:page])
@domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i.positive?
render_by_format('admin/reserved_domains/index', 'reserved_domains')

View file

@ -16,12 +16,12 @@ class Account < ApplicationRecord
[id, balance, currency, registrar]
end
def self.ransackable_associations(auth_object = nil)
super
def self.ransackable_associations(*)
authorizable_ransackable_associations
end
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
def self.csv_header

View file

@ -25,12 +25,12 @@ class AccountActivity < ApplicationRecord
end
class << self
def ransackable_attributes(auth_object = nil)
super
def ransackable_associations(*)
authorizable_ransackable_associations
end
def ransackable_associations(auth_object = nil)
super
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
def types_for_select

View file

@ -5,12 +5,12 @@ module ApiLog
# for a configuration lookup is deprecated
establish_connection "api_log_#{Rails.env}".to_sym
def self.ransackable_associations(auth_object = nil)
super
def self.ransackable_associations(*)
authorizable_ransackable_associations
end
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
end
end

View file

@ -33,12 +33,12 @@ class Auction < ApplicationRecord
where('domain ilike ?', "%#{domain_name.strip}%") if domain_name.present?
}
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_associations(*)
authorizable_ransackable_associations
end
def self.ransackable_associations(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
def self.pending(domain_name)

View file

@ -10,8 +10,8 @@ class BankStatement < ApplicationRecord
PARTIALLY_BINDED = 'partially_binded'.freeze
NOT_BINDED = 'not_binded'.freeze
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
# TODO: Cache this to database so it can be used for searching

View file

@ -8,12 +8,12 @@ class BankTransaction < ApplicationRecord # rubocop:disable Metrics/ClassLength
where('id NOT IN (SELECT bank_transaction_id FROM account_activities where bank_transaction_id IS NOT NULL)')
}
def self.ransackable_associations(auth_object = nil)
super
def self.ransackable_associations(*)
authorizable_ransackable_associations
end
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
def binded?

View file

@ -21,8 +21,8 @@ module Billing
new_record? || duration_changed?
end
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
def self.operation_categories

View file

@ -6,12 +6,12 @@ class BlockedDomain < ApplicationRecord
validates :name, domain_name: true, uniqueness: true
class << self
def ransackable_attributes(auth_object = nil)
super
def ransackable_associations(*)
authorizable_ransackable_associations
end
def ransackable_associations(auth_object = nil)
super
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
def by_domain(name)

View file

@ -183,12 +183,12 @@ class Contact < ApplicationRecord
#
class << self
def ransackable_associations(auth_object = nil)
super
def ransackable_associations(*)
authorizable_ransackable_associations
end
def ransackable_attributes(auth_object = nil)
super
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
def search_by_query(query)

View file

@ -21,12 +21,12 @@ class Dispute < ApplicationRecord # rubocop:disable Metrics/ClassLength
Domain.find_by(name: domain_name)
end
def self.ransackable_associations(auth_object = nil)
super
def self.ransackable_associations(*)
authorizable_ransackable_associations
end
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
def self.close_by_domain(domain_name)

View file

@ -154,30 +154,30 @@ class Domain < ApplicationRecord
validates :nameservers, domain_nameserver: {
min: -> { Setting.ns_min_count },
max: -> { Setting.ns_max_count }
max: -> { Setting.ns_max_count },
}
validates :dnskeys, object_count: {
min: -> { Setting.dnskeys_min_count },
max: -> { Setting.dnskeys_max_count }
max: -> { Setting.dnskeys_max_count },
}
validates :admin_domain_contacts, object_count: {
min: -> { Setting.admin_contacts_min_count },
max: -> { Setting.admin_contacts_max_count }
max: -> { Setting.admin_contacts_max_count },
}
validates :tech_domain_contacts, object_count: {
min: -> { Setting.tech_contacts_min_count },
max: -> { Setting.tech_contacts_max_count }
max: -> { Setting.tech_contacts_max_count },
}
validates :nameservers, uniqueness_multi: {
attribute: 'hostname'
attribute: 'hostname',
}
validates :dnskeys, uniqueness_multi: {
attribute: 'public_key'
attribute: 'public_key',
}
validate :validate_nameserver_ips
@ -225,7 +225,7 @@ class Domain < ApplicationRecord
end
def delegated_nameservers
nameservers.select { |x| !x.hostname.end_with?(name) }
nameservers.reject { |x| x.hostname.end_with?(name) }
end
def extension_update_prohibited?
@ -245,12 +245,12 @@ class Domain < ApplicationRecord
end
class << self
def ransackable_associations(auth_object = nil)
super
def ransackable_associations(*)
authorizable_ransackable_associations
end
def ransackable_attributes(auth_object = nil)
super
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
def nameserver_required?
@ -604,17 +604,17 @@ class Domain < ApplicationRecord
# check for deleted status
statuses.each do |s|
unless update.include? s
case s
when DomainStatus::PENDING_DELETE
self.delete_date = nil
when DomainStatus::SERVER_MANUAL_INZONE # removal causes server hold to set
self.outzone_at = Time.zone.now if force_delete_scheduled?
when DomainStatus::EXPIRED # removal causes server hold to set
self.outzone_at = expire_time + 15.day
when DomainStatus::SERVER_HOLD # removal causes server hold to set
self.outzone_at = nil
end
next if update.include? s
case s
when DomainStatus::PENDING_DELETE
self.delete_date = nil
when DomainStatus::SERVER_MANUAL_INZONE # removal causes server hold to set
self.outzone_at = Time.zone.now if force_delete_scheduled?
when DomainStatus::EXPIRED # removal causes server hold to set
self.outzone_at = expire_time + 15.day
when DomainStatus::SERVER_HOLD # removal causes server hold to set
self.outzone_at = nil
end
end
end
@ -626,7 +626,7 @@ class Domain < ApplicationRecord
def set_pending_update
if pending_update_prohibited?
logger.info "DOMAIN STATUS UPDATE ISSUE ##{id}: PENDING_UPDATE not allowed to set. [#{statuses}]"
return nil
return
end
statuses << DomainStatus::PENDING_UPDATE
end
@ -655,7 +655,7 @@ class Domain < ApplicationRecord
def set_pending_delete
if pending_delete_prohibited?
logger.info "DOMAIN STATUS UPDATE ISSUE ##{id}: PENDING_DELETE not allowed to set. [#{statuses}]"
return nil
return
end
statuses << DomainStatus::PENDING_DELETE
end
@ -755,12 +755,17 @@ class Domain < ApplicationRecord
def as_csv_row
[
name,
registrant_name,
registrant_info[0],
registrant_info[1],
registrant_info[2],
registrant_info[3],
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,
]
@ -772,21 +777,31 @@ class Domain < ApplicationRecord
generator.to_pdf
end
def registrant_name
return registrant.name if registrant
def registrant_info
if registrant
return [registrant.name, registrant.ident, registrant.ident_country_code,
registrant.ident_type]
end
ver = Version::ContactVersion.where(item_id: registrant_id).last
contact = Contact.all_versions_for([registrant_id], created_at).first
contact = ObjectVersionsParser.new(ver).parse if contact.nil? && ver
contact.try(:name) || 'Deleted'
[contact.try(:name), contact.try(:ident), contact.try(:ident_country_code),
contact.try(:ident_type)] || ['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'
'Domain', 'Registrant name', 'Registrant ident', 'Registrant ident country code',
'Registrant ident type', 'Valid to', 'Registrar', 'Created at',
'Statuses', 'Admin. contacts', 'Tech. contacts', 'Nameservers', 'Force delete date',
'Force delete data'
]
end
@ -808,7 +823,7 @@ class Domain < ApplicationRecord
end
def self.uses_zone?(zone)
exists?(["name ILIKE ?", "%.#{zone.origin}"])
exists?(['name ILIKE ?', "%.#{zone.origin}"])
end
def self.swap_elements(array, indexes)

View file

@ -144,12 +144,12 @@ class Invoice < ApplicationRecord
]
end
def self.ransackable_associations(auth_object = nil)
super
def self.ransackable_associations(*)
authorizable_ransackable_associations
end
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
def self.csv_header

View file

@ -86,6 +86,10 @@ class Nameserver < ApplicationRecord
def hostnames
pluck(:hostname)
end
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
end
private

View file

@ -51,6 +51,14 @@ class Registrar < ApplicationRecord # rubocop:disable Metrics/ClassLength
self.ignored_columns = %w[legacy_id]
class << self
def ransackable_associations(*)
authorizable_ransackable_associations
end
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
def ordered
order(name: :asc)
end

View file

@ -13,12 +13,12 @@ class ReservedDomain < ApplicationRecord
self.ignored_columns = %w[legacy_id]
class << self
def ransackable_attributes(auth_object = nil)
super
def ransackable_associations(*)
authorizable_ransackable_associations
end
def ransackable_associations(auth_object = nil)
super
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
def pw_for(domain_name)

View file

@ -17,12 +17,12 @@ class Version::ContactVersion < PaperTrail::Version
]
end
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_associations(*)
authorizable_ransackable_associations
end
def self.ransackable_associations(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
def self.csv_header

View file

@ -11,19 +11,19 @@ class Version::DomainVersion < PaperTrail::Version
[
domain.name,
domain.registrant_name,
domain.registrant_info[0],
domain.registrar,
event,
created_at.to_formatted_s(:db)
created_at.to_formatted_s(:db),
]
end
def self.ransackable_attributes(auth_object = nil)
super
def self.ransackable_associations(*)
authorizable_ransackable_associations
end
def self.ransackable_associations(auth_object = nil)
super
def self.ransackable_attributes(*)
authorizable_ransackable_attributes
end
def self.was_contact_linked?(contact_id)

View file

@ -3,11 +3,23 @@ class PartialSearchFormatter
search_params = params.deep_dup
search_params.each do |key, value|
next unless key.include?('matches') && value.present?
next unless should_format?(key, value)
search_params[key] = "%#{value}%"
search_params[key] = format_value(value)
end
search_params
end
def self.should_format?(key, value)
key.include?('matches') && value.present?
end
def self.format_value(value)
if value =~ /\A\*.*\*\z/
value.gsub(/\A\*|\*\z/, '')
else
"%#{value}%"
end
end
end

View file

@ -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

View file

@ -1,5 +1,5 @@
<tr>
<td><%= link_to domain, admin_domain_path(domain) %></td>
<td style="word-break:break-all;"><%= link_to domain, admin_domain_path(domain) %></td>
<td><%= link_to domain.registrant, admin_contact_path(domain.registrant) %></td>
<td><%= l domain.expire_time %></td>
<td><%= link_to domain.registrar, admin_registrar_path(domain.registrar) %></td>

View file

@ -67,7 +67,7 @@
</div>
<div class="row">
<div class="col-md-5"></div>
<div class="col-md-5">Tip: Use format *text* for exact match!</div>
<div class="col-md-3"></div>
<div class="col-md-4">
<div class="form-group">

View file

@ -1,2 +1,2 @@
Domain,Registrant,Valid to,Registrar,Created at,Statuses,Contacts code,Force delete date,Force delete data
metro.test,Jack,2010-07-05 00:00:00,Good Names,2010-07-05 07:30:00,[],"[""jack-001"", ""jack-001""]",,
Domain,Registrant name,Registrant ident,Registrant ident country code,Registrant ident type,Valid to,Registrar,Created at,Statuses,Admin. contacts,Tech. contacts,Nameservers,Force delete date,Force delete data
metro.test,Jack,12345678,US,org,2010-07-05 00:00:00,Good Names,2010-07-05 07:30:00,[],"[""Jack, jack-001, 12345678 [US org]""]","[""Jack, jack-001, 12345678 [US org]""]","[""ns1.bestnames.test""]",,

1 Domain Registrant Registrant name Registrant ident Registrant ident country code Registrant ident type Valid to Contacts code Registrar Created at Statuses Admin. contacts Tech. contacts Nameservers Force delete date Force delete data
2 metro.test Jack Jack 12345678 US org 2010-07-05 00:00:00 ["jack-001", "jack-001"] Good Names 2010-07-05 07:30:00 [] ["Jack, jack-001, 12345678 [US org]"] ["Jack, jack-001, 12345678 [US org]"] ["ns1.bestnames.test"]