Skip to content

Commit

Permalink
feat: geolocation setter in sendgrid-ruby for GDPR compliance
Browse files Browse the repository at this point in the history
  • Loading branch information
manisha1997 committed Nov 22, 2023
1 parent bc213ec commit 82be96b
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 114 deletions.
66 changes: 2 additions & 64 deletions examples/dataresidency/setregion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
content = SendGrid::Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = SendGrid::Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
sg.sendgrid_data_residency(region: "global")
puts sg.host
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
Expand All @@ -24,7 +25,7 @@
content = SendGrid::Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = SendGrid::Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY_EU'])
sg.data_residency(region: 'eu')
sg.sendgrid_data_residency(region: 'eu')
puts sg.host
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
Expand All @@ -45,66 +46,3 @@
puts response.status_code
puts response.body
puts response.headers

# Example 4
# Sending using "global" data residency in constructor

from = SendGrid::Email.new(email: '[email protected]')
to = SendGrid::Email.new(email: '[email protected]')
subject = 'Sending with Twilio SendGrid is Fun'
content = SendGrid::Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = SendGrid::Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'], region: 'global')
puts sg.host
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
puts response.body
puts response.headers

# Example 5
# Sending using "eu" data residency in constructor

from = SendGrid::Email.new(email: '[email protected]')
to = SendGrid::Email.new(email: '[email protected]')
subject = 'Sending with Twilio SendGrid is Fun'
content = SendGrid::Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = SendGrid::Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY_EU'], region: 'eu')
puts sg.host
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
puts response.body
puts response.headers

# Example 6
# Sending using "nil" data residency
# This will throw exception because data residency cannot be null

from = SendGrid::Email.new(email: '[email protected]')
to = SendGrid::Email.new(email: '[email protected]')
subject = 'Sending with Twilio SendGrid is Fun'
content = SendGrid::Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = SendGrid::Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY_EU'])
sg.data_residency(region: nil)
puts sg.host
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
puts response.body
puts response.headers

# Example 7
# First region, then host
from = SendGrid::Email.new(email: '[email protected]')
to = SendGrid::Email.new(email: '[email protected]')
subject = 'Sending with Twilio SendGrid is Fun'
content = SendGrid::Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = SendGrid::Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
sg.data_residency(region: "eu")
sg.update_host(host: "https://api.sendgrid.com")
puts sg.host
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
puts response.body
puts response.headers
28 changes: 12 additions & 16 deletions lib/sendgrid/base_interface.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@ class BaseInterface
# in the "On-Behalf-Of" header
# - +http_options+ -> http options that you want to be globally applied to each request
#
def initialize(auth:, host:, region: nil, request_headers: nil, version: nil, impersonate_subuser: nil, http_options: {})
def initialize(auth:, host:, request_headers: nil, version: nil, impersonate_subuser: nil, http_options: {})
@auth = auth
if !region.nil?
data_residency(region: region)
else
@host = host
end
@host = host
@version = version || 'v3'
@impersonate_subuser = impersonate_subuser
@user_agent = "sendgrid/#{SendGrid::VERSION};ruby"
Expand All @@ -42,20 +38,20 @@ def initialize(auth:, host:, region: nil, request_headers: nil, version: nil, im
http_options: @http_options)
end

def update_host(host:)
@host = host
@client = SendGrid::Client.new(host: "#{@host}/#{@version}",
request_headers: @request_headers,
http_options: @http_options)
end

def data_residency(region:)
# Client libraries contain setters for specifying region/edge.
# This supports global and eu regions only. This set will likely expand in the future.
# Global is the default residency (or region)
# Global region means the message will be sent through https://api.sendgrid.com
# EU region means the message will be sent through https://api.eu.sendgrid.com
# Parameters:
# - region(String) : specify the region. Currently supports "global" and "eu"
def sendgrid_data_residency(region:)
region_host_dict = { "eu" => 'https://api.eu.sendgrid.com', "global" => 'https://api.sendgrid.com' }
raise ArgumentError, "region can only be \"eu\" or \"global\"" if region.nil? || !region_host_dict.key?(region)

@host = region_host_dict[region]
@client = SendGrid::Client.new(host: "#{@host}/#{@version}",
request_headers: @request_headers,
http_options: @http_options)
request_headers: @request_headers,
http_options: @http_options)
end
end
5 changes: 2 additions & 3 deletions lib/sendgrid/sendgrid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ class API < BaseInterface
# - +impersonate_subuser+ -> the subuser to impersonate, will be passed
# in the "On-Behalf-Of" header
# - +http_options+ -> http options that you want to be globally applied to each request
# - +region+ -> data residency. The values only be either 'eu' or 'global'.
#
def initialize(api_key:, host: nil, region: nil, request_headers: nil, version: nil, impersonate_subuser: nil, http_options: {})
def initialize(api_key:, host: nil, request_headers: nil, version: nil, impersonate_subuser: nil, http_options: {})
auth = "Bearer #{api_key}"
host ||= 'https://api.sendgrid.com'
super(auth: auth, host: host, region: region, request_headers: request_headers, version: version, impersonate_subuser: impersonate_subuser, http_options: http_options)
super(auth: auth, host: host, request_headers: request_headers, version: version, impersonate_subuser: impersonate_subuser, http_options: http_options)
end
end
end
40 changes: 9 additions & 31 deletions test/sendgrid/helpers/mail/test_data_residency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,63 +11,41 @@ def setup

def test_with_global_data_residency
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
sg.data_residency(region: 'global')
assert_equal @global_email, sg.host
end

def test_with_global_data_residency_in_constructor
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'], region: 'global')
sg.sendgrid_data_residency(region: 'global')
assert_equal @global_email, sg.host
end

def test_with_global_eu_residency
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
sg.data_residency(region: 'eu')
assert_equal @eu_email, sg.host
end

def test_with_global_eu_residency_in_constructor
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'], region: 'eu')
assert_equal @eu_email, sg.host
end

def test_with_host_set_first_and_residency_set_second
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'], region: 'eu')
sg.update_host(host: "https://api.test.sendgrid.com")
sg.data_residency(region: "eu")
sg.sendgrid_data_residency(region: 'eu')
assert_equal @eu_email, sg.host
end

def test_with_residency_set_first_and_host_set_second
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'], region: 'eu')
sg.data_residency(region: "eu")
sg.update_host(host: "https://api.test.sendgrid.com")
assert_equal "https://api.test.sendgrid.com", sg.host
end

def test_with_global_nil_residency
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
assert_raises(ArgumentError) do
sg.data_residency(region: nil)
sg.sendgrid_data_residency(region: nil)
end
end

def test_with_global_invalid_residency
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
assert_raises(ArgumentError) do
sg.data_residency(region: "abc")
sg.sendgrid_data_residency(region: "abc")
end
end

def test_with_global_empty_residency
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
assert_raises(ArgumentError) do
sg.data_residency(region: "")
sg.sendgrid_data_residency(region: "")
end
end

def test_host_with_both_host_and_region_in_constructor
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'], host: "https://example.com", region: "eu")
def test_with_global_eu_residency
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
sg.sendgrid_data_residency(region: '')
assert_equal @eu_email, sg.host
end

end

0 comments on commit 82be96b

Please sign in to comment.