-
-
Notifications
You must be signed in to change notification settings - Fork 344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support custom path for installed extensions #1940
Conversation
Required Extension ChangesExtension changes in order to be compatible:
{
"min_lnbits_version": "xx.yy",
...
}
Change 1:Remove the From: tpos_static_files = [
{
"path": "/tpos/static",
"app": StaticFiles(directory="lnbits/extensions/tpos/static"),
"name": "tpos_static",
}
] To: tpos_static_files = [
{
"path": "/tpos/static",
"name": "tpos_static",
}
] Change 2:Make the From: def tpos_renderer():
return template_renderer(["lnbits/extensions/tpos/templates"]) To: def tpos_renderer():
return template_renderer(["tpos/templates"]) |
Codecov Report
@@ Coverage Diff @@
## dev #1940 +/- ##
==========================================
+ Coverage 59.56% 59.80% +0.24%
==========================================
Files 50 50
Lines 7500 7531 +31
==========================================
+ Hits 4467 4504 +37
+ Misses 3033 3027 -6
... and 3 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
Comparability table for "custom extension path support":
|
lnbits/app.py
Outdated
def register_custom_extensions_path(): | ||
if settings.has_default_extension_path: | ||
return | ||
default_ext_path = "lnbits/extensions" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should use os.path.join()
instead of a string concatenation.
) | ||
logger.warning( | ||
f"You can move the existing '{default_ext_path}' directory to: " | ||
+ f" '{settings.lnbits_extensions_path}/extensions'" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should use os.path.join()
instead of a string concatenation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its just a log message here
sys.path.append(str(Path(settings.lnbits_extensions_path, "extensions"))) | ||
sys.path.append(str(Path(settings.lnbits_extensions_path, "upgrades"))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again os.path.join would help
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is wrong with Path
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i prefer Path
) | ||
|
||
tmp_dir = Path(settings.lnbits_data_folder, "unzip-temp", self.hash) | ||
shutil.rmtree(tmp_dir, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this one can error (for example insufficient permissions), consider try: except:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in that case it is OK for the exception to be propagated (should not be hidden)
shutil.rmtree(self.ext_upgrade_dir, True) | ||
shutil.copytree( | ||
Path(tmp_dir, generated_dir_name), | ||
Path(self.ext_upgrade_dir), | ||
) | ||
shutil.rmtree(tmp_dir, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, all this can error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let it fail ❄️ , let it fail ❄️ , let it fail ❄️ ☃️ 🏔️
with open( | ||
Path(self.ext_upgrade_dir, self.id, "config.json"), "r+" | ||
) as json_file: | ||
with open(Path(self.ext_upgrade_dir, "config.json"), "r+") as json_file: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should you check for existence of this file before opening?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- if the file does not exist then
open
will throw - this is fine
extract_archive
should fail in this case
lnbits/settings.py
Outdated
@property | ||
def has_default_extension_path(self) -> bool: | ||
return self.lnbits_extensions_path == "./lnbits" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs os.path.join
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! awesome
@@ -30,6 +30,10 @@ def url_for(endpoint: str, external: Optional[bool] = False, **params: Any) -> s | |||
def template_renderer(additional_folders: Optional[List] = None) -> Jinja2Templates: | |||
folders = ["lnbits/templates", "lnbits/core/templates"] | |||
if additional_folders: | |||
additional_folders += [ | |||
Path(settings.lnbits_extensions_path, "extensions", f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we want to perform this hack to allow compatibility with old extensions?
But I agree it is just better to perform a clean cut.
Path(settings.lnbits_extensions_path, "extensions", f) | |
Path(settings.lnbits_extensions_path, "extensions", f[18:] if f.startswith("lnbits/extensions/" else f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
* [FIX] correct amount in fiat tracking (#1934) * better debug log * fix: convert msat to sat for fiat amount * [CHORE] update to version 0.11.0 (#1933) * [FIX] codeql for dev branch (#1935) * [FEAT] create data folder if it doesnt exist (#1930) * [FEAT] improve update_admin_settings (#1903) * [FEAT] improve update_admin_settings while working on the push notification pr i found it very hard just to update 2 settings inside the db, so i improved upon update_admin_settings. now you just need to provide a dict with key/values you want to update inside db. also debugging the endpoints for update_settings i found despite the type of `EditableSettings` fastapi did in fact pass a dict. * t * use `EditableSettings` as param in update_settings * fix settings model validation we previously overrode the pydantic validation with our own method * make `LnbitsSettings` a `BaseModel` and only add `BaseSettings` later this allows us to instantiate `EditableSettings` without the environment values being loaded in * add test * forbid extra fields in update api * fixup * add test * test datadir * move UpdateSettings * fix compat * fixup webpush --------- Co-authored-by: jacksn <[email protected]> * [TEST] use clean db in postgres tests (#1928) * [CORE] Document CoreLightningRestWallet (#1920) * document CoreLightningRestWallet * pushed to comment * fixed base64 comment --------- Co-authored-by: Ben <[email protected]> * [TEST] use test data as mockdata (#1929) * add db group to cli * delete mock_data.zip * generate migration data through tests * [BUG] self payments for the same wallet (#1914) * [BUG] self payments for fakewallet make it possible to pay to yourself on fakewallet f * bugfix selfpayments for fakewallet * delete by wallet and fix previous_payment check (#1919) --------- Co-authored-by: callebtc <[email protected]> * [REFACTOR] core/__init__ to not have circular import issues (#1876) * F541 fix remove unused workflow and combine linters into one add lnbits/static to ruff ignore remote setupnode ignore upgrades for mypy ignore F401 for __init__ files unused noqa ignore upgrades for black F821: undefine name disabled and logged webhook_listener for opennode and lnpay because they are obvisouly not working E402: module level import not at top of file fixup revert breaking changes wait for PR #1876 #1876 E721 fixes, only popped up for python3.9 not 3.10 [REFACTOR] core/__init__ to not have circular import issues WIP add db for backwards compat fix pyright make mypy happy again pyright did not catch those, i think mypy got confused with relative imports. maybe we should use absolute ones everywhere E402: module level import not at top of file dont forget to add core_app rebase on ruff pr f remo format * fix clnrest * ignore E402 in conftest * refactoring issues --------- Co-authored-by: jacksn <[email protected]> * make wallets name prettier! (#1918) * make wallets name prettier! * Update lnbits/core/templates/admin/index.html Co-authored-by: dni ⚡ <[email protected]> * Update lnbits/core/templates/admin/index.html Co-authored-by: dni ⚡ <[email protected]> --------- Co-authored-by: Arc <[email protected]> Co-authored-by: dni ⚡ <[email protected]> * Fix payments chart (#1851) * feat: payment history endpoint * test payment history * use new endpoint in frontend * refactor tests * [CHORE] bugfix formatting prettier (#1936) * do not show deleted wallets (#1942) * do not show deleted wallets * rename parameter for clarity * extension loader: do not panic! (#1945) * Revert "do not show deleted wallets (#1942)" (#1947) This reverts commit 1ee2d53. * remove LNURL-p description_hash validation (#1951) * [CHORE] update dependencies, unsafe pip packages, fastapi (#1609) * d * middleware needs to be initialised before startup runs on python3.11 update secp256k1 update psycopg * update fastapi to v0.103 * fix webpush * bump dependencies * ruff issue * lock versions * bump versions --------- Co-authored-by: jacksn <[email protected]> * [FEAT] Focus cursor to textarea (#1959) * Focus cursor to textarea Fix need for additional click to textarea before pasting * [FEAT] autofocus textarea on paste request closes #1959 * format arba * bundle --------- Co-authored-by: dni ⚡ <[email protected]> * add editorconfig config, fix issues (only whitespace changes) (#1958) * adding bolt11 lib and removing bolt11.py from the codebase (#1817) * add latest bolt11 lib decode exception handling for create_payment fix json response for decode bugfix hexing description hash improvement on bolt11 lib update to bolt11 2.0.1 fix clnrest * bolt 2.0.4 * refactor core/crud.py * catch bolt11 erxception clnrest * Updated guide for extension development for current extension management process (#1962) * Startup optimization: nonblocking expiry check (#1943) * nonblocking expiry check * autoruff * smaller interval --------- Co-authored-by: dni ⚡ <[email protected]> * Support custom path for installed extensions (#1940) * feat: the more you fuck around the more you learn * feat: backwards compatible static file loading * refactor: update paths for extension files * refactor: var renaming * doc: update `LNBITS_EXTENSIONS_PATH` documentation * fix: default folder install * feat: install ext without external path * doc: `PYTHONPATH` no longer required * fix: add warnings * fix: missing path * refactor: re-order statements * fix: hardcoded path separator --------- Co-authored-by: dni ⚡ <[email protected]> * [FEAT] Node Managment (#1895) * [FEAT] Node Managment feat: node dashboard channels and transactions fix: update channel variables better types refactor ui add onchain balances and backend_name mock values for fake wallet remove app tab start implementing peers and channel management peer and channel management implement channel closing add channel states, better errors seperate payments and invoices on transactions tab display total channel balance feat: optional public page feat: show node address fix: port conversion feat: details dialog on transactions fix: peer info without alias fix: rename channel balances small improvements to channels tab feat: pagination on transactions tab test caching transactions refactor: move WALLET into wallets module fix: backwards compatibility refactor: move get_node_class to nodes modules post merge bundle fundle feat: disconnect peer feat: initial lnd support only use filtered channels for total balance adjust closing logic add basic node tests add setting for disabling transactions tab revert unnecessary changes add tests for invoices and payments improve payment and invoice implementations the previously used invoice fixture has a session scope, but a new invoice is required tests and bug fixes for channels api use query instead of body in channel delete delete requests should generally not use a body take node id through path instead of body for delete endpoint add peer management tests more tests for errors improve error handling rename id and pubkey to peer_id for consistency remove dead code fix http status codes make cache keys safer cache node public info comments for node settings rename node prop in frontend adjust tests to new status codes cln: use amount_msat instead of value for onchain balance turn transactions tab off by default enable transactions in tests only allow super user to create or delete fix prop name in admin navbar --------- Co-authored-by: jacksn <[email protected]> * [FEAT] cleanup GET /wallet endpoint, add wallet api routes (#1932) * [FEAT] cleanup GET /wallet endpoint, add wallet api route this removes the functionalitiy to create accounts and wallets via the GET /wallet endpoint in generic.py it add endpoints inside the api.py for it and the frontend is modified to use the api endpoints this also simplifies for the `feat/login` for the route. * remove stale generic tests and add api tests * bug wrong endpoint create account * vlad nitpick * added checkif deleted is 404 * reload after renaming wallet * another iteration with vlad * create new wallet if it none exist * fix delete refresh * formatting * Don't create user if allowed users is set (#1822) * dont allow creating of users when allowed users are set * add info to .env.example --------- Co-authored-by: dni ⚡ <[email protected]> * fix typos (#1969) * fix: node ranks (#1968) * [BUG] bundle is broken (#1972) * [BUG] Fix bad transation call (#1973) * fix: `:label="$('xxx')` to :label="$t('xxx') * chore: commit bundles * chore: remove extra file * fix: catch sse exceptions (#1971) * Add Markdown capability globally (#1965) * add markdown capability globally * add markdown to site description * add showdown to package.json remove it from vendor.json, its bundled * formatting * io * Update lnbits/core/templates/core/index.html --------- Co-authored-by: dni ⚡ <[email protected]> * feat: remove commit version (#1980) * nix: fix nixosModule and build (#1979) * lnbits/settings: get LNBITS_COMMIT from envvar if available There is no other way of setting the git commit at runtime, for build systems like Nix that allow you to hermetically define envvars derived from the source that will be available reproducibly at runtime * nix: update potree2nix and nixosModule This is a general refactor that gets everything building and passing the vmTest again * Update nix/modules/lnbits-service.nix --------- Co-authored-by: Pavol Rusnak <[email protected]> * catch exceptions in migrations for extensions (#1987) * fix: admin_ui js error (#1982) * fix: admin_ui js error undefined formData.lnbits_allowed_currencies JS error in console * vlad suggestion * update: to 0.11.1 * revert: update --------- Co-authored-by: jackstar12 <[email protected]> Co-authored-by: dni ⚡ <[email protected]> Co-authored-by: jacksn <[email protected]> Co-authored-by: Ben <[email protected]> Co-authored-by: Tiago Vasconcelos <[email protected]> Co-authored-by: Arc <[email protected]> Co-authored-by: arbadacarba <[email protected]> Co-authored-by: Pavol Rusnak <[email protected]> Co-authored-by: blackcoffeexbt <[email protected]> Co-authored-by: Vlad Stan <[email protected]> Co-authored-by: Matthew Croughan <[email protected]>
* feat: the more you fuck around the more you learn * feat: backwards compatible static file loading * refactor: update paths for extension files * refactor: var renaming * doc: update `LNBITS_EXTENSIONS_PATH` documentation * fix: default folder install * feat: install ext without external path * doc: `PYTHONPATH` no longer required * fix: add warnings * fix: missing path * refactor: re-order statements * fix: hardcoded path separator --------- Co-authored-by: dni ⚡ <[email protected]>
* feat: the more you fuck around the more you learn * feat: backwards compatible static file loading * refactor: update paths for extension files * refactor: var renaming * doc: update `LNBITS_EXTENSIONS_PATH` documentation * fix: default folder install * feat: install ext without external path * doc: `PYTHONPATH` no longer required * fix: add warnings * fix: missing path * refactor: re-order statements * fix: hardcoded path separator --------- Co-authored-by: dni ⚡ <[email protected]>
Summary
Long discussion here: #1579
By default extensions are installed in a hard-coded directory:
lnbits/extensions
.This PR allow users to specify a custom directory where the extensions will be installed by specifying an environment variable.
The reason for having a custom extension path is that some users do not want to perform write operations in their
lnbits
directory (maybe they are using Nix which installs programs to immutable locations).Required changes for extensions:
Config Steps:
.env
file by configuringLNBITS_EXTENSIONS_PATH
. This location must allow WRITE operations.Testing
Backwards compatible
LNBITS_EXTENSIONS_PATH
Extension Install
LNBITS_EXTENSIONS_PATH
to a valid pathlnbits/extensions
directory is empty/does not existLNBITS_EXTENSIONS_PATH
has anextensions
folder that contains the installed extensionTest data:
https://raw.githubusercontent.com/motorina0/watchonly/main/manifest.json
Screenshots