mirror of
https://github.com/lnbits/lnbits.git
synced 2025-10-04 02:14:23 +02:00
FEAT: add db export admin route for pg and sqlite, add to adminui
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -43,6 +43,8 @@ docker
|
|||||||
# fly.io
|
# fly.io
|
||||||
fly.toml
|
fly.toml
|
||||||
|
|
||||||
|
lnbits-backup.zip
|
||||||
|
|
||||||
# Ignore extensions (post installable extension PR)
|
# Ignore extensions (post installable extension PR)
|
||||||
extensions/
|
extensions/
|
||||||
upgrades/
|
upgrades/
|
||||||
|
@@ -47,11 +47,11 @@
|
|||||||
<q-tooltip> Add funds to a wallet. </q-tooltip>
|
<q-tooltip> Add funds to a wallet. </q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
|
||||||
<!-- <q-btn
|
<q-btn
|
||||||
label="Download Database Backup"
|
label="Download Database Backup"
|
||||||
flat
|
flat
|
||||||
@click="downloadBackup"
|
@click="downloadBackup"
|
||||||
></q-btn> -->
|
></q-btn>
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
@@ -535,19 +535,7 @@
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
downloadBackup() {
|
downloadBackup() {
|
||||||
LNbits.api
|
window.open('/admin/api/v1/backup/?usr=' + this.g.user.id, '_blank')
|
||||||
.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)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -1,7 +1,13 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
from shutil import make_archive
|
||||||
|
from subprocess import Popen
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from fastapi import Body, Depends
|
from fastapi import Body, Depends
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
from starlette.exceptions import HTTPException
|
from starlette.exceptions import HTTPException
|
||||||
|
|
||||||
from lnbits.core.crud import get_wallet
|
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.core.services import update_cached_settings, update_wallet_balance
|
||||||
from lnbits.decorators import check_admin, check_super_user
|
from lnbits.decorators import check_admin, check_super_user
|
||||||
from lnbits.server import server_restart
|
from lnbits.server import server_restart
|
||||||
from lnbits.settings import AdminSettings, EditableSettings
|
from lnbits.settings import AdminSettings, EditableSettings, settings
|
||||||
|
|
||||||
from .. import core_app
|
from .. import core_app
|
||||||
from ..crud import delete_admin_settings, get_admin_settings, update_admin_settings
|
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))
|
await update_wallet_balance(wallet_id=id, amount=int(amount))
|
||||||
|
|
||||||
return {"status": "Success"}
|
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"
|
||||||
|
)
|
||||||
|
Reference in New Issue
Block a user