feat(settings): persist storage provider settings to DB, add export endpoint, enrich setup wizard
- dropbox/google_drive/onedrive save-settings: switch to DB as primary, .env write as best-effort (no longer fails when .env is absent) - onedrive/google_drive update-settings: persist changes to DB alongside in-memory update; call notify_settings_updated() - onedrive test_onedrive_token: persist rotated refresh token to DB - settings_service: add get_settings_for_export() (db / effective modes) - settings API: add GET /api/settings/export-env (admin-only, downloads .env) - wizard: enrich settings with current values (DB > ENV > default) and value_source badges; pass setup_skipped to template; call notify_settings_updated() on save; add /setup/undo-skip route - setup_wizard.html: pre-populate inputs with current_value; show DB/ENV/DEFAULT source badges; skip/undo-skip messaging - settings.html: replace single Audit Log button with Setup Wizard link, Export .env dropdown, and Audit Log button group Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -450,3 +450,61 @@ async def rollback_setting_to_history(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Failed to roll back setting: {key}",
|
||||
)
|
||||
|
||||
|
||||
@router.get("/export-env")
|
||||
async def export_env_settings(
|
||||
request: Request,
|
||||
db: DbSession,
|
||||
admin: AdminUser,
|
||||
source: str = "db",
|
||||
):
|
||||
"""
|
||||
Export current settings as a ``.env`` file.
|
||||
|
||||
Query params:
|
||||
- ``source=db`` (default) – only settings explicitly saved to the database.
|
||||
- ``source=effective`` – full runtime configuration (DB > ENV > defaults) for
|
||||
every key defined in SETTING_METADATA.
|
||||
|
||||
Returns a downloadable plain-text file suitable for bootstrapping another
|
||||
installation. All values — including sensitive ones — are included; only
|
||||
admins can access this endpoint.
|
||||
"""
|
||||
from fastapi.responses import Response as FastAPIResponse
|
||||
|
||||
from app.utils.settings_service import get_settings_for_export
|
||||
|
||||
if source not in ("db", "effective"):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="source must be 'db' or 'effective'",
|
||||
)
|
||||
|
||||
try:
|
||||
export_data = get_settings_for_export(db, source=source)
|
||||
lines = [
|
||||
"# DocuElevate configuration export",
|
||||
f"# Source: {source}",
|
||||
"# Generated by DocuElevate Settings Export",
|
||||
"# WARNING: This file contains sensitive values. Handle with care.",
|
||||
"",
|
||||
]
|
||||
for env_key, value in export_data.items():
|
||||
lines.append(f"{env_key}={value}")
|
||||
lines.append("") # trailing newline
|
||||
content = "\n".join(lines)
|
||||
|
||||
return FastAPIResponse(
|
||||
content=content,
|
||||
media_type="text/plain",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="docuelevate-{source}.env"'
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error exporting settings: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Failed to export settings",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user