lib/sym/app/password/cache.rb
require 'digest'
require 'singleton'
require 'colored2'
require 'timeout'
require 'sym/extensions/with_retry'
require 'sym/extensions/with_timeout'
require 'sym/configuration'
require 'sym/app/password/providers'
module Sym
module App
module Password
# +Provider+ is the primary implementation of the underlying cache.
# It should support the following API:
#
# def initialize(*args, **opts, &block)
# end
#
# def read(key)
# end
#
# def write(key, value, expire_timeout_seconds)
# end
#
# it must be intantiatable via #new
class Cache
include Singleton
include Sym::Extensions::WithRetry
include Sym::Extensions::WithTimeout
attr_accessor :provider, :enabled, :timeout, :verbose
def configure(**opts)
self.enabled = opts[:enabled]
self.verbose = opts[:verbose]
self.timeout = opts[:timeout] || ::Sym::Configuration.config.password_cache_timeout
self.provider = Providers.provider(opts[:provider], **(opts[:provider_opts] || {}))
self.enabled = false unless self.provider
self
end
def [](key)
cache = self
operation { cache.provider.read(cache.md5(key)) }
end
def []=(key, value)
cache = self
operation { cache.provider.write(cache.md5(key), value, cache.timeout) }
end
def md5(string)
Digest::MD5.base64digest(string)
end
private
def operation
return nil unless self.enabled
with_timeout(1) do
with_retry do
yield if block_given?
end
end
rescue Timeout::Error => e
error(nil, 'Password cache server timed out...')
rescue StandardError => e
error(e, 'Error connecting to password caching server...')
end
def error(exception = nil, message = nil)
if self.verbose
print 'WARNING: '
print message ? message.yellow : ''
print exception ? exception.message.red : ''
puts
end
self.enabled = false
nil
end
end
end
end
end