test_organization_users.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. import json
  2. from django.core import mail
  3. from django.shortcuts import reverse
  4. from django.test import override_settings
  5. from rest_framework.test import APITestCase
  6. from model_bakery import baker
  7. from glitchtip import test_utils # pylint: disable=unused-import
  8. from ..models import OrganizationUserRole, OrganizationUser
  9. class OrganizationUsersAPITestCase(APITestCase):
  10. def setUp(self):
  11. self.user = baker.make("users.user")
  12. self.organization = baker.make("organizations_ext.Organization")
  13. self.org_user = self.organization.add_user(
  14. self.user, role=OrganizationUserRole.MANAGER
  15. )
  16. self.client.force_login(self.user)
  17. self.users_url = reverse(
  18. "organization-users-list",
  19. kwargs={"organization_slug": self.organization.slug},
  20. )
  21. self.members_url = reverse(
  22. "organization-members-list",
  23. kwargs={"organization_slug": self.organization.slug},
  24. )
  25. def test_organization_users_list(self):
  26. res = self.client.get(self.users_url)
  27. self.assertContains(res, self.user.email)
  28. res = self.client.get(self.members_url)
  29. self.assertContains(res, self.user.email)
  30. def test_organization_members_email_field(self):
  31. """
  32. Org Member email should refer to the invited email before acceptance
  33. After acceptance, it should refer to the user's primary email address
  34. """
  35. url = reverse(
  36. "organization-members-detail",
  37. kwargs={
  38. "organization_slug": self.organization.slug,
  39. "pk": self.org_user.pk,
  40. },
  41. )
  42. res = self.client.get(url)
  43. self.assertEqual(res.data["email"], self.user.email)
  44. def test_organization_team_members_list(self):
  45. team = baker.make("teams.Team", organization=self.organization)
  46. url = reverse(
  47. "team-members-list",
  48. kwargs={"team_pk": f"{self.organization.slug}/{team.slug}"},
  49. )
  50. res = self.client.get(url)
  51. self.assertNotContains(res, self.user.email)
  52. team.members.add(self.org_user)
  53. res = self.client.get(url)
  54. self.assertContains(res, self.user.email)
  55. def test_organization_users_detail(self):
  56. other_user = baker.make("users.user")
  57. other_organization = baker.make("organizations_ext.Organization")
  58. other_org_user = other_organization.add_user(other_user)
  59. team = baker.make("teams.Team", organization=self.organization)
  60. team.members.add(self.org_user)
  61. url = reverse(
  62. "organization-members-detail",
  63. kwargs={
  64. "organization_slug": self.organization.slug,
  65. "pk": self.org_user.pk,
  66. },
  67. )
  68. res = self.client.get(url)
  69. self.assertContains(res, self.user.email)
  70. self.assertContains(res, team.slug)
  71. self.assertNotContains(res, other_user.email)
  72. url = reverse(
  73. "organization-members-detail",
  74. kwargs={"organization_slug": self.organization.slug, "pk": "me"},
  75. )
  76. res = self.client.get(url)
  77. self.assertContains(res, self.user.email)
  78. self.assertNotContains(res, other_user.email)
  79. url = reverse(
  80. "organization-members-detail",
  81. kwargs={
  82. "organization_slug": other_organization.slug,
  83. "pk": other_org_user.pk,
  84. },
  85. )
  86. res = self.client.get(url)
  87. self.assertEqual(res.status_code, 404)
  88. def test_organization_users_add_team_member(self):
  89. team = baker.make("teams.Team", organization=self.organization)
  90. url = (
  91. reverse(
  92. "organization-members-detail",
  93. kwargs={
  94. "organization_slug": self.organization.slug,
  95. "pk": self.org_user.pk,
  96. },
  97. )
  98. + f"teams/{team.slug}/"
  99. )
  100. self.assertEqual(team.members.count(), 0)
  101. res = self.client.post(url)
  102. self.assertEqual(res.status_code, 201)
  103. self.assertEqual(team.members.count(), 1)
  104. res = self.client.delete(url)
  105. self.assertEqual(res.status_code, 200)
  106. self.assertEqual(team.members.count(), 0)
  107. def test_organization_users_add_self_team_member(self):
  108. team = baker.make("teams.Team", organization=self.organization)
  109. url = (
  110. reverse(
  111. "organization-members-detail",
  112. kwargs={
  113. "organization_slug": self.organization.slug,
  114. "pk": "me",
  115. },
  116. )
  117. + f"teams/{team.slug}/"
  118. )
  119. self.assertEqual(team.members.count(), 0)
  120. res = self.client.post(url)
  121. self.assertEqual(res.status_code, 201)
  122. self.assertEqual(team.members.count(), 1)
  123. res = self.client.delete(url)
  124. self.assertEqual(res.status_code, 200)
  125. self.assertEqual(team.members.count(), 0)
  126. def test_organization_users_create_and_accept_invite(self):
  127. data = {
  128. "email": "new@example.com",
  129. "role": OrganizationUserRole.MANAGER.label.lower(),
  130. "teams": [],
  131. "user": "new@example.com",
  132. }
  133. res = self.client.post(self.members_url, data)
  134. self.assertTrue(res.data["pending"])
  135. body = mail.outbox[0].body
  136. body_split = body[body.find("http://localhost:8000/accept/") :].split("/")
  137. org_user_id = body_split[4]
  138. token = body_split[5]
  139. url = reverse(
  140. "accept-invite", kwargs={"org_user_id": org_user_id, "token": token}
  141. )
  142. # Check that we can determine organization name from GET request to accept invite endpoint
  143. self.client.logout()
  144. res = self.client.get(url)
  145. self.assertContains(res, self.organization.name)
  146. user = baker.make("users.user")
  147. self.client.force_login(user)
  148. data = {"accept_invite": True}
  149. res = self.client.post(url, data)
  150. self.assertContains(res, self.organization.name)
  151. self.assertFalse(res.data["org_user"]["pending"])
  152. self.assertTrue(
  153. OrganizationUser.objects.filter(
  154. user=user, organization=self.organization
  155. ).exists()
  156. )
  157. def test_closed_user_registration(self):
  158. data = {
  159. "email": "new@example.com",
  160. "role": OrganizationUserRole.MANAGER.label.lower(),
  161. "teams": [],
  162. "user": "new@example.com",
  163. }
  164. with override_settings(ENABLE_USER_REGISTRATION=False):
  165. # Non-existing user cannot be invited
  166. res = self.client.post(self.members_url, data)
  167. self.assertEqual(res.status_code, 403)
  168. # Existing user can be invited
  169. self.user = baker.make("users.user", email="new@example.com")
  170. res = self.client.post(self.members_url, data)
  171. self.assertEqual(res.status_code, 201)
  172. def test_organization_users_invite_twice(self):
  173. """Don't allow inviting user who is already in the group"""
  174. data = {
  175. "email": "new@example.com",
  176. "role": OrganizationUserRole.MANAGER.label.lower(),
  177. "teams": [],
  178. "user": "new@example.com",
  179. }
  180. res = self.client.post(self.members_url, data)
  181. self.assertEqual(res.status_code, 201)
  182. res = self.client.post(self.members_url, data)
  183. self.assertEqual(res.status_code, 409)
  184. data["email"] = self.user.email
  185. res = self.client.post(self.members_url, data)
  186. self.assertEqual(res.status_code, 409)
  187. def test_organization_users_add_team_member_permission(self):
  188. self.org_user.role = OrganizationUserRole.MEMBER
  189. self.org_user.save()
  190. team = baker.make("teams.Team", organization=self.organization)
  191. url = (
  192. reverse(
  193. "organization-members-detail",
  194. kwargs={
  195. "organization_slug": self.organization.slug,
  196. "pk": self.org_user.pk,
  197. },
  198. )
  199. + f"teams/{team.slug}/"
  200. )
  201. # Add self with open membership
  202. res = self.client.post(url)
  203. self.assertEqual(res.status_code, 201)
  204. res = self.client.delete(url)
  205. # Can't add self without open membership
  206. self.organization.open_membership = False
  207. self.organization.save()
  208. res = self.client.post(url)
  209. self.assertEqual(res.status_code, 403)
  210. self.organization.open_membership = True
  211. self.organization.save()
  212. # Can't add someone else with open membership when not admin
  213. other_user = baker.make("users.User")
  214. other_org_user = self.organization.add_user(other_user)
  215. other_org_user_url = (
  216. reverse(
  217. "organization-members-detail",
  218. kwargs={
  219. "organization_slug": self.organization.slug,
  220. "pk": other_org_user.pk,
  221. },
  222. )
  223. + f"teams/{team.slug}/"
  224. )
  225. res = self.client.post(other_org_user_url)
  226. self.assertEqual(res.status_code, 403)
  227. # Can't add someone when admin and not in team
  228. self.org_user.role = OrganizationUserRole.ADMIN
  229. self.org_user.save()
  230. res = self.client.post(other_org_user_url)
  231. self.assertEqual(res.status_code, 403)
  232. # Can add someone when admin and in team
  233. team.members.add(self.org_user)
  234. res = self.client.post(other_org_user_url)
  235. self.assertEqual(res.status_code, 201)
  236. team.members.remove(self.org_user)
  237. team.members.remove(other_org_user)
  238. # Can add someone else when manager
  239. self.org_user.role = OrganizationUserRole.MANAGER
  240. self.org_user.save()
  241. res = self.client.post(other_org_user_url)
  242. self.assertEqual(res.status_code, 201)
  243. def test_organization_users_create(self):
  244. team = baker.make("teams.Team", organization=self.organization)
  245. data = {
  246. "email": "new@example.com",
  247. "role": OrganizationUserRole.MANAGER.label.lower(),
  248. "teams": [team.slug],
  249. "user": "new@example.com",
  250. }
  251. res = self.client.post(
  252. self.members_url, json.dumps(data), content_type="application/json"
  253. )
  254. self.assertContains(res, data["email"], status_code=201)
  255. self.assertEqual(res.data["role"], "manager")
  256. self.assertTrue(
  257. OrganizationUser.objects.filter(
  258. organization=self.organization,
  259. email=data["email"],
  260. user=None,
  261. role=OrganizationUserRole.MANAGER,
  262. ).exists()
  263. )
  264. self.assertTrue(team.members.exists())
  265. self.assertEqual(len(mail.outbox), 1)
  266. def test_organization_users_create_and_accept(self):
  267. data = {
  268. "email": "new@example.com",
  269. "role": OrganizationUserRole.MANAGER.label.lower(),
  270. "teams": [],
  271. "user": "new@example.com",
  272. }
  273. self.client.post(self.members_url, data)
  274. body = mail.outbox[0].body
  275. token = body[body.find("http://localhost:8000/accept/") :].split("/")[4]
  276. def test_organization_users_create_without_permissions(self):
  277. """Admin cannot add users to org"""
  278. self.org_user.role = OrganizationUserRole.ADMIN
  279. self.org_user.save()
  280. data = {
  281. "email": "new@example.com",
  282. "role": OrganizationUserRole.MANAGER.label.lower(),
  283. "teams": [],
  284. "user": "new@example.com",
  285. }
  286. res = self.client.post(self.members_url, data)
  287. self.assertEquals(res.status_code, 403)
  288. def test_organization_users_reinvite(self):
  289. other_user = baker.make("users.user")
  290. other_org_user = baker.make(
  291. "organizations_ext.OrganizationUser",
  292. email=other_user.email,
  293. organization=self.organization,
  294. )
  295. url = reverse(
  296. "organization-members-detail",
  297. kwargs={
  298. "organization_slug": self.organization.slug,
  299. "pk": other_org_user.pk,
  300. },
  301. )
  302. data = {"reinvite": 1}
  303. res = self.client.put(url, data)
  304. self.assertContains(res, other_user.email)
  305. self.assertTrue(len(mail.outbox))
  306. def test_organization_users_update(self):
  307. other_user = baker.make("users.user")
  308. other_org_user = self.organization.add_user(other_user)
  309. url = reverse(
  310. "organization-members-detail",
  311. kwargs={
  312. "organization_slug": self.organization.slug,
  313. "pk": other_org_user.pk,
  314. },
  315. )
  316. new_role = OrganizationUserRole.ADMIN
  317. data = {"role": new_role.label.lower(), "teams": []}
  318. res = self.client.put(url, data)
  319. self.assertContains(res, other_user.email)
  320. self.assertTrue(
  321. OrganizationUser.objects.filter(
  322. organization=self.organization, role=new_role, user=other_user
  323. ).exists()
  324. )
  325. def test_organization_users_update_without_permissions(self):
  326. self.org_user.role = OrganizationUserRole.ADMIN
  327. self.org_user.save()
  328. other_user = baker.make("users.user")
  329. other_org_user = self.organization.add_user(other_user)
  330. url = reverse(
  331. "organization-members-detail",
  332. kwargs={
  333. "organization_slug": self.organization.slug,
  334. "pk": other_org_user.pk,
  335. },
  336. )
  337. new_role = OrganizationUserRole.ADMIN
  338. data = {"role": new_role.label.lower(), "teams": []}
  339. res = self.client.put(url, data)
  340. self.assertEqual(res.status_code, 403)
  341. def test_organization_users_delete(self):
  342. other_user = baker.make("users.user")
  343. other_org_user = self.organization.add_user(other_user)
  344. url = reverse(
  345. "organization-members-detail",
  346. kwargs={
  347. "organization_slug": self.organization.slug,
  348. "pk": other_org_user.pk,
  349. },
  350. )
  351. res = self.client.delete(url)
  352. self.assertEqual(res.status_code, 204)
  353. self.assertEqual(other_user.organizations_ext_organizationuser.count(), 0)
  354. def test_organization_users_delete_without_permissions(self):
  355. self.org_user.role = OrganizationUserRole.ADMIN
  356. self.org_user.save()
  357. other_user = baker.make("users.user")
  358. other_org_user = self.organization.add_user(other_user)
  359. url = reverse(
  360. "organization-members-detail",
  361. kwargs={
  362. "organization_slug": self.organization.slug,
  363. "pk": other_org_user.pk,
  364. },
  365. )
  366. res = self.client.delete(url)
  367. self.assertEqual(res.status_code, 403)
  368. self.assertEqual(other_user.organizations_ext_organizationuser.count(), 1)