diff --git a/.env.example b/.env.example index 993bd8b8..101a8cb7 100644 --- a/.env.example +++ b/.env.example @@ -36,6 +36,10 @@ LNBITS_DISABLED_EXTENSIONS="amilk" # GitHub has rate-limits for its APIs. The limit can be increased specifying a GITHUB_TOKEN # LNBITS_EXT_GITHUB_TOKEN=github_pat_xxxxxxxxxxxxxxxxxx +# Extensions to be installed by default. If an extension from this list is uninstalled then it will be re-installed on the next restart. +# The extension must be removed from this list in order to not be re-installed. +LNBITS_EXTENSIONS_DEFAULT_INSTALL="tpos" + # Database: to use SQLite, specify LNBITS_DATA_FOLDER # to use PostgreSQL, specify LNBITS_DATABASE_URL=postgres://... # to use CockroachDB, specify LNBITS_DATABASE_URL=cockroachdb://... diff --git a/lnbits/app.py b/lnbits/app.py index 5167055b..e4f5aaf3 100644 --- a/lnbits/app.py +++ b/lnbits/app.py @@ -8,7 +8,7 @@ import signal import sys import traceback from http import HTTPStatus -from typing import Callable +from typing import Callable, List from fastapi import FastAPI, Request from fastapi.exceptions import HTTPException, RequestValidationError @@ -24,7 +24,7 @@ from lnbits.core.tasks import register_task_listeners from lnbits.settings import get_wallet_class, set_wallet_class, settings from .commands import db_versions, load_disabled_extension_list, migrate_databases -from .core import core_app, core_app_extra +from .core import add_installed_extension, core_app, core_app_extra from .core.services import check_admin_settings from .core.views.generic import core_html_routes from .extension_manager import ( @@ -129,7 +129,7 @@ async def check_installed_extensions(app: FastAPI): """ shutil.rmtree(os.path.join("lnbits", "upgrades"), True) await load_disabled_extension_list() - installed_extensions = await get_installed_extensions() + installed_extensions = await build_all_installed_extensions_list() for ext in installed_extensions: try: @@ -142,6 +142,31 @@ async def check_installed_extensions(app: FastAPI): logger.warning(f"Failed to re-install extension: {ext.id}") +async def build_all_installed_extensions_list() -> List[InstallableExtension]: + """ + Returns a list of all the installed extensions plus the extensions that + MUST be installed by default (see LNBITS_EXTENSIONS_DEFAULT_INSTALL). + """ + installed_extensions = await get_installed_extensions() + + installed_extensions_ids = [e.id for e in installed_extensions] + for ext_id in settings.lnbits_extensions_default_install: + if ext_id in installed_extensions_ids: + continue + + ext_releases = await InstallableExtension.get_extension_releases(ext_id) + release = ext_releases[0] if len(ext_releases) else None + + if release: + ext_info = InstallableExtension( + id=ext_id, name=ext_id, installed_release=release, icon=release.icon + ) + installed_extensions.append(ext_info) + await add_installed_extension(ext_info) + + return installed_extensions + + def check_installed_extension(ext: InstallableExtension) -> bool: if ext.has_installed_version: return True diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py index b6c083ce..43ffffd9 100644 --- a/lnbits/core/views/api.py +++ b/lnbits/core/views/api.py @@ -781,9 +781,7 @@ async def api_install_extension( @core_app.delete("/api/v1/extension/{ext_id}") async def api_uninstall_extension(ext_id: str, user: User = Depends(check_admin)): - installable_extensions: List[ - InstallableExtension - ] = await InstallableExtension.get_installable_extensions() + installable_extensions = await InstallableExtension.get_installable_extensions() extensions = [e for e in installable_extensions if e.id == ext_id] if len(extensions) == 0: diff --git a/lnbits/extension_manager.py b/lnbits/extension_manager.py index f9b5ce01..aad67636 100644 --- a/lnbits/extension_manager.py +++ b/lnbits/extension_manager.py @@ -55,7 +55,7 @@ class Extension(NamedTuple): class ExtensionManager: - def __init__(self, include_disabled_exts=False): + def __init__(self): self._disabled: List[str] = settings.lnbits_disabled_extensions self._admin_only: List[str] = settings.lnbits_admin_extensions p = Path(settings.lnbits_path, "extensions") diff --git a/lnbits/settings.py b/lnbits/settings.py index 3bec3f72..3c54f930 100644 --- a/lnbits/settings.py +++ b/lnbits/settings.py @@ -49,7 +49,7 @@ class ExtensionsSettings(LNbitsSettings): "https://raw.githubusercontent.com/lnbits/lnbits-extensions/main/extensions.json" ] ) - + lnbits_extensions_default_install: List[str] = Field(default=[]) # required due to GitHUb rate-limit lnbits_ext_github_token: str = Field(default="")