feat(auth): make OAuth credentials user-specific via UserIntegration records
Setup pages now accept an integration_id query param to save OAuth credentials to the user's personal UserIntegration record instead of global settings. The integrations dashboard shows an "Authorize" button for OAuth types (Dropbox, Google Drive, OneDrive) that need credentials. Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
@@ -26,3 +26,21 @@ class TestDropboxViews:
|
||||
"""Test the Dropbox OAuth callback with auth code."""
|
||||
response = client.get("/dropbox-callback?code=test_code")
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_dropbox_setup_page_with_integration_id(self, client):
|
||||
"""Test the Dropbox setup page accepts integration_id query param."""
|
||||
response = client.get("/dropbox-setup?integration_id=42")
|
||||
assert response.status_code == 200
|
||||
# The template should store the integration_id for per-user OAuth flow
|
||||
assert b"oauth_integration_id" in response.content
|
||||
assert b"42" in response.content
|
||||
|
||||
def test_dropbox_setup_page_without_integration_id(self, client):
|
||||
"""Test the Dropbox setup page works without integration_id (global flow)."""
|
||||
response = client.get("/dropbox-setup")
|
||||
assert response.status_code == 200
|
||||
# The template should not set integration_id when not provided
|
||||
body = response.text
|
||||
assert "oauth_integration_id" in body # The JS code is always present
|
||||
# But integration_id template var should be empty
|
||||
assert 'const integrationId = ""' in body
|
||||
|
||||
@@ -30,6 +30,22 @@ class TestGoogleDriveViews:
|
||||
response = client.get("/google-drive-callback?code=test_code")
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_google_drive_setup_page_with_integration_id(self, client):
|
||||
"""Test the Google Drive setup page accepts integration_id query param."""
|
||||
response = client.get("/google-drive-setup?integration_id=99")
|
||||
assert response.status_code == 200
|
||||
# The template should store the integration_id for per-user OAuth flow
|
||||
assert b"oauth_integration_id" in response.content
|
||||
assert b"99" in response.content
|
||||
|
||||
def test_google_drive_setup_page_without_integration_id(self, client):
|
||||
"""Test the Google Drive setup page works without integration_id (global flow)."""
|
||||
response = client.get("/google-drive-setup")
|
||||
assert response.status_code == 200
|
||||
body = response.text
|
||||
assert "oauth_integration_id" in body
|
||||
assert 'const integrationId = ""' in body
|
||||
|
||||
def test_google_drive_callback_with_code_and_state(self, client):
|
||||
"""Test the Google Drive OAuth callback with code and state."""
|
||||
response = client.get("/google-drive-callback?code=test_code&state=test_state")
|
||||
|
||||
@@ -76,6 +76,33 @@ class TestIntegrationsDashboardView:
|
||||
assert "return '/google-drive'" not in body.replace("/google-drive-setup", "")
|
||||
assert "return '/onedrive'" not in body.replace("/onedrive-setup", "")
|
||||
|
||||
def test_integrations_page_contains_authorize_button(self, client):
|
||||
"""GET /integrations page includes per-user Authorize button for OAuth types."""
|
||||
response = client.get("/integrations")
|
||||
assert response.status_code == 200
|
||||
body = response.text
|
||||
assert "isOAuthType" in body
|
||||
assert "Authorize" in body
|
||||
assert "integration_id=" in body
|
||||
|
||||
def test_integrations_page_contains_oauth_types_constant(self, client):
|
||||
"""GET /integrations includes OAUTH_TYPES Set constant."""
|
||||
response = client.get("/integrations")
|
||||
assert response.status_code == 200
|
||||
body = response.text
|
||||
assert "OAUTH_TYPES" in body
|
||||
assert "'DROPBOX'" in body
|
||||
assert "'GOOGLE_DRIVE'" in body
|
||||
assert "'ONEDRIVE'" in body
|
||||
|
||||
def test_integrations_page_modal_info_box_per_user(self, client):
|
||||
"""The create modal info box instructs to save first then authorize."""
|
||||
response = client.get("/integrations")
|
||||
assert response.status_code == 200
|
||||
body = response.text
|
||||
assert "Save this integration first" in body
|
||||
assert "personal integration record" in body
|
||||
|
||||
def test_integrations_page_contains_quota_indicators(self, client):
|
||||
"""GET /integrations page includes quota labels."""
|
||||
response = client.get("/integrations")
|
||||
|
||||
@@ -26,3 +26,19 @@ class TestOnedriveViews:
|
||||
"""Test the OneDrive OAuth callback with auth code."""
|
||||
response = client.get("/onedrive-callback?code=test_code")
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_onedrive_setup_page_with_integration_id(self, client):
|
||||
"""Test the OneDrive setup page accepts integration_id query param."""
|
||||
response = client.get("/onedrive-setup?integration_id=77")
|
||||
assert response.status_code == 200
|
||||
# The template should store the integration_id for per-user OAuth flow
|
||||
assert b"oauth_integration_id" in response.content
|
||||
assert b"77" in response.content
|
||||
|
||||
def test_onedrive_setup_page_without_integration_id(self, client):
|
||||
"""Test the OneDrive setup page works without integration_id (global flow)."""
|
||||
response = client.get("/onedrive-setup")
|
||||
assert response.status_code == 200
|
||||
body = response.text
|
||||
assert "oauth_integration_id" in body
|
||||
assert 'const integrationId = ""' in body
|
||||
|
||||
Reference in New Issue
Block a user