lnbits-legend/lnbits/core/views/extension_api.py

478 lines
16 KiB
Python
Raw Normal View History

from http import HTTPStatus
from typing import (
List,
)
from bolt11 import decode as bolt11_decode
from fastapi import (
APIRouter,
Depends,
HTTPException,
)
from loguru import logger
2024-09-11 12:41:37 +03:00
from lnbits.core.extensions.extension_manager import (
activate_extension,
deactivate_extension,
install_extension,
uninstall_extension,
)
from lnbits.core.extensions.models import (
CreateExtension,
Extension,
ExtensionConfig,
ExtensionRelease,
InstallableExtension,
PayToEnableInfo,
ReleasePaymentInfo,
UserExtensionInfo,
)
from lnbits.core.models import (
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
SimpleStatus,
User,
)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
from lnbits.core.services import check_transaction_status, create_invoice
from lnbits.decorators import (
check_admin,
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
check_user_exists,
)
from ..crud import (
delete_dbversion,
drop_extension_db,
get_dbversions,
get_installed_extension,
get_installed_extensions,
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
get_user_extension,
update_extension_pay_to_enable,
update_user_extension,
update_user_extension_extra,
)
extension_router = APIRouter(
tags=["Extension Managment"],
prefix="/api/v1/extension",
)
2024-09-11 12:41:37 +03:00
@extension_router.post("", dependencies=[Depends(check_admin)])
async def api_install_extension(data: CreateExtension):
release = await InstallableExtension.get_extension_release(
data.ext_id, data.source_repo, data.archive, data.version
)
if not release:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Release not found"
)
if not release.is_version_compatible:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST, detail="Incompatible extension version"
)
release.payment_hash = data.payment_hash
ext_info = InstallableExtension(
id=data.ext_id, name=data.ext_id, installed_release=release, icon=release.icon
)
try:
2024-09-11 12:41:37 +03:00
extension = await install_extension(ext_info)
2024-09-11 12:41:37 +03:00
except Exception as exc:
logger.warning(exc)
ext_info.clean_extension_files()
detail = (
str(exc)
if isinstance(exc, AssertionError)
else f"Failed to install extension '{ext_info.id}'."
f"({ext_info.installed_version})."
)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=detail,
) from exc
2024-09-11 12:41:37 +03:00
try:
await activate_extension(extension)
return extension
except Exception as exc:
logger.warning(exc)
2024-09-11 12:41:37 +03:00
await deactivate_extension(extension.code)
detail = (
str(exc)
if isinstance(exc, AssertionError)
else f"Extension `{extension.code}` installed, but activation failed."
)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
2024-09-11 12:41:37 +03:00
detail=detail,
) from exc
@extension_router.get("/{ext_id}/details", dependencies=[Depends(check_user_exists)])
async def api_extension_details(
ext_id: str,
details_link: str,
):
try:
all_releases = await InstallableExtension.get_extension_releases(ext_id)
release = next(
(r for r in all_releases if r.details_link == details_link), None
)
assert release, "Details not found for release"
2024-09-11 12:41:37 +03:00
release_details = await ExtensionRelease.fetch_release_details(details_link)
assert release_details, "Cannot fetch details for release"
release_details["icon"] = release.icon
release_details["repo"] = release.repo
return release_details
except AssertionError as exc:
raise HTTPException(HTTPStatus.BAD_REQUEST, str(exc)) from exc
except Exception as exc:
logger.warning(exc)
raise HTTPException(
HTTPStatus.INTERNAL_SERVER_ERROR,
f"Failed to get details for extension {ext_id}.",
) from exc
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
@extension_router.put("/{ext_id}/sell")
async def api_update_pay_to_enable(
ext_id: str,
data: PayToEnableInfo,
user: User = Depends(check_admin),
) -> SimpleStatus:
try:
assert (
data.wallet in user.wallet_ids
), "Wallet does not belong to this admin user."
await update_extension_pay_to_enable(ext_id, data)
return SimpleStatus(
success=True, message=f"Payment info updated for '{ext_id}' extension."
)
except AssertionError as exc:
raise HTTPException(HTTPStatus.BAD_REQUEST, str(exc)) from exc
except Exception as exc:
logger.warning(exc)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=(f"Failed to update pay to install data for extension '{ext_id}' "),
) from exc
@extension_router.put("/{ext_id}/enable")
async def api_enable_extension(
ext_id: str, user: User = Depends(check_user_exists)
) -> SimpleStatus:
2024-09-11 12:41:37 +03:00
if ext_id not in [e.code for e in Extension.get_valid_extensions()]:
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
raise HTTPException(
HTTPStatus.NOT_FOUND, f"Extension '{ext_id}' doesn't exist."
)
try:
logger.info(f"Enabling extension: {ext_id}.")
ext = await get_installed_extension(ext_id)
assert ext, f"Extension '{ext_id}' is not installed."
assert ext.active, f"Extension '{ext_id}' is not activated."
if user.admin or not ext.requires_payment:
await update_user_extension(user_id=user.id, extension=ext_id, active=True)
return SimpleStatus(success=True, message=f"Extension '{ext_id}' enabled.")
user_ext = await get_user_extension(user.id, ext_id)
if not (user_ext and user_ext.extra and user_ext.extra.payment_hash_to_enable):
raise HTTPException(
HTTPStatus.PAYMENT_REQUIRED, f"Extension '{ext_id}' requires payment."
)
if user_ext.is_paid:
await update_user_extension(user_id=user.id, extension=ext_id, active=True)
return SimpleStatus(
success=True, message=f"Paid extension '{ext_id}' enabled."
)
assert (
ext.pay_to_enable and ext.pay_to_enable.wallet
), f"Extension '{ext_id}' is missing payment wallet."
payment_status = await check_transaction_status(
wallet_id=ext.pay_to_enable.wallet,
payment_hash=user_ext.extra.payment_hash_to_enable,
)
if not payment_status.paid:
raise HTTPException(
HTTPStatus.PAYMENT_REQUIRED,
f"Invoice generated but not paid for enabeling extension '{ext_id}'.",
)
user_ext.extra.paid_to_enable = True
await update_user_extension_extra(user.id, ext_id, user_ext.extra)
await update_user_extension(user_id=user.id, extension=ext_id, active=True)
return SimpleStatus(success=True, message=f"Paid extension '{ext_id}' enabled.")
except AssertionError as exc:
raise HTTPException(HTTPStatus.BAD_REQUEST, str(exc)) from exc
except HTTPException as exc:
raise exc from exc
except Exception as exc:
logger.warning(exc)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=(f"Failed to enable '{ext_id}' "),
) from exc
@extension_router.put("/{ext_id}/disable")
async def api_disable_extension(
ext_id: str, user: User = Depends(check_user_exists)
) -> SimpleStatus:
2024-09-11 12:41:37 +03:00
if ext_id not in [e.code for e in Extension.get_valid_extensions()]:
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
raise HTTPException(
HTTPStatus.BAD_REQUEST, f"Extension '{ext_id}' doesn't exist."
)
try:
logger.info(f"Disabeling extension: {ext_id}.")
await update_user_extension(user_id=user.id, extension=ext_id, active=False)
return SimpleStatus(success=True, message=f"Extension '{ext_id}' disabled.")
except Exception as exc:
logger.warning(exc)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=(f"Failed to disable '{ext_id}'."),
) from exc
@extension_router.put("/{ext_id}/activate", dependencies=[Depends(check_admin)])
async def api_activate_extension(ext_id: str) -> SimpleStatus:
try:
logger.info(f"Activating extension: '{ext_id}'.")
2024-09-11 12:41:37 +03:00
ext = Extension.get_valid_extension(ext_id)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
assert ext, f"Extension '{ext_id}' doesn't exist."
2024-09-11 12:41:37 +03:00
await activate_extension(ext)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
return SimpleStatus(success=True, message=f"Extension '{ext_id}' activated.")
except Exception as exc:
logger.warning(exc)
2024-09-11 12:41:37 +03:00
await deactivate_extension(ext_id)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=(f"Failed to activate '{ext_id}'."),
) from exc
@extension_router.put("/{ext_id}/deactivate", dependencies=[Depends(check_admin)])
async def api_deactivate_extension(ext_id: str) -> SimpleStatus:
try:
logger.info(f"Deactivating extension: '{ext_id}'.")
2024-09-11 12:41:37 +03:00
ext = Extension.get_valid_extension(ext_id)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
assert ext, f"Extension '{ext_id}' doesn't exist."
2024-09-11 12:41:37 +03:00
await deactivate_extension(ext_id)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
return SimpleStatus(success=True, message=f"Extension '{ext_id}' deactivated.")
except Exception as exc:
logger.warning(exc)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=(f"Failed to deactivate '{ext_id}'."),
) from exc
2024-09-11 12:41:37 +03:00
@extension_router.delete("/{ext_id}", dependencies=[Depends(check_admin)])
async def api_uninstall_extension(ext_id: str) -> SimpleStatus:
2024-09-11 12:41:37 +03:00
extension = await get_installed_extension(ext_id)
if not extension:
raise HTTPException(
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
status_code=HTTPStatus.NOT_FOUND,
detail=f"Unknown extension id: {ext_id}",
)
2024-09-11 12:41:37 +03:00
installed_extensions = await get_installed_extensions()
# check that other extensions do not depend on this one
2024-09-11 12:41:37 +03:00
for valid_ext_id in [ext.code for ext in Extension.get_valid_extensions()]:
installed_ext = next(
(ext for ext in installed_extensions if ext.id == valid_ext_id), None
)
if installed_ext and ext_id in installed_ext.dependencies:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=(
f"Cannot uninstall. Extension '{installed_ext.name}' "
"depends on this one."
),
)
try:
2024-09-11 12:41:37 +03:00
await uninstall_extension(ext_id)
logger.success(f"Extension '{ext_id}' uninstalled.")
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
return SimpleStatus(success=True, message=f"Extension '{ext_id}' uninstalled.")
except Exception as exc:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(exc)
) from exc
@extension_router.get("/{ext_id}/releases", dependencies=[Depends(check_admin)])
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
async def get_extension_releases(ext_id: str) -> List[ExtensionRelease]:
try:
extension_releases: List[ExtensionRelease] = (
await InstallableExtension.get_extension_releases(ext_id)
)
installed_ext = await get_installed_extension(ext_id)
if not installed_ext:
return extension_releases
for release in extension_releases:
payment_info = installed_ext.find_existing_payment(release.pay_link)
if payment_info:
release.paid_sats = payment_info.amount
return extension_releases
except Exception as exc:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(exc)
) from exc
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
@extension_router.put("/{ext_id}/invoice/install", dependencies=[Depends(check_admin)])
async def get_pay_to_install_invoice(
ext_id: str, data: CreateExtension
) -> ReleasePaymentInfo:
try:
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
assert (
ext_id == data.ext_id
), f"Wrong extension id. Expected {ext_id}, but got {data.ext_id}"
assert data.cost_sats, "A non-zero amount must be specified."
release = await InstallableExtension.get_extension_release(
data.ext_id, data.source_repo, data.archive, data.version
)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
assert release, "Release not found."
assert release.pay_link, "Pay link not found for release."
2024-09-11 12:41:37 +03:00
payment_info = await release.fetch_release_payment_info(data.cost_sats)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
assert payment_info and payment_info.payment_request, "Cannot request invoice."
invoice = bolt11_decode(payment_info.payment_request)
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
assert invoice.amount_msat is not None, "Invoic amount is missing."
invoice_amount = int(invoice.amount_msat / 1000)
assert (
invoice_amount == data.cost_sats
), f"Wrong invoice amount: {invoice_amount}."
assert (
payment_info.payment_hash == invoice.payment_hash
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
), "Wrong invoice payment hash."
return payment_info
except AssertionError as exc:
raise HTTPException(HTTPStatus.BAD_REQUEST, str(exc)) from exc
except Exception as exc:
logger.warning(exc)
raise HTTPException(
HTTPStatus.INTERNAL_SERVER_ERROR, "Cannot request invoice"
) from exc
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
@extension_router.put("/{ext_id}/invoice/enable")
async def get_pay_to_enable_invoice(
ext_id: str, data: PayToEnableInfo, user: User = Depends(check_user_exists)
):
try:
assert data.amount and data.amount > 0, "A non-zero amount must be specified."
ext = await get_installed_extension(ext_id)
assert ext, f"Extension '{ext_id}' not found."
assert ext.pay_to_enable, f"Payment Info not found for extension '{ext_id}'."
assert (
ext.pay_to_enable.required
), f"Payment not required for extension '{ext_id}'."
assert ext.pay_to_enable.wallet and ext.pay_to_enable.amount, (
f"Payment wallet or amount missing for extension '{ext_id}'."
"Please contact the administrator."
)
assert (
data.amount >= ext.pay_to_enable.amount
), f"Minimum amount is {ext.pay_to_enable.amount} sats."
payment_hash, payment_request = await create_invoice(
wallet_id=ext.pay_to_enable.wallet,
amount=data.amount,
memo=f"Enable '{ext.name}' extension.",
)
user_ext = await get_user_extension(user.id, ext_id)
user_ext_info = (
user_ext.extra if user_ext and user_ext.extra else UserExtensionInfo()
)
user_ext_info.payment_hash_to_enable = payment_hash
await update_user_extension_extra(user.id, ext_id, user_ext_info)
return {"payment_hash": payment_hash, "payment_request": payment_request}
except AssertionError as exc:
raise HTTPException(HTTPStatus.BAD_REQUEST, str(exc)) from exc
except Exception as exc:
logger.warning(exc)
raise HTTPException(
HTTPStatus.INTERNAL_SERVER_ERROR, "Cannot request invoice."
) from exc
@extension_router.get(
"/release/{org}/{repo}/{tag_name}",
dependencies=[Depends(check_admin)],
)
async def get_extension_release(org: str, repo: str, tag_name: str):
try:
2024-09-11 12:41:37 +03:00
config = await ExtensionConfig.fetch_github_release_config(org, repo, tag_name)
if not config:
return {}
return {
"min_lnbits_version": config.min_lnbits_version,
"is_version_compatible": config.is_version_compatible(),
"warning": config.warning,
}
except Exception as exc:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(exc)
) from exc
@extension_router.delete(
"/{ext_id}/db",
dependencies=[Depends(check_admin)],
)
async def delete_extension_db(ext_id: str):
try:
db_version = (await get_dbversions()).get(ext_id, None)
if not db_version:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=f"Unknown extension id: {ext_id}",
)
await drop_extension_db(ext_id=ext_id)
await delete_dbversion(ext_id=ext_id)
logger.success(f"Database removed for extension '{ext_id}'")
[feat] Pay to enable extension (#2516) * feat: add payment tab * feat: add buttons * feat: persist `pay to enable` changes * fix: do not disable extension on upgrade * fix: show releases tab first * feat: extract `enableExtension` logic * refactor: rename routes * feat: show dialog for paying extension * feat: create invoice to enable * refactor: extract enable/disable extension logic * feat: add extra info to UserExtensions * feat: check payment for extension enable * fix: parsing * feat: admins must not pay * fix: code checks * fix: test * refactor: extract extension activate/deactivate to the `api` side * feat: add `get_user_extensions ` * feat: return explicit `requiresPayment` * feat: add `isPaymentRequired` to extension list * fix: `paid_to_enable` status * fix: ui layout * feat: show QR Code * feat: wait for invoice to be paid * test: removed deprecated test and dead code * feat: add re-check button * refactor: rename paths for endpoints * feat: i18n * feat: add `{"success": True}` * test: fix listener * fix: rebase errors * chore: update bundle * fix: return error status code for the HTML error pages * fix: active extension loading from file system * chore: temp commit * fix: premature optimisation * chore: make check * refactor: remove extracted logic * chore: code format * fix: enable by default after install * fix: use `discard` instead of `remove` for `set` * chore: code format * fix: better error code * fix: check for stop function before invoking * feat: check if the wallet belongs to the admin user * refactor: return 402 Requires Payment * chore: more typing * chore: temp checkout different branch for tests * fix: too much typing * fix: remove try-except * fix: typo * fix: manual format * fix: merge issue * remove this line --------- Co-authored-by: dni ⚡ <office@dnilabs.com>
2024-05-28 14:07:33 +03:00
return SimpleStatus(
success=True, message=f"DB deleted for '{ext_id}' extension."
)
except HTTPException as ex:
logger.error(ex)
raise ex
except Exception as exc:
logger.error(exc)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=f"Cannot delete data for extension '{ext_id}'",
) from exc