Git Product home page Git Product logo

gnucash-web's Introduction

GnuCash Web

GnuCash Web is a simple, easy to use, mobile-friendly web interface for GnuCash intended for self-hosting. It can access a single GnuCash-Database in sqlite3, postgres or mysql (including mariadb) format using the great piecash GnuCash library for Python.

Development status should be considered at most Beta, see below for more information.

Check out the demo!

Features

The primary use case for GnuCash Web is adding simple two-split transactions on the go, e.g. to record a cash expense when buying a coffee.

Key features include:

  • Browse account hierarchy
  • View transaction history and balance for an account
  • Add and edit two-split transactions, delete transactions
  • Recycle commonly used transactions
  • Simple single-user authentication
  • Ease of use, especially on mobile
  • CLI to update the price database
Browse account hierarchy View and add transactions Edit transactions
Browse account hierarchy View and add transactions Edit transaction

Core Technology Stack

Installation

GnuCash Web is available on PyPI, so you can simply install it via pip install gnucash_web. Additionally, you may need to install mysql or psycopg2, depending on which back end you want to use (sqlite back end is included in the python standard library).

Note that at least Python 3.8 is required.

You also need to setup a database that stores the GnuCash data, see below for more information. Mind that you will likely need to be able to access the database directly from your desktop/notebook with the official GnuCash desktop app, since GnuCash Web is only a companion and not intended to be used on its own. If your database is not publicly accessible, using an SSH Tunnel is an easy and secure way to access it remotely.

Usage

GnuCash Web is aimed at system administrators, but is otherwise easy to set up.

Configuration

Create a config file in /etc/gnucash-web/config.py or in ~/.config/gnucash-web/config.py. If both files are present, values from the latter override those from the former. Set the environment variable GNUCASH_WEB_CONFIG to load a different config file. If set, no other config files are read.

Config variables can also be set via environment variables, with the same available options.

The config file is a python script. The following example illustrates possible values for all available options. This is the normal Flask configuration file, so all standard configuration variables can also be set. All options have default values, but you should at least set SECRET_KEY and DB_NAME.

import logging

# A 32-bit-key used e.g. to encrypt the session cookie or for other cryptographic operations
# Use e.g. `from Crypto.Random import get_random_bytes; print(get_random_bytes(32))`
SECRET_KEY = 'please use something thats actually safe'

# Python standard library log level
LOG_LEVEL = logging.WARN

# Supported values: 'sqlite', 'mysql' or 'postgres'
DB_DRIVER = 'mysql'

# Host name of the database (ignored for DB_DRIVER = 'sqlite')
DB_HOST = 'database.example.org'

# Name of the Database on the host (for DB_DRIVER = 'sqlite', this is the 'path/to/db.sqlite')
DB_NAME = 'gnucash_data'

# Supported values: None, 'passthrough'. See below for details.
AUTH_MECHANISM = None

# The maximum number of transactions per page in the ledger
TRANSACTION_PAGE_LENGTH = 25

# Name of the account to be preselected when creating new transactions (optional)
PRESELECTED_CONTRA_ACCOUNT = 'Example:Account'

Running

It is not recommended to use the builtin Flask web server in production. GnuCash Web comes as a WSGI application, so there are many options available to run it.

Most WSGI web server require setting a "module", which is the WSGI object that runs the app. For GnuCash Web, this is gnucash_web.wsgi:app.

For example, the following .ini-file might be used as a config for uWSGI:

[uwsgi]
module = gnucash_web.wsgi:app
pidfile = gnucash_web.pid
master = true
processes = 1
http-socket = :8080
chmod-socket = 660
vacuum = true

Docker

GnuCash Web can be run using Docker, either using the published packages, DockerFile, or using docker compose with the provided sample docker-compose.yml files. This uses a simple SQLite backend, though if you want to use a dedicated database backend then docker-compose-postgres.yml is also provided, running PostgreSQL as the name implies.

In either case, configuration is done via environment variables in the compose file instead of the default configuration file. The same options are available.

If you're running a dedicated backend as part of docker compose, then in order to initialise the database you'll need to expose the respective ports. Keep security in mind when exposing ports, such as using a strong password, as exposing ports may grant any user on the internet access to your database.

If you want to quickly spin up and test gnucash-web, then a sample GnuCash database is provided for the SQLite version.

The Docker version runs the gunicorn WSGI server.

Initialising database

GnuCash Web only works on a preexisting database. It is also currently not possible to create accounts. Therefore, you have to create a database and populate it with an account hierarchy before you can use GnuCash Web.

Preferably, you will use the official GnuCash desktop app to create a new book. Simply select the appropriate database back end in the Open-dialog. You can also migrate an existing GnuCash XML file to a database using Save as. More details and database considerations can be found in the official GnuCash documentation.

Alternatively, you can also use piecash to create a new book, as is described in their example section.

Authentication

Currently, there are only two authentication mechanisms supported, None and 'passthrough'.

When using no authentication, anyone can access the web interface and no credentials are provided to the database host. This is generally only useful when using the sqlite back end (which does not accept credentials).

When using pass-through authentication, GnuCash Web asks for username and password upon login, which are provided as credentials for the database hosts. They are also stored in an encrypted session cookie in the users browser. "Logging out" simply deletes the session cookie.

CLI

The CLI is called gnucash-web and is installed with the PyPi package. Currently, the only supported subcommand is gnucash-web commodities:

Usage: gnucash-web commodities [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  list           List all used commodities.
  update_prices  Update prices for all commodities for which it is enabled.

You can add/edit commodities using the GnuCash desktop app. Make sure to enable online quotes updating. Then, gnucash-web commodities update_prices will retrieve daily closing prices from Yahoo Finance (Quandl for currencies). See also the piecash documentation of the underlying function.

Development

Initialise submodules and install dependencies:

    git submodule init
    git submodule update
    pip install -r src/requirements.txt

Run it:

    cd src/gnucash_web/
    flask run --debug

Make new release:

  • Update version number in src/gnucash_web/version.txt
  • Build and upload package
        cd src/
        python -m build
        python -m twine upload dist/gnucash_web-$VERSION*
  • Tag commit and create release on GitHub

Contributing

Development is at an early stage, but contributions are welcome.

This is (currently) a personal project to play around with and satisfy my own everyday needs and intellectual curiosity.

Since GnuCash Web fulfills my primary use case for it, I don't expect much development in the near future. However, if anyone is willing to help taking this into a more feature-rich direction, I am motivated to work on that, though time is naturally scarce.

Please note that my primary user is myself and any changes must be compatible with my use case and workflows. I will also not accept changes or additions that I cannot gauarantee to maintain in the future. Simplicity is more important to me than features, so please consider this and talk to me before spending time on big changes.

See Issues and Milestones for some ideas on how to get started.

Related Work

There seem to be few other projects in the same direction:

  • The GnuCash mailing list(s) has a few results
  • The GnuCash Wiki's Wishlist lists the use through a web browser (as well as an iPhone-App) as "WONTFIX" (discussion from 2006/2007).
  • In 2016, mikedom722 asked on Reddit, whether anyone would be interested in a web interface (stating that he has one), but did not follow up.
  • In the same thread, superman279 presents his app Remote GnuCash, but the last commit is from 2017 and the website is down.
  • The GnuCash Wiki mentions two GnuCash mobile apps, one for iOS and one for Android. The one for Android seems to be discontinued (last commit 2020) the one for iOS still has new commits in 2022, but its purpose seems to be to export a CSV to be imported in GnuCash, rather then writing to the database directly.
  • There is alensiljak/gnucash-portfolio-webui on GitHub, but the README does not clearly state what it does. It seems to be only a exporter for certain reports. Anyway, it was archived in 2022, with last commit from 2018.

To conclude, all projects in this direction seem to be at most prototypes for playing around and even those are scarce. The GnuCash dev-team itself doesn't seem to be keen on providing a real mobile/web alternative, which is perfectly fine and understandable. I probably wouldn't either if I were them. Luckily, I am not!

License

Copyright © 2023 Joshua Bachmeier [email protected]

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the GNU General Public License for more details.

See LICENSE in this repository or https://www.gnu.org/licenses/ for a copy of the GNU General Public License.

The contents of the submodules EncryptedSession (GPLv3), Selectize (Apache License 2.0), Bootstrap (MIT License) and GnuCash (mutually-compatible set of licenses) as well as all dependencies are published under their own licenses by their respective authors.

gnucash-web's People

Contributors

freddo3000 avatar jayenashar avatar joshuabach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gnucash-web's Issues

Space before comma

In the account ledger, there is a superfluous space before the comma seperating multiple accounts in split transactions.

Screenshot 2022-01-04 at 11-55-22 Aktiva Liquide Mittel Geldbeutel — GnuCash Web

Favicon to small

Firefox for Android displays the favicon as a page icon in e.g. the "new tab" page, which looks pixelated. Probably use 32x32 instead of 16x16.

Docker - container access denied

I was eagerly awaiting the docker PR to be merged. Tested pulling an image yesterday. Result is:

xxxx:~/docker/gnucash$ docker compose up -d
[+] Running 1/1
 ✘ app Error                                                                                                                                                     0.9s
Error response from daemon: Head "https://ghcr.io/v2/joshuabach/gnucash-web/manifests/latest": denied

If I request https://ghcr.io/v2/joshuabach/gnucash-web/manifests/latest (same for main and latest) I get a response of:
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required"}]}

Google tells me this was a bug a few years ago, fixed by logging out of ghcr.io. Tried that, but it doesn't make any differnce.

Can you please check that the container is public and available for anonymous download?

Pipx installation of extras impossible due to spaces

What happens

Trying to install gnucash-web with the postgres extras, the following happened:

➜  ~ pipx install 'gnucash-web[PostgreSQL backend]' --pip-args 'Flask<2.3' --verbose
pipx >(setup:801): pipx version is 1.2.0
pipx >(setup:802): Default python interpreter is '/usr/bin/python'
Unable to parse package spec: gnucash-web[PostgreSQL backend]

Why it happens

The extras are defined here:

gnucash-web/setup.py

Lines 58 to 61 in 085a63d

extras_require={
'PostgreSQL backend': 'psycopg2',
'MySQL / MariaDB backend': 'mysql',
},

Pipx uses packaging.Requirements to parse the spec, see
the source. What a named requirement should look like is determined by PEP508:

identifier_end = letterOrDigit | (('-' | '_' | '.' )* letterOrDigit)
identifier    = letterOrDigit identifier_end*
name          = identifier
extras_list   = identifier (wsp* ',' wsp* identifier)*
extras        = '[' wsp* extras_list? wsp* ']'

name_req      = name wsp* extras? wsp* versionspec? wsp* quoted_marker?

In other words: spaces are not allowed in the extras part..

Fix

Just rename the extras requirements to postgres and mysql.

Testing

There are no unit, integration or end-to-end tests whatsover.

This is ungood.

How to run gnucash_web flask

I have to admit, I'm running GnucashDB (mariaDB) on a Raspi and would like to enable a web front end to the DB.
So I came along to this project.

To be fair, I have no clue about flask and would rather avoid to go too deep into flask setup and configuration.

So, how would i start the flask webserver after I installed it with pip install GnuCash-Web ?
I did the configuration in /etc/gnucash_web/config.py ... but have no clue how to start it w/o to learn flask setup

Hope somebody can provide an easy (end user) guide/hint

Add ability to switch between books

Glenn asked about this on the GnuCash-User Mailinglist.

Currently, the book to connect to is fixed in the config as the DATABASE_NAME, but it should not be difficult to make this dynamically selectable. A dropdown menu in the navbar that allows entry of new strings should suffice. The previously used books can be saved in a session cookie so that a user can easily switch between their books.

User management

Would like to manage users, which databases they can see and whether they can edit them or not.

Button color scheme ambiguous

Deposit / withdraw is colored green / red in the transaction form, but recycle / delete is colored green / red as well. Maybe this should be 4 different colors.

Add split transactions

Sometimes it is necessary / convenient to add transactions with more than two splits.

EncryptedSession uses deprecated Flask attribute

[2023-05-31 01:48:57,257] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
  File "/home/python/venv/lib/python3.11/site-packages/flask/app.py", line 2189, in wsgi_app
    ctx.push()
  File "/home/python/venv/lib/python3.11/site-packages/flask/ctx.py", line 377, in push
    self.session = session_interface.open_session(self.app, self.request)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/python/venv/lib/python3.11/site-packages/encrypted_session/__init__.py", line 33, in open_session
    session_cookie = request.cookies.get(app.session_cookie_name)
                                         ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Flask' object has no attribute 'session_cookie_name'

app.session_cookie_name was removed in Flask 2.3, so pinning Flask to <2.3 in setup.py is a sufficient workaround for now.

AttributeError in update_prices

Output of gnucash-web commodities update_prices on my uberspace on Wed, 28 Dec 2022 23:00:29 +0000:

New price for L4K3.DE: €15.58@2022-12-27 -> €15.31@2022-12-28
Traceback (most recent call last):
  File "/home/joshua/gnucash_web/ENV/bin/gnucash-web", line 8, in <module>
    sys.exit(cli())
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/core.py", line 1128, in __call__
    return self.main(*args, **kwargs)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/flask/cli.py", line 600, in main
    return super().main(*args, **kwargs)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/core.py", line 1395, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/flask/cli.py", line 444, in decorator
    return __ctx.invoke(f, *args, **kwargs)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/click/decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/joshua/gnucash_web/ENV/lib64/python3.9/site-packages/gnucash_web/commodities.py", line 117, in update_prices
    f"Price for {commodity.menmonic}:"
AttributeError: 'Commodity' object has no attribute 'menmonic'

Error when root account does not have a defined commodity

ERROR [gnucash_web] Exception on /book/accounts/ [GET]
Traceback (most recent call last):

  ... removed ...

  File "/home/python/venv/lib/python3.11/site-packages/gnucash_web/templates/forms.j2", line 26, in template
    step="{{ 1 / account.commodity.fraction }}"
    ^^^^^^^^^^^^^^^^^^^^^^^^^
jinja2.exceptions.UndefinedError: 'None' has no attribute 'fraction'

I'm using a SQLite GnuCash file. Somehow my root account does not have a defined commodity.

image

I haven't done anything strange with this book, so I don't know if this is normal or how to correct it.

Navbar at bottom of screen on mobile

On one-handed touch devices such as smartphones, it is usually more ergonomic to have the navbar at the bottom of the screen, where the thumb usually rests.

This is also the default for the URL bar on Firefox for Android.

Possible solution ist to do the following below a certain Bootstrap breakpoint:

  • Set navbar to class="fixed-bottom"
  • Invert .scrolled-up and .scrolled-down CSS rules
  • Remove top padding on body

Unexpected value for identifier

[2023-07-30 13:27:25,461] ERROR in app: Exception on /book/accounts/ [GET]
Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/flask/app.py", line 2529, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/flask/app.py", line 1825, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/flask/app.py", line 1823, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/gnucash_web/auth.py", line 62, in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/gnucash_web/book.py", line 96, in show_account
    return render_template(
           ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/flask/templating.py", line 147, in render_template
    return _render(app, template, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/flask/templating.py", line 130, in _render
    rv = template.render(context)
         ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/lib/python3.11/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/usr/lib/python3.11/site-packages/gnucash_web/templates/account.j2", line 2, in top-level template code
    {% from 'forms.j2' import transaction_form %}
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/gnucash_web/templates/base.j2", line 56, in top-level template code
    {% block content required %}{% endblock %}
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/gnucash_web/templates/account.j2", line 40, in block 'content'
    {% for account in account.children | sort(attribute='name') recursive %}
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/gnucash_web/templates/account.j2", line 57, in template
    {{ account.get_balance() | money(account.commodity) }}
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/gnucash_web/utils/jinja.py", line 62, in money
    if numbers.get_currency_symbol(commodity.mnemonic) != commodity.mnemonic:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/babel/numbers.py", line 152, in get_currency_symbol
    return Locale.parse(locale).currency_symbols.get(currency, currency)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/babel/core.py", line 317, in parse
    raise TypeError(f"Unexpected value for identifier: {identifier!r}")
TypeError: Unexpected value for identifier: None

List of recent transactions

In a seperate view, there could be a list of recent transactions (across all accounts), to get a quick overview of what happend recently. Combined with #14, this would make a great feature to quickly editi&repeat common transactions.

Transaction unfolding out of sync

When quickly mashing the fold/unfold button of transactions, the display state sometimes becomes out of sync: When the transaction is unfolded, the amount and contra accounts are displayed in the top left, but when it is folded, the buttons are displayed.

Contra-Account selection overflowing on mobile

On small screens, text from long account names in the contra-account selectize overflow on the right side, making them unreadable and extending the page to the right beyond the screen, adding horizontal scroll.

None of this is desired. Long account names should be ellipsed or (preferably) broken

Ability to unlock database

When the GnuCash Database is locked, the 423 page should include an option to override and delete the lock.

Improve contra account picker

Possible solutions include:

  • Set default account by config or to 'Imbalance-EUR'
  • Sort accounts by MFU or LRU
  • Fuzzy auto completion

Firefox on Android does not show form validation errors

When entering invalid data in the add_transaction form on a mobile device (tested on Mozilla/5.0 (Android 10; Mobile; rv:94.0) Gecko/94.0 Firefox/94.0), form validation error tooltips are not shown when hitting: "Add Transaction". Simply nothing happens.

Ledger pagination

Large accounts load a bit slow, show there should probably be some form of pagination / infinite scroll to adress that.

Improve error handling on invalid transactions

Deployed in Docker running on Ubuntu Server 20.04 connected to Postgres 15 using the sample docker-compose in the repo. When I try to navigate to /book/accounts/Assets/Current+Assets/Checking+Account I get an "Internal Server Error", checking the docker logs I see the below error.

app_1  | [2023-12-13 05:42:29,098] ERROR in app: Exception on /book/accounts/Assets/Current+Assets/Checking+Account [GET]
app_1  | Traceback (most recent call last):
app_1  |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 2529, in wsgi_app
app_1  |     response = self.full_dispatch_request()
app_1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 1825, in full_dispatch_request
app_1  |     rv = self.handle_user_exception(e)
app_1  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 1823, in full_dispatch_request
app_1  |     rv = self.dispatch_request()
app_1  |          ^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 1799, in dispatch_request
app_1  |     return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
app_1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/srv/gnucash_web/auth.py", line 62, in inner
app_1  |     return func(*args, **kwargs)
app_1  |            ^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/srv/gnucash_web/book.py", line 94, in show_account
app_1  |     return render_template(
app_1  |            ^^^^^^^^^^^^^^^^
app_1  |   File "/usr/local/lib/python3.11/site-packages/flask/templating.py", line 147, in render_template
app_1  |     return _render(app, template, context)
app_1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/usr/local/lib/python3.11/site-packages/flask/templating.py", line 130, in _render
app_1  |     rv = template.render(context)
app_1  |          ^^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/usr/local/lib/python3.11/site-packages/jinja2/environment.py", line 1301, in render
app_1  |     self.environment.handle_exception()
app_1  |   File "/usr/local/lib/python3.11/site-packages/jinja2/environment.py", line 936, in handle_exception
app_1  |     raise rewrite_traceback_stack(source=source)
app_1  |   File "/srv/gnucash_web/templates/account.j2", line 2, in top-level template code
app_1  |     {% from 'forms.j2' import transaction_form %}
app_1  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/srv/gnucash_web/templates/base.j2", line 56, in top-level template code
app_1  |     {% block content required %}{% endblock %}
app_1  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/srv/gnucash_web/templates/account.j2", line 77, in block 'content'
app_1  |     {% include 'transaction.j2' %}
app_1  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
app_1  |   File "/srv/gnucash_web/templates/transaction.j2", line 100, in top-level template code
app_1  |     data-bs-transaction-sign="{{ split.value / split.value|abs  }}"
app_1  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
app_1  | decimal.InvalidOperation: [<class 'decimal.DivisionUndefined'>]

Firefox Android quickly forgets login

On Firefox for Android (and possibly on other browsers), login expires pretty quickly, while on Firefox for Linux, it does not seem to expire at all.

Probably this has something todo with us specifieng no cookie expiry and thus relying on the browser to define the end of a session.

EncryptedSession is unmaintained

We use SaintFlipper/EncryptedSession to store sensitive information (DB password) as a cookie in the users browser.

However, the project seems unmaintained, which is not ideal for a secrurity-relevant dependency.

I should either "audit" the project myself or find a different solution.

Account filter

The Account view is a bit cluddered. There should be an option to filter acconuts by certain criteria.

Especially, hidden acconuts should be hidden by default (duh).

How to store GnuCash database in SQL

We should add a quick explanation to the README on how to either create an empty book in an SQL database or how to migrate an existing GnuCash-XML-File into an SQL-server using the desktop client.

Remove GnuCash submodule

Including the whole GnuCash code repository as a submodule just to get a few icons is a bit overkill.

[BUG] Compatibility with Flask >= 2.3.0

Hi,

When I try to access the web server at :8080, the browser returns a 500 error and I get the following message from the uWSGI shell:

ERROR in app: Exception on / [GET]
Traceback (most recent call last):
  File "/root/.venv/lib/python3.11/site-packages/flask/app.py", line 2189, in wsgi_app
    ctx.push()
  File "/root/.venv/lib/python3.11/site-packages/flask/ctx.py", line 377, in push
    self.session = session_interface.open_session(self.app, self.request)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.venv/lib/python3.11/site-packages/encrypted_session/__init__.py", line 33, in open_session
    session_cookie = request.cookies.get(app.session_cookie_name)
                                         ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Flask' object has no attribute 'session_cookie_name'

Looking at the version release notes for Flask, I see

as of 2.3.0 The session_cookie_name, send_file_max_age_default, use_x_sendfile, propagate_exceptions, and templates_auto_reload properties on app are removed.

Running the following to downgrade to an older Flask (pre-2.3.0) was able to resolve this. Is this a known issue, or is there maybe something specific to my installation that is causing this error?

pip uninstall flask
pip install --force-reinstall flask==2.2.5

Long info on how I have installed and configured the app:

when I try to install the app, pip install gnucash-web fails with this error message:

error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.
    
    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.
    
    If you wish to install a non-Debian packaged Python application,
    it may be easiest to use pipx install xyz, which will manage a
    virtual environment for you. Make sure you have pipx installed.
    
    See /usr/share/doc/python3.11/README.venv for more information.

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.

Installing into a venv works, so I did that instead:

python3 -m venv .venv
source .venv/bin/activate
pip install GnuCash-Web
pip install uwsgi

I created a config file at etc/gnucash_web_config.py:

import logging

# A 32-bit-key used e.g. to encrypt the session cookie or for other cryptographic operations
SECRET_KEY = '<32 bit key>'

# Python standard library log level
LOG_LEVEL = logging.WARN

# Supported values: 'sqlite', 'mysql' or 'postgres'
DB_DRIVER = 'sqlite'

# Host name of the database (ignored for DB_DRIVER = 'sqlite')
DB_HOST = 'database.example.org'

# Name of the Database on the host (for DB_DRIVER = 'sqlite', this is the 'path/to/db.sqlite')
DB_NAME = '/mnt/gnucash/FY_2023.sqlite'

# Supported values: None, 'passthrough'. See below for details.
AUTH_MECHANISM = None

# The maximum number of transactions per page in the ledger
TRANSACTION_PAGE_LENGTH = 25

# Name of the account to be preselected when creating new transactions (optional)
#PRESELECTED_CONTRA_ACCOUNT = 'Example:Account'

Then I can start the application:

~# uwsgi --ini /root/.venv/bin/gnucash.ini
[uWSGI] getting INI configuration from /root/.venv/bin/gnucash.ini
*** Starting uWSGI 2.0.22 (64bit) on [Sat Sep  9 22:25:22 2023] ***
compiled with version: 12.3.0 on 09 September 2023 22:03:45
os: Linux-6.2.16-3-pve #1 SMP PREEMPT_DYNAMIC PVE 6.2.16-3 (2023-06-17T05:58Z)
nodename: gnuCash
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /root
writing pidfile to gnucash_web.pid
detected binary path: /root/.venv/bin/uwsgi
your processes number limit is 189765
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address :8080 fd 3
Python version: 3.11.4 (main, Jun  9 2023, 07:59:55) [GCC 12.3.0]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x7fdbce161018
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 145808 bytes (142 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x7fdbce161018 pid: 5887 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 5887)
spawned uWSGI worker 1 (pid: 5890, cores: 1)

[Wishlist] Add support for transaction linked documents

Gnucash has support for associating external files with transactions, which is useful for scanning receipts, invoices, and other records. The problem is that users can only do so when they have access to a computer, and requires a consistent file structure or separate webserver.

It is on just that separate webserver part where I think this project could be used, allowing the user to upload files while on the run which can be accessed at as something such as http://gnucash-web.etc/files/myreceipt.png, and implementing this as an option when creating a transaction. This would allow users to digitize receipts using their phone and unless they have a reason to hold on to the physical receipt, discard it.

[SUPPORT] Database 'sqlite:///db/gnucash.sqlite' does not exist

I'm several hours into trying to set this up, but am now stuck at an error I can't figure out. The app is saying it cannot find the database file, and I do not understand why. I have the database location correctly defined in the config file, and I can open the database file successfully on desktop gnuCash. Any help would be appreciated!

Error text

2023-09-09 23:46:07,678] ERROR in app: Exception on /book/accounts/ [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 2529, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1825, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1823, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1799, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/gnucash_web/auth.py", line 62, in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/gnucash_web/book.py", line 79, in show_account
    with open_book(
  File "/usr/lib/python3.11/contextlib.py", line 137, in __enter__
    return next(self.gen)
           ^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/gnucash_web/utils/gnucash.py", line 73, in open_book
    raise e
  File "/usr/local/lib/python3.11/dist-packages/gnucash_web/utils/gnucash.py", line 66, in open_book
    with piecash.open_book(*args, **kwargs) as book:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/piecash/core/session.py", line 409, in open_book
    raise GnucashException(
piecash._common.GnucashException: Database 'sqlite:///db/gnucash.sqlite' does not exist (please use create_book to create GnuCash books from scratch). If you want to bypass this existence check, use the argument check_exists=False.
[pid: 445|app: 0|req: 1/1] 192.168.1.23 () {38 vars in 780 bytes} [Sat Sep  9 23:46:07 2023] GET /book/accounts/ => generated 265 bytes in 8 msecs (HTTP/1.1 500) 2 headers in 99 bytes (1 switches on core 0)

Config File

:~# cat /etc/gnucash_web/config.py
import logging

# A 32-bit-key used e.g. to encrypt the session cookie or for other cryptographic operations
SECRET_KEY = '<32 bit key>'

# Python standard library log level
LOG_LEVEL = logging.WARN

# Supported values: 'sqlite', 'mysql' or 'postgres'
DB_DRIVER = 'sqlite'

# Host name of the database (ignored for DB_DRIVER = 'sqlite')
DB_HOST = 'database.example.org'

# Name of the Database on the host (for DB_DRIVER = 'sqlite', this is the 'path/to/db.sqlite')
DB_NAME = '/mnt/gnucash/FY_2023.sqlite'

# Supported values: None, 'passthrough'. See below for details.
AUTH_MECHANISM = None

# The maximum number of transactions per page in the ledger
TRANSACTION_PAGE_LENGTH = 25

# Name of the account to be preselected when creating new transactions (optional)
#PRESELECTED_CONTRA_ACCOUNT = 'Example:Account'

Database location

:~# ls -lh /mnt/gnucash/              
total 2.6M
-rwxrw-r-- 1 1005 users 5.8M Sep  9 23:04 FY_2023.sqlite

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.