mirror of
https://github.com/Evolix/chexpire.git
synced 2024-05-05 18:25:09 +02:00
Merge pull request #50 from Evolix/notifications-improvements
Notifications improvements
This commit is contained in:
commit
b3bcaa92f9
|
@ -13,9 +13,12 @@ addons:
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- cp config/database.example.yml config/database.yml
|
- cp config/database.example.yml config/database.yml
|
||||||
- cp config/chexpire.test.yml config/chexpire.yml
|
|
||||||
- cp config/secrets.example.yml config/secrets.yml
|
- cp config/secrets.example.yml config/secrets.yml
|
||||||
|
|
||||||
|
# Test configuration loaded from chexpire.defaults.yml,
|
||||||
|
# but chexpire.yml file is required
|
||||||
|
- touch config/chexpire.yml
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- bundle install
|
- bundle install
|
||||||
- yarn install
|
- yarn install
|
||||||
|
|
1
Gemfile
1
Gemfile
|
@ -38,6 +38,7 @@ gem 'bcrypt', '~> 3.1.7'
|
||||||
|
|
||||||
gem 'open4'
|
gem 'open4'
|
||||||
gem 'naught'
|
gem 'naught'
|
||||||
|
gem 'hashie'
|
||||||
gem 'whenever', require: false
|
gem 'whenever', require: false
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,7 @@ GEM
|
||||||
has_scope (0.7.2)
|
has_scope (0.7.2)
|
||||||
actionpack (>= 4.1)
|
actionpack (>= 4.1)
|
||||||
activesupport (>= 4.1)
|
activesupport (>= 4.1)
|
||||||
|
hashie (3.5.7)
|
||||||
i18n (1.0.1)
|
i18n (1.0.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
io-like (0.3.0)
|
io-like (0.3.0)
|
||||||
|
@ -354,6 +355,7 @@ DEPENDENCIES
|
||||||
guard
|
guard
|
||||||
guard-minitest
|
guard-minitest
|
||||||
has_scope
|
has_scope
|
||||||
|
hashie
|
||||||
jbuilder (~> 2.5)
|
jbuilder (~> 2.5)
|
||||||
kaminari
|
kaminari
|
||||||
launchy
|
launchy
|
||||||
|
|
|
@ -45,11 +45,13 @@ To use elliptic curve SSH keys, we need to have `libsodium` and its headers.
|
||||||
|
|
||||||
## Rails configuration
|
## Rails configuration
|
||||||
|
|
||||||
After cloning this repository, you have to create and edit a few files from example files, for your local development configuration :
|
After cloning this repository, you have to create and edit a few files from example or defaults files, for your local development configuration :
|
||||||
|
|
||||||
- `config/database.yml`
|
- `config/database.yml`
|
||||||
- `config/chexpire.yml`
|
|
||||||
- `config/secrets.yml`
|
- `config/secrets.yml`
|
||||||
|
- `config/chexpire.yml` : set at least the `mailer_default_from` and `host` variables. See other configuration overridable in `config/chexpire.defaults.yml`.
|
||||||
|
|
||||||
|
Theses files will be ignored by git.
|
||||||
|
|
||||||
## Database
|
## Database
|
||||||
|
|
||||||
|
|
|
@ -62,5 +62,5 @@ Finally, you have to write the way the checks will be notified to theirs users.
|
||||||
- expires_soon
|
- expires_soon
|
||||||
- recurrent_failures
|
- recurrent_failures
|
||||||
|
|
||||||
First, add your checks kinds and these notifications definitions in the base class for notifier: `app/services/notifier/base.rb` : in the notify method, for your new check kind, a specific method will be called in each notifier. For example, in the email channel, a specific mailer action is called for each couple (check kin, notification kind).
|
First, add your checks kinds and these notifications definitions in the base class for notifier: `app/services/notifier/channels/base.rb` : in the notify method, for your new check kind, a specific method will be called in each notifier. For example, in the email channel, a specific mailer action is called for each couple (check kin, notification kind).
|
||||||
Then, in each notifier class, implements the details of this method. If you want to ignore a notification for a given channel, simply write the method and do nothing.
|
Then, in each notifier class, implements the details of this method. If you want to ignore a notification for a given channel, simply write the method and do nothing.
|
||||||
|
|
|
@ -6,7 +6,9 @@ class ChecksController < ApplicationController
|
||||||
|
|
||||||
has_scope :kind
|
has_scope :kind
|
||||||
has_scope :by_domain
|
has_scope :by_domain
|
||||||
has_scope :recurrent_failures, type: :boolean
|
has_scope :recurrent_failures, type: :boolean do |_controller, scope, _value|
|
||||||
|
scope.consecutive_failures(Rails.configuration.chexpire.interface.consecutive_failures_as_error)
|
||||||
|
end
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@checks = apply_scopes(policy_scope(Check)).order(Hash[*current_sort]).page(params[:page])
|
@checks = apply_scopes(policy_scope(Check)).order(Hash[*current_sort]).page(params[:page])
|
||||||
|
|
|
@ -29,7 +29,12 @@ module ChecksHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_in_error(check)
|
def check_in_error?(check)
|
||||||
|
check.consecutive_failures >=
|
||||||
|
Rails.configuration.chexpire.interface.consecutive_failures_as_error
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_error(check)
|
||||||
content_tag(
|
content_tag(
|
||||||
:span,
|
:span,
|
||||||
Octicons::Octicon.new("alert", class: "ml-1").to_svg.html_safe,
|
Octicons::Octicon.new("alert", class: "ml-1").to_svg.html_safe,
|
||||||
|
|
|
@ -1,34 +1,38 @@
|
||||||
class NotificationsMailer < ApplicationMailer
|
class NotificationsMailer < ApplicationMailer
|
||||||
helper :application
|
helper :application
|
||||||
|
|
||||||
before_action do
|
before_action except: :recurrent_failures do
|
||||||
@notification = params.fetch(:notification)
|
@notification = params.fetch(:notification)
|
||||||
@check = @notification.check
|
@check = @notification.check
|
||||||
end
|
end
|
||||||
|
|
||||||
default to: -> { @notification.recipient }
|
|
||||||
|
|
||||||
def domain_expires_soon
|
def domain_expires_soon
|
||||||
@expire_in_days = Integer(@check.domain_expires_at.to_date - Date.today)
|
@expire_in_days = Integer(@check.domain_expires_at.to_date - Date.today)
|
||||||
|
|
||||||
subject = t(".subject", domain: @check.domain, count: @expire_in_days)
|
I18n.with_locale params&.fetch(:locale) { @check.user.locale } do
|
||||||
mail subject: subject
|
subject = t(".subject", domain: @check.domain, count: @expire_in_days)
|
||||||
end
|
mail subject: subject, to: @notification.recipient
|
||||||
|
end
|
||||||
def domain_recurrent_failures
|
|
||||||
subject = t(".subject", domain: @check.domain)
|
|
||||||
mail subject: subject
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def ssl_expires_soon
|
def ssl_expires_soon
|
||||||
@expire_in_days = Integer(@check.domain_expires_at.to_date - Date.today)
|
@expire_in_days = Integer(@check.domain_expires_at.to_date - Date.today)
|
||||||
|
|
||||||
subject = t(".subject", domain: @check.domain, count: @expire_in_days)
|
I18n.with_locale params&.fetch(:locale) { @check.user.locale } do
|
||||||
mail subject: subject
|
subject = t(".subject", domain: @check.domain, count: @expire_in_days)
|
||||||
|
mail subject: subject, to: @notification.recipient
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def ssl_recurrent_failures
|
def recurrent_failures(user, checks)
|
||||||
subject = t(".subject", domain: @check.domain)
|
@checks = checks
|
||||||
mail subject: subject
|
|
||||||
|
# params generally not set, except for preview mailer
|
||||||
|
params_locale = (params[:locale] if params.present?)
|
||||||
|
|
||||||
|
I18n.with_locale params_locale || user.locale do
|
||||||
|
subject = t(".subject", count: checks.count, domain: checks.first.domain)
|
||||||
|
mail subject: subject, to: user.email
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,20 +2,21 @@
|
||||||
#
|
#
|
||||||
# Table name: checks
|
# Table name: checks
|
||||||
#
|
#
|
||||||
# id :bigint(8) not null, primary key
|
# id :bigint(8) not null, primary key
|
||||||
# active :boolean default(TRUE), not null
|
# active :boolean default(TRUE), not null
|
||||||
# comment :string(255)
|
# comment :string(255)
|
||||||
# domain :string(255) not null
|
# consecutive_failures :integer default(0), not null
|
||||||
# domain_created_at :datetime
|
# domain :string(255) not null
|
||||||
# domain_expires_at :datetime
|
# domain_created_at :datetime
|
||||||
# domain_updated_at :datetime
|
# domain_expires_at :datetime
|
||||||
# kind :integer not null
|
# domain_updated_at :datetime
|
||||||
# last_run_at :datetime
|
# kind :integer not null
|
||||||
# last_success_at :datetime
|
# last_run_at :datetime
|
||||||
# vendor :string(255)
|
# last_success_at :datetime
|
||||||
# created_at :datetime not null
|
# vendor :string(255)
|
||||||
# updated_at :datetime not null
|
# created_at :datetime not null
|
||||||
# user_id :bigint(8)
|
# updated_at :datetime not null
|
||||||
|
# user_id :bigint(8)
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
@ -27,8 +28,6 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
class Check < ApplicationRecord
|
class Check < ApplicationRecord
|
||||||
ERROR_DELAY_DAYS = 3
|
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_many :logs, class_name: "CheckLog", dependent: :destroy
|
has_many :logs, class_name: "CheckLog", dependent: :destroy
|
||||||
has_many :notifications, validate: true, dependent: :destroy
|
has_many :notifications, validate: true, dependent: :destroy
|
||||||
|
@ -51,6 +50,7 @@ class Check < ApplicationRecord
|
||||||
validates :comment, length: { maximum: 255 }
|
validates :comment, length: { maximum: 255 }
|
||||||
validates :vendor, length: { maximum: 255 }
|
validates :vendor, length: { maximum: 255 }
|
||||||
|
|
||||||
|
before_save :reset_consecutive_failures
|
||||||
after_update :reset_notifications
|
after_update :reset_notifications
|
||||||
after_save :enqueue_sync
|
after_save :enqueue_sync
|
||||||
|
|
||||||
|
@ -62,30 +62,25 @@ class Check < ApplicationRecord
|
||||||
|
|
||||||
scope :kind, ->(kind) { where(kind: kind) }
|
scope :kind, ->(kind) { where(kind: kind) }
|
||||||
scope :by_domain, ->(domain) { where("domain LIKE ?", "%#{domain}%") }
|
scope :by_domain, ->(domain) { where("domain LIKE ?", "%#{domain}%") }
|
||||||
scope :recurrent_failures, -> {
|
scope :consecutive_failures, ->(consecutive) {
|
||||||
interval = "INTERVAL #{ERROR_DELAY_DAYS} DAY"
|
where("consecutive_failures >= ?", consecutive)
|
||||||
where("last_run_at IS NOT NULL AND created_at <= DATE_SUB(NOW(), #{interval})")
|
|
||||||
.where("last_success_at IS NULL OR last_success_at <= DATE_SUB(last_run_at, #{interval})")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def self.default_sort
|
def self.default_sort
|
||||||
[:domain_expires_at, :asc]
|
[:domain_expires_at, :asc]
|
||||||
end
|
end
|
||||||
|
|
||||||
def in_error?
|
|
||||||
return false if created_at > ERROR_DELAY_DAYS.days.ago
|
|
||||||
return false if last_run_at.nil?
|
|
||||||
return true if last_success_at.nil?
|
|
||||||
|
|
||||||
last_success_at < ERROR_DELAY_DAYS.days.ago
|
|
||||||
end
|
|
||||||
|
|
||||||
def days_from_last_success
|
def days_from_last_success
|
||||||
return unless last_success_at.present?
|
return unless last_success_at.present?
|
||||||
|
|
||||||
(Date.today - last_success_at.to_date).to_i
|
(Date.today - last_success_at.to_date).to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def increment_consecutive_failures!
|
||||||
|
self.consecutive_failures += 1
|
||||||
|
save!
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def domain_created_at_past
|
def domain_created_at_past
|
||||||
|
@ -108,4 +103,11 @@ class Check < ApplicationRecord
|
||||||
|
|
||||||
notifications.each(&:reset!)
|
notifications.each(&:reset!)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reset_consecutive_failures
|
||||||
|
return unless last_success_at_changed?
|
||||||
|
return if consecutive_failures_changed?
|
||||||
|
|
||||||
|
self.consecutive_failures = 0
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
class CheckLogger
|
class CheckLogger
|
||||||
|
attr_reader :check
|
||||||
attr_reader :check_log
|
attr_reader :check_log
|
||||||
|
|
||||||
def initialize(check)
|
def initialize(check)
|
||||||
|
@check = check
|
||||||
@check_log = CheckLog.create!(check: check, status: :pending)
|
@check_log = CheckLog.create!(check: check, status: :pending)
|
||||||
|
@error_logged = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def log(event, message)
|
def log(event, message)
|
||||||
|
@ -12,7 +15,13 @@ class CheckLogger
|
||||||
when :parsed_response
|
when :parsed_response
|
||||||
log_parsed_response(message)
|
log_parsed_response(message)
|
||||||
when :parser_error, :service_error, :standard_error
|
when :parser_error, :service_error, :standard_error
|
||||||
|
# avoid multiple logging & wrong incrementation of consecutive failures
|
||||||
|
# (because a Service exception could be re-raised from a Job)
|
||||||
|
return if error_logged?
|
||||||
|
|
||||||
log_error(message)
|
log_error(message)
|
||||||
|
|
||||||
|
@error_logged = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -41,7 +50,12 @@ class CheckLogger
|
||||||
end
|
end
|
||||||
|
|
||||||
def log_error(exception)
|
def log_error(exception)
|
||||||
|
check.increment_consecutive_failures!
|
||||||
check_log.error = [exception.message, exception.backtrace].join("\n")
|
check_log.error = [exception.message, exception.backtrace].join("\n")
|
||||||
check_log.failed!
|
check_log.failed!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def error_logged?
|
||||||
|
@error_logged
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,14 +28,14 @@ module CheckProcessor
|
||||||
def resolve_expire_long_term
|
def resolve_expire_long_term
|
||||||
scope
|
scope
|
||||||
.where("DATE(domain_expires_at) >= DATE_ADD(CURDATE(), INTERVAL ? DAY)",
|
.where("DATE(domain_expires_at) >= DATE_ADD(CURDATE(), INTERVAL ? DAY)",
|
||||||
configuration.long_term)
|
configuration.long_term_interval)
|
||||||
.where("DATEDIFF(domain_expires_at, CURDATE()) MOD ? = 0",
|
.where("DATEDIFF(domain_expires_at, CURDATE()) MOD ? = 0",
|
||||||
configuration.long_term_frequency)
|
configuration.long_term_frequency)
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_expire_short_term
|
def resolve_expire_short_term
|
||||||
scope.where("DATE(domain_expires_at) < DATE_ADD(CURDATE(), INTERVAL ? DAY)",
|
scope.where("DATE(domain_expires_at) < DATE_ADD(CURDATE(), INTERVAL ? DAY)",
|
||||||
configuration.long_term)
|
configuration.long_term_interval)
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_unknown_expiry
|
def resolve_unknown_expiry
|
||||||
|
@ -71,12 +71,6 @@ module CheckProcessor
|
||||||
private
|
private
|
||||||
|
|
||||||
def default_configuration
|
def default_configuration
|
||||||
config = Rails.configuration.chexpire.fetch(configuration_key, {})
|
Rails.configuration.chexpire.fetch(configuration_key)
|
||||||
|
|
||||||
OpenStruct.new(
|
|
||||||
interval: config.fetch("interval") { 0.00 },
|
|
||||||
long_term: config.fetch("long_term") { 60 },
|
|
||||||
long_term_frequency: config.fetch("long_term_frequency") { 10 },
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,39 +1,33 @@
|
||||||
module Notifier
|
module Notifier
|
||||||
module Channels
|
module Channels
|
||||||
class Base
|
class Base
|
||||||
def notify(reason, notification) # rubocop:disable Metrics/MethodLength
|
def notify(notification) # rubocop:disable Metrics/MethodLength
|
||||||
return unless supports?(reason, notification)
|
return unless supports?(notification)
|
||||||
|
|
||||||
notification.ongoing!
|
notification.ongoing!
|
||||||
|
|
||||||
case [notification.check.kind.to_sym, reason]
|
case notification.check.kind.to_sym
|
||||||
when [:domain, :expires_soon]
|
when :domain
|
||||||
domain_notify_expires_soon(notification)
|
domain_notify_expires_soon(notification)
|
||||||
when [:domain, :recurrent_failures]
|
when :ssl
|
||||||
domain_notify_recurrent_failures(notification)
|
|
||||||
when [:ssl, :expires_soon]
|
|
||||||
ssl_notify_expires_soon(notification)
|
ssl_notify_expires_soon(notification)
|
||||||
when [:ssl, :recurrent_failures]
|
|
||||||
ssl_notify_recurrent_failures(notification)
|
|
||||||
else
|
else
|
||||||
fail ArgumentError,
|
fail ArgumentError,
|
||||||
"Invalid notification reason `#{reason}` for check kind `#{notification.check.kind}`."
|
"Invalid notification for check kind `#{notification.check.kind}`."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# :nocov:
|
# :nocov:
|
||||||
def supports?(_reason, _notification)
|
def supports?(_notification)
|
||||||
fail NotImplementedError,
|
fail NotImplementedError,
|
||||||
"#{self.class.name} channel did not implemented method #{__callee__}"
|
"#{self.class.name} channel did not implemented method #{__callee__}"
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[
|
%i[
|
||||||
domain_notify_expires_soon
|
domain_notify_expires_soon
|
||||||
domain_notify_recurrent_failures
|
|
||||||
ssl_notify_expires_soon
|
ssl_notify_expires_soon
|
||||||
ssl_notify_recurrent_failures
|
|
||||||
].each do |method|
|
].each do |method|
|
||||||
define_method(method) do
|
define_method(method) do
|
||||||
fail NotImplementedError,
|
fail NotImplementedError,
|
||||||
|
|
|
@ -1,29 +1,25 @@
|
||||||
module Notifier
|
module Notifier
|
||||||
module Channels
|
module Channels
|
||||||
class Email < Base
|
class Email < Base
|
||||||
REASONS = %i[expires_soon recurrent_failures].freeze
|
# Error notifications - all checks grouped by user
|
||||||
|
def notify_recurrent_failures(user, checks)
|
||||||
|
NotificationsMailer.recurrent_failures(user, checks).deliver_now
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def supports?(reason, _notification)
|
def supports?(_notification)
|
||||||
REASONS.include?(reason)
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Expiration notifications
|
||||||
def domain_notify_expires_soon(notification)
|
def domain_notify_expires_soon(notification)
|
||||||
NotificationsMailer.with(notification: notification).domain_expires_soon.deliver_now
|
NotificationsMailer.with(notification: notification).domain_expires_soon.deliver_now
|
||||||
end
|
end
|
||||||
|
|
||||||
def domain_notify_recurrent_failures(notification)
|
|
||||||
NotificationsMailer.with(notification: notification).domain_recurrent_failures.deliver_now
|
|
||||||
end
|
|
||||||
|
|
||||||
def ssl_notify_expires_soon(notification)
|
def ssl_notify_expires_soon(notification)
|
||||||
NotificationsMailer.with(notification: notification).ssl_expires_soon.deliver_now
|
NotificationsMailer.with(notification: notification).ssl_expires_soon.deliver_now
|
||||||
end
|
end
|
||||||
|
|
||||||
def ssl_notify_recurrent_failures(notification)
|
|
||||||
NotificationsMailer.with(notification: notification).ssl_recurrent_failures.deliver_now
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module Notifier
|
module Notifier
|
||||||
Configuration = Struct.new(:interval, :failure_days)
|
Configuration = Struct.new(:interval, :consecutive_failures)
|
||||||
|
|
||||||
class Processor
|
class Processor
|
||||||
attr_reader :configuration
|
attr_reader :configuration
|
||||||
|
@ -16,18 +16,19 @@ module Notifier
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_expires_soon
|
def process_expires_soon
|
||||||
resolver.resolve_expires_soon.find_each do |notification|
|
resolver.notifications_expiring_soon.find_each do |notification|
|
||||||
notifier_channel_for(notification).notify(:expires_soon, notification)
|
notifier_channel_for(notification).notify(notification)
|
||||||
|
|
||||||
sleep configuration.interval
|
sleep configuration.interval
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Notify checks in error by email to the check owner adress email.
|
||||||
|
# A single email contains all checks for a same user.
|
||||||
def process_recurrent_failures
|
def process_recurrent_failures
|
||||||
resolver.resolve_check_failed.find_each do |notification|
|
failed_checks = resolver.checks_recurrent_failures(configuration.consecutive_failures)
|
||||||
next unless should_notify_for_recurrent_failures?(notification)
|
failed_checks.group_by(&:user).each_pair do |user, checks|
|
||||||
|
channels[:email].notify_recurrent_failures(user, checks)
|
||||||
notifier_channel_for(notification).notify(:recurrent_failures, notification)
|
|
||||||
|
|
||||||
sleep configuration.interval
|
sleep configuration.interval
|
||||||
end
|
end
|
||||||
|
@ -36,21 +37,11 @@ module Notifier
|
||||||
private
|
private
|
||||||
|
|
||||||
def default_configuration
|
def default_configuration
|
||||||
config = Rails.configuration.chexpire.fetch("notifier", {})
|
Rails.configuration.chexpire.fetch("notifier")
|
||||||
|
|
||||||
Configuration.new(
|
|
||||||
config.fetch("interval") { 0.00 },
|
|
||||||
config.fetch("failures_days") { 3 },
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def notifier_channel_for(notification)
|
def notifier_channel_for(notification)
|
||||||
channels.fetch(notification.channel.to_sym)
|
channels.fetch(notification.channel.to_sym)
|
||||||
end
|
end
|
||||||
|
|
||||||
def should_notify_for_recurrent_failures?(_notification)
|
|
||||||
true
|
|
||||||
# TODO: dependent of logs consecutive failures
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
module Notifier
|
module Notifier
|
||||||
class Resolver
|
class Resolver
|
||||||
def resolve_expires_soon
|
def notifications_expiring_soon
|
||||||
scope
|
scope
|
||||||
.where("checks.domain_expires_at >= CURDATE()")
|
.where("checks.domain_expires_at >= CURDATE()")
|
||||||
.where("DATE(checks.domain_expires_at)
|
.where("DATE(checks.domain_expires_at)
|
||||||
<= DATE_ADD(CURDATE(), INTERVAL notifications.interval DAY)")
|
<= DATE_ADD(CURDATE(), INTERVAL notifications.interval DAY)")
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_check_failed
|
def checks_recurrent_failures(min_consecutive)
|
||||||
# Only gets here the checks having its last run in error
|
Check
|
||||||
# Logical rules are in plain ruby inside processor
|
.active
|
||||||
scope
|
.consecutive_failures(min_consecutive)
|
||||||
.includes(check: :logs)
|
.includes(:user)
|
||||||
.merge(Check.last_run_failed)
|
.where.not(user: ignore_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<span class="badge badge-info"><%= t(".kind_labels.#{check.kind}") %></span>
|
<span class="badge badge-info"><%= t(".kind_labels.#{check.kind}") %></span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<%= check_in_error(check) if check.in_error? %>
|
<%= check_error(check) if check_in_error?(check) %>
|
||||||
<strong><%= check.domain %></strong>
|
<strong><%= check.domain %></strong>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<%- if @check.comment.present? -%>
|
<%- if check.comment.present? -%>
|
||||||
<p>
|
<p>
|
||||||
You wrote the following comment with this domain:
|
You wrote the following comment with this domain:
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<%= @check.comment -%>
|
<%= check.comment -%>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</p>
|
</p>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
|
|
||||||
<%- if @check.vendor.present? -%>
|
<%- if check.vendor.present? -%>
|
||||||
Vendor: <%= @check.vendor %>
|
Vendor: <%= check.vendor %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
<%- if @check.comment.present? -%>
|
<%- if check.comment.present? -%>
|
||||||
You wrote the following comment with this domain:
|
You wrote the following comment with this domain:
|
||||||
|
|
||||||
<%= @check.comment -%>
|
<%= check.comment -%>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
|
|
||||||
|
<%- if check.vendor.present? -%>
|
||||||
|
Vendor: <%= check.vendor %>
|
||||||
<%- if @check.vendor.present? -%>
|
|
||||||
Vendor: <%= @check.vendor %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<%- if @check.comment.present? -%>
|
<%- if check.comment.present? -%>
|
||||||
<p>
|
<p>
|
||||||
Vous avez saisi le commentaire suivant pour ce domaine :
|
Vous avez saisi le commentaire suivant pour ce domaine :
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<%= @check.comment -%>
|
<%= check.comment -%>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</p>
|
</p>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
|
|
||||||
<%- if @check.vendor.present? -%>
|
<%- if check.vendor.present? -%>
|
||||||
Fournisseur : <%= @check.vendor %>
|
Fournisseur : <%= check.vendor %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
<%- if @check.comment.present? -%>
|
<%- if check.comment.present? -%>
|
||||||
Vous avez saisi le commentaire suivant pour ce domaine :
|
Vous avez saisi le commentaire suivant pour ce domaine :
|
||||||
|
<%= check.comment -%>
|
||||||
<%= @check.comment -%>
|
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
|
|
||||||
|
<%- if check.vendor.present? -%>
|
||||||
|
Fournisseur : <%= check.vendor %>
|
||||||
<%- if @check.vendor.present? -%>
|
|
||||||
Fournisseur : <%= @check.vendor %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<p>
|
||||||
|
<strong>Domain: <%= check.domain %></strong> (<%= check.consecutive_failures %> consecutive errors)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<%- if check.domain_expires_at.present? %>
|
||||||
|
Last known expiry date : <%= format_utc(check.domain_expires_at) %>.
|
||||||
|
<br />
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%- if check.last_success_at.present? %>
|
||||||
|
Last successful check occured : <%= format_utc(check.last_success_at) %>.
|
||||||
|
<br />
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<p>If you have deleted your domain or have not renewed it, please disable
|
||||||
|
or delete the check by following this link: <br />
|
||||||
|
<%= edit_check_url(check) %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<%= render "check_comment_vendor", check: check %>
|
|
@ -0,0 +1,15 @@
|
||||||
|
Domain: <%= check.domain %> (<%= check.consecutive_failures %> consecutive errors)
|
||||||
|
<%= "-" * (check.domain.length + "Domain: ".length) %>
|
||||||
|
|
||||||
|
<%- if check.domain_expires_at.present? %>
|
||||||
|
Last known expiry date : <%= format_utc(check.domain_expires_at) %>.
|
||||||
|
<% end %>
|
||||||
|
<%- if check.last_success_at.present? %>
|
||||||
|
Last successful check occured : <%= format_utc(check.last_success_at) %>.
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
If you have deleted your domain or have not renewed it, please disable
|
||||||
|
or delete the check by following this link:
|
||||||
|
<%= edit_check_url(check) %>
|
||||||
|
|
||||||
|
<%= render "check_comment_vendor", check: check %>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<p>
|
||||||
|
<strong>Domaine: <%= check.domain %></strong> (<%= check.consecutive_failures %> erreurs consécutives)
|
||||||
|
<br />
|
||||||
|
<%- if check.domain_expires_at.present? %>
|
||||||
|
Dernière date d'expiration connue : <%= format_utc(check.domain_expires_at) %>.
|
||||||
|
<br />
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%- if check.last_success_at.present? %>
|
||||||
|
Dernière vérification réussie : <%= format_utc(check.last_success_at) %>.
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Si vous avez supprimé le domaine ou ne l'avez pas renouvellé, merci de désactiver la vérification associée, avec ce lien :<br />
|
||||||
|
<%= link_to nil, edit_check_url(check) %>
|
||||||
|
</p>
|
||||||
|
<%= render "check_comment_vendor", check: check %>
|
|
@ -0,0 +1,15 @@
|
||||||
|
Domaine: <%= check.domain %> (<%= check.consecutive_failures %> erreurs consécutives)
|
||||||
|
<%= "-" * (check.domain.length + "Domaine: ".length) %>
|
||||||
|
|
||||||
|
<%- if check.domain_expires_at.present? %>
|
||||||
|
Dernière date d'expiration connue : <%= format_utc(check.domain_expires_at) %>.
|
||||||
|
<% end %>
|
||||||
|
<%- if check.last_success_at.present? %>
|
||||||
|
Dernière vérification réussie : <%= format_utc(check.last_success_at) %>.
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
Si vous avez supprimé le domaine ou ne l'avez pas renouvellé,
|
||||||
|
merci de désactiver la vérification associée, avec ce lien :
|
||||||
|
<%= edit_check_url(check) %>
|
||||||
|
|
||||||
|
<%= render "check_comment_vendor", check: check %>
|
|
@ -1,11 +1,8 @@
|
||||||
<br />
|
<br />
|
||||||
<br />
|
|
||||||
--
|
--
|
||||||
|
|
||||||
<p>You received this email because of the notification <%= interval %> days before
|
<p>You can handle all your checks by following this link:<br />
|
||||||
the last known expiry date.<br />
|
<%= link_to nil, checks_url %>
|
||||||
You can handle the check by following this link: <br />
|
|
||||||
<%= link_to nil, edit_check_url(check) %>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>The Chexpire Team</p>
|
<p>The Chexpire Team</p>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
--
|
--
|
||||||
|
|
||||||
You received this email because of the notification <%= interval %> days before
|
You can handle all your checks by following this link:
|
||||||
the last known expiry date.
|
<%= checks_url %>
|
||||||
You can handle the check by following this link:
|
|
||||||
<%= edit_check_url(check) %>
|
|
||||||
|
|
||||||
The Chexpire Team
|
The Chexpire Team
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
<br />
|
<br />
|
||||||
<br />
|
|
||||||
--
|
--
|
||||||
|
|
||||||
<p>Vous avez reçu ce courriel à <%= pluralize(interval, "jour", "jours") %> avant la dernière date d'expiration connue.<br />
|
<p>Vous pouvez gérer l'ensemble de vos vérifications à cette adresse : <br />
|
||||||
Vous pouvez gérer les notifications pour cette vérification à ce adresse :
|
<%= link_to nil, checks_url %>
|
||||||
<%= link_to nil, edit_check_url(check) %>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>L'équipe Chexpire</p>
|
<p>L'équipe Chexpire</p>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
--
|
--
|
||||||
|
|
||||||
Vous avez reçu ce courriel à <%= pluralize(interval, "jour", "jours") %>
|
Vous pouvez gérer l'ensemble de vos vérifications à cette adresse :
|
||||||
avant la dernière date d'expiration connue.
|
<%= checks_url %>
|
||||||
Vous pouvez gérer les notifications pour cette vérification à ce adresse :
|
|
||||||
<%= edit_check_url(check) %>
|
|
||||||
|
|
||||||
L'équipe Chexpire
|
L'équipe Chexpire
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<p>
|
||||||
|
<strong>SSL: <%= check.domain %></strong> (<%= check.consecutive_failures %> erreurs consécutives)
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<%- if check.domain_expires_at.present? %>
|
||||||
|
Last known expiry date : <%= format_utc(check.domain_expires_at) %>.
|
||||||
|
<br />
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
|
<%- if check.last_success_at.present? %>
|
||||||
|
Last successful check : <%= format_utc(check.last_success_at) %>.
|
||||||
|
<br />
|
||||||
|
<%- end %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If there is no more SSL endpoint for this domain, please disable
|
||||||
|
or delete the check by following this link: <br />
|
||||||
|
<%= edit_check_url(check) %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<%= render "check_comment_vendor", check: check %>
|
|
@ -0,0 +1,15 @@
|
||||||
|
SSL: <%= check.domain %> (<%= check.consecutive_failures %> erreurs consécutives)
|
||||||
|
<%= "-" * (check.domain.length + "SSL: ".length) %>
|
||||||
|
|
||||||
|
<%- if check.domain_expires_at.present? %>
|
||||||
|
Last known expiry date : <%= format_utc(check.domain_expires_at) %>.
|
||||||
|
<%- end %>
|
||||||
|
<%- if check.last_success_at.present? %>
|
||||||
|
Last successful check : <%= format_utc(check.last_success_at) %>.
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
|
If there is no more SSL endpoint for this domain, please disable
|
||||||
|
or delete the check by following this link:
|
||||||
|
<%= edit_check_url(check) %>
|
||||||
|
|
||||||
|
<%= render "check_comment_vendor", check: check %>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<p>
|
||||||
|
<strong>SSL: <%= check.domain %></strong> (<%= check.consecutive_failures %> erreurs consécutives)
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<%- if check.domain_expires_at.present? %>
|
||||||
|
Dernière date d'expiration connue : <%= format_utc(check.domain_expires_at) %>.
|
||||||
|
<br />
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%- if check.last_success_at.present? %>
|
||||||
|
Dernière vérification réussie : <%= format_utc(check.last_success_at) %>.
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
S'il n'y a plus de terminaison SSL pour ce site ou s'il n'existe plus,
|
||||||
|
merci de désactiver la vérification associée, avec ce lien :<br />
|
||||||
|
<%= link_to nil, edit_check_url(check) %>
|
||||||
|
</p>
|
||||||
|
<%= render "check_comment_vendor", check: check %>
|
|
@ -0,0 +1,15 @@
|
||||||
|
SSL: <%= check.domain %> (<%= check.consecutive_failures %> erreurs consécutives)
|
||||||
|
<%= "-" * (check.domain.length + "SSL: ".length) %>
|
||||||
|
|
||||||
|
<%- if check.domain_expires_at.present? %>
|
||||||
|
Dernière date d'expiration connue : <%= format_utc(check.domain_expires_at) %>.
|
||||||
|
<% end %>
|
||||||
|
<%- if check.last_success_at.present? %>
|
||||||
|
Dernière vérification réussie : <%= format_utc(check.last_success_at) %>.
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
S'il n'y a plus de terminaison SSL pour ce site ou s'il n'existe plus,
|
||||||
|
merci de désactiver la vérification associée, avec ce lien :
|
||||||
|
<%= edit_check_url(check) %>
|
||||||
|
|
||||||
|
<%= render "check_comment_vendor", check: check %>
|
|
@ -7,6 +7,6 @@
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
<%= render "check_comment_vendor", check: @check %>
|
||||||
|
|
||||||
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
||||||
|
|
|
@ -3,7 +3,7 @@ Hi,
|
||||||
the domain <%= @check.domain %> will expire <%= format_utc(@check.domain_expires_at) %>.
|
the domain <%= @check.domain %> will expire <%= format_utc(@check.domain_expires_at) %>.
|
||||||
|
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
<%= render "check_comment_vendor", check: @check %>
|
||||||
|
|
||||||
|
|
||||||
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
||||||
|
|
|
@ -7,6 +7,6 @@
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
<%= render "check_comment_vendor", check: @check %>
|
||||||
|
|
||||||
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
||||||
|
|
|
@ -3,7 +3,7 @@ Salut,
|
||||||
le domaine <%= @check.domain %> va expirer le <%= format_utc(@check.domain_expires_at) %>.
|
le domaine <%= @check.domain %> va expirer le <%= format_utc(@check.domain_expires_at) %>.
|
||||||
|
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
<%= render "check_comment_vendor", check: @check %>
|
||||||
|
|
||||||
|
|
||||||
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
<p>
|
|
||||||
Hi,
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
|
|
||||||
We had <strong>recurrent failures</strong> while checking the whois database for domain
|
|
||||||
<strong><%= @check.domain %></strong>. As of today, we can't anymore verify the expiry date.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<%- if @check.domain_expires_at.present? %>
|
|
||||||
Our last known expiry date is <%= format_utc(@check.domain_expires_at) %>.
|
|
||||||
<br />
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%- if @check.last_success_at.present? %>
|
|
||||||
Our last successful check occured <%= format_utc(@check.last_success_at) %>.
|
|
||||||
<% end %>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If you have deleted the domain or have not renewed it, please disable
|
|
||||||
or delete the check by following this link: <br /><br />
|
|
||||||
<%= link_to nil, edit_check_url(@check) %>
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<%= render "check_comment_vendor" %>
|
|
||||||
|
|
||||||
|
|
||||||
<%= render "footer_recurrent_failures", interval: @notification.interval, check: @check %>
|
|
|
@ -1,20 +0,0 @@
|
||||||
Hi,
|
|
||||||
|
|
||||||
We had recurrent failures while checking the whois database for domain
|
|
||||||
<%= @check.domain %>. As of today, we can't anymore verify the expiry date.
|
|
||||||
|
|
||||||
<%- if @check.domain_expires_at.present? %>
|
|
||||||
The last known expiry date is <%= format_utc(@check.domain_expires_at) %>.
|
|
||||||
<% end %>
|
|
||||||
<%- if @check.last_success_at.present? %>
|
|
||||||
The last successful check occured <%= format_utc(@check.last_success_at) %>.
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
If you have deleted your domain or have not renewed it, please disable
|
|
||||||
or delete the check by following this link:
|
|
||||||
|
|
||||||
<%= edit_check_url(@check) %>
|
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
|
||||||
|
|
||||||
<%= render "footer_recurrent_failures", interval: @notification.interval, check: @check %>
|
|
|
@ -1,29 +0,0 @@
|
||||||
<p>
|
|
||||||
Salut,
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
|
|
||||||
Nous avons rencontré de <strong>multiples erreurs</strong> pendant l'exécution des vérifications du domaine <strong><%= @check.domain %></strong>.
|
|
||||||
Nous ne pouvons plus interroger la base Whois pour vérifier la date d'expiration.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<%- if @check.domain_expires_at.present? %>
|
|
||||||
La dernière date d'expiration connue est le <%= format_utc(@check.domain_expires_at) %>.
|
|
||||||
<br />
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%- if @check.last_success_at.present? %>
|
|
||||||
Notre dernière vérification réussie a eu lieu le <%= format_utc(@check.last_success_at) %>.
|
|
||||||
<% end %>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Si vous avez supprimé le domaine ou ne l'avez pas renouvellé, merci de désactiver la vérification associée, avec ce lien :<br /><br />
|
|
||||||
<%= link_to nil, edit_check_url(@check) %>
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<%= render "check_comment_vendor" %>
|
|
||||||
|
|
||||||
|
|
||||||
<%= render "footer_recurrent_failures", interval: @notification.interval, check: @check %>
|
|
|
@ -1,20 +0,0 @@
|
||||||
Salut,
|
|
||||||
|
|
||||||
Nous avons rencontré de multiples erreurs pendant l'exécution des vérifications
|
|
||||||
du domaine <strong><%= @check.domain %></strong>.
|
|
||||||
Nous ne pouvons plus interroger la base Whois pour vérifier la date d'expiration.
|
|
||||||
|
|
||||||
<%- if @check.domain_expires_at.present? %>
|
|
||||||
La dernière date d'expiration connue est le <%= format_utc(@check.domain_expires_at) %>.
|
|
||||||
<% end %>
|
|
||||||
<%- if @check.last_success_at.present? %>
|
|
||||||
Notre dernière vérification réussie a eu lieu le <%= format_utc(@check.last_success_at) %>.
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
Si vous avez supprimé le domaine ou ne l'avez pas renouvellé,
|
|
||||||
merci de désactiver la vérification associée, avec ce lien :
|
|
||||||
<%= edit_check_url(@check) %>
|
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
|
||||||
|
|
||||||
<%= render "footer_recurrent_failures", interval: @notification.interval, check: @check %>
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<p>
|
||||||
|
Hi,
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<%= t(".header", count: @checks.count) %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<%- @checks.each_with_index do |check, index| %>
|
||||||
|
<%- if index > 0 -%>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
<%= render "#{check.kind}_recurrent_failure", check: check %>
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<%= render "footer_recurrent_failures" %>
|
|
@ -0,0 +1,14 @@
|
||||||
|
Hi,
|
||||||
|
|
||||||
|
<%= t(".header", count: @checks.count) %>
|
||||||
|
|
||||||
|
<%- @checks.each_with_index do |check, index| %>
|
||||||
|
<%- if index > 0 -%>
|
||||||
|
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
<%= render "#{check.kind}_recurrent_failure", check: check %>
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
|
||||||
|
<%= render "footer_recurrent_failures" %>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<p>
|
||||||
|
Salut,
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<%= t(".header", count: @checks.count) %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<%- @checks.each_with_index do |check, index| %>
|
||||||
|
<%- if index > 0 -%>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
<%= render "#{check.kind}_recurrent_failure", check: check %>
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<%= render "footer_recurrent_failures" %>
|
|
@ -0,0 +1,14 @@
|
||||||
|
Salut,
|
||||||
|
|
||||||
|
<%= t(".header", count: @checks.count) %>
|
||||||
|
|
||||||
|
<%- @checks.each_with_index do |check, index| %>
|
||||||
|
<%- if index > 0 -%>
|
||||||
|
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
<%= render "#{check.kind}_recurrent_failure", check: check %>
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
|
||||||
|
<%= render "footer_recurrent_failures" %>
|
|
@ -7,6 +7,6 @@
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
<%= render "check_comment_vendor", check: @check %>
|
||||||
|
|
||||||
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
||||||
|
|
|
@ -3,7 +3,7 @@ Hi,
|
||||||
the SSL certificate for <%= @check.domain %> will expire <%= format_utc(@check.domain_expires_at) %>.
|
the SSL certificate for <%= @check.domain %> will expire <%= format_utc(@check.domain_expires_at) %>.
|
||||||
|
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
<%= render "check_comment_vendor", check: @check %>
|
||||||
|
|
||||||
|
|
||||||
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
||||||
|
|
|
@ -7,6 +7,6 @@
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
<%= render "check_comment_vendor", check: @check %>
|
||||||
|
|
||||||
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
||||||
|
|
|
@ -3,7 +3,7 @@ Salut,
|
||||||
le certificat SSL pour <%= @check.domain %> va expirer le <%= format_utc(@check.domain_expires_at) %>.
|
le certificat SSL pour <%= @check.domain %> va expirer le <%= format_utc(@check.domain_expires_at) %>.
|
||||||
|
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
<%= render "check_comment_vendor", check: @check %>
|
||||||
|
|
||||||
|
|
||||||
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
<%= render "footer_expires_soon", interval: @notification.interval, check: @check %>
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
<p>
|
|
||||||
Hi,
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
|
|
||||||
We had <strong>recurrent failures</strong> while checking the SSL certificate for
|
|
||||||
<strong><%= @check.domain %></strong>. As of today, we can no longer verify the certificate
|
|
||||||
expiry date.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<%- if @check.domain_expires_at.present? %>
|
|
||||||
Our last known expiry date is <%= format_utc(@check.domain_expires_at) %>.
|
|
||||||
<br />
|
|
||||||
<%- end %>
|
|
||||||
|
|
||||||
<%- if @check.last_success_at.present? %>
|
|
||||||
Our last successful check occured <%= format_utc(@check.last_success_at) %>.
|
|
||||||
<%- end %>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If there is no more SSL endpoint for this domain, please disable
|
|
||||||
or delete the check by following this link: <br /><br />
|
|
||||||
<%= link_to nil, edit_check_url(@check) %>
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<%= render "check_comment_vendor" %>
|
|
||||||
|
|
||||||
|
|
||||||
<%= render "footer_recurrent_failures", interval: @notification.interval, check: @check %>
|
|
|
@ -1,22 +0,0 @@
|
||||||
Hi,
|
|
||||||
|
|
||||||
We had recurrent failures while checking the SSL certificate for
|
|
||||||
<%= @check.domain %>. As of today, we can no longer verify the certificate
|
|
||||||
expiry date.
|
|
||||||
|
|
||||||
<%- if @check.domain_expires_at.present? %>
|
|
||||||
The last known expiry date is <%= format_utc(@check.domain_expires_at) %>.
|
|
||||||
<%- end %>
|
|
||||||
|
|
||||||
<%- if @check.last_success_at.present? %>
|
|
||||||
The last successful check occured <%= format_utc(@check.last_success_at) %>.
|
|
||||||
<%- end %>
|
|
||||||
|
|
||||||
If there is no more SSL endpoint for this domain, please disable
|
|
||||||
or delete the check by following this link:
|
|
||||||
|
|
||||||
<%= edit_check_url(@check) %>
|
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
|
||||||
|
|
||||||
<%= render "footer_recurrent_failures", interval: @notification.interval, check: @check %>
|
|
|
@ -1,35 +0,0 @@
|
||||||
<p>
|
|
||||||
Salut,
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
|
|
||||||
Nous avons rencontré de <strong>multiples erreurs</strong>
|
|
||||||
pendant l'exécution des vérifications du certificat SSL
|
|
||||||
du site <strong><%= @check.domain %></strong>.
|
|
||||||
Nous ne pouvons plus vérifier la date d'expiration du certificat
|
|
||||||
en nous connectant au site.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<%- if @check.domain_expires_at.present? %>
|
|
||||||
La dernière date d'expiration connue est le <%= format_utc(@check.domain_expires_at) %>.
|
|
||||||
<br />
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%- if @check.last_success_at.present? %>
|
|
||||||
Notre dernière vérification réussie a eu lieu le <%= format_utc(@check.last_success_at) %>.
|
|
||||||
<% end %>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
S'il n'y a plus de terminaison SSL pour ce site ou s'il n'existe plus,
|
|
||||||
merci de désactiver la vérification associée, avec ce lien :
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<%= link_to nil, edit_check_url(@check) %>
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<%= render "check_comment_vendor" %>
|
|
||||||
|
|
||||||
|
|
||||||
<%= render "footer_recurrent_failures", interval: @notification.interval, check: @check %>
|
|
|
@ -1,22 +0,0 @@
|
||||||
Salut,
|
|
||||||
|
|
||||||
Nous avons rencontré de multiples erreurs pendant l'exécution des vérifications
|
|
||||||
du certificat SSL pour le site <strong><%= @check.domain %></strong>.
|
|
||||||
Nous ne pouvons plus vérifier la date d'expiration du certificat
|
|
||||||
en nous connectant au site.
|
|
||||||
|
|
||||||
<%- if @check.domain_expires_at.present? %>
|
|
||||||
La dernière date d'expiration connue est le <%= format_utc(@check.domain_expires_at) %>.
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%- if @check.last_success_at.present? %>
|
|
||||||
Notre dernière vérification réussie a eu lieu le <%= format_utc(@check.last_success_at) %>.
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
S'il n'y a plus de terminaison SSL pour ce site ou s'il n'existe plus,
|
|
||||||
merci de désactiver la vérification associée, avec ce lien :
|
|
||||||
<%= edit_check_url(@check) %>
|
|
||||||
|
|
||||||
<%= render "check_comment_vendor" %>
|
|
||||||
|
|
||||||
<%= render "footer_recurrent_failures", interval: @notification.interval, check: @check %>
|
|
|
@ -32,6 +32,12 @@ module Chexpire
|
||||||
|
|
||||||
config.time_zone = "Europe/Paris"
|
config.time_zone = "Europe/Paris"
|
||||||
|
|
||||||
config.chexpire = config_for(:chexpire)
|
unless Rails.root.join("config", "chexpire.yml").readable?
|
||||||
|
fail "Missing Chexpire configuration file.
|
||||||
|
You have to create the config/chexpire.yml file and set at least the required values.
|
||||||
|
Look at config/chexpire.defaults.yml and INSTALL.md for more information"
|
||||||
|
end
|
||||||
|
|
||||||
|
config.chexpire = Hashie::Mash.new(config_for(:"chexpire.defaults").deep_merge(config_for(:chexpire)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
53
config/chexpire.defaults.yml
Normal file
53
config/chexpire.defaults.yml
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# DO NOT EDIT THIS FILE
|
||||||
|
#
|
||||||
|
# If you want override a value for any environment,
|
||||||
|
# create a `config/chexpire.yml` file,
|
||||||
|
# write your overrided keys under your environment namespace.
|
||||||
|
#
|
||||||
|
# Some keys are required to be overidden for your environment.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# production:
|
||||||
|
# mailer_default_from: "contact@yourdomain.org"
|
||||||
|
# host: mychexpire.instance.org
|
||||||
|
|
||||||
|
default: &default
|
||||||
|
mailer_default_from: "from@example.org" # REQUIRED: Email will be sent with this address as From header
|
||||||
|
host: chexpire.local # REQUIRED: Host of the website.
|
||||||
|
|
||||||
|
interface:
|
||||||
|
consecutive_failures_as_error: 2 # number of consecutive failures before display a check as "in error" (value for interface only)
|
||||||
|
notifier:
|
||||||
|
interval: 0.00 # pause in second between each notification sent
|
||||||
|
consecutive_failures: 4 # number of consecutive failures before sending a notification for recurrent failures
|
||||||
|
checks_domain:
|
||||||
|
interval: 0.5 # pause in second between each whois call
|
||||||
|
long_term_interval: 300 # when last known expiry date exceeds this interval in days, whois verification won't happen every day
|
||||||
|
long_term_frequency: 4 # when last known expiry exceeds $long_term, perform whois verification each $long_term_frequency days instead of every day
|
||||||
|
checks_ssl:
|
||||||
|
check_http_path: # defaults to check_http in $PATH
|
||||||
|
check_http_args: # array of arguments appended to defaults arguments (-C 0 -H $HOSTNAME).
|
||||||
|
|
||||||
|
development:
|
||||||
|
<<: *default
|
||||||
|
host: "chexpire.local"
|
||||||
|
|
||||||
|
production:
|
||||||
|
<<: *default
|
||||||
|
action_mailer_config:
|
||||||
|
delivery_method: :sendmail
|
||||||
|
|
||||||
|
staging:
|
||||||
|
<<: *default
|
||||||
|
action_mailer_config:
|
||||||
|
delivery_method: :sendmail
|
||||||
|
|
||||||
|
test:
|
||||||
|
<<: *default
|
||||||
|
mailer_default_from: "testcontact@example.org"
|
||||||
|
host: localhost
|
||||||
|
checks_dummy:
|
||||||
|
interval: 0.0
|
||||||
|
long_term_interval: 60
|
||||||
|
long_term_frequency: 10
|
|
@ -1,27 +0,0 @@
|
||||||
default: &default
|
|
||||||
mailer_default_from: "from@example.org"
|
|
||||||
notifier:
|
|
||||||
interval: 0.00
|
|
||||||
failure_days: 3
|
|
||||||
checks_domain:
|
|
||||||
interval: 0.5
|
|
||||||
long_term: 60
|
|
||||||
long_term_frequency: 10
|
|
||||||
checks_ssl:
|
|
||||||
check_http_path: # default to check_http in $PATH)
|
|
||||||
check_http_args: # array of arguments appended to defaults: -C 0 -H $HOSTNAME.
|
|
||||||
|
|
||||||
development:
|
|
||||||
<<: *default
|
|
||||||
host: "chexpire.local"
|
|
||||||
|
|
||||||
production:
|
|
||||||
action_mailer_config:
|
|
||||||
delivery_method: :sendmail
|
|
||||||
|
|
||||||
staging:
|
|
||||||
action_mailer_config:
|
|
||||||
delivery_method: :sendmail
|
|
||||||
|
|
||||||
# test configuration included in file used by CI services
|
|
||||||
<%= IO.read Rails.root.join("config", "chexpire.test.yml") %>
|
|
|
@ -1,13 +0,0 @@
|
||||||
test:
|
|
||||||
mailer_default_from: "contact@chexpire.org"
|
|
||||||
host: "localhost"
|
|
||||||
notifier:
|
|
||||||
interval: 0.00
|
|
||||||
failure_days: 3
|
|
||||||
checks_domain:
|
|
||||||
interval: 0.00
|
|
||||||
long_term: 60
|
|
||||||
long_term_frequency: 10
|
|
||||||
checks_ssl:
|
|
||||||
check_http_path:
|
|
||||||
check_http_args:
|
|
|
@ -40,8 +40,13 @@ en:
|
||||||
one: "Domain %{domain} expires TOMORROW!"
|
one: "Domain %{domain} expires TOMORROW!"
|
||||||
other: "Domain %{domain} expires in %{count} days"
|
other: "Domain %{domain} expires in %{count} days"
|
||||||
|
|
||||||
domain_recurrent_failures:
|
recurrent_failures:
|
||||||
subject: "Recurrent failures in %{domain} domain expiry check"
|
subject:
|
||||||
|
one: "Recurrent failures for %{domain} expiry check"
|
||||||
|
other: "%{count} checks in error"
|
||||||
|
header:
|
||||||
|
one: "We had recurrent failures during excution of the following check:"
|
||||||
|
other: "We had recurrent failures during excution of the %{count} following checks:"
|
||||||
|
|
||||||
ssl_expires_soon:
|
ssl_expires_soon:
|
||||||
subject:
|
subject:
|
||||||
|
|
|
@ -75,8 +75,13 @@ fr:
|
||||||
one: "Le domaine %{domain} expire DEMAIN !"
|
one: "Le domaine %{domain} expire DEMAIN !"
|
||||||
other: "Le domaine %{domain} expire dans %{count} jours"
|
other: "Le domaine %{domain} expire dans %{count} jours"
|
||||||
|
|
||||||
domain_recurrent_failures:
|
recurrent_failures:
|
||||||
subject: "Erreurs dans la vérification d'expiration du domaine %{domain}"
|
subject:
|
||||||
|
one: "Erreurs de vérification d'expiration pour %{domain}"
|
||||||
|
other: "%{count} vérifications en erreur"
|
||||||
|
header:
|
||||||
|
one: "Nous avons rencontré des erreurs pendant l'exécution d'une de vos vérifications :"
|
||||||
|
other: "Nous avons rencontré des erreurs pendant l'exécution des %{count} vérifications suivantes :"
|
||||||
|
|
||||||
ssl_expires_soon:
|
ssl_expires_soon:
|
||||||
subject:
|
subject:
|
||||||
|
@ -84,10 +89,6 @@ fr:
|
||||||
one: "Le certificat SSL pour %{domain} expire DEMAIN !"
|
one: "Le certificat SSL pour %{domain} expire DEMAIN !"
|
||||||
other: "Le certificat SSL pour %{domain} expire dans %{count} jours"
|
other: "Le certificat SSL pour %{domain} expire dans %{count} jours"
|
||||||
|
|
||||||
ssl_recurrent_failures:
|
|
||||||
subject: "Erreurs dans la vérification d'expiration du certificat SSL %{domain}"
|
|
||||||
|
|
||||||
|
|
||||||
shared:
|
shared:
|
||||||
locales:
|
locales:
|
||||||
en: Anglais
|
en: Anglais
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddConsecutiveFailuresToChecks < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :checks, :consecutive_failures, :integer, default: 0, null: false
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2018_06_13_055303) do
|
ActiveRecord::Schema.define(version: 2018_08_01_072038) do
|
||||||
|
|
||||||
create_table "check_logs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
|
create_table "check_logs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
|
||||||
t.bigint "check_id"
|
t.bigint "check_id"
|
||||||
|
@ -38,6 +38,7 @@ ActiveRecord::Schema.define(version: 2018_06_13_055303) do
|
||||||
t.boolean "active", default: true, null: false
|
t.boolean "active", default: true, null: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.integer "consecutive_failures", default: 0, null: false
|
||||||
t.index ["user_id"], name: "index_checks_on_user_id"
|
t.index ["user_id"], name: "index_checks_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ check_chexpire_org_error = Check.create!(
|
||||||
vendor: "Some random registrar",
|
vendor: "Some random registrar",
|
||||||
last_run_at: 20.minutes.ago,
|
last_run_at: 20.minutes.ago,
|
||||||
created_at: 3.weeks.ago,
|
created_at: 3.weeks.ago,
|
||||||
|
consecutive_failures: 4,
|
||||||
)
|
)
|
||||||
|
|
||||||
ssl_check_chexpire_org = Check.create!(
|
ssl_check_chexpire_org = Check.create!(
|
||||||
|
@ -67,6 +68,7 @@ ssl_check_chexpire_org_error = Check.create!(
|
||||||
vendor: "Some random registrar",
|
vendor: "Some random registrar",
|
||||||
last_run_at: 20.minutes.ago,
|
last_run_at: 20.minutes.ago,
|
||||||
last_success_at: 4.days.ago,
|
last_success_at: 4.days.ago,
|
||||||
|
consecutive_failures: 8,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,21 @@
|
||||||
#
|
#
|
||||||
# Table name: checks
|
# Table name: checks
|
||||||
#
|
#
|
||||||
# id :bigint(8) not null, primary key
|
# id :bigint(8) not null, primary key
|
||||||
# active :boolean default(TRUE), not null
|
# active :boolean default(TRUE), not null
|
||||||
# comment :string(255)
|
# comment :string(255)
|
||||||
# domain :string(255) not null
|
# consecutive_failures :integer default(0), not null
|
||||||
# domain_created_at :datetime
|
# domain :string(255) not null
|
||||||
# domain_expires_at :datetime
|
# domain_created_at :datetime
|
||||||
# domain_updated_at :datetime
|
# domain_expires_at :datetime
|
||||||
# kind :integer not null
|
# domain_updated_at :datetime
|
||||||
# last_run_at :datetime
|
# kind :integer not null
|
||||||
# last_success_at :datetime
|
# last_run_at :datetime
|
||||||
# vendor :string(255)
|
# last_success_at :datetime
|
||||||
# created_at :datetime not null
|
# vendor :string(255)
|
||||||
# updated_at :datetime not null
|
# created_at :datetime not null
|
||||||
# user_id :bigint(8)
|
# updated_at :datetime not null
|
||||||
|
# user_id :bigint(8)
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
@ -39,6 +40,7 @@ FactoryBot.define do
|
||||||
comment nil
|
comment nil
|
||||||
last_run_at nil
|
last_run_at nil
|
||||||
last_success_at nil
|
last_success_at nil
|
||||||
|
consecutive_failures 0
|
||||||
|
|
||||||
trait :domain do
|
trait :domain do
|
||||||
kind :domain
|
kind :domain
|
||||||
|
@ -63,6 +65,7 @@ FactoryBot.define do
|
||||||
end
|
end
|
||||||
|
|
||||||
trait :last_runs_failed do
|
trait :last_runs_failed do
|
||||||
|
consecutive_failures 5
|
||||||
last_run_at 3.days.ago - 90.minutes
|
last_run_at 3.days.ago - 90.minutes
|
||||||
last_success_at 7.days.ago - 2.hours
|
last_success_at 7.days.ago - 2.hours
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,5 +40,9 @@ FactoryBot.define do
|
||||||
notifications_enabled true
|
notifications_enabled true
|
||||||
locale "en"
|
locale "en"
|
||||||
tos_accepted true
|
tos_accepted true
|
||||||
|
|
||||||
|
trait :fr do
|
||||||
|
locale "fr"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,6 @@ class SSLSyncJobTest < ActiveJob::TestCase
|
||||||
test "ignore invalid response" do
|
test "ignore invalid response" do
|
||||||
domain = "domain.fr"
|
domain = "domain.fr"
|
||||||
check = create(:check, :nil_dates, domain: domain)
|
check = create(:check, :nil_dates, domain: domain)
|
||||||
original_updated_at = check.updated_at
|
|
||||||
|
|
||||||
mock_system_command("check_http", expected_command_arg(domain), stdout: "not a response") do
|
mock_system_command("check_http", expected_command_arg(domain), stdout: "not a response") do
|
||||||
SSLSyncJob.perform_now(check.id)
|
SSLSyncJob.perform_now(check.id)
|
||||||
|
@ -32,8 +31,8 @@ class SSLSyncJobTest < ActiveJob::TestCase
|
||||||
|
|
||||||
assert_just_now check.last_run_at
|
assert_just_now check.last_run_at
|
||||||
assert_nil check.last_success_at
|
assert_nil check.last_success_at
|
||||||
assert_equal original_updated_at, check.updated_at
|
|
||||||
assert check.active?
|
assert check.active?
|
||||||
|
assert_equal 1, check.consecutive_failures
|
||||||
end
|
end
|
||||||
|
|
||||||
test "should ignore not found (removed) checks" do
|
test "should ignore not found (removed) checks" do
|
||||||
|
@ -51,9 +50,25 @@ class SSLSyncJobTest < ActiveJob::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
check.reload
|
||||||
|
|
||||||
assert_equal 1, check.logs.count
|
assert_equal 1, check.logs.count
|
||||||
assert_match(/undefined method \W+valid\?/, check.logs.last.error)
|
assert_match(/undefined method \W+valid\?/, check.logs.last.error)
|
||||||
assert check.logs.last.failed?
|
assert check.logs.last.failed?
|
||||||
|
assert_equal 1, check.consecutive_failures
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should reset consecutive failures with a valid response" do
|
||||||
|
domain = "ssl0.domain.org"
|
||||||
|
check = create(:check, :nil_dates, domain: domain, consecutive_failures: 1)
|
||||||
|
|
||||||
|
mock_system_command("check_http", expected_command_arg(domain), stdout: ssl_response(domain)) do
|
||||||
|
SSLSyncJob.perform_now(check.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
check.reload
|
||||||
|
|
||||||
|
assert_equal 0, check.consecutive_failures
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -33,6 +33,7 @@ class WhoisSyncJobTest < ActiveJob::TestCase
|
||||||
assert_nil check.last_success_at
|
assert_nil check.last_success_at
|
||||||
assert_equal original_updated_at, check.updated_at
|
assert_equal original_updated_at, check.updated_at
|
||||||
assert check.active?
|
assert check.active?
|
||||||
|
assert_equal 1, check.consecutive_failures
|
||||||
end
|
end
|
||||||
|
|
||||||
test "should ignore not found (removed) checks" do
|
test "should ignore not found (removed) checks" do
|
||||||
|
@ -50,9 +51,12 @@ class WhoisSyncJobTest < ActiveJob::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
check.reload
|
||||||
|
|
||||||
assert_equal 1, check.logs.count
|
assert_equal 1, check.logs.count
|
||||||
assert_match(/undefined method \W+valid\?/, check.logs.last.error)
|
assert_match(/undefined method \W+valid\?/, check.logs.last.error)
|
||||||
assert check.logs.last.failed?
|
assert check.logs.last.failed?
|
||||||
|
assert_equal 1, check.consecutive_failures
|
||||||
end
|
end
|
||||||
|
|
||||||
test "disable check when whois responds domain not found" do
|
test "disable check when whois responds domain not found" do
|
||||||
|
@ -68,6 +72,7 @@ class WhoisSyncJobTest < ActiveJob::TestCase
|
||||||
refute check.active?
|
refute check.active?
|
||||||
assert_just_now check.last_run_at
|
assert_just_now check.last_run_at
|
||||||
assert_nil check.last_success_at
|
assert_nil check.last_success_at
|
||||||
|
assert_equal 1, check.consecutive_failures
|
||||||
end
|
end
|
||||||
|
|
||||||
test "default logger is CheckLogger" do
|
test "default logger is CheckLogger" do
|
||||||
|
@ -80,6 +85,19 @@ class WhoisSyncJobTest < ActiveJob::TestCase
|
||||||
assert_equal 1, check.logs.count
|
assert_equal 1, check.logs.count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "should reset consecutive failures with a valid response" do
|
||||||
|
domain = "domain.fr"
|
||||||
|
check = create(:check, :nil_dates, domain: domain, consecutive_failures: 1)
|
||||||
|
|
||||||
|
mock_system_command("whois", domain, stdout: whois_response(domain)) do
|
||||||
|
WhoisSyncJob.perform_now(check.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
check.reload
|
||||||
|
|
||||||
|
assert_equal 0, check.consecutive_failures
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def whois_response(domain)
|
def whois_response(domain)
|
||||||
|
|
|
@ -31,32 +31,32 @@ class NotificationsMailerTest < ActionMailer::TestCase # rubocop:disable Metrics
|
||||||
end
|
end
|
||||||
|
|
||||||
test "domain_expires_soon FR" do
|
test "domain_expires_soon FR" do
|
||||||
check = create(:check, domain_expires_at: Time.new(2018, 6, 10, 12, 0, 5, "+02:00"))
|
check = create(:check,
|
||||||
|
domain_expires_at: Time.new(2018, 6, 10, 12, 0, 5, "+02:00"),
|
||||||
|
user: build(:user, :fr))
|
||||||
notification = build(:notification, interval: 10, check: check, recipient: "colin@example.org")
|
notification = build(:notification, interval: 10, check: check, recipient: "colin@example.org")
|
||||||
|
|
||||||
I18n.with_locale :fr do
|
Date.stub :today, Date.new(2018, 6, 2) do
|
||||||
Date.stub :today, Date.new(2018, 6, 2) do
|
mail = NotificationsMailer.with(notification: notification).domain_expires_soon
|
||||||
mail = NotificationsMailer.with(notification: notification).domain_expires_soon
|
|
||||||
|
|
||||||
assert_emails 1 do
|
assert_emails 1 do
|
||||||
mail.deliver_now
|
mail.deliver_now
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_match "domain.fr", mail.subject
|
assert_match "domain.fr", mail.subject
|
||||||
assert_match "dans 8 jours", mail.subject
|
assert_match "dans 8 jours", mail.subject
|
||||||
assert_equal ["colin@example.org"], mail.to
|
assert_equal ["colin@example.org"], mail.to
|
||||||
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
||||||
|
|
||||||
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
||||||
|
|
||||||
parts.each do |part|
|
parts.each do |part|
|
||||||
assert_match "domain.fr", part
|
assert_match "domain.fr", part
|
||||||
assert_match "dim 10 juin 2018 10:00:05 +0000", part
|
assert_match "dim 10 juin 2018 10:00:05 +0000", part
|
||||||
assert_match "10 jours", part
|
assert_match "10 jours", part
|
||||||
assert_match "/checks/#{check.id}/edit", part
|
assert_match "/checks/#{check.id}/edit", part
|
||||||
assert_no_match "commentaire", part
|
assert_no_match "commentaire", part
|
||||||
assert_no_match "fournisseur", part
|
assert_no_match "fournisseur", part
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -82,36 +82,34 @@ class NotificationsMailerTest < ActionMailer::TestCase # rubocop:disable Metrics
|
||||||
check = create(:check,
|
check = create(:check,
|
||||||
domain_expires_at: 1.week.from_now,
|
domain_expires_at: 1.week.from_now,
|
||||||
comment: "My comment",
|
comment: "My comment",
|
||||||
vendor: "The vendor")
|
vendor: "The vendor",
|
||||||
|
user: build(:user, :fr))
|
||||||
notification = build(:notification, check: check)
|
notification = build(:notification, check: check)
|
||||||
|
|
||||||
I18n.with_locale :fr do
|
mail = NotificationsMailer.with(notification: notification).domain_expires_soon
|
||||||
mail = NotificationsMailer.with(notification: notification).domain_expires_soon
|
|
||||||
|
|
||||||
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
||||||
|
|
||||||
parts.each do |part|
|
parts.each do |part|
|
||||||
assert_match "commentaire", part
|
assert_match "commentaire", part
|
||||||
assert_match "Fournisseur", part
|
assert_match "Fournisseur", part
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "domain_recurrent_failures" do
|
test "recurrent_failures" do
|
||||||
last_success_at = Time.new(2018, 5, 30, 6, 10, 0, "+00:00")
|
last_success_at = Time.new(2018, 5, 30, 6, 10, 0, "+00:00")
|
||||||
domain_expires_at = Time.new(2018, 10, 10, 7, 20, 0, "+04:00")
|
domain_expires_at = Time.new(2018, 10, 10, 7, 20, 0, "+04:00")
|
||||||
check = build(:check, :last_runs_failed,
|
check = create(:check, :last_runs_failed,
|
||||||
domain: "invalid-domain.fr",
|
domain: "invalid-domain.fr",
|
||||||
last_success_at: last_success_at,
|
last_success_at: last_success_at,
|
||||||
domain_expires_at: domain_expires_at,
|
domain_expires_at: domain_expires_at,
|
||||||
comment: "My comment")
|
comment: "My comment")
|
||||||
notification = create(:notification, check: check)
|
|
||||||
|
|
||||||
mail = NotificationsMailer.with(notification: notification).domain_recurrent_failures
|
mail = NotificationsMailer.recurrent_failures(check.user, [check])
|
||||||
assert_match "failures", mail.subject
|
assert_match "failures", mail.subject
|
||||||
assert_match "invalid-domain.fr", mail.subject
|
assert_match "invalid-domain.fr", mail.subject
|
||||||
|
|
||||||
assert_equal ["recipient@domain.fr"], mail.to
|
assert_match(/user-\d+@chexpire.org/, mail.to.first)
|
||||||
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
||||||
|
|
||||||
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
||||||
|
@ -119,41 +117,39 @@ class NotificationsMailerTest < ActionMailer::TestCase # rubocop:disable Metrics
|
||||||
parts.each do |part|
|
parts.each do |part|
|
||||||
assert_match "invalid-domain.fr", part
|
assert_match "invalid-domain.fr", part
|
||||||
assert_match "recurrent failures", part
|
assert_match "recurrent failures", part
|
||||||
assert_match(/success[a-z ]+ Wed, 30 May 2018 06:10:00 \+0000/, part)
|
assert_match(/success[a-z: ]+ Wed, 30 May 2018 06:10:00 \+0000/, part)
|
||||||
assert_match(/expiry[a-z ]+ Wed, 10 Oct 2018 03:20:00 \+0000/, part)
|
assert_match(/expiry[a-z: ]+ Wed, 10 Oct 2018 03:20:00 \+0000/, part)
|
||||||
assert_match "My comment", part
|
assert_match "My comment", part
|
||||||
assert_match "/checks/#{check.id}/edit", part
|
assert_match "/checks/#{check.id}/edit", part
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "domain_recurrent_failures - FR" do
|
test "recurrent_failures - FR" do
|
||||||
last_success_at = Time.new(2018, 5, 30, 6, 10, 0, "+00:00")
|
last_success_at = Time.new(2018, 5, 30, 6, 10, 0, "+00:00")
|
||||||
domain_expires_at = Time.new(2018, 10, 10, 7, 20, 0, "+04:00")
|
domain_expires_at = Time.new(2018, 10, 10, 7, 20, 0, "+04:00")
|
||||||
check = build(:check, :last_runs_failed,
|
check = create(:check, :last_runs_failed,
|
||||||
domain: "invalid-domain.fr",
|
domain: "invalid-domain.fr",
|
||||||
last_success_at: last_success_at,
|
last_success_at: last_success_at,
|
||||||
domain_expires_at: domain_expires_at,
|
domain_expires_at: domain_expires_at,
|
||||||
comment: "My comment")
|
comment: "My comment",
|
||||||
notification = create(:notification, check: check)
|
user: build(:user, :fr))
|
||||||
|
|
||||||
I18n.with_locale :fr do
|
mail = NotificationsMailer.recurrent_failures(check.user, [check])
|
||||||
mail = NotificationsMailer.with(notification: notification).domain_recurrent_failures
|
assert_match "Erreurs", mail.subject
|
||||||
assert_match "Erreurs", mail.subject
|
assert_match "invalid-domain.fr", mail.subject
|
||||||
assert_match "invalid-domain.fr", mail.subject
|
|
||||||
|
|
||||||
assert_equal ["recipient@domain.fr"], mail.to
|
assert_match(/user-\d+@chexpire.org/, mail.to.first)
|
||||||
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
||||||
|
|
||||||
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
||||||
|
|
||||||
parts.each do |part|
|
parts.each do |part|
|
||||||
assert_match "invalid-domain.fr", part
|
assert_match "invalid-domain.fr", part
|
||||||
assert_match "erreurs", part
|
assert_match "erreurs", part
|
||||||
assert_match(/réussie[a-z ]+ mer 30 mai 2018 06:10:00 \+0000/, part)
|
assert_match(/réussie[a-z: ]+ mer 30 mai 2018 06:10:00 \+0000/, part)
|
||||||
assert_match(/expiration[a-z ]+ mer 10 oct. 2018 03:20:00 \+0000/, part)
|
assert_match(/expiration[a-z: ]+ mer 10 oct. 2018 03:20:00 \+0000/, part)
|
||||||
assert_match "commentaire", part
|
assert_match "commentaire", part
|
||||||
assert_match "/checks/#{check.id}/edit", part
|
assert_match "/checks/#{check.id}/edit", part
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -188,95 +184,33 @@ class NotificationsMailerTest < ActionMailer::TestCase # rubocop:disable Metrics
|
||||||
end
|
end
|
||||||
|
|
||||||
test "ssl_expires_soon - FR" do
|
test "ssl_expires_soon - FR" do
|
||||||
check = create(:check, :ssl, domain_expires_at: Time.new(2018, 6, 10, 12, 0, 5, "+02:00"))
|
check = create(:check, :ssl,
|
||||||
|
domain_expires_at: Time.new(2018, 6, 10, 12, 0, 5, "+02:00"),
|
||||||
|
user: build(:user, :fr))
|
||||||
notification = build(:notification, interval: 10, check: check, recipient: "colin@example.org")
|
notification = build(:notification, interval: 10, check: check, recipient: "colin@example.org")
|
||||||
|
|
||||||
I18n.with_locale :fr do
|
Date.stub :today, Date.new(2018, 6, 2) do
|
||||||
Date.stub :today, Date.new(2018, 6, 2) do
|
mail = NotificationsMailer.with(notification: notification).ssl_expires_soon
|
||||||
mail = NotificationsMailer.with(notification: notification).ssl_expires_soon
|
|
||||||
|
|
||||||
assert_emails 1 do
|
assert_emails 1 do
|
||||||
mail.deliver_now
|
mail.deliver_now
|
||||||
end
|
|
||||||
|
|
||||||
assert_match "domain.fr", mail.subject
|
|
||||||
assert_match "SSL", mail.subject
|
|
||||||
assert_match "dans 8 jours", mail.subject
|
|
||||||
assert_equal ["colin@example.org"], mail.to
|
|
||||||
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
|
||||||
|
|
||||||
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
|
||||||
|
|
||||||
parts.each do |part|
|
|
||||||
assert_match "domain.fr", part
|
|
||||||
assert_match "dim 10 juin 2018 10:00:05 +0000", part
|
|
||||||
assert_match "10 jours", part
|
|
||||||
assert_match "/checks/#{check.id}/edit", part
|
|
||||||
assert_no_match "commentaire", part
|
|
||||||
assert_no_match "fournisseur", part
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "ssl_recurrent_failures" do
|
assert_match "domain.fr", mail.subject
|
||||||
last_success_at = Time.new(2018, 5, 30, 6, 10, 0, "+00:00")
|
|
||||||
domain_expires_at = Time.new(2018, 10, 10, 7, 20, 0, "+04:00")
|
|
||||||
check = build(:check, :ssl, :last_runs_failed,
|
|
||||||
domain: "invalid-domain.fr",
|
|
||||||
last_success_at: last_success_at,
|
|
||||||
domain_expires_at: domain_expires_at,
|
|
||||||
comment: "My comment")
|
|
||||||
notification = create(:notification, check: check)
|
|
||||||
|
|
||||||
mail = NotificationsMailer.with(notification: notification).ssl_recurrent_failures
|
|
||||||
assert_match "failures", mail.subject
|
|
||||||
assert_match "invalid-domain.fr", mail.subject
|
|
||||||
assert_match "SSL", mail.subject
|
|
||||||
|
|
||||||
assert_equal ["recipient@domain.fr"], mail.to
|
|
||||||
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
|
||||||
|
|
||||||
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
|
||||||
|
|
||||||
parts.each do |part|
|
|
||||||
assert_match "invalid-domain.fr", part
|
|
||||||
assert_match "recurrent failures", part
|
|
||||||
assert_match(/success[a-z ]+ Wed, 30 May 2018 06:10:00 \+0000/, part)
|
|
||||||
assert_match(/expiry[a-z ]+ Wed, 10 Oct 2018 03:20:00 \+0000/, part)
|
|
||||||
assert_match "My comment", part
|
|
||||||
assert_match "/checks/#{check.id}/edit", part
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "ssl_recurrent_failures - FR" do
|
|
||||||
last_success_at = Time.new(2018, 5, 30, 6, 10, 0, "+00:00")
|
|
||||||
domain_expires_at = Time.new(2018, 10, 10, 7, 20, 0, "+04:00")
|
|
||||||
check = build(:check, :ssl, :last_runs_failed,
|
|
||||||
domain: "invalid-domain.fr",
|
|
||||||
last_success_at: last_success_at,
|
|
||||||
domain_expires_at: domain_expires_at,
|
|
||||||
comment: "My comment")
|
|
||||||
notification = create(:notification, check: check)
|
|
||||||
|
|
||||||
I18n.with_locale :fr do
|
|
||||||
mail = NotificationsMailer.with(notification: notification).ssl_recurrent_failures
|
|
||||||
assert_match "Erreurs", mail.subject
|
|
||||||
assert_match "invalid-domain.fr", mail.subject
|
|
||||||
assert_match "SSL", mail.subject
|
assert_match "SSL", mail.subject
|
||||||
|
assert_match "dans 8 jours", mail.subject
|
||||||
assert_equal ["recipient@domain.fr"], mail.to
|
assert_equal ["colin@example.org"], mail.to
|
||||||
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
|
||||||
|
|
||||||
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
parts = [mail.text_part.decode_body, mail.html_part.decode_body]
|
||||||
|
|
||||||
parts.each do |part|
|
parts.each do |part|
|
||||||
assert_match "invalid-domain.fr", part
|
assert_match "domain.fr", part
|
||||||
assert_match "erreurs", part
|
assert_match "dim 10 juin 2018 10:00:05 +0000", part
|
||||||
assert_match(/réussie[a-z ]+ mer 30 mai 2018 06:10:00 \+0000/, part)
|
assert_match "10 jours", part
|
||||||
assert_match(/expiration[a-z ]+ mer 10 oct. 2018 03:20:00 \+0000/, part)
|
|
||||||
assert_match "commentaire", part
|
|
||||||
assert_match "/checks/#{check.id}/edit", part
|
assert_match "/checks/#{check.id}/edit", part
|
||||||
|
assert_no_match "commentaire", part
|
||||||
|
assert_no_match "fournisseur", part
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,21 +6,16 @@ class NotificationsMailerPreview < ActionMailer::Preview
|
||||||
NotificationsMailer.with(notification: check.notifications.first).domain_expires_soon
|
NotificationsMailer.with(notification: check.notifications.first).domain_expires_soon
|
||||||
end
|
end
|
||||||
|
|
||||||
# Preview this email at http://localhost:3000/rails/mailers/notifications_mailer/domain_recurrent_failures
|
|
||||||
def domain_recurrent_failures
|
|
||||||
check = Check.domain.where("last_run_at != last_success_at").first
|
|
||||||
NotificationsMailer.with(notification: check.notifications.first).domain_recurrent_failures
|
|
||||||
end
|
|
||||||
|
|
||||||
# Preview this email at http://localhost:3000/rails/mailers/notifications_mailer/ssl_expires_soon
|
# Preview this email at http://localhost:3000/rails/mailers/notifications_mailer/ssl_expires_soon
|
||||||
def ssl_expires_soon
|
def ssl_expires_soon
|
||||||
check = Check.ssl.first
|
check = Check.ssl.first
|
||||||
NotificationsMailer.with(notification: check.notifications.first).ssl_expires_soon
|
NotificationsMailer.with(notification: check.notifications.first).ssl_expires_soon
|
||||||
end
|
end
|
||||||
|
|
||||||
# Preview this email at http://localhost:3000/rails/mailers/notifications_mailer/ssl_recurrent_failures
|
# Preview this email at http://localhost:3000/rails/mailers/notifications_mailer/recurrent_failures
|
||||||
def ssl_recurrent_failures
|
def recurrent_failures
|
||||||
check = Check.ssl.where("last_run_at != last_success_at").first
|
user = User.first
|
||||||
NotificationsMailer.with(notification: check.notifications.first).ssl_recurrent_failures
|
checks = Check.consecutive_failures(2).where(user: user)
|
||||||
|
NotificationsMailer.recurrent_failures(user, checks)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,20 +2,21 @@
|
||||||
#
|
#
|
||||||
# Table name: checks
|
# Table name: checks
|
||||||
#
|
#
|
||||||
# id :bigint(8) not null, primary key
|
# id :bigint(8) not null, primary key
|
||||||
# active :boolean default(TRUE), not null
|
# active :boolean default(TRUE), not null
|
||||||
# comment :string(255)
|
# comment :string(255)
|
||||||
# domain :string(255) not null
|
# consecutive_failures :integer default(0), not null
|
||||||
# domain_created_at :datetime
|
# domain :string(255) not null
|
||||||
# domain_expires_at :datetime
|
# domain_created_at :datetime
|
||||||
# domain_updated_at :datetime
|
# domain_expires_at :datetime
|
||||||
# kind :integer not null
|
# domain_updated_at :datetime
|
||||||
# last_run_at :datetime
|
# kind :integer not null
|
||||||
# last_success_at :datetime
|
# last_run_at :datetime
|
||||||
# vendor :string(255)
|
# last_success_at :datetime
|
||||||
# created_at :datetime not null
|
# vendor :string(255)
|
||||||
# updated_at :datetime not null
|
# created_at :datetime not null
|
||||||
# user_id :bigint(8)
|
# updated_at :datetime not null
|
||||||
|
# user_id :bigint(8)
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
@ -50,40 +51,6 @@ class CheckTest < ActiveSupport::TestCase
|
||||||
assert_nil notification.sent_at
|
assert_nil notification.sent_at
|
||||||
end
|
end
|
||||||
|
|
||||||
test "in_error? for recently added" do
|
|
||||||
check = build(:check, created_at: 1.day.ago)
|
|
||||||
refute check.in_error?
|
|
||||||
|
|
||||||
check = build(:check, created_at: 1.day.ago, last_run_at: 3.minutes.ago)
|
|
||||||
refute check.in_error?
|
|
||||||
|
|
||||||
check = build(:check, created_at: 1.day.ago, last_success_at: 1.hour.ago)
|
|
||||||
refute check.in_error?
|
|
||||||
end
|
|
||||||
|
|
||||||
test "in_error? for never success check, with at least 1 run" do
|
|
||||||
check = build(:check, created_at: 3.weeks.ago, last_run_at: 1.day.ago)
|
|
||||||
assert check.in_error?
|
|
||||||
|
|
||||||
check = build(:check, created_at: 3.weeks.ago, last_run_at: 4.days.ago)
|
|
||||||
assert check.in_error?
|
|
||||||
end
|
|
||||||
|
|
||||||
test "in_error? ignore check without run" do
|
|
||||||
check = build(:check, created_at: 3.weeks.ago)
|
|
||||||
refute check.in_error?
|
|
||||||
end
|
|
||||||
|
|
||||||
test "in_error? for last success a few days ago" do
|
|
||||||
check = build(:check, created_at: 3.weeks.ago,
|
|
||||||
last_success_at: 10.days.ago, last_run_at: 1.day.ago)
|
|
||||||
assert check.in_error?
|
|
||||||
|
|
||||||
check = build(:check, created_at: 3.weeks.ago,
|
|
||||||
last_success_at: 1.days.ago, last_run_at: 1.day.ago)
|
|
||||||
refute check.in_error?
|
|
||||||
end
|
|
||||||
|
|
||||||
test "days_from_last_success without any success" do
|
test "days_from_last_success without any success" do
|
||||||
check = build(:check)
|
check = build(:check)
|
||||||
assert_nil check.days_from_last_success
|
assert_nil check.days_from_last_success
|
||||||
|
|
|
@ -109,8 +109,8 @@ class CheckProcessorTest < ActiveSupport::TestCase
|
||||||
create_list(:check, 3, :expires_next_week)
|
create_list(:check, 3, :expires_next_week)
|
||||||
|
|
||||||
configuration = Minitest::Mock.new
|
configuration = Minitest::Mock.new
|
||||||
2.times do configuration.expect(:long_term, 60) end
|
2.times do configuration.expect(:long_term_interval, 300) end
|
||||||
configuration.expect(:long_term_frequency, 10)
|
configuration.expect(:long_term_frequency, 4)
|
||||||
|
|
||||||
3.times do
|
3.times do
|
||||||
configuration.expect(:interval, 0.000001)
|
configuration.expect(:interval, 0.000001)
|
||||||
|
|
|
@ -5,8 +5,8 @@ module Notifier
|
||||||
class BaseTest < ActiveSupport::TestCase
|
class BaseTest < ActiveSupport::TestCase
|
||||||
setup do
|
setup do
|
||||||
class FakeChannel < Base
|
class FakeChannel < Base
|
||||||
def supports?(reason, _notification)
|
def supports?(notification)
|
||||||
reason != :unsupported
|
notification.interval < 1_000
|
||||||
end
|
end
|
||||||
|
|
||||||
def domain_notify_expires_soon(*); end
|
def domain_notify_expires_soon(*); end
|
||||||
|
@ -18,7 +18,7 @@ module Notifier
|
||||||
test "#notify change the status of the notification" do
|
test "#notify change the status of the notification" do
|
||||||
notification = create(:notification)
|
notification = create(:notification)
|
||||||
|
|
||||||
@channel.notify(:expires_soon, notification)
|
@channel.notify(notification)
|
||||||
|
|
||||||
notification.reload
|
notification.reload
|
||||||
|
|
||||||
|
@ -26,18 +26,30 @@ module Notifier
|
||||||
assert_just_now notification.sent_at
|
assert_just_now notification.sent_at
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#notify raises an exception for a invalid reason" do
|
test "#notify raises an exception for a non supported check kind" do
|
||||||
notification = build(:notification)
|
notification = Minitest::Mock.new
|
||||||
|
notification.expect :ongoing!, true
|
||||||
|
notification.expect :interval, 10
|
||||||
|
|
||||||
|
check = Minitest::Mock.new
|
||||||
|
check.expect(:kind, :invalid_kind)
|
||||||
|
check.expect(:kind, :invalid_kind) # twice (second call for exception message)
|
||||||
|
|
||||||
|
notification.expect :check, check
|
||||||
|
notification.expect :check, check
|
||||||
|
|
||||||
assert_raises ArgumentError do
|
assert_raises ArgumentError do
|
||||||
@channel.notify(:unknown, notification)
|
@channel.notify(notification)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
check.verify
|
||||||
|
notification.verify
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#notify does nothing when channel does not support a reason" do
|
test "#notify does nothing when channel doesn't support a notification whatever the reason" do
|
||||||
notification = create(:notification)
|
notification = create(:notification, interval: 10_000)
|
||||||
|
|
||||||
@channel.notify(:unsupported, notification)
|
@channel.notify(notification)
|
||||||
|
|
||||||
notification.reload
|
notification.reload
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,10 @@ module Notifier
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#process_recurrent_failures respects the interval configuration between sends" do
|
test "#process_recurrent_failures respects the interval configuration between sends" do
|
||||||
create_list(:notification, 3, :email, check: build(:check, :last_runs_failed))
|
create_list(:check, 3, :last_runs_failed)
|
||||||
test_interval_respected(:process_recurrent_failures, 3)
|
test_interval_respected(:process_recurrent_failures, 3) do |configuration|
|
||||||
|
configuration.expect(:consecutive_failures, 4.2)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -34,6 +36,9 @@ module Notifier
|
||||||
count_expected.times do
|
count_expected.times do
|
||||||
configuration.expect(:interval, 0.000001)
|
configuration.expect(:interval, 0.000001)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
yield configuration if block_given?
|
||||||
|
|
||||||
processor = Processor.new(configuration)
|
processor = Processor.new(configuration)
|
||||||
|
|
||||||
mock = Minitest::Mock.new
|
mock = Minitest::Mock.new
|
||||||
|
|
|
@ -6,58 +6,58 @@ module Notifier
|
||||||
@resolver = Notifier::Resolver.new
|
@resolver = Notifier::Resolver.new
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_expires_soon ignores user having notification disabled" do
|
test "#notifications_expiring_soon ignores user having notification disabled" do
|
||||||
n1 = create(:notification, check: build(:check, :expires_next_week))
|
n1 = create(:notification, check: build(:check, :expires_next_week))
|
||||||
n1.check.user.update_attribute(:notifications_enabled, false)
|
n1.check.user.update_attribute(:notifications_enabled, false)
|
||||||
n2 = create(:notification, check: build(:check, :expires_next_week))
|
n2 = create(:notification, check: build(:check, :expires_next_week))
|
||||||
|
|
||||||
notifications = @resolver.resolve_expires_soon
|
notifications = @resolver.notifications_expiring_soon
|
||||||
|
|
||||||
assert_not_includes notifications, n1
|
assert_not_includes notifications, n1
|
||||||
assert_includes notifications, n2
|
assert_includes notifications, n2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_expires_soon ignores inactive checks" do
|
test "#notifications_expiring_soon ignores inactive checks" do
|
||||||
n1 = create(:notification, check: build(:check, :expires_next_week, :inactive))
|
n1 = create(:notification, check: build(:check, :expires_next_week, :inactive))
|
||||||
n2 = create(:notification, check: build(:check, :expires_next_week))
|
n2 = create(:notification, check: build(:check, :expires_next_week))
|
||||||
|
|
||||||
notifications = @resolver.resolve_expires_soon
|
notifications = @resolver.notifications_expiring_soon
|
||||||
|
|
||||||
assert_not_includes notifications, n1
|
assert_not_includes notifications, n1
|
||||||
assert_includes notifications, n2
|
assert_includes notifications, n2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_expires_soon gets only checks inside interval" do
|
test "#notifications_expiring_soon gets only checks inside interval" do
|
||||||
n1 = create(:notification, check: build(:check, :expires_next_week), interval: 6)
|
n1 = create(:notification, check: build(:check, :expires_next_week), interval: 6)
|
||||||
n2 = create(:notification, check: build(:check, :expires_next_week), interval: 7)
|
n2 = create(:notification, check: build(:check, :expires_next_week), interval: 7)
|
||||||
|
|
||||||
notifications = @resolver.resolve_expires_soon
|
notifications = @resolver.notifications_expiring_soon
|
||||||
|
|
||||||
assert_not_includes notifications, n1
|
assert_not_includes notifications, n1
|
||||||
assert_includes notifications, n2
|
assert_includes notifications, n2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_expires_soon can gets several notifications for a same check" do
|
test "#notifications_expiring_soon can gets several notifications for a same check" do
|
||||||
check = create(:check, :expires_next_week)
|
check = create(:check, :expires_next_week)
|
||||||
n1 = create(:notification, check: check, interval: 3)
|
n1 = create(:notification, check: check, interval: 3)
|
||||||
n2 = create(:notification, check: check, interval: 10)
|
n2 = create(:notification, check: check, interval: 10)
|
||||||
n3 = create(:notification, check: check, interval: 30)
|
n3 = create(:notification, check: check, interval: 30)
|
||||||
|
|
||||||
notifications = @resolver.resolve_expires_soon
|
notifications = @resolver.notifications_expiring_soon
|
||||||
|
|
||||||
assert_not_includes notifications, n1
|
assert_not_includes notifications, n1
|
||||||
assert_includes notifications, n2
|
assert_includes notifications, n2
|
||||||
assert_includes notifications, n3
|
assert_includes notifications, n3
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_expires_soon takes care of the status" do
|
test "#notifications_expiring_soon takes care of the status" do
|
||||||
check = create(:check, :expires_next_week)
|
check = create(:check, :expires_next_week)
|
||||||
n1 = create(:notification, check: check)
|
n1 = create(:notification, check: check)
|
||||||
n2 = create(:notification, :failed, check: check)
|
n2 = create(:notification, :failed, check: check)
|
||||||
n3 = create(:notification, :ongoing, check: check)
|
n3 = create(:notification, :ongoing, check: check)
|
||||||
n4 = create(:notification, :succeed, check: check)
|
n4 = create(:notification, :succeed, check: check)
|
||||||
|
|
||||||
notifications = @resolver.resolve_expires_soon
|
notifications = @resolver.notifications_expiring_soon
|
||||||
|
|
||||||
assert_includes notifications, n1
|
assert_includes notifications, n1
|
||||||
assert_includes notifications, n2
|
assert_includes notifications, n2
|
||||||
|
@ -65,49 +65,51 @@ module Notifier
|
||||||
assert_not_includes notifications, n4
|
assert_not_includes notifications, n4
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_expires_soon ignores checks expired and without date" do
|
test "#notifications_expiring_soon ignores checks expired and without date" do
|
||||||
n1 = create(:notification, check: build(:check, :expires_next_week))
|
n1 = create(:notification, check: build(:check, :expires_next_week))
|
||||||
n2 = create(:notification, check: build(:check, domain_expires_at: 1.week.ago))
|
n2 = create(:notification, check: build(:check, domain_expires_at: 1.week.ago))
|
||||||
n3 = create(:notification, check: build(:check, :nil_dates))
|
n3 = create(:notification, check: build(:check, :nil_dates))
|
||||||
|
|
||||||
notifications = @resolver.resolve_expires_soon
|
notifications = @resolver.notifications_expiring_soon
|
||||||
|
|
||||||
assert_includes notifications, n1
|
assert_includes notifications, n1
|
||||||
assert_not_includes notifications, n2
|
assert_not_includes notifications, n2
|
||||||
assert_not_includes notifications, n3
|
assert_not_includes notifications, n3
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_check_failed ignores inactive checks" do
|
test "#checks_recurrent_failures ignores inactive checks" do
|
||||||
n1 = create(:notification, check: build(:check, :last_runs_failed, :inactive))
|
c1 = create(:check, :last_runs_failed, :inactive)
|
||||||
n2 = create(:notification, check: build(:check, :last_runs_failed))
|
c2 = create(:check, :last_runs_failed)
|
||||||
|
|
||||||
notifications = @resolver.resolve_check_failed
|
checks = @resolver.checks_recurrent_failures(4)
|
||||||
|
|
||||||
assert_not_includes notifications, n1
|
assert_not_includes checks, c1
|
||||||
assert_includes notifications, n2
|
assert_includes checks, c2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_check_failed ignores user having notification disabled" do
|
test "#checks_recurrent_failures ignores user having notification disabled" do
|
||||||
n1 = create(:notification, check: build(:check, :last_runs_failed))
|
c1 = create(:check, :last_runs_failed)
|
||||||
n1.check.user.update_attribute(:notifications_enabled, false)
|
c1.user.update_attribute(:notifications_enabled, false)
|
||||||
n2 = create(:notification, check: build(:check, :last_runs_failed))
|
c2 = create(:check, :last_runs_failed)
|
||||||
|
|
||||||
notifications = @resolver.resolve_check_failed
|
checks = @resolver.checks_recurrent_failures(4)
|
||||||
|
|
||||||
assert_not_includes notifications, n1
|
assert_not_includes checks, c1
|
||||||
assert_includes notifications, n2
|
assert_includes checks, c2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#resolve_check_failed gets only checks having last run in error" do
|
test "#checks_recurrent_failures gets only checks having consecutive failures" do
|
||||||
n1 = create(:notification, check: build(:check, :nil_dates))
|
c1 = create(:check, :nil_dates)
|
||||||
n2 = create(:notification, check: build(:check, :last_run_succeed))
|
c2 = create(:check, :last_run_succeed)
|
||||||
n3 = create(:notification, check: build(:check, :last_runs_failed))
|
c3 = create(:check, :last_runs_failed, consecutive_failures: 5)
|
||||||
|
c4 = create(:check, :last_runs_failed, consecutive_failures: 3)
|
||||||
|
|
||||||
notifications = @resolver.resolve_check_failed
|
checks = @resolver.checks_recurrent_failures(4)
|
||||||
|
|
||||||
assert_not_includes notifications, n1
|
assert_not_includes checks, c1
|
||||||
assert_not_includes notifications, n2
|
assert_not_includes checks, c2
|
||||||
assert_includes notifications, n3
|
assert_not_includes checks, c4
|
||||||
|
assert_includes checks, c3
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue