test_organization_users.py 14 KB

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