Module: Safetynet

Extended by:
ActiveSupport::Concern
Defined in:
lib/safetynet.rb,
lib/safetynet/engine.rb,
lib/safetynet/history.rb,
lib/safetynet/version.rb,
lib/safetynet/notification_mailer.rb

Defined Under Namespace

Modules: ClassMethods Classes: Engine, History, NotificationMailer

Constant Summary collapse

VERSION =
"0.1.1"

Instance Method Summary collapse

Instance Method Details

#check_safetynet_windowObject

Hook added to after_filter to disable current action or mail delivery



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/safetynet.rb', line 84

def check_safetynet_window
  # Skip check if email is already stopped
  return false if mail.perform_deliveries == false

  channel = self.class.safetynet_channel
  options = self.class.safetynet_options
  method = action_name
  limit = options[channel][:limit]
  timeframe = options[channel][:timeframe]

  # Update the mail.to array with those who are whitelisted and permitted
  mail.to = mail.to.keep_if do |email|
    next true if is_whitelisted?(email)
    permit_delivery?(email, channel, method, limit, timeframe)
  end

  permit_delivery = mail.to.any?

  if channel == :email
    mail.perform_deliveries = permit_delivery
  end
  permit_delivery
end

#is_whitelisted?(address) ⇒ Boolean

Permits all whitelisted addresses by regex

Returns:

  • (Boolean)


109
110
111
# File 'lib/safetynet.rb', line 109

def is_whitelisted?(address)
  !!(self.class.safetynet_options[:whitelist].match(address))
end

#permit_delivery?(address, channel = nil, method = nil, limit = nil, timeframe = nil) ⇒ Boolean

Returns true if delivery is permitted through the given channel

user        A model to monitor
channel     email|sms (symbol)
method      Name of watched method
limit       Maximum # of methods for this channel
timeframe   Minimum allowed timeframe between last method and next (default: 30.minutes)

Standalone usage on a User model

* Defaults to configured channel, caller method,
* and rails configuration limit & timeframe for the channel

class User < ActiveRecord::Base
  include Safetynet
  safetynet :sms

  def send_sms
    if permit_delivery?(self)
      ...
    end
  end
end

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/safetynet.rb', line 40

def permit_delivery?(address, channel=nil, method=nil, limit=nil, timeframe=nil)
  # Skip check if address is whitelisted
  return true if is_whitelisted?(address)

  options = self.class.safetynet_options
  # Set defaults from current config and call stack
  channel = self.class.safetynet_channel if channel.nil?
  method = caller_locations(1, 1)[0].label if method.nil?
  limit = options[channel][:limit] if limit.nil?
  timeframe = options[channel][:timeframe] if timeframe.nil?

  # Query the model to determine if delivery is permitted
  permit_delivery = true
  if limit != false
    count_query = Safetynet::History.where({
      address: address,
      channel: channel,
      method: method
    })

    if timeframe != false
      count_query = count_query.where('created_at >= ?', Time.now - timeframe)
    end

    # If our sending is over the limit, deny
    if count_query.count >= limit
      permit_delivery = false
    end
  end

  if permit_delivery
    save_safetynet_delivery(address, channel, method)
  else
    Safetynet::NotificationMailer.delivery_denied_notification(address, channel, method, {
      limit: limit,
      timeframe: timeframe,
      message: 'Safetynet has caught a method!'
    }).deliver
  end

  permit_delivery
end

#save_safetynet_delivery(address, channel, method) ⇒ Object

Saves a record for the current method



10
11
12
13
14
15
16
17
# File 'lib/safetynet.rb', line 10

def save_safetynet_delivery(address, channel, method)
  Safetynet::History.create({
    address: address,
    method: method,
    channel: channel.to_s,
    created_at: Time.now
  })
end