Skip to content

Commit

Permalink
Refactoring SMS credentials to be multi-tenant and persisted in database
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim Van Fleet committed Nov 21, 2017
1 parent 060dccf commit 64cedd9
Show file tree
Hide file tree
Showing 21 changed files with 131 additions and 293 deletions.
5 changes: 4 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,8 @@ DEPENDENCIES
unicorn
webmock

RUBY VERSION
ruby 2.2.3p173

BUNDLED WITH
1.10.6
1.15.1
1 change: 1 addition & 0 deletions app/models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ module Models
require 'app/models/city'
require 'app/models/event'
require 'app/models/publisher'
require 'app/models/sms_credentials'
require 'app/models/subscription'

# access model class constants without qualifying namespace
Expand Down
4 changes: 4 additions & 0 deletions app/models/publisher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Citygram::Models
class Publisher < Sequel::Model
one_to_many :subscriptions
one_to_many :events
many_to_one :sms_credentials

plugin :url_validation
plugin :serialization, :pg_array, :tags
Expand All @@ -19,6 +20,9 @@ def active
where(active: true)
end
end

delegate :credential_name, :from_number, :account_sid, :auth_token, to: :sms_credentials


def validate
super
Expand Down
12 changes: 12 additions & 0 deletions app/models/sms_credentials.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Citygram::Models
class SmsCredentials < Sequel::Model
dataset_module do
end

def validate
super
validates_presence [:from_number, :account_sid, :auth_token]
validates_unique :account_sid
end
end
end
2 changes: 2 additions & 0 deletions app/models/subscription.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ def last_notification
def last_notification_date
self.last_notification.strftime("%b %d, %Y")
end

delegate :credential_name, :from_number, :account_sid, :auth_token, to: :publisher

def validate
super
Expand Down
15 changes: 15 additions & 0 deletions app/modules/sms_sender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Citygram
module SmsSender

def send_sms(subscription, body)
Citygram::App.logger.info("Sending SMS via #{subscription.credential_name}")
Citygram::Services::Channels::SMS.sms(
subscription.account_sid,
subscription.auth_token, {
from: subscription.from_number,
to: subscription.phone_number,
body: body
})
end
end
end
1 change: 1 addition & 0 deletions app/services/channels.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class NotificationFailure < StandardError; end
end
end

require 'app/modules/sms_sender'
require 'app/services/channels/base'
require 'app/services/channels/email'
require 'app/services/channels/sms'
Expand Down
15 changes: 5 additions & 10 deletions app/services/channels/sms.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
module Citygram::Services::Channels
class SMS < Base
FROM_NUMBER = ENV.fetch('TWILIO_FROM_NUMBER').freeze

include ::Citygram::SmsSender

TWILIO_ACCOUNT_SID = ENV.fetch('TWILIO_ACCOUNT_SID').freeze
TWILIO_AUTH_TOKEN = ENV.fetch('TWILIO_AUTH_TOKEN').freeze

UNSUBSCRIBE_ERROR_CODES = [
21211, # number cannot exist - https://www.twilio.com/docs/errors/21211
21610, # user replied with a stop word - https://www.twilio.com/docs/errors/21610
21614, # not a valid mobile number - https://www.twilio.com/docs/errors/21614
].freeze

def self.sms(*args)
client = Twilio::REST::Client.new(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
def self.sms(sid, token, *args)
client = Twilio::REST::Client.new(sid, token)
client.account.messages.create(*args)
end

def call
self.class.sms(
from: FROM_NUMBER,
to: subscription.phone_number,
body: event.title
)
send_sms(subscription, event.title)
rescue Twilio::REST::RequestError => e
Citygram::App.logger.error(e)

Expand Down
2 changes: 2 additions & 0 deletions app/workers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ module Workers
end
end

require 'app/modules/sms_sender'
require 'app/workers/publisher_poll'
require 'app/workers/notifier'
require 'app/workers/subscription_confirmation'
require 'app/workers/reminder_notification'
require 'app/workers/middleware/database_connections'


Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add Citygram::Workers::Middleware::DatabaseConnections, Sequel::Model.db
Expand Down
7 changes: 2 additions & 5 deletions app/workers/reminder_notification.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Citygram::Workers
class ReminderNotification
include Sidekiq::Worker
include ::Citygram::SmsSender
sidekiq_options retry: 5

def reminder_url(subscription)
Expand All @@ -23,11 +24,7 @@ def perform(subscription_id)
# ...but if there is an error sending this message, tomorrow's might work
subscription.remind!
[body_1, body_2].each do |body|
Citygram::Services::Channels::SMS.sms(
from: Citygram::Services::Channels::SMS::FROM_NUMBER,
to: subscription.phone_number,
body: body
)
send_sms(subscription, body)
end
rescue Twilio::REST::RequestError => e
Citygram::App.logger.error(e)
Expand Down
9 changes: 3 additions & 6 deletions app/workers/subscription_confirmation.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module Citygram::Workers
class SubscriptionConfirmation
include Sidekiq::Worker
include ::Citygram::SmsSender

sidekiq_options retry: 5

def digest_url(subscription)
Expand All @@ -15,12 +17,7 @@ def perform(subscription_id)
case subscription.channel
when 'sms'
body = "Welcome! You are now subscribed to #{publisher.title} in #{publisher.city}. To see current Citygrams please visit #{digest_url(subscription)}. To unsubscribe from all messages, reply REMOVE."

Citygram::Services::Channels::SMS.sms(
from: Citygram::Services::Channels::SMS::FROM_NUMBER,
to: subscription.phone_number,
body: body
)
send_sms(subscription, body)
when 'email'
body = <<-BODY.dedent
<p>Thank you for subscribing! <a href="#{digest_url(subscription)}">View Citygrams</a> in a browser.</p>
Expand Down
17 changes: 17 additions & 0 deletions db/migrations/031_create_sms_credentials.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Sequel.migration do
up do
create_table :sms_credentials do
primary_key :id
String :credential_name
String :from_number
String :account_sid
String :auth_token
DateTime :updated_at
DateTime :created_at
end
end

down do
drop_table :sms_credentials
end
end
13 changes: 13 additions & 0 deletions db/migrations/032_add_sms_credentials_to_publisher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Sequel.migration do
up do
alter_table(:publishers) do
add_foreign_key :sms_credentials_id, :sms_credentials
end
end

down do
alter_table(:publishers) do
drop_foreign_key :sms_credentials_id
end
end
end
Loading

0 comments on commit 64cedd9

Please sign in to comment.