test_get_user_data.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. from unittest.mock import Mock, patch
  2. import pytest
  3. from requests.exceptions import Timeout
  4. from ...conf.test import override_dynamic_settings
  5. from .. import exceptions
  6. from ..client import REQUESTS_TIMEOUT, get_user_data
  7. ACCESS_TOKEN = "acc3ss-t0k3n"
  8. @pytest.fixture
  9. def mock_request(dynamic_settings):
  10. return Mock(settings=dynamic_settings)
  11. @override_dynamic_settings(
  12. oauth2_user_url="https://example.com/oauth2/user",
  13. oauth2_user_method="GET",
  14. oauth2_user_token_name="atoken",
  15. oauth2_user_token_location="QUERY",
  16. oauth2_json_id_path="id",
  17. oauth2_json_name_path="name",
  18. oauth2_json_email_path="email",
  19. oauth2_json_avatar_path="avatar",
  20. )
  21. def test_user_data_is_returned_using_get_request_with_token_in_query_string(
  22. mock_request,
  23. ):
  24. user_data = {
  25. "id": "7dds8a7dd89sa",
  26. "name": "Aerith",
  27. "email": "aerith@example.com",
  28. "avatar": "https://example.com/avatar.png",
  29. }
  30. get_mock = Mock(
  31. return_value=Mock(
  32. status_code=200,
  33. json=Mock(
  34. return_value=user_data,
  35. ),
  36. ),
  37. )
  38. with patch("requests.get", get_mock):
  39. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  40. get_mock.assert_called_once_with(
  41. f"https://example.com/oauth2/user?atoken={ACCESS_TOKEN}",
  42. headers={},
  43. timeout=REQUESTS_TIMEOUT,
  44. )
  45. @override_dynamic_settings(
  46. oauth2_user_url="https://example.com/oauth2/user",
  47. oauth2_user_method="GET",
  48. oauth2_user_token_name="Authentication",
  49. oauth2_user_token_location="HEADER",
  50. oauth2_json_id_path="id",
  51. oauth2_json_name_path="name",
  52. oauth2_json_email_path="email",
  53. oauth2_json_avatar_path="avatar",
  54. )
  55. def test_user_data_is_returned_using_get_request_with_token_in_header(mock_request):
  56. user_data = {
  57. "id": "7dds8a7dd89sa",
  58. "name": "Aerith",
  59. "email": "aerith@example.com",
  60. "avatar": "https://example.com/avatar.png",
  61. }
  62. get_mock = Mock(
  63. return_value=Mock(
  64. status_code=200,
  65. json=Mock(
  66. return_value=user_data,
  67. ),
  68. ),
  69. )
  70. with patch("requests.get", get_mock):
  71. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  72. get_mock.assert_called_once_with(
  73. f"https://example.com/oauth2/user",
  74. headers={"Authentication": ACCESS_TOKEN},
  75. timeout=REQUESTS_TIMEOUT,
  76. )
  77. @override_dynamic_settings(
  78. oauth2_user_url="https://example.com/oauth2/user",
  79. oauth2_user_method="GET",
  80. oauth2_user_token_name="Authentication",
  81. oauth2_user_token_location="HEADER_BEARER",
  82. oauth2_json_id_path="id",
  83. oauth2_json_name_path="name",
  84. oauth2_json_email_path="email",
  85. oauth2_json_avatar_path="avatar",
  86. )
  87. def test_user_data_is_returned_using_get_request_with_bearer_token_in_header(
  88. mock_request,
  89. ):
  90. user_data = {
  91. "id": "7dds8a7dd89sa",
  92. "name": "Aerith",
  93. "email": "aerith@example.com",
  94. "avatar": "https://example.com/avatar.png",
  95. }
  96. get_mock = Mock(
  97. return_value=Mock(
  98. status_code=200,
  99. json=Mock(
  100. return_value=user_data,
  101. ),
  102. ),
  103. )
  104. with patch("requests.get", get_mock):
  105. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  106. get_mock.assert_called_once_with(
  107. f"https://example.com/oauth2/user",
  108. headers={"Authentication": f"Bearer {ACCESS_TOKEN}"},
  109. timeout=REQUESTS_TIMEOUT,
  110. )
  111. @override_dynamic_settings(
  112. oauth2_user_url="https://example.com/oauth2/user",
  113. oauth2_user_method="POST",
  114. oauth2_user_token_name="atoken",
  115. oauth2_user_token_location="QUERY",
  116. oauth2_json_id_path="id",
  117. oauth2_json_name_path="name",
  118. oauth2_json_email_path="email",
  119. oauth2_json_avatar_path="avatar",
  120. )
  121. def test_user_data_is_returned_using_post_request_with_token_in_query_string(
  122. mock_request,
  123. ):
  124. user_data = {
  125. "id": "7dds8a7dd89sa",
  126. "name": "Aerith",
  127. "email": "aerith@example.com",
  128. "avatar": "https://example.com/avatar.png",
  129. }
  130. post_mock = Mock(
  131. return_value=Mock(
  132. status_code=200,
  133. json=Mock(
  134. return_value=user_data,
  135. ),
  136. ),
  137. )
  138. with patch("requests.post", post_mock):
  139. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  140. post_mock.assert_called_once_with(
  141. f"https://example.com/oauth2/user?atoken={ACCESS_TOKEN}",
  142. headers={},
  143. timeout=REQUESTS_TIMEOUT,
  144. )
  145. @override_dynamic_settings(
  146. oauth2_user_url="https://example.com/oauth2/user",
  147. oauth2_user_method="POST",
  148. oauth2_user_token_name="Authentication",
  149. oauth2_user_token_location="HEADER",
  150. oauth2_json_id_path="id",
  151. oauth2_json_name_path="name",
  152. oauth2_json_email_path="email",
  153. oauth2_json_avatar_path="avatar",
  154. )
  155. def test_user_data_is_returned_using_post_request_with_token_in_header(mock_request):
  156. user_data = {
  157. "id": "7dds8a7dd89sa",
  158. "name": "Aerith",
  159. "email": "aerith@example.com",
  160. "avatar": "https://example.com/avatar.png",
  161. }
  162. post_mock = Mock(
  163. return_value=Mock(
  164. status_code=200,
  165. json=Mock(
  166. return_value=user_data,
  167. ),
  168. ),
  169. )
  170. with patch("requests.post", post_mock):
  171. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  172. post_mock.assert_called_once_with(
  173. f"https://example.com/oauth2/user",
  174. headers={"Authentication": ACCESS_TOKEN},
  175. timeout=REQUESTS_TIMEOUT,
  176. )
  177. @override_dynamic_settings(
  178. oauth2_user_url="https://example.com/oauth2/user",
  179. oauth2_user_method="POST",
  180. oauth2_user_token_name="Authentication",
  181. oauth2_user_token_location="HEADER_BEARER",
  182. oauth2_json_id_path="id",
  183. oauth2_json_name_path="name",
  184. oauth2_json_email_path="email",
  185. oauth2_json_avatar_path="avatar",
  186. )
  187. def test_user_data_is_returned_using_post_request_with_bearer_token_in_header(
  188. mock_request,
  189. ):
  190. user_data = {
  191. "id": "7dds8a7dd89sa",
  192. "name": "Aerith",
  193. "email": "aerith@example.com",
  194. "avatar": "https://example.com/avatar.png",
  195. }
  196. post_mock = Mock(
  197. return_value=Mock(
  198. status_code=200,
  199. json=Mock(
  200. return_value=user_data,
  201. ),
  202. ),
  203. )
  204. with patch("requests.post", post_mock):
  205. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  206. post_mock.assert_called_once_with(
  207. f"https://example.com/oauth2/user",
  208. headers={"Authentication": f"Bearer {ACCESS_TOKEN}"},
  209. timeout=REQUESTS_TIMEOUT,
  210. )
  211. @override_dynamic_settings(
  212. oauth2_user_url="https://example.com/oauth2/user",
  213. oauth2_user_method="POST",
  214. oauth2_user_token_name="Authentication",
  215. oauth2_user_token_location="HEADER_BEARER",
  216. oauth2_user_extra_headers="Accept: application/json\nApi-Ver:1234",
  217. oauth2_json_id_path="id",
  218. oauth2_json_name_path="name",
  219. oauth2_json_email_path="email",
  220. oauth2_json_avatar_path="avatar",
  221. )
  222. def test_user_data_is_returned_using_post_request_with_extra_headers(
  223. mock_request,
  224. ):
  225. user_data = {
  226. "id": "7dds8a7dd89sa",
  227. "name": "Aerith",
  228. "email": "aerith@example.com",
  229. "avatar": "https://example.com/avatar.png",
  230. }
  231. post_mock = Mock(
  232. return_value=Mock(
  233. status_code=200,
  234. json=Mock(
  235. return_value=user_data,
  236. ),
  237. ),
  238. )
  239. with patch("requests.post", post_mock):
  240. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  241. post_mock.assert_called_once_with(
  242. f"https://example.com/oauth2/user",
  243. headers={
  244. "Authentication": f"Bearer {ACCESS_TOKEN}",
  245. "Accept": "application/json",
  246. "Api-Ver": "1234",
  247. },
  248. timeout=REQUESTS_TIMEOUT,
  249. )
  250. @override_dynamic_settings(
  251. oauth2_user_url="https://example.com/oauth2/data?type=user",
  252. oauth2_user_method="GET",
  253. oauth2_user_token_name="atoken",
  254. oauth2_user_token_location="QUERY",
  255. oauth2_json_id_path="id",
  256. oauth2_json_name_path="name",
  257. oauth2_json_email_path="email",
  258. oauth2_json_avatar_path="avatar",
  259. )
  260. def test_user_data_request_with_token_in_url_respects_existing_querystring(
  261. mock_request,
  262. ):
  263. user_data = {
  264. "id": "7dds8a7dd89sa",
  265. "name": "Aerith",
  266. "email": "aerith@example.com",
  267. "avatar": "https://example.com/avatar.png",
  268. }
  269. get_mock = Mock(
  270. return_value=Mock(
  271. status_code=200,
  272. json=Mock(
  273. return_value=user_data,
  274. ),
  275. ),
  276. )
  277. with patch("requests.get", get_mock):
  278. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  279. get_mock.assert_called_once_with(
  280. f"https://example.com/oauth2/data?type=user&atoken={ACCESS_TOKEN}",
  281. headers={},
  282. timeout=REQUESTS_TIMEOUT,
  283. )
  284. @override_dynamic_settings(
  285. oauth2_user_url="https://example.com/oauth2/data?type=user",
  286. oauth2_user_method="GET",
  287. oauth2_user_token_name="atoken",
  288. oauth2_user_token_location="QUERY",
  289. oauth2_json_id_path="id",
  290. oauth2_json_name_path="user.profile.name",
  291. oauth2_json_email_path="user.profile.email",
  292. oauth2_json_avatar_path="user.profile.avatar",
  293. )
  294. def test_user_data_json_values_are_mapped_to_result(mock_request):
  295. user_data = {
  296. "id": "7dds8a7dd89sa",
  297. "name": "Aerith",
  298. "email": "aerith@example.com",
  299. "avatar": "https://example.com/avatar.png",
  300. }
  301. get_mock = Mock(
  302. return_value=Mock(
  303. status_code=200,
  304. json=Mock(
  305. return_value={
  306. "id": user_data["id"],
  307. "user": {
  308. "profile": {
  309. "name": user_data["name"],
  310. "email": user_data["email"],
  311. "avatar": user_data["avatar"],
  312. }
  313. },
  314. },
  315. ),
  316. ),
  317. )
  318. with patch("requests.get", get_mock):
  319. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  320. get_mock.assert_called_once_with(
  321. f"https://example.com/oauth2/data?type=user&atoken={ACCESS_TOKEN}",
  322. headers={},
  323. timeout=REQUESTS_TIMEOUT,
  324. )
  325. @override_dynamic_settings(
  326. oauth2_user_url="https://example.com/oauth2/data?type=user",
  327. oauth2_user_method="GET",
  328. oauth2_user_token_name="atoken",
  329. oauth2_user_token_location="QUERY",
  330. oauth2_json_id_path="id",
  331. oauth2_json_name_path="user.profile.name",
  332. oauth2_json_email_path="user.profile.email",
  333. oauth2_json_avatar_path="user.profile.avatar",
  334. )
  335. def test_user_data_json_values_are_none_when_not_found(mock_request):
  336. user_data = {
  337. "id": "7dds8a7dd89sa",
  338. "name": "Aerith",
  339. "email": "aerith@example.com",
  340. "avatar": "https://example.com/avatar.png",
  341. }
  342. get_mock = Mock(
  343. return_value=Mock(
  344. status_code=200,
  345. json=Mock(
  346. return_value={
  347. "profile_id": user_data["id"],
  348. "user": {
  349. "data": {
  350. "name": user_data["name"],
  351. "email": user_data["email"],
  352. "avatar": user_data["avatar"],
  353. }
  354. },
  355. },
  356. ),
  357. ),
  358. )
  359. with patch("requests.get", get_mock):
  360. assert get_user_data(mock_request, ACCESS_TOKEN) == {
  361. "id": None,
  362. "name": None,
  363. "email": None,
  364. "avatar": None,
  365. }
  366. get_mock.assert_called_once_with(
  367. f"https://example.com/oauth2/data?type=user&atoken={ACCESS_TOKEN}",
  368. headers={},
  369. timeout=REQUESTS_TIMEOUT,
  370. )
  371. @override_dynamic_settings(
  372. oauth2_user_url="https://example.com/oauth2/data?type=user",
  373. oauth2_user_method="GET",
  374. oauth2_user_token_name="atoken",
  375. oauth2_user_token_location="QUERY",
  376. oauth2_json_id_path="id",
  377. oauth2_json_name_path="user.profile.name",
  378. oauth2_json_email_path="user.profile.email",
  379. oauth2_json_avatar_path="",
  380. )
  381. def test_user_data_skips_avatar_if_path_is_not_set(mock_request):
  382. user_data = {
  383. "id": "7dds8a7dd89sa",
  384. "name": "Aerith",
  385. "email": "aerith@example.com",
  386. "avatar": None,
  387. }
  388. get_mock = Mock(
  389. return_value=Mock(
  390. status_code=200,
  391. json=Mock(
  392. return_value={
  393. "id": user_data["id"],
  394. "user": {
  395. "profile": {
  396. "name": user_data["name"],
  397. "email": user_data["email"],
  398. "avatar": "https://example.com/avatar.png",
  399. }
  400. },
  401. },
  402. ),
  403. ),
  404. )
  405. with patch("requests.get", get_mock):
  406. assert get_user_data(mock_request, ACCESS_TOKEN) == user_data
  407. get_mock.assert_called_once_with(
  408. f"https://example.com/oauth2/data?type=user&atoken={ACCESS_TOKEN}",
  409. headers={},
  410. timeout=REQUESTS_TIMEOUT,
  411. )
  412. @override_dynamic_settings(
  413. oauth2_user_url="https://example.com/oauth2/data",
  414. oauth2_user_method="POST",
  415. oauth2_user_token_name="atoken",
  416. oauth2_user_token_location="QUERY",
  417. )
  418. def test_exception_is_raised_if_user_data_request_times_out(mock_request):
  419. post_mock = Mock(side_effect=Timeout())
  420. with patch("requests.post", post_mock):
  421. with pytest.raises(exceptions.OAuth2UserDataRequestError):
  422. get_user_data(mock_request, ACCESS_TOKEN)
  423. post_mock.assert_called_once()
  424. @override_dynamic_settings(
  425. oauth2_user_url="https://example.com/oauth2/data",
  426. oauth2_user_method="POST",
  427. oauth2_user_token_name="atoken",
  428. oauth2_user_token_location="QUERY",
  429. )
  430. def test_exception_is_raised_if_user_data_request_response_is_not_200(mock_request):
  431. post_mock = Mock(
  432. return_value=Mock(
  433. status_code=400,
  434. ),
  435. )
  436. with patch("requests.post", post_mock):
  437. with pytest.raises(exceptions.OAuth2UserDataResponseError):
  438. get_user_data(mock_request, ACCESS_TOKEN)
  439. post_mock.assert_called_once()
  440. @override_dynamic_settings(
  441. oauth2_user_url="https://example.com/oauth2/data",
  442. oauth2_user_method="POST",
  443. oauth2_user_token_name="atoken",
  444. oauth2_user_token_location="QUERY",
  445. )
  446. def test_exception_is_raised_if_user_data_request_response_is_not_json(mock_request):
  447. post_mock = Mock(
  448. return_value=Mock(
  449. status_code=200,
  450. json=Mock(
  451. side_effect=ValueError(),
  452. ),
  453. ),
  454. )
  455. with patch("requests.post", post_mock):
  456. with pytest.raises(exceptions.OAuth2UserDataJSONError):
  457. get_user_data(mock_request, ACCESS_TOKEN)
  458. post_mock.assert_called_once()
  459. @override_dynamic_settings(
  460. oauth2_user_url="https://example.com/oauth2/data",
  461. oauth2_user_method="POST",
  462. oauth2_user_token_name="atoken",
  463. oauth2_user_token_location="QUERY",
  464. )
  465. def test_exception_is_raised_if_user_data_request_response_json_is_not_object(
  466. mock_request,
  467. ):
  468. post_mock = Mock(
  469. return_value=Mock(
  470. status_code=200,
  471. json=Mock(
  472. return_value=["json", "list"],
  473. ),
  474. ),
  475. )
  476. with patch("requests.post", post_mock):
  477. with pytest.raises(exceptions.OAuth2UserDataJSONError):
  478. get_user_data(mock_request, ACCESS_TOKEN)
  479. post_mock.assert_called_once()