FEAT: add db export admin route for pg and sqlite, add to adminui

This commit is contained in:
dni ⚡ 2023-03-02 15:22:39 +01:00
parent c81d3e06c8
commit 6cf1d97d5a
No known key found for this signature in database
GPG key ID: 886317704CC4E618
3 changed files with 52 additions and 16 deletions

2
.gitignore vendored
View file

@ -43,6 +43,8 @@ docker
# fly.io
fly.toml
lnbits-backup.zip
# Ignore extensions (post installable extension PR)
extensions/
upgrades/

View file

@ -47,11 +47,11 @@
<q-tooltip> Add funds to a wallet. </q-tooltip>
</q-btn>
<!-- <q-btn
<q-btn
label="Download Database Backup"
flat
@click="downloadBackup"
></q-btn> -->
></q-btn>
<q-btn
flat
@ -535,19 +535,7 @@
})
},
downloadBackup() {
LNbits.api
.request('GET', '/admin/api/v1/backup/?usr=' + this.g.user.id)
.then(response => {
this.$q.notify({
type: 'positive',
message:
'Success! Database backup request, download starts soon!',
icon: null
})
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
window.open('/admin/api/v1/backup/?usr=' + this.g.user.id, '_blank')
}
}
})

View file

@ -1,7 +1,13 @@
import os
import time
from http import HTTPStatus
from shutil import make_archive
from subprocess import Popen
from typing import Optional
from urllib.parse import urlparse
from fastapi import Body, Depends
from fastapi.responses import FileResponse
from starlette.exceptions import HTTPException
from lnbits.core.crud import get_wallet
@ -9,7 +15,7 @@ from lnbits.core.models import User
from lnbits.core.services import update_cached_settings, update_wallet_balance
from lnbits.decorators import check_admin, check_super_user
from lnbits.server import server_restart
from lnbits.settings import AdminSettings, EditableSettings
from lnbits.settings import AdminSettings, EditableSettings, settings
from .. import core_app
from ..crud import delete_admin_settings, get_admin_settings, update_admin_settings
@ -72,3 +78,43 @@ async def api_topup_balance(
await update_wallet_balance(wallet_id=id, amount=int(amount))
return {"status": "Success"}
@core_app.get(
"/admin/api/v1/backup/",
status_code=HTTPStatus.OK,
dependencies=[Depends(check_super_user)],
response_class=FileResponse,
)
async def api_download_backup() -> FileResponse:
last_filename = "lnbits-backup"
filename = f"lnbits-backup-{int(time.time())}.zip"
db_url = settings.lnbits_database_url
pg_backup_filename = f"{settings.lnbits_data_folder}/lnbits-database.dmp"
is_pg = db_url and db_url.startswith("postgres://")
if is_pg:
p = urlparse(db_url)
command = (
f"pg_dump --host={p.hostname} "
f'--dbname={p.path.replace("/", "")} '
f"--username={p.username} "
f"--no-password "
f"--format=c "
f"--file={pg_backup_filename}"
)
proc = Popen(
command, shell=True, env={**os.environ, "PGPASSWORD": p.password or ""}
)
proc.wait()
make_archive(last_filename, "zip", settings.lnbits_data_folder)
# cleanup pg_dump file
if is_pg:
proc = Popen(f"rm {pg_backup_filename}", shell=True)
proc.wait()
return FileResponse(
path=f"{last_filename}.zip", filename=filename, media_type="application/zip"
)