feat: used dedicated table for installed extensions

This commit is contained in:
Vlad Stan 2023-01-11 19:06:58 +02:00
parent 9bd1720d03
commit 38a132604b
6 changed files with 94 additions and 16 deletions

View file

@ -11,7 +11,7 @@ from lnbits.settings import settings
from .core import db as core_db from .core import db as core_db
from .core import migrations as core_migrations from .core import migrations as core_migrations
from .core.crud import USER_ID_ALL, get_dbversions, get_inactive_extensions from .core.crud import get_dbversions, get_inactive_extensions
from .core.helpers import migrate_extension_database, run_migration from .core.helpers import migrate_extension_database, run_migration
from .db import COCKROACH, POSTGRES, SQLITE from .db import COCKROACH, POSTGRES, SQLITE
from .extension_manger import get_valid_extensions from .extension_manger import get_valid_extensions
@ -83,5 +83,5 @@ async def migrate_databases():
async def load_disabled_extension_list() -> None: async def load_disabled_extension_list() -> None:
"""Update list of extensions that have been explicitly disabled""" """Update list of extensions that have been explicitly disabled"""
inactive_extensions = await get_inactive_extensions(user_id=USER_ID_ALL) inactive_extensions = await get_inactive_extensions()
settings.lnbits_disabled_extensions += inactive_extensions settings.lnbits_disabled_extensions += inactive_extensions

View file

@ -11,8 +11,6 @@ from lnbits.settings import AdminSettings, EditableSettings, SuperSettings, sett
from . import db from . import db
from .models import BalanceCheck, Payment, User, Wallet from .models import BalanceCheck, Payment, User, Wallet
USER_ID_ALL = "all"
# accounts # accounts
# -------- # --------
@ -68,6 +66,61 @@ async def get_user(user_id: str, conn: Optional[Connection] = None) -> Optional[
) )
# extensions
# -------
async def add_installed_extension(
*,
ext_id: str,
version,
active: bool,
hash: str,
meta: dict,
conn: Optional[Connection] = None,
) -> None:
await (conn or db).execute(
"""
INSERT INTO installed_extensions (id, version, active, hash, meta) VALUES (?, ?, ?, ?, ?)
ON CONFLICT (id) DO
UPDATE SET (version, active, hash, meta) = (?, ?, ?, ?)
""",
(
ext_id,
version,
active,
hash,
json.dumps(meta),
version,
active,
hash,
json.dumps(meta),
),
)
async def update_installed_extension_state(
*, ext_id: str, active: bool, conn: Optional[Connection] = None
) -> None:
await (conn or db).execute(
"""
UPDATE installed_extensions SET active = ? WHERE id = ?
""",
(active, ext_id),
)
async def delete_installed_extension(
*, ext_id: str, conn: Optional[Connection] = None
) -> None:
await (conn or db).execute(
"""
DELETE from installed_extensions WHERE id = ?
""",
(ext_id,),
)
async def update_user_extension( async def update_user_extension(
*, user_id: str, extension: str, active: bool, conn: Optional[Connection] = None *, user_id: str, extension: str, active: bool, conn: Optional[Connection] = None
) -> None: ) -> None:
@ -80,12 +133,10 @@ async def update_user_extension(
) )
async def get_inactive_extensions( async def get_inactive_extensions(*, conn: Optional[Connection] = None) -> List[str]:
*, user_id: str, conn: Optional[Connection] = None
) -> List[str]:
inactive_extensions = await (conn or db).fetchall( inactive_extensions = await (conn or db).fetchall(
"""SELECT extension FROM extensions WHERE "user" = ? AND NOT active""", """SELECT id FROM installed_extensions WHERE NOT active""",
(user_id,), (),
) )
return ( return (
[ext[0] for ext in inactive_extensions] if len(inactive_extensions) != 0 else [] [ext[0] for ext in inactive_extensions] if len(inactive_extensions) != 0 else []

View file

@ -269,3 +269,17 @@ async def m008_create_admin_settings_table(db):
); );
""" """
) )
async def m009_create_installed_extensions_table(db):
await db.execute(
"""
CREATE TABLE IF NOT EXISTS installed_extensions (
id TEXT PRIMARY KEY,
version INT NOT NULL,
active BOOLEAN DEFAULT false,
hash TEXT NOT NULL,
meta TEXT NOT NULL DEFAULT '{}'
);
"""
)

View file

@ -59,14 +59,14 @@ from lnbits.utils.exchange_rates import (
from .. import core_app, core_app_extra, db from .. import core_app, core_app_extra, db
from ..crud import ( from ..crud import (
USER_ID_ALL, add_installed_extension,
delete_installed_extension,
get_dbversions, get_dbversions,
get_payments, get_payments,
get_standalone_payment, get_standalone_payment,
get_total_balance, get_total_balance,
get_wallet_for_key, get_wallet_for_key,
save_balance_check, save_balance_check,
update_user_extension,
update_wallet, update_wallet,
) )
from ..services import ( from ..services import (
@ -741,7 +741,13 @@ async def api_install_extension(
await migrate_extension_database(extension, db_version) await migrate_extension_database(extension, db_version)
# disable by default # disable by default
await update_user_extension(user_id=USER_ID_ALL, extension=ext_id, active=False) await add_installed_extension(
ext_id=ext_id,
version=ext_info.version,
active=False,
hash=hash,
meta=dict(ext_info),
)
settings.lnbits_disabled_extensions += [ext_id] settings.lnbits_disabled_extensions += [ext_id]
# mount routes for the new version # mount routes for the new version
@ -788,6 +794,7 @@ async def api_uninstall_extension(ext_id: str, user: User = Depends(check_admin)
for ext_info in extensions: for ext_info in extensions:
ext_info.clean_extension_files() ext_info.clean_extension_files()
await delete_installed_extension(ext_id=ext_info.id)
except Exception as ex: except Exception as ex:
raise HTTPException( raise HTTPException(

View file

@ -18,7 +18,6 @@ from lnbits.settings import get_wallet_class, settings
from ...extension_manger import InstallableExtension, get_valid_extensions from ...extension_manger import InstallableExtension, get_valid_extensions
from ..crud import ( from ..crud import (
USER_ID_ALL,
create_account, create_account,
create_wallet, create_wallet,
delete_wallet, delete_wallet,
@ -26,6 +25,7 @@ from ..crud import (
get_inactive_extensions, get_inactive_extensions,
get_user, get_user,
save_balance_notify, save_balance_notify,
update_installed_extension_state,
update_user_extension, update_user_extension,
) )
from ..services import pay_invoice, redeem_lnurl_withdraw from ..services import pay_invoice, redeem_lnurl_withdraw
@ -89,10 +89,15 @@ async def extensions_install(
settings.lnbits_disabled_extensions = list( settings.lnbits_disabled_extensions = list(
filter(lambda e: e != activate, settings.lnbits_disabled_extensions) filter(lambda e: e != activate, settings.lnbits_disabled_extensions)
) )
await toggle_extension(activate, deactivate, USER_ID_ALL)
ext_id = activate or deactivate
if ext_id:
await update_installed_extension_state(
ext_id=ext_id, active=activate != None
)
installed_extensions = list(map(lambda e: e.code, get_valid_extensions(True))) installed_extensions = list(map(lambda e: e.code, get_valid_extensions(True)))
inactive_extensions = await get_inactive_extensions(user_id=USER_ID_ALL) inactive_extensions = await get_inactive_extensions()
extensions = list( extensions = list(
map( map(
lambda ext: { lambda ext: {

View file

@ -12,6 +12,7 @@ import httpx
from fastapi.exceptions import HTTPException from fastapi.exceptions import HTTPException
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from loguru import logger from loguru import logger
from pydantic import BaseModel
from starlette.types import ASGIApp, Receive, Scope, Send from starlette.types import ASGIApp, Receive, Scope, Send
from lnbits.settings import settings from lnbits.settings import settings
@ -101,7 +102,7 @@ class ExtensionManager:
return output return output
class InstallableExtension(NamedTuple): class InstallableExtension(BaseModel):
id: str id: str
name: str name: str
archive: str archive: str