test_api.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. from datetime import datetime, timedelta, timezone
  2. from sentry.models.authidentity import AuthIdentity
  3. from sentry.models.authprovider import AuthProvider
  4. from sentry.testutils.cases import AuthProviderTestCase
  5. from sentry.testutils.skips import requires_snuba
  6. from sentry.utils.auth import SSO_EXPIRY_TIME, SsoSession
  7. pytestmark = [requires_snuba]
  8. # TODO: move these into the tests/sentry/auth directory and remove deprecated logic
  9. class AuthenticationTest(AuthProviderTestCase):
  10. def setUp(self):
  11. self.organization = self.create_organization(name="foo")
  12. self.user = self.create_user("foobar@example.com", is_superuser=False)
  13. team = self.create_team(name="bar", organization=self.organization)
  14. self.project = self.create_project(name="baz", organization=self.organization, teams=[team])
  15. member = self.create_member(user=self.user, organization=self.organization, teams=[team])
  16. setattr(member.flags, "sso:linked", True)
  17. member.save()
  18. event = self.store_event(data={}, project_id=self.project.id)
  19. group_id = event.group_id
  20. auth_provider = AuthProvider.objects.create(
  21. organization_id=self.organization.id, provider="dummy", flags=0
  22. )
  23. AuthIdentity.objects.create(auth_provider=auth_provider, user=self.user)
  24. self.login_as(self.user)
  25. self.paths = (
  26. f"/api/0/organizations/{self.organization.slug}/",
  27. f"/api/0/projects/{self.organization.slug}/{self.project.slug}/",
  28. f"/api/0/teams/{self.organization.slug}/{self.team.slug}/",
  29. f"/api/0/issues/{group_id}/",
  30. # this uses the internal API, which once upon a time was broken
  31. f"/api/0/issues/{group_id}/events/latest/",
  32. )
  33. def test_sso_auth_required(self):
  34. # we should be redirecting the user to the authentication form as they
  35. # haven't verified this specific organization
  36. self._test_paths_with_status(401)
  37. def test_sso_superuser_required(self):
  38. # superuser should still require SSO as they're a member of the org
  39. self.user.update(is_superuser=True)
  40. self._test_paths_with_status(401)
  41. def test_sso_with_expiry_valid(self):
  42. sso_session = SsoSession.create(self.organization.id)
  43. self.session[sso_session.session_key] = sso_session.to_dict()
  44. self.save_session()
  45. self._test_paths_with_status(200)
  46. def test_sso_with_expiry_expired(self):
  47. sso_session_expired = SsoSession(
  48. self.organization.id,
  49. datetime.now(tz=timezone.utc) - SSO_EXPIRY_TIME - timedelta(hours=1),
  50. )
  51. self.session[sso_session_expired.session_key] = sso_session_expired.to_dict()
  52. self.save_session()
  53. self._test_paths_with_status(401)
  54. def test_sso_redirect_url_internal(self):
  55. sso_session_expired = SsoSession(
  56. self.organization.id,
  57. datetime.now(tz=timezone.utc) - SSO_EXPIRY_TIME - timedelta(hours=1),
  58. )
  59. self.session[sso_session_expired.session_key] = sso_session_expired.to_dict()
  60. self.save_session()
  61. resp = self.client.get(
  62. f"/api/0/teams/{self.organization.slug}/{self.team.slug}/",
  63. HTTP_REFERER=f"/organizations/{self.organization.slug}/teams",
  64. )
  65. assert (
  66. resp.json()["detail"]["extra"]["loginUrl"]
  67. == "/auth/login/foo/?next=%2Forganizations%2Ffoo%2Fteams"
  68. )
  69. def test_sso_redirect_url_internal_with_domain(self):
  70. sso_session_expired = SsoSession(
  71. self.organization.id,
  72. datetime.now(tz=timezone.utc) - SSO_EXPIRY_TIME - timedelta(hours=1),
  73. )
  74. self.session[sso_session_expired.session_key] = sso_session_expired.to_dict()
  75. self.save_session()
  76. resp = self.client.get(
  77. f"/api/0/teams/{self.organization.slug}/{self.team.slug}/",
  78. HTTP_REFERER=f"https://testdomain.com/organizations/{self.organization.slug}/teams",
  79. SERVER_NAME="testdomain.com",
  80. )
  81. assert (
  82. resp.json()["detail"]["extra"]["loginUrl"]
  83. == "/auth/login/foo/?next=https%3A%2F%2Ftestdomain.com%2Forganizations%2Ffoo%2Fteams"
  84. )
  85. def test_sso_redirect_url_external_removed(self):
  86. sso_session_expired = SsoSession(
  87. self.organization.id,
  88. datetime.now(tz=timezone.utc) - SSO_EXPIRY_TIME - timedelta(hours=1),
  89. )
  90. self.session[sso_session_expired.session_key] = sso_session_expired.to_dict()
  91. self.save_session()
  92. resp = self.client.get(
  93. f"/api/0/teams/{self.organization.slug}/{self.team.slug}/",
  94. HTTP_REFERER="http://example.com",
  95. )
  96. assert resp.json()["detail"]["extra"]["loginUrl"] == "/auth/login/foo/"
  97. def _test_paths_with_status(self, status):
  98. for path in self.paths:
  99. resp = self.client.get(path)
  100. assert resp.status_code == status, (resp.status_code, resp.content)