remove blocking on keyring

This commit is contained in:
adamhaley
2025-08-19 18:36:16 -07:00
parent d3cfa57d55
commit 898fd78f60
2 changed files with 102 additions and 86 deletions
+45 -41
View File
@@ -234,53 +234,57 @@ class DropboxAuthManager:
def reset(self, revoke_token=True):
"""Clear stored tokens and optionally revoke authorization with Dropbox"""
# Load credentials from keyring first if we don't have them in memory
if revoke_token and not (self.refresh_token and self.app_key and self.app_secret):
print("[DropboxAuthManager] Loading credentials for token revocation...")
self._try_load_from_keyring()
# First, revoke the token with Dropbox if requested and possible
if revoke_token and self.refresh_token and self.app_key and self.app_secret:
try:
print("[DropboxAuthManager] Revoking token with Dropbox...")
# Get current access token to revoke
access_token = self.get_access_token()
# Revoke the token with Dropbox
revoke_data = {
"token": access_token
}
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
response = requests.post(
"https://api.dropboxapi.com/2/auth/token/revoke",
headers=headers,
json=revoke_data
)
if response.status_code == 200:
print("[DropboxAuthManager] Token successfully revoked with Dropbox")
else:
print(f"[DropboxAuthManager] Token revocation failed: {response.status_code} - {response.text}")
if revoke_token:
# Load credentials from keyring first if we don't have them in memory
if not (self.refresh_token and self.app_key and self.app_secret):
print("[DropboxAuthManager] Loading credentials for token revocation...")
self._try_load_from_keyring()
# First, revoke the token with Dropbox if requested and possible
if self.refresh_token and self.app_key and self.app_secret:
try:
print("[DropboxAuthManager] Revoking token with Dropbox...")
except Exception as e:
print(f"[DropboxAuthManager] Could not revoke token with Dropbox: {e}")
# Continue with local cleanup even if revocation fails
# Get current access token to revoke
access_token = self.get_access_token()
# Revoke the token with Dropbox
revoke_data = {
"token": access_token
}
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
response = requests.post(
"https://api.dropboxapi.com/2/auth/token/revoke",
headers=headers,
json=revoke_data
)
if response.status_code == 200:
print("[DropboxAuthManager] Token successfully revoked with Dropbox")
else:
print(f"[DropboxAuthManager] Token revocation failed: {response.status_code} - {response.text}")
except Exception as e:
print(f"[DropboxAuthManager] Could not revoke token with Dropbox: {e}")
# Continue with local cleanup even if revocation fails
else:
print("[DropboxAuthManager] Skipping token revocation (revoke_token=False)")
# Clear from keyring - but don't block if keyring setup fails
try:
if self._ensure_keyring_setup():
# Clear from keyring - but only if keyring is already available (don't force setup)
if self.keyring_tested and self.keyring_available:
try:
keyring.delete_password(DROPBOX_KEYRING_SERVICE, "app_key")
keyring.delete_password(DROPBOX_KEYRING_SERVICE, "app_secret")
keyring.delete_password(DROPBOX_KEYRING_SERVICE, "refresh_token")
print("[DropboxAuthManager] Cleared credentials from keyring")
except Exception as e:
print(f"[DropboxAuthManager] Could not clear keyring (continuing): {e}")
# Don't fail the reset - just continue with local cleanup
except Exception as e:
print(f"[DropboxAuthManager] Could not clear keyring (continuing): {e}")
else:
print("[DropboxAuthManager] Keyring not accessed - will clear file-based keyring manually")
# Clear instance variables regardless of keyring availability
self.app_key = None
+57 -45
View File
@@ -12,49 +12,48 @@ from .oauth_handler import OAuthCallbackHandler, get_server_base_url
class DropboxSetupNode:
@classmethod
def INPUT_TYPES(cls):
# Check if credentials are already stored WITHOUT loading from keyring (non-blocking)
def _check_credentials_non_blocking(cls):
"""Check for credentials without accessing keyring (non-blocking)"""
try:
print(f"[DropboxSetup] INPUT_TYPES: Checking for credentials (non-blocking)...")
is_connected = False
keyring_available = True # Assume available for UI defaults
# Check for .env file credentials first (no keyring access)
node_dir = os.path.dirname(__file__)
# Check .env file
env_path = os.path.join(node_dir, ".env")
if os.path.exists(env_path):
from dotenv import dotenv_values
env_vars = dotenv_values(env_path)
if all([env_vars.get("DROPBOX_APP_KEY"), env_vars.get("DROPBOX_APP_SECRET"), env_vars.get("DROPBOX_REFRESH_TOKEN")]):
is_connected = True
print(f"[DropboxSetup] Found credentials in .env file")
return True
# Check for display_only completion marker with environment variables
if not is_connected:
display_marker_path = os.path.join(node_dir, ".dropbox_display_complete")
if os.path.exists(display_marker_path):
# For display_only, verify that the user actually set up environment variables
display_only_env_set = all([
os.getenv("DROPBOX_APP_KEY"),
os.getenv("DROPBOX_APP_SECRET"),
os.getenv("DROPBOX_REFRESH_TOKEN")
])
if display_only_env_set:
is_connected = True
print(f"[DropboxSetup] Found display_only completion marker with valid environment variables")
else:
print(f"[DropboxSetup] Found display_only completion marker but environment variables not set yet")
# Check for keyring credentials ONLY by looking for keyring files (no keyring access)
if not is_connected:
keyring_files = [".dropbox_keyring.cfg", ".dropbox_keyring_plaintext.cfg"]
for keyring_file in keyring_files:
keyring_path = os.path.join(node_dir, keyring_file)
if os.path.exists(keyring_path) and os.path.getsize(keyring_path) > 0:
is_connected = True
print(f"[DropboxSetup] Found keyring credential file: {keyring_file}")
break
# Check display_only with environment variables
display_marker_path = os.path.join(node_dir, ".dropbox_display_complete")
if os.path.exists(display_marker_path):
display_only_env_set = all([
os.getenv("DROPBOX_APP_KEY"),
os.getenv("DROPBOX_APP_SECRET"),
os.getenv("DROPBOX_REFRESH_TOKEN")
])
if display_only_env_set:
return True
# Check keyring files existence
keyring_files = [".dropbox_keyring.cfg", ".dropbox_keyring_plaintext.cfg"]
for keyring_file in keyring_files:
keyring_path = os.path.join(node_dir, keyring_file)
if os.path.exists(keyring_path) and os.path.getsize(keyring_path) > 0:
return True
return False
except Exception:
return False
@classmethod
def INPUT_TYPES(cls):
# Check if credentials are already stored WITHOUT loading from keyring (non-blocking)
try:
print(f"[DropboxSetup] INPUT_TYPES: Checking for credentials (non-blocking)...")
is_connected = cls._check_credentials_non_blocking()
keyring_available = True # Assume available for UI defaults
print(f"[DropboxSetup] INPUT_TYPES check - is_connected: {is_connected} (no keyring access)")
except Exception as e:
print(f"[DropboxSetup] INPUT_TYPES error: {e}")
@@ -119,30 +118,41 @@ class DropboxSetupNode:
print(f" auto_oauth: {auto_oauth}")
print(f" storage_method: {storage_method}")
# Initialize auth manager
# Initialize auth manager (no keyring access yet)
auth_manager = DropboxAuthManager()
print(f"[DropboxSetup] Auth manager initialized. Is connected: {auth_manager.is_connected()}")
print(f"[DropboxSetup] Auth manager initialized (keyring access deferred)")
# Handle reconnect/reset request
if reconnect:
print("[DropboxSetup] Reconnect requested - revoking token and clearing credentials")
print("[DropboxSetup] Reconnect requested - clearing all credentials")
# Clear keyring credentials AND revoke token with Dropbox
auth_manager.reset(revoke_token=True)
# Skip token revocation to avoid keyring access - just clear everything
print("[DropboxSetup] Skipping token revocation to avoid keyring prompts")
auth_manager.reset(revoke_token=False)
# Also clear .env file if it exists
# Manually clear all credential files
node_dir = os.path.dirname(__file__)
# Clear .env file if it exists
env_path = os.path.join(node_dir, ".env")
if os.path.exists(env_path):
print(f"[DropboxSetup] Removing .env file: {env_path}")
os.remove(env_path)
# Also clear display_only marker if it exists
# 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)
# Clear keyring files manually (avoiding keyring API)
keyring_files = [".dropbox_keyring.cfg", ".dropbox_keyring_plaintext.cfg"]
for keyring_file in keyring_files:
keyring_path = os.path.join(node_dir, keyring_file)
if os.path.exists(keyring_path):
print(f"[DropboxSetup] Removing keyring file: {keyring_file}")
os.remove(keyring_path)
# Send WebSocket message to trigger ComfyUI refresh after clearing credentials
try:
from server import PromptServer
@@ -163,13 +173,15 @@ class DropboxSetupNode:
"result": (message,)
}
# Check if already connected (keyring has credentials)
if auth_manager.is_connected():
# Check if already connected using the same non-blocking method as INPUT_TYPES
is_connected = self._check_credentials_non_blocking()
if is_connected:
print("[DropboxSetup] Already connected - testing stored credentials")
# Test the stored credentials by getting an access token
# Only access keyring now when we know we need to test credentials
try:
# This will trigger keyring access but only when we know credentials exist
access_token = auth_manager.get_access_token()
message = "✅ Dropbox already connected using stored keyring credentials. Ready to upload files."
message = "✅ Dropbox already connected using stored credentials. Ready to upload files."
print(f"[DropboxSetup] {message}")
return {
"ui": {"text": [message]},