gramps-webapi 3.22.1__tar.gz → 3.22.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/PKG-INFO +1 -1
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/_version.py +1 -1
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/media.py +1 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/trees.py +1 -1
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/util.py +1 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/auth/__init__.py +45 -42
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/auth/const.py +9 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi.egg-info/PKG-INFO +1 -1
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_oidc.py +74 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.devcontainer/Dockerfile +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.devcontainer/devcontainer.json +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.devcontainer/docker-compose.yml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.dockerignore +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.editorconfig +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.flake8 +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.github/workflows/base-image.yml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.github/workflows/image.yml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.github/workflows/pypi.yml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.github/workflows/test.yml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.gitignore +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.pre-commit-config.yaml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.pylintrc +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.vscode/extensions.json +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.vscode/launch.json +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.vscode/settings.json +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/.vscode/tasks.json +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/CLAUDE.md +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/CODE_OF_CONDUCT.md +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/CONTRIBUTING.md +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/Dockerfile +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/Dockerfile.base +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/LICENSE +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/MANIFEST.in +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/README.md +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/ROADMAP.md +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic.ini +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/README +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/env.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/script.py.mako +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/2082445b0769_add_oidc_accounts_table_for_secure_.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/22c8d1fba959_add_trees_enabled.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/66e56620891a_add_trees_table.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/6d8f3cb50b71_add_persistent_access_tokens_table.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/84960b7d968c_use_bigint_for_quota_media.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/a8e57fe0d82e_add_columns_for_ai_quota.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/b0582f54029c_use_bigint_for_usage_media.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/b2c3d4e5f6a7_add_tree_config_column.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/c1d2e3f4a5b6_merge_task_tree_and_tree_config.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/c89728e71264_.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/d4e9a1c7b3f2_drop_unique_constraint_on_user_email.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/e176543c72a8_add_tree_column_to_user.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/e5e738d09fa7_added_configuration_table.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/f3a1c8e92b47_add_task_tree_table.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/docker-entrypoint.sh +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/__init__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/__main__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/__init__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/auth.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/blueprint.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/cache.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/check.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/deprecations.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/dna.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/emails.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/export.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/file.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/html.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/image.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/llm/__init__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/llm/agent.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/llm/deps.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/llm/tools.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/media_importer.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/people_families_cache.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/ratelimiter.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/report.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/__init__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/access_tokens.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/anniversaries.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/base.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/bookmarks.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/chat.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/citations.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/config.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/db_backend.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/delete.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/dna.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/emit.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/events.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/export_media.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/exporters.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/face_detection.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/facts.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/families.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/file.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/filters.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/history.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/holidays.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/import_media.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/importers.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/living.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/match.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/media.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/merge.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/metadata.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/name_formats.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/name_groups.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/notes.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/object_query.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/objects.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/ocr.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/oidc.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/people.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/places.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/relations.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/reports.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/repositories.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/restore.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/schemas.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/search.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/sort.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/sources.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/tags.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/tasks.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/timeline.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/token.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/transactions.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/translations.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/types.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/user.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/util.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/verify.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/resources/ydna.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/s3.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/search/__init__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/search/embeddings.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/search/indexer.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/search/metadata.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/search/text.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/search/text_semantic.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/tasks.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/api/telemetry.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/app.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/auth/oidc.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/auth/oidc_helpers.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/auth/passwords.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/auth/sql_guid.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/celery.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/config.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/const.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/data/empty_gramps_auth.cfg +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/data/example_gramps_auth.cfg +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/data/face_detection_yunet_2023mar.onnx +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/data/test_auth.cfg +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/dbloader.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/dbmanager.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/logging_utils.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/profiler.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/sentry.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/static/index.html +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/templates/confirmation.html +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/templates/reset_password.html +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/templates/reset_password_base.html +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/templates/reset_password_error.html +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/translogger.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/types.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/undodb.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/util/__init__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/util/celery.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/verify_lib.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi/wsgi.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi.egg-info/SOURCES.txt +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi.egg-info/dependency_links.txt +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi.egg-info/requires.txt +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/gramps_webapi.egg-info/top_level.txt +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/mypy.ini +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/pyproject.toml +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/requirements-dev.txt +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/scripts/s3_rename.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/scripts/start_dev_container.sh +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/semantic_index.txt +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/setup.cfg +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/setup.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/__init__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_check.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_cli.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_db.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_delete.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_deprecations.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_dna_match_parser.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_embeddings.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/__init__.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/checks.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_access_tokens.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_anniversaries_ics.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_bookmarks.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_chat.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_citations.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_config.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_db_handle.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_delete.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_dna.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_events.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_exporters.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_facts.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_families.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_file.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_filters.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_history.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_holidays.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_import_media.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_importers.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_living.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_media.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_media_archive.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_merge.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_metadata.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_name_formats.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_name_groups.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_notes.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_object_query.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_object_query_where_tree.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_ocr.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_paging_sort.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_people.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_people_query.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_places.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_post.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_profiler.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_put.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_ready.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_relations.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_repair.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_reports.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_repositories.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_restore.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_s3.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_search.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_sources.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_tags.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_tasks.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_timelines.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_token.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_transactions.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_translations.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_treeless_admin.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_trees.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_types.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_upload.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_user.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_verify.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/test_ydna.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_endpoints/util.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_file.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_image.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_import_util.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_jwt.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_limiter.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_llm_errors.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_llm_tools.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_logging_utils.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_map_tile.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_media_importer.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_media_prefix_tree.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_migrate_grampsdb.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_object_query_parsing.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_oidc_auth.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_openapi_operation_ids.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_password.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_private_proxy.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_s3.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_search_metadata.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_sentry.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_sort_raw_data.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_sqlauth.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_task_error.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_tasks.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_telemetry.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_text.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_undodb.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_util.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_verify_lib.py +0 -0
- {gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/tests/test_version.py +0 -0
|
@@ -390,6 +390,7 @@ def check_quota_media(
|
|
|
390
390
|
usage_dict = get_tree_usage(tree)
|
|
391
391
|
assert usage_dict is not None, "Unexpected error while looking up usage data."
|
|
392
392
|
usage = usage_dict["usage_media"]
|
|
393
|
+
assert usage is not None, "Unexpected error while looking up usage data."
|
|
393
394
|
quota = usage_dict.get("quota_media")
|
|
394
395
|
if quota is None:
|
|
395
396
|
return
|
|
@@ -77,7 +77,7 @@ from .schemas import TreeConfigSchema, TreeSchema
|
|
|
77
77
|
TREE_ID_REGEX = re.compile(r"^[a-zA-Z0-9_-]+$")
|
|
78
78
|
|
|
79
79
|
|
|
80
|
-
def get_tree_details(tree_id: str) -> Dict[str, str | bool | int]:
|
|
80
|
+
def get_tree_details(tree_id: str) -> Dict[str, str | bool | int | None]:
|
|
81
81
|
"""Get details about a tree."""
|
|
82
82
|
try:
|
|
83
83
|
dbmgr = WebDbManager(
|
|
@@ -747,6 +747,7 @@ def check_quota_people(
|
|
|
747
747
|
usage_dict = get_tree_usage(tree)
|
|
748
748
|
assert usage_dict is not None, "Unexpected error while looking up usage data."
|
|
749
749
|
usage = usage_dict["usage_people"]
|
|
750
|
+
assert usage is not None, "Unexpected error while looking up usage data."
|
|
750
751
|
quota = usage_dict.get("quota_people")
|
|
751
752
|
if quota is None:
|
|
752
753
|
return
|
|
@@ -30,7 +30,7 @@ import sqlalchemy as sa
|
|
|
30
30
|
from flask import current_app
|
|
31
31
|
from flask_sqlalchemy import SQLAlchemy
|
|
32
32
|
from sqlalchemy.exc import IntegrityError, StatementError
|
|
33
|
-
from sqlalchemy.orm import mapped_column
|
|
33
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
34
34
|
from sqlalchemy.sql.functions import coalesce
|
|
35
35
|
|
|
36
36
|
|
|
@@ -483,7 +483,7 @@ def config_get(key: str) -> Optional[str]:
|
|
|
483
483
|
return config.value
|
|
484
484
|
|
|
485
485
|
|
|
486
|
-
def config_get_all() -> Dict[str, str]:
|
|
486
|
+
def config_get_all() -> Dict[str, str | None]:
|
|
487
487
|
"""Get all config items as dictionary."""
|
|
488
488
|
query = user_db.session.query(Config) # pylint: disable=no-member
|
|
489
489
|
configs = query.all()
|
|
@@ -513,7 +513,7 @@ def config_delete(key: str) -> None:
|
|
|
513
513
|
user_db.session.commit() # pylint: disable=no-member
|
|
514
514
|
|
|
515
515
|
|
|
516
|
-
def get_tree_usage(tree: str) -> Optional[dict[str, int]]:
|
|
516
|
+
def get_tree_usage(tree: str) -> Optional[dict[str, int | None]]:
|
|
517
517
|
"""Get tree usage info."""
|
|
518
518
|
query = user_db.session.query(Tree) # pylint: disable=no-member
|
|
519
519
|
tree_obj: Tree = query.filter_by(id=tree).scalar()
|
|
@@ -529,7 +529,7 @@ def get_tree_usage(tree: str) -> Optional[dict[str, int]]:
|
|
|
529
529
|
}
|
|
530
530
|
|
|
531
531
|
|
|
532
|
-
def get_tree_permissions(tree: str) -> Optional[dict[str, int]]:
|
|
532
|
+
def get_tree_permissions(tree: str) -> Optional[dict[str, int | None]]:
|
|
533
533
|
"""Get tree permissions."""
|
|
534
534
|
query = user_db.session.query(Tree) # pylint: disable=no-member
|
|
535
535
|
tree_obj: Tree = query.filter_by(id=tree).scalar()
|
|
@@ -667,13 +667,14 @@ class User(user_db.Model): # type: ignore
|
|
|
667
667
|
|
|
668
668
|
__tablename__ = "users"
|
|
669
669
|
|
|
670
|
-
id = mapped_column(GUID, primary_key=True)
|
|
671
|
-
name = mapped_column(sa.String, unique=True, nullable=False)
|
|
672
|
-
email = mapped_column(sa.String, index=True)
|
|
673
|
-
fullname = mapped_column(sa.String)
|
|
674
|
-
pwhash = mapped_column(sa.String, nullable=False)
|
|
675
|
-
|
|
676
|
-
|
|
670
|
+
id: Mapped[uuid.UUID] = mapped_column(GUID, primary_key=True)
|
|
671
|
+
name: Mapped[str] = mapped_column(sa.String, unique=True, nullable=False)
|
|
672
|
+
email: Mapped[str | None] = mapped_column(sa.String, index=True)
|
|
673
|
+
fullname: Mapped[str | None] = mapped_column(sa.String)
|
|
674
|
+
pwhash: Mapped[str] = mapped_column(sa.String, nullable=False)
|
|
675
|
+
# nullable in the schema, but always set via the default
|
|
676
|
+
role: Mapped[int] = mapped_column(sa.Integer, nullable=True, default=0)
|
|
677
|
+
tree: Mapped[str | None] = mapped_column(sa.String, index=True)
|
|
677
678
|
|
|
678
679
|
def __repr__(self):
|
|
679
680
|
"""Return string representation of instance."""
|
|
@@ -685,19 +686,19 @@ class AccessToken(user_db.Model): # type: ignore
|
|
|
685
686
|
|
|
686
687
|
__tablename__ = "access_tokens"
|
|
687
688
|
|
|
688
|
-
id = mapped_column(sa.Integer, primary_key=True, autoincrement=True)
|
|
689
|
-
user_id = mapped_column(
|
|
689
|
+
id: Mapped[int] = mapped_column(sa.Integer, primary_key=True, autoincrement=True)
|
|
690
|
+
user_id: Mapped[uuid.UUID] = mapped_column(
|
|
690
691
|
GUID, sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True
|
|
691
692
|
)
|
|
692
|
-
scope = mapped_column(sa.String(64), nullable=False, index=True)
|
|
693
|
-
token_hash = mapped_column(sa.String(64), nullable=True)
|
|
694
|
-
created_at = mapped_column(
|
|
693
|
+
scope: Mapped[str] = mapped_column(sa.String(64), nullable=False, index=True)
|
|
694
|
+
token_hash: Mapped[str | None] = mapped_column(sa.String(64), nullable=True)
|
|
695
|
+
created_at: Mapped[datetime] = mapped_column(
|
|
695
696
|
sa.DateTime, nullable=False, server_default=sa.func.now()
|
|
696
697
|
)
|
|
697
|
-
updated_at = mapped_column(
|
|
698
|
+
updated_at: Mapped[datetime] = mapped_column(
|
|
698
699
|
sa.DateTime, nullable=False, server_default=sa.func.now()
|
|
699
700
|
)
|
|
700
|
-
revoked_at = mapped_column(sa.DateTime, nullable=True)
|
|
701
|
+
revoked_at: Mapped[datetime | None] = mapped_column(sa.DateTime, nullable=True)
|
|
701
702
|
|
|
702
703
|
__table_args__ = (
|
|
703
704
|
sa.UniqueConstraint("user_id", "scope", name="uq_access_tokens_user_scope"),
|
|
@@ -717,9 +718,9 @@ class Config(user_db.Model): # type: ignore
|
|
|
717
718
|
|
|
718
719
|
__tablename__ = "configuration"
|
|
719
720
|
|
|
720
|
-
id = mapped_column(sa.Integer, primary_key=True)
|
|
721
|
-
key = mapped_column(sa.String, unique=True, nullable=False)
|
|
722
|
-
value = mapped_column(sa.String)
|
|
721
|
+
id: Mapped[int] = mapped_column(sa.Integer, primary_key=True)
|
|
722
|
+
key: Mapped[str] = mapped_column(sa.String, unique=True, nullable=False)
|
|
723
|
+
value: Mapped[str | None] = mapped_column(sa.String)
|
|
723
724
|
|
|
724
725
|
def __repr__(self):
|
|
725
726
|
"""Return string representation of instance."""
|
|
@@ -731,16 +732,18 @@ class Tree(user_db.Model): # type: ignore
|
|
|
731
732
|
|
|
732
733
|
__tablename__ = "trees"
|
|
733
734
|
|
|
734
|
-
id = mapped_column(sa.String, primary_key=True)
|
|
735
|
-
quota_media = mapped_column(sa.BigInteger)
|
|
736
|
-
quota_people = mapped_column(sa.Integer)
|
|
737
|
-
quota_ai = mapped_column(sa.Integer)
|
|
738
|
-
usage_media = mapped_column(sa.BigInteger)
|
|
739
|
-
usage_people = mapped_column(sa.Integer)
|
|
740
|
-
usage_ai = mapped_column(sa.Integer)
|
|
741
|
-
min_role_ai = mapped_column(sa.Integer)
|
|
742
|
-
enabled = mapped_column(
|
|
743
|
-
|
|
735
|
+
id: Mapped[str] = mapped_column(sa.String, primary_key=True)
|
|
736
|
+
quota_media: Mapped[int | None] = mapped_column(sa.BigInteger)
|
|
737
|
+
quota_people: Mapped[int | None] = mapped_column(sa.Integer)
|
|
738
|
+
quota_ai: Mapped[int | None] = mapped_column(sa.Integer)
|
|
739
|
+
usage_media: Mapped[int | None] = mapped_column(sa.BigInteger)
|
|
740
|
+
usage_people: Mapped[int | None] = mapped_column(sa.Integer)
|
|
741
|
+
usage_ai: Mapped[int | None] = mapped_column(sa.Integer)
|
|
742
|
+
min_role_ai: Mapped[int | None] = mapped_column(sa.Integer)
|
|
743
|
+
enabled: Mapped[int | None] = mapped_column(
|
|
744
|
+
sa.Integer, default=1, server_default="1"
|
|
745
|
+
)
|
|
746
|
+
config: Mapped[dict | None] = mapped_column(sa.JSON, nullable=True)
|
|
744
747
|
|
|
745
748
|
def __repr__(self):
|
|
746
749
|
"""Return string representation of instance."""
|
|
@@ -752,14 +755,14 @@ class OIDCAccount(user_db.Model): # type: ignore
|
|
|
752
755
|
|
|
753
756
|
__tablename__ = "oidc_accounts"
|
|
754
757
|
|
|
755
|
-
id = mapped_column(sa.Integer, primary_key=True, autoincrement=True)
|
|
756
|
-
user_id = mapped_column(
|
|
758
|
+
id: Mapped[int] = mapped_column(sa.Integer, primary_key=True, autoincrement=True)
|
|
759
|
+
user_id: Mapped[uuid.UUID] = mapped_column(
|
|
757
760
|
GUID, sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True
|
|
758
761
|
)
|
|
759
|
-
provider_id = mapped_column(sa.String(64), nullable=False)
|
|
760
|
-
subject_id = mapped_column(sa.String(255), nullable=False)
|
|
761
|
-
email = mapped_column(sa.String(255), nullable=True, index=True)
|
|
762
|
-
created_at = mapped_column(
|
|
762
|
+
provider_id: Mapped[str] = mapped_column(sa.String(64), nullable=False)
|
|
763
|
+
subject_id: Mapped[str] = mapped_column(sa.String(255), nullable=False)
|
|
764
|
+
email: Mapped[str | None] = mapped_column(sa.String(255), nullable=True, index=True)
|
|
765
|
+
created_at: Mapped[datetime] = mapped_column(
|
|
763
766
|
sa.DateTime, nullable=False, server_default=sa.func.now()
|
|
764
767
|
)
|
|
765
768
|
|
|
@@ -779,11 +782,11 @@ class TaskTree(user_db.Model): # type: ignore
|
|
|
779
782
|
|
|
780
783
|
__tablename__ = "task_tree"
|
|
781
784
|
|
|
782
|
-
task_id = mapped_column(sa.String(155), primary_key=True)
|
|
783
|
-
tree = mapped_column(sa.String, index=True)
|
|
784
|
-
user_id = mapped_column(sa.String, index=True)
|
|
785
|
-
name = mapped_column(sa.String, nullable=False)
|
|
786
|
-
created_at = mapped_column(
|
|
785
|
+
task_id: Mapped[str] = mapped_column(sa.String(155), primary_key=True)
|
|
786
|
+
tree: Mapped[str | None] = mapped_column(sa.String, index=True)
|
|
787
|
+
user_id: Mapped[str | None] = mapped_column(sa.String, index=True)
|
|
788
|
+
name: Mapped[str] = mapped_column(sa.String, nullable=False)
|
|
789
|
+
created_at: Mapped[datetime] = mapped_column(
|
|
787
790
|
sa.DateTime, nullable=False, server_default=sa.func.now()
|
|
788
791
|
)
|
|
789
792
|
|
|
@@ -129,6 +129,15 @@ PERMISSIONS[ROLE_ADMIN] = PERMISSIONS[ROLE_OWNER] | {
|
|
|
129
129
|
PERM_DISABLE_TREE,
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
# Users with a negative role (disabled or unconfirmed) hold no permissions,
|
|
133
|
+
# but the role must still be a key here: get_permissions() looks up
|
|
134
|
+
# PERMISSIONS[user.role] directly, and the OIDC callback resolves permissions
|
|
135
|
+
# before it checks for a disabled account, so a missing key raises instead of
|
|
136
|
+
# reaching the "Account Under Review" page. Local login is unaffected (it
|
|
137
|
+
# rejects a negative role before any permission lookup).
|
|
138
|
+
PERMISSIONS[ROLE_DISABLED] = set()
|
|
139
|
+
PERMISSIONS[ROLE_UNCONFIRMED] = set()
|
|
140
|
+
|
|
132
141
|
# keys/values for user claims
|
|
133
142
|
CLAIM_LIMITED_SCOPE = "limited_scope"
|
|
134
143
|
SCOPE_RESET_PW = "reset_password"
|
|
@@ -934,6 +934,80 @@ class TestOIDCSingleTree(unittest.TestCase):
|
|
|
934
934
|
)
|
|
935
935
|
self.assertEqual(rv.status_code, 422)
|
|
936
936
|
|
|
937
|
+
@patch("gramps_webapi.api.resources.oidc.is_oidc_enabled", return_value=True)
|
|
938
|
+
@patch(
|
|
939
|
+
"gramps_webapi.api.resources.oidc.get_available_oidc_providers",
|
|
940
|
+
return_value=["custom"],
|
|
941
|
+
)
|
|
942
|
+
@patch("gramps_webapi.api.resources.oidc.create_or_update_oidc_user")
|
|
943
|
+
@patch("gramps_webapi.api.resources.oidc.get_name")
|
|
944
|
+
def test_callback_negative_role_renders_review_page(
|
|
945
|
+
self,
|
|
946
|
+
mock_get_name,
|
|
947
|
+
mock_create_user,
|
|
948
|
+
mock_providers,
|
|
949
|
+
mock_oidc_enabled,
|
|
950
|
+
):
|
|
951
|
+
"""A disabled or unconfirmed account sees the review page, not a 500.
|
|
952
|
+
|
|
953
|
+
New OIDC sign-ups default to ROLE_DISABLED when no group->role
|
|
954
|
+
mapping is configured, and an account may also be ROLE_UNCONFIRMED.
|
|
955
|
+
Resolving permissions for either negative role must not raise, so
|
|
956
|
+
that the callback reaches its "Account Under Review" branch and
|
|
957
|
+
renders it instead of returning 500.
|
|
958
|
+
"""
|
|
959
|
+
from gramps_webapi.auth import add_user, delete_user, get_guid, get_tree
|
|
960
|
+
from gramps_webapi.auth.const import ROLE_DISABLED, ROLE_UNCONFIRMED
|
|
961
|
+
|
|
962
|
+
for role in (ROLE_DISABLED, ROLE_UNCONFIRMED):
|
|
963
|
+
with self.subTest(role=role):
|
|
964
|
+
username = f"oidc_negative_{role}"
|
|
965
|
+
with self.client.application.app_context():
|
|
966
|
+
# Belong to the same tree as the seeded users, so tree
|
|
967
|
+
# resolution succeeds and the login is not refused for
|
|
968
|
+
# want of a tree; the account is simply not active.
|
|
969
|
+
tree = get_tree(get_guid("owner"))
|
|
970
|
+
add_user(
|
|
971
|
+
name=username,
|
|
972
|
+
password="disabled-pw",
|
|
973
|
+
role=role,
|
|
974
|
+
tree=tree,
|
|
975
|
+
)
|
|
976
|
+
account_guid = get_guid(username)
|
|
977
|
+
|
|
978
|
+
try:
|
|
979
|
+
mock_create_user.return_value = account_guid
|
|
980
|
+
mock_get_name.return_value = username
|
|
981
|
+
|
|
982
|
+
mock_oauth = MagicMock()
|
|
983
|
+
mock_oidc_client = MagicMock()
|
|
984
|
+
mock_oauth.gramps_custom = mock_oidc_client
|
|
985
|
+
mock_oidc_client.authorize_access_token.return_value = {
|
|
986
|
+
"access_token": "t"
|
|
987
|
+
}
|
|
988
|
+
mock_oidc_client.userinfo.return_value = {
|
|
989
|
+
"sub": f"negative-subject-{role}",
|
|
990
|
+
"email": "inactive@example.com",
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
# get_tree_id_and_permissions() -> get_permissions()
|
|
994
|
+
# runs for real here: that lookup is what used to raise
|
|
995
|
+
# KeyError for a negative role.
|
|
996
|
+
with patch.dict(
|
|
997
|
+
self.client.application.extensions,
|
|
998
|
+
{"authlib.integrations.flask_client": mock_oauth},
|
|
999
|
+
clear=False,
|
|
1000
|
+
):
|
|
1001
|
+
rv = self.client.get(
|
|
1002
|
+
BASE_URL + "/oidc/callback/custom?code=auth_code"
|
|
1003
|
+
)
|
|
1004
|
+
|
|
1005
|
+
self.assertEqual(rv.status_code, 200)
|
|
1006
|
+
self.assertIn(b"Account Under Review", rv.data)
|
|
1007
|
+
finally:
|
|
1008
|
+
with self.client.application.app_context():
|
|
1009
|
+
delete_user(username)
|
|
1010
|
+
|
|
937
1011
|
|
|
938
1012
|
class TestOIDCCodeExchange(unittest.TestCase):
|
|
939
1013
|
"""Test cases for the single-use exchange code and its redemption."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gramps_webapi-3.22.1 → gramps_webapi-3.22.2}/alembic_users/versions/66e56620891a_add_trees_table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|