2018-08-02 00:09:29 +02:00
|
|
|
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Jeremy Lecour <jlecour@evolix.fr>, 2018 Evolix <info@evolix.fr>
|
|
|
|
# License: GNU AGPL-3+ (see full text in LICENSE file)
|
2018-05-29 10:28:03 +02:00
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: checks
|
|
|
|
#
|
2018-08-01 10:32:34 +02:00
|
|
|
# id :bigint(8) not null, primary key
|
|
|
|
# active :boolean default(TRUE), not null
|
|
|
|
# comment :string(255)
|
|
|
|
# consecutive_failures :integer default(0), not null
|
|
|
|
# domain :string(255) not null
|
|
|
|
# domain_created_at :datetime
|
|
|
|
# domain_expires_at :datetime
|
|
|
|
# domain_updated_at :datetime
|
|
|
|
# kind :integer not null
|
|
|
|
# last_run_at :datetime
|
|
|
|
# last_success_at :datetime
|
2018-08-29 16:31:13 +02:00
|
|
|
# mode :integer default("auto"), not null
|
2018-07-25 11:57:07 +02:00
|
|
|
# round_robin :boolean default(TRUE)
|
2018-08-01 10:32:34 +02:00
|
|
|
# vendor :string(255)
|
|
|
|
# created_at :datetime not null
|
|
|
|
# updated_at :datetime not null
|
|
|
|
# user_id :bigint(8)
|
2018-05-29 10:28:03 +02:00
|
|
|
#
|
|
|
|
# Indexes
|
|
|
|
#
|
|
|
|
# index_checks_on_user_id (user_id)
|
|
|
|
#
|
|
|
|
# Foreign Keys
|
|
|
|
#
|
|
|
|
# fk_rails_... (user_id => users.id)
|
|
|
|
#
|
|
|
|
|
|
|
|
class Check < ApplicationRecord
|
|
|
|
belongs_to :user
|
2018-07-05 16:26:15 +02:00
|
|
|
has_many :logs, class_name: "CheckLog", dependent: :destroy
|
2018-08-30 11:08:37 +02:00
|
|
|
has_many :check_notifications, dependent: :destroy
|
2018-08-30 18:40:23 +02:00
|
|
|
has_many :notifications, -> { order(checks_count: :desc) },
|
|
|
|
through: :check_notifications, validate: true
|
2018-08-30 11:08:37 +02:00
|
|
|
|
2018-06-04 20:39:53 +02:00
|
|
|
accepts_nested_attributes_for :notifications,
|
2018-08-30 20:09:52 +02:00
|
|
|
reject_if: lambda { |att| att["interval"].blank? }
|
2018-05-29 10:28:03 +02:00
|
|
|
|
|
|
|
enum kind: [:domain, :ssl]
|
2018-08-29 16:31:13 +02:00
|
|
|
enum mode: [:auto, :manual]
|
2018-05-29 10:28:03 +02:00
|
|
|
|
2019-08-20 01:14:50 +02:00
|
|
|
# Those dates are written as UTC,
|
|
|
|
# but not converted back when read from the database
|
2018-05-29 10:28:03 +02:00
|
|
|
self.skip_time_zone_conversion_for_attributes = [
|
|
|
|
:domain_created_at,
|
|
|
|
:domain_updated_at,
|
2018-06-02 17:45:50 +02:00
|
|
|
:domain_expires_at,
|
2018-05-29 10:28:03 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
validates :kind, presence: true
|
|
|
|
validates :domain, presence: true
|
2018-05-29 13:11:22 +02:00
|
|
|
validate :domain_created_at_past
|
|
|
|
validate :domain_updated_at_past
|
2018-08-29 16:42:00 +02:00
|
|
|
validates :domain_expires_at, presence: true, unless: :supported?
|
2018-05-29 13:11:22 +02:00
|
|
|
validates :comment, length: { maximum: 255 }
|
|
|
|
validates :vendor, length: { maximum: 255 }
|
|
|
|
|
2018-08-01 10:37:06 +02:00
|
|
|
before_save :reset_consecutive_failures
|
2018-08-29 16:33:36 +02:00
|
|
|
before_save :set_mode
|
2018-08-30 11:08:37 +02:00
|
|
|
after_update :reset_check_notifications
|
2018-05-30 18:16:43 +02:00
|
|
|
after_save :enqueue_sync
|
|
|
|
|
2018-06-05 15:24:44 +02:00
|
|
|
scope :active, -> { where(active: true) }
|
|
|
|
scope :last_run_failed, -> {
|
|
|
|
where("(last_success_at IS NULL AND last_run_at IS NOT NULL)
|
|
|
|
OR (last_success_at <= DATE_SUB(last_run_at, INTERVAL 5 MINUTE))")
|
|
|
|
}
|
|
|
|
|
2018-07-03 20:11:52 +02:00
|
|
|
scope :kind, ->(kind) { where(kind: kind) }
|
|
|
|
scope :by_domain, ->(domain) { where("domain LIKE ?", "%#{domain}%") }
|
2018-07-24 14:57:26 +02:00
|
|
|
scope :consecutive_failures, ->(consecutive) {
|
|
|
|
where("consecutive_failures >= ?", consecutive)
|
2018-07-04 11:55:44 +02:00
|
|
|
}
|
2018-07-03 20:11:52 +02:00
|
|
|
|
|
|
|
def self.default_sort
|
2018-07-05 10:24:26 +02:00
|
|
|
[:domain_expires_at, :asc]
|
2018-07-03 20:11:52 +02:00
|
|
|
end
|
|
|
|
|
2018-07-04 19:05:52 +02:00
|
|
|
def days_from_last_success
|
|
|
|
return unless last_success_at.present?
|
|
|
|
|
2019-08-20 00:46:52 +02:00
|
|
|
# return the number of whole days
|
|
|
|
((Time.now - last_success_at) / (24 * 3600)).to_i
|
2018-07-04 19:05:52 +02:00
|
|
|
end
|
|
|
|
|
2018-08-01 10:37:06 +02:00
|
|
|
def increment_consecutive_failures!
|
|
|
|
self.consecutive_failures += 1
|
2018-08-31 14:26:03 +02:00
|
|
|
save!(validate: false)
|
2018-08-01 10:37:06 +02:00
|
|
|
end
|
|
|
|
|
2018-08-29 16:32:52 +02:00
|
|
|
def supported?
|
|
|
|
return true unless domain?
|
|
|
|
return true if domain.blank?
|
|
|
|
|
|
|
|
begin
|
|
|
|
Whois::Parser.for(domain)
|
|
|
|
true
|
|
|
|
rescue Whois::UnsupportedDomainError
|
|
|
|
false
|
|
|
|
rescue StandardError
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-08-20 01:10:54 +02:00
|
|
|
def domain_expires_in_days
|
|
|
|
Integer(domain_expires_at.to_date - Time.now.utc.to_date)
|
|
|
|
end
|
|
|
|
|
2018-06-04 14:06:37 +02:00
|
|
|
private
|
2018-05-29 13:11:22 +02:00
|
|
|
|
|
|
|
def domain_created_at_past
|
|
|
|
errors.add(:domain_created_at, :past) if domain_created_at.present? && domain_created_at.future?
|
|
|
|
end
|
|
|
|
|
|
|
|
def domain_updated_at_past
|
|
|
|
errors.add(:domain_updated_at, :past) if domain_updated_at.present? && domain_updated_at.future?
|
|
|
|
end
|
2018-05-30 18:16:43 +02:00
|
|
|
|
|
|
|
def enqueue_sync
|
|
|
|
return unless active?
|
|
|
|
return unless saved_changes.key?("domain")
|
|
|
|
|
2018-07-05 17:54:21 +02:00
|
|
|
ResyncJob.perform_later(id)
|
2018-05-30 18:16:43 +02:00
|
|
|
end
|
2018-06-04 14:06:37 +02:00
|
|
|
|
2018-08-30 11:08:37 +02:00
|
|
|
def reset_check_notifications
|
2018-06-04 14:06:37 +02:00
|
|
|
return unless (saved_changes.keys & %w[domain domain_expires_at]).present?
|
|
|
|
|
2018-08-30 11:08:37 +02:00
|
|
|
check_notifications.each(&:reset!)
|
2018-06-04 14:06:37 +02:00
|
|
|
end
|
2018-08-01 10:37:06 +02:00
|
|
|
|
|
|
|
def reset_consecutive_failures
|
2018-08-31 14:27:00 +02:00
|
|
|
return unless last_success_at_changed? || mode_changed? || domain_changed?
|
2018-08-01 10:37:06 +02:00
|
|
|
return if consecutive_failures_changed?
|
|
|
|
|
|
|
|
self.consecutive_failures = 0
|
|
|
|
end
|
2018-08-29 16:33:36 +02:00
|
|
|
|
|
|
|
def set_mode
|
|
|
|
return unless domain_changed?
|
|
|
|
self.mode = supported? ? :auto : :manual
|
|
|
|
end
|
2018-05-29 10:28:03 +02:00
|
|
|
end
|