From 398511ca6b083003567f5bcf74a449c1c26b0c15 Mon Sep 17 00:00:00 2001 From: robgendron <163159602+robgendron@users.noreply.github.com> Date: Thu, 29 Aug 2024 09:39:26 -0400 Subject: [PATCH 1/6] Create sprint-105-summary.md (#3150) * Create sprint-105-summary.md * Update sprint-105-summary.md * Update sprint-105-summary.md --------- Co-authored-by: Miles Reiter Co-authored-by: Andrew <84722778+andrew-jameson@users.noreply.github.com> --- docs/Sprint-Review/sprint-105-summary.md | 92 ++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docs/Sprint-Review/sprint-105-summary.md diff --git a/docs/Sprint-Review/sprint-105-summary.md b/docs/Sprint-Review/sprint-105-summary.md new file mode 100644 index 000000000..b9b57f9ef --- /dev/null +++ b/docs/Sprint-Review/sprint-105-summary.md @@ -0,0 +1,92 @@ +# sprint-105-summary + +7/31/2024 - 8/14/2024 + +### Priority Setting + +* Reparsing + * Tickets: + * \#3064 — Re-parse Meta Model + * \#3113 — As tech lead, I need the validation on the header update indicator revised to unblock parsing + * \#3073 — \[bug] TDP is raising cat 4 error on TANF/SSP closed case files that is not present +* System Monitoring +* DIGIT Work + +### Sprint Goal + +**Dev:** + +_**Plain Language Error Messaging and Application Health Monitoring work, improved dev tooling, and fixing bugs**_ + +* \#2792 — \[Error Audit] Category 3 error messages clean-up +* \#2965 — As tech lead, I want a database seed implemented for testing +* \#3064 — Re-parse Meta Model +* \#3113 — As tech lead, I need the validation on the header update indicator revised to unblock parsing +* \#3073 — \[bug] TDP is raising cat 4 error on TANF/SSP closed case files that is not present +* \#3062 — bug: ES docker image for non-dev spaces stored in personal dockerhub +* \#1646 — \[A11y Fix] Correct TDP home : aria label mismatch + +**DevOps:** + +_**Successful deployments across environments and pipeline stability investments**_ + +* \#2458 — Integrate Nexus into CircleCI + +**Design:** + +_**Support reviews, Complete Research Synthesis, Continue Error Audit (Cat 4)**_ + +* \#3078 — DIGIT Admin Experience Synthesis +* \#3114 — \[Design Spike] In-app banner for submission history pages +* \#2968 — \[Design Deliverable] Update Error Audit for Cat 4 / QA + +## Tickets + +### Completed/Merged + +* [#1621 As a TDP user, I'd like to see a descriptive error message page if authentication source is unavailable.](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/1621) +* [#1646 \[A11y Fix\] Correct TDP home : aria label mismatch](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/1646) +* [#3033 As tech lead, I need the sections 3 and 4 calendar quarter logic updated](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3033) +* [#3055 Service timeout blocks parsing completion](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3055) +* [#3057 \[Design Deliverable\] Spec for light-lift fiscal quarter / calendar quarter explainer in TDP](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3057) +* [#3113 As tech lead, I need the validation on the header update indicator revised to unblock parsing ](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3113) + +### Submitted (QASP Review, OCIO Review) + +* [#2954 Extend SESSION\_COOKIE\_AGE](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2954) +* [#3061 \[a11y fix\] Django multi-select filter ](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3061) +* [#3079 DB Backup Script Fix](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3079) +* [#2883 Pre-Made Reporting Dashboards on Kibana](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2883) +* [#2985 \[Design Deliverable\] Email spec for Admin Notification for stuck files](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2985) +* [#2996 Add dynamic field name to cat4 error messages](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2996) +* [#2993 Kibana Dashboard MVP](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2993) + +### Ready to Merge + +* [#3058 \[Design Deliverable\] Release notes email template](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3058) +* [#3062 bug: ES docker image for non-dev spaces stored in personal dockerhub](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3062) +* [#3073 \[bug\] TDP is raising cat 4 error on TANF/SSP closed case files that is not present](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3073) +* [#3107 \[Re-parse command\] Retain original submission date when command runs](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3107) + +### Closed (Not Merged) + +* [#1355 Research questions around DIGIT teams query usage for parsed data](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/1355) + +### Moved to Next Sprint + +**In Progress** + +* [#2965 As tech lead, I want a database seed implemented for testing](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2965) + +#### Blocked + +* [#2458 Integrate Nexus into CircleCI](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2458) + +**Raft Review** + +* [#3043 Sentry: Local environment for Debugging](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3043) +* [#3064 Re-parse Meta Model](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3064) +* [#3065 Spike - Guarantee Sequential Execution of Re-parse Command](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3065) +* [#3078 \[Research Synthesis\] DIGIT Admin Experience Improvements](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3078) +* [#3087 Admin By Newest Filter Enhancements for Data Files Page](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3087) +* [#2792 \[Error Audit\] Category 3 error messages clean-up](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2792) From 6c70977830ed8bd6d085a9f4a9115bfcf7a9e9fe Mon Sep 17 00:00:00 2001 From: raftmsohani <97037188+raftmsohani@users.noreply.github.com> Date: Tue, 3 Sep 2024 07:36:53 -0400 Subject: [PATCH 2/6] 3043 Sentry local (#3101) * 2960 Added taskfile for common tasks * 2960 additional commands * 2960 added linting for frontend * Fixes and improvement * 2960 remove frontend-pip lock * added Sentry to local, includes task file commits * correction on port setting * limited memory to 4g * had to increase mem to 6g * removed commands.sh * increased memory once more since kafka was not running for under 8G * Sentry added to Django app * added default config file for sentry * linting * remove unused docker-file * added backend logs for local * correct importing package * added Kafka heapsize * added sentry local * use version 23.7.2 with 8G mem cap * updated backup file and script * updated Sentry version * change docker-compose to docker compose * Update local.py * Update local.py * enable sentry using env var * 3043 update piplock --- Taskfile.yml | 61 ++- sentry/.env | 35 ++ sentry/backup.json | 503 ++++++++++++++++++++++ sentry/docker-compose.yml | 496 +++++++++++++++++++++ tdrs-backend/Pipfile | 1 + tdrs-backend/Pipfile.lock | 490 +++++++++++---------- tdrs-backend/tdpservice/settings/local.py | 28 ++ 7 files changed, 1387 insertions(+), 227 deletions(-) create mode 100644 sentry/.env create mode 100644 sentry/backup.json create mode 100644 sentry/docker-compose.yml diff --git a/Taskfile.yml b/Taskfile.yml index 74f3e9c7c..5985f0604 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -5,16 +5,66 @@ tasks: create-network: desc: Create the external network cmds: - - docker network create external-net + - (docker network create external-net) || true init-backend: desc: Initialize the backend project dir: tdrs-backend cmds: + - task: create-network - docker-compose -f docker-compose.yml up -d --build - docker-compose -f docker-compose.yml exec web sh -c "python ./manage.py makemigrations" - docker-compose -f docker-compose.yml exec web sh -c "python ./manage.py migrate" - docker-compose -f docker-compose.yml down + - task: sentry-down + + clone-sentry-repo: + desc: Clone the sentry repo + dir: sentry + cmds: + - git clone https://github.com/getsentry/self-hosted.git || true + + + create-sentry: + desc: Create Sentry service + dir: sentry + cmds: + # limiting the memory to 2GB and CPU to only one cpu @0, for faster response, you can remove the limittask : --cpuset-cpus 0 + - (docker run --privileged -p 9001:9000 -d --memory="8g" --memory-swap="8g" --name sentry docker:dind) || true + - docker exec sentry sh -c "git clone https://github.com/getsentry/self-hosted.git || true" + + # need sleep 10 for docker to start + # there is a bug with other version of self-hosted. looks like they are trying to upgrade to Django 5.0 (July 2024) + - docker exec sentry sh -c "cd self-hosted && sleep 10 && git checkout tags/23.10.1" + + # add bash + - docker exec sentry sh -c "apk add bash" + - docker cp docker-compose.yml sentry:/self-hosted/docker-compose.yml + - docker cp .env sentry:/self-hosted/.env + - docker exec sentry bash -c "cd self-hosted && ./install.sh --skip-user-creation --no-report-self-hosted-issues" + # create a new user + - docker exec sentry bash -c "cd self-hosted && docker-compose run --rm web createuser --email admin@tanf.com --password admin --superuser" + # copy backup.json file to sentry + - docker cp backup.json sentry:/self-hosted/sentry/backup.json + # restore backup + - docker exec sentry bash -c "cd self-hosted && docker compose up -d" + - docker exec sentry bash -c "docker cp /self-hosted/sentry/backup.json sentry-self-hosted-web-1:/home/sentry/backup.json" + - docker exec sentry bash -c "docker exec sentry-self-hosted-web-1 bash -c 'sentry import /home/sentry/backup.json'" + - docker exec sentry bash -c "cd self-hosted && docker compose down" + - docker exec sentry bash -c "cd self-hosted && docker compose up -d" + + + sentry-up: + desc: Start sentry service + dir: sentry + cmds: + - docker exec sentry bash -c "cd self-hosted && docker-compose up -d" + + sentry-down: + desc: Stop sentry service + dir: sentry + cmds: + - docker exec sentry bash -c "cd self-hosted && docker-compose down" drop-db: desc: Drop the backend database @@ -78,6 +128,7 @@ tasks: desc: Run flake8 in the backend container dir: tdrs-backend cmds: + - task backend-up - docker-compose -f docker-compose.yml exec web sh -c "flake8 . && if [ $? -eq 0 ]; then echo 'Flake8 linter found no issues'; fi" backend-pip-lock: @@ -85,6 +136,7 @@ tasks: desc: Lock the pip dependencies dir: tdrs-backend cmds: + - task: backend-up - docker-compose -f docker-compose.yml exec web sh -c "pipenv lock" psql: @@ -99,9 +151,10 @@ tasks: clean: desc: Remove all containers, networks, and volumes cmds: - - docker-compose -f tdrs-backend/docker-compose.yml down -v - - docker-compose -f tdrs-frontend/docker-compose.yml down -v - - docker system prune -f -a + - docker stop $(docker ps -aq) || true + - docker rm $(docker ps -aq) || true + - docker rmi $(docker images -q) || true + - docker volume rm $(docker volume ls -q) || true clamav-up: desc: Start clamav service diff --git a/sentry/.env b/sentry/.env new file mode 100644 index 000000000..a3d4f1b11 --- /dev/null +++ b/sentry/.env @@ -0,0 +1,35 @@ +COMPOSE_PROJECT_NAME=sentry-self-hosted +COMPOSE_PROFILES=feature-complete +SENTRY_EVENT_RETENTION_DAYS=90 +# You can either use a port number or an IP:PORT combo for SENTRY_BIND +# See https://docs.docker.com/compose/compose-file/#ports for more +SENTRY_BIND=9000 +# Set SENTRY_MAIL_HOST to a valid FQDN (host/domain name) to be able to send emails! +# SENTRY_MAIL_HOST=example.com + + +# https://hub.docker.com/r/getsentry/sentry/tags?page=1205&page_size=&ordering=&name= +SENTRY_IMAGE=getsentry/sentry:23.10.1 + + +# https://hub.docker.com/r/getsentry/snuba/tags?page=105&page_size=&name=&ordering= +SNUBA_IMAGE=getsentry/snuba:23.10.1 + +# https://hub.docker.com/r/getsentry/relay/tags?page=100&page_size=&name=&ordering= +RELAY_IMAGE=getsentry/relay:23.10.1 + + +#https://hub.docker.com/r/getsentry/symbolicator/tags?page=15&page_size=&name=&ordering= +SYMBOLICATOR_IMAGE=getsentry/symbolicator:23.10.1 + +# https://hub.docker.com/r/getsentry/vroom/tags?page=15&page_size=&name=&ordering= +VROOM_IMAGE=getsentry/vroom:23.10.1 + + +WAL2JSON_VERSION=latest +HEALTHCHECK_INTERVAL=30s +HEALTHCHECK_TIMEOUT=1m30s +HEALTHCHECK_RETRIES=10 +# Caution: Raising max connections of postgres increases CPU and RAM usage +# see https://github.com/getsentry/self-hosted/pull/2740 for more information +POSTGRES_MAX_CONNECTIONS=100 \ No newline at end of file diff --git a/sentry/backup.json b/sentry/backup.json new file mode 100644 index 000000000..e83f7b874 --- /dev/null +++ b/sentry/backup.json @@ -0,0 +1,503 @@ +[ +{ + "model": "sites.site", + "pk": 1, + "fields": { + "domain": "example.com", + "name": "example.com" + } +}, +{ + "model": "sentry.option", + "pk": 1, + "fields": { + "key": "sentry:last_worker_ping", + "last_updated": "2024-08-01T13:53:00.189Z", + "last_updated_by": "unknown", + "value": 1722520380.1114867 + } +}, +{ + "model": "sentry.option", + "pk": 2, + "fields": { + "key": "sentry:last_worker_version", + "last_updated": "2024-08-01T13:53:00.238Z", + "last_updated_by": "unknown", + "value": "\"23.7.0.dev0\"" + } +}, +{ + "model": "sentry.option", + "pk": 3, + "fields": { + "key": "system.url-prefix", + "last_updated": "2024-08-01T13:50:36.841Z", + "last_updated_by": "unknown", + "value": "\"http://localhost:9001\"" + } +}, +{ + "model": "sentry.option", + "pk": 4, + "fields": { + "key": "system.admin-email", + "last_updated": "2024-08-01T13:50:36.854Z", + "last_updated_by": "unknown", + "value": "\"admin@tanf.com\"" + } +}, +{ + "model": "sentry.option", + "pk": 5, + "fields": { + "key": "mail.port", + "last_updated": "2024-08-01T13:50:36.860Z", + "last_updated_by": "unknown", + "value": 25 + } +}, +{ + "model": "sentry.option", + "pk": 6, + "fields": { + "key": "mail.username", + "last_updated": "2024-08-01T13:50:36.866Z", + "last_updated_by": "unknown", + "value": "\"\"" + } +}, +{ + "model": "sentry.option", + "pk": 7, + "fields": { + "key": "mail.password", + "last_updated": "2024-08-01T13:50:36.870Z", + "last_updated_by": "unknown", + "value": "\"\"" + } +}, +{ + "model": "sentry.option", + "pk": 8, + "fields": { + "key": "mail.use-tls", + "last_updated": "2024-08-01T13:50:36.873Z", + "last_updated_by": "unknown", + "value": false + } +}, +{ + "model": "sentry.option", + "pk": 9, + "fields": { + "key": "mail.use-ssl", + "last_updated": "2024-08-01T13:50:36.876Z", + "last_updated_by": "unknown", + "value": false + } +}, +{ + "model": "sentry.option", + "pk": 10, + "fields": { + "key": "auth.allow-registration", + "last_updated": "2024-08-01T13:50:36.883Z", + "last_updated_by": "unknown", + "value": false + } +}, +{ + "model": "sentry.option", + "pk": 11, + "fields": { + "key": "sentry:version-configured", + "last_updated": "2024-08-01T13:50:36.889Z", + "last_updated_by": "unknown", + "value": "\"23.7.0.dev0.dd25c26bcece07936bb6401f6fa9c89b96a2118e\"" + } +}, +{ + "model": "sentry.actor", + "pk": 1, + "fields": { + "type": 0, + "user_id": null, + "team": 1 + } +}, +{ + "model": "sentry.actor", + "pk": 2, + "fields": { + "type": 1, + "user_id": 1, + "team": null + } +}, +{ + "model": "sentry.email", + "pk": 1, + "fields": { + "email": "admin@tanf.com", + "date_added": "2024-08-01T13:46:16.066Z" + } +}, +{ + "model": "sentry.organization", + "pk": 1, + "fields": { + "name": "Sentry", + "slug": "sentry", + "status": 0, + "date_added": "2024-08-01T13:44:41.175Z", + "default_role": "member", + "is_test": false, + "flags": "1" + } +}, +{ + "model": "sentry.user", + "pk": 1, + "fields": { + "password": "pbkdf2_sha256$150000$hhBadj48lYdN$XnnczKcFZPnOXsw6KLgbOdg+9Ff8oIFCzKBFuLPh7M4=", + "last_login": "2024-08-01T13:50:33.020Z", + "username": "admin@tanf.com", + "name": "", + "email": "admin@tanf.com", + "is_staff": true, + "is_active": true, + "is_superuser": true, + "is_managed": false, + "is_sentry_app": null, + "is_password_expired": false, + "last_password_change": "2024-08-01T13:46:16.183Z", + "flags": "0", + "session_nonce": null, + "date_joined": "2024-08-01T13:46:16.058Z", + "last_active": "2024-08-01T13:51:16.376Z", + "avatar_type": 0, + "avatar_url": null + } +}, +{ + "model": "sentry.organizationmapping", + "pk": 1, + "fields": { + "organization_id": 1, + "slug": "sentry", + "name": "Sentry", + "date_created": "2024-08-01T13:44:41.239Z", + "customer_id": null, + "verified": false, + "idempotency_key": "", + "region_name": "--monolith--", + "status": 0 + } +}, +{ + "model": "sentry.relayusage", + "pk": 1, + "fields": { + "relay_id": "6d26be62-e8e3-4604-a148-656227d9769f", + "version": "23.6.1", + "first_seen": "2024-08-01T13:48:32.374Z", + "last_seen": "2024-08-01T13:48:32.374Z", + "public_key": "VGxPbAyvOjbRdVdaIF8PmuCq-0YCjRqT9Q0dKhxYg_A" + } +}, +{ + "model": "sentry.relay", + "pk": 1, + "fields": { + "relay_id": "6d26be62-e8e3-4604-a148-656227d9769f", + "public_key": "VGxPbAyvOjbRdVdaIF8PmuCq-0YCjRqT9Q0dKhxYg_A", + "first_seen": null, + "last_seen": null, + "is_internal": true + } +}, +{ + "model": "sentry.useremail", + "pk": 1, + "fields": { + "user": [ + "admin@tanf.com" + ], + "email": "admin@tanf.com", + "validation_hash": "PFGHXGxhV2oGjQI9tZDOLjx6Q1qZWtKN", + "date_hash_added": "2024-08-01T13:46:16.064Z", + "is_verified": false + } +}, +{ + "model": "sentry.userip", + "pk": 1, + "fields": { + "user": [ + "admin@tanf.com" + ], + "ip_address": "192.168.65.1", + "country_code": null, + "region_code": null, + "first_seen": "2024-08-01T13:49:08.204Z", + "last_seen": "2024-08-01T13:49:08.193Z" + } +}, +{ + "model": "sentry.userrole", + "pk": 1, + "fields": { + "date_updated": "2024-08-01T13:44:41.170Z", + "date_added": "2024-08-01T13:44:41.170Z", + "name": "Super Admin", + "permissions": "['broadcasts.admin', 'users.admin', 'options.admin']" + } +}, +{ + "model": "sentry.userroleuser", + "pk": 1, + "fields": { + "date_updated": "2024-08-01T13:46:16.196Z", + "date_added": "2024-08-01T13:46:16.196Z", + "user": [ + "admin@tanf.com" + ], + "role": 1 + } +}, +{ + "model": "sentry.team", + "pk": 1, + "fields": { + "organization": 1, + "slug": "sentry", + "name": "Sentry", + "status": 0, + "actor": 1, + "idp_provisioned": false, + "date_added": "2024-08-01T13:44:41.185Z", + "org_role": null + } +}, +{ + "model": "sentry.organizationmember", + "pk": 1, + "fields": { + "organization": 1, + "user_id": 1, + "email": null, + "role": "owner", + "flags": "0", + "token": null, + "date_added": "2024-08-01T13:46:16.073Z", + "token_expires_at": null, + "has_global_access": true, + "inviter_id": null, + "invite_status": 0, + "type": 50, + "user_is_active": true, + "user_email": "admin@tanf.com" + } +}, +{ + "model": "sentry.project", + "pk": 1, + "fields": { + "slug": "internal", + "name": "Internal", + "forced_color": null, + "organization": 1, + "public": false, + "date_added": "2024-08-01T13:44:41.191Z", + "status": 0, + "first_event": null, + "flags": "10", + "platform": null + } +}, +{ + "model": "sentry.project", + "pk": 2, + "fields": { + "slug": "python-django", + "name": "python-django", + "forced_color": null, + "organization": 1, + "public": false, + "date_added": "2024-08-01T13:50:58.893Z", + "status": 0, + "first_event": null, + "flags": "10", + "platform": "python-django" + } +}, +{ + "model": "sentry.projectkey", + "pk": 1, + "fields": { + "project": 1, + "label": "Default", + "public_key": "20835f66e30e4e19ac9c98c83bbd951f", + "secret_key": "50b61843dabe4b78886b6817421dc6a1", + "roles": "1", + "status": 0, + "date_added": "2024-08-01T13:44:41.205Z", + "rate_limit_count": null, + "rate_limit_window": null, + "data": { + "dynamicSdkLoaderOptions": { + "hasPerformance": true, + "hasReplay": true + } + } + } +}, +{ + "model": "sentry.projectkey", + "pk": 2, + "fields": { + "project": 2, + "label": "Default", + "public_key": "43ebf8abe1434ec6aea2c7b92c465a0e", + "secret_key": "c62d7709665848f88bbe09082e019f75", + "roles": "1", + "status": 0, + "date_added": "2024-08-01T13:50:59.103Z", + "rate_limit_count": null, + "rate_limit_window": null, + "data": { + "dynamicSdkLoaderOptions": { + "hasPerformance": true, + "hasReplay": true + } + } + } +}, +{ + "model": "sentry.rule", + "pk": 1, + "fields": { + "project": 1, + "environment_id": null, + "label": "Send a notification for new issues", + "data": "{\"match\":\"all\",\"conditions\":[{\"id\":\"sentry.rules.conditions.first_seen_event.FirstSeenEventCondition\"}],\"actions\":[{\"id\":\"sentry.mail.actions.NotifyEmailAction\",\"targetType\":\"IssueOwners\",\"targetIdentifier\":null,\"fallthroughType\":\"ActiveMembers\"}]}", + "status": 0, + "source": 0, + "owner": null, + "date_added": "2024-08-01T13:44:41.213Z" + } +}, +{ + "model": "sentry.rule", + "pk": 2, + "fields": { + "project": 2, + "environment_id": null, + "label": "Send a notification for new issues", + "data": "{\"match\":\"all\",\"conditions\":[{\"id\":\"sentry.rules.conditions.first_seen_event.FirstSeenEventCondition\"}],\"actions\":[{\"id\":\"sentry.mail.actions.NotifyEmailAction\",\"targetType\":\"IssueOwners\",\"targetIdentifier\":null,\"fallthroughType\":\"ActiveMembers\"}]}", + "status": 0, + "source": 0, + "owner": null, + "date_added": "2024-08-01T13:50:59.204Z" + } +}, +{ + "model": "sentry.projectteam", + "pk": 1, + "fields": { + "project": 1, + "team": 1 + } +}, +{ + "model": "sentry.projectteam", + "pk": 2, + "fields": { + "project": 2, + "team": 1 + } +}, +{ + "model": "sentry.organizationmemberteam", + "pk": 1, + "fields": { + "team": 1, + "organizationmember": 1, + "is_active": true, + "role": null + } +}, +{ + "model": "sentry.projectoption", + "pk": 1, + "fields": { + "project": 1, + "key": "sentry:relay-rev", + "value": "\"124b064568394513a93c1cf6b96fa531\"" + } +}, +{ + "model": "sentry.projectoption", + "pk": 2, + "fields": { + "project": 1, + "key": "sentry:relay-rev-lastchange", + "value": "\"2024-08-01T13:44:41.228498Z\"" + } +}, +{ + "model": "sentry.projectoption", + "pk": 3, + "fields": { + "project": 1, + "key": "sentry:option-epoch", + "value": 11 + } +}, +{ + "model": "sentry.projectoption", + "pk": 4, + "fields": { + "project": 1, + "key": "sentry:origins", + "value": "[\"*\"]" + } +}, +{ + "model": "sentry.projectoption", + "pk": 5, + "fields": { + "project": 2, + "key": "sentry:relay-rev", + "value": "\"c588a54b4537446c8ca91477867aeddd\"" + } +}, +{ + "model": "sentry.projectoption", + "pk": 6, + "fields": { + "project": 2, + "key": "sentry:relay-rev-lastchange", + "value": "\"2024-08-01T13:51:01.098125Z\"" + } +}, +{ + "model": "sentry.projectoption", + "pk": 7, + "fields": { + "project": 2, + "key": "sentry:option-epoch", + "value": 11 + } +}, +{ + "model": "sentry.projectoption", + "pk": 8, + "fields": { + "project": 2, + "key": "sentry:token", + "value": "\"164d36a4500d11ef938f0242ac130024\"" + } +} +] diff --git a/sentry/docker-compose.yml b/sentry/docker-compose.yml new file mode 100644 index 000000000..86ecb3615 --- /dev/null +++ b/sentry/docker-compose.yml @@ -0,0 +1,496 @@ +x-restart-policy: &restart_policy + restart: unless-stopped +x-depends_on-healthy: &depends_on-healthy + condition: service_healthy +x-depends_on-default: &depends_on-default + condition: service_started +x-healthcheck-defaults: &healthcheck_defaults + # Avoid setting the interval too small, as docker uses much more CPU than one would expect. + # Related issues: + # https://github.com/moby/moby/issues/39102 + # https://github.com/moby/moby/issues/39388 + # https://github.com/getsentry/self-hosted/issues/1000 + interval: "$HEALTHCHECK_INTERVAL" + timeout: "$HEALTHCHECK_TIMEOUT" + retries: $HEALTHCHECK_RETRIES + start_period: 10s +x-sentry-defaults: &sentry_defaults + <<: *restart_policy + image: sentry-self-hosted-local + # Set the platform to build for linux/arm64 when needed on Apple silicon Macs. + platform: ${DOCKER_PLATFORM:-} + build: + context: ./sentry + args: + - SENTRY_IMAGE + depends_on: + redis: + <<: *depends_on-healthy + kafka: + <<: *depends_on-healthy + postgres: + <<: *depends_on-healthy + memcached: + <<: *depends_on-default + smtp: + <<: *depends_on-default + snuba-api: + <<: *depends_on-default + snuba-consumer: + <<: *depends_on-default + snuba-outcomes-consumer: + <<: *depends_on-default + snuba-transactions-consumer: + <<: *depends_on-default + snuba-subscription-consumer-events: + <<: *depends_on-default + snuba-subscription-consumer-transactions: + <<: *depends_on-default + snuba-replacer: + <<: *depends_on-default + symbolicator: + <<: *depends_on-default + vroom: + <<: *depends_on-default + entrypoint: "/etc/sentry/entrypoint.sh" + command: ["run", "web"] + environment: + PYTHONUSERBASE: "/data/custom-packages" + SENTRY_CONF: "/etc/sentry" + SNUBA: "http://snuba-api:1218" + VROOM: "http://vroom:8085" + # Force everything to use the system CA bundle + # This is mostly needed to support installing custom CA certs + # This one is used by botocore + DEFAULT_CA_BUNDLE: &ca_bundle "/etc/ssl/certs/ca-certificates.crt" + # This one is used by requests + REQUESTS_CA_BUNDLE: *ca_bundle + # This one is used by grpc/google modules + GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR: *ca_bundle + # Leaving the value empty to just pass whatever is set + # on the host system (or in the .env file) + SENTRY_EVENT_RETENTION_DAYS: + SENTRY_MAIL_HOST: + SENTRY_MAX_EXTERNAL_SOURCEMAP_SIZE: + # Set this value if you plan on using the Suggested Fix Feature + OPENAI_API_KEY: + volumes: + - "sentry-data:/data" + - "./sentry:/etc/sentry" + - "./geoip:/geoip:ro" + - "./certificates:/usr/local/share/ca-certificates:ro" +x-snuba-defaults: &snuba_defaults + <<: *restart_policy + depends_on: + clickhouse: + <<: *depends_on-healthy + kafka: + <<: *depends_on-healthy + redis: + <<: *depends_on-healthy + image: "$SNUBA_IMAGE" + environment: + SNUBA_SETTINGS: self_hosted + CLICKHOUSE_HOST: clickhouse + DEFAULT_BROKERS: "kafka:9092" + REDIS_HOST: redis + UWSGI_MAX_REQUESTS: "10000" + UWSGI_DISABLE_LOGGING: "true" + # Leaving the value empty to just pass whatever is set + # on the host system (or in the .env file) + SENTRY_EVENT_RETENTION_DAYS: +services: + smtp: + <<: *restart_policy + platform: linux/amd64 + image: tianon/exim4 + hostname: "${SENTRY_MAIL_HOST:-}" + volumes: + - "sentry-smtp:/var/spool/exim4" + - "sentry-smtp-log:/var/log/exim4" + memcached: + <<: *restart_policy + image: "memcached:1.6.21-alpine" + command: ["-I", "${SENTRY_MAX_EXTERNAL_SOURCEMAP_SIZE:-1M}"] + healthcheck: + <<: *healthcheck_defaults + # From: https://stackoverflow.com/a/31877626/5155484 + test: echo stats | nc 127.0.0.1 11211 + redis: + <<: *restart_policy + image: "redis:6.2.13-alpine" + healthcheck: + <<: *healthcheck_defaults + test: redis-cli ping + volumes: + - "sentry-redis:/data" + ulimits: + nofile: + soft: 10032 + hard: 10032 + postgres: + <<: *restart_policy + # Using the same postgres version as Sentry dev for consistency purposes + image: "postgres:14.5" + healthcheck: + <<: *healthcheck_defaults + # Using default user "postgres" from sentry/sentry.conf.example.py or value of POSTGRES_USER if provided + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"] + command: + [ + "postgres", + "-c", + "wal_level=logical", + "-c", + "max_replication_slots=1", + "-c", + "max_wal_senders=1", + ] + environment: + POSTGRES_HOST_AUTH_METHOD: "trust" + entrypoint: /opt/sentry/postgres-entrypoint.sh + volumes: + - "sentry-postgres:/var/lib/postgresql/data" + - type: bind + read_only: true + source: ./postgres/ + target: /opt/sentry/ + zookeeper: + <<: *restart_policy + image: "confluentinc/cp-zookeeper:5.5.7" + environment: + ZOOKEEPER_CLIENT_PORT: "2181" + CONFLUENT_SUPPORT_METRICS_ENABLE: "false" + ZOOKEEPER_LOG4J_ROOT_LOGLEVEL: "WARN" + ZOOKEEPER_TOOLS_LOG4J_LOGLEVEL: "WARN" + KAFKA_OPTS: "-Dzookeeper.4lw.commands.whitelist=ruok" + ulimits: + nofile: + soft: 4096 + hard: 4096 + volumes: + - "sentry-zookeeper:/var/lib/zookeeper/data" + - "sentry-zookeeper-log:/var/lib/zookeeper/log" + - "sentry-secrets:/etc/zookeeper/secrets" + healthcheck: + <<: *healthcheck_defaults + test: + ["CMD-SHELL", 'echo "ruok" | nc -w 2 localhost 2181 | grep imok'] + kafka: + <<: *restart_policy + depends_on: + zookeeper: + <<: *depends_on-healthy + image: "confluentinc/cp-kafka:5.5.7" + environment: + KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181" + KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://kafka:9092" + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1" + KAFKA_OFFSETS_TOPIC_NUM_PARTITIONS: "1" + KAFKA_LOG_RETENTION_HOURS: "24" + KAFKA_MESSAGE_MAX_BYTES: "50000000" #50MB or bust + KAFKA_MAX_REQUEST_SIZE: "50000000" #50MB on requests apparently too + KAFKA_HEAP_OPTS: "-Xmx500M -Xms500M" + CONFLUENT_SUPPORT_METRICS_ENABLE: "false" + KAFKA_LOG4J_LOGGERS: "kafka.cluster=WARN,kafka.controller=WARN,kafka.coordinator=WARN,kafka.log=WARN,kafka.server=WARN,kafka.zookeeper=WARN,state.change.logger=WARN" + KAFKA_LOG4J_ROOT_LOGLEVEL: "WARN" + KAFKA_TOOLS_LOG4J_LOGLEVEL: "WARN" + ulimits: + nofile: + soft: 4096 + hard: 4096 + volumes: + - "sentry-kafka:/var/lib/kafka/data" + - "sentry-kafka-log:/var/lib/kafka/log" + - "sentry-secrets:/etc/kafka/secrets" + healthcheck: + <<: *healthcheck_defaults + test: ["CMD-SHELL", "/usr/bin/kafka-topics --bootstrap-server kafka:9092 --list"] + interval: 10s + timeout: 10s + retries: 30 + clickhouse: + <<: *restart_policy + image: clickhouse-self-hosted-local + build: + context: ./clickhouse + args: + BASE_IMAGE: "${CLICKHOUSE_IMAGE:-}" + ulimits: + nofile: + soft: 262144 + hard: 262144 + volumes: + - "sentry-clickhouse:/var/lib/clickhouse" + - "sentry-clickhouse-log:/var/log/clickhouse-server" + - type: bind + read_only: true + source: ./clickhouse/config.xml + target: /etc/clickhouse-server/config.d/sentry.xml + environment: + # This limits Clickhouse's memory to 30% of the host memory + # If you have high volume and your search return incomplete results + # You might want to change this to a higher value (and ensure your host has enough memory) + MAX_MEMORY_USAGE_RATIO: 0.3 + healthcheck: + test: [ + "CMD-SHELL", + # Manually override any http_proxy envvar that might be set, because + # this wget does not support no_proxy. See: + # https://github.com/getsentry/self-hosted/issues/1537 + "http_proxy='' wget -nv -t1 --spider 'http://localhost:8123/' || exit 1", + ] + interval: 10s + timeout: 10s + retries: 30 + geoipupdate: + image: "ghcr.io/maxmind/geoipupdate:v6.0.0" + # Override the entrypoint in order to avoid using envvars for config. + # Futz with settings so we can keep mmdb and conf in same dir on host + # (image looks for them in separate dirs by default). + entrypoint: ["/usr/bin/geoipupdate", "-d", "/sentry", "-f", "/sentry/GeoIP.conf"] + volumes: + - "./geoip:/sentry" + snuba-api: + <<: *snuba_defaults + # Kafka consumer responsible for feeding events into Clickhouse + snuba-consumer: + <<: *snuba_defaults + command: consumer --storage errors --auto-offset-reset=latest --max-batch-time-ms 750 --no-strict-offset-reset + # Kafka consumer responsible for feeding outcomes into Clickhouse + # Use --auto-offset-reset=earliest to recover up to 7 days of TSDB data + # since we did not do a proper migration + snuba-outcomes-consumer: + <<: *snuba_defaults + command: consumer --storage outcomes_raw --auto-offset-reset=earliest --max-batch-time-ms 750 --no-strict-offset-reset + # Kafka consumer responsible for feeding transactions data into Clickhouse + snuba-transactions-consumer: + <<: *snuba_defaults + command: consumer --storage transactions --consumer-group transactions_group --auto-offset-reset=latest --max-batch-time-ms 750 --no-strict-offset-reset + snuba-replays-consumer: + <<: *snuba_defaults + command: consumer --storage replays --auto-offset-reset=latest --max-batch-time-ms 750 --no-strict-offset-reset + snuba-issue-occurrence-consumer: + <<: *snuba_defaults + command: consumer --storage search_issues --consumer-group generic_events_group --auto-offset-reset=latest --max-batch-time-ms 750 --no-strict-offset-reset + snuba-metrics-consumer: + <<: *snuba_defaults + command: consumer --storage metrics_raw --consumer-group snuba-metrics-consumers --auto-offset-reset=latest --max-batch-time-ms 750 --no-strict-offset-reset + snuba-generic-metrics-distributions-consumer: + <<: *snuba_defaults + command: consumer --storage generic_metrics_distributions_raw --consumer-group snuba-gen-metrics-distributions-consumers --auto-offset-reset=latest --max-batch-time-ms 750 --no-strict-offset-reset + snuba-generic-metrics-sets-consumer: + <<: *snuba_defaults + command: consumer --storage generic_metrics_sets_raw --consumer-group snuba-gen-metrics-sets-consumers --auto-offset-reset=latest --max-batch-time-ms 750 --no-strict-offset-reset + snuba-generic-metrics-counters-consumer: + <<: *snuba_defaults + command: consumer --storage generic_metrics_counters_raw --consumer-group snuba-gen-metrics-counters-consumers --auto-offset-reset=latest --max-batch-time-ms 750 --no-strict-offset-reset + snuba-replacer: + <<: *snuba_defaults + command: replacer --storage errors --auto-offset-reset=latest --no-strict-offset-reset + snuba-subscription-consumer-events: + <<: *snuba_defaults + command: subscriptions-scheduler-executor --dataset events --entity events --auto-offset-reset=latest --no-strict-offset-reset --consumer-group=snuba-events-subscriptions-consumers --followed-consumer-group=snuba-consumers --schedule-ttl=60 --stale-threshold-seconds=900 + snuba-subscription-consumer-transactions: + <<: *snuba_defaults + command: subscriptions-scheduler-executor --dataset transactions --entity transactions --auto-offset-reset=latest --no-strict-offset-reset --consumer-group=snuba-transactions-subscriptions-consumers --followed-consumer-group=transactions_group --schedule-ttl=60 --stale-threshold-seconds=900 + snuba-subscription-consumer-metrics: + <<: *snuba_defaults + command: subscriptions-scheduler-executor --dataset metrics --entity metrics_sets --entity metrics_counters --auto-offset-reset=latest --no-strict-offset-reset --consumer-group=snuba-metrics-subscriptions-consumers --followed-consumer-group=snuba-metrics-consumers --schedule-ttl=60 --stale-threshold-seconds=900 + snuba-profiling-profiles-consumer: + <<: *snuba_defaults + command: consumer --storage profiles --auto-offset-reset=latest --max-batch-time-ms 1000 --no-strict-offset-reset + snuba-profiling-functions-consumer: + <<: *snuba_defaults + command: consumer --storage functions_raw --auto-offset-reset=latest --max-batch-time-ms 1000 --no-strict-offset-reset + symbolicator: + <<: *restart_policy + image: "$SYMBOLICATOR_IMAGE" + volumes: + - "sentry-symbolicator:/data" + - type: bind + read_only: true + source: ./symbolicator + target: /etc/symbolicator + command: run -c /etc/symbolicator/config.yml + symbolicator-cleanup: + <<: *restart_policy + image: symbolicator-cleanup-self-hosted-local + build: + context: ./cron + args: + BASE_IMAGE: "$SYMBOLICATOR_IMAGE" + command: '"55 23 * * * gosu symbolicator symbolicator cleanup"' + volumes: + - "sentry-symbolicator:/data" + web: + <<: *sentry_defaults + ulimits: + nofile: + soft: 4096 + hard: 4096 + healthcheck: + <<: *healthcheck_defaults + test: + - "CMD" + - "/bin/bash" + - "-c" + # Courtesy of https://unix.stackexchange.com/a/234089/108960 + - 'exec 3<>/dev/tcp/127.0.0.1/9000 && echo -e "GET /_health/ HTTP/1.1\r\nhost: 127.0.0.1\r\n\r\n" >&3 && grep ok -s -m 1 <&3' + cron: + <<: *sentry_defaults + command: run cron + worker: + <<: *sentry_defaults + command: run worker + events-consumer: + <<: *sentry_defaults + command: run consumer ingest-events --consumer-group ingest-consumer + attachments-consumer: + <<: *sentry_defaults + command: run consumer ingest-attachments --consumer-group ingest-consumer + transactions-consumer: + <<: *sentry_defaults + command: run consumer ingest-transactions --consumer-group ingest-consumer + metrics-consumer: + <<: *sentry_defaults + command: run consumer ingest-metrics --consumer-group metrics-consumer + generic-metrics-consumer: + <<: *sentry_defaults + command: run consumer ingest-generic-metrics --consumer-group generic-metrics-consumer + billing-metrics-consumer: + <<: *sentry_defaults + command: run consumer billing-metrics-consumer --consumer-group billing-metrics-consumer + ingest-replay-recordings: + <<: *sentry_defaults + command: run consumer ingest-replay-recordings --consumer-group ingest-replay-recordings + ingest-occurrences: + <<: *sentry_defaults + command: run consumer ingest-occurrences --consumer-group ingest-occurrences + ingest-profiles: + <<: *sentry_defaults + command: run consumer --no-strict-offset-reset ingest-profiles --consumer-group ingest-profiles + ingest-monitors: + <<: *sentry_defaults + command: run consumer --no-strict-offset-reset ingest-monitors --consumer-group ingest-monitors + post-process-forwarder-errors: + <<: *sentry_defaults + command: run consumer post-process-forwarder-errors --consumer-group post-process-forwarder --synchronize-commit-log-topic=snuba-commit-log --synchronize-commit-group=snuba-consumers + post-process-forwarder-transactions: + <<: *sentry_defaults + command: run consumer post-process-forwarder-transactions --consumer-group post-process-forwarder --synchronize-commit-log-topic=snuba-transactions-commit-log --synchronize-commit-group transactions_group + post-process-forwarder-issue-platform: + <<: *sentry_defaults + command: run consumer post-process-forwarder-issue-platform --consumer-group post-process-forwarder --synchronize-commit-log-topic=snuba-generic-events-commit-log --synchronize-commit-group generic_events_group + subscription-consumer-events: + <<: *sentry_defaults + command: run consumer events-subscription-results --consumer-group query-subscription-consumer + subscription-consumer-transactions: + <<: *sentry_defaults + command: run consumer transactions-subscription-results --consumer-group query-subscription-consumer + subscription-consumer-metrics: + <<: *sentry_defaults + command: run consumer metrics-subscription-results --consumer-group query-subscription-consumer + subscription-consumer-generic-metrics: + <<: *sentry_defaults + command: run consumer generic-metrics-subscription-results --consumer-group query-subscription-consumer + sentry-cleanup: + <<: *sentry_defaults + image: sentry-cleanup-self-hosted-local + build: + context: ./cron + args: + BASE_IMAGE: sentry-self-hosted-local + entrypoint: "/entrypoint.sh" + command: '"0 0 * * * gosu sentry sentry cleanup --days $SENTRY_EVENT_RETENTION_DAYS"' + nginx: + <<: *restart_policy + ports: + - "$SENTRY_BIND:80/tcp" + image: "nginx:1.25.2-alpine" + volumes: + - type: bind + read_only: true + source: ./nginx + target: /etc/nginx + - sentry-nginx-cache:/var/cache/nginx + depends_on: + - web + - relay + relay: + <<: *restart_policy + image: "$RELAY_IMAGE" + volumes: + - type: bind + read_only: true + source: ./relay + target: /work/.relay + - type: bind + read_only: true + source: ./geoip + target: /geoip + depends_on: + kafka: + <<: *depends_on-healthy + redis: + <<: *depends_on-healthy + web: + <<: *depends_on-healthy + vroom: + <<: *restart_policy + image: "$VROOM_IMAGE" + environment: + SENTRY_KAFKA_BROKERS_PROFILING: "kafka:9092" + SENTRY_KAFKA_BROKERS_OCCURRENCES: "kafka:9092" + SENTRY_BUCKET_PROFILES: file://localhost//var/lib/sentry-profiles + SENTRY_SNUBA_HOST: "http://snuba-api:1218" + volumes: + - sentry-vroom:/var/lib/sentry-profiles + depends_on: + kafka: + <<: *depends_on-healthy + vroom-cleanup: + <<: *restart_policy + image: vroom-cleanup-self-hosted-local + build: + context: ./cron + args: + BASE_IMAGE: "$VROOM_IMAGE" + entrypoint: "/entrypoint.sh" + environment: + # Leaving the value empty to just pass whatever is set + # on the host system (or in the .env file) + SENTRY_EVENT_RETENTION_DAYS: + command: '"0 0 * * * find /var/lib/sentry-profiles -type f -mtime +$SENTRY_EVENT_RETENTION_DAYS -delete"' + volumes: + - sentry-vroom:/var/lib/sentry-profiles + +volumes: + # These store application data that should persist across restarts. + sentry-data: + external: true + sentry-postgres: + external: true + sentry-redis: + external: true + sentry-zookeeper: + external: true + sentry-kafka: + external: true + sentry-clickhouse: + external: true + sentry-symbolicator: + external: true + # This volume stores profiles and should be persisted. + # Not being external will still persist data across restarts. + # It won't persist if someone does a docker compose down -v. + sentry-vroom: + # These store ephemeral data that needn't persist across restarts. + # That said, volumes will be persisted across restarts until they are deleted. + sentry-secrets: + sentry-smtp: + sentry-nginx-cache: + sentry-zookeeper-log: + sentry-kafka-log: + sentry-smtp-log: + sentry-clickhouse-log: diff --git a/tdrs-backend/Pipfile b/tdrs-backend/Pipfile index 6e3775877..a1defabdb 100644 --- a/tdrs-backend/Pipfile +++ b/tdrs-backend/Pipfile @@ -59,6 +59,7 @@ cerberus = "==1.3.4" xlsxwriter = "==3.1.9" openpyxl = "==3.1.2" sendgrid = "==6.10.0" +sentry-sdk = "==2.11.0" [requires] python_version = "3.10.8" diff --git a/tdrs-backend/Pipfile.lock b/tdrs-backend/Pipfile.lock index 7b054c8b7..9a2398138 100644 --- a/tdrs-backend/Pipfile.lock +++ b/tdrs-backend/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "80bf15489b1a4a07f3711904a66fe19188e49eaa58dbd920d20bf4432dcd5518" + "sha256": "902bde5efee2d67d08d56183d72faea8d701ed4c753c2ec2f64cb51f08f1846e" }, "pipfile-spec": 6, "requires": { @@ -83,69 +83,84 @@ }, "certifi": { "hashes": [ - "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b", - "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90" + "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", + "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9" ], "markers": "python_version >= '3.6'", - "version": "==2024.7.4" + "version": "==2024.8.30" }, "cffi": { "hashes": [ - "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", - "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", - "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", - "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", - "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", - "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", - "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", - "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", - "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", - "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", - "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", - "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", - "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", - "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", - "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", - "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", - "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", - "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", - "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", - "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", - "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", - "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", - "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", - "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", - "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", - "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", - "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", - "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", - "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", - "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", - "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", - "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", - "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", - "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", - "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", - "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", - "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", - "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", - "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", - "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", - "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", - "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", - "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", - "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", - "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", - "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", - "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", - "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", - "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", - "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", - "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", - "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" + "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f", + "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab", + "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499", + "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058", + "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693", + "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb", + "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377", + "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885", + "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2", + "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401", + "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4", + "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b", + "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59", + "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f", + "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c", + "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555", + "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa", + "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424", + "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb", + "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2", + "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8", + "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e", + "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9", + "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82", + "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828", + "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759", + "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc", + "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118", + "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf", + "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932", + "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a", + "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29", + "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206", + "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2", + "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c", + "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c", + "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0", + "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a", + "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195", + "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6", + "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9", + "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc", + "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb", + "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0", + "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7", + "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb", + "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a", + "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492", + "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720", + "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42", + "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7", + "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d", + "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d", + "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb", + "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4", + "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2", + "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b", + "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8", + "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e", + "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204", + "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3", + "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150", + "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4", + "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76", + "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e", + "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb", + "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91" ], "markers": "python_version >= '3.8'", - "version": "==1.16.0" + "version": "==1.17.0" }, "charset-normalizer": { "hashes": [ @@ -451,11 +466,11 @@ }, "executing": { "hashes": [ - "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147", - "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc" + "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf", + "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab" ], - "markers": "python_version >= '3.5'", - "version": "==2.0.1" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "flower": { "hashes": [ @@ -484,11 +499,11 @@ }, "idna": { "hashes": [ - "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc", - "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0" + "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac", + "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603" ], "markers": "python_version >= '3'", - "version": "==3.7" + "version": "==3.8" }, "inflection": { "hashes": [ @@ -508,11 +523,11 @@ }, "ipython": { "hashes": [ - "sha256:1cec0fbba8404af13facebe83d04436a7434c7400e59f47acf467c64abd0956c", - "sha256:e6b347c27bdf9c32ee9d31ae85defc525755a1869f14057e900675b9e8d6e6ff" + "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e", + "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c" ], "markers": "python_version >= '3.7'", - "version": "==8.26.0" + "version": "==8.27.0" }, "itypes": { "hashes": [ @@ -555,11 +570,11 @@ }, "kombu": { "hashes": [ - "sha256:011c4cd9a355c14a1de8d35d257314a1d2456d52b7140388561acac3cf1a97bf", - "sha256:5634c511926309c7f9789f1433e9ed402616b56836ef9878f01bd59267b4c7a9" + "sha256:ad200a8dbdaaa2bbc5f26d2ee7d707d9a1fded353a0f4bd751ce8c7d9f449c60", + "sha256:c8dd99820467610b4febbc7a9e8a0d3d7da2d35116b67184418b51cc520ea6b6" ], "markers": "python_version >= '3.8'", - "version": "==5.3.7" + "version": "==5.4.0" }, "markdown": { "hashes": [ @@ -984,13 +999,22 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==6.10.0" }, + "sentry-sdk": { + "hashes": [ + "sha256:4ca16e9f5c7c6bc2fb2d5c956219f4926b148e511fffdbbde711dc94f1e0468f", + "sha256:d964710e2dbe015d9dc4ff0ad16225d68c3b36936b742a6fe0504565b760a3b7" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==2.11.0" + }, "setuptools": { "hashes": [ - "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936", - "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855" + "sha256:bea195a800f510ba3a2bc65645c88b7e016fe36709fefc58a880c4ae8a0138d7", + "sha256:cee604bd76cc092355a4e43ec17aee5369095974f41f088676724dc6bc2c9ef8" ], "markers": "python_version >= '3.8'", - "version": "==71.1.0" + "version": "==74.1.0" }, "six": { "hashes": [ @@ -1072,11 +1096,11 @@ }, "urllib3": { "hashes": [ - "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3", - "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429" + "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", + "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.19" + "version": "==1.26.20" }, "vine": { "hashes": [ @@ -1244,61 +1268,81 @@ "toml" ], "hashes": [ - "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382", - "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1", - "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac", - "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee", - "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166", - "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57", - "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c", - "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b", - "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51", - "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da", - "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450", - "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2", - "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd", - "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d", - "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d", - "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6", - "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca", - "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169", - "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1", - "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713", - "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b", - "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6", - "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c", - "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605", - "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463", - "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b", - "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6", - "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5", - "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63", - "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c", - "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783", - "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44", - "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca", - "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8", - "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d", - "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390", - "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933", - "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67", - "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b", - "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03", - "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b", - "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791", - "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb", - "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807", - "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6", - "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2", - "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428", - "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd", - "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c", - "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94", - "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8", - "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b" + "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca", + "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d", + "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6", + "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", + "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c", + "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b", + "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223", + "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", + "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56", + "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", + "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8", + "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb", + "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388", + "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0", + "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a", + "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", + "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f", + "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a", + "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962", + "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", + "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391", + "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc", + "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", + "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155", + "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb", + "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", + "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c", + "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a", + "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004", + "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060", + "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232", + "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93", + "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129", + "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163", + "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", + "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6", + "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23", + "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", + "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", + "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778", + "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d", + "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36", + "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a", + "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", + "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34", + "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704", + "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106", + "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9", + "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862", + "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", + "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", + "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", + "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", + "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133", + "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb", + "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", + "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d", + "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca", + "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36", + "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c", + "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e", + "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff", + "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", + "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5", + "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02", + "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c", + "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df", + "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3", + "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", + "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959", + "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234", + "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc" ], "markers": "python_version >= '3.8'", - "version": "==7.6.0" + "version": "==7.6.1" }, "docutils": { "hashes": [ @@ -1327,11 +1371,11 @@ }, "faker": { "hashes": [ - "sha256:0f60978314973de02c00474c2ae899785a42b2cf4f41b7987e93c132a2b8a4a9", - "sha256:886ee28219be96949cd21ecc96c4c742ee1680e77f687b095202c8def1a08f06" + "sha256:b17d69312ef6485a720e21bffa997668c88876a5298b278e903ba706243c9c6b", + "sha256:bc460a0e6020966410d0b276043879abca0fac51890f3324bc254bb0a383ee3a" ], "markers": "python_version >= '3.8'", - "version": "==26.0.0" + "version": "==28.1.0" }, "flake8": { "hashes": [ @@ -1625,60 +1669,62 @@ }, "pyyaml": { "hashes": [ - "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", - "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", - "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", - "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", - "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", - "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", - "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", - "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", - "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", - "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", - "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", - "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", - "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", - "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", - "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", - "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", - "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", - "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", - "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", - "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", - "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", - "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", - "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", - "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", - "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", - "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", - "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", - "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", - "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", - "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", - "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", - "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", - "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", - "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", - "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", - "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", - "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", - "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", - "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", - "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", - "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", - "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", - "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", - "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", - "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", - "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", - "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", - "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", - "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", - "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" + "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", + "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", + "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", + "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", + "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", + "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", + "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", + "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", + "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", + "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", + "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", + "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", + "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", + "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", + "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", + "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", + "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", + "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", + "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", + "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", + "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", + "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", + "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", + "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", + "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", + "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", + "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", + "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", + "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", + "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", + "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", + "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", + "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", + "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", + "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", + "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", + "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", + "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", + "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", + "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", + "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", + "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", + "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", + "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", + "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", + "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", + "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", + "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", + "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", + "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", + "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", + "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", + "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" ], - "markers": "python_version >= '3.6'", - "version": "==6.0.1" + "markers": "python_version >= '3.8'", + "version": "==6.0.2" }, "pyyaml-env-tag": { "hashes": [ @@ -1737,49 +1783,47 @@ }, "urllib3": { "hashes": [ - "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3", - "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429" + "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", + "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.19" + "version": "==1.26.20" }, "watchdog": { "hashes": [ - "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7", - "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767", - "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175", - "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459", - "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5", - "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429", - "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6", - "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d", - "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7", - "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28", - "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235", - "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57", - "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a", - "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5", - "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709", - "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee", - "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84", - "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd", - "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba", - "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db", - "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682", - "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35", - "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d", - "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645", - "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253", - "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193", - "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b", - "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44", - "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b", - "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625", - "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e", - "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5" - ], - "markers": "python_version >= '3.8'", - "version": "==4.0.1" + "sha256:1e8ca9b7f5f03d2f0556a43db1e9adf1e5af6adf52e0890f781324514b67a612", + "sha256:20a28c8b0b3edf4ea2b27fb3527fc0a348e983f22a4317d316bb561524391932", + "sha256:2b8cd627b76194e725ed6f48d9524b1ad93a51a0dc3bd0225c56023716245091", + "sha256:39e828c4270452b966bc9d814911a3c7e24c62d726d2a3245f5841664ff56b5e", + "sha256:39f0de161a822402f0f00c68b82349a4d71c9814e749148ca2b083a25606dbf9", + "sha256:4eaebff2f938f5325788cef26521891b2d8ecc8e7852aa123a9b458815f93875", + "sha256:5541a8765c4090decb4dba55d3dceb57724748a717ceaba8dc4f213edb0026e0", + "sha256:59ec6111f3750772badae3403ef17263489ed6f27ac01ec50c0244b2afa258fb", + "sha256:664917cd513538728875a42d5654584b533da88cf06680452c98e73b45466968", + "sha256:6bb68d9adb9c45f0dc1c2b12f4fb6eab0463a8f9741e371e4ede6769064e0785", + "sha256:6fbb4dd5ace074a2969825fde10034b35b31efcb6973defb22eb945b1d3acc37", + "sha256:70e30116849f4ec52240eb1fad83d27e525eae179bfe1c09b3bf120163d731b6", + "sha256:72dbdffe4aa0c36c59f4a5190bceeb7fdfdf849ab98a562b3a783a64cc6dacdd", + "sha256:753c6a4c1eea9d3b96cd58159b49103e66cb288216a414ab9ad234ccc7642ec2", + "sha256:763c6f82bb65504b47d4aea268462b2fb662676676356e04787f332a11f03eb0", + "sha256:8ba1472b5fa7c644e49641f70d7ccc567f70b54d776defa5d6f755dc2edc3fbb", + "sha256:9b1b32f89f95162f09aea6e15d9384f6e0490152f10d7ed241f8a85cddc50658", + "sha256:a03a6ccb846ead406a25a0b702d0a6b88fdfa77becaf907cfcfce7737ebbda1f", + "sha256:a1cd7c919940b15f253db8279a579fb81e4e4e434b39b11a1cb7f54fe3fa46a6", + "sha256:a6b8c6c82ada78479a0df568d27d69aa07105aba9301ac66d1ae162645f4ba34", + "sha256:a791dfc050ed24b82f7f100ae794192594fe863a7e9bdafcdfa5c6e405a981e5", + "sha256:b21e6601efe8453514c2fc21aca57fb5413c3d8b157bfe520b05b57b1788a167", + "sha256:b2d56425dfa0c1e6f8a510f21d3d54ef7fe50bbc29638943c2cb1394b7b49156", + "sha256:c4ae0b3e95455fa9d959aa3b253c87845ad454ef188a4bf5a69cab287c131216", + "sha256:c92812a358eabebe92b12b9290d16dc95c8003654658f6b2676c9a2103a73ceb", + "sha256:c93aa24899cb4e8a51492c7ccc420bea45ced502fe9ef2e83f9ab1107e5a13b5", + "sha256:e321f1561adea30e447130882efe451af519646178d04189d6ba91a8cd7d88a5", + "sha256:f0180e84e6493ef7c82e051334e8c9b00ffd89fa9de5e0613d3c267f6ccf2d38", + "sha256:f3006361dba2005552cc8aa49c44d16a10e0a1939bb3286e888a14f722122808", + "sha256:f66df2c152edf5a2fe472bb2f8a5d562165bcf6cf9686cee5d75e524c21ca895" + ], + "markers": "python_version >= '3.9'", + "version": "==5.0.1" } } } diff --git a/tdrs-backend/tdpservice/settings/local.py b/tdrs-backend/tdpservice/settings/local.py index 171608fe5..bffbddd66 100644 --- a/tdrs-backend/tdpservice/settings/local.py +++ b/tdrs-backend/tdpservice/settings/local.py @@ -1,5 +1,8 @@ """Define configuration settings for local environment.""" import os +import logging +import django + from distutils.util import strtobool from .common import Common @@ -43,3 +46,28 @@ class Local(Common): } REDIS_SERVER_LOCAL = bool(strtobool(os.getenv("REDIS_SERVER_LOCAL", "TRUE"))) + + if os.getenv("ENABLE_SENTRY", "no") == "yes": + # SENTRY + import sentry_sdk + from sentry_sdk.integrations.django import DjangoIntegration + from sentry_sdk.integrations.logging import LoggingIntegration + sentry_sdk.init( + dsn="http://43ebf8abe1434ec6aea2c7b92c465a0e@host.docker.internal:9001/2", + # Set traces_sample_rate to 1.0 to capture 100% + # of transactions for performance monitoring. + integrations=[ + DjangoIntegration( + transaction_style='url', + middleware_spans=True, + signals_spans=True, + signals_denylist=[ + django.db.models.signals.pre_init, + django.db.models.signals.post_init, + ], + cache_spans=False, + ), + LoggingIntegration(level=logging.DEBUG, event_level=logging.DEBUG) + ], + traces_sample_rate=1.0, + ) From 1a3e1dc980d0f2f57256ef43f3046f73aab454fc Mon Sep 17 00:00:00 2001 From: raftmsohani <97037188+raftmsohani@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:07:04 -0400 Subject: [PATCH 3/6] Bugfix remove ipdb (#3169) * remove ipdb * update piplock --- tdrs-backend/Pipfile | 1 - tdrs-backend/Pipfile.lock | 132 ++------------------------------------ 2 files changed, 4 insertions(+), 129 deletions(-) diff --git a/tdrs-backend/Pipfile b/tdrs-backend/Pipfile index a1defabdb..a46415b51 100644 --- a/tdrs-backend/Pipfile +++ b/tdrs-backend/Pipfile @@ -39,7 +39,6 @@ django-csp = "==3.7" djangorestframework = "==3.13.1" drf-yasg = "==1.20.0" gunicorn = "==20.1.0" -ipdb = "==0.13.9" jwcrypto = "==1.3.1" markdown = "==3.3.7" psycopg2 = "==2.9.9" diff --git a/tdrs-backend/Pipfile.lock b/tdrs-backend/Pipfile.lock index 9a2398138..1ce6d4773 100644 --- a/tdrs-backend/Pipfile.lock +++ b/tdrs-backend/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "902bde5efee2d67d08d56183d72faea8d701ed4c753c2ec2f64cb51f08f1846e" + "sha256": "3cc4c598cd727b0e161a34560e9efa1e43a3d4d137d6983b2b059947707dee05" }, "pipfile-spec": 6, "requires": { @@ -32,13 +32,6 @@ "markers": "python_version >= '3.8'", "version": "==3.8.1" }, - "asttokens": { - "hashes": [ - "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", - "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0" - ], - "version": "==2.4.1" - }, "billiard": { "hashes": [ "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547", @@ -236,14 +229,6 @@ "markers": "python_version >= '3.6'", "version": "==3.4.7" }, - "decorator": { - "hashes": [ - "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", - "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" - ], - "markers": "python_version >= '3.7'", - "version": "==5.1.1" - }, "deprecated": { "hashes": [ "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c", @@ -456,22 +441,6 @@ "markers": "python_version >= '3.6'", "version": "==1.1.0" }, - "exceptiongroup": { - "hashes": [ - "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", - "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc" - ], - "markers": "python_version < '3.11'", - "version": "==1.2.2" - }, - "executing": { - "hashes": [ - "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf", - "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab" - ], - "markers": "python_version >= '3.8'", - "version": "==2.1.0" - }, "flower": { "hashes": [ "sha256:77be4bece7330893703e8cca3f3baddba356a0019186594a961e3968289da7ec", @@ -513,22 +482,6 @@ "markers": "python_version >= '3.5'", "version": "==0.5.1" }, - "ipdb": { - "hashes": [ - "sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5" - ], - "index": "pypi", - "markers": "python_version >= '2.7'", - "version": "==0.13.9" - }, - "ipython": { - "hashes": [ - "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e", - "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c" - ], - "markers": "python_version >= '3.7'", - "version": "==8.27.0" - }, "itypes": { "hashes": [ "sha256:03da6872ca89d29aef62773672b2d408f490f80db48b23079a4b194c86dd04c6", @@ -536,14 +489,6 @@ ], "version": "==1.2.0" }, - "jedi": { - "hashes": [ - "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd", - "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0" - ], - "markers": "python_version >= '3.6'", - "version": "==0.19.1" - }, "jinja2": { "hashes": [ "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", @@ -651,14 +596,6 @@ "markers": "python_version >= '3.7'", "version": "==2.1.5" }, - "matplotlib-inline": { - "hashes": [ - "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", - "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca" - ], - "markers": "python_version >= '3.8'", - "version": "==0.1.7" - }, "openpyxl": { "hashes": [ "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184", @@ -676,22 +613,6 @@ "markers": "python_version >= '3.8'", "version": "==24.1" }, - "parso": { - "hashes": [ - "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", - "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d" - ], - "markers": "python_version >= '3.6'", - "version": "==0.8.4" - }, - "pexpect": { - "hashes": [ - "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", - "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" - ], - "markers": "sys_platform != 'win32' and sys_platform != 'emscripten'", - "version": "==4.9.0" - }, "pillow": { "hashes": [ "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885", @@ -814,20 +735,6 @@ "markers": "python_version >= '3.7'", "version": "==2.9.9" }, - "ptyprocess": { - "hashes": [ - "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", - "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" - ], - "version": "==0.7.0" - }, - "pure-eval": { - "hashes": [ - "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", - "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42" - ], - "version": "==0.2.3" - }, "pycparser": { "hashes": [ "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", @@ -836,14 +743,6 @@ "markers": "python_version >= '3.8'", "version": "==2.22" }, - "pygments": { - "hashes": [ - "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", - "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a" - ], - "markers": "python_version >= '3.8'", - "version": "==2.18.0" - }, "pyjwt": { "hashes": [ "sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf", @@ -1010,11 +909,11 @@ }, "setuptools": { "hashes": [ - "sha256:bea195a800f510ba3a2bc65645c88b7e016fe36709fefc58a880c4ae8a0138d7", - "sha256:cee604bd76cc092355a4e43ec17aee5369095974f41f088676724dc6bc2c9ef8" + "sha256:2353af060c06388be1cecbf5953dcdb1f38362f87a2356c480b6b4d5fcfc8847", + "sha256:fc91b5f89e392ef5b77fe143b17e32f65d3024744fba66dc3afe07201684d766" ], "markers": "python_version >= '3.8'", - "version": "==74.1.0" + "version": "==74.1.1" }, "six": { "hashes": [ @@ -1032,27 +931,12 @@ "markers": "python_version >= '3.8'", "version": "==0.5.1" }, - "stack-data": { - "hashes": [ - "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", - "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695" - ], - "version": "==0.6.3" - }, "starkbank-ecdsa": { "hashes": [ "sha256:9399c3371b899d4a235b68a1ed7919d202fbf024bd2c863ae8ebdad343c2a63a" ], "version": "==2.2.0" }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" - ], - "markers": "python_version >= '3.7'", - "version": "==0.10.2" - }, "tornado": { "hashes": [ "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8", @@ -1070,14 +954,6 @@ "markers": "python_version >= '3.8'", "version": "==6.4.1" }, - "traitlets": { - "hashes": [ - "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", - "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f" - ], - "markers": "python_version >= '3.8'", - "version": "==5.14.3" - }, "typing-extensions": { "hashes": [ "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", From abd8609eccb904833dcc245c51b8c1ebaea70859 Mon Sep 17 00:00:00 2001 From: raftmsohani <97037188+raftmsohani@users.noreply.github.com> Date: Wed, 4 Sep 2024 09:50:00 -0400 Subject: [PATCH 4/6] 3074 TDP Datafile page for DIGIT and Sys Admin groups (#3158) * added migration and changes * 3074 corrected test * revert changes * 3074 added similar group permissions to DIGITTeam as Admin * remove logging for frontend * 3074-added permissions for System Admin --- Taskfile.yml | 4 +- ...ers_digit_group_add_datafile_permission.py | 58 +++++++++++++++++++ .../tdpservice/users/test/test_permissions.py | 4 +- .../src/components/Reports/Reports.jsx | 15 +++-- 4 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 tdrs-backend/tdpservice/users/migrations/0041_users_digit_group_add_datafile_permission.py diff --git a/Taskfile.yml b/Taskfile.yml index 5985f0604..2c67784b9 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -95,7 +95,7 @@ tasks: desc: Restart backend web server dir: tdrs-backend cmds: - - docker-compose -f docker-compose.yml restart -d + - docker-compose -f docker-compose.yml restart backend-bash: desc: Open a shell in the backend container @@ -178,7 +178,7 @@ tasks: desc: Restart frontend web server dir: tdrs-frontend cmds: - - docker-compose -f docker-compose.yml restart -d + - docker-compose -f docker-compose.yml restart frontend-av: desc: Start frontend with optional clamav service diff --git a/tdrs-backend/tdpservice/users/migrations/0041_users_digit_group_add_datafile_permission.py b/tdrs-backend/tdpservice/users/migrations/0041_users_digit_group_add_datafile_permission.py new file mode 100644 index 000000000..67dbd70ab --- /dev/null +++ b/tdrs-backend/tdpservice/users/migrations/0041_users_digit_group_add_datafile_permission.py @@ -0,0 +1,58 @@ +# Generated by Django 3.2.5 on 2021-08-16 14:10 +from django.contrib.auth.models import Group +from django.db import migrations + +from tdpservice.users.permissions import ( + add_permissions_q, + get_permission_ids_for_model, + view_permissions_q +) + + +def set_digit_team_permissions(apps, schema_editor): + """Set relevant Group Permissions for DIGIT Team group.""" + digit = ( + apps.get_model('auth', 'Group').objects.get(name='DIGIT Team') + ) + + stt_permissions = get_permission_ids_for_model( + 'stts', + 'stt', + filters=[view_permissions_q] + ) + + + datafile_permissions = get_permission_ids_for_model( + 'data_files', + 'datafile', + filters=[view_permissions_q, add_permissions_q] + ) + + # Assign model permissions + digit.permissions.add(*datafile_permissions, *stt_permissions) + +def unset_digit_team_permissions(apps, schema_editor): + """Remove all Group Permissions added to DIGIT Team.""" + digit = ( + apps.get_model('auth', 'Group').objects.get(name='DIGIT Team') + ) + datafile_permissions = get_permission_ids_for_model( + 'data_files', + 'datafile', + filters=[view_permissions_q, add_permissions_q] + ) + digit.permissions.remove(*datafile_permissions) + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '__latest__'), + ('users', '0040_users_digit_group_permissions'), + ] + + operations = [ + migrations.RunPython( + set_digit_team_permissions, + reverse_code=unset_digit_team_permissions + ) + ] diff --git a/tdrs-backend/tdpservice/users/test/test_permissions.py b/tdrs-backend/tdpservice/users/test/test_permissions.py index 608305131..ae53b3cda 100644 --- a/tdrs-backend/tdpservice/users/test/test_permissions.py +++ b/tdrs-backend/tdpservice/users/test/test_permissions.py @@ -180,6 +180,8 @@ def test_digit_team_permissions(digit_team): expected_permissions = {'parsers.view_parsererror', 'parsers.view_datafilesummary', 'data_files.view_datafile', + 'data_files.add_datafile', + 'stts.view_stt', 'search_indexes.view_ssp_m3', 'search_indexes.view_tribal_tanf_t5', 'search_indexes.view_tribal_tanf_t3', @@ -200,7 +202,7 @@ def test_digit_team_permissions(digit_team): 'search_indexes.view_tanf_t4', 'search_indexes.view_ssp_m6', 'search_indexes.view_tribal_tanf_t2', - 'search_indexes.view_tanf_t6' + 'search_indexes.view_tanf_t6', } group_permissions = digit_team.get_group_permissions() assert group_permissions == expected_permissions diff --git a/tdrs-frontend/src/components/Reports/Reports.jsx b/tdrs-frontend/src/components/Reports/Reports.jsx index 1f00df2c2..82e161e37 100644 --- a/tdrs-frontend/src/components/Reports/Reports.jsx +++ b/tdrs-frontend/src/components/Reports/Reports.jsx @@ -38,6 +38,9 @@ function Reports() { // The logged in user saved in our redux `auth` state object const user = useSelector((state) => state.auth.user) const isOFAAdmin = useSelector(selectPrimaryUserRole)?.name === 'OFA Admin' + const isDIGITTeam = useSelector(selectPrimaryUserRole)?.name === 'DIGIT Team' + const isSystemAdmin = + useSelector(selectPrimaryUserRole)?.name === 'OFA System Admin' const sttList = useSelector((state) => state?.stts?.sttList) const [errorModalVisible, setErrorModalVisible] = useState(false) @@ -59,7 +62,8 @@ function Reports() { Q4: 'Quarter 4 (July - September)', } - const currentStt = isOFAAdmin ? selectedStt : userProfileStt + const currentStt = + isOFAAdmin || isDIGITTeam || isSystemAdmin ? selectedStt : userProfileStt const stt = sttList?.find((stt) => stt?.name === currentStt) @@ -68,7 +72,8 @@ function Reports() { const errorsCount = formValidation.errors - const missingStt = !isOFAAdmin && !currentStt + const missingStt = + !isOFAAdmin && !isDIGITTeam && !isSystemAdmin && !currentStt const errorsRef = useRef(null) @@ -194,7 +199,7 @@ function Reports() { ) const touchedFields = Object.keys(touched).length - const expected_fields = isOFAAdmin ? 3 : 2 + const expected_fields = isOFAAdmin || isDIGITTeam || isSystemAdmin ? 3 : 2 const errors = touchedFields === 3 ? expected_fields - form.length : 0 @@ -215,6 +220,8 @@ function Reports() { setFormValidationState, touched, isOFAAdmin, + isDIGITTeam, + isSystemAdmin, ]) return ( @@ -237,7 +244,7 @@ function Reports() { )}
- {isOFAAdmin && ( + {(isOFAAdmin || isDIGITTeam || isSystemAdmin) && (
Date: Wed, 4 Sep 2024 15:47:33 -0400 Subject: [PATCH 5/6] 2561 Deactivating inactive user automatically (#3145) * Added logic and test for deactivating the user automatically * 2561- linting * added admin notification * linting * [2561] added sending email to admin * Update tdrs-backend/tdpservice/email/helpers/admin_notifications.py Co-authored-by: Alex P. <63075587+ADPennington@users.noreply.github.com> --------- Co-authored-by: Alex P. <63075587+ADPennington@users.noreply.github.com> --- tdrs-backend/tdpservice/email/email_enums.py | 1 + .../helpers/account_deactivation_warning.py | 4 +-- .../email/helpers/admin_notifications.py | 35 +++++++++++++++++++ tdrs-backend/tdpservice/email/tasks.py | 25 +++++++++++++ .../templates/account-deactivated-admin.html | 18 ++++++++++ .../test/test_user_deactivation_warning.py | 16 +++++++++ tdrs-backend/tdpservice/settings/common.py | 7 ++++ 7 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 tdrs-backend/tdpservice/email/helpers/admin_notifications.py create mode 100644 tdrs-backend/tdpservice/email/templates/account-deactivated-admin.html diff --git a/tdrs-backend/tdpservice/email/email_enums.py b/tdrs-backend/tdpservice/email/email_enums.py index 3b7028681..4527b6016 100644 --- a/tdrs-backend/tdpservice/email/email_enums.py +++ b/tdrs-backend/tdpservice/email/email_enums.py @@ -13,4 +13,5 @@ class EmailType(Enum): REQUEST_DENIED = 'request-denied.html' DEACTIVATION_WARNING = 'account-deactivation-warning.html' ACCOUNT_DEACTIVATED = 'account-deactivated.html' + ACCOUNT_DEACTIVATED_ADMIN = 'account-deactivated-admin.html' UPCOMING_SUBMISSION_DEADLINE = 'upcoming-submission-deadline.html' diff --git a/tdrs-backend/tdpservice/email/helpers/account_deactivation_warning.py b/tdrs-backend/tdpservice/email/helpers/account_deactivation_warning.py index 75af0a4ef..9851c155c 100644 --- a/tdrs-backend/tdpservice/email/helpers/account_deactivation_warning.py +++ b/tdrs-backend/tdpservice/email/helpers/account_deactivation_warning.py @@ -3,12 +3,10 @@ from tdpservice.email.email import automated_email from datetime import datetime, timedelta, timezone from django.conf import settings - +from tdpservice.users.models import User def send_deactivation_warning_email(users, days): """Send an email to users that are about to be deactivated.""" - from tdpservice.users.models import User - template_path = EmailType.DEACTIVATION_WARNING.value text_message = f'Your account will be deactivated in {days} days.' subject = f'Account Deactivation Warning: {days} days remaining' diff --git a/tdrs-backend/tdpservice/email/helpers/admin_notifications.py b/tdrs-backend/tdpservice/email/helpers/admin_notifications.py new file mode 100644 index 000000000..594e48710 --- /dev/null +++ b/tdrs-backend/tdpservice/email/helpers/admin_notifications.py @@ -0,0 +1,35 @@ +"""helper functions to administer user accounts.""" + +def email_admin_deactivated_user(user): + """Send an email to OFA Admins when a user is deactivated.""" + from tdpservice.users.models import User + from tdpservice.email.email_enums import EmailType + from tdpservice.email.email import automated_email, log + from tdpservice.email.tasks import get_ofa_admin_user_emails + + recipient_emails = get_ofa_admin_user_emails() + logger_context = { + 'user_id': user.id, + 'object_id': user.id, + 'object_repr': user.username, + 'content_type': User, + } + + template_path = EmailType.ACCOUNT_DEACTIVATED_ADMIN.value + text_message = 'A user account has been deactivated.' + subject = ' TDP User Account Deactivated due to Inactivity' + context = { + 'user': user, + } + + log(f"Preparing email to OFA Admins for deactivated user {user.username}", logger_context=logger_context) + + for recipient_email in recipient_emails: + automated_email( + email_path=template_path, + recipient_email=recipient_email, + subject=subject, + email_context=context, + text_message=text_message, + logger_context=logger_context + ) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 089ea4e8d..179eeed86 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -16,10 +16,35 @@ from tdpservice.email.email import automated_email, log from tdpservice.email.email_enums import EmailType from tdpservice.parsers.util import calendar_to_fiscal +from tdpservice.email.helpers.admin_notifications import email_admin_deactivated_user logger = logging.getLogger(__name__) +@shared_task +def deactivate_users(): + """Deactivate users that have not logged in in the last 180 days.""" + users_to_deactivate = User.objects.filter( + last_login__lte=datetime.now(tz=timezone.utc) - timedelta(days=180), + account_approval_status=AccountApprovalStatusChoices.APPROVED, + ) + + for user in users_to_deactivate: + user.account_approval_status = AccountApprovalStatusChoices.DEACTIVATED + user.groups.clear() + user.save() + + logger_context = { + 'user_id': user.id, + 'object_id': user.id, + 'object_repr': user.username, + } + email_admin_deactivated_user(user) + log( + f"Deactivated user {user.username} for inactivity.", + logger_context=logger_context if not settings.DEBUG else None + ) + @shared_task def check_for_accounts_needing_deactivation_warning(): diff --git a/tdrs-backend/tdpservice/email/templates/account-deactivated-admin.html b/tdrs-backend/tdpservice/email/templates/account-deactivated-admin.html new file mode 100644 index 000000000..d8b5130fa --- /dev/null +++ b/tdrs-backend/tdpservice/email/templates/account-deactivated-admin.html @@ -0,0 +1,18 @@ +{% extends 'base.html' %} +{% block content %} + +

+ +

The following user account for the TANF Data Portal (TDP) has been deactivated.

+ +

Account Information:

+
    +
  • Name: {{ user.first_name }}
  • +
  • Last name: {{ user.last_name }}
  • +
  • Email: {{ user.email }}
  • +
+ +

Thank you,

+ TDP Team +

+{% endblock %} \ No newline at end of file diff --git a/tdrs-backend/tdpservice/scheduling/test/test_user_deactivation_warning.py b/tdrs-backend/tdpservice/scheduling/test/test_user_deactivation_warning.py index 369688d1a..1f4c2caf7 100644 --- a/tdrs-backend/tdpservice/scheduling/test/test_user_deactivation_warning.py +++ b/tdrs-backend/tdpservice/scheduling/test/test_user_deactivation_warning.py @@ -30,6 +30,22 @@ def test_deactivation_email_10_days(user, mocker): assert tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email.called_once_with( users=[user], days=10) +@pytest.mark.django_db +def test_deactivate_users(user, mocker): + """Test that the deactivate_users task runs.""" + mocker.patch( + 'tdpservice.email.helpers.admin_notifications.email_admin_deactivated_user', + return_value=None + ) + user.groups.add() + user.last_login = datetime.now(tz=timezone.utc) - timedelta(days=181) + user.account_approval_status = AccountApprovalStatusChoices.APPROVED + user.save() + tdpservice.email.tasks.deactivate_users() + assert user.groups.count() == 0 + assert tdpservice.email.helpers.admin_notifications.email_admin_deactivated_user.called_once_with(user) + + @pytest.mark.django_db def test_deactivation_email_3_days(user, mocker): """Test that the check_for_accounts_needing_deactivation_warning task runs.""" diff --git a/tdrs-backend/tdpservice/settings/common.py b/tdrs-backend/tdpservice/settings/common.py index 7a7baad72..89acbe10c 100644 --- a/tdrs-backend/tdpservice/settings/common.py +++ b/tdrs-backend/tdpservice/settings/common.py @@ -475,6 +475,13 @@ class Common(Configuration): 'expires': 15.0, }, }, + 'Deactivate Users': { + 'task': 'tdpservice.email.tasks.deactivate_users', + 'schedule': crontab(day_of_week='*', hour='13', minute='0'), # Every day at 1pm UTC (9am EST) + 'options': { + 'expires': 15.0, + }, + }, 'Email Admin Number of Access Requests' : { 'task': 'tdpservice.email.tasks.email_admin_num_access_requests', 'schedule': crontab(minute='0', hour='1', day_of_week='*', day_of_month='*', month_of_year='*'), # Every day at 1am UTC (9pm EST) From db43855b279f01772086dd30fca93a59d7af1a3e Mon Sep 17 00:00:00 2001 From: robgendron <163159602+robgendron@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:35:20 -0400 Subject: [PATCH 6/6] Create sprint-106-summary.md (#3166) Co-authored-by: Andrew <84722778+andrew-jameson@users.noreply.github.com> --- docs/Sprint-Review/sprint-106-summary.md | 97 ++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 docs/Sprint-Review/sprint-106-summary.md diff --git a/docs/Sprint-Review/sprint-106-summary.md b/docs/Sprint-Review/sprint-106-summary.md new file mode 100644 index 000000000..6d211ed81 --- /dev/null +++ b/docs/Sprint-Review/sprint-106-summary.md @@ -0,0 +1,97 @@ +# sprint-106-summary + +8/14/202 - 8/27/2024 + +### Priority Setting + +* Reparsing + * Reasoning: OFA has ability to reparse and the data process with latest system logic which will enable STTs to get error reports that are meaningful and relevant and OFA gets the needed data. System, as a whole, will be more flexible with data flow (able to hot fix and hit reparse). Additionally, we want to avoid missing data and be able to repopulate the database after cleaning the data. +* Data Access Strategy + * Reasoning: Creating daily blockers +* Admin Console Improvements + * Reasoning: Trigger has been met to refine tickets (Research Synthesis) +* Improved Dev Tooling + * improve test\_parse.py 2641 + * separate celery 2592 + * Reasoning: Developing / refining tickets to support the above priorities – These tickets will enhance capabilities while the above are being flushed out + +### Sprint Goal + +**Dev:** + +_**Reparsing, Admin Console Improvements, Application Health Monitoring work, and Improved Dev Tooling**_ + +* \#2965 — As tech lead, I want a database seed implemented for testing +* \#3102 — Admin Exp: Django Implement Multi-Select Fiscal Period Dropdown For Data Export +* \#2561 — As a sys admin, I need TDP to automatically deactivate accounts that are inactive for 180 days +* \#3110 — Spike - Investigate Custom Filter Integration +* \#3137 — \[bug] OFA unable to export data to csv by record type and fiscal period +* \#3074 — TDP Data Files page permissions for DIGIT & Sys Admin user groups +* \#3076 — Admin Filter Enhancements for Data Files Page + +**DevOps:** + +_**Successful deployments across environments and pipeline stability investments**_ + +* + +**Design:** + +_**Support reviews, In-app banner to support parsed data, Continue Error Audit (Cat 4)**_ + +* \#2968 — \[Design Deliverable] Update Error Audit for Cat 4 / QA +* \#3114 — \[Design Spike] In-app banner for submission history pages w/ data parsed before May 2024 +* \#3143 — August release notes — Knowledge Center & Email Template + + + +## Tickets + +### Completed/Merged + +* [#2985 \[Design Deliverable\] Email spec for Admin Notification for stuck files](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2985) +* [#2996 Add dynamic field name to cat4 error messages](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2996) +* [#3143 August release notes — Knowledge Center & Email Template](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3143) +* [#3061 \[a11y fix\] Django multi-select filter ](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3061) +* [#2954 Extend SESSION\_COOKIE\_AGE](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2954) +* [#3079 DB Backup Script Fix](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3079) + +### Submitted (QASP Review, OCIO Review) + +* [#3064 Re-parse Meta Model](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3064) +* [#3065 Spike - Guarantee Sequential Execution of Re-parse Command](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3065) +* [#2792 \[Error Audit\] Category 3 error messages clean-up](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2792) +* [#2883 Pre-Made Reporting Dashboards on Kibana](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2883) +* [#2561 As a sys admin, I need TDP to automatically deactivate accounts that are inactive for 180 days](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2561) +* [#3078 \[Research Synthesis\] DIGIT Admin Experience Improvements](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3078) + +### Ready to Merge + +### Closed (Not Merged) + +* [#3147 S3 buckets contain fewer datafiles than DAC](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3147) + +### Moved to Next Sprint + +**In Progress** + +* [#2965 As tech lead, I want a database seed implemented for testing](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2965) +* [#2458 Integrate Nexus into CircleCI](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2458) +* [#3137 \[bug\] OFA unable to export data to csv by record type and fiscal period](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3137) +* [#2968 \[Design Deliverable\] Update Error Audit for Cat 4 / QA](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/2968) +* [#3060 As a TDP user, I need to stay logged in when I'm actively using the system](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3060) +* [#3074 TDP Data Files page permissions for DIGIT & Sys Admin user groups](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3074) +* [#3114 \[Design Spike\] In-app banner for submission history pages w/ data parsed before May 2024](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3114) +* [#3142 \[Research Spike\] Get more detail about Yun & DIGIT's data workflow and use cases](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3142) + +#### Blocked + +* + +**Raft Review** + +* [#3043 Sentry: Local environment for Debugging](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3043) +* [#3110 Spike - Investigate Custom Filter Integration](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3110) +* [#3102 Admin Exp: Django Implement Multi-Select Fiscal Period Dropdown For Data Export ](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3102) +* [#3087 Admin By Newest Filter Enhancements for Data Files Page](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3087) +* [#3076 Admin Filter Enhancements for Data Files Page ](https://app.zenhub.com/workspaces/sprint-board-5f18ab06dfd91c000f7e682e/issues/gh/raft-tech/tanf-app/3076)