oncall-engine/engine/apps/api/tests/test_auth.py

307 lines
11 KiB
Python
Raw Permalink Normal View History

from unittest.mock import Mock, patch
import pytest
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponse
Google OAuth2 flow + fetch Google Calendar OOO events (#4067) # What this PR does The following is deployed under a feature flag. **How it works** 1. The user clicks on the "Connect using your Google account" button in the user profile settings modal 2. The UI makes a call to `GET /api/internal/v1/login/google-oauth2`. The backend has now been configured to add `apps.social_auth.backends.GoogleOAuth2` as a "`social_auth` backend". 3. The backend will respond w/ a URL which points to the Google OAuth2 consent screen. The frontend then proceeds by sending the user to this page. This URL includes the following query parameters (amongst others): - `redirect_uri` - this will send the user back to `/api/internal/v1/complete/google-oauth2` (ie. make another API call to the OnCall backend to finalize the Google OAuth2 flow) - `state` - this represents an `apps.auth_token.models.GoogleOAuth2Token` token. This allows us to identify the OnCall user once they've linked their Google account. 4. Once redirected back to `/api/internal/v1/complete/google-oauth2`, this will complete the OAuth2 flow. At this point, the backend has access to several pieces of information about the Google user, including their `access_token` and `refresh_token`. We persist these (encrypted) for future use to fetch the user's out-of-office calendar events 5. The response from the API call in 4 above ☝️ is HTTP 302 (redirect) to `/a/grafana-oncall-app/users/me` (ie. open the user profile settings modal). At this point the user will see that their account has been connected and they can further configure the settings ![image](https://github.com/grafana/oncall/assets/9406895/c7673055-8485-4f9a-98df-b4f7347229ce) ## Which issue(s) this PR closes Closes https://github.com/grafana/oncall-private/issues/2584 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - will be done in https://github.com/grafana/oncall-private/issues/2591 - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. - will be done in https://github.com/grafana/oncall-private/issues/2591 --------- Co-authored-by: Dominik <dominik.broj@grafana.com> Co-authored-by: Maxim Mordasov <maxim.mordasov@grafana.com>
2024-04-02 14:59:03 -04:00
from django.test.utils import override_settings
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
from apps.auth_token.constants import MATTERMOST_AUTH_TOKEN_NAME, SLACK_AUTH_TOKEN_NAME
from apps.social_auth.backends import MATTERMOST_LOGIN_BACKEND, SLACK_INSTALLATION_BACKEND
from common.constants.plugin_ids import PluginID
from common.constants.slack_auth import SLACK_OAUTH_ACCESS_RESPONSE
GRAFANA_URL = "http://example.com"
@pytest.mark.django_db
@pytest.mark.parametrize(
"backend_name,expected_url",
(
("slack-login", f"{GRAFANA_URL}/a/{PluginID.ONCALL}/users/me"),
(SLACK_INSTALLATION_BACKEND, f"{GRAFANA_URL}/a/{PluginID.ONCALL}/chat-ops"),
),
)
def test_complete_slack_auth_redirect_ok(
make_organization,
make_user_for_organization,
make_slack_token_for_user,
backend_name,
expected_url,
):
organization = make_organization(grafana_url=GRAFANA_URL)
admin = make_user_for_organization(organization)
_, slack_token = make_slack_token_for_user(admin)
client = APIClient()
url = (
Google OAuth2 flow + fetch Google Calendar OOO events (#4067) # What this PR does The following is deployed under a feature flag. **How it works** 1. The user clicks on the "Connect using your Google account" button in the user profile settings modal 2. The UI makes a call to `GET /api/internal/v1/login/google-oauth2`. The backend has now been configured to add `apps.social_auth.backends.GoogleOAuth2` as a "`social_auth` backend". 3. The backend will respond w/ a URL which points to the Google OAuth2 consent screen. The frontend then proceeds by sending the user to this page. This URL includes the following query parameters (amongst others): - `redirect_uri` - this will send the user back to `/api/internal/v1/complete/google-oauth2` (ie. make another API call to the OnCall backend to finalize the Google OAuth2 flow) - `state` - this represents an `apps.auth_token.models.GoogleOAuth2Token` token. This allows us to identify the OnCall user once they've linked their Google account. 4. Once redirected back to `/api/internal/v1/complete/google-oauth2`, this will complete the OAuth2 flow. At this point, the backend has access to several pieces of information about the Google user, including their `access_token` and `refresh_token`. We persist these (encrypted) for future use to fetch the user's out-of-office calendar events 5. The response from the API call in 4 above ☝️ is HTTP 302 (redirect) to `/a/grafana-oncall-app/users/me` (ie. open the user profile settings modal). At this point the user will see that their account has been connected and they can further configure the settings ![image](https://github.com/grafana/oncall/assets/9406895/c7673055-8485-4f9a-98df-b4f7347229ce) ## Which issue(s) this PR closes Closes https://github.com/grafana/oncall-private/issues/2584 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - will be done in https://github.com/grafana/oncall-private/issues/2591 - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. - will be done in https://github.com/grafana/oncall-private/issues/2591 --------- Co-authored-by: Dominik <dominik.broj@grafana.com> Co-authored-by: Maxim Mordasov <maxim.mordasov@grafana.com>
2024-04-02 14:59:03 -04:00
reverse("api-internal:complete-social-auth", kwargs={"backend": backend_name})
+ f"?{SLACK_AUTH_TOKEN_NAME}={slack_token}"
)
with patch("apps.api.views.auth.do_complete") as mock_do_complete:
mock_do_complete.return_value = None
response = client.get(url)
assert response.status_code == status.HTTP_302_FOUND
assert response.url == expected_url
@pytest.mark.django_db
def test_complete_slack_auth_redirect_error(
make_organization,
make_user_for_organization,
make_slack_token_for_user,
):
organization = make_organization()
admin = make_user_for_organization(organization)
_, slack_token = make_slack_token_for_user(admin)
client = APIClient()
url = (
Google OAuth2 flow + fetch Google Calendar OOO events (#4067) # What this PR does The following is deployed under a feature flag. **How it works** 1. The user clicks on the "Connect using your Google account" button in the user profile settings modal 2. The UI makes a call to `GET /api/internal/v1/login/google-oauth2`. The backend has now been configured to add `apps.social_auth.backends.GoogleOAuth2` as a "`social_auth` backend". 3. The backend will respond w/ a URL which points to the Google OAuth2 consent screen. The frontend then proceeds by sending the user to this page. This URL includes the following query parameters (amongst others): - `redirect_uri` - this will send the user back to `/api/internal/v1/complete/google-oauth2` (ie. make another API call to the OnCall backend to finalize the Google OAuth2 flow) - `state` - this represents an `apps.auth_token.models.GoogleOAuth2Token` token. This allows us to identify the OnCall user once they've linked their Google account. 4. Once redirected back to `/api/internal/v1/complete/google-oauth2`, this will complete the OAuth2 flow. At this point, the backend has access to several pieces of information about the Google user, including their `access_token` and `refresh_token`. We persist these (encrypted) for future use to fetch the user's out-of-office calendar events 5. The response from the API call in 4 above ☝️ is HTTP 302 (redirect) to `/a/grafana-oncall-app/users/me` (ie. open the user profile settings modal). At this point the user will see that their account has been connected and they can further configure the settings ![image](https://github.com/grafana/oncall/assets/9406895/c7673055-8485-4f9a-98df-b4f7347229ce) ## Which issue(s) this PR closes Closes https://github.com/grafana/oncall-private/issues/2584 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - will be done in https://github.com/grafana/oncall-private/issues/2591 - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. - will be done in https://github.com/grafana/oncall-private/issues/2591 --------- Co-authored-by: Dominik <dominik.broj@grafana.com> Co-authored-by: Maxim Mordasov <maxim.mordasov@grafana.com>
2024-04-02 14:59:03 -04:00
reverse("api-internal:complete-social-auth", kwargs={"backend": "slack-login"})
+ f"?{SLACK_AUTH_TOKEN_NAME}={slack_token}"
)
def _custom_do_complete(backend, *args, **kwargs):
backend.strategy.session[REDIRECT_FIELD_NAME] = "some-url"
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
with patch("apps.api.views.auth.do_complete", side_effect=_custom_do_complete):
response = client.get(url)
assert response.status_code == status.HTTP_302_FOUND
assert response.url == "some-url"
Google OAuth2 flow + fetch Google Calendar OOO events (#4067) # What this PR does The following is deployed under a feature flag. **How it works** 1. The user clicks on the "Connect using your Google account" button in the user profile settings modal 2. The UI makes a call to `GET /api/internal/v1/login/google-oauth2`. The backend has now been configured to add `apps.social_auth.backends.GoogleOAuth2` as a "`social_auth` backend". 3. The backend will respond w/ a URL which points to the Google OAuth2 consent screen. The frontend then proceeds by sending the user to this page. This URL includes the following query parameters (amongst others): - `redirect_uri` - this will send the user back to `/api/internal/v1/complete/google-oauth2` (ie. make another API call to the OnCall backend to finalize the Google OAuth2 flow) - `state` - this represents an `apps.auth_token.models.GoogleOAuth2Token` token. This allows us to identify the OnCall user once they've linked their Google account. 4. Once redirected back to `/api/internal/v1/complete/google-oauth2`, this will complete the OAuth2 flow. At this point, the backend has access to several pieces of information about the Google user, including their `access_token` and `refresh_token`. We persist these (encrypted) for future use to fetch the user's out-of-office calendar events 5. The response from the API call in 4 above ☝️ is HTTP 302 (redirect) to `/a/grafana-oncall-app/users/me` (ie. open the user profile settings modal). At this point the user will see that their account has been connected and they can further configure the settings ![image](https://github.com/grafana/oncall/assets/9406895/c7673055-8485-4f9a-98df-b4f7347229ce) ## Which issue(s) this PR closes Closes https://github.com/grafana/oncall-private/issues/2584 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - will be done in https://github.com/grafana/oncall-private/issues/2591 - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. - will be done in https://github.com/grafana/oncall-private/issues/2591 --------- Co-authored-by: Dominik <dominik.broj@grafana.com> Co-authored-by: Maxim Mordasov <maxim.mordasov@grafana.com>
2024-04-02 14:59:03 -04:00
@override_settings(UNIFIED_SLACK_APP_ENABLED=False)
@pytest.mark.django_db
def test_start_slack_ok(
make_organization_and_user_with_plugin_token,
make_user_auth_headers,
):
"""
Covers the case when user starts Slack integration installation via Grafana OnCall
"""
_, user, token = make_organization_and_user_with_plugin_token()
client = APIClient()
url = reverse("api-internal:social-auth", kwargs={"backend": SLACK_INSTALLATION_BACKEND})
mock_do_auth_return = Mock()
mock_do_auth_return.url = "https://slack_oauth_redirect.com"
with patch("apps.api.views.auth.do_auth", return_value=mock_do_auth_return) as mock_do_auth:
response = client.get(url, **make_user_auth_headers(user, token))
assert mock_do_auth.called
assert response.status_code == status.HTTP_200_OK
assert response.json() == "https://slack_oauth_redirect.com"
@pytest.mark.django_db
@pytest.mark.parametrize(
"backend_name,expected_url",
((MATTERMOST_LOGIN_BACKEND, "a/grafana-oncall-app/users/me"),),
)
def test_complete_mattermost_auth_redirect_ok(
make_organization,
make_user_for_organization,
make_mattermost_token_for_user,
backend_name,
expected_url,
):
organization = make_organization()
admin = make_user_for_organization(organization)
_, mattermost_token = make_mattermost_token_for_user(admin)
client = APIClient()
url = (
reverse("api-internal:complete-social-auth", kwargs={"backend": backend_name})
+ f"?{MATTERMOST_AUTH_TOKEN_NAME}={mattermost_token}"
)
with patch("apps.api.views.auth.do_complete") as mock_do_complete:
mock_do_complete.return_value = None
response = client.get(url)
assert response.status_code == status.HTTP_302_FOUND
assert response.url == expected_url
@pytest.mark.django_db
def test_complete_mattermost_auth_redirect_error(
make_organization,
make_user_for_organization,
make_mattermost_token_for_user,
):
organization = make_organization()
admin = make_user_for_organization(organization)
_, mattermost_token = make_mattermost_token_for_user(admin)
client = APIClient()
url = (
reverse("api-internal:complete-social-auth", kwargs={"backend": MATTERMOST_LOGIN_BACKEND})
+ f"?{MATTERMOST_AUTH_TOKEN_NAME}={mattermost_token}"
)
def _custom_do_complete(backend, *args, **kwargs):
backend.strategy.session[REDIRECT_FIELD_NAME] = "some-url"
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
with patch("apps.api.views.auth.do_complete", side_effect=_custom_do_complete):
response = client.get(url)
assert response.status_code == status.HTTP_302_FOUND
assert response.url == "some-url"
@pytest.mark.django_db
def test_start_mattermost_ok(
make_organization_and_user_with_plugin_token,
make_user_auth_headers,
):
"""
Covers the case when user starts Mattermost integration installation via Grafana OnCall
"""
_, user, token = make_organization_and_user_with_plugin_token()
client = APIClient()
url = reverse("api-internal:social-auth", kwargs={"backend": MATTERMOST_LOGIN_BACKEND})
mock_do_auth_return = Mock()
mock_do_auth_return.url = "https://mattermost_oauth_redirect.com"
with patch("apps.api.views.auth.do_auth", return_value=mock_do_auth_return) as mock_do_auth:
response = client.get(url, **make_user_auth_headers(user, token))
assert mock_do_auth.called
assert response.status_code == status.HTTP_200_OK
assert response.json() == "https://mattermost_oauth_redirect.com"
@override_settings(UNIFIED_SLACK_APP_ENABLED=True)
@pytest.mark.django_db
def test_start_unified_slack_ok(
make_organization_and_user_with_plugin_token,
make_user_auth_headers,
):
"""
Covers the case when user starts Unified Slack integration installation
"""
_, user, token = make_organization_and_user_with_plugin_token()
client = APIClient()
url = reverse("api-internal:social-auth", kwargs={"backend": SLACK_INSTALLATION_BACKEND})
with patch(
"apps.api.views.auth.get_installation_link_from_chatops_proxy", return_value="https://slack_oauth_redirect.com"
):
response = client.get(url, **make_user_auth_headers(user, token))
assert response.status_code == status.HTTP_200_OK
assert response.json() == "https://slack_oauth_redirect.com"
@override_settings(UNIFIED_SLACK_APP_ENABLED=True)
@patch("apps.api.views.auth.get_installation_link_from_chatops_proxy", return_value=None)
@patch("apps.api.views.auth.get_slack_oauth_response_from_chatops_proxy", return_value=SLACK_OAUTH_ACCESS_RESPONSE)
@patch("apps.api.views.auth.install_slack_integration", return_value=None)
@pytest.mark.django_db
def test_start_slack_ok_via_chatops_proxy_when_already_installed(
mock_install_slack_integration,
mock_get_slack_oauth_response_from_chatops_proxy,
mock_get_installation_link_from_chatops_proxy,
make_organization_and_user_with_plugin_token,
make_user_auth_headers,
):
"""
Covers the case when user starts Unified Slack integration installation, but it's already installed.
It might happen if integration was installed from Incident side, but OnCall missed the corresponding event
"""
org, user, token = make_organization_and_user_with_plugin_token()
client = APIClient()
url = reverse("api-internal:social-auth", kwargs={"backend": SLACK_INSTALLATION_BACKEND})
response = client.get(url, **make_user_auth_headers(user, token))
assert response.status_code == status.HTTP_201_CREATED
assert mock_install_slack_integration.call_args.args == (org, user, SLACK_OAUTH_ACCESS_RESPONSE)
Google OAuth2 flow + fetch Google Calendar OOO events (#4067) # What this PR does The following is deployed under a feature flag. **How it works** 1. The user clicks on the "Connect using your Google account" button in the user profile settings modal 2. The UI makes a call to `GET /api/internal/v1/login/google-oauth2`. The backend has now been configured to add `apps.social_auth.backends.GoogleOAuth2` as a "`social_auth` backend". 3. The backend will respond w/ a URL which points to the Google OAuth2 consent screen. The frontend then proceeds by sending the user to this page. This URL includes the following query parameters (amongst others): - `redirect_uri` - this will send the user back to `/api/internal/v1/complete/google-oauth2` (ie. make another API call to the OnCall backend to finalize the Google OAuth2 flow) - `state` - this represents an `apps.auth_token.models.GoogleOAuth2Token` token. This allows us to identify the OnCall user once they've linked their Google account. 4. Once redirected back to `/api/internal/v1/complete/google-oauth2`, this will complete the OAuth2 flow. At this point, the backend has access to several pieces of information about the Google user, including their `access_token` and `refresh_token`. We persist these (encrypted) for future use to fetch the user's out-of-office calendar events 5. The response from the API call in 4 above ☝️ is HTTP 302 (redirect) to `/a/grafana-oncall-app/users/me` (ie. open the user profile settings modal). At this point the user will see that their account has been connected and they can further configure the settings ![image](https://github.com/grafana/oncall/assets/9406895/c7673055-8485-4f9a-98df-b4f7347229ce) ## Which issue(s) this PR closes Closes https://github.com/grafana/oncall-private/issues/2584 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - will be done in https://github.com/grafana/oncall-private/issues/2591 - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. - will be done in https://github.com/grafana/oncall-private/issues/2591 --------- Co-authored-by: Dominik <dominik.broj@grafana.com> Co-authored-by: Maxim Mordasov <maxim.mordasov@grafana.com>
2024-04-02 14:59:03 -04:00
@pytest.mark.django_db
@patch("apps.social_auth.backends.GoogleOAuth2.get_redirect_uri")
@patch("apps.social_auth.backends.GoogleOAuth2Token.create_auth_token", return_value=("something", "token_string"))
@override_settings(SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE=["https://www.googleapis.com/auth/calendar.events.readonly"])
@override_settings(SOCIAL_AUTH_GOOGLE_OAUTH2_KEY="ouath2_key")
def test_google_start_auth_redirect_ok(
_mock_create_google_oauth2_auth_token,
mock_google_oauth2_backend_get_redirect_uri,
make_organization_and_user_with_plugin_token,
make_user_auth_headers,
):
redirect_uri = "http://testserver"
mock_google_oauth2_backend_get_redirect_uri.return_value = redirect_uri
_, user, token = make_organization_and_user_with_plugin_token()
client = APIClient()
url = reverse("api-internal:social-auth", kwargs={"backend": "google-oauth2"})
response = client.get(url, **make_user_auth_headers(user, token))
assert response.status_code == status.HTTP_200_OK
assert response.json() == (
"https://accounts.google.com/o/oauth2/auth?client_id=ouath2_key"
f"&redirect_uri={redirect_uri}&response_type=code"
"&state=token_string&scope=https://www.googleapis.com/auth/calendar.events.readonly+openid+email+profile"
"&access_type=offline&approval_prompt=auto"
)
@pytest.mark.django_db
@patch("apps.api.views.auth.do_complete", return_value=None)
def test_google_complete_auth_redirect_ok(
_mock_do_complete,
make_organization,
make_user_for_organization,
make_google_oauth2_token_for_user,
):
organization = make_organization(grafana_url=GRAFANA_URL)
Google OAuth2 flow + fetch Google Calendar OOO events (#4067) # What this PR does The following is deployed under a feature flag. **How it works** 1. The user clicks on the "Connect using your Google account" button in the user profile settings modal 2. The UI makes a call to `GET /api/internal/v1/login/google-oauth2`. The backend has now been configured to add `apps.social_auth.backends.GoogleOAuth2` as a "`social_auth` backend". 3. The backend will respond w/ a URL which points to the Google OAuth2 consent screen. The frontend then proceeds by sending the user to this page. This URL includes the following query parameters (amongst others): - `redirect_uri` - this will send the user back to `/api/internal/v1/complete/google-oauth2` (ie. make another API call to the OnCall backend to finalize the Google OAuth2 flow) - `state` - this represents an `apps.auth_token.models.GoogleOAuth2Token` token. This allows us to identify the OnCall user once they've linked their Google account. 4. Once redirected back to `/api/internal/v1/complete/google-oauth2`, this will complete the OAuth2 flow. At this point, the backend has access to several pieces of information about the Google user, including their `access_token` and `refresh_token`. We persist these (encrypted) for future use to fetch the user's out-of-office calendar events 5. The response from the API call in 4 above ☝️ is HTTP 302 (redirect) to `/a/grafana-oncall-app/users/me` (ie. open the user profile settings modal). At this point the user will see that their account has been connected and they can further configure the settings ![image](https://github.com/grafana/oncall/assets/9406895/c7673055-8485-4f9a-98df-b4f7347229ce) ## Which issue(s) this PR closes Closes https://github.com/grafana/oncall-private/issues/2584 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - will be done in https://github.com/grafana/oncall-private/issues/2591 - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. - will be done in https://github.com/grafana/oncall-private/issues/2591 --------- Co-authored-by: Dominik <dominik.broj@grafana.com> Co-authored-by: Maxim Mordasov <maxim.mordasov@grafana.com>
2024-04-02 14:59:03 -04:00
admin = make_user_for_organization(organization)
_, google_oauth2_token = make_google_oauth2_token_for_user(admin)
client = APIClient()
url = (
reverse("api-internal:complete-social-auth", kwargs={"backend": "google-oauth2"})
+ f"?state={google_oauth2_token}"
)
response = client.get(url)
assert response.status_code == status.HTTP_302_FOUND
assert response.url == f"{GRAFANA_URL}/a/{PluginID.ONCALL}/users/me"
address Google OAuth2 issues where user didn't grant us the `https://www.googleapis.com/auth/calendar.events.readonly` scope (#4802) # What this PR does Follow up PR to https://github.com/grafana/oncall/pull/4792 Basically if when communicating with Google Calendar's API we encounter an HTTP 403, or the Google client throws a `google.auth.exceptions.RefreshError` this means one of three things: 1. the refresh token we have persisted for the user is missing the `https://www.googleapis.com/auth/calendar.events.readonly` scope (HTTP 403) 2. the Google user has been deleted (`google.auth.exceptions.RefreshError`) 3. the refresh token has expired (`google.auth.exceptions.RefreshError`) To prevent scenario 1 above from happening in the future we now will check that the token has been granted the required scopes. If the user doesn't grant us all the necessary scopes, we will show them an error message in the UI: https://www.loom.com/share/0055ef03192b4154b894c2221cecbd5f For tokens that were granted prior to this PR and which are missing the required scope, we will show the user a dismissible warning banner in the UI letting them know that they will need to reconnect their account and grant us the missing permissions (see [this second demo video](https://www.loom.com/share/bf2ee8b840864a64893165370a892bcd) showing this). ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --------- Co-authored-by: Dominik <dominik.broj@grafana.com>
2024-08-14 18:02:34 -04:00
@pytest.mark.django_db
def test_complete_google_auth_redirect_error(
make_organization,
make_user_for_organization,
make_google_oauth2_token_for_user,
):
organization = make_organization()
admin = make_user_for_organization(organization)
_, google_oauth2_token = make_google_oauth2_token_for_user(admin)
client = APIClient()
url = (
reverse("api-internal:complete-social-auth", kwargs={"backend": "google-oauth2"})
+ f"?state={google_oauth2_token}"
)
def _custom_do_complete(backend, *args, **kwargs):
backend.strategy.session[REDIRECT_FIELD_NAME] = "some-url"
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
with patch("apps.api.views.auth.do_complete", side_effect=_custom_do_complete):
response = client.get(url)
assert response.status_code == status.HTTP_302_FOUND
assert response.url == "some-url"