From abe1e2fb27d381058aac9b9a4b9bfb92aad2d1ea Mon Sep 17 00:00:00 2001 From: Tiago Vasconcelos Date: Tue, 30 Jun 2026 11:18:36 +0100 Subject: [PATCH] display expiry on ACL tokens --- lnbits/core/models/misc.py | 1 + lnbits/core/views/auth_api.py | 5 ++++- lnbits/static/js/pages/account.js | 5 +++++ lnbits/templates/pages/account.vue | 33 ++++++++++++++++++++++++++++++ tests/api/test_auth.py | 10 ++++++--- 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/lnbits/core/models/misc.py b/lnbits/core/models/misc.py index 5aad3fdc9..029b19510 100644 --- a/lnbits/core/models/misc.py +++ b/lnbits/core/models/misc.py @@ -41,6 +41,7 @@ class SimpleStatus(BaseModel): class SimpleItem(BaseModel): id: str name: str + expires_at: int | None = None class DbVersion(BaseModel): diff --git a/lnbits/core/views/auth_api.py b/lnbits/core/views/auth_api.py index 71a792a93..5d5c08d4f 100644 --- a/lnbits/core/views/auth_api.py +++ b/lnbits/core/views/auth_api.py @@ -295,7 +295,10 @@ async def api_create_user_api_token( account.username, api_token_id, data.expiration_time_minutes ) - acl.token_id_list.append(SimpleItem(id=api_token_id, name=data.token_name)) + expires_at = int(time()) + data.expiration_time_minutes * 60 + acl.token_id_list.append( + SimpleItem(id=api_token_id, name=data.token_name, expires_at=expires_at) + ) await update_user_access_control_list(acls) return ApiTokenResponse(id=api_token_id, api_token=api_token) diff --git a/lnbits/static/js/pages/account.js b/lnbits/static/js/pages/account.js index 28dbc38fc..4f2a7515e 100644 --- a/lnbits/static/js/pages/account.js +++ b/lnbits/static/js/pages/account.js @@ -217,6 +217,11 @@ window.PageAccount = { computed: { isUserTouched() { return !_.isEqual(this.g.user, this.untouchedUser) + }, + selectedApiToken() { + return this.selectedApiAcl.token_id_list.find( + token => token.id === this.apiAcl.selectedTokenId + ) } }, methods: { diff --git a/lnbits/templates/pages/account.vue b/lnbits/templates/pages/account.vue index 2373062b3..ac1a5f2e2 100644 --- a/lnbits/templates/pages/account.vue +++ b/lnbits/templates/pages/account.vue @@ -889,6 +889,39 @@ > +
+ + + + +
diff --git a/tests/api/test_auth.py b/tests/api/test_auth.py index aea787cff..82361e6d9 100644 --- a/tests/api/test_auth.py +++ b/tests/api/test_auth.py @@ -1745,10 +1745,14 @@ async def test_api_create_user_api_token_success( ), "Expiration time should be 60 minutes from now." token_id = payload["api_token_id"] - assert any( - token_id in [token.id for token in acl.token_id_list] + stored_token = next( + token for acl in acls.access_control_list - ), "API token should be part of at least one ACL." + for token in acl.token_id_list + if token.id == token_id + ) + assert stored_token.expires_at is not None + assert abs(stored_token.expires_at - expiration_time) <= 1 @pytest.mark.anyio