-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Twilio Integration and More update notification (#1719)
* Twilio Gateway * Enable Twilio test account for Travis * Pass twilio settings into tox env * Pass all the tests * 100% test coverage * Remove unnecessary lines of code * Currently removed TWILIO_PHONE_NUMBER from settings, add that later once we have phone numbers, remove unnecessary settings from default settings * Remove comments * Make tests pass * Make tests pass, remove TwilioGateway logger, move FakeGateway logger to settings/default.py * Send email/sms regardless of phone/email('s) verification status * Add changes addressed to PR * Rebasing and changes
- Loading branch information
1 parent
0b94377
commit 3a50a2a
Showing
18 changed files
with
342 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import random | ||
import logging | ||
|
||
from django.conf import settings | ||
from twilio.rest import Client, TwilioException | ||
|
||
fake_logger = logging.getLogger(name='accounts.FakeGateway') | ||
|
||
|
||
class TwilioGateway(object): | ||
|
||
def __init__(self, | ||
account_sid=settings.TWILIO_ACCOUNT_SID, | ||
auth_token=settings.TWILIO_AUTH_TOKEN, | ||
from_phone_number_list=[]): | ||
|
||
self.client = Client(account_sid, auth_token) | ||
self.from_phone_number_list = from_phone_number_list | ||
|
||
def send_sms(self, to, body): | ||
try: | ||
# create and send a message with client | ||
message = self.client.messages.create( | ||
to=to, | ||
from_=random.choice(self.from_phone_number_list), | ||
body=body) | ||
|
||
except TwilioException as e: | ||
message = e | ||
|
||
return message | ||
|
||
|
||
class FakeGateway(object): | ||
|
||
def send_sms(self, to, body): | ||
fake_logger.debug("Message sent to: {phone}. Message: {body}".format( | ||
phone=to, body=body)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,3 +15,37 @@ | |
unverified_identifier = _( | ||
"You have not verified your phone or email. We request you to verify" | ||
" your registered phone or email in order to access your account.") | ||
|
||
# send an sms to the user's phone(if any) notifying the removal of email | ||
email_delete = _( | ||
"You are receiving this message because a user at Cadasta Platform removed" | ||
" the email address from the account linked to this phone number." | ||
" If it wasn't you, please contact us immediately at [email protected]") | ||
|
||
# send an sms to the user's phone(if any) notifying the change in email | ||
email_change = _( | ||
"You are receiving this message because a user at Cadasta Platform updated" | ||
" the email address for the account linked to this phone" | ||
" number." | ||
" If it wasn't you, please contact us immediately at [email protected]") | ||
|
||
# send an sms to the user's old phone(if any) notifying the removal of phone | ||
phone_delete = _( | ||
"You are receiving this message because a user at Cadasta Platform removed" | ||
" the phone number from the account previously linked to this" | ||
" phone number." | ||
" If it wasn't you, please contact us immediately at [email protected]") | ||
|
||
# send an sms to the user's old phone(if any) notifying the change in phone | ||
phone_change = _( | ||
"You are receiving this message because a user at Cadasta Platform changed" | ||
" the phone number for the account previously linked to this" | ||
" phone number." | ||
" If it wasn't you, please contact us immediately at [email protected]") | ||
|
||
# send an sms to the user's phone notifying the change in password | ||
password_change_or_reset = _( | ||
"You are receiving this message because a user at Cadasta Platform has" | ||
" changed or reset the password for your account linked to this phone" | ||
" number." | ||
" If it wasn't you, please contact us immediately at [email protected]") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -509,9 +509,10 @@ def test_update_user(self): | |
assert user.email_verified is True | ||
assert user.phone == '+919327768250' | ||
assert user.phone_verified is True | ||
assert len(mail.outbox) == 2 | ||
assert len(mail.outbox) == 3 | ||
assert '[email protected]' in mail.outbox[0].to | ||
assert '[email protected]' in mail.outbox[1].to | ||
assert '[email protected]' in mail.outbox[2].to | ||
|
||
def test_display_name(self): | ||
user = UserFactory.create(username='imagine71', | ||
|
@@ -725,6 +726,8 @@ def test_update_phone_only(self): | |
assert user.phone_verified is True | ||
assert VerificationDevice.objects.filter( | ||
unverified_phone='+919327768250').exists() is False | ||
assert len(mail.outbox) == 1 | ||
assert '[email protected]' in mail.outbox[0].to | ||
|
||
def test_update_email_only(self): | ||
user = UserFactory.create(username='sherlock', | ||
|
@@ -764,6 +767,7 @@ def test_update_email_only(self): | |
assert '[email protected]' in mail.outbox[1].to | ||
assert EmailAddress.objects.filter( | ||
email="[email protected]").exists() is False | ||
# sms must be sent about email change to phone '+919327768250' | ||
|
||
def test_update_with_duplicate_phone(self): | ||
UserFactory.create(phone='+12345678990') | ||
|
@@ -814,6 +818,8 @@ def test_update_add_phone(self): | |
assert user.phone == '+919327768250' | ||
assert user.phone_verified is False | ||
assert VerificationDevice.objects.count() == 1 | ||
assert len(mail.outbox) == 1 | ||
assert '[email protected]' in mail.outbox[0].to | ||
|
||
def test_update_add_email(self): | ||
user = UserFactory.create(username='sherlock', | ||
|
@@ -929,6 +935,8 @@ def test_update_remove_phone(self): | |
assert not user.phone | ||
assert user.phone_verified is False | ||
assert VerificationDevice.objects.count() == 0 | ||
assert len(mail.outbox) == 1 | ||
assert '[email protected]' in mail.outbox[0].to | ||
|
||
def test_update_remove_email(self): | ||
user = UserFactory.create(username='sherlock', | ||
|
@@ -957,6 +965,8 @@ def test_update_remove_email(self): | |
assert not user.email | ||
assert user.email_verified is False | ||
assert EmailAddress.objects.count() == 0 | ||
assert len(mail.outbox) == 1 | ||
assert '[email protected]' in mail.outbox[0].to | ||
|
||
def test_update_add_phone_and_remove_email(self): | ||
user = UserFactory.create(username='sherlock', | ||
|
@@ -988,6 +998,8 @@ def test_update_add_phone_and_remove_email(self): | |
assert user.email_verified is False | ||
assert EmailAddress.objects.count() == 0 | ||
assert VerificationDevice.objects.count() == 1 | ||
assert len(mail.outbox) == 1 | ||
assert '[email protected]' in mail.outbox[0].to | ||
|
||
def test_update_add_email_and_remove_phone(self): | ||
user = UserFactory.create(username='sherlock', | ||
|
@@ -1027,6 +1039,9 @@ def test_update_add_email_and_remove_phone(self): | |
assert user.email_verified is False | ||
assert EmailAddress.objects.count() == 1 | ||
assert VerificationDevice.objects.count() == 0 | ||
assert len(mail.outbox) == 2 | ||
assert '[email protected]' in mail.outbox[0].to | ||
assert '[email protected]' in mail.outbox[0].to | ||
|
||
def test_update_phone_and_remove_email(self): | ||
user = UserFactory.create(username='sherlock', | ||
|
@@ -1062,6 +1077,10 @@ def test_update_phone_and_remove_email(self): | |
assert EmailAddress.objects.count() == 0 | ||
assert VerificationDevice.objects.filter( | ||
unverified_phone='+12345678990').exists() is False | ||
assert len(mail.outbox) == 1 | ||
assert '[email protected]' in mail.outbox[0].to | ||
# send sms to user's phone '+12345678990' about email removal | ||
# send sms to user's phone '+12345678990' about phone change | ||
|
||
def test_update_email_and_remove_phone(self): | ||
user = UserFactory.create(username='sherlock', | ||
|
@@ -1103,6 +1122,10 @@ def test_update_email_and_remove_phone(self): | |
assert EmailAddress.objects.filter( | ||
email='[email protected]').exists() is False | ||
assert VerificationDevice.objects.count() == 0 | ||
assert len(mail.outbox) == 3 | ||
assert '[email protected]' in mail.outbox[0].to | ||
assert '[email protected]' in mail.outbox[1].to | ||
assert '[email protected]' in mail.outbox[2].to | ||
|
||
def test_update_with_existing_email_in_EmailAddress(self): | ||
user = UserFactory.create() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
from django.test import TestCase | ||
from django.conf import settings | ||
from accounts.gateways import TwilioGateway, FakeGateway | ||
from django.test.utils import override_settings | ||
from unittest import mock | ||
|
||
|
||
class TwilioGatewayTest(TestCase): | ||
|
||
@override_settings( | ||
TWILIO_ACCOUNT_SID='SID', | ||
TWILIO_AUTH_TOKEN='TOKEN', | ||
TWILIO_PHONE_NUMBER_LIST=['+123']) | ||
@mock.patch('accounts.gateways.Client') | ||
def test_gateway(self, mock_client): | ||
twilio = TwilioGateway( | ||
account_sid=settings.TWILIO_ACCOUNT_SID, | ||
auth_token=settings.TWILIO_AUTH_TOKEN, | ||
from_phone_number_list=settings.TWILIO_PHONE_NUMBER_LIST | ||
) | ||
mock_client.assert_called_with('SID', 'TOKEN') | ||
body = 'Testing Twilio SMS gateway!' | ||
to = '+456' | ||
twilio.send_sms(to, body) | ||
mock_client.return_value.messages.create.assert_called_with( | ||
to=to, | ||
body=body, | ||
from_='+123') | ||
|
||
def test_message_sent_successfully(self): | ||
twiliobj = TwilioGateway( | ||
account_sid=settings.TWILIO_ACCOUNT_SID, | ||
auth_token=settings.TWILIO_AUTH_TOKEN, | ||
from_phone_number_list=['+15005550006', ] | ||
) | ||
to = '+919327768250' | ||
body = 'Test message send successfully' | ||
message = twiliobj.send_sms(to, body) | ||
assert message.status == 'queued' | ||
assert message.sid is not None | ||
|
||
def test_message_send_to_invalid_number(self): | ||
twiliobj = TwilioGateway( | ||
account_sid=settings.TWILIO_ACCOUNT_SID, | ||
auth_token=settings.TWILIO_AUTH_TOKEN, | ||
from_phone_number_list=['+15005550006', ] | ||
) | ||
to = '+15005550001' | ||
body = 'This is an invalid phone number!' | ||
message = twiliobj.send_sms(to, body) | ||
assert message.status == 400 | ||
|
||
|
||
class FakeGatewayTest(TestCase): | ||
@mock.patch('accounts.gateways.fake_logger') | ||
def test_gateway(self, mock_logger): | ||
fake_gateway = FakeGateway() | ||
to = '+456' | ||
body = 'Testing Fake SMS gateway!' | ||
fake_gateway.send_sms(to, body) | ||
mock_logger.debug.assert_called_with( | ||
"Message sent to: {phone}. Message: {body}".format( | ||
phone=to, body=body)) |
Oops, something went wrong.