From 4341c329fd651c6bda9a6d92f86f2f0c86d05a90 Mon Sep 17 00:00:00 2001 From: Arc Date: Fri, 1 May 2026 12:16:39 +0100 Subject: [PATCH] extend to repo manifests --- lnbits/core/models/extensions.py | 26 +++++++++++++++++++----- tests/api/test_extension_api.py | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/lnbits/core/models/extensions.py b/lnbits/core/models/extensions.py index ab6b29cf1..e2931d502 100644 --- a/lnbits/core/models/extensions.py +++ b/lnbits/core/models/extensions.py @@ -54,6 +54,8 @@ class GitHubRelease(BaseModel): id: str organisation: str repository: str + admin_only: bool = False + super_user_only: bool = False class Manifest(BaseModel): @@ -594,6 +596,15 @@ class InstallableExtension(BaseModel): github_release.organisation, github_release.repository ) source_repo = f"{github_release.organisation}/{github_release.repository}" + admin_only = github_release.admin_only or config.admin_only + super_user_only = ( + github_release.super_user_only or config.super_user_only + ) + latest_extension_release = ExtensionRelease.from_github_release( + source_repo, latest_release + ) + latest_extension_release.admin_only = admin_only + latest_extension_release.super_user_only = super_user_only return InstallableExtension( id=github_release.id, name=config.name, @@ -605,11 +616,9 @@ class InstallableExtension(BaseModel): config.tile, ), meta=ExtensionMeta( - admin_only=config.admin_only, - super_user_only=config.super_user_only, - latest_release=ExtensionRelease.from_github_release( - source_repo, latest_release - ), + admin_only=admin_only, + super_user_only=super_user_only, + latest_release=latest_extension_release, ), ) except Exception as e: @@ -768,6 +777,13 @@ class InstallableExtension(BaseModel): repo_releases = await ExtensionRelease.get_github_releases( r.organisation, r.repository ) + for repo_release in repo_releases: + repo_release.admin_only = ( + repo_release.admin_only or r.admin_only + ) + repo_release.super_user_only = ( + repo_release.super_user_only or r.super_user_only + ) extension_releases += repo_releases for e in manifest.extensions: diff --git a/tests/api/test_extension_api.py b/tests/api/test_extension_api.py index e9aa3521b..ecc91df5c 100644 --- a/tests/api/test_extension_api.py +++ b/tests/api/test_extension_api.py @@ -20,7 +20,9 @@ from lnbits.core.models.extensions import ( Extension, ExtensionConfig, ExtensionRelease, + GitHubRelease, InstallableExtension, + Manifest, PayToEnableInfo, ReleasePaymentInfo, UserExtensionInfo, @@ -464,3 +466,36 @@ async def test_extension_api_enable_rejects_admin_and_super_only_extensions( with pytest.raises(HTTPException, match="User not authorized"): await api_enable_extension(super_only_ext, AccountId(id=admin_user.id)) + + +@pytest.mark.anyio +async def test_repo_manifest_flags_apply_to_repo_releases(mocker): + ext_id = f"repo_{uuid4().hex[:8]}" + release = make_extension_release(ext_id) + manifest = Manifest( + repos=[ + GitHubRelease( + id=ext_id, + organisation="lnbits", + repository="tunnel_me_out", + admin_only=True, + super_user_only=True, + ) + ] + ) + mocker.patch.object( + InstallableExtension, + "fetch_manifest", + mocker.AsyncMock(return_value=manifest), + ) + mocker.patch.object( + ExtensionRelease, + "get_github_releases", + mocker.AsyncMock(return_value=[release]), + ) + + releases = await InstallableExtension.get_extension_releases(ext_id) + + assert len(releases) == 1 + assert releases[0].admin_only is True + assert releases[0].super_user_only is True