test_msisdn.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # Copyright 2021 The Matrix.org Foundation C.I.C.
  2. # Licensed under the Apache License, Version 2.0 (the "License");
  3. # you may not use this file except in compliance with the License.
  4. # You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software
  9. # distributed under the License is distributed on an "AS IS" BASIS,
  10. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. # See the License for the specific language governing permissions and
  12. # limitations under the License.
  13. import asyncio
  14. import os.path
  15. from typing import Awaitable
  16. from unittest.mock import MagicMock, patch
  17. import attr
  18. from twisted.trial import unittest
  19. from twisted.web.server import Request
  20. from tests.utils import make_request, make_sydent
  21. @attr.s(auto_attribs=True)
  22. class FakeHeader:
  23. """
  24. A fake header object
  25. """
  26. headers: dict
  27. def getAllRawHeaders(self):
  28. return self.headers
  29. @attr.s(auto_attribs=True)
  30. class FakeResponse:
  31. """A fake twisted.web.IResponse object"""
  32. # HTTP response code
  33. code: int
  34. # Fake Header
  35. headers: FakeHeader
  36. class TestRequestCode(unittest.TestCase):
  37. def setUp(self) -> None:
  38. # Create a new sydent
  39. config = {
  40. "general": {
  41. "templates.path": os.path.join(
  42. os.path.dirname(os.path.dirname(__file__)), "res"
  43. ),
  44. },
  45. }
  46. self.sydent = make_sydent(test_config=config)
  47. def _render_request(self, request: Request) -> Awaitable[MagicMock]:
  48. # Patch out the email sending so we can investigate the resulting email.
  49. with patch("sydent.sms.openmarket.OpenMarketSMS.sendTextSMS") as sendTextSMS:
  50. # We can't use AsyncMock until Python 3.8. Instead, mock the
  51. # function as returning a future.
  52. f = asyncio.Future()
  53. f.set_result(MagicMock())
  54. sendTextSMS.return_value = f
  55. request.render(self.sydent.servlets.msisdnRequestCode)
  56. return sendTextSMS
  57. def test_request_code(self) -> None:
  58. self.sydent.run()
  59. request, channel = make_request(
  60. self.sydent.reactor,
  61. "POST",
  62. "/_matrix/identity/api/v1/validate/msisdn/requestToken",
  63. {
  64. "phone_number": "447700900750",
  65. "country": "GB",
  66. "client_secret": "oursecret",
  67. "send_attempt": 0,
  68. },
  69. )
  70. sendSMS_mock = self._render_request(request)
  71. sendSMS_mock.assert_called_once()
  72. self.assertEqual(channel.code, 200)
  73. def test_request_code_via_url_query_params(self) -> None:
  74. self.sydent.run()
  75. url = (
  76. "/_matrix/identity/api/v1/validate/msisdn/requestToken?"
  77. "phone_number=447700900750"
  78. "&country=GB"
  79. "&client_secret=oursecret"
  80. "&send_attempt=0"
  81. )
  82. request, channel = make_request(self.sydent.reactor, "POST", url)
  83. sendSMS_mock = self._render_request(request)
  84. sendSMS_mock.assert_called_once()
  85. self.assertEqual(channel.code, 200)
  86. @patch("sydent.http.httpclient.HTTPClient.post_json_maybe_get_json")
  87. def test_bad_api_response_raises_exception(self, post_json: MagicMock) -> None:
  88. """Test that an error response from OpenMarket raises an exception
  89. and that the requester receives an error code."""
  90. header = FakeHeader({})
  91. resp = FakeResponse(code=400, headers=header), {}
  92. post_json.return_value = resp
  93. self.sydent.run()
  94. request, channel = make_request(
  95. self.sydent.reactor,
  96. "POST",
  97. "/_matrix/identity/api/v1/validate/msisdn/requestToken",
  98. {
  99. "phone_number": "447700900750",
  100. "country": "GB",
  101. "client_secret": "oursecret",
  102. "send_attempt": 0,
  103. },
  104. )
  105. request.render(self.sydent.servlets.msisdnRequestCode)
  106. self.assertEqual(channel.code, 500)