test_accept_organization_invite.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from django.db.models import F
  2. from django.test import override_settings
  3. from selenium.webdriver.common.by import By
  4. from sentry.models.authprovider import AuthProvider
  5. from sentry.models.organization import Organization
  6. from sentry.testutils.cases import AcceptanceTestCase
  7. from sentry.testutils.silo import no_silo_test
  8. # When we want to set this @region_silo_test, we'll need to configure regions in order for invites to work.
  9. # See the accept_organization_invite.py#get_invite_state logic
  10. @no_silo_test
  11. class AcceptOrganizationInviteTest(AcceptanceTestCase):
  12. def setUp(self):
  13. super().setUp()
  14. self.user = self.create_user("foo@example.com")
  15. self.org = self.create_organization(name="Rowdy Tiger", owner=None)
  16. self.team = self.create_team(organization=self.org, name="Mariachi Band")
  17. self.member = self.create_member(
  18. user=None,
  19. email="bar@example.com",
  20. organization=self.org,
  21. role="owner",
  22. teams=[self.team],
  23. )
  24. def _sign_in_user(self, email, password):
  25. """
  26. Helper method to sign in a user with given email and password.
  27. """
  28. self.browser.find_element(By.ID, "id_username").send_keys(email)
  29. self.browser.find_element(By.ID, "id_password").send_keys(password)
  30. self.browser.find_element(By.XPATH, "//button[contains(text(), 'Sign In')]").click()
  31. def test_invite_simple(self):
  32. self.login_as(self.user)
  33. self.browser.get(self.member.get_invite_link().split("/", 3)[-1])
  34. self.browser.wait_until('[data-test-id="accept-invite"]')
  35. assert self.browser.element_exists('[data-test-id="join-organization"]')
  36. def test_invite_not_authenticated(self):
  37. self.browser.get(self.member.get_invite_link().split("/", 3)[-1])
  38. self.browser.wait_until('[data-test-id="accept-invite"]')
  39. assert self.browser.element_exists('[data-test-id="create-account"]')
  40. def test_invite_2fa_enforced_org(self):
  41. self.org.update(flags=F("flags").bitor(Organization.flags.require_2fa))
  42. self.browser.get(self.member.get_invite_link().split("/", 3)[-1])
  43. self.browser.wait_until('[data-test-id="accept-invite"]')
  44. assert not self.browser.element_exists_by_test_id("2fa-warning")
  45. self.login_as(self.user)
  46. self.org.update(flags=F("flags").bitor(Organization.flags.require_2fa))
  47. self.browser.get(self.member.get_invite_link().split("/", 3)[-1])
  48. self.browser.wait_until('[data-test-id="accept-invite"]')
  49. assert self.browser.element_exists_by_test_id("2fa-warning")
  50. def test_invite_sso_org(self):
  51. AuthProvider.objects.create(organization_id=self.org.id, provider="google")
  52. self.browser.get(self.member.get_invite_link().split("/", 3)[-1])
  53. self.browser.wait_until('[data-test-id="accept-invite"]')
  54. assert self.browser.element_exists_by_test_id("action-info-sso")
  55. assert self.browser.element_exists('[data-test-id="sso-login"]')
  56. @override_settings(SENTRY_SINGLE_ORGANIZATION=True)
  57. def test_authenticated_user_already_member_of_an_org_accept_invite_other_org(self):
  58. """
  59. Test that an authenticated user already part of an organization can accept an invite to another organization.
  60. """
  61. # Setup: Create a second user and make them a member of an organization
  62. email = "dummy@example.com"
  63. password = "dummy"
  64. user2 = self.create_user(email=email)
  65. user2.set_password(password)
  66. user2.save()
  67. self.create_organization(name="Second Org", owner=user2)
  68. # Action: Invite User2 to the first organization
  69. new_member = self.create_member(
  70. user=None,
  71. email=user2.email,
  72. organization=self.org,
  73. role="owner",
  74. teams=[self.team],
  75. )
  76. self.login_as(user2)
  77. # Simulate the user accessing the invite link
  78. self.browser.get(new_member.get_invite_link().split("/", 3)[-1])
  79. self.browser.wait_until('[data-test-id="accept-invite"]')
  80. self.browser.click('button[data-test-id="join-organization"]')
  81. assert self.browser.wait_until('[aria-label="Create project"]')
  82. @override_settings(SENTRY_SINGLE_ORGANIZATION=True)
  83. def test_not_authenticated_user_already_member_of_an_org_accept_invite_other_org(self):
  84. """
  85. Test that a not authenticated user already part of an organization can accept an invite to another organization.
  86. """
  87. # Setup: Create a second user and make them a member of an organization
  88. email = "dummy@example.com"
  89. password = "dummy"
  90. user2 = self.create_user(email=email)
  91. user2.set_password(password)
  92. user2.save()
  93. self.create_organization(name="Second Org", owner=user2)
  94. # Action: Invite User2 to the first organization
  95. new_member = self.create_member(
  96. user=None,
  97. email=user2.email,
  98. organization=self.org,
  99. role="member",
  100. teams=[self.team],
  101. )
  102. # Simulate the user accessing the invite link
  103. self.browser.get(new_member.get_invite_link().split("/", 3)[-1])
  104. self.browser.wait_until('[data-test-id="accept-invite"]')
  105. # Choose to login with existing account
  106. self.browser.click('a[data-test-id="link-with-existing"]')
  107. self.browser.wait_until_not('[data-test-id="loading-indicator"]')
  108. # Handle form validation: Prevent default invalid event blocking
  109. self.browser.driver.execute_script(
  110. "document.addEventListener('invalid', function(e) { e.preventDefault(); }, true);"
  111. )
  112. # Login
  113. self._sign_in_user(email, password)
  114. self.browser.wait_until('[data-test-id="join-organization"]')
  115. # Display the acceptance view for the invitation to join a new organization
  116. assert self.browser.element_exists(f"[aria-label='Join the {self.org.slug} organization']")
  117. @override_settings(SENTRY_SINGLE_ORGANIZATION=True)
  118. def test_existing_user_invite_2fa_enforced_org(self):
  119. """
  120. Test that a user who has an existing Sentry account can accept an invite to another organization
  121. and is required to go through the 2FA configuration view.
  122. """
  123. self.org.update(flags=F("flags").bitor(Organization.flags.require_2fa))
  124. # Setup: Create a second user and make them a member of an organization
  125. email = "dummy@example.com"
  126. password = "dummy"
  127. user2 = self.create_user(email=email)
  128. user2.set_password(password)
  129. user2.save()
  130. self.create_organization(name="Second Org", owner=user2)
  131. # Action: Invite User2 to the first organization
  132. new_member = self.create_member(
  133. user=None,
  134. email=user2.email,
  135. organization=self.org,
  136. role="owner",
  137. teams=[self.team],
  138. )
  139. # Simulate the user accessing the invite link
  140. self.browser.get(new_member.get_invite_link().split("/", 3)[-1])
  141. self.browser.wait_until('[data-test-id="accept-invite"]')
  142. # Accept the invitation using the existing account
  143. self.browser.click('a[data-test-id="link-with-existing"]')
  144. self.browser.wait_until_not('[data-test-id="loading-indicator"]')
  145. # Handle form validation: Prevent default invalid event blocking
  146. self.browser.driver.execute_script(
  147. "document.addEventListener('invalid', function(e) { e.preventDefault(); }, true);"
  148. )
  149. # Login using existing credentials
  150. self._sign_in_user(email, password)
  151. self.browser.wait_until('[data-test-id="2fa-warning"]')
  152. # Display the 2FA configuration view
  153. assert self.browser.element_exists("[aria-label='Configure Two-Factor Auth']")