diff --git a/RUNPOD_SETUP.md b/RUNPOD_SETUP.md deleted file mode 100644 index 1756bb3..0000000 --- a/RUNPOD_SETUP.md +++ /dev/null @@ -1,67 +0,0 @@ -# RunPod OAuth Setup Guide - -## Quick Setup for RunPod - -The DropSend node now automatically detects RunPod environments, but for OAuth to work properly, you may need to configure your public URL. - -### Option 1: Automatic Detection (Try This First) - -The node will try to automatically detect your RunPod URL. Just run the OAuth flow and check the console for messages like: - -``` -[OAuthHandler] Detected server URL from request: https://your-runpod-url.runpod.net -``` - -### Option 2: Manual Configuration (If Auto-Detection Fails) - -If the automatic detection doesn't work, set one of these environment variables: - -#### Method A: Set PUBLIC_URL Environment Variable -```bash -export PUBLIC_URL="https://your-runpod-id.runpod.net:8188" -``` - -#### Method B: Set COMFYUI_PUBLIC_URL Environment Variable -```bash -export COMFYUI_PUBLIC_URL="https://your-runpod-id.runpod.net:8188" -``` - -### How to Find Your RunPod URL - -1. **From RunPod Dashboard**: Look for your pod's public URL -2. **From Browser**: Copy the URL you use to access ComfyUI -3. **From Console**: The node will log detected URLs during OAuth - -### Example URLs - -- `https://abc123-8188.proxy.runpod.net` -- `https://xyz789.runpod.net:8188` -- `https://your-custom-domain.com:8188` - -### Testing the Configuration - -1. Run the DropboxSetupNode -2. Check console output for detected URL -3. If URL looks wrong, set the environment variable and restart ComfyUI - -### Troubleshooting - -**Problem**: OAuth callback fails with "redirect_uri mismatch" -**Solution**: Check that the detected URL in the console matches how you access ComfyUI - -**Problem**: Automatic detection shows localhost -**Solution**: Set PUBLIC_URL or COMFYUI_PUBLIC_URL environment variable - -**Problem**: Still getting localhost after setting environment variables -**Solution**: Restart ComfyUI after setting environment variables - -### Storage Method Recommendations for RunPod - -1. **`keyring`**: Now works with encrypted file storage (recommended) -2. **`display_only`**: Best for temporary pods - copy credentials to environment -3. **`env_file`**: Good for persistent storage volumes - -## Tips - -- Use `display_only` for maximum flexibility in cloud environments -- Set environment variables in your RunPod template for automatic configuration diff --git a/generate_base64.py b/generate_base64.py deleted file mode 100644 index 05ed4a9..0000000 --- a/generate_base64.py +++ /dev/null @@ -1,10 +0,0 @@ -# ComfyUI_DropSendNode/generate_base64.py - -import base64 - -app_key = input("Enter your App Key: ") -app_secret = input("Enter your App Secret: ") - -credentials = f"{app_key}:{app_secret}" -encoded = base64.b64encode(credentials.encode()).decode() -print(f"\nBasic {encoded}") diff --git a/get_refresh_token.py b/get_refresh_token.py deleted file mode 100644 index 5c7fafb..0000000 --- a/get_refresh_token.py +++ /dev/null @@ -1,27 +0,0 @@ -# ComfyUI_DropSendNode/get_refresh_token.py - -import base64 -import requests - -APP_KEY = input("Enter your APP KEY: ") -APP_SECRET = input("Enter your APP SECRET: ") -AUTH_CODE = input("Paste the Dropbox authorization code: ") - -auth_header = base64.b64encode(f"{APP_KEY}:{APP_SECRET}".encode()).decode() -res = requests.post( - "https://api.dropbox.com/oauth2/token", - data={ - "code": AUTH_CODE, - "grant_type": "authorization_code", - "redirect_uri": "https://localhost" - }, - headers={ - "Authorization": f"Basic {auth_header}", - "Content-Type": "application/x-www-form-urlencoded" - } -) - -if res.ok: - print("\nYour refresh token is:\n", res.json().get("refresh_token")) -else: - print("Error:", res.text) diff --git a/oauth_handler.py b/oauth_handler.py index 5027e1e..ded42c1 100644 --- a/oauth_handler.py +++ b/oauth_handler.py @@ -70,12 +70,8 @@ class OAuthCallbackHandler: success_message = "Dropbox connected successfully! Credentials saved to .env file." elif self.storage_method == "display_only": - # Display credentials for manual copying and create completion marker + # Display credentials for manual copying import os - node_dir = os.path.dirname(__file__) - display_marker_path = os.path.join(node_dir, ".dropbox_display_complete") - with open(display_marker_path, "w") as f: - f.write("display_only_setup_completed") # Print credentials to console for easy copy/paste print("\n" + "=" * 80) diff --git a/requirements.txt b/requirements.txt index f067d84..a41eb3f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,5 +2,3 @@ requests python-dotenv watchdog dropbox -keyring -keyrings.alt diff --git a/setup_dropbox_node.py b/setup_dropbox_node.py index 7af41a6..ed86c81 100644 --- a/setup_dropbox_node.py +++ b/setup_dropbox_node.py @@ -68,13 +68,6 @@ class DropboxSetupNode: print(f"[DropboxSetup] Removing .env file: {env_path}") os.remove(env_path) - # Clear display_only marker if it exists - display_marker_path = os.path.join(node_dir, ".dropbox_display_complete") - if os.path.exists(display_marker_path): - print(f"[DropboxSetup] Removing display_only marker: {display_marker_path}") - os.remove(display_marker_path) - - # Send WebSocket message to trigger ComfyUI refresh after clearing credentials try: from server import PromptServer @@ -95,31 +88,19 @@ class DropboxSetupNode: "result": (message,) } - # Check for display_only environment variables (user set them up after OAuth flow) - display_only_env_set = all([ + # Check for environment variables (from any source) + env_vars_set = all([ os.getenv("DROPBOX_APP_KEY"), os.getenv("DROPBOX_APP_SECRET"), os.getenv("DROPBOX_REFRESH_TOKEN") ]) - if display_only_env_set: - # Check if this came from display_only flow - node_dir = os.path.dirname(__file__) - display_marker_path = os.path.join(node_dir, ".dropbox_display_complete") - if os.path.exists(display_marker_path): - message = "Dropbox connected using environment variables (display_only setup). Ready to upload files." - print(f"[DropboxSetup] {message}") - return { - "ui": {"text": [message]}, - "result": (message,) - } - else: - # Legacy environment variables (not from display_only) - message = "Dropbox credentials found in system environment variables. Ready to upload files." - print(f"[DropboxSetup] {message}") - return { - "ui": {"text": [message]}, - "result": (message,) - } + if env_vars_set: + message = "Dropbox credentials found in system environment variables. Ready to upload files." + print(f"[DropboxSetup] {message}") + return { + "ui": {"text": [message]}, + "result": (message,) + } # Check for RunPod secrets runpod_env_set = all([ @@ -199,11 +180,7 @@ class DropboxSetupNode: message = "Dropbox connected successfully! Credentials saved to .env file." elif storage_method == "display_only": - # Display credentials for manual copying and create completion marker - node_dir = os.path.dirname(__file__) - display_marker_path = os.path.join(node_dir, ".dropbox_display_complete") - with open(display_marker_path, "w") as f: - f.write("display_only_setup_completed") + # Display credentials for manual copying message = f"""Dropbox Connected Successfully! diff --git a/test_dropbox_auth.py b/test_dropbox_auth.py deleted file mode 100644 index 228a510..0000000 --- a/test_dropbox_auth.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -# test_dropbox_auth_simple.py - Non-interactive testing script for DropboxAuthManager - -from dropbox_auth_manager import DropboxAuthManager - -def test_oauth_url_generation(): - """Test OAuth URL generation""" - print("๐Ÿงช TEST 1: OAuth URL generation") - print("-" * 40) - - # Use a dummy app key for testing - test_app_key = "test_app_key_12345" - - try: - auth = DropboxAuthManager(app_key=test_app_key) - oauth_url = auth.get_oauth_url() - print(f"โœ… Generated OAuth URL:") - print(f" {oauth_url}") - expected_url = f"https://www.dropbox.com/oauth2/authorize?response_type=code&client_id={test_app_key}&token_access_type=offline" - if oauth_url == expected_url: - print("โœ… URL format is correct") - return True - else: - print("โŒ URL format mismatch") - return False - except Exception as e: - print(f"โŒ Error generating OAuth URL: {e}") - return False - -def test_stored_credentials(): - """Test retrieving stored credentials""" - print("\n๐Ÿงช TEST 2: Check for stored credentials") - print("-" * 40) - - try: - auth = DropboxAuthManager() - - print(f"App key stored: {bool(auth.app_key)}") - print(f"App secret stored: {bool(auth.app_secret)}") - print(f"Refresh token stored: {bool(auth.refresh_token)}") - print(f"Is connected: {auth.is_connected()}") - - if auth.is_connected(): - print("โœ… Stored credentials found - testing access token...") - try: - access_token = auth.get_access_token() - print(f"โœ… Got access token: {access_token[:10]}...") - return True - except Exception as e: - print(f"โŒ Error getting access token: {e}") - return False - else: - print("โ„น๏ธ No stored credentials found (this is expected for first run)") - return True - - except Exception as e: - print(f"โŒ Error checking stored credentials: {e}") - return False - -def test_auth_code_exchange(): - """Test auth code exchange with placeholder values""" - print("\n๐Ÿงช TEST 3: Auth code exchange test (with dummy values)") - print("-" * 40) - - # These are dummy values - replace with real ones to test - test_app_key = "your_app_key_here" - test_app_secret = "your_app_secret_here" - test_auth_code = "your_auth_code_here" - - if test_app_key == "your_app_key_here": - print("โ„น๏ธ Skipping auth code exchange test - placeholder values detected") - print("โ„น๏ธ To test this, replace the dummy values in this function with real credentials") - return True - - try: - auth = DropboxAuthManager(test_app_key, test_app_secret) - print(f"Created DropboxAuthManager with app_key: {bool(auth.app_key)}, app_secret: {bool(auth.app_secret)}") - - auth.exchange_auth_code(test_auth_code) - print("โœ… Auth code exchange successful") - print("โœ… Credentials stored successfully") - return True - - except Exception as e: - print(f"โŒ Error during auth code exchange: {e}") - return False - -def test_manager_initialization(): - """Test DropboxAuthManager initialization with different parameters""" - print("\n๐Ÿงช TEST 4: Manager initialization tests") - print("-" * 40) - - try: - # Test 1: Empty initialization - auth1 = DropboxAuthManager() - print(f"โœ… Empty init - app_key: {auth1.app_key}, app_secret: {auth1.app_secret}") - - # Test 2: With parameters - auth2 = DropboxAuthManager("test_key", "test_secret") - print(f"โœ… With params - app_key: {auth2.app_key}, app_secret: {auth2.app_secret}") - - # Test 3: With empty strings (this was causing the bug) - auth3 = DropboxAuthManager("", "") - print(f"โœ… Empty strings - app_key: '{auth3.app_key}', app_secret: '{auth3.app_secret}'") - - return True - except Exception as e: - print(f"โŒ Error during initialization tests: {e}") - return False - -def main(): - print("๐Ÿš€ Dropbox Auth Manager Test Suite (Non-Interactive)") - print("=" * 60) - - # Run all tests - tests = [ - test_oauth_url_generation, - test_stored_credentials, - test_manager_initialization, - test_auth_code_exchange - ] - - results = [] - for test in tests: - result = test() - results.append(result) - - print("\n" + "=" * 60) - print("๐Ÿ“Š TEST SUMMARY:") - passed = sum(results) - total = len(results) - print(f"โœ… Passed: {passed}/{total}") - - if passed == total: - print("๐ŸŽ‰ All tests passed!") - else: - print("โš ๏ธ Some tests failed - check output above") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/test_dropbox_auth_simple.py b/tests/test_dropbox_auth.py similarity index 59% rename from test_dropbox_auth_simple.py rename to tests/test_dropbox_auth.py index df32107..e10e407 100644 --- a/test_dropbox_auth_simple.py +++ b/tests/test_dropbox_auth.py @@ -8,8 +8,11 @@ Usage: This script tests the DropboxAuthManager without requiring user input. """ -from dropbox_auth_manager import DropboxAuthManager +import sys import os +# Add parent directory to path so we can import from the main module +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from dropbox_auth_manager import DropboxAuthManager def test_basic_functionality(): """Test basic DropboxAuthManager functionality""" @@ -21,44 +24,43 @@ def test_basic_functionality(): # Test initialization without credentials print("\n1. Testing initialization without credentials...") auth = DropboxAuthManager() - print(f"โœ… DropboxAuthManager initialized") + print(f"PASS: DropboxAuthManager initialized") print(f" is_connected(): {auth.is_connected()}") # Test initialization with test credentials print("\n2. Testing initialization with test credentials...") test_auth = DropboxAuthManager(app_key="test_key_123", app_secret="test_secret_456") - print(f"โœ… DropboxAuthManager initialized with test credentials") + print(f"PASS: DropboxAuthManager initialized with test credentials") print(f" app_key: {test_auth.app_key}") print(f" is_connected(): {test_auth.is_connected()}") # Test OAuth URL generation print("\n3. Testing OAuth URL generation...") oauth_url = test_auth.get_oauth_url() - print(f"โœ… Basic OAuth URL: {oauth_url[:80]}...") + print(f"PASS: Basic OAuth URL: {oauth_url[:80]}...") - # Test OAuth URL with redirect_uri - callback_url = "http://localhost:8188/oauth/dropbox/callback" - oauth_url_with_redirect = test_auth.get_oauth_url(redirect_uri=callback_url, state="test-session-123") - print(f"โœ… OAuth URL with redirect: {oauth_url_with_redirect[:100]}...") + # Test OAuth URL with manual flow (no redirect_uri needed) + oauth_url_manual = test_auth.get_oauth_url(state="test-session-123", force_reapprove=True) + print(f"PASS: Manual OAuth URL: {oauth_url_manual[:100]}...") - # Test that redirect_uri is included - if "redirect_uri=" in oauth_url_with_redirect and callback_url in oauth_url_with_redirect: - print("โœ… redirect_uri properly included in OAuth URL") + # Test that manual OAuth URL is properly formatted + if "response_type=code" in oauth_url_manual and "token_access_type=offline" in oauth_url_manual: + print("PASS: OAuth URL properly formatted for manual flow") else: - print("โŒ redirect_uri not found in OAuth URL") + print("FAIL: OAuth URL missing required parameters") - # Test that state is included - if "state=test-session-123" in oauth_url_with_redirect: - print("โœ… state parameter properly included in OAuth URL") + # Test that state is included when provided + if "state=test-session-123" in oauth_url_manual: + print("PASS: state parameter properly included in OAuth URL") else: - print("โŒ state parameter not found in OAuth URL") + print("FAIL: state parameter not found in OAuth URL") print("\n" + "=" * 50) - print("โœ… All basic functionality tests passed!") + print("PASS: All basic functionality tests passed!") print("=" * 50) except Exception as e: - print(f"โŒ Error during basic functionality test: {e}") + print(f"FAIL: Error during basic functionality test: {e}") raise def test_error_handling(): @@ -73,24 +75,24 @@ def test_error_handling(): auth_no_key = DropboxAuthManager() try: auth_no_key.get_oauth_url() - print("โŒ Should have raised ValueError") + print("FAIL: Should have raised ValueError") except ValueError as e: - print(f"โœ… Correctly raised ValueError: {e}") + print(f"PASS: Correctly raised ValueError: {e}") # Test auth code exchange without credentials print("\n2. Testing auth code exchange without credentials...") try: auth_no_key.exchange_auth_code_raw("test_code") - print("โŒ Should have raised ValueError") + print("FAIL: Should have raised ValueError") except ValueError as e: - print(f"โœ… Correctly raised ValueError: {e}") + print(f"PASS: Correctly raised ValueError: {e}") print("\n" + "=" * 50) - print("โœ… All error handling tests passed!") + print("PASS: All error handling tests passed!") print("=" * 50) except Exception as e: - print(f"โŒ Unexpected error during error handling test: {e}") + print(f"FAIL: Unexpected error during error handling test: {e}") raise def test_token_exchange_retry_logic(): @@ -107,46 +109,46 @@ def test_token_exchange_retry_logic(): print("\n1. Testing exchange_auth_code_raw method signature...") # Test method exists and accepts parameters (will fail with API call, but that's expected) - try: - test_auth.exchange_auth_code_raw("fake_code", redirect_uri="http://localhost:8188/oauth/dropbox/callback") - except Exception as e: - if "400" in str(e) or "requests" in str(e) or "HTTPSConnectionPool" in str(e): - print(f"โœ… Method executed correctly (expected API failure): {type(e).__name__}") - else: - print(f"โŒ Unexpected error type: {e}") - - # Test method without redirect_uri try: test_auth.exchange_auth_code_raw("fake_code") except Exception as e: if "400" in str(e) or "requests" in str(e) or "HTTPSConnectionPool" in str(e): - print(f"โœ… Method executed correctly without redirect_uri (expected API failure): {type(e).__name__}") + print(f"PASS: Method executed correctly (expected API failure): {type(e).__name__}") else: - print(f"โŒ Unexpected error type: {e}") + print(f"FAIL: Unexpected error type: {e}") + + # Test method with redirect_uri (for backward compatibility) + try: + test_auth.exchange_auth_code_raw("fake_code", redirect_uri="http://localhost:8188/oauth/dropbox/callback") + except Exception as e: + if "400" in str(e) or "requests" in str(e) or "HTTPSConnectionPool" in str(e): + print(f"PASS: Method with redirect_uri executed correctly (expected API failure): {type(e).__name__}") + else: + print(f"FAIL: Unexpected error type: {e}") print("\n" + "=" * 50) - print("โœ… Token exchange retry logic tests completed!") + print("PASS: Token exchange retry logic tests completed!") print("=" * 50) except Exception as e: - print(f"โŒ Error during retry logic test: {e}") + print(f"FAIL: Error during retry logic test: {e}") raise def main(): """Run all tests""" - print("๐Ÿงช Starting DropboxAuthManager Tests") - print("๐Ÿ“ This script tests the auth manager without making real API calls") + print("Starting DropboxAuthManager Tests") + print("This script tests the auth manager without making real API calls") try: test_basic_functionality() test_error_handling() test_token_exchange_retry_logic() - print("\n๐ŸŽ‰ All tests completed successfully!") - print("๐Ÿ’ก To test with real Dropbox credentials, use the interactive flow in ComfyUI") + print("\nAll tests completed successfully!") + print("To test with real Dropbox credentials, use the interactive flow in ComfyUI") except Exception as e: - print(f"\n๐Ÿ’ฅ Test failed: {e}") + print(f"\nTest failed: {e}") return 1 return 0