test_organization_users.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. import json
  2. from django.core import mail
  3. from django.test import override_settings
  4. from django.urls import reverse
  5. from model_bakery import baker
  6. from rest_framework.test import APITestCase
  7. from ..models import OrganizationUser, OrganizationUserRole
  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 get_org_member_detail_url(self, organization_slug, pk):
  25. return reverse(
  26. "organization-members-detail",
  27. kwargs={
  28. "organization_slug": organization_slug,
  29. "pk": pk,
  30. },
  31. )
  32. def test_organization_users_list(self):
  33. res = self.client.get(self.users_url)
  34. self.assertContains(res, self.user.email)
  35. res = self.client.get(self.members_url)
  36. self.assertContains(res, self.user.email)
  37. def test_organization_members_email_field(self):
  38. """
  39. Org Member email should refer to the invited email before acceptance
  40. After acceptance, it should refer to the user's primary email address
  41. """
  42. url = self.get_org_member_detail_url(self.organization.slug, self.org_user.pk)
  43. res = self.client.get(url)
  44. self.assertEqual(res.data["email"], self.user.email)
  45. def test_organization_team_members_list(self):
  46. team = baker.make("teams.Team", organization=self.organization)
  47. url = reverse(
  48. "team-members-list",
  49. kwargs={"team_pk": f"{self.organization.slug}/{team.slug}"},
  50. )
  51. res = self.client.get(url)
  52. self.assertNotContains(res, self.user.email)
  53. team.members.add(self.org_user)
  54. res = self.client.get(url)
  55. self.assertContains(res, self.user.email)
  56. def test_organization_users_detail(self):
  57. other_user = baker.make("users.user")
  58. other_organization = baker.make("organizations_ext.Organization")
  59. other_org_user = other_organization.add_user(other_user)
  60. team = baker.make("teams.Team", organization=self.organization)
  61. team.members.add(self.org_user)
  62. url = self.get_org_member_detail_url(self.organization.slug, self.org_user.pk)
  63. res = self.client.get(url)
  64. self.assertContains(res, self.user.email)
  65. self.assertContains(res, team.slug)
  66. self.assertNotContains(res, other_user.email)
  67. url = self.get_org_member_detail_url(self.organization.slug, "me")
  68. res = self.client.get(url)
  69. self.assertContains(res, self.user.email)
  70. self.assertNotContains(res, other_user.email)
  71. url = self.get_org_member_detail_url(self.organization.slug, other_org_user.pk)
  72. res = self.client.get(url)
  73. self.assertEqual(res.status_code, 404)
  74. def test_organization_users_add_team_member(self):
  75. team = baker.make("teams.Team", organization=self.organization)
  76. url = (
  77. self.get_org_member_detail_url(self.organization.slug, self.org_user.pk)
  78. + f"teams/{team.slug}/"
  79. )
  80. self.assertEqual(team.members.count(), 0)
  81. res = self.client.post(url)
  82. self.assertEqual(res.status_code, 201)
  83. self.assertEqual(team.members.count(), 1)
  84. res = self.client.delete(url)
  85. self.assertEqual(res.status_code, 200)
  86. self.assertEqual(team.members.count(), 0)
  87. def test_organization_users_add_self_team_member(self):
  88. team = baker.make("teams.Team", organization=self.organization)
  89. url = (
  90. self.get_org_member_detail_url(self.organization.slug, "me")
  91. + f"teams/{team.slug}/"
  92. )
  93. self.assertEqual(team.members.count(), 0)
  94. res = self.client.post(url)
  95. self.assertEqual(res.status_code, 201)
  96. self.assertEqual(team.members.count(), 1)
  97. res = self.client.delete(url)
  98. self.assertEqual(res.status_code, 200)
  99. self.assertEqual(team.members.count(), 0)
  100. def test_organization_users_create_and_accept_invite(self):
  101. data = {
  102. "email": "new@example.com",
  103. "role": OrganizationUserRole.MANAGER.label.lower(),
  104. "teams": [],
  105. "user": "new@example.com",
  106. }
  107. res = self.client.post(self.members_url, data)
  108. self.assertTrue(res.data["pending"])
  109. body = mail.outbox[0].body
  110. body_split = body[body.find("http://localhost:8000/accept/") :].split("/")
  111. org_user_id = body_split[4]
  112. token = body_split[5]
  113. url = reverse(
  114. "accept-invite", kwargs={"org_user_id": org_user_id, "token": token}
  115. )
  116. # Check that we can determine organization name from GET request to accept invite endpoint
  117. self.client.logout()
  118. res = self.client.get(url)
  119. self.assertContains(res, self.organization.name)
  120. user = baker.make("users.user")
  121. self.client.force_login(user)
  122. data = {"accept_invite": True}
  123. res = self.client.post(url, data)
  124. self.assertContains(res, self.organization.name)
  125. self.assertFalse(res.data["org_user"]["pending"])
  126. self.assertTrue(
  127. OrganizationUser.objects.filter(
  128. user=user, organization=self.organization
  129. ).exists()
  130. )
  131. def test_closed_user_registration(self):
  132. data = {
  133. "email": "new@example.com",
  134. "role": OrganizationUserRole.MANAGER.label.lower(),
  135. "teams": [],
  136. "user": "new@example.com",
  137. }
  138. with override_settings(ENABLE_USER_REGISTRATION=False):
  139. # Non-existing user cannot be invited
  140. res = self.client.post(self.members_url, data)
  141. self.assertEqual(res.status_code, 403)
  142. # Existing user can be invited
  143. self.user = baker.make("users.user", email="new@example.com")
  144. res = self.client.post(self.members_url, data)
  145. self.assertEqual(res.status_code, 201)
  146. def test_organization_users_invite_twice(self):
  147. """Don't allow inviting user who is already in the group"""
  148. data = {
  149. "email": "new@example.com",
  150. "role": OrganizationUserRole.MANAGER.label.lower(),
  151. "teams": [],
  152. "user": "new@example.com",
  153. }
  154. res = self.client.post(self.members_url, data)
  155. self.assertEqual(res.status_code, 201)
  156. res = self.client.post(self.members_url, data)
  157. self.assertEqual(res.status_code, 409)
  158. data["email"] = self.user.email
  159. res = self.client.post(self.members_url, data)
  160. self.assertEqual(res.status_code, 409)
  161. def test_organization_users_create(self):
  162. team = baker.make("teams.Team", organization=self.organization)
  163. data = {
  164. "email": "new@example.com",
  165. "role": OrganizationUserRole.MANAGER.label.lower(),
  166. "teams": [team.slug],
  167. "user": "new@example.com",
  168. }
  169. res = self.client.post(
  170. self.members_url, json.dumps(data), content_type="application/json"
  171. )
  172. self.assertContains(res, data["email"], status_code=201)
  173. self.assertEqual(res.data["role"], "manager")
  174. self.assertTrue(
  175. OrganizationUser.objects.filter(
  176. organization=self.organization,
  177. email=data["email"],
  178. user=None,
  179. role=OrganizationUserRole.MANAGER,
  180. ).exists()
  181. )
  182. self.assertTrue(team.members.exists())
  183. self.assertEqual(len(mail.outbox), 1)
  184. def test_organization_users_create_and_accept(self):
  185. data = {
  186. "email": "new@example.com",
  187. "role": OrganizationUserRole.MANAGER.label.lower(),
  188. "teams": [],
  189. "user": "new@example.com",
  190. }
  191. self.client.post(self.members_url, data)
  192. body = mail.outbox[0].body
  193. body[body.find("http://localhost:8000/accept/") :].split("/")[4]
  194. def test_organization_users_create_without_permissions(self):
  195. """Admin cannot add users to org"""
  196. self.org_user.role = OrganizationUserRole.ADMIN
  197. self.org_user.save()
  198. data = {
  199. "email": "new@example.com",
  200. "role": OrganizationUserRole.MANAGER.label.lower(),
  201. "teams": [],
  202. "user": "new@example.com",
  203. }
  204. res = self.client.post(self.members_url, data)
  205. self.assertEqual(res.status_code, 403)
  206. def test_organization_users_reinvite(self):
  207. other_user = baker.make("users.user")
  208. other_org_user = baker.make(
  209. "organizations_ext.OrganizationUser",
  210. email=other_user.email,
  211. organization=self.organization,
  212. )
  213. url = self.get_org_member_detail_url(self.organization.slug, other_org_user.pk)
  214. data = {"reinvite": 1}
  215. res = self.client.put(url, data)
  216. self.assertContains(res, other_user.email)
  217. self.assertTrue(len(mail.outbox))
  218. def test_organization_users_update(self):
  219. other_user = baker.make("users.user")
  220. other_org_user = self.organization.add_user(other_user)
  221. url = self.get_org_member_detail_url(self.organization.slug, other_org_user.pk)
  222. new_role = OrganizationUserRole.ADMIN
  223. data = {"role": new_role.label.lower(), "teams": []}
  224. res = self.client.put(url, data)
  225. self.assertContains(res, other_user.email)
  226. self.assertTrue(
  227. OrganizationUser.objects.filter(
  228. organization=self.organization, role=new_role, user=other_user
  229. ).exists()
  230. )
  231. def test_organization_users_update_without_permissions(self):
  232. self.org_user.role = OrganizationUserRole.ADMIN
  233. self.org_user.save()
  234. other_user = baker.make("users.user")
  235. other_org_user = self.organization.add_user(other_user)
  236. url = self.get_org_member_detail_url(self.organization.slug, other_org_user.pk)
  237. new_role = OrganizationUserRole.ADMIN
  238. data = {"role": new_role.label.lower(), "teams": []}
  239. res = self.client.put(url, data)
  240. self.assertEqual(res.status_code, 403)
  241. def test_organization_users_delete(self):
  242. other_user = baker.make("users.user")
  243. other_org_user = self.organization.add_user(other_user)
  244. url = self.get_org_member_detail_url(self.organization.slug, other_org_user.pk)
  245. res = self.client.delete(url)
  246. self.assertEqual(res.status_code, 204)
  247. self.assertEqual(other_user.organizations_ext_organizationuser.count(), 0)
  248. url = self.get_org_member_detail_url(self.organization.slug, self.org_user.pk)
  249. res = self.client.delete(url)
  250. self.assertEqual(
  251. res.status_code,
  252. 400,
  253. "Org owner should not be able to remove themselves from org",
  254. )
  255. third_user = baker.make("users.user")
  256. third_org_user = self.organization.add_user(third_user)
  257. change_ownership_url = (
  258. self.get_org_member_detail_url(self.organization.slug, third_org_user.pk)
  259. + "set_owner/"
  260. )
  261. self.client.post(change_ownership_url)
  262. res = self.client.delete(url)
  263. self.assertEqual(
  264. res.status_code,
  265. 204,
  266. "Can remove self after transferring ownership",
  267. )
  268. def test_organization_users_delete_without_permissions(self):
  269. self.org_user.role = OrganizationUserRole.ADMIN
  270. self.org_user.save()
  271. other_user = baker.make("users.user")
  272. other_org_user = self.organization.add_user(other_user)
  273. url = self.get_org_member_detail_url(self.organization.slug, other_org_user.pk)
  274. res = self.client.delete(url)
  275. self.assertEqual(res.status_code, 403)
  276. self.assertEqual(other_user.organizations_ext_organizationuser.count(), 1)
  277. def test_organization_members_set_owner(self):
  278. other_user = baker.make("users.user")
  279. other_org_user = self.organization.add_user(other_user)
  280. random_org_user = baker.make("organizations_ext.OrganizationUser")
  281. url = (
  282. self.get_org_member_detail_url(self.organization.slug, random_org_user.pk)
  283. + "set_owner/"
  284. )
  285. res = self.client.post(url)
  286. self.assertEqual(
  287. res.status_code, 404, "Don't set random unrelated users as owner"
  288. )
  289. url = (
  290. self.get_org_member_detail_url(self.organization.slug, other_org_user.pk)
  291. + "set_owner/"
  292. )
  293. res = self.client.post(url)
  294. self.assertTrue(
  295. res.data["isOwner"], "Current owner may set another org member as owner"
  296. )
  297. url = (
  298. self.get_org_member_detail_url(self.organization.slug, self.org_user.pk)
  299. + "set_owner/"
  300. )
  301. self.org_user.role = OrganizationUserRole.MANAGER
  302. self.org_user.save()
  303. res = self.client.post(url)
  304. self.assertEqual(
  305. res.status_code, 403, "Can't set self as owner with only manager role"
  306. )
  307. self.org_user.role = OrganizationUserRole.OWNER
  308. self.org_user.save()
  309. res = self.client.post(url)
  310. self.assertTrue(res.data["isOwner"], "Owner role may set org member as owner")
  311. self.assertEqual(self.organization.owners.count(), 1)