aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPatrick J Cherry <patrick@bytemark.co.uk>2012-04-25 17:15:49 +0100
committerPatrick J Cherry <patrick@bytemark.co.uk>2012-04-25 17:15:49 +0100
commite959c0fe4c887154bbe28c31324fef2975cbe467 (patch)
tree3088c7a1f389944d613e57b551b452f7ec83181d /lib
parent5fff12fc11cb8b02a44fd40ed78fa9d196f269d7 (diff)
Big update.
* Max acknowledgement time is now specified in the config * Calendar interface improved. * holiday_url no longer used -- replaced by notify_when_on_holiday! * added notify_when_off_sick! * Added ability for the calendar to be queried for a list of bank holdays. * Added ability for Time to be given a list of bank holidays to check against. * PeopleLists can now be a Proc, allowing downloading of lists * Person is no longer a struct * Moved the method_missing bit into ObjectBuilder from various sub classes. * Added tests for the calendar interface * Updated tests in other bits.
Diffstat (limited to 'lib')
-rw-r--r--lib/mauve/alert.rb2
-rw-r--r--lib/mauve/authentication.rb10
-rw-r--r--lib/mauve/calendar_interface.rb100
-rw-r--r--lib/mauve/configuration.rb113
-rw-r--r--lib/mauve/configuration_builder.rb12
-rw-r--r--lib/mauve/configuration_builders/notification_method.rb12
-rw-r--r--lib/mauve/configuration_builders/person.rb6
-rw-r--r--lib/mauve/configuration_builders/server.rb25
-rw-r--r--lib/mauve/mauve_time.rb28
-rw-r--r--lib/mauve/notification.rb3
-rw-r--r--lib/mauve/notifiers/xmpp.rb5
-rw-r--r--lib/mauve/people_list.rb10
-rw-r--r--lib/mauve/person.rb124
-rw-r--r--lib/mauve/processor.rb14
-rw-r--r--lib/mauve/server.rb112
-rw-r--r--lib/mauve/web_interface.rb19
-rw-r--r--lib/object_builder.rb14
17 files changed, 381 insertions, 228 deletions
diff --git a/lib/mauve/alert.rb b/lib/mauve/alert.rb
index f249913..6b08f82 100644
--- a/lib/mauve/alert.rb
+++ b/lib/mauve/alert.rb
@@ -420,7 +420,7 @@ module Mauve
#
# Limit acknowledgment time.
#
- limit = Time.now + 15.days
+ limit = Time.now + Configuration.current.max_acknowledgement_time
ack_until = limit if ack_until > limit
self.acknowledged_by = person.username
diff --git a/lib/mauve/authentication.rb b/lib/mauve/authentication.rb
index c467a1d..24c6bd3 100644
--- a/lib/mauve/authentication.rb
+++ b/lib/mauve/authentication.rb
@@ -70,7 +70,7 @@ module Mauve
unless true == result
logger.info "Authentication for #{login} failed"
# Rate limit
- sleep Server.instance.failed_login_delay
+ sleep Configuration.current.failed_login_delay
end
result
@@ -97,15 +97,15 @@ module Mauve
#
# Don't bother checking if no auth_url has been set.
#
- return false unless Server.instance.bytemark_auth_url.is_a?(URI)
+ return false unless Configuration.current.bytemark_auth_url.is_a?(URI)
#
# Don't bother checking if the person doesn't exist.
#
return false unless Mauve::Configuration.current.people.has_key?(login)
- uri = Server.instance.bytemark_auth_url
- timeout = Server.instance.remote_http_timeout
+ uri = Configuration.current.bytemark_auth_url
+ timeout = Configuration.current.remote_http_timeout
# host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, user=nil, password=nil, use_ssl=nil, timeout=nil)
client = XMLRPC::Client.new(uri.host, uri.path, uri.port, nil, nil, uri.user, uri.password, uri.scheme == "https", timeout)
@@ -114,7 +114,7 @@ module Mauve
#
if client.http.use_ssl?
client.http.ca_path = "/etc/ssl/certs/"
- client.http.verify_mode = Server.instance.remote_https_verify_mode
+ client.http.verify_mode = Configuration.current.remote_https_verify_mode
end
begin
diff --git a/lib/mauve/calendar_interface.rb b/lib/mauve/calendar_interface.rb
index cf515d1..692981d 100644
--- a/lib/mauve/calendar_interface.rb
+++ b/lib/mauve/calendar_interface.rb
@@ -17,52 +17,58 @@ module Mauve
@logger ||= Log4r::Logger.new(self.to_s)
end
- # Gets a list of ssologin on support.
+ def get_attendees(klass, at=Time.now)
+ #
+ # Returns nil if no calendar_url has been set.
+ #
+ return [] unless Configuration.current.bytemark_calendar_url
+
+ url = Configuration.current.bytemark_calendar_url.dup
+
+ url.merge!(File.join(url.path, "/api/attendees/#{klass}/#{at.strftime("%Y-%m-%dT%H:%M:00")}"))
+ ans = do_get(url)
+
+ return [] unless ans.is_a?(Array)
+
+ ans.select{|x| x.is_a?(String)}
+ end
+
#
- # @param [String] url A Calendar API url.
+ # This should return a list of dates of forthcoming bank holidays
#
- # @return [Array] A list of all the usernames on support.
- def get_users_on_support(url)
- result = do_get_with_cache(url)
-
- if result.is_a?(String)
- result = result.split("\n")
- else
- result = []
- end
+ def get_bank_holiday_list(at = Time.now)
+ return [] unless Configuration.current.bytemark_calendar_url
- return result
+ url = Configuration.current.bytemark_calendar_url.dup
+ url.merge!(File.join(url.path, "/api/bank_holidays/#{at.strftime("%Y-%m-%d")}"))
+ ans = do_get(url)
+
+ return [] unless ans.is_a?(Array)
+ ans.select{|x| x.is_a?(Date)}
end
- # Check to see if the user is on support.
+ # Check to see if the user is on holiday.
#
- # @param [String] url A Calendar API url.
- # @param [String] usr User single sign on.
+ # Class method.
#
- # @return [Boolean] True if on support, false otherwise.
- def is_user_on_support?(url, usr)
- return get_users_on_support(url).include?(usr)
+ # @param [String] usr User single sign on.
+ #
+ # @return [Boolean] True if on holiday, false otherwise.
+ def is_user_on_holiday?(usr, at=Time.now)
+ get_attendees("staff_holiday").include?(usr)
end
# Check to see if the user is on holiday.
#
# Class method.
#
- # @param [String] url A Calendar API url.
# @param [String] usr User single sign on.
#
# @return [Boolean] True if on holiday, false otherwise.
- def is_user_on_holiday?(url)
- result = do_get_with_cache(url)
-
- if result.is_a?(String) and result =~ /^\d{4}(-\d\d){2}[ T](\d\d:){2}\d\d/
- return true
- else
- return false
- end
+ def is_user_off_sick?(usr, at=Time.now)
+ get_attendees("sick_period", at).include?(usr)
end
-
private
# Grab a URL from the wide web.
@@ -74,7 +80,7 @@ module Mauve
#
def do_get (uri, limit = 11)
- if 0 == limit
+ if 0 > limit
logger.warn("HTTP redirect too deep for #{uri}.")
return nil
end
@@ -99,8 +105,22 @@ module Mauve
response = http.start { http.get(uri.request_uri()) }
if response.is_a?(Net::HTTPOK)
- return response.body
+ #
+ # Parse the string as YAML.
+ #
+ result = if response.body.is_a?(String)
+ begin
+ YAML.load(response.body)
+ rescue YAML::Error => err
+ logger.error "Caught #{ex.class.to_s} (#{ex.to_s}) whilst querying #{url.to_s}."
+ logger.debug err.backtrace.join("\n")
+ nil
+ end
+ else
+ nil
+ end
+ return result
elsif response.is_a?(Net::HTTPRedirection) and response.key?('Location')
location = response['Location']
@@ -123,6 +143,7 @@ module Mauve
logger.error("Timeout caught during fetch of #{uri.to_s}.")
rescue StandardError => ex
+ pp ex.backtrace
logger.error("#{ex.class} caught during fetch of #{uri.to_s}: #{ex.to_s}.")
logger.debug(ex.backtrace.join("\n"))
@@ -140,10 +161,10 @@ module Mauve
def do_get_with_cache(url, cache_until = Time.now + 5.minutes)
@cache ||= {}
- if @cache.has_key?(url.to_s)
- result, cache_until = @cache[url.to_s]
+ if @cache.has_key?(url)
+ result, cached_until = @cache[url]
- return result if cache_until >= Time.now and not result.nil?
+ return result if cached_until > Time.now and not result.nil?
end
result = do_get(url)
@@ -152,6 +173,19 @@ module Mauve
return result
end
+ #
+ # This should get called periodically.
+ #
+ def clean_cache
+
+ @cache.keys.select do |url|
+ result, cached_until = @cache[url]
+ @cache.delete(url) if !cached_until.is_a?(Time) or cached_until <= Time.now
+ end
+
+ @cache
+ end
+
end
end
diff --git a/lib/mauve/configuration.rb b/lib/mauve/configuration.rb
index 65f5f71..3a8f9cc 100644
--- a/lib/mauve/configuration.rb
+++ b/lib/mauve/configuration.rb
@@ -40,6 +40,12 @@ module Mauve
# @return [Hash]
attr_reader :source_lists
+ # Various further configuration items
+ #
+ attr_reader :bytemark_auth_url, :bytemark_calendar_url, :remote_http_timeout, :remote_https_verify_mode, :failed_login_delay
+ attr_reader :max_acknowledgement_time
+
+
#
# Set up a base config.
#
@@ -50,7 +56,114 @@ module Mauve
@people_lists = {}
@source_lists = Hash.new{|h,k| h[k] = Mauve::SourceList.new(k)}
@alert_groups = []
+
+ #
+ # Set the auth/calendar URLs
+ #
+ @bytemark_auth_url = nil
+ @bytemark_calendar_url = nil
+
+ #
+ # Set a couple of params for remote HTTP requests.
+ #
+ @remote_http_timeout = 5
+ @remote_https_verify_mode = OpenSSL::SSL::VERIFY_PEER
+
+ #
+ # Rate limit login attempts to limit the success of brute-forcing.
+ #
+ @failed_login_delay = 1
+
+ #
+ # Maximum amount of time to acknowledge for
+ #
+ @max_acknowledgement_time = 15.days
+ end
+
+ # Set the calendar URL.
+ #
+ # @param [String] arg
+ # @return [URI]
+ def bytemark_calendar_url=(arg)
+ raise ArgumentError, "bytemark_calendar_url must be a string" unless arg.is_a?(String)
+
+ @bytemark_calendar_url = URI.parse(arg)
+
+ #
+ # Make sure we get an HTTP URL.
+ #
+ raise ArgumentError, "bytemark_calendar_url must be an HTTP(S) URL." unless %w(http https).include?(@bytemark_calendar_url.scheme)
+
+ #
+ # Set a default request path, if none was given
+ #
+ @bytemark_calendar_url.normalize!
+
+ @bytemark_calendar_url
+ end
+
+ # Set the Bytemark Authentication URL
+ #
+ # @param [String] arg
+ # @return [URI]
+ def bytemark_auth_url=(arg)
+ raise ArgumentError, "bytemark_auth_url must be a string" unless arg.is_a?(String)
+
+ @bytemark_auth_url = URI.parse(arg)
+ #
+ # Make sure we get an HTTP URL.
+ #
+ raise ArgumentError, "bytemark_auth_url must be an HTTP(S) URL." unless %w(http https).include?(@bytemark_auth_url.scheme)
+
+ #
+ # Set a default request path, if none was given
+ #
+ @bytemark_auth_url.normalize!
+
+ @bytemark_auth_url
+ end
+
+ # Sets the timeout when making remote HTTP requests
+ #
+ # @param [Integer] arg
+ # @return [Integer]
+ def remote_http_timeout=(arg)
+ raise ArgumentError, "remote_http_timeout must be an integer" unless s.is_a?(Integer)
+ @remote_http_timeout = arg
+ end
+
+ # Sets the SSL verification mode when makeing remote HTTPS requests
+ #
+ # @param [String] arg must be one of "none" or "peer"
+ # @return [Constant]
+ def remote_https_verify_mode=(arg)
+ @remote_https_verify_mode = case arg
+ when "peer"
+ OpenSSL::SSL::VERIFY_PEER
+ when "none"
+ OpenSSL::SSL::VERIFY_NONE
+ else
+ raise ArgumentError, "remote_https_verify_mode must be either 'peer' or 'none'"
+ end
+ end
+
+ # Set the delay added following a failed login attempt.
+ #
+ # @param [Numeric] arg Number of seconds to delay following a failed login attempt
+ # @return [Numeric]
+ #
+ def failed_login_delay=(arg)
+ raise ArgumentError, "failed_login_delay must be numeric" unless arg.is_a?(Numeric)
+ @failed_login_delay = arg
end
+ # Set the maximum amount of time alerts can be ack'd for
+ #
+ #
+ def max_acknowledgement_time=(arg)
+ raise ArgumentError, "max_acknowledgement_time must be numeric" unless arg.is_a?(Numeric)
+ @max_acknowledgement_time = arg
+ end
+
end
end
diff --git a/lib/mauve/configuration_builder.rb b/lib/mauve/configuration_builder.rb
index 3f7138e..c689c1b 100644
--- a/lib/mauve/configuration_builder.rb
+++ b/lib/mauve/configuration_builder.rb
@@ -29,18 +29,6 @@ module Mauve
@result.source_lists[label] += list
end
- # Adds a people list
- #
- # @param [String] label
- # @param [Array] list
- #
- # @return [Array] the whole people list for label
- # ef people_list(label, *list)
- # _logger.warn("Duplicate people_list '#{label}'") if @result.people_lists.has_key?(label)
- # @result.people_lists[label] += list
- # end
-
-
# Have to use the method _logger here, cos logger is defined as a builder elsewhere.
#
# @return [Log4r::Logger]
diff --git a/lib/mauve/configuration_builders/notification_method.rb b/lib/mauve/configuration_builders/notification_method.rb
index 3f9283e..7951dee 100644
--- a/lib/mauve/configuration_builders/notification_method.rb
+++ b/lib/mauve/configuration_builders/notification_method.rb
@@ -40,18 +40,6 @@ module Mauve
result.extend(Mauve::Notifiers::Debug)
end
- # This catches all methods available for a provider, as needed.
- #
- # Missing methods / bad arguments etc. are caught in the
- # ObjectBuilder#parse method, via NoMethodError.
- #
- def method_missing(name, value=nil)
- if value
- result.send("#{name}=".to_sym, value)
- else
- result.send(name.to_sym)
- end
- end
end
end
diff --git a/lib/mauve/configuration_builders/person.rb b/lib/mauve/configuration_builders/person.rb
index dff6f85..7a20491 100644
--- a/lib/mauve/configuration_builders/person.rb
+++ b/lib/mauve/configuration_builders/person.rb
@@ -18,12 +18,14 @@ module Mauve
is_block_attribute "urgent"
is_block_attribute "normal"
is_block_attribute "low"
+
is_attribute "password"
is_attribute "sms"
- is_attribute "holiday_url"
is_attribute "email"
is_attribute "xmpp"
- is_attribute "sms"
+
+ is_flag_attribute "notify_when_on_holiday!"
+ is_flag_attribute "notify_when_off_sick!"
# Sets the block for all levels of alert
#
diff --git a/lib/mauve/configuration_builders/server.rb b/lib/mauve/configuration_builders/server.rb
index d22ed87..734fb3b 100644
--- a/lib/mauve/configuration_builders/server.rb
+++ b/lib/mauve/configuration_builders/server.rb
@@ -171,31 +171,6 @@ module Mauve
is_attribute "use_packet_buffer"
is_attribute "use_notification_buffer"
- #
- # This is where the calendar is located. The request paths are hard-coded.
- #
- is_attribute "bytemark_calendar_url"
-
- #
- # This is where the Bytemark authentication server is located.
- #
- is_attribute "bytemark_auth_url"
-
- #
- # This is the level of SSL verification used when making external HTTPS connections.
- #
- is_attribute "remote_https_verify_mode"
-
- #
- # This is the default timeout when making remote HTTP requests
- #
- is_attribute "remote_http_timeout"
-
- #
- # This is the default sleep time after an authentication attempt has failed.
- #
- is_attribute "failed_login_delay"
-
def builder_setup
@result = Mauve::Server.instance
end
diff --git a/lib/mauve/mauve_time.rb b/lib/mauve/mauve_time.rb
index f564fdb..dfbf99b 100644
--- a/lib/mauve/mauve_time.rb
+++ b/lib/mauve/mauve_time.rb
@@ -98,12 +98,37 @@ class Time
t
end
+ # Returns the bank_holidays array, or an empty array if bank_holidays hasn't
+ # been set.
+ #
+ #
+ def bank_holidays
+ @bank_holidays ||= []
+ end
+
+ # This sets the bank holiday dates for the bank_holiday? check.
+ #
+ # @param [Array] arg An array of Date of bank holidays
+ # @returns [Array]
+ #
+ def bank_holidays=(arg)
+ raise ArgumentError unless arg.is_a?(Array) and arg.all?{|a| a.is_a?(Date)}
+ @bank_holidays = arg
+ end
+
+ # This relies on bank_holidays being set.
+ #
+ def bank_holiday?
+ today = Date.new(self.year, self.month, self.day)
+ self.bank_holidays.any?{|bh| bh == today}
+ end
+
# Test to see if we're in working hours. The working day is from 8.30am until
# 17:00
#
# @return [Boolean]
def working_hours?
- (1..5).include?(self.wday) and ((9..16).include?(self.hour) or (self.hour == 8 && self.min >= 30))
+ !bank_holiday? and (1..5).include?(self.wday) and ((9..16).include?(self.hour) or (self.hour == 8 && self.min >= 30))
end
# Test to see if it is currently daytime. The daytime day is 14 hours long
@@ -113,7 +138,6 @@ class Time
(8..21).include?(self.hour)
end
-
# We're always in wallclock hours
#
# @return [true]
diff --git a/lib/mauve/notification.rb b/lib/mauve/notification.rb
index d06e03a..5877e0f 100644
--- a/lib/mauve/notification.rb
+++ b/lib/mauve/notification.rb
@@ -163,8 +163,9 @@ module Mauve
# Test to see if we're in working hours. See Time#working_hours?
#
# @return [Boolean]
- def working_hours?
+ def working_hours?
@test_time = @time if @test_time.nil?
+ @test_time.bank_holidays = Server.instance.bank_holidays
@test_time.working_hours?
end
diff --git a/lib/mauve/notifiers/xmpp.rb b/lib/mauve/notifiers/xmpp.rb
index a0ad86e..b291442 100644
--- a/lib/mauve/notifiers/xmpp.rb
+++ b/lib/mauve/notifiers/xmpp.rb
@@ -604,7 +604,10 @@ EOF
end
begin
- ack_until = Time.now.in_x_hours(n_hours, type_hours)
+ now = Time.now
+ now.bank_holidays = Server.instance.bank_holidays
+
+ ack_until = now.in_x_hours(n_hours, type_hours)
rescue RangeError
return "I'm sorry, you tried to acknowedge for far too long, and my buffers overflowed!"
end
diff --git a/lib/mauve/people_list.rb b/lib/mauve/people_list.rb
index eab4ae3..0433034 100644
--- a/lib/mauve/people_list.rb
+++ b/lib/mauve/people_list.rb
@@ -35,6 +35,8 @@ module Mauve
arr = arr.flatten
when String
arr = [arr]
+ when Proc
+ arr = [arr]
else
logger.warn "Not sure what to do with #{arr.inspect} -- converting to string, and continuing"
arr = [arr.to_s]
@@ -62,10 +64,12 @@ module Mauve
#
# @return [Array]
def people
-
l = list.collect do |name|
- Configuration.current.people.has_key?(name) ? Configuration.current.people[name] : nil
- end.reject{|person| person.nil?}
+ name.is_a?(Proc) ? name.call : name
+ end.flatten.compact.uniq.collect do |name|
+ Configuration.current.people[name]
+ end.compact
+
#
# Hmm.. no-one in the list?!
#
diff --git a/lib/mauve/person.rb b/lib/mauve/person.rb
index 1cf4ea0..929f511 100644
--- a/lib/mauve/person.rb
+++ b/lib/mauve/person.rb
@@ -3,23 +3,15 @@ require 'timeout'
require 'log4r'
module Mauve
- class Person < Struct.new(:username, :password, :urgent, :normal, :low, :email, :xmpp, :sms)
+ class Person
+ attr_reader :username, :password, :urgent, :normal, :low, :email, :xmpp, :sms
attr_reader :notification_thresholds, :last_pop3_login, :suppressed, :notifications
-
+ attr_reader :notify_when_off_sick, :notify_when_on_holiday
+
# Set up a new Person
#
- # @param [Hash] args The options for setting up the person
- # @option args [String] :username The person's username
- # @option args [String] :password The SHA1 sum of the person's password
- # @option args [String] :holiday_url The URL that can be checked by Mauve::CalendarInterface#is_user_on_holiday?
- # @option args [Proc] :urgent The block to execute when an urgent-level notification is issued
- # @option args [Proc] :normal The block to execute when an normal-level notification is issued
- # @option args [Proc] :low The block to execute when an low-level notification is issued
- # @option args [String] :email The person's email address
- # @option args [String] :sms The person's mobile number
- #
- def initialize(*args)
+ def initialize(username)
@notification_thresholds = nil
@suppressed = false
#
@@ -28,9 +20,85 @@ module Mauve
@last_pop3_login = {:from => nil, :at => nil}
@notifications = []
- super(*args)
- end
+ @username = username
+ @password = nil
+ @urgent = lambda { false }
+ @normal = lambda { false }
+ @low = lambda { false }
+ @email = @sms = @xmpp = nil
+ @notify_when_on_holiday = @notify_when_off_sick = false
+ end
+
+ # Determines if a user should be notified if they're ill.
+ #
+ # @return [Boolean]
+ #
+ def notify_when_off_sick!
+ @notify_when_off_sick = true
+ end
+
+ # Determines if a user should be notified if they're on their holdiays.
+ #
+ # @return [Boolean]
+ #
+ def notify_when_on_holiday!
+ @notify_when_on_holiday = true
+ end
+
+ # Sets the Proc to call for urgent notifications
+ #
+ def urgent=(block)
+ raise ArgumentError unless block.is_a?(Proc)
+ @urgent = block
+ end
+
+ # Sets the Proc to call for normal notifications
+ #
+ def normal=(block)
+ raise ArgumentError unless block.is_a?(Proc)
+ @normal = block
+ end
+
+ # Sets the Proc to call for low notifications
+ #
+ def low=(block)
+ raise ArgumentError unless block.is_a?(Proc)
+ @low = block
+ end
+
+ # Sets the email parameter
+ #
+ #
+ def email=(arg)
+ raise ArgumentError unless arg.is_a?(String)
+ @email = arg
+ end
+
+ # Sets the sms parameter
+ #
+ #
+ def sms=(arg)
+ raise ArgumentError unless arg.is_a?(String)
+ @sms = arg
+ end
+
+ # Sets the xmpp parameter
+ #
+ #
+ def xmpp=(arg)
+ raise ArgumentError unless arg.is_a?(String)
+ @xmpp = arg
+ end
+
+ # Sets the password parameter
+ #
+ #
+ def password=(arg)
+ raise ArgumentError unless arg.is_a?(String)
+ @password=arg
+ end
+
# @return Log4r::Logger
def logger ; @logger ||= Log4r::Logger.new self.class.to_s ; end
@@ -39,8 +107,6 @@ module Mauve
# @return [Boolean]
def suppressed? ; @suppressed ; end
- def holiday_url ; nil ; end
-
# Works out if a notification should be suppressed. If no parameters are supplied, it will
#
# @param [Time] Theoretical time of notification
@@ -155,8 +221,7 @@ module Mauve
# @param [Mauve::Alert] alert Alert we're notifiying about
#
# @return [Boolean] if the notification was successful
- def send_alert(level, alert)
- now = Time.now
+ def send_alert(level, alert, now=Time.now)
was_suppressed = @suppressed
@suppressed = self.should_suppress?
@@ -168,7 +233,7 @@ module Mauve
# We only suppress notifications if we were suppressed before we started,
# and are still suppressed.
#
- if @suppressed or self.is_on_holiday?
+ if @suppressed or self.is_on_holiday?(now) or self.is_off_sick?(now)
note = "#{alert.update_type.capitalize} notification to #{self.username} suppressed"
logger.info note + " about #{alert}."
History.create(:alerts => [alert], :type => "notification", :event => note)
@@ -217,20 +282,19 @@ module Mauve
end
end
- #
- #
- #
- def alert_during
-
- end
-
# Whether the person is on holiday or not.
#
# @return [Boolean] True if person on holiday, false otherwise.
- def is_on_holiday? ()
- return false if holiday_url.nil? or holiday_url.empty?
+ def is_on_holiday?(at=Time.now)
+ return false if self.notify_when_on_holiday
+
+ return CalendarInterface.is_user_on_holiday?(self.username, at)
+ end
+
+ def is_off_sick?(at=Time.now)
+ return false if self.notify_when_off_sick
- return CalendarInterface.is_user_on_holiday?(holiday_url)
+ return CalendarInterface.is_user_off_sick?(self.username, at)
end
end
diff --git a/lib/mauve/processor.rb b/lib/mauve/processor.rb
index 0ac7b59..acf72b3 100644
--- a/lib/mauve/processor.rb
+++ b/lib/mauve/processor.rb
@@ -57,14 +57,11 @@ module Mauve
to_delete = []
- @transmission_id_cache.each do |tid, received_at|
- to_delete << tid if (now - received_at) > @transmission_cache_expire_time
+ @transmission_id_cache = @transmission_id_cache.delete_if do |cache_data|
+ tid, received_at = cache_data
+ (now - received_at) > @transmission_cache_expire_time
end
- to_delete.each do |tid|
- @transmission_id_cache.delete(tid)
- end
-
@transmission_cache_checked_at = now
end
@@ -197,6 +194,11 @@ module Mauve
sz.times do
process_packet(*Server.packet_pop)
end
+
+ #
+ # Now expire the cache. This will only get processed at most once every minute.
+ #
+ expire_transmission_id_cache
end
def timer_should_stop?
diff --git a/lib/mauve/server.rb b/lib/mauve/server.rb
index 2b0e101..366191c 100644
--- a/lib/mauve/server.rb
+++ b/lib/mauve/server.rb
@@ -50,21 +50,10 @@ module Mauve
@notification_buffer = []
#
- # Set the auth/calendar URLs
+ # Bank Holidays -- this list is kept here, because I can't think of
+ # anywhere else to put it.
#
- @bytemark_auth_url = nil
- @bytemark_calendar_url = nil
-
- #
- # Set a couple of params for remote HTTP requests.
- #
- @remote_http_timeout = 5
- @remote_https_verify_mode = OpenSSL::SSL::VERIFY_PEER
-
- #
- # Rate limit login attempts to limit the success of brute-forcing.
- #
- @failed_login_delay = 1
+ @bank_holidays = nil
#
# Set up a blank config.
@@ -114,83 +103,6 @@ module Mauve
@notification_buffer
end
- # Set the calendar URL.
- #
- # @param [String] arg
- # @return [URI]
- def bytemark_calendar_url=(arg)
- raise ArgumentError, "bytemark_calendar_url must be a string" unless arg.is_a?(String)
-
- @bytemark_calendar_url = URI.parse(arg)
-
- #
- # Make sure we get an HTTP URL.
- #
- raise ArgumentError, "bytemark_calendar_url must be an HTTP(S) URL." unless %w(http https).include?(@bytemark_calendar_url.scheme)
-
- #
- # Set a default request path, if none was given
- #
- @bytemark_calendar_url.path="/" if @bytemark_calendar_url.path.empty?
-
- @bytemark_calendar_url
- end
-
- # Set the Bytemark Authentication URL
- #
- # @param [String] arg
- # @return [URI]
- def bytemark_auth_url=(arg)
- raise ArgumentError, "bytemark_auth_url must be a string" unless arg.is_a?(String)
-
- @bytemark_auth_url = URI.parse(arg)
- #
- # Make sure we get an HTTP URL.
- #
- raise ArgumentError, "bytemark_auth_url must be an HTTP(S) URL." unless %w(http https).include?(@bytemark_auth_url.scheme)
-
- #
- # Set a default request path, if none was given
- #
- @bytemark_auth_url.path="/" if @bytemark_auth_url.path.empty?
-
- @bytemark_auth_url
- end
-
- # Sets the timeout when making remote HTTP requests
- #
- # @param [Integer] arg
- # @return [Integer]
- def remote_http_timeout=(arg)
- raise ArgumentError, "initial_sleep must be an integer" unless s.is_a?(Integer)
- @remote_http_timeout = arg
- end
-
- # Sets the SSL verification mode when makeing remote HTTPS requests
- #
- # @param [String] arg must be one of "none" or "peer"
- # @return [Constant]
- def remote_https_verify_mode=(arg)
- @remote_https_verify_mode = case arg
- when "peer"
- OpenSSL::SSL::VERIFY_PEER
- when "none"
- OpenSSL::SSL::VERIFY_NONE
- else
- raise ArgumentError, "remote_https_verify_mode must be either 'peer' or 'none'"
- end
- end
-
- # Set the delay added following a failed login attempt.
- #
- # @param [Numeric] arg Number of seconds to delay following a failed login attempt
- # @return [Numeric]
- #
- def failed_login_delay=(arg)
- raise ArgumentError, "initial_sleep must be numeric" unless arg.is_a?(Numeric)
- @failed_login_delay = arg
- end
-
# Set the sleep period during which notifications about old alerts are
# suppressed.
#
@@ -207,6 +119,24 @@ module Mauve
Time.now < self.started_at + self.initial_sleep
end
+ # Check with the calendar for the list of bank holidays
+ #
+ #
+ def bank_holidays
+ #
+ # Update the bank holidays list hourly.
+ #
+ if @bank_holidays.nil? or
+ @bank_holidays_last_checked_at.nil? or
+ @bank_holidays_last_checked_at < (Time.now - 1.hour)
+
+ @bank_holidays = CalendarInterface.get_bank_holiday_list(Time.now)
+ @bank_holidays_last_checked_at = Time.now
+ end
+
+ @bank_holidays
+ end
+
# return [Log4r::Logger]
def logger
@logger ||= Log4r::Logger.new(self.class.to_s)
diff --git a/lib/mauve/web_interface.rb b/lib/mauve/web_interface.rb
index 16e7da2..a8e1ece 100644
--- a/lib/mauve/web_interface.rb
+++ b/lib/mauve/web_interface.rb
@@ -218,9 +218,13 @@ EOF
note = params[:note] || nil
n_hours = (n_hours.to_f > 188 ? 188 : n_hours.to_f)
+ type_hours = "daytime" unless %w(daytime working wallclock).include?(type_hours)
if ack_until.to_s.empty?
- ack_until = Time.now.in_x_hours(n_hours, type_hours.to_s)
+ now = Time.now
+ now.bank_holidays = Server.instance.bank_holidays
+
+ ack_until = now.in_x_hours(n_hours, type_hours.to_s)
else
ack_until = Time.at(ack_until.to_i)
end
@@ -275,12 +279,14 @@ EOF
#
n_hours = ( n_hours > 300 ? 300 : n_hours )
type_hours = "daytime" unless %w(daytime working wallclock).include?(type_hours)
- ack_until = Time.now.in_x_hours(n_hours, type_hours)
+ now = Time.now
+ now.bank_holidays = Server.instance.bank_holidays
+ ack_until = now.in_x_hours(n_hours, type_hours)
#
# Make sure we can't ack longer than a week.
#
- max_ack = (Time.now + 86400*8)
+ max_ack = (Time.now + Configuration.current.max_acknowledgement_time)
ack_until = max_ack if ack_until > max_ack
#
@@ -359,8 +365,13 @@ EOF
type_hours = params[:type_hours].to_s
note = params[:note] || nil
+ type_hours = "daytime" unless %w(daytime working wallclock).include?(type_hours)
+
if ack_until == 0
- ack_until = Time.now.in_x_hours(n_hours, type_hours)
+ now = Time.now
+ now.bank_holidays = Server.instance.bank_holidays
+
+ ack_until = now.in_x_hours(n_hours, type_hours)
else
ack_until = Time.at(ack_until)
end
diff --git a/lib/object_builder.rb b/lib/object_builder.rb
index ebd655b..ccb2c63 100644
--- a/lib/object_builder.rb
+++ b/lib/object_builder.rb
@@ -181,6 +181,20 @@ class ObjectBuilder
end
end
+ # This catches all methods available for a provider, as needed.
+ #
+ # Missing methods / bad arguments etc. are caught in the
+ # ObjectBuilder#parse method, via NoMethodError.
+ #
+ def method_missing(name, value=nil)
+ if value
+ result.send("#{name}=".to_sym, value)
+ else
+ result.send(name.to_sym)
+ end
+ end
+
+
class << self
# Defines a new builder