Open strombringer opened 5 months ago
Ok, I think that's a problem with our compose examples for multi-tree. Please try adding entrypoint: []
to the grampsweb
service.
Thank you! With the entrypoint
change I'm able to start the containers.
I'm still a bit lost on how to continue from here. Opening the service in the browser gives me the login form, but I don't have a user yet. The user registration doesn't work and from the documentation I know that it can't work in multi-tree mode and I should disable it. The "first-run wizard" that's mentioned in the documentation is not shown.
https://www.grampsweb.org/multi-tree/ says that users are tied to trees. If I want to create a tree, it is recommended to do that via the web api. But to do that, I need a JWT, which I get by authorizing as a user. That's a chicken and egg issue for me :D
It should show the first run wizard. Please check the container logs.
These are the logs of a fresh gramps instance that I started and opened in the browser:
[2024-04-21 20:13:10 +0000] [7] [INFO] Starting gunicorn 21.2.0
[2024-04-21 20:13:10 +0000] [7] [INFO] Listening at: http://0.0.0.0:5000 (7)
[2024-04-21 20:13:10 +0000] [7] [INFO] Using worker: sync
[2024-04-21 20:13:10 +0000] [8] [INFO] Booting worker with pid: 8
[2024-04-21 20:13:10 +0000] [9] [INFO] Booting worker with pid: 9
[2024-04-21 20:13:11 +0000] [10] [INFO] Booting worker with pid: 10
[2024-04-21 20:13:11 +0000] [11] [INFO] Booting worker with pid: 11
[2024-04-21 20:13:11 +0000] [12] [INFO] Booting worker with pid: 12
[2024-04-21 20:13:11 +0000] [13] [INFO] Booting worker with pid: 13
[2024-04-21 20:13:11 +0000] [14] [INFO] Booting worker with pid: 14
[2024-04-21 20:13:11 +0000] [15] [INFO] Booting worker with pid: 15
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
(gunicorn:9): Gtk-CRITICAL **: 20:13:19.926: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
(gunicorn:12): Gtk-CRITICAL **: 20:13:19.928: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
(gunicorn:14): Gtk-CRITICAL **: 20:13:19.941: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:10): Gtk-CRITICAL **: 20:13:19.954: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
(gunicorn:15): Gtk-CRITICAL **: 20:13:19.961: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:8): Gtk-CRITICAL **: 20:13:19.988: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:13): Gtk-CRITICAL **: 20:13:19.994: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:11): Gtk-CRITICAL **: 20:13:20.039: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
[2024-04-21 20:14:10 +0000] [11] [ERROR] Error handling request /api/token/create_owner/
Traceback (most recent call last):
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/base.py", line 1970, in _exec_single_context
self.dialect.do_execute(
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/default.py", line 924, in do_execute
cursor.execute(statement, parameters)
sqlite3.OperationalError: no such table: users
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/python3.11/dist-packages/gunicorn/workers/sync.py", line 135, in handle
self.handle_request(listener, req, client, addr)
File "/usr/local/lib/python3.11/dist-packages/gunicorn/workers/sync.py", line 178, in handle_request
respiter = self.wsgi(environ, resp.start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1488, in __call__
return self.wsgi_app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1466, in wsgi_app
response = self.handle_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1463, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 872, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 870, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 855, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask/views.py", line 110, in view
return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask/views.py", line 191, in dispatch_request
return current_app.ensure_sync(meth)(**kwargs) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/flask_limiter/extension.py", line 1299, in __inner
return cast(R, flask.current_app.ensure_sync(obj)(*a, **k))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/webargs/core.py", line 649, in wrapper
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/api/resources/token.py", line 161, in post
if get_all_user_details(
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/auth/__init__.py", line 231, in get_all_user_details
users = query.all()
^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/orm/query.py", line 2673, in all
return self._iter().all() # type: ignore
^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/orm/query.py", line 2827, in _iter
result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/orm/session.py", line 2306, in execute
return self._execute_internal(
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/orm/session.py", line 2191, in _execute_internal
result: Result[Any] = compile_state_cls.orm_execute_statement(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/orm/context.py", line 293, in orm_execute_statement
result = conn.execute(
^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/base.py", line 1421, in execute
return meth(
^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/sql/elements.py", line 514, in _execute_on_connection
return connection._execute_clauseelement(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/base.py", line 1643, in _execute_clauseelement
ret = self._execute_context(
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/base.py", line 1849, in _execute_context
return self._exec_single_context(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/base.py", line 1989, in _exec_single_context
self._handle_dbapi_exception(
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/base.py", line 2356, in _handle_dbapi_exception
raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/base.py", line 1970, in _exec_single_context
self.dialect.do_execute(
File "/usr/local/lib/python3.11/dist-packages/sqlalchemy/engine/default.py", line 924, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users
[SQL: SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.fullname AS users_fullname, users.pwhash AS users_pwhash, users.role AS users_role, users.tree AS users_tree
FROM users]
(Background on this error at: https://sqlalche.me/e/20/e3q8)
So it seems like the database is not created correctly.
Did you specify USER_DB_URI
? If not, please try that. If yes, please run
docker-compose run grampsweb python3 -m gramps_webapi --config /app/config/config.cfg user migrate
I had not specified USER_DB_URI
, as it was not needed for the single-tree installation.
I now added this to the compose.yml: GRAMPSWEB_USER_DB_URI: "sqlite:////app/users/users.sqlite"
This is the default setting anyway, right? At least it did not seem to have an effect.
I then ran
docker-compose run grampsweb python3 -m gramps_webapi --config /app/config/config.cfg user migrate
and got this:
[+] Running 1/0
⠿ Container grampsweb_redis Running 0.0s
/usr/local/lib/python3.11/dist-packages/gramps/plugins/tool/check.py:51: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
from gi.repository import Gtk
(__main__.py:1): Gtk-CRITICAL **: 15:30:13.940: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
FAILED: No config file 'alembic.ini' found, or file has no '[alembic]' section
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/__main__.py", line 234, in <module>
cli(
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1157, in __call__
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1078, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1688, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1688, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/decorators.py", line 33, in new_func
return f(get_current_context(), *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/__main__.py", line 118, in migrate_db
subprocess.run(cmd, env=env, check=True)
File "/usr/lib/python3.11/subprocess.py", line 571, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['/usr/bin/python3', '-m', 'alembic', 'upgrade', 'head']' returned non-zero exit status 255.
I tried the command with and without the GRAMPSWEB_USER_DB_URI
setting. both returned the same result. I also cleared the volumes between each try, just to avoid any strange side effects.
Next try:
docker-compose run --entrypoint="" --rm -w /app/src grampsweb python3 -m gramps_webapi --config /app/config/config.cfg user migrate
Thanks for bearing with me :sweat_smile:
I'm happy to work through this with your help 😄
The last command worked and the first run wizard is shown in the browser. But when I enter my data and submit, I get a "Wrong username or password" error message: SMTP data left empty, no tree to import.
I don't see any error messages in either of the three containers logs. When I try to submit again, I get the message "Users already exists" (I assume it should be "User"). Username is in the format "firstname-lastname" and password is 48 characters [a-zA-Z0-9], in case it makes a difference.
Going back to the root in the browser, I'm now presented with the login form again. But when trying to login, it says "Error: Wrong username or password"
Ha, that's weird because it means creating the user worked, but fetching a token didn't work, and the Javascript functions for both operations use the same variables for the username and password.
If you can start over and monitor the API calls in the browser dev console, that would be useful. Perhaps it's some weird special character issue, but I wouldn't see why...
These are requests for loading the page, entering the user information and sending it (with placeholder data). Everything on a completely fresh installation.
I saved the requests as a HAR file. Github doesn't allow attaching it here, so I uploaded it to Dropbox: (removed, because no longer needed)
Maybe that's helpful for you 😄
For completeness sake:
This is the part that's changed from the default compose.yml file:
environment:
GRAMPSWEB_SECRET_KEY: "mysecret"
GRAMPSWEB_TREE: "*"
GRAMPSWEB_MEDIA_PREFIX_TREE: "True"
...
entrypoint: []
And I executed this command of yours:
docker-compose run --entrypoint="" --rm -w /app/src grampsweb python3 -m gramps_webapi --config /app/config/config.cfg user migrate
I just realized I didn't mention this before: I tried the default compose.yml for a single-tree setup and there everything worked out of the box, with the same username and password that I tried for the multi-tree setup. So I don't think it's a special character issue.
Ok I think I know what's happening.
In the multi-tree setup, the first run wizard creates a site admin, not a tree owner. But the site admin does not have a tree. You would first have to create a tree, or to assign the admin to a specific tree. In a multi-tenant setup, the site admin might anyway just be a service account that is used to create new trees and manage trees, without being itself associated with a tree.
Of course, the UI for that doesn't make sense right now and needs to be changed - I'll open an issue in the frontend repo.
Your next step is to create a new tree via the API by posting to /api/trees/
. It will return a tree ID. You can then go to https://yourgrampsweb/firstrun/<treeid>
to get the first run wizard for the tree owner.
(Thanks by the way for the detailed logs, very helpful!)
For posting to /api/trees
, I need a JWT. Otherwise I get a 401 error (as it should be). But when I try POSTing to /api/token
with the username and password from the first run wizard, I get a 403 error.
Do I need to copy the token from the web session, for creating the first tree? I expected that the call to api/token
should work in any case.
Right :man_facepalming: I take that back:
Ok I think I know what's happening.
Your logs showed you got a 403 permission denied when trying to fetch a token with username/password, which should work regardless of tree. I will try to reproduce this later, there must be a bug somewhere.
@strombringer did you manage to create a tree via the api endpoint?
@Corepex no, I didn't. After the last test in April, I switched to single-tree mode and the setup wizard worked for that. I'll try again when a bugfix is available, though it's not high priority for me.
FYI, I am running a multi tree setup and creating new trees via the API all the time, so there could be a bug, but it's not obvious to me what it is as I'm not affected by it.
I'm trying to setup a Multi-Tree installation with Docker and followed the instructions at https://www.grampsweb.org/Deployment/, but starting the grampsweb container fails with this error message:
I'm using the docker-compose file linked in the documentation, with minor changes: Port, SECRET_KEY, TREE and MEDIA_PREFIX_TREE are changed
My understanding from the documentation is,
https://myhost:13000
to setup the server administrator accountIs my understanding wrong and I overlooked something? Where should I have setup the tree, that's mentioned in the error message?
Thanks in advance for the support!