addressed first review comments and fixed tests
This commit is contained in:
Родитель
aa21d76723
Коммит
9f1e5469eb
|
@ -38,6 +38,7 @@ TWILIO_SMS_APPLICATION_SID=
|
|||
TWILIO_MESSAGING_SERVICE_SID=
|
||||
TWILIO_MAIN_NUMBER=
|
||||
IQ_ENABLED=False
|
||||
IQ_FOR_NEW_NUMBERS=False
|
||||
IQ_OUTBOUND_API_KEY=""
|
||||
IQ_INBOUND_API_KEY=""
|
||||
PERIODICAL_PREMIUM_PROD_ID=prod_KGizMiBqUJdYoY
|
||||
|
|
|
@ -9,6 +9,7 @@ from twilio.rest import Client
|
|||
from django.conf import settings
|
||||
|
||||
from rest_framework.test import RequestsClient
|
||||
from api.views.phones import compute_iq_mac
|
||||
|
||||
from phones.tests.models_tests import make_phone_test_user
|
||||
from api.tests.phones_views_tests import _make_real_phone, _make_relay_number
|
||||
|
@ -77,21 +78,18 @@ def test_iq_endpoint_invalid_hash():
|
|||
|
||||
def test_iq_endpoint_valid_hash_no_auth_failed_status():
|
||||
message_id = "9a09df23-01f3-4e0f-adbc-2a783878a574"
|
||||
combined = settings.IQ_INBOUND_API_KEY + message_id
|
||||
token = hashlib.sha256(combined.encode()).hexdigest()
|
||||
token = compute_iq_mac(message_id)
|
||||
client = RequestsClient()
|
||||
client.headers.update({"Verificationtoken": token})
|
||||
client.headers.update({"MessageId": message_id})
|
||||
response = client.post(INBOUND_SMS_PATH)
|
||||
|
||||
assert response.status_code != 401
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def _prepare_valid_iq_request_client() -> RequestsClient:
|
||||
message_id = "9a09df23-01f3-4e0f-adbc-2a783878a574"
|
||||
combined = settings.IQ_INBOUND_API_KEY + message_id
|
||||
token = hashlib.sha256(combined.encode()).hexdigest()
|
||||
token = compute_iq_mac(message_id)
|
||||
client = RequestsClient()
|
||||
client.headers.update({"Verificationtoken": token})
|
||||
client.headers.update({"MessageId": message_id})
|
||||
|
|
38
api/urls.py
38
api/urls.py
|
@ -68,19 +68,20 @@ urlpatterns = [
|
|||
),
|
||||
]
|
||||
|
||||
if settings.PHONES_ENABLED:
|
||||
from .views.phones import (
|
||||
RealPhoneViewSet,
|
||||
RelayNumberViewSet,
|
||||
InboundContactViewSet,
|
||||
inbound_call,
|
||||
inbound_sms,
|
||||
vCard,
|
||||
sms_status,
|
||||
voice_status,
|
||||
resend_welcome_sms,
|
||||
)
|
||||
from .views.phones import (
|
||||
RealPhoneViewSet,
|
||||
RelayNumberViewSet,
|
||||
InboundContactViewSet,
|
||||
inbound_call,
|
||||
inbound_sms,
|
||||
inbound_sms_iq,
|
||||
vCard,
|
||||
sms_status,
|
||||
voice_status,
|
||||
resend_welcome_sms,
|
||||
)
|
||||
|
||||
if settings.PHONES_ENABLED:
|
||||
api_router.register(r"realphone", RealPhoneViewSet, "real_phone")
|
||||
api_router.register(r"relaynumber", RelayNumberViewSet, "relay_number")
|
||||
api_router.register(r"inboundcontact", InboundContactViewSet, "inbound_contact")
|
||||
|
@ -131,12 +132,13 @@ if settings.PHONES_ENABLED:
|
|||
]
|
||||
|
||||
|
||||
if settings.PHONES_ENABLED and settings.IQ_ENABLED:
|
||||
from .views.phones import inbound_sms_iq
|
||||
|
||||
urlpatterns += [
|
||||
path("v1/inbound_sms_iq/", inbound_sms_iq, name="inbound_sms"),
|
||||
]
|
||||
urlpatterns += [
|
||||
path(
|
||||
"v1/inbound_sms_iq/",
|
||||
enable_if_setting("IQ_ENABLED")(inbound_sms_iq),
|
||||
name="inbound_sms",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
urlpatterns += [
|
||||
|
|
|
@ -476,6 +476,10 @@ def _try_delete_from_twilio(message):
|
|||
raise e
|
||||
|
||||
|
||||
def message_body(from_num, body):
|
||||
return f"[Relay 📲 {from_num}] {body}"
|
||||
|
||||
|
||||
@decorators.api_view(["POST"])
|
||||
@decorators.permission_classes([permissions.AllowAny])
|
||||
@decorators.renderer_classes([TemplateTwiMLRenderer])
|
||||
|
@ -538,9 +542,10 @@ def inbound_sms(request):
|
|||
client = twilio_client()
|
||||
app = twiml_app()
|
||||
incr_if_enabled("phones_outbound_sms")
|
||||
body = message_body(inbound_from, inbound_body)
|
||||
client.messages.create(
|
||||
from_=relay_number.number,
|
||||
body=f"[Relay 📲 {inbound_from}] {inbound_body}",
|
||||
body=body,
|
||||
status_callback=app.sms_status_callback,
|
||||
to=real_phone.number,
|
||||
)
|
||||
|
@ -591,7 +596,7 @@ def inbound_sms_iq(request: Request) -> response.Response:
|
|||
_check_and_update_contact(inbound_contact, "texts", relay_number)
|
||||
|
||||
iq_formatted_real_num = real_phone.number.replace("+", "")
|
||||
text = f"[Relay 📲 {inbound_from}] {inbound_body}"
|
||||
text = message_body(inbound_from, inbound_body)
|
||||
json_body = {"from": relay_num, "to": [iq_formatted_real_num], "text": text}
|
||||
resp = requests.post(
|
||||
"https://messagebroker.inteliquent.com/msgbroker/rest/publishMessages",
|
||||
|
@ -1106,21 +1111,25 @@ def _validate_twilio_request(request):
|
|||
raise exceptions.ValidationError("Invalid request: invalid signature")
|
||||
|
||||
|
||||
def _validate_iq_request(request):
|
||||
def compute_iq_mac(message_id: str) -> str:
|
||||
iq_api_key = settings.IQ_INBOUND_API_KEY
|
||||
# FIXME: switch to proper hmac when iQ is ready
|
||||
# mac = hmac.new(iq_api_key.encode(), msg=message_id.encode(), digestmod=hashlib.sha256)
|
||||
combined = iq_api_key + message_id
|
||||
return hashlib.sha256(combined.encode()).hexdigest()
|
||||
|
||||
|
||||
def _validate_iq_request(request: Request) -> None:
|
||||
if "Verificationtoken" not in request._request.headers:
|
||||
raise exceptions.AuthenticationFailed("missing Verificationtoken header.")
|
||||
|
||||
if "MessageId" not in request._request.headers:
|
||||
raise exceptions.AuthenticationFailed("missing MessageId header.")
|
||||
|
||||
iq_api_key = settings.IQ_INBOUND_API_KEY
|
||||
message_id = request._request.headers["Messageid"]
|
||||
mac = compute_iq_mac(message_id)
|
||||
|
||||
token = request._request.headers["verificationToken"]
|
||||
|
||||
# FIXME: switch to proper hmac when iQ is ready
|
||||
# mac = hmac.new(iq_api_key.encode(), msg=message_id.encode(), digestmod=hashlib.sha256)
|
||||
combined = iq_api_key + message_id
|
||||
mac = hashlib.sha256(combined.encode())
|
||||
|
||||
if mac.hexdigest() != token:
|
||||
if mac != token:
|
||||
raise exceptions.AuthenticationFailed("verficiationToken != computed sha256")
|
||||
|
|
Загрузка…
Ссылка в новой задаче