The temp root is resolve()d in settings but the file path was only
abspath()ed, so a symlink inside the temp folder could point outside it
and still pass the check. Resolve both sides the same way.
Also drop the unused /temp folder from the prod image.
A non-numeric, NaN or infinite value raised while parsing and threw away
the whole table. Each bad row is now skipped on its own.
Log a warning when a table has rows but none of a usable rate type, so a
bank with unknown types does not fail silently.
Add an Options field to exchange rate services. Providers get the raw
text, can validate it on save through clean_options, and describe it
with options_help.
The service form now shows API Key only for providers that require one,
and Options only for providers that read it, with that provider's help.
AllRatesToday reads its bank code from Options instead of API Key.
Drop fixed container names so each worktree gets its own containers,
add docker/dev/worktree.sh to set up and tear down a worktree, and
document it under a new Development section in the README.
Navigating back while a mobile picker was open reattached its overlay still
active, leaving the page covered by an overlay nothing could close. Also skip
the reattach when the global container doesn't exist yet.
Import uploads were always written to /usr/src/app/temp, presets were
read from /usr/src/app/import_presets and the caches lived in /var/tmp,
so WYGIWYH only worked from the Docker image's layout. Running it as a
systemd service with a strict sandbox, or on an immutable distro like
NixOS, needs these folders to follow the app or be configurable.
- Presets are read from IMPORT_PRESETS_ROOT, the import_presets folder
next to the app.
- Uploads wait in IMPORT_TEMP_ROOT, the temp folder next to the app by
default, and movable with the IMPORT_TEMP_ROOT env var. The web views,
the API and the import service all use it.
- The file-based caches live under CACHE_ROOT, /var/tmp by default, and
movable with the CACHE_ROOT env var.
In the Docker image the app sits in /usr/src/app, so every default
resolves to the same folder as before.
The import service checked that a file was inside the temp folder with a
plain string prefix, which also accepted sibling folders such as
/usr/src/app/temp-other. It now compares paths.
CI no longer needs to create /usr/src/app before running the tests.
Fixes#472
On touch devices AirDatepicker opens pickers in mobile mode, which closes
them through a shared overlay rather than on blur. The library keeps that
overlay in its module scope, inside a global container appended to the
body. Boosted navigation swaps the body, so the container and overlay are
removed: the library notices the missing container and builds a new one
for the next picker, but keeps reusing the detached overlay. From then on
nothing receives the outside click, and an open picker stays on screen
over the form until the page is fully reloaded.
Create every picker through a helper that remembers the overlay and moves
it back into the current global container whenever it was left detached.
Fixes#227
The update check shared the file-based default cache with cachalot, whose culling randomly deleted the key as pages loaded. Store only the latest release in a dedicated cache, compare it to APP_VERSION at render time, and drop the startup delete. Hide the banner when CHECK_FOR_UPDATES is off or APP_VERSION isn't a valid version.
- Add flag-off login page and admin password tests so the refusal tests can't pass for unrelated reasons
- Expect exactly 401 from refused basic auth
- Gate OIDC_DISABLE_LOCAL_LOGIN on an explicit OIDC_CONFIGURED flag
- Realign the README OIDC table, use "email" consistently, and warn about lockout with OIDC_ALLOW_SIGNUP=false
When the flag is on and an OIDC provider is configured, every e-mail and
password check is refused: the login page, the admin and the API's basic
auth. OIDC logins, API tokens, OAuth apps and permission checks keep working.
The login page hides the password form.
Transfers are still two transactions, now linked to each other:
- shown as one item in lists, with each side's amount, account,
category and tags ("Combine transfers" user setting, on by default)
- date, reference date, paid and mute stay in sync between sides
- edit opens the transfer form; delete, restore, duplicate and bulk
actions act on both sides
- transfers made by the transfer form now trigger rules for each side
Recurring and quick transactions gain a Transfer type, with a "To
account" and optional "To amount", generating linked transfers. A
transfer can be converted into either.
Existing transfers are left as they are, since there is no reliable
way to pair them.
Replace the hard-dated demo fixture with a load_demo_data command that
builds the dataset around the current date, so the demo always has data
in the current month. It also covers more features: multi-currency
accounts with exchange rate history, an ETF and Bitcoin tracked with DCA
strategies, transfers, a credit card using reference dates, installment
plans, recurring transactions, quick transactions, rules and filter
presets.
Credit cards often have paid transactions dated after the invoice being
closed, which made reconciliation against all paid transactions wrong.
The reconciliation panel now lets you balance against all paid
transactions (previous behavior), paid transactions up to a date, or
paid transactions up to a reference month. The adjustment transaction is
dated at the cutoff so later reconciliations with the same or a later
cutoff include it. An invalid cutoff blocks the reconciliation instead
of silently falling back.