Compare commits

...

80 Commits

Author SHA1 Message Date
ccostino
acfbffa3d8 Merge pull request #1745 from GSA/pythonupgrade
python upgrade to 3.13.2
2025-06-03 14:53:46 -04:00
Kenneth Kehl
965bb3047c update 2025-06-03 08:57:34 -07:00
ccostino
bcd33e7af8 Merge pull request #1751 from GSA/dependabot/pip/pytest-8.4.0
Bump pytest from 8.3.5 to 8.4.0
2025-06-03 10:47:27 -04:00
dependabot[bot]
64535abb7c Bump pytest from 8.3.5 to 8.4.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.5 to 8.4.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.5...8.4.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 8.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 12:56:28 +00:00
ccostino
25ee386155 Merge pull request #1750 from GSA/dependabot/pip/celery-5.5.3
Bump celery from 5.5.2 to 5.5.3
2025-06-03 08:54:17 -04:00
dependabot[bot]
e15a49ba18 Bump celery from 5.5.2 to 5.5.3
Bumps [celery](https://github.com/celery/celery) from 5.5.2 to 5.5.3.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.5.2...v5.5.3)

---
updated-dependencies:
- dependency-name: celery
  dependency-version: 5.5.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 21:49:47 +00:00
ccostino
6d8e2221d0 Merge pull request #1748 from GSA/fix-daily-checks
Update daily checks to match PR checks
2025-06-02 09:52:15 -04:00
Carlo Costino
8af59b1c55 Update daily checks to match PR checks
This changeset adds the same additional steps needed in our PR checks to make sure the daily checks work properly with the recent Poetry update.  It also updates our PR checks to use the latest pip-audit GitHub action.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-06-02 09:23:02 -04:00
Beverly Nguyen
abdaa74d0b Merge pull request #1747 from GSA/remove-python-vuln-ignore-again
Remove extra vulnerability from our ignore list
2025-05-30 14:21:57 -07:00
Kenneth Kehl
44f2c52a52 merge from main 2025-05-30 13:29:53 -07:00
Carlo Costino
cf4deb083b Remove extra vulnerability from our ignore list
This changeset fixes an oversight where a vulnerability got added back to our ignore list.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-05-30 16:28:03 -04:00
Kenneth Kehl
fb3bf6d9b1 okay upgrade to 3.13.2 now to stay in sync with admin 2025-05-30 12:35:27 -07:00
Kenneth Kehl
86c7e77197 try eventlet 0.40.0 2025-05-30 11:37:43 -07:00
Kenneth Kehl
f7f92dd1f4 try python 3.13.3 2025-05-30 11:20:56 -07:00
Kenneth Kehl
ad17ddc23f try upgrading to python 3.13.1 2025-05-30 11:09:10 -07:00
Kenneth Kehl
ac9e3a49d8 try downgrading eventlet to 0.33.3 2025-05-30 11:01:31 -07:00
Kenneth Kehl
72289ace08 python upgrade 2025-05-30 10:49:42 -07:00
ccostino
cbe50a1aa7 Merge pull request #1744 from GSA/add-detect-secrets-docs
Add detect-secrets documentation
2025-05-30 11:50:14 -04:00
Carlo Costino
0a28b33e99 Add detect-secrets documentation
This changeset adds documentation to help our team manage our secrets detection with the detect-secrets pre-commit plugin.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-05-30 11:39:07 -04:00
ccostino
c301513caf Merge pull request #1738 from GSA/poetry
upgrade poetry
2025-05-30 10:55:47 -04:00
Kenneth Kehl
e5484f0723 Update Makefile
Co-authored-by: ccostino <ccostino@users.noreply.github.com>
2025-05-29 11:14:29 -07:00
Kenneth Kehl
222e258e34 Update Makefile
Co-authored-by: ccostino <ccostino@users.noreply.github.com>
2025-05-29 11:14:00 -07:00
Kenneth Kehl
d40ab17770 Update Makefile
Co-authored-by: ccostino <ccostino@users.noreply.github.com>
2025-05-29 11:13:36 -07:00
Kenneth Kehl
3b5f11932f ugh secrets 2025-05-29 10:15:58 -07:00
Kenneth Kehl
c2ed11d28e add comments about poetry upgrade 2025-05-29 08:48:00 -07:00
Kenneth Kehl
59af82b0a4 merge from main 2025-05-29 08:05:46 -07:00
Alex Janousek
062683ada6 Merge pull request #1742 from GSA/dependabot/pip/phonenumbers-9.0.6
Bump phonenumbers from 9.0.5 to 9.0.6
2025-05-29 09:19:29 -04:00
dependabot[bot]
47a3c6dc91 Bump phonenumbers from 9.0.5 to 9.0.6
Bumps [phonenumbers](https://github.com/daviddrysdale/python-phonenumbers) from 9.0.5 to 9.0.6.
- [Commits](https://github.com/daviddrysdale/python-phonenumbers/compare/v9.0.5...v9.0.6)

---
updated-dependencies:
- dependency-name: phonenumbers
  dependency-version: 9.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-29 13:12:28 +00:00
Beverly Nguyen
500dc80557 Merge pull request #1743 from GSA/ignore-redis-false-report
Updated pip-audit ignore-vulns
2025-05-28 17:32:24 -07:00
Carlo Costino
55e24a611a Updated pip-audit ignore-vulns
This changeset updates the PYSEC notices to ignore to due versions that either cannot be fixed or are false positives.  Specifically, this changeset removes previously ignored vulnerability reports and adds PYSEC-2023-312 to the list because it is a false positive and refers to Redis itself, not the Python Redis client (see https://github.com/pypa/advisory-database/issues/237 for details).

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-05-28 17:43:50 -04:00
Kenneth Kehl
1287be143c filter requirements text 2025-05-28 08:57:49 -07:00
Kenneth Kehl
976027d52f filter requirements text 2025-05-28 08:54:59 -07:00
Kenneth Kehl
bf9f01e526 filter requirements text 2025-05-28 08:40:17 -07:00
Kenneth Kehl
ca5b0b2230 filter requirements text 2025-05-28 08:33:55 -07:00
Kenneth Kehl
3c02ad92bb filter requirements text 2025-05-28 08:29:31 -07:00
Kenneth Kehl
87d29de41d filter requirements text 2025-05-28 08:16:38 -07:00
Kenneth Kehl
f620a886b0 oops 2025-05-28 08:10:28 -07:00
Kenneth Kehl
9c68deb337 revert to pinned oscrypto 2025-05-28 08:03:43 -07:00
Kenneth Kehl
b976b395c6 try oscrypto 1.3.0 2025-05-28 07:55:50 -07:00
Kenneth Kehl
96bb7f24d0 try oscrypto 1.3.0 2025-05-28 07:44:50 -07:00
Kenneth Kehl
d526e0a54c use skip-editable for pip-audit to work around dependencies that are pinned to revisions 2025-05-28 07:35:47 -07:00
Kenneth Kehl
f0739b5fcf try setting package-mode to false 2025-05-28 07:11:15 -07:00
Alex Janousek
c924cff4d2 Merge pull request #1739 from GSA/dependabot/pip/cryptography-45.0.3
Bump cryptography from 45.0.2 to 45.0.3
2025-05-27 18:34:19 -04:00
dependabot[bot]
cf70242482 Bump cryptography from 45.0.2 to 45.0.3
Bumps [cryptography](https://github.com/pyca/cryptography) from 45.0.2 to 45.0.3.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/45.0.2...45.0.3)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 45.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 22:27:19 +00:00
Alex Janousek
903587ed27 Merge pull request #1740 from GSA/dependabot/pip/setuptools-80.9.0
Bump setuptools from 80.8.0 to 80.9.0
2025-05-27 18:25:07 -04:00
dependabot[bot]
e98fb4913f Bump setuptools from 80.8.0 to 80.9.0
Bumps [setuptools](https://github.com/pypa/setuptools) from 80.8.0 to 80.9.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v80.8.0...v80.9.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-version: 80.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 22:18:27 +00:00
Alex Janousek
da629baef0 Merge pull request #1741 from GSA/dependabot/pip/freezegun-1.5.2
Bump freezegun from 1.5.1 to 1.5.2
2025-05-27 18:16:19 -04:00
dependabot[bot]
4e7a0893ff Bump freezegun from 1.5.1 to 1.5.2
Bumps [freezegun](https://github.com/spulec/freezegun) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/spulec/freezegun/releases)
- [Changelog](https://github.com/spulec/freezegun/blob/master/CHANGELOG)
- [Commits](https://github.com/spulec/freezegun/compare/1.5.1...1.5.2)

---
updated-dependencies:
- dependency-name: freezegun
  dependency-version: 1.5.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 21:46:36 +00:00
Kenneth Kehl
3a9db4f3a7 fix makefile 2025-05-27 14:40:06 -07:00
Kenneth Kehl
ebbb894245 upgrade poetry 2025-05-27 14:24:42 -07:00
Kenneth Kehl
22a0d9e287 upgrade poetry 2025-05-27 14:14:44 -07:00
ccostino
04a50c8825 Merge pull request #1732 from GSA/update-register_socket_handlers
Socket.IO 400 errors
2025-05-27 14:23:57 -04:00
Alex Janousek
119914a3f7 Merge pull request #1735 from GSA/dependabot/pip/pytest-xdist-3.7.0
Bump pytest-xdist from 3.6.1 to 3.7.0
2025-05-27 14:07:55 -04:00
dependabot[bot]
3e1a7df375 Bump pytest-xdist from 3.6.1 to 3.7.0
Bumps [pytest-xdist](https://github.com/pytest-dev/pytest-xdist) from 3.6.1 to 3.7.0.
- [Release notes](https://github.com/pytest-dev/pytest-xdist/releases)
- [Changelog](https://github.com/pytest-dev/pytest-xdist/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-xdist/compare/v3.6.1...v3.7.0)

---
updated-dependencies:
- dependency-name: pytest-xdist
  dependency-version: 3.7.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 18:00:08 +00:00
Alex Janousek
7168d50f38 Merge pull request #1731 from GSA/dependabot/pip/cachetools-6.0.0
Bump cachetools from 5.4.0 to 6.0.0
2025-05-27 13:58:01 -04:00
dependabot[bot]
d5c0497767 Bump cachetools from 5.4.0 to 6.0.0
Bumps [cachetools](https://github.com/tkem/cachetools) from 5.4.0 to 6.0.0.
- [Changelog](https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tkem/cachetools/compare/v5.4.0...v6.0.0)

---
updated-dependencies:
- dependency-name: cachetools
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 17:51:16 +00:00
Alex Janousek
cb8e3776a8 Merge pull request #1736 from GSA/dependabot/pip/moto-5.1.5
Bump moto from 5.1.4 to 5.1.5
2025-05-27 13:49:08 -04:00
dependabot[bot]
eb4c6a5ff9 Bump moto from 5.1.4 to 5.1.5
Bumps [moto](https://github.com/getmoto/moto) from 5.1.4 to 5.1.5.
- [Release notes](https://github.com/getmoto/moto/releases)
- [Changelog](https://github.com/getmoto/moto/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getmoto/moto/compare/5.1.4...5.1.5)

---
updated-dependencies:
- dependency-name: moto
  dependency-version: 5.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 16:47:06 +00:00
ccostino
d20dc03e77 Merge pull request #1733 from GSA/dependabot/pip/pytest-mock-3.14.1
Bump pytest-mock from 3.14.0 to 3.14.1
2025-05-27 12:44:50 -04:00
dependabot[bot]
7aa98ffc5b Bump pytest-mock from 3.14.0 to 3.14.1
Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.14.0 to 3.14.1.
- [Release notes](https://github.com/pytest-dev/pytest-mock/releases)
- [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.14.0...v3.14.1)

---
updated-dependencies:
- dependency-name: pytest-mock
  dependency-version: 3.14.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 15:14:35 +00:00
ccostino
a118262da2 Merge pull request #1734 from GSA/dependabot/pip/jsonschema-4.24.0
Bump jsonschema from 4.23.0 to 4.24.0
2025-05-27 11:12:29 -04:00
dependabot[bot]
6d3c1e4bea Bump jsonschema from 4.23.0 to 4.24.0
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.23.0 to 4.24.0.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.23.0...v4.24.0)

---
updated-dependencies:
- dependency-name: jsonschema
  dependency-version: 4.24.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-26 21:38:26 +00:00
Beverly Nguyen
590ac64cba imported but unused 2025-05-23 16:02:01 -07:00
Beverly Nguyen
fd14baa2b1 Merge branch 'main' into update-register_socket_handlers 2025-05-23 15:57:13 -07:00
Beverly Nguyen
dcae1ca914 The issue might be that without importing socketio in application.py, gunicorn can't find the Socket.IO server to handle the WebSocket upgrade. 2025-05-23 15:55:50 -07:00
Alex Janousek
d96b6658de Merge pull request #1721 from GSA/feature/scan-updates
Added false positive fix for scan
2025-05-23 10:50:05 -04:00
Carlo Costino
6742d45f60 Merge branch 'main' into feature/scan-updates 2025-05-23 10:42:56 -04:00
ccostino
50132bc60d Merge pull request #1730 from GSA/update-register_socket_handlers
Added @socketio.on(connect) and @socketio.on(disconnect)
2025-05-23 10:32:38 -04:00
ccostino
a987f93ef1 Merge pull request #1726 from GSA/blocking
change page size
2025-05-23 10:23:36 -04:00
Kenneth Kehl
1b7c6c2b74 Update app/aws/s3.py
Co-authored-by: ccostino <ccostino@users.noreply.github.com>
2025-05-23 06:58:21 -07:00
Kenneth Kehl
91f3bbaf98 Update app/aws/s3.py
Co-authored-by: ccostino <ccostino@users.noreply.github.com>
2025-05-23 06:58:09 -07:00
Beverly Nguyen
ec60818d8d remove comments 2025-05-22 17:09:02 -07:00
Beverly Nguyen
c5dca6b533 black . 2025-05-22 17:08:15 -07:00
Beverly Nguyen
877313509f Added @socketio.on(connect) and @socketio.on(disconnect) handlers to log and manage Socket.IO connections. The intention is to resolve connection issues by ensuring the server properly acknowledges incoming WebSocket clients. 2025-05-22 17:07:02 -07:00
Kenneth Kehl
8861cc4963 merge from main 2025-05-22 08:31:56 -07:00
Kenneth Kehl
170dc12284 fix reports 2025-05-22 08:31:33 -07:00
Kenneth Kehl
45f9790b1c fix tests 2025-05-21 14:47:51 -07:00
Kenneth Kehl
6a5ff00136 change page size 2025-05-21 14:12:42 -07:00
Kenneth Kehl
2788c21420 change page size 2025-05-21 13:44:14 -07:00
Alex Janousek
cb750e1689 Update docs/openapi.yml
Co-authored-by: ccostino <ccostino@users.noreply.github.com>
2025-05-20 13:13:39 -04:00
20 changed files with 966 additions and 654 deletions

View File

@@ -136,7 +136,253 @@
"line_number": 18,
"is_secret": false
}
],
".github/workflows/checks.yml": [
{
"type": "Secret Keyword",
"filename": ".github/workflows/checks.yml",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 28,
"is_secret": false
},
{
"type": "Basic Auth Credentials",
"filename": ".github/workflows/checks.yml",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 45,
"is_secret": false
}
],
".github/workflows/daily_checks.yml": [
{
"type": "Secret Keyword",
"filename": ".github/workflows/daily_checks.yml",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 71,
"is_secret": false
},
{
"type": "Basic Auth Credentials",
"filename": ".github/workflows/daily_checks.yml",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 87,
"is_secret": false
}
],
"app/enums.py": [
{
"type": "Secret Keyword",
"filename": "app/enums.py",
"hashed_secret": "12322e07b94ee3c7cd65a2952ece441538b53eb3",
"is_verified": false,
"line_number": 123,
"is_secret": false
}
],
"app/notifications/receive_notifications.py": [
{
"type": "Base64 High Entropy String",
"filename": "app/notifications/receive_notifications.py",
"hashed_secret": "d70eab08607a4d05faa2d0d6647206599e9abc65",
"is_verified": false,
"line_number": 29,
"is_secret": false
}
],
"deploy-config/sandbox.yml": [
{
"type": "Secret Keyword",
"filename": "deploy-config/sandbox.yml",
"hashed_secret": "113151dd10316fcb0d5507b6215d78e2f3fe9e54",
"is_verified": false,
"line_number": 11,
"is_secret": false
}
],
"sample.env": [
{
"type": "Basic Auth Credentials",
"filename": "sample.env",
"hashed_secret": "5b98cf4c3d794c8af1fcd7991e89cd4e52fb42a4",
"is_verified": false,
"line_number": 16,
"is_secret": false
}
],
"tests/app/clients/test_document_download.py": [
{
"type": "Secret Keyword",
"filename": "tests/app/clients/test_document_download.py",
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
"is_verified": false,
"line_number": 14,
"is_secret": false
}
],
"tests/app/clients/test_performance_platform.py": [
{
"type": "Base64 High Entropy String",
"filename": "tests/app/clients/test_performance_platform.py",
"hashed_secret": "76bb66c38ac4046bf73cd4a2c35a2b0af94aeb61",
"is_verified": false,
"line_number": 84,
"is_secret": false
}
],
"tests/app/dao/test_services_dao.py": [
{
"type": "Secret Keyword",
"filename": "tests/app/dao/test_services_dao.py",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 289,
"is_secret": false
}
],
"tests/app/dao/test_users_dao.py": [
{
"type": "Secret Keyword",
"filename": "tests/app/dao/test_users_dao.py",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 69,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "tests/app/dao/test_users_dao.py",
"hashed_secret": "f2c57870308dc87f432e5912d4de6f8e322721ba",
"is_verified": false,
"line_number": 199,
"is_secret": false
}
],
"tests/app/db.py": [
{
"type": "Secret Keyword",
"filename": "tests/app/db.py",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 90,
"is_secret": false
}
],
"tests/app/notifications/test_receive_notification.py": [
{
"type": "Secret Keyword",
"filename": "tests/app/notifications/test_receive_notification.py",
"hashed_secret": "913a73b565c8e2c8ed94497580f619397709b8b6",
"is_verified": false,
"line_number": 27,
"is_secret": false
},
{
"type": "Base64 High Entropy String",
"filename": "tests/app/notifications/test_receive_notification.py",
"hashed_secret": "d70eab08607a4d05faa2d0d6647206599e9abc65",
"is_verified": false,
"line_number": 57,
"is_secret": false
}
],
"tests/app/notifications/test_validators.py": [
{
"type": "Base64 High Entropy String",
"filename": "tests/app/notifications/test_validators.py",
"hashed_secret": "6c1a8443963d02d13ffe575a71abe19ea731fb66",
"is_verified": false,
"line_number": 672,
"is_secret": false
}
],
"tests/app/service/test_rest.py": [
{
"type": "Secret Keyword",
"filename": "tests/app/service/test_rest.py",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 1285,
"is_secret": false
}
],
"tests/app/test_cloudfoundry_config.py": [
{
"type": "Secret Keyword",
"filename": "tests/app/test_cloudfoundry_config.py",
"hashed_secret": "e5e178db7317356946d13e5d2da037d39ac61c71",
"is_verified": false,
"line_number": 12,
"is_secret": false
},
{
"type": "Basic Auth Credentials",
"filename": "tests/app/test_cloudfoundry_config.py",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 14,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "tests/app/test_cloudfoundry_config.py",
"hashed_secret": "cfd48edeb81ba7d48cbddcf1eeede25ba67057e8",
"is_verified": false,
"line_number": 33,
"is_secret": false
}
],
"tests/app/user/test_rest.py": [
{
"type": "Secret Keyword",
"filename": "tests/app/user/test_rest.py",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 110,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "tests/app/user/test_rest.py",
"hashed_secret": "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33",
"is_verified": false,
"line_number": 864,
"is_secret": false
}
],
"tests/notifications_utils/clients/antivirus/test_antivirus_client.py": [
{
"type": "Secret Keyword",
"filename": "tests/notifications_utils/clients/antivirus/test_antivirus_client.py",
"hashed_secret": "932b25270abe1301c22c709a19082dff07d469ff",
"is_verified": false,
"line_number": 16,
"is_secret": false
}
],
"tests/notifications_utils/clients/encryption/test_encryption_client.py": [
{
"type": "Secret Keyword",
"filename": "tests/notifications_utils/clients/encryption/test_encryption_client.py",
"hashed_secret": "f1e923a9667de11be6a210849a8651c1bfd81605",
"is_verified": false,
"line_number": 13,
"is_secret": false
}
],
"tests/notifications_utils/clients/zendesk/test_zendesk_client.py": [
{
"type": "Secret Keyword",
"filename": "tests/notifications_utils/clients/zendesk/test_zendesk_client.py",
"hashed_secret": "913a73b565c8e2c8ed94497580f619397709b8b6",
"is_verified": false,
"line_number": 16,
"is_secret": false
}
]
},
"generated_at": "2025-05-12T16:45:34Z"
"generated_at": "2025-06-02T13:22:36Z"
}

View File

@@ -9,13 +9,16 @@ runs:
sudo apt-get update \
&& sudo apt-get install -y --no-install-recommends \
libcurl4-openssl-dev
- name: Set up Python 3.12.3
- name: Set up Python 3.13.2
uses: actions/setup-python@v4
with:
python-version: "3.12.3"
python-version: "3.13.2"
- name: Install poetry
shell: bash
run: pip install poetry==1.8.5
run: pip install poetry==2.1.3
- name: Install poetry export
shell: bash
run: poetry self add poetry-plugin-export
- name: Downgrade virtualenv to compatible version
shell: bash
run: pip install "virtualenv<20.30"

View File

@@ -87,12 +87,20 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Create requirements.txt
run: poetry export --without-hashes --format=requirements.txt > requirements.txt
- uses: pypa/gh-action-pip-audit@v1.0.8
run: poetry export --output requirements_tmp.txt --without-hashes
- name: Filter requirements.txt
run: grep -v "oscrypto@ git" requirements_tmp.txt > requirements.txt
- name: Verify requirements.txt
run: ls -l requirements.txt
- name: Print requirements.txt
run: |
echo "Contents of requirements.txt:"
cat requirements.txt
- uses: pypa/gh-action-pip-audit@v1.1.0
with:
inputs: requirements.txt
ignore-vulns: |
PYSEC-2022-43162
PYSEC-2023-312
static-scan:
runs-on: ubuntu-latest

View File

@@ -26,10 +26,20 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- name: Create requirements.txt
run: poetry export --without-hashes --format=requirements.txt > requirements.txt
run: poetry export --output requirements_tmp.txt --without-hashes
- name: Filter requirements.txt
run: grep -v "oscrypto@ git" requirements_tmp.txt > requirements.txt
- name: Verify requirements.txt
run: ls -l requirements.txt
- name: Print requirements.txt
run: |
echo "Contents of requirements.txt:"
cat requirements.txt
- uses: pypa/gh-action-pip-audit@v1.1.0
with:
inputs: requirements.txt
ignore-vulns: |
PYSEC-2023-312
- name: Upload pip-audit artifact
uses: actions/upload-artifact@v4
with:

View File

@@ -44,7 +44,7 @@ jobs:
run: make bootstrap
- name: Create requirements.txt
run: poetry export --without-hashes --format=requirements.txt > requirements.txt
run: poetry export --output requirements.txt
- name: Deploy to cloud.gov
uses: cloud-gov/cg-cli-tools@main

View File

@@ -48,7 +48,7 @@ jobs:
run: make bootstrap
- name: Create requirements.txt
run: poetry export --without-hashes --format=requirements.txt > requirements.txt
run: poetry export --output requirements.txt
- name: Deploy to cloud.gov
uses: cloud-gov/cg-cli-tools@main

View File

@@ -50,7 +50,7 @@ jobs:
run: make bootstrap
- name: Create requirements.txt
run: poetry export --without-hashes --format=requirements.txt > requirements.txt
run: poetry export --output requirements.txt
- name: Deploy to cloud.gov
uses: cloud-gov/cg-cli-tools@main

View File

@@ -16,8 +16,7 @@ GIT_HOOKS_PATH ?= $(shell git config --global core.hooksPath || echo "")
.PHONY: bootstrap
bootstrap: ## Set up everything to run the app
make generate-version-file
poetry lock --no-update
poetry install --sync --no-root
poetry sync --no-root
poetry run pre-commit install
createdb notification_api || true
createdb test_notification_api || true
@@ -26,8 +25,7 @@ bootstrap: ## Set up everything to run the app
.PHONY: bootstrap-with-git-hooks
bootstrap-with-git-hooks: ## Sets everything up and accounts for pre-existing git hooks
make generate-version-file
poetry lock --no-update
poetry install --sync --no-root
poetry sync --no-root
git config --global --unset-all core.hooksPath
poetry run pre-commit install
git config --global core.hookspath "${GIT_HOOKS_PATH}"
@@ -112,19 +110,19 @@ test: ## Run tests and create coverage report
.PHONY: py-lock
py-lock: ## Syncs dependencies and updates lock file without performing recursive internal updates
poetry lock --no-update
poetry install --sync
poetry sync --no-root
poetry lock
.PHONY: freeze-requirements
freeze-requirements: ## Pin all requirements including sub dependencies into requirements.txt
poetry export --without-hashes --format=requirements.txt > requirements.txt
poetry export --output > requirements.txt
.PHONY: audit
audit:
poetry requirements > requirements.txt
poetry requirements --dev > requirements_for_test.txt
poetry run pip-audit -r requirements.txt
poetry run pip-audit -r requirements_for_test.txt
poetry run pip-audit -r requirements.txt --skip-editable
poetry run pip-audit -r requirements_for_test.txt --skip-editable
.PHONY: static-scan
static-scan:

View File

@@ -40,7 +40,7 @@ You will need the following items:
This project currently works with these major versions of the following main
components:
- Python 3.12.x
- Python 3.13.x
- PostgreSQL 15.x (version 12.x is used in the hosted environments)
These instructions will walk you through how to set your machine up with all of
@@ -173,12 +173,12 @@ session to make the changes take effect.
Now we're ready to install the Python version we need with `pyenv`, like so:
```sh
pyenv install 3.12
pyenv install 3.13
```
This will install the latest version of Python 3.12.
This will install the latest version of Python 3.13.
_NOTE: This project currently runs on Python 3.12.x._
_NOTE: This project currently runs on Python 3.13.x._
#### Python Dependency Installation
@@ -259,12 +259,12 @@ git clone git@github.com:GSA/notifications-api.git
Now go into the project directory (`notifications-api` by default), create a
virtual environment, and set the local Python version to point to the virtual
environment (assumes version Python `3.12.2` is what is installed on your
environment (assumes version Python `3.13.2` is what is installed on your
machine):
```sh
cd notifications-api
pyenv virtualenv 3.12.2 notify-api
pyenv virtualenv 3.13.2 notify-api
pyenv local notify-api
```
@@ -311,10 +311,10 @@ If you're upgrading an existing project to a newer version of Python, you can
follow these steps to get yourself up-to-date.
First, use `pyenv` to install the newer version of Python you'd like to use;
we'll use `3.12` in our example here since we recently upgraded to this version:
we'll use `3.13` in our example here since we recently upgraded to this version:
```sh
pyenv install 3.12
pyenv install 3.13
```
Next, delete the virtual environment you previously had set up. If you followed
@@ -329,7 +329,7 @@ environment with the newer version of Python you just installed:
```sh
cd notifications-api
pyenv virtualenv 3.12.2 notify-api
pyenv virtualenv 3.13.2 notify-api
pyenv local notify-api
```
@@ -339,6 +339,21 @@ you'll be set with an upgraded version of Python.
_If you're not sure about the details of your current virtual environment, you can run `poetry env info` to get more information. If you've been using `pyenv` for everything, you can also see all available virtual environments with `pyenv virtualenvs`._
#### Poetry upgrades ####
If you are doing a new project setup, then after you install poetry you need to install the export plugin
```sh
poetry self add poetry-plugin-export
```
If you are upgrading from poetry 1.8.5, you need to do this:
```sh
curl -sSL https://install.python-poetry.org | python3 - --version 2.1.3
poetry self add poetry-export-plugin
```
### Final environment setup
There's one final thing to adjust in the newly created `.env` file. This
@@ -462,6 +477,8 @@ instructions above for more details.
- [Onboarding](./docs/all.md#onboarding)
- [Setting up the infrastructure](./docs/all.md#setting-up-the-infrastructure)
- [Using the logs](./docs/all.md#using-the-logs)
- [`git` hooks](./docs/all.md#git-hooks)
- [detect-secrets pre-commit plugin](./docs/all.md#detect-secrets-pre-commit-plugin)
- [Testing](./docs/all.md#testing)
- [CI testing](./docs/all.md#ci-testing)
- [Manual testing](./docs/all.md#manual-testing)

View File

@@ -5,7 +5,7 @@ import string
import time
import uuid
from contextlib import contextmanager
from multiprocessing import Manager
from threading import Lock
from time import monotonic
from celery import Celery, Task, current_task
@@ -32,6 +32,9 @@ from notifications_utils.clients.encryption.encryption_client import Encryption
from notifications_utils.clients.redis.redis_client import RedisClient
from notifications_utils.clients.zendesk.zendesk_client import ZendeskClient
job_cache = {}
job_cache_lock = Lock()
class NotifyCelery(Celery):
def init_app(self, app):
@@ -152,9 +155,6 @@ def create_app(application):
redis_store.init_app(application)
document_download_client.init_app(application)
manager = Manager()
application.config["job_cache"] = manager.dict()
register_blueprint(application)
# avoid circular imports by importing this file later

View File

@@ -9,6 +9,7 @@ import eventlet
from boto3 import Session
from flask import current_app
from app import job_cache, job_cache_lock
from app.clients import AWS_CLIENT_CONFIG
from notifications_utils import aware_utcnow
@@ -32,30 +33,25 @@ def get_service_id_from_key(key):
def set_job_cache(key, value):
current_app.logger.debug(f"Setting {key} in the job_cache to {value}.")
job_cache = current_app.config["job_cache"]
job_cache[key] = (value, time.time() + 8 * 24 * 60 * 60)
# current_app.logger.debug(f"Setting {key} in the job_cache to {value}.")
with job_cache_lock:
job_cache[key] = (value, time.time() + 8 * 24 * 60 * 60)
def get_job_cache(key):
job_cache = current_app.config["job_cache"]
ret = job_cache.get(key)
if ret is None:
current_app.logger.warning(f"Could not find {key} in the job_cache.")
else:
current_app.logger.debug(f"Got {key} from job_cache with value {ret}.")
return ret
def len_job_cache():
job_cache = current_app.config["job_cache"]
ret = len(job_cache)
current_app.logger.debug(f"Length of job_cache is {ret}")
return ret
def clean_cache():
job_cache = current_app.config["job_cache"]
current_time = time.time()
keys_to_delete = []
for key, (_, expiry_time) in job_cache.items():
@@ -65,8 +61,9 @@ def clean_cache():
current_app.logger.debug(
f"Deleting the following keys from the job_cache: {keys_to_delete}"
)
for key in keys_to_delete:
del job_cache[key]
with job_cache_lock:
for key in keys_to_delete:
del job_cache[key]
def get_s3_client():
@@ -207,9 +204,8 @@ def read_s3_file(bucket_name, object_key, s3res):
extract_personalisation(job),
)
except LookupError:
# perhaps our key is not formatted as we expected. If so skip it.
current_app.logger.exception("LookupError #notify-debug-admin-1200")
except Exception as e:
current_app.logger.exception(str(e))
def get_s3_files():
@@ -308,9 +304,7 @@ def file_exists(file_location):
def get_job_location(service_id, job_id):
current_app.logger.debug(
f"#notify-debug-s3-partitioning NEW JOB_LOCATION: {NEW_FILE_LOCATION_STRUCTURE.format(service_id, job_id)}"
)
return (
current_app.config["CSV_UPLOAD_BUCKET"]["bucket"],
NEW_FILE_LOCATION_STRUCTURE.format(service_id, job_id),
@@ -326,9 +320,7 @@ def get_old_job_location(service_id, job_id):
but it will take a few days where we have to support both formats.
Remove this when everything works with the NEW_FILE_LOCATION_STRUCTURE.
"""
current_app.logger.debug(
f"#notify-debug-s3-partitioning OLD JOB LOCATION: {FILE_LOCATION_STRUCTURE.format(service_id, job_id)}"
)
return (
current_app.config["CSV_UPLOAD_BUCKET"]["bucket"],
FILE_LOCATION_STRUCTURE.format(service_id, job_id),
@@ -467,7 +459,6 @@ def extract_personalisation(job):
def get_phone_number_from_s3(service_id, job_id, job_row_number):
job = get_job_cache(job_id)
if job is None:
current_app.logger.debug(f"job {job_id} was not in the cache")
job = get_job_from_s3(service_id, job_id)
# Even if it is None, put it here to avoid KeyErrors
set_job_cache(job_id, job)
@@ -481,8 +472,16 @@ def get_phone_number_from_s3(service_id, job_id, job_row_number):
)
return "Unavailable"
phones = extract_phones(job, service_id, job_id)
set_job_cache(f"{job_id}_phones", phones)
phones = get_job_cache(f"{job_id}_phones")
if phones is None:
current_app.logger.debug("HAVE TO REEXTRACT PHONES!")
phones = extract_phones(job, service_id, job_id)
set_job_cache(f"{job_id}_phones", phones)
current_app.logger.debug(f"SETTING PHONES TO {phones}")
else:
phones = phones[
0
] # we only want the phone numbers not the cache expiration time
# If we can find the quick dictionary, use it
phone_to_return = phones[job_row_number]
@@ -501,7 +500,6 @@ def get_personalisation_from_s3(service_id, job_id, job_row_number):
# So this is a little recycling mechanism to reduce the number of downloads.
job = get_job_cache(job_id)
if job is None:
current_app.logger.debug(f"job {job_id} was not in the cache")
job = get_job_from_s3(service_id, job_id)
# Even if it is None, put it here to avoid KeyErrors
set_job_cache(job_id, job)
@@ -519,7 +517,9 @@ def get_personalisation_from_s3(service_id, job_id, job_row_number):
)
return {}
set_job_cache(f"{job_id}_personalisation", extract_personalisation(job))
personalisation = get_job_cache(f"{job_id}_personalisation")
if personalisation is None:
set_job_cache(f"{job_id}_personalisation", extract_personalisation(job))
return get_job_cache(f"{job_id}_personalisation")[0].get(job_row_number)

View File

@@ -1,4 +1,5 @@
import itertools
import time
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
@@ -504,6 +505,10 @@ def get_all_notifications_for_service(service_id):
if "page_size" in data
else current_app.config.get("PAGE_SIZE")
)
# HARD CODE TO 100 for now. 1000 or 10000 causes reports to time out before they complete (if big)
# Tests are relying on the value in config (20), whereas the UI seems to pass 10000
if page_size > 100:
page_size = 100
limit_days = data.get("limit_days")
include_jobs = data.get("include_jobs", True)
include_from_test_key = data.get("include_from_test_key", False)
@@ -517,6 +522,8 @@ def get_all_notifications_for_service(service_id):
f"get pagination with {service_id} service_id filters {data} \
limit_days {limit_days} include_jobs {include_jobs} include_one_off {include_one_off}"
)
start_time = time.time()
current_app.logger.debug(f"Start report generation with page.size {page_size}")
pagination = notifications_dao.get_notifications_for_service(
service_id,
filter_dict=data,
@@ -528,9 +535,13 @@ def get_all_notifications_for_service(service_id):
include_from_test_key=include_from_test_key,
include_one_off=include_one_off,
)
current_app.logger.debug(f"Query complete at {int(time.time()-start_time)*1000}")
for notification in pagination.items:
if notification.job_id is not None:
current_app.logger.debug(
f"Processing job_id {notification.job_id} at {int(time.time()-start_time)*1000}"
)
notification.personalisation = get_personalisation_from_s3(
notification.service_id,
notification.job_id,

View File

@@ -3,6 +3,17 @@ from flask_socketio import join_room, leave_room
def register_socket_handlers(socketio):
@socketio.on("connect")
def on_connect():
current_app.logger.info(
f"Socket {request.sid} connected from {request.environ.get('HTTP_ORIGIN')}"
)
return True
@socketio.on("disconnect")
def on_disconnect():
current_app.logger.info(f"Socket {request.sid} disconnected")
@socketio.on("join")
def on_join(data): # noqa: F401
room = data.get("room")

View File

@@ -4,7 +4,7 @@ from __future__ import print_function
from flask import Flask
from werkzeug.serving import WSGIRequestHandler
from app import create_app
from app import create_app, socketio # noqa: F401
WSGIRequestHandler.version_string = lambda self: "SecureServer"

View File

@@ -7,6 +7,7 @@
- [Setting up the infrastructure](#setting-up-the-infrastructure)
- [Using the logs](#using-the-logs)
- [`git` hooks](#git-hooks)
- [detect-secrets pre-commit plugin](#detect-secrets-pre-commit-plugin)
- [Testing](#testing)
- [CI testing](#ci-testing)
- [Manual testing](#manual-testing)
@@ -262,6 +263,17 @@ The configuration is stored in `.pre-commit-config.yaml`. In that config, there
We do not maintain any hooks in this repository.
## detect-secrets pre-commit plugin
One of the pre-commit hooks we use is [`detect-secrets`](https://github.com/Yelp/detect-secrets), which checks for all sorts of things that might be committed accidently that should not be. The project is already set up with a baseline file (`.ds.baseline`) and this should just work out of the box, but occasionally it will flag something new when you try and commit something; or, the file may need a refresh after a while. In either case, to get things back on track and update the `.ds.baseline` file, run these two commands:
```sh
detect-secrets scan --baseline .ds.baseline
detect-secrets audit .ds.baseline
```
The second command will walk you through all of the new detected secrets and ask you to validate if they actually are or if they're false positives. Mark off each one as apppropriate (they should all be false positives - if they're not please stop and check in with the team!), then commit the updates to the `.ds.baseline` file and push them remotely so the project stays up-to-date.
# Testing
```

View File

@@ -570,7 +570,7 @@ paths:
reference:
type: string
example:
phone_number: "2028675309"
phone_number: "800-555-0100"
template_id: "85b58733-7ebf-494e-bee2-a21a4ce17d58"
personalisation:
variable: "value"

1136
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
[tool.poetry]
name = "notifications-api"
package-mode = false
version = "0.1.0"
description = "Notify.gov backend"
authors = ["Your Name <you@example.com>"]
@@ -7,14 +8,14 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "^3.12.2"
python = "^3.13.2"
alembic = "==1.16.1"
amqp = "==5.3.1"
beautifulsoup4 = "==4.13.4"
boto3 = "^1.34.150"
botocore = "^1.34.159"
cachetools = "==5.4.0"
celery = {version = "==5.5.2", extras = ["redis"]}
cachetools = "==6.0.0"
celery = {version = "==5.5.3", extras = ["redis"]}
certifi = ">=2022.12.7"
cffi = "==1.17.1"
charset-normalizer = "^3.4.2"
@@ -24,7 +25,7 @@ click-didyoumean = "==0.3.1"
click-plugins = "==1.1.1"
click-repl = "==0.3.0"
deprecated = "==1.2.14"
eventlet = "==0.36.1"
eventlet = "==0.40.0"
expiringdict = "==1.2.2"
flask = "~=3.1"
flask-bcrypt = "==1.0.1"
@@ -34,7 +35,7 @@ flask-redis = "==0.4.0"
flask-sqlalchemy = "==3.1.1"
gunicorn = {version = "==23.0.0", extras = ["eventlet"]}
iso8601 = "==2.1.0"
jsonschema = {version = "==4.23.0", extras = ["format"]}
jsonschema = {version = "==4.24.0", extras = ["format"]}
lxml = "==5.4.0"
marshmallow = "==3.26.1"
marshmallow-sqlalchemy = "==1.0.0"
@@ -43,7 +44,7 @@ notifications-python-client = "==10.0.1"
oscrypto = { git = "https://github.com/wbond/oscrypto.git", rev = "1547f53" }
packaging = "==25.0"
poetry-dotenv-plugin = "==0.2.0"
psycopg2-binary = "==2.9.9"
psycopg2-binary = "==2.9.10"
pyjwt = "==2.10.1"
python-dotenv = "==1.1.0"
sqlalchemy = "==2.0.41"
@@ -54,14 +55,14 @@ bleach = "^6.1.0"
geojson = "^3.2.0"
numpy = "^2.2.6"
ordered-set = "^4.1.0"
phonenumbers = "^9.0.5"
phonenumbers = "^9.0.6"
python-json-logger = "^3.3.0"
regex = "^2024.11.6"
shapely = "^2.1.1"
smartypants = "^2.0.1"
mistune = "^3.1.3"
blinker = "^1.9.0"
cryptography = "^45.0.2"
cryptography = "^45.0.3"
idna = "^3.7"
jmespath = "^1.0.1"
markupsafe = "^3.0.2"
@@ -88,21 +89,21 @@ cloudfoundry-client = "*"
exceptiongroup = "==1.3.0"
flake8 = "^7.2.0"
flake8-bugbear = "^24.12.12"
freezegun = "^1.5.1"
freezegun = "^1.5.2"
honcho = "*"
isort = "^6.0.1"
jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
moto = "==5.1.4"
moto = "==5.1.5"
pip-audit = "*"
pre-commit = "^4.2.0"
pytest = "^8.3.2"
pytest = "^8.4.0"
pytest-env = "^1.1.3"
pytest-mock = "^3.14.0"
pytest-mock = "^3.14.1"
pytest-cov = "^6.1.1"
pytest-xdist = "^3.5.0"
pytest-xdist = "^3.7.0"
radon = "^6.0.1"
requests-mock = "^1.11.0"
setuptools = "^80.8.0"
setuptools = "^80.9.0"
sqlalchemy-utils = "^0.41.2"
vulture = "^2.10"
detect-secrets = "^1.5.0"

View File

@@ -1 +1 @@
python-3.12.x
python-3.13.x

View File

@@ -221,20 +221,6 @@ def test_get_s3_file_makes_correct_call(notify_api, mocker):
2,
"5555555552",
),
(
# simulate file saved with utf8withbom
"\\ufeffPHONE NUMBER\n",
"eee",
2,
"5555555552",
),
(
# simulate file saved without utf8withbom
"\\PHONE NUMBER\n",
"eee",
2,
"5555555552",
),
],
)
def test_get_phone_number_from_s3(
@@ -242,6 +228,7 @@ def test_get_phone_number_from_s3(
):
get_job_mock = mocker.patch("app.aws.s3.get_job_from_s3")
get_job_mock.return_value = job
phone_number = get_phone_number_from_s3("service_id", job_id, job_row_number)
assert phone_number == expected_phone_number