add dbversion model

This commit is contained in:
dni ⚡
2024-10-14 11:19:14 +02:00
parent 1c451674cf
commit 62d9470010
9 changed files with 66 additions and 39 deletions
+2 -2
View File
@@ -17,7 +17,7 @@ from slowapi.util import get_remote_address
from starlette.middleware.sessions import SessionMiddleware
from lnbits.core.crud import (
get_dbversions,
get_db_version,
get_installed_extensions,
update_installed_extension_state,
)
@@ -313,7 +313,7 @@ async def restore_installed_extension(app: FastAPI, ext: InstallableExtension):
extension = Extension.from_installable_ext(ext)
register_ext_routes(app, extension)
current_version = (await get_dbversions()).get(ext.id, 0)
current_version = await get_db_version(ext.id)
await migrate_extension_database(ext, current_version)
# mount routes for the new version
+2 -2
View File
@@ -17,7 +17,7 @@ from lnbits.core.crud import (
delete_unused_wallets,
delete_wallet_by_id,
delete_wallet_payment,
get_dbversions,
get_db_versions,
get_installed_extension,
get_installed_extensions,
get_payments,
@@ -122,7 +122,7 @@ def database_migrate():
async def db_versions():
"""Show current database versions"""
async with core_db.connect() as conn:
click.echo(await get_dbversions(conn))
click.echo(await get_db_versions(conn))
@db.command("cleanup-wallets")
+25 -16
View File
@@ -25,6 +25,7 @@ from .models import (
AccountFilters,
AccountOverview,
CreatePayment,
DbVersion,
Payment,
PaymentFilters,
PaymentHistoryPoint,
@@ -842,35 +843,37 @@ async def check_internal(
Returns the checking_id of the internal payment if it exists,
otherwise None
"""
row: dict = await (conn or db).fetchone(
payment = await (conn or db).fetchone(
f"""
SELECT checking_id FROM apipayments
SELECT * FROM apipayments
WHERE payment_hash = :hash AND status = '{PaymentState.PENDING}' AND amount > 0
""",
{"hash": payment_hash},
Payment,
)
if not row:
if not payment:
return None
else:
return row["checking_id"]
return payment.checking_id
async def check_internal_status(
async def is_internal_status_success(
payment_hash: str, conn: Optional[Connection] = None
) -> bool:
"""
Returns True if the internal payment was successful
Returns True if the internal payment was found and has the given status,
"""
row: dict = await (conn or db).fetchone(
payment = await (conn or db).fetchone(
"""
SELECT status FROM apipayments
SELECT * FROM apipayments
WHERE payment_hash = :payment_hash AND amount > 0
""",
{"payment_hash": payment_hash},
Payment,
)
if not row:
if not payment:
return True
return row["status"] == PaymentState.SUCCESS.value
return payment.status == PaymentState.SUCCESS.value
async def mark_webhook_sent(payment_hash: str, status: int) -> None:
@@ -950,12 +953,18 @@ async def create_admin_settings(super_user: str, new_settings: dict):
# db versions
# --------------
async def get_dbversions(conn: Optional[Connection] = None) -> dict:
result = await (conn or db).execute("SELECT db, version FROM dbversions")
_dict = {}
for row in result.mappings().all():
_dict[row["db"]] = row["version"]
return _dict
async def get_db_version(
ext_id: str, conn: Optional[Connection] = None
) -> Optional[DbVersion]:
return await (conn or db).fetchone(
"SELECT * FROM dbversions WHERE db = :ext_id",
{"ext_id": ext_id},
model=DbVersion,
)
async def get_db_versions(conn: Optional[Connection] = None) -> list[DbVersion]:
return await (conn or db).fetchall("SELECT * FROM dbversions", model=DbVersion)
async def update_migration_version(conn, db_name, version):
+2 -2
View File
@@ -7,7 +7,7 @@ from lnbits.core import core_app_extra
from lnbits.core.crud import (
create_installed_extension,
delete_installed_extension,
get_dbversions,
get_db_version,
get_installed_extension,
update_installed_extension_state,
)
@@ -28,7 +28,7 @@ async def install_extension(ext_info: InstallableExtension) -> Extension:
ext_info.extract_archive()
db_version = (await get_dbversions()).get(ext_id, 0)
db_version = await get_db_version(ext_id)
await migrate_extension_database(ext_info, db_version)
await create_installed_extension(ext_info)
+20 -8
View File
@@ -1,6 +1,6 @@
import importlib
import re
from typing import Any
from typing import Any, Optional
from urllib.parse import urlparse
from uuid import UUID
@@ -8,17 +8,20 @@ from loguru import logger
from lnbits.core import migrations as core_migrations
from lnbits.core.crud import (
get_dbversions,
get_db_versions,
get_installed_extensions,
update_migration_version,
)
from lnbits.core.db import db as core_db
from lnbits.core.extensions.models import InstallableExtension
from lnbits.core.models import DbVersion
from lnbits.db import COCKROACH, POSTGRES, SQLITE, Connection
from lnbits.settings import settings
async def migrate_extension_database(ext: InstallableExtension, current_version: int):
async def migrate_extension_database(
ext: InstallableExtension, current_version: Optional[DbVersion] = None
):
try:
ext_migrations = importlib.import_module(f"{ext.module_name}.migrations")
@@ -32,14 +35,17 @@ async def migrate_extension_database(ext: InstallableExtension, current_version:
async def run_migration(
db: Connection, migrations_module: Any, db_name: str, current_version: int
db: Connection,
migrations_module: Any,
db_name: str,
current_version: Optional[DbVersion] = None,
):
matcher = re.compile(r"^m(\d\d\d)_")
for key, migrate in migrations_module.__dict__.items():
match = matcher.match(key)
if match:
version = int(match.group(1))
if version > current_version:
if not current_version or version > current_version.version:
logger.debug(f"running migration {db_name}.{version}")
print(f"running migration {db_name}.{version}")
await migrate(db)
@@ -71,7 +77,7 @@ async def load_disabled_extension_list() -> None:
async def migrate_databases():
"""Creates the necessary databases if they don't exist already; or migrates them."""
current_versions = await get_dbversions()
current_versions = await get_db_versions()
async with core_db.connect() as conn:
exists = False
if conn.type == SQLITE:
@@ -87,7 +93,10 @@ async def migrate_databases():
if not exists:
await core_migrations.m000_create_migrations_table(conn)
core_version = current_versions.get("core", 0)
core_version = next(
(v for v in current_versions if v.db == "core"),
DbVersion(db="core", version=0),
)
await run_migration(conn, core_migrations, "core", core_version)
# here is the first place we can be sure that the
@@ -95,7 +104,10 @@ async def migrate_databases():
await load_disabled_extension_list()
for ext in await get_installed_extensions():
current_version = current_versions.get(ext.id)
current_version = next(
(v for v in current_versions if v.db == ext.id),
DbVersion(db=ext.id, version=0),
)
if current_version is None:
logger.warning(
f"Extension {ext.id} has no migration version. This should not happen."
+5
View File
@@ -469,3 +469,8 @@ class BalanceDelta(BaseModel):
class SimpleStatus(BaseModel):
success: bool
message: str
class DbVersion(BaseModel):
db: str
version: int
+2 -4
View File
@@ -46,7 +46,6 @@ from lnbits.wallets.base import (
from .crud import (
check_internal,
check_internal_status,
create_account,
create_admin_settings,
create_payment,
@@ -62,6 +61,7 @@ from .crud import (
get_user,
get_wallet,
get_wallet_payment,
is_internal_status_success,
update_admin_settings,
update_payment_details,
update_payment_status,
@@ -246,9 +246,7 @@ async def pay_invoice(
extra=extra,
)
# we check if an internal invoice exists that has already been paid
# (not pending anymore)
if await check_internal_status(invoice.payment_hash, conn=conn):
if await is_internal_status_success(invoice.payment_hash, conn=conn):
raise PaymentError("Internal invoice already paid.", status="failed")
# check_internal() returns the checking_id of the invoice we're waiting for
+2 -2
View File
@@ -40,7 +40,7 @@ from ..crud import (
create_user_extension,
delete_dbversion,
drop_extension_db,
get_dbversions,
get_db_version,
get_installed_extension,
get_installed_extensions,
get_user_extension,
@@ -474,7 +474,7 @@ async def get_extension_release(org: str, repo: str, tag_name: str):
)
async def delete_extension_db(ext_id: str):
try:
db_version = (await get_dbversions()).get(ext_id, None)
db_version = await get_db_version(ext_id)
if not db_version:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
+6 -3
View File
@@ -23,7 +23,7 @@ from lnbits.wallets import get_funding_source
from ...utils.exchange_rates import allowed_currencies, currencies
from ..crud import (
create_wallet,
get_dbversions,
get_db_versions,
get_installed_extensions,
get_user_by_id,
get_wallet,
@@ -104,7 +104,8 @@ async def extensions(request: Request, user: User = Depends(check_user_exists)):
all_ext_ids = [ext.code for ext in Extension.get_valid_extensions()]
inactive_extensions = [e.id for e in await get_installed_extensions(active=False)]
db_version = await get_dbversions()
db_versions = await get_db_versions()
extensions = [
{
"id": ext.id,
@@ -115,7 +116,9 @@ async def extensions(request: Request, user: User = Depends(check_user_exists)):
"isFeatured": ext.meta.featured if ext.meta else False,
"dependencies": ext.meta.dependencies if ext.meta else "",
"isInstalled": ext.id in installed_exts_ids,
"hasDatabaseTables": ext.id in db_version,
"hasDatabaseTables": next(
(True for version in db_versions if version.db == ext.id), False
),
"isAvailable": ext.id in all_ext_ids,
"isAdminOnly": ext.id in settings.lnbits_admin_extensions,
"isActive": ext.id not in inactive_extensions,