feat: used dedicated table for installed extensions
This commit is contained in:
parent
9bd1720d03
commit
38a132604b
6 changed files with 94 additions and 16 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 []
|
||||||
|
|
|
||||||
|
|
@ -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 '{}'
|
||||||
|
);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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: {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue