cattle_grid 0.2.0__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.
- cattle_grid-0.2.0/.behaverc +3 -0
- cattle_grid-0.2.0/.gitignore +13 -0
- cattle_grid-0.2.0/.readthedocs.yaml +15 -0
- cattle_grid-0.2.0/.woodpecker/publish.yml +13 -0
- cattle_grid-0.2.0/.woodpecker/test.yml +23 -0
- cattle_grid-0.2.0/.woodpecker/website.yml +27 -0
- cattle_grid-0.2.0/LICENSE +21 -0
- cattle_grid-0.2.0/PKG-INFO +109 -0
- cattle_grid-0.2.0/README.md +83 -0
- cattle_grid-0.2.0/cattle_grid/__init__.py +84 -0
- cattle_grid-0.2.0/cattle_grid/__main__.py +150 -0
- cattle_grid-0.2.0/cattle_grid/account/__init__.py +0 -0
- cattle_grid-0.2.0/cattle_grid/account/account.py +39 -0
- cattle_grid-0.2.0/cattle_grid/account/cli.py +39 -0
- cattle_grid-0.2.0/cattle_grid/account/models.py +37 -0
- cattle_grid-0.2.0/cattle_grid/account/rabbit.py +119 -0
- cattle_grid-0.2.0/cattle_grid/account/router/__init__.py +26 -0
- cattle_grid-0.2.0/cattle_grid/account/router/annotations.py +87 -0
- cattle_grid-0.2.0/cattle_grid/account/router/exception.py +33 -0
- cattle_grid-0.2.0/cattle_grid/account/router/exchange.py +3 -0
- cattle_grid-0.2.0/cattle_grid/account/router/info.py +9 -0
- cattle_grid-0.2.0/cattle_grid/account/router/router.py +222 -0
- cattle_grid-0.2.0/cattle_grid/account/router/schema.py +47 -0
- cattle_grid-0.2.0/cattle_grid/account/router/test_annotations.py +5 -0
- cattle_grid-0.2.0/cattle_grid/account/router/test_exception.py +52 -0
- cattle_grid-0.2.0/cattle_grid/account/router/test_handlers.py +53 -0
- cattle_grid-0.2.0/cattle_grid/account/router/test_router.py +122 -0
- cattle_grid-0.2.0/cattle_grid/account/server/__init__.py +50 -0
- cattle_grid-0.2.0/cattle_grid/account/server/account.py +109 -0
- cattle_grid-0.2.0/cattle_grid/account/server/actor.py +82 -0
- cattle_grid-0.2.0/cattle_grid/account/server/app.py +33 -0
- cattle_grid-0.2.0/cattle_grid/account/server/dependencies.py +23 -0
- cattle_grid-0.2.0/cattle_grid/account/server/requests.py +43 -0
- cattle_grid-0.2.0/cattle_grid/account/server/responses.py +56 -0
- cattle_grid-0.2.0/cattle_grid/account/server/test_account.py +59 -0
- cattle_grid-0.2.0/cattle_grid/account/server/test_actor.py +89 -0
- cattle_grid-0.2.0/cattle_grid/account/server/test_methods.py +12 -0
- cattle_grid-0.2.0/cattle_grid/account/server/test_signin.py +57 -0
- cattle_grid-0.2.0/cattle_grid/account/server/testing.py +51 -0
- cattle_grid-0.2.0/cattle_grid/account/test_account.py +36 -0
- cattle_grid-0.2.0/cattle_grid/account/test_rabbit.py +70 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/__init__.py +42 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/activity.py +34 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/actor.py +294 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/enqueuer.py +62 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/models.py +163 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/__init__.py +34 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/common.py +52 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/incoming.py +166 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/outgoing.py +156 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/remote.py +64 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/store_activity.py +43 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/test_incoming.py +213 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/test_outgoing.py +255 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/test_remote.py +158 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/test_store_activity.py +23 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/test_util.py +96 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/processing/util.py +28 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/server/__init__.py +78 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/server/router.py +103 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/server/router_inbox.py +75 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/server/router_object.py +33 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/server/test_init.py +59 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/server/test_router.py +199 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/server/test_router_inbox.py +120 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/server/test_router_object.py +148 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/test_activity.py +17 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/test_actor.py +198 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/test_actor_valid_requester.py +49 -0
- cattle_grid-0.2.0/cattle_grid/activity_pub/test_enqueuer.py +27 -0
- cattle_grid-0.2.0/cattle_grid/auth/__init__.py +33 -0
- cattle_grid-0.2.0/cattle_grid/auth/__main__.py +39 -0
- cattle_grid-0.2.0/cattle_grid/auth/block_cli.py +108 -0
- cattle_grid-0.2.0/cattle_grid/auth/key_cli.py +35 -0
- cattle_grid-0.2.0/cattle_grid/auth/model.py +11 -0
- cattle_grid-0.2.0/cattle_grid/auth/public_key_cache.py +75 -0
- cattle_grid-0.2.0/cattle_grid/auth/router.py +157 -0
- cattle_grid-0.2.0/cattle_grid/auth/templates/index.html +15 -0
- cattle_grid-0.2.0/cattle_grid/auth/test_app.py +146 -0
- cattle_grid-0.2.0/cattle_grid/auth/test_block_cli.py +65 -0
- cattle_grid-0.2.0/cattle_grid/auth/test_key_cli.py +42 -0
- cattle_grid-0.2.0/cattle_grid/auth/test_public_key_cache.py +109 -0
- cattle_grid-0.2.0/cattle_grid/auth/test_router.py +17 -0
- cattle_grid-0.2.0/cattle_grid/auth/test_util.py +15 -0
- cattle_grid-0.2.0/cattle_grid/auth/util.py +52 -0
- cattle_grid-0.2.0/cattle_grid/config/__init__.py +21 -0
- cattle_grid-0.2.0/cattle_grid/config/auth.py +91 -0
- cattle_grid-0.2.0/cattle_grid/config/messaging.py +42 -0
- cattle_grid-0.2.0/cattle_grid/config/settings.py +19 -0
- cattle_grid-0.2.0/cattle_grid/config/test_auth.py +26 -0
- cattle_grid-0.2.0/cattle_grid/config/test_config.py +17 -0
- cattle_grid-0.2.0/cattle_grid/config/test_messaging.py +23 -0
- cattle_grid-0.2.0/cattle_grid/config/test_validators.py +61 -0
- cattle_grid-0.2.0/cattle_grid/config/validators.py +54 -0
- cattle_grid-0.2.0/cattle_grid/database.py +94 -0
- cattle_grid-0.2.0/cattle_grid/dependencies/__init__.py +60 -0
- cattle_grid-0.2.0/cattle_grid/dependencies/fastapi.py +21 -0
- cattle_grid-0.2.0/cattle_grid/dependencies/globals.py +65 -0
- cattle_grid-0.2.0/cattle_grid/dependencies/test_globals.py +8 -0
- cattle_grid-0.2.0/cattle_grid/exchange/__init__.py +99 -0
- cattle_grid-0.2.0/cattle_grid/exchange/actor_update.py +89 -0
- cattle_grid-0.2.0/cattle_grid/exchange/handlers.py +85 -0
- cattle_grid-0.2.0/cattle_grid/exchange/info.py +19 -0
- cattle_grid-0.2.0/cattle_grid/exchange/message_handlers.py +45 -0
- cattle_grid-0.2.0/cattle_grid/exchange/server/__init__.py +34 -0
- cattle_grid-0.2.0/cattle_grid/exchange/server/account.py +54 -0
- cattle_grid-0.2.0/cattle_grid/exchange/server/test_account.py +111 -0
- cattle_grid-0.2.0/cattle_grid/exchange/shovel.py +138 -0
- cattle_grid-0.2.0/cattle_grid/exchange/test_actor_update.py +49 -0
- cattle_grid-0.2.0/cattle_grid/exchange/test_handlers.py +92 -0
- cattle_grid-0.2.0/cattle_grid/exchange/test_message_handlers.py +32 -0
- cattle_grid-0.2.0/cattle_grid/exchange/test_shovel.py +216 -0
- cattle_grid-0.2.0/cattle_grid/extensions/__init__.py +161 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/__init__.py +0 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/cache/__init__.py +66 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/cache/config.py +9 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/cache/dependencies.py +32 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/cache/lookup.py +23 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/cache/test_lookup.py +30 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/cache/testing.py +11 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/recipients.py +35 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/__init__.py +201 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/config.py +36 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/database.py +40 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/message_types.py +41 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/models.py +43 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/test_api.py +135 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/test_config.py +18 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/test_handlers.py +132 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/simple_storage/test_init.py +16 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/test_examples.py +20 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/test_recipients.py +14 -0
- cattle_grid-0.2.0/cattle_grid/extensions/examples/webfinger_lookup.py +77 -0
- cattle_grid-0.2.0/cattle_grid/extensions/helper.py +31 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/__init__.py +116 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/lifespan.py +23 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/lookup.py +16 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/test_init.py +30 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/test_lifespan.py +36 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/test_load.py +29 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/test_lookup.py +36 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/test_util.py +38 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/types.py +22 -0
- cattle_grid-0.2.0/cattle_grid/extensions/load/util.py +56 -0
- cattle_grid-0.2.0/cattle_grid/extensions/test_init.py +80 -0
- cattle_grid-0.2.0/cattle_grid/extensions/test_init_api_router.py +29 -0
- cattle_grid-0.2.0/cattle_grid/extensions/util.py +23 -0
- cattle_grid-0.2.0/cattle_grid/migrations/ap_models/0_20241226112941_init.py +106 -0
- cattle_grid-0.2.0/cattle_grid/model/__init__.py +39 -0
- cattle_grid-0.2.0/cattle_grid/model/account.py +187 -0
- cattle_grid-0.2.0/cattle_grid/model/exchange.py +82 -0
- cattle_grid-0.2.0/cattle_grid/model/extension.py +23 -0
- cattle_grid-0.2.0/cattle_grid/model/lookup.py +26 -0
- cattle_grid-0.2.0/cattle_grid/model/messages.py +35 -0
- cattle_grid-0.2.0/cattle_grid/model/processing.py +17 -0
- cattle_grid-0.2.0/cattle_grid/model/test_exchange.py +17 -0
- cattle_grid-0.2.0/cattle_grid/processor.py +70 -0
- cattle_grid-0.2.0/cattle_grid/statistics.py +12 -0
- cattle_grid-0.2.0/cattle_grid/test_database.py +23 -0
- cattle_grid-0.2.0/cattle_grid/test_init.py +7 -0
- cattle_grid-0.2.0/cattle_grid/testing/__init__.py +0 -0
- cattle_grid-0.2.0/cattle_grid/testing/extensions/__init__.py +0 -0
- cattle_grid-0.2.0/cattle_grid/testing/extensions/lookup.py +24 -0
- cattle_grid-0.2.0/cattle_grid/testing/extensions/one.py +6 -0
- cattle_grid-0.2.0/cattle_grid/testing/extensions/two.py +6 -0
- cattle_grid-0.2.0/cattle_grid/testing/features/__init__.py +119 -0
- cattle_grid-0.2.0/cattle_grid/testing/features/reporting.py +26 -0
- cattle_grid-0.2.0/cattle_grid/testing/features/steps/__init__.py +5 -0
- cattle_grid-0.2.0/cattle_grid/testing/features/steps/block.py +72 -0
- cattle_grid-0.2.0/cattle_grid/testing/features/steps/collection.py +61 -0
- cattle_grid-0.2.0/cattle_grid/testing/features/steps/follow.py +173 -0
- cattle_grid-0.2.0/cattle_grid/testing/features/steps/messaging.py +194 -0
- cattle_grid-0.2.0/cattle_grid/testing/features/steps/user.py +117 -0
- cattle_grid-0.2.0/cattle_grid/testing/fixtures.py +31 -0
- cattle_grid-0.2.0/cattle_grid/testing/reporter.py +120 -0
- cattle_grid-0.2.0/cattle_grid/version.py +1 -0
- cattle_grid-0.2.0/cattle_grid.toml +45 -0
- cattle_grid-0.2.0/docker-compose.yml +102 -0
- cattle_grid-0.2.0/docs/.pages +15 -0
- cattle_grid-0.2.0/docs/apis.md +32 -0
- cattle_grid-0.2.0/docs/architecture/.pages +11 -0
- cattle_grid-0.2.0/docs/architecture/activity_pub.md +9 -0
- cattle_grid-0.2.0/docs/architecture/activity_pub.models.md +3 -0
- cattle_grid-0.2.0/docs/architecture/activity_pub.processing.md +5 -0
- cattle_grid-0.2.0/docs/architecture/activity_pub.server.md +5 -0
- cattle_grid-0.2.0/docs/architecture/activitypub.md +67 -0
- cattle_grid-0.2.0/docs/architecture/exchange.md +5 -0
- cattle_grid-0.2.0/docs/architecture/index.md +74 -0
- cattle_grid-0.2.0/docs/architecture/usage.md +9 -0
- cattle_grid-0.2.0/docs/assets/.gitignore +1 -0
- cattle_grid-0.2.0/docs/assets/asyncapi.html +82 -0
- cattle_grid-0.2.0/docs/assets/redoc.html +17 -0
- cattle_grid-0.2.0/docs/assets/redoc_auth.html +6 -0
- cattle_grid-0.2.0/docs/authentication/blocking.md +7 -0
- cattle_grid-0.2.0/docs/authentication/configuration.md +133 -0
- cattle_grid-0.2.0/docs/authentication/index.md +127 -0
- cattle_grid-0.2.0/docs/authentication/request_flow.md +117 -0
- cattle_grid-0.2.0/docs/cattle_drive.md +383 -0
- cattle_grid-0.2.0/docs/extensions/.pages +9 -0
- cattle_grid-0.2.0/docs/extensions/cache.md +4 -0
- cattle_grid-0.2.0/docs/extensions/dependencies.md +4 -0
- cattle_grid-0.2.0/docs/extensions/index.md +55 -0
- cattle_grid-0.2.0/docs/extensions/recipients.md +3 -0
- cattle_grid-0.2.0/docs/extensions/reference.md +7 -0
- cattle_grid-0.2.0/docs/extensions/simple_storage.md +4 -0
- cattle_grid-0.2.0/docs/extensions/webfinger_lookup.md +3 -0
- cattle_grid-0.2.0/docs/index.md +218 -0
- cattle_grid-0.2.0/docs/installation.md +86 -0
- cattle_grid-0.2.0/docs/methods.md +5 -0
- cattle_grid-0.2.0/docs/reference/auth.md +5 -0
- cattle_grid-0.2.0/docs/reference/config.md +5 -0
- cattle_grid-0.2.0/docs/reference/model.md +5 -0
- cattle_grid-0.2.0/docs/reference/rabbitmq.md +13 -0
- cattle_grid-0.2.0/docs/testing/feature.md +3 -0
- cattle_grid-0.2.0/docs/testing/index.md +5 -0
- cattle_grid-0.2.0/docs/testing/reporting.md +52 -0
- cattle_grid-0.2.0/docs/testing/steps.md +17 -0
- cattle_grid-0.2.0/docs/tool.md +7 -0
- cattle_grid-0.2.0/dummy_woodpecker.yml +8 -0
- cattle_grid-0.2.0/features/.gitignore +2 -0
- cattle_grid-0.2.0/features/authorization.feature +39 -0
- cattle_grid-0.2.0/features/basic.feature +39 -0
- cattle_grid-0.2.0/features/environment.py +8 -0
- cattle_grid-0.2.0/features/simple_storage.feature +9 -0
- cattle_grid-0.2.0/features/steps/authorization.py +44 -0
- cattle_grid-0.2.0/features/steps/import.py +1 -0
- cattle_grid-0.2.0/features/steps/messaging.py +44 -0
- cattle_grid-0.2.0/features/steps/my_steps.py +57 -0
- cattle_grid-0.2.0/features/steps/server.py +58 -0
- cattle_grid-0.2.0/features/steps/simple_storage.py +27 -0
- cattle_grid-0.2.0/fediverse-features.toml +10 -0
- cattle_grid-0.2.0/jskitten/Dockerfile +3 -0
- cattle_grid-0.2.0/jskitten/app.js +162 -0
- cattle_grid-0.2.0/jskitten/package-lock.json +1096 -0
- cattle_grid-0.2.0/jskitten/package.json +19 -0
- cattle_grid-0.2.0/jskitten/startup.sh +11 -0
- cattle_grid-0.2.0/mastodon.png +0 -0
- cattle_grid-0.2.0/mkdocs.yml +72 -0
- cattle_grid-0.2.0/pyproject.toml +83 -0
- cattle_grid-0.2.0/resources/activity_message.schema.json +43 -0
- cattle_grid-0.2.0/resources/dev/03_http_auth.conf +8 -0
- cattle_grid-0.2.0/resources/dev/nginx.conf +88 -0
- cattle_grid-0.2.0/resources/dev/rabbit_enabled_plugins +1 -0
- cattle_grid-0.2.0/resources/dev/startup.sh +7 -0
- cattle_grid-0.2.0/resources/docker/Dockerfile +4 -0
- cattle_grid-0.2.0/resources/docker/build.sh +19 -0
- cattle_grid-0.2.0/resources/docker/cattle_grid.toml +223 -0
- cattle_grid-0.2.0/resources/docker_dev/Dockerfile +6 -0
- cattle_grid-0.2.0/resources/generate_models.sh +44 -0
- cattle_grid-0.2.0/resources/managing.schema.json +65 -0
- cattle_grid-0.2.0/resources/packages/Dockerfile +8 -0
- cattle_grid-0.2.0/resources/packages/build.sh +9 -0
- cattle_grid-0.2.0/resources/packages/cattle_grid.toml +19 -0
- cattle_grid-0.2.0/resources/packages/cattle_grid_auth.toml +45 -0
- cattle_grid-0.2.0/resources/packages/docker-compose.yml +75 -0
- cattle_grid-0.2.0/resources/schema/activity_pub/activity.schema.json +41 -0
- cattle_grid-0.2.0/resources/schema/activity_pub/base.schema.json +52 -0
- cattle_grid-0.2.0/resources/schema/activity_pub/object.schema.json +49 -0
- cattle_grid-0.2.0/resources/schema/activity_pub.schema.json +7 -0
- cattle_grid-0.2.0/resources/schema/gateway/gateway_message.schema.json +31 -0
- cattle_grid-0.2.0/resources/schema/gateway/gateway_message_result.schema.json +23 -0
- cattle_grid-0.2.0/resources/schema/gateway.schema.json +9 -0
- cattle_grid-0.2.0/uv.lock +3423 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
build:
|
|
4
|
+
os: "ubuntu-22.04"
|
|
5
|
+
tools:
|
|
6
|
+
python: "3.11"
|
|
7
|
+
jobs:
|
|
8
|
+
post_create_environment:
|
|
9
|
+
- pip install poetry
|
|
10
|
+
- poetry config virtualenvs.create false
|
|
11
|
+
post_install:
|
|
12
|
+
- poetry install --with=dev,doc --all-extras -vvv
|
|
13
|
+
|
|
14
|
+
mkdocs:
|
|
15
|
+
configuration: docs/mkdocs.yml
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
when:
|
|
2
|
+
- branch: [main]
|
|
3
|
+
event: [pull_request, push]
|
|
4
|
+
|
|
5
|
+
steps:
|
|
6
|
+
build:
|
|
7
|
+
image: ghcr.io/astral-sh/uv:python3.11-alpine
|
|
8
|
+
commands:
|
|
9
|
+
- uv sync --frozen
|
|
10
|
+
test_format:
|
|
11
|
+
image: ghcr.io/astral-sh/uv:python3.11-alpine
|
|
12
|
+
commands:
|
|
13
|
+
- uv run ruff format .
|
|
14
|
+
- uv run ruff check .
|
|
15
|
+
test_pytest:
|
|
16
|
+
image: ghcr.io/astral-sh/uv:python3.11-alpine
|
|
17
|
+
commands:
|
|
18
|
+
- uv run pytest
|
|
19
|
+
build_docs:
|
|
20
|
+
image: ghcr.io/astral-sh/uv:python3.11-alpine
|
|
21
|
+
commands:
|
|
22
|
+
- uv run mkdocs build
|
|
23
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
when:
|
|
2
|
+
branch: main
|
|
3
|
+
event: push
|
|
4
|
+
|
|
5
|
+
steps:
|
|
6
|
+
build:
|
|
7
|
+
image: ghcr.io/astral-sh/uv:python3.11-alpine
|
|
8
|
+
commands:
|
|
9
|
+
- mkdir -p docs/assets/schemas
|
|
10
|
+
- uv sync --frozen
|
|
11
|
+
- uv run python -mcattle_grid.auth new-config http://localhost/cattle_grid_actor
|
|
12
|
+
- uv run python -mcattle_grid openapi --filename docs/assets/schemas/openapi.json
|
|
13
|
+
- uv run python -mcattle_grid openapi --filename docs/assets/schemas/openapi_ap.json --component ap
|
|
14
|
+
- uv run python -mcattle_grid openapi --filename docs/assets/schemas/openapi_autn.json --component auth
|
|
15
|
+
- uv run python -mcattle_grid async-api --filename docs/assets/schemas/asyncapi_ap.json --component ap
|
|
16
|
+
- uv run python -mcattle_grid async-api --filename docs/assets/schemas/asyncapi_exchange.json
|
|
17
|
+
- uv run python -mcattle_grid openapi --component account --filename docs/assets/schemas/openapi_account.json
|
|
18
|
+
- uv run python -mcattle_grid openapi --component account --filename docs/assets/schemas/openapi_account_ap.json --component ap
|
|
19
|
+
- uv run python -mcattle_grid async-api --component account --filename docs/assets/schemas/asyncapi_account.json
|
|
20
|
+
- uv run python -mcattle_grid openapi --component rabbit --filename docs/assets/schemas/openapi_rabbit.json
|
|
21
|
+
- uv run mkdocs build
|
|
22
|
+
deploy:
|
|
23
|
+
image: codeberg.org/xfix/plugin-codeberg-pages-deploy:1
|
|
24
|
+
settings:
|
|
25
|
+
folder: site
|
|
26
|
+
ssh_key:
|
|
27
|
+
from_secret: deploy_ssh_key
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Helge
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cattle_grid
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Middleware for the Fediverse
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: aerich>=0.8.0
|
|
8
|
+
Requires-Dist: almabtrieb>=0.1.0a1
|
|
9
|
+
Requires-Dist: argon2-cffi>=23.1.0
|
|
10
|
+
Requires-Dist: bleach>=6.2.0
|
|
11
|
+
Requires-Dist: bovine>=0.5.13
|
|
12
|
+
Requires-Dist: dynaconf>=3.2.6
|
|
13
|
+
Requires-Dist: fastapi>=0.115.4
|
|
14
|
+
Requires-Dist: faststream[cli,rabbit]>=0.5.25
|
|
15
|
+
Requires-Dist: fediverse-pasture>=0.2.14
|
|
16
|
+
Requires-Dist: python-multipart>=0.0.17
|
|
17
|
+
Requires-Dist: quart>=0.19.6
|
|
18
|
+
Requires-Dist: sqlalchemy-utils>=0.41.2
|
|
19
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.36
|
|
20
|
+
Requires-Dist: tomli-w>=1.0.0
|
|
21
|
+
Requires-Dist: tortoise-orm[asyncpg]>=0.21.6
|
|
22
|
+
Requires-Dist: uuid6>=2024.7.10
|
|
23
|
+
Provides-Extra: cache
|
|
24
|
+
Requires-Dist: redis>=5.2.1; extra == 'cache'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# cattle_grid
|
|
28
|
+
|
|
29
|
+
THIS README needs to be updated for cattle_grid 0.2.0
|
|
30
|
+
|
|
31
|
+
cattle_grid is meant to simplify handling authentication in server to
|
|
32
|
+
server communication of the Fediverse. cattle_grid checks the HTTP
|
|
33
|
+
signatures based on the headers. For this public keys are retrieved
|
|
34
|
+
and cached.
|
|
35
|
+
|
|
36
|
+
For installation instructions see the [documentation](https://bovine.codeberg.page/cattle_grid/).
|
|
37
|
+
|
|
38
|
+
## Running
|
|
39
|
+
|
|
40
|
+
After creating a configuration file, one can run cattle_grid via
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
poetry run uvicorn cattle_grid:create_app
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
One can run the pytest tests via
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
poetry install
|
|
52
|
+
poetry run pytest
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Development with Fediverse pasture
|
|
56
|
+
|
|
57
|
+
In your Funfedi.dev directory (see [here](https://funfedi.dev/testing_tools/verify_actor/)
|
|
58
|
+
for details), run
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
cd fediverse-pasture
|
|
62
|
+
docker compose --file pasture.yml up pasture_verify_actor
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Now in the cattle grid directory, run
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
poetry run python -mcattle_grid.config --actor_id http://cattle_grid/actor
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
to create a `cattle_grid.toml` file. Then start the docker containers via
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
docker compose up
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
By opening [http://localhost:2909/?actor_uri=jskitten@cattle_grid_demo](http://localhost:2909/?actor_uri=jskitten%40cattle_grid_demo), you should then be able to view the verify actor result. By refreshing the page and inspecting the log files, you can also check that the requests only ran once.
|
|
78
|
+
|
|
79
|
+
### Creating an user
|
|
80
|
+
|
|
81
|
+
By running
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
docker compose run runner
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
one can start a shell in the docker environment. By then running in it
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
curl abel/admin/create -X POST -F username=name -F password=secret
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
one can create the user with handle `@name@abel`.
|
|
94
|
+
|
|
95
|
+
## Running GUI tests with the pasture
|
|
96
|
+
|
|
97
|
+
Start mastodon accessible through your browser
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cd fediverse-pasture
|
|
101
|
+
docker compose --file mastodon42.yml --profile nginx up
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
See [Fun Fediverse Development](https://funfedi.dev/fediverse_pasture/applications/mastodon_4_2/) for instructions.
|
|
105
|
+
|
|
106
|
+
Then you can open [mastodon42web](http://mastodon42web) and lookup `jskitten@cattle_grid_demo`.
|
|
107
|
+
When you send a message to this kitten, it should reply with a meow, e.g.
|
|
108
|
+
|
|
109
|
+

|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# cattle_grid
|
|
2
|
+
|
|
3
|
+
THIS README needs to be updated for cattle_grid 0.2.0
|
|
4
|
+
|
|
5
|
+
cattle_grid is meant to simplify handling authentication in server to
|
|
6
|
+
server communication of the Fediverse. cattle_grid checks the HTTP
|
|
7
|
+
signatures based on the headers. For this public keys are retrieved
|
|
8
|
+
and cached.
|
|
9
|
+
|
|
10
|
+
For installation instructions see the [documentation](https://bovine.codeberg.page/cattle_grid/).
|
|
11
|
+
|
|
12
|
+
## Running
|
|
13
|
+
|
|
14
|
+
After creating a configuration file, one can run cattle_grid via
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
poetry run uvicorn cattle_grid:create_app
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Development
|
|
21
|
+
|
|
22
|
+
One can run the pytest tests via
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
poetry install
|
|
26
|
+
poetry run pytest
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Development with Fediverse pasture
|
|
30
|
+
|
|
31
|
+
In your Funfedi.dev directory (see [here](https://funfedi.dev/testing_tools/verify_actor/)
|
|
32
|
+
for details), run
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd fediverse-pasture
|
|
36
|
+
docker compose --file pasture.yml up pasture_verify_actor
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Now in the cattle grid directory, run
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
poetry run python -mcattle_grid.config --actor_id http://cattle_grid/actor
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
to create a `cattle_grid.toml` file. Then start the docker containers via
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
docker compose up
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
By opening [http://localhost:2909/?actor_uri=jskitten@cattle_grid_demo](http://localhost:2909/?actor_uri=jskitten%40cattle_grid_demo), you should then be able to view the verify actor result. By refreshing the page and inspecting the log files, you can also check that the requests only ran once.
|
|
52
|
+
|
|
53
|
+
### Creating an user
|
|
54
|
+
|
|
55
|
+
By running
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
docker compose run runner
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
one can start a shell in the docker environment. By then running in it
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
curl abel/admin/create -X POST -F username=name -F password=secret
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
one can create the user with handle `@name@abel`.
|
|
68
|
+
|
|
69
|
+
## Running GUI tests with the pasture
|
|
70
|
+
|
|
71
|
+
Start mastodon accessible through your browser
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cd fediverse-pasture
|
|
75
|
+
docker compose --file mastodon42.yml --profile nginx up
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
See [Fun Fediverse Development](https://funfedi.dev/fediverse_pasture/applications/mastodon_4_2/) for instructions.
|
|
79
|
+
|
|
80
|
+
Then you can open [mastodon42web](http://mastodon42web) and lookup `jskitten@cattle_grid_demo`.
|
|
81
|
+
When you send a message to this kitten, it should reply with a meow, e.g.
|
|
82
|
+
|
|
83
|
+

|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from fastapi import FastAPI
|
|
5
|
+
from faststream.rabbit import RabbitBroker
|
|
6
|
+
from contextlib import asynccontextmanager
|
|
7
|
+
|
|
8
|
+
from .activity_pub.server import router as ap_router
|
|
9
|
+
from .auth.router import create_auth_router
|
|
10
|
+
|
|
11
|
+
from .config import load_settings, default_filenames
|
|
12
|
+
from .config.messaging import broker
|
|
13
|
+
from .config.auth import get_auth_config
|
|
14
|
+
from .exchange.server import create_exchange_api_router
|
|
15
|
+
from .account.server import router as fe_router
|
|
16
|
+
from .account.rabbit import rabbit_router
|
|
17
|
+
from .extensions.load import load_extensions, add_routes_to_api, set_globals
|
|
18
|
+
from .dependencies.globals import alchemy_database
|
|
19
|
+
|
|
20
|
+
from .version import __version__
|
|
21
|
+
from .database import database, upgrade
|
|
22
|
+
|
|
23
|
+
logging.basicConfig(level=logging.INFO)
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
tags_description = [
|
|
28
|
+
{
|
|
29
|
+
"name": "activity_pub",
|
|
30
|
+
"description": "Endpoints used and consumed by other Fediverse applications to communicate through cattle_grid",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "auth",
|
|
34
|
+
"description": """Authentication endpoints
|
|
35
|
+
|
|
36
|
+
The auth endpoint allows one to check the HTTP Signature
|
|
37
|
+
and reject requests with an invalid one, only based on the
|
|
38
|
+
headers. This step then occurs before the request is passed
|
|
39
|
+
to the application. Furthermore, this behavior can be shared
|
|
40
|
+
accross many services.""",
|
|
41
|
+
},
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def create_app(filenames: List[str] = default_filenames) -> FastAPI:
|
|
46
|
+
logger.info("Running cattle grid version %s", __version__)
|
|
47
|
+
|
|
48
|
+
base_config = load_settings(filenames=filenames)
|
|
49
|
+
|
|
50
|
+
extensions = load_extensions(base_config)
|
|
51
|
+
set_globals(extensions)
|
|
52
|
+
|
|
53
|
+
@asynccontextmanager
|
|
54
|
+
async def lifespan(app: FastAPI, broker: RabbitBroker = broker()):
|
|
55
|
+
await upgrade(base_config)
|
|
56
|
+
|
|
57
|
+
await broker.start()
|
|
58
|
+
async with database(base_config.db_uri, generate_schemas=False):
|
|
59
|
+
async with alchemy_database(base_config.db_uri):
|
|
60
|
+
yield
|
|
61
|
+
await broker.close()
|
|
62
|
+
|
|
63
|
+
app = FastAPI(
|
|
64
|
+
lifespan=lifespan,
|
|
65
|
+
title="cattle_grid",
|
|
66
|
+
description="middle ware for the Fediverse",
|
|
67
|
+
version=__version__,
|
|
68
|
+
openapi_tags=tags_description,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
app.include_router(ap_router)
|
|
72
|
+
app.include_router(create_exchange_api_router(base_config))
|
|
73
|
+
app.include_router(create_auth_router(get_auth_config(base_config)), prefix="/auth")
|
|
74
|
+
|
|
75
|
+
app.include_router(fe_router, prefix="/fe")
|
|
76
|
+
app.include_router(rabbit_router)
|
|
77
|
+
|
|
78
|
+
add_routes_to_api(app, extensions)
|
|
79
|
+
|
|
80
|
+
@app.get("/")
|
|
81
|
+
async def main() -> str:
|
|
82
|
+
return "cattle_grid"
|
|
83
|
+
|
|
84
|
+
return app
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import os
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from cattle_grid.config import load_settings, default_filenames
|
|
7
|
+
from .statistics import statistics
|
|
8
|
+
from .auth.block_cli import add_block_command
|
|
9
|
+
from .auth.key_cli import add_keys_command
|
|
10
|
+
|
|
11
|
+
from .extensions.helper import add_extension_commands
|
|
12
|
+
from .account.cli import add_account_commands
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.group()
|
|
18
|
+
@click.option("--config_file", default="cattle_grid.toml")
|
|
19
|
+
@click.pass_context
|
|
20
|
+
def main(ctx, config_file):
|
|
21
|
+
ctx.ensure_object(dict)
|
|
22
|
+
ctx.obj["config_file"] = config_file
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
ctx.obj["config"] = load_settings(config_file)
|
|
26
|
+
except Exception as e:
|
|
27
|
+
logger.Exception(e)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@main.command()
|
|
31
|
+
@click.option(
|
|
32
|
+
"--force",
|
|
33
|
+
help="Used to override the old configuration file",
|
|
34
|
+
is_flag=True,
|
|
35
|
+
default=False,
|
|
36
|
+
)
|
|
37
|
+
@click.pass_context
|
|
38
|
+
def new_config(ctx, force):
|
|
39
|
+
"""Creates a new configuration file"""
|
|
40
|
+
filename = ctx.obj["config_file"]
|
|
41
|
+
|
|
42
|
+
if os.path.exists(filename) and not force:
|
|
43
|
+
print("Configuration file already exists! Use --force to overwrite.")
|
|
44
|
+
exit(1)
|
|
45
|
+
|
|
46
|
+
# FIXME
|
|
47
|
+
|
|
48
|
+
exit(1)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@main.command()
|
|
52
|
+
@click.pass_context
|
|
53
|
+
def stat(ctx):
|
|
54
|
+
"""Displays statistical information about cattle_grid"""
|
|
55
|
+
asyncio.run(statistics(ctx.obj["config"]))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@main.command()
|
|
59
|
+
@click.option("--db_uri")
|
|
60
|
+
@click.option("--name")
|
|
61
|
+
@click.pass_context
|
|
62
|
+
def create_db_migration(ctx, db_uri, name):
|
|
63
|
+
"""Creates a database migration; run after editing models"""
|
|
64
|
+
from .database import migrate
|
|
65
|
+
|
|
66
|
+
config = ctx.obj["config"]
|
|
67
|
+
|
|
68
|
+
if db_uri:
|
|
69
|
+
config.db_uri = db_uri
|
|
70
|
+
|
|
71
|
+
asyncio.run(migrate(config, name))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@main.command()
|
|
75
|
+
@click.option("--db_uri")
|
|
76
|
+
@click.pass_context
|
|
77
|
+
def upgrade_db(ctx, db_uri):
|
|
78
|
+
from .database import upgrade
|
|
79
|
+
|
|
80
|
+
config = ctx.obj["config"]
|
|
81
|
+
|
|
82
|
+
if db_uri:
|
|
83
|
+
config.db_uri = db_uri
|
|
84
|
+
|
|
85
|
+
asyncio.run(upgrade(config))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@main.command()
|
|
89
|
+
@click.option("--filename", default="asyncapi.json")
|
|
90
|
+
@click.option(
|
|
91
|
+
"--component",
|
|
92
|
+
default=None,
|
|
93
|
+
help="Restrict to a component. Currently allowed ap",
|
|
94
|
+
)
|
|
95
|
+
def async_api(filename, component):
|
|
96
|
+
if component == "ap":
|
|
97
|
+
from .activity_pub import get_async_api_schema
|
|
98
|
+
elif component == "account":
|
|
99
|
+
from .account.router.schema import get_async_api_schema
|
|
100
|
+
else:
|
|
101
|
+
from .exchange import get_async_api_schema
|
|
102
|
+
|
|
103
|
+
schema = get_async_api_schema().to_json()
|
|
104
|
+
|
|
105
|
+
with open(filename, "w") as fp:
|
|
106
|
+
fp.write(schema)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@main.command()
|
|
110
|
+
@click.option("--filename", default="openapi.json")
|
|
111
|
+
@click.option(
|
|
112
|
+
"--component",
|
|
113
|
+
default=None,
|
|
114
|
+
help="Restrict to a component. Currently allowed auth or ap",
|
|
115
|
+
)
|
|
116
|
+
@click.pass_context
|
|
117
|
+
def openapi(ctx, filename, component):
|
|
118
|
+
import json
|
|
119
|
+
|
|
120
|
+
match component:
|
|
121
|
+
case "auth":
|
|
122
|
+
from .auth import create_app
|
|
123
|
+
|
|
124
|
+
app = create_app(default_filenames)
|
|
125
|
+
case "ap":
|
|
126
|
+
from .activity_pub import get_fastapi_app
|
|
127
|
+
|
|
128
|
+
app = get_fastapi_app()
|
|
129
|
+
case "account":
|
|
130
|
+
from .account.server.app import app
|
|
131
|
+
case "rabbit":
|
|
132
|
+
from .account.rabbit import app_for_schema
|
|
133
|
+
|
|
134
|
+
app = app_for_schema()
|
|
135
|
+
case _:
|
|
136
|
+
from . import create_app
|
|
137
|
+
|
|
138
|
+
# app = create_app(ctx.obj["config_file"])
|
|
139
|
+
app = create_app()
|
|
140
|
+
with open(filename, "w") as fp:
|
|
141
|
+
json.dump(app.openapi(), fp)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
add_block_command(main)
|
|
145
|
+
add_keys_command(main)
|
|
146
|
+
add_extension_commands(main)
|
|
147
|
+
add_account_commands(main)
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import argon2
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
from .models import Account
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
password_hasher = argon2.PasswordHasher()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def create_account(username: str, password: str) -> Account | None:
|
|
13
|
+
"""Creates a new account for username and password"""
|
|
14
|
+
if await Account.get_or_none(name=username):
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
return await Account.create(
|
|
18
|
+
name=username, password_hash=password_hasher.hash(password)
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def account_with_username_password(
|
|
23
|
+
username: str, password: str
|
|
24
|
+
) -> Account | None:
|
|
25
|
+
"""Retrieves account for given username and password"""
|
|
26
|
+
account = await Account.get_or_none(name=username)
|
|
27
|
+
if account is None:
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
password_hasher.verify(account.password_hash, password)
|
|
32
|
+
except argon2.exceptions.VerifyMismatchError:
|
|
33
|
+
logger.warning("Got wrong password for %s", username)
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
# Implement rehash?
|
|
37
|
+
# https://argon2-cffi.readthedocs.io/en/stable/howto.html
|
|
38
|
+
|
|
39
|
+
return account
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import asyncio
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
from cattle_grid.database import database
|
|
6
|
+
from .models import Account
|
|
7
|
+
from .account import create_account
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async def new_account(config, name, password):
|
|
11
|
+
async with database(db_uri=config.db_uri):
|
|
12
|
+
await create_account(name, password)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def list_accounts(config):
|
|
16
|
+
async with database(db_uri=config.db_uri):
|
|
17
|
+
accounts = await Account.all()
|
|
18
|
+
for account in accounts:
|
|
19
|
+
print(account.name)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def add_account_commands(main):
|
|
23
|
+
@main.group()
|
|
24
|
+
def account():
|
|
25
|
+
"""Used to manage accounts associated with cattle_grid"""
|
|
26
|
+
|
|
27
|
+
@account.command()
|
|
28
|
+
@click.argument("name")
|
|
29
|
+
@click.argument("password")
|
|
30
|
+
@click.pass_context
|
|
31
|
+
def new(cfg, name, password):
|
|
32
|
+
"""Creates a new account"""
|
|
33
|
+
asyncio.run(new_account(cfg.obj["config"], name, password))
|
|
34
|
+
|
|
35
|
+
@account.command()
|
|
36
|
+
@click.pass_context
|
|
37
|
+
def list(cfg):
|
|
38
|
+
"""Lists existing accounts"""
|
|
39
|
+
asyncio.run(list_accounts(cfg.obj["config"]))
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from tortoise import fields
|
|
2
|
+
from tortoise.models import Model
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Account(Model):
|
|
6
|
+
"""Represents an Account"""
|
|
7
|
+
|
|
8
|
+
id = fields.IntField(primary_key=True)
|
|
9
|
+
|
|
10
|
+
name = fields.CharField(max_length=255)
|
|
11
|
+
"""The account name"""
|
|
12
|
+
|
|
13
|
+
password_hash = fields.CharField(max_length=255)
|
|
14
|
+
"""The hashed password"""
|
|
15
|
+
|
|
16
|
+
actors: fields.ReverseRelation["ActorForAccount"]
|
|
17
|
+
"""Actors associated with this account"""
|
|
18
|
+
|
|
19
|
+
token: fields.ReverseRelation["AuthenticationToken"]
|
|
20
|
+
"""Authentication tokens for this account"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ActorForAccount(Model):
|
|
24
|
+
id = fields.IntField(primary_key=True)
|
|
25
|
+
|
|
26
|
+
account: fields.ForeignKeyRelation[Account] = fields.ForeignKeyField(
|
|
27
|
+
"gateway_models.Account", related_name="actors"
|
|
28
|
+
)
|
|
29
|
+
actor = fields.CharField(max_length=255)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AuthenticationToken(Model):
|
|
33
|
+
token = fields.CharField(max_length=64, primary_key=True)
|
|
34
|
+
|
|
35
|
+
account: fields.ForeignKeyRelation[Account] = fields.ForeignKeyField(
|
|
36
|
+
"gateway_models.Account", related_name="tokens"
|
|
37
|
+
)
|