test_api.py 4.8 KB

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