Merge pull request #716 from christianlouis/code-health/simplify-save-onedrive-settings-12338634662690804221

🧹 [Code Health] Simplify save_onedrive_settings logic and extract env_utils
This commit is contained in:
Christian Krakau-Louis
2026-03-16 10:56:25 +01:00
committed by GitHub
3 changed files with 81 additions and 100 deletions
+19 -93
View File
@@ -3,7 +3,6 @@ OneDrive API endpoints
""" """
import logging import logging
import os
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Annotated, Optional from typing import Annotated, Optional
@@ -14,6 +13,7 @@ from sqlalchemy.orm import Session
from app.auth import require_login from app.auth import require_login
from app.config import settings from app.config import settings
from app.database import get_db from app.database import get_db
from app.utils.env_utils import update_env_file
from app.utils.oauth_helper import exchange_oauth_token from app.utils.oauth_helper import exchange_oauth_token
from app.utils.settings_service import save_setting_to_db from app.utils.settings_service import save_setting_to_db
from app.utils.settings_sync import notify_settings_updated from app.utils.settings_sync import notify_settings_updated
@@ -115,32 +115,7 @@ async def test_onedrive_token(request: Request):
settings.onedrive_refresh_token = new_refresh_token settings.onedrive_refresh_token = new_refresh_token
# Also try to update .env file if it exists # Also try to update .env file if it exists
try: update_env_file({"ONEDRIVE_REFRESH_TOKEN": new_refresh_token})
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), ".env")
if os.path.exists(env_path):
with open(env_path, "r") as f:
env_lines = f.readlines()
updated_lines = []
updated = False
for line in env_lines:
if line.startswith("ONEDRIVE_REFRESH_TOKEN="):
updated_lines.append(f"ONEDRIVE_REFRESH_TOKEN={new_refresh_token}\n")
updated = True
else:
updated_lines.append(line)
if not updated:
updated_lines.append(f"ONEDRIVE_REFRESH_TOKEN={new_refresh_token}\n")
with open(env_path, "w") as f:
f.writelines(updated_lines)
logger.info("Updated refresh token in .env file")
except Exception as e:
logger.warning(f"Failed to update refresh token in .env file: {e}")
# Persist the rotated refresh token to the database # Persist the rotated refresh token to the database
try: try:
@@ -246,75 +221,26 @@ async def save_onedrive_settings(
user.get("preferred_username") or user.get("username") or user.get("email") or user.get("id") or "wizard" user.get("preferred_username") or user.get("username") or user.get("email") or user.get("id") or "wizard"
) )
# Best-effort .env file write # Build settings dictionary mapped to database/memory keys
try: onedrive_settings = {
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), ".env") "onedrive_refresh_token": refresh_token,
if not os.path.exists(env_path): "onedrive_client_id": client_id,
logger.warning(f".env file not found at {env_path}, skipping file write") "onedrive_client_secret": client_secret,
else: "onedrive_tenant_id": tenant_id,
logger.info(f"Updating OneDrive settings in {env_path}") "onedrive_folder_path": folder_path,
}
with open(env_path, "r") as f: # Filter out None values
env_lines = f.readlines() onedrive_settings = {k: v for k, v in onedrive_settings.items() if v is not None}
onedrive_settings = {"ONEDRIVE_REFRESH_TOKEN": refresh_token} # Best-effort .env file write using the new utility
if client_id: env_settings = {k.upper(): v for k, v in onedrive_settings.items()}
onedrive_settings["ONEDRIVE_CLIENT_ID"] = client_id update_env_file(env_settings)
if client_secret:
onedrive_settings["ONEDRIVE_CLIENT_SECRET"] = client_secret
if tenant_id:
onedrive_settings["ONEDRIVE_TENANT_ID"] = tenant_id
if folder_path:
onedrive_settings["ONEDRIVE_FOLDER_PATH"] = folder_path
updated = set() # Update in-memory settings and persist to database dynamically
new_env_lines = [] for key, value in onedrive_settings.items():
for line in env_lines: setattr(settings, key, value)
stripped_line = line.rstrip() save_setting_to_db(db, key, value, changed_by=changed_by)
is_updated = False
for key, value in onedrive_settings.items():
if stripped_line.startswith(f"{key}=") or stripped_line.startswith(f"# {key}="):
new_env_lines.append(f"{key}={value}")
updated.add(key)
is_updated = True
break
if not is_updated:
new_env_lines.append(stripped_line)
for key, value in onedrive_settings.items():
if key not in updated:
new_env_lines.append(f"{key}={value}")
with open(env_path, "w") as f:
f.write("\n".join(new_env_lines) + "\n")
logger.info("Successfully updated OneDrive settings in .env file")
except Exception as env_err:
logger.warning(f"Failed to write .env file (non-fatal): {env_err}")
# Update the settings in memory
if refresh_token:
settings.onedrive_refresh_token = refresh_token
if client_id:
settings.onedrive_client_id = client_id
if client_secret:
settings.onedrive_client_secret = client_secret
if tenant_id:
settings.onedrive_tenant_id = tenant_id
if folder_path:
settings.onedrive_folder_path = folder_path
# Persist to database (primary)
if refresh_token:
save_setting_to_db(db, "onedrive_refresh_token", refresh_token, changed_by=changed_by)
if client_id:
save_setting_to_db(db, "onedrive_client_id", client_id, changed_by=changed_by)
if client_secret:
save_setting_to_db(db, "onedrive_client_secret", client_secret, changed_by=changed_by)
if tenant_id:
save_setting_to_db(db, "onedrive_tenant_id", tenant_id, changed_by=changed_by)
if folder_path:
save_setting_to_db(db, "onedrive_folder_path", folder_path, changed_by=changed_by)
notify_settings_updated() notify_settings_updated()
+55
View File
@@ -0,0 +1,55 @@
import logging
import os
from typing import Dict
logger = logging.getLogger(__name__)
def update_env_file(settings_to_update: Dict[str, str]) -> bool:
"""
Updates the .env file with the given settings (best-effort).
Creates or modifies existing keys.
Args:
settings_to_update: A dictionary mapping uppercase env var names to their new string values.
Returns:
True if the file was successfully updated, False otherwise.
"""
try:
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), ".env")
if not os.path.exists(env_path):
logger.warning(f".env file not found at {env_path}, skipping file write")
return False
logger.info(f"Updating settings in {env_path}")
with open(env_path, "r") as f:
env_lines = f.readlines()
updated = set()
new_env_lines = []
for line in env_lines:
stripped_line = line.rstrip()
is_updated = False
for key, value in settings_to_update.items():
if stripped_line.startswith(f"{key}=") or stripped_line.startswith(f"# {key}="):
new_env_lines.append(f"{key}={value}")
updated.add(key)
is_updated = True
break
if not is_updated:
new_env_lines.append(stripped_line)
for key, value in settings_to_update.items():
if key not in updated:
new_env_lines.append(f"{key}={value}")
with open(env_path, "w") as f:
f.write("\n".join(new_env_lines) + "\n")
logger.info("Successfully updated settings in .env file")
return True
except Exception as env_err:
logger.warning(f"Failed to write .env file (non-fatal): {env_err}")
return False
+7 -7
View File
@@ -75,8 +75,8 @@ class TestTestTokenRotation:
patch.object(settings, "onedrive_refresh_token", "old_token"), patch.object(settings, "onedrive_refresh_token", "old_token"),
patch.object(settings, "onedrive_client_id", "cid"), patch.object(settings, "onedrive_client_id", "cid"),
patch.object(settings, "onedrive_client_secret", "sec"), patch.object(settings, "onedrive_client_secret", "sec"),
patch("app.api.onedrive.os.path.join", return_value=str(env_file)), patch("app.utils.env_utils.os.path.join", return_value=str(env_file)),
patch("app.api.onedrive.os.path.exists", return_value=True), patch("app.utils.env_utils.os.path.exists", return_value=True),
patch("app.database.SessionLocal") as mock_session_local, patch("app.database.SessionLocal") as mock_session_local,
patch("app.api.onedrive.save_setting_to_db"), patch("app.api.onedrive.save_setting_to_db"),
patch("app.api.onedrive.notify_settings_updated"), patch("app.api.onedrive.notify_settings_updated"),
@@ -117,7 +117,7 @@ class TestTestTokenRotation:
patch.object(settings, "onedrive_refresh_token", "old_token"), patch.object(settings, "onedrive_refresh_token", "old_token"),
patch.object(settings, "onedrive_client_id", "cid"), patch.object(settings, "onedrive_client_id", "cid"),
patch.object(settings, "onedrive_client_secret", "sec"), patch.object(settings, "onedrive_client_secret", "sec"),
patch("app.api.onedrive.os.path.exists", return_value=False), patch("app.utils.env_utils.os.path.exists", return_value=False),
patch("app.database.SessionLocal") as mock_session_local, patch("app.database.SessionLocal") as mock_session_local,
patch("app.api.onedrive.save_setting_to_db"), patch("app.api.onedrive.save_setting_to_db"),
patch("app.api.onedrive.notify_settings_updated"), patch("app.api.onedrive.notify_settings_updated"),
@@ -157,7 +157,7 @@ class TestTestTokenRotation:
patch.object(settings, "onedrive_refresh_token", "old_token"), patch.object(settings, "onedrive_refresh_token", "old_token"),
patch.object(settings, "onedrive_client_id", "cid"), patch.object(settings, "onedrive_client_id", "cid"),
patch.object(settings, "onedrive_client_secret", "sec"), patch.object(settings, "onedrive_client_secret", "sec"),
patch("app.api.onedrive.os.path.exists", return_value=True), patch("app.utils.env_utils.os.path.exists", return_value=True),
patch("builtins.open", side_effect=PermissionError("Permission denied")), patch("builtins.open", side_effect=PermissionError("Permission denied")),
patch("app.database.SessionLocal") as mock_session_local, patch("app.database.SessionLocal") as mock_session_local,
patch("app.api.onedrive.save_setting_to_db"), patch("app.api.onedrive.save_setting_to_db"),
@@ -198,7 +198,7 @@ class TestTestTokenRotation:
patch.object(settings, "onedrive_refresh_token", "old_token"), patch.object(settings, "onedrive_refresh_token", "old_token"),
patch.object(settings, "onedrive_client_id", "cid"), patch.object(settings, "onedrive_client_id", "cid"),
patch.object(settings, "onedrive_client_secret", "sec"), patch.object(settings, "onedrive_client_secret", "sec"),
patch("app.api.onedrive.os.path.exists", return_value=False), patch("app.utils.env_utils.os.path.exists", return_value=False),
patch("app.database.SessionLocal", side_effect=Exception("DB error")), patch("app.database.SessionLocal", side_effect=Exception("DB error")),
): ):
response = client.get("/api/onedrive/test-token") response = client.get("/api/onedrive/test-token")
@@ -277,8 +277,8 @@ class TestTokenRotationEnvAppendLine:
patch.object(settings, "onedrive_refresh_token", "old_token"), patch.object(settings, "onedrive_refresh_token", "old_token"),
patch.object(settings, "onedrive_client_id", "cid"), patch.object(settings, "onedrive_client_id", "cid"),
patch.object(settings, "onedrive_client_secret", "sec"), patch.object(settings, "onedrive_client_secret", "sec"),
patch("app.api.onedrive.os.path.join", return_value=str(env_file)), patch("app.utils.env_utils.os.path.join", return_value=str(env_file)),
patch("app.api.onedrive.os.path.exists", return_value=True), patch("app.utils.env_utils.os.path.exists", return_value=True),
patch("app.database.SessionLocal") as mock_sl, patch("app.database.SessionLocal") as mock_sl,
patch("app.api.onedrive.save_setting_to_db"), patch("app.api.onedrive.save_setting_to_db"),
patch("app.api.onedrive.notify_settings_updated"), patch("app.api.onedrive.notify_settings_updated"),