mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-31 20:00:00 -04:00
merge from main
This commit is contained in:
714
.ds.baseline
Normal file
714
.ds.baseline
Normal file
@@ -0,0 +1,714 @@
|
||||
{
|
||||
"version": "1.5.0",
|
||||
"plugins_used": [
|
||||
{
|
||||
"name": "ArtifactoryDetector"
|
||||
},
|
||||
{
|
||||
"name": "AWSKeyDetector"
|
||||
},
|
||||
{
|
||||
"name": "AzureStorageKeyDetector"
|
||||
},
|
||||
{
|
||||
"name": "Base64HighEntropyString",
|
||||
"limit": 4.5
|
||||
},
|
||||
{
|
||||
"name": "BasicAuthDetector"
|
||||
},
|
||||
{
|
||||
"name": "CloudantDetector"
|
||||
},
|
||||
{
|
||||
"name": "DiscordBotTokenDetector"
|
||||
},
|
||||
{
|
||||
"name": "GitHubTokenDetector"
|
||||
},
|
||||
{
|
||||
"name": "GitLabTokenDetector"
|
||||
},
|
||||
{
|
||||
"name": "HexHighEntropyString",
|
||||
"limit": 3.0
|
||||
},
|
||||
{
|
||||
"name": "IbmCloudIamDetector"
|
||||
},
|
||||
{
|
||||
"name": "IbmCosHmacDetector"
|
||||
},
|
||||
{
|
||||
"name": "IPPublicDetector"
|
||||
},
|
||||
{
|
||||
"name": "JwtTokenDetector"
|
||||
},
|
||||
{
|
||||
"name": "KeywordDetector",
|
||||
"keyword_exclude": ""
|
||||
},
|
||||
{
|
||||
"name": "MailchimpDetector"
|
||||
},
|
||||
{
|
||||
"name": "NpmDetector"
|
||||
},
|
||||
{
|
||||
"name": "OpenAIDetector"
|
||||
},
|
||||
{
|
||||
"name": "PrivateKeyDetector"
|
||||
},
|
||||
{
|
||||
"name": "PypiTokenDetector"
|
||||
},
|
||||
{
|
||||
"name": "SendGridDetector"
|
||||
},
|
||||
{
|
||||
"name": "SlackDetector"
|
||||
},
|
||||
{
|
||||
"name": "SoftlayerDetector"
|
||||
},
|
||||
{
|
||||
"name": "SquareOAuthDetector"
|
||||
},
|
||||
{
|
||||
"name": "StripeDetector"
|
||||
},
|
||||
{
|
||||
"name": "TelegramBotTokenDetector"
|
||||
},
|
||||
{
|
||||
"name": "TwilioKeyDetector"
|
||||
}
|
||||
],
|
||||
"filters_used": [
|
||||
{
|
||||
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.common.is_baseline_file",
|
||||
"filename": ".ds.baseline"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
||||
"min_level": 2
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
||||
}
|
||||
],
|
||||
"results": {
|
||||
".github/workflows/checks.yml": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": ".github/workflows/checks.yml",
|
||||
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
|
||||
"is_verified": false,
|
||||
"line_number": 61,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Basic Auth Credentials",
|
||||
"filename": ".github/workflows/checks.yml",
|
||||
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
|
||||
"is_verified": false,
|
||||
"line_number": 95,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"app/assets/js/uswds.min.js": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "app/assets/js/uswds.min.js",
|
||||
"hashed_secret": "372ea08cab33e71c02c651dbc83a474d32c676ea",
|
||||
"is_verified": false,
|
||||
"line_number": 85,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "app/assets/js/uswds.min.js",
|
||||
"hashed_secret": "53e07a32bf191d6917ee6fd863f0b52632a86798",
|
||||
"is_verified": false,
|
||||
"line_number": 85,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"app/config.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "app/config.py",
|
||||
"hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc",
|
||||
"is_verified": false,
|
||||
"line_number": 111,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"app/main/_commonly_used_passwords.py": [
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "82e19fa12aab7cfc718a002fc82c0f074bf070e7",
|
||||
"is_verified": false,
|
||||
"line_number": 123,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "a172ffc990129fe6f68b50f6037c54a1894ee3fd",
|
||||
"is_verified": false,
|
||||
"line_number": 240,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "4de69ee6b12b7fc91070873b71ba6e2929b90619",
|
||||
"is_verified": false,
|
||||
"line_number": 244,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "370194ff6e0f93a7432e16cc9badd9427e8b4e13",
|
||||
"is_verified": false,
|
||||
"line_number": 284,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "3dd635a808ddb6dd4b6731f7c409d53dd4b14df2",
|
||||
"is_verified": false,
|
||||
"line_number": 356,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "67a74306b06d0c01624fe0d0249a570f4d093747",
|
||||
"is_verified": false,
|
||||
"line_number": 374,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "61d6504733ca7757e259c644acd085c4dd471019",
|
||||
"is_verified": false,
|
||||
"line_number": 910,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "4ea872dfd7eefbde0036da7f0780826353dc7477",
|
||||
"is_verified": false,
|
||||
"line_number": 940,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "b214f706bb602c1cc2adc5c6165e73622305f4bb",
|
||||
"is_verified": false,
|
||||
"line_number": 1010,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "5cbabd43e49a1fedbbc3b86311aa6c8fe446abf9",
|
||||
"is_verified": false,
|
||||
"line_number": 1195,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "18ad10fd4a67f21fc07b1aa5046b410f6b2bedf1",
|
||||
"is_verified": false,
|
||||
"line_number": 1213,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "10470c3b4b1fed12c3baac014be15fac67c6e815",
|
||||
"is_verified": false,
|
||||
"line_number": 1263,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "65e1946c8f102eca8ba0af291f7c5e807516d94c",
|
||||
"is_verified": false,
|
||||
"line_number": 1346,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "0075df0a74c07ee295c98238c018401c9a80183b",
|
||||
"is_verified": false,
|
||||
"line_number": 1397,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "ca0023d7b345802fbc227b902cb9c57a3e02195f",
|
||||
"is_verified": false,
|
||||
"line_number": 1442,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "c8c6ca2e11c2dfd2a40914585b5944bffea15c8c",
|
||||
"is_verified": false,
|
||||
"line_number": 1555,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "b85b97a99eab8c809570c61d6404c1e49bdefbb4",
|
||||
"is_verified": false,
|
||||
"line_number": 1596,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "dec7dd342a499dfd4d283d872ccf598d8a7b6039",
|
||||
"is_verified": false,
|
||||
"line_number": 1789,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "2dc5053699a351121bf839c446bd4a878dda5735",
|
||||
"is_verified": false,
|
||||
"line_number": 1939,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "e5d54f0ac13abbdaa94b696c2469148b96dd11ab",
|
||||
"is_verified": false,
|
||||
"line_number": 2242,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "6059f42e2bbae78141e8a9e6286755ee691d5ce0",
|
||||
"is_verified": false,
|
||||
"line_number": 2305,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "fe703d258c7ef5f50b71e06565a65aa07194907f",
|
||||
"is_verified": false,
|
||||
"line_number": 2348,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "c229b68e1c3ffd9874838b5cb5354a0ee1367ddc",
|
||||
"is_verified": false,
|
||||
"line_number": 2349,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "756de479126e911b6f3400ae686d663d9d26b509",
|
||||
"is_verified": false,
|
||||
"line_number": 2920,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "6b174322afcdb440ee9cc3cc11eb16f9a00dec04",
|
||||
"is_verified": false,
|
||||
"line_number": 2975,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "9860783bfb510cbb2bf34471ec0b84a7ea587695",
|
||||
"is_verified": false,
|
||||
"line_number": 3359,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "b227cbd22eaa96019ebfc4aff35ad2add2a47439",
|
||||
"is_verified": false,
|
||||
"line_number": 3590,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "381d48209aecab8834eb495c5b5406100da07882",
|
||||
"is_verified": false,
|
||||
"line_number": 3811,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Hex High Entropy String",
|
||||
"filename": "app/main/_commonly_used_passwords.py",
|
||||
"hashed_secret": "508b38590a90d32990aadd7350d160b795c3ab41",
|
||||
"is_verified": false,
|
||||
"line_number": 3850,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"app/main/views/sign_in.py": [
|
||||
{
|
||||
"type": "Private Key",
|
||||
"filename": "app/main/views/sign_in.py",
|
||||
"hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9",
|
||||
"is_verified": false,
|
||||
"line_number": 27,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"app/templates/new/components/head.html": [
|
||||
{
|
||||
"type": "Base64 High Entropy String",
|
||||
"filename": "app/templates/new/components/head.html",
|
||||
"hashed_secret": "ee5048791fc7ff45a1545e24f85bec3317371327",
|
||||
"is_verified": false,
|
||||
"line_number": 35,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"app/templates/old/admin_template.html": [
|
||||
{
|
||||
"type": "Base64 High Entropy String",
|
||||
"filename": "app/templates/old/admin_template.html",
|
||||
"hashed_secret": "ee5048791fc7ff45a1545e24f85bec3317371327",
|
||||
"is_verified": false,
|
||||
"line_number": 18,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"deploy-config/sandbox.yml": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "deploy-config/sandbox.yml",
|
||||
"hashed_secret": "113151dd10316fcb0d5507b6215d78e2f3fe9e54",
|
||||
"is_verified": false,
|
||||
"line_number": 8,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"pytest.ini": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "pytest.ini",
|
||||
"hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc",
|
||||
"is_verified": false,
|
||||
"line_number": 7,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Base64 High Entropy String",
|
||||
"filename": "pytest.ini",
|
||||
"hashed_secret": "d347784b1ab6074a65cda7bc42f1561bed85493f",
|
||||
"is_verified": false,
|
||||
"line_number": 7,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Base64 High Entropy String",
|
||||
"filename": "pytest.ini",
|
||||
"hashed_secret": "ed1754d5cc82c8fd83205ebfb8c43fe4e88415a4",
|
||||
"is_verified": false,
|
||||
"line_number": 9,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "pytest.ini",
|
||||
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
||||
"is_verified": false,
|
||||
"line_number": 11,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/__init__.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/__init__.py",
|
||||
"hashed_secret": "f8377c90fcfd699f0ddbdcb30c2c9183d2d933ea",
|
||||
"is_verified": false,
|
||||
"line_number": 388,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/forms/test_register_user_form.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/forms/test_register_user_form.py",
|
||||
"hashed_secret": "8c6c978dc8e08771c7dea1ea2370fdf2446e5ba5",
|
||||
"is_verified": false,
|
||||
"line_number": 38,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/test_errorhandlers.py": [
|
||||
{
|
||||
"type": "Base64 High Entropy String",
|
||||
"filename": "tests/app/main/test_errorhandlers.py",
|
||||
"hashed_secret": "005fa73b3f2be8f0d71d361c1f0a9d787cd09b4e",
|
||||
"is_verified": false,
|
||||
"line_number": 33,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/test_request_header.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/test_request_header.py",
|
||||
"hashed_secret": "6866ef97a972ba3a2c6ff8bb2812981054770162",
|
||||
"is_verified": false,
|
||||
"line_number": 21,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/views/organizations/test_organization_invites.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/organizations/test_organization_invites.py",
|
||||
"hashed_secret": "bdbb156d25d02fd7792865824201dda1c60f4473",
|
||||
"is_verified": false,
|
||||
"line_number": 265,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/organizations/test_organization_invites.py",
|
||||
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
|
||||
"is_verified": false,
|
||||
"line_number": 273,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/views/test_accept_invite.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_accept_invite.py",
|
||||
"hashed_secret": "07f0a6c13923fc3b5f0c57ffa2d29b715eb80d71",
|
||||
"is_verified": false,
|
||||
"line_number": 607,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/views/test_new_password.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_new_password.py",
|
||||
"hashed_secret": "a41d5c3bbcd0b39c627b9cbf4897c6d25efa694f",
|
||||
"is_verified": false,
|
||||
"line_number": 89,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/views/test_register.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_register.py",
|
||||
"hashed_secret": "bdbb156d25d02fd7792865824201dda1c60f4473",
|
||||
"is_verified": false,
|
||||
"line_number": 116,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_register.py",
|
||||
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
|
||||
"is_verified": false,
|
||||
"line_number": 192,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_register.py",
|
||||
"hashed_secret": "bb5b7caa27d005d38039e3797c3ddb9bcd22c3c8",
|
||||
"is_verified": false,
|
||||
"line_number": 260,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/views/test_sign_in.py": [
|
||||
{
|
||||
"type": "Private Key",
|
||||
"filename": "tests/app/main/views/test_sign_in.py",
|
||||
"hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9",
|
||||
"is_verified": false,
|
||||
"line_number": 31,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_sign_in.py",
|
||||
"hashed_secret": "8b8b69116ee882b5e987e330f55db81aba0636f9",
|
||||
"is_verified": false,
|
||||
"line_number": 104,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/views/test_two_factor.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_two_factor.py",
|
||||
"hashed_secret": "dc66ad927c29e31c6c374231f57a4684b0687bfe",
|
||||
"is_verified": false,
|
||||
"line_number": 267,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/views/test_user_profile.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_user_profile.py",
|
||||
"hashed_secret": "8072d7aad32964ec43fbcb699c75dc38890792f7",
|
||||
"is_verified": false,
|
||||
"line_number": 350,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_user_profile.py",
|
||||
"hashed_secret": "4c9dbb972da179e4f66f023eaa5fb9451d835030",
|
||||
"is_verified": false,
|
||||
"line_number": 351,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/main/views/test_verify.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/main/views/test_verify.py",
|
||||
"hashed_secret": "faafcfa63e128929409bf310b7ea5a415f2331ce",
|
||||
"is_verified": false,
|
||||
"line_number": 160,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/notify_client/test_user_client.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/notify_client/test_user_client.py",
|
||||
"hashed_secret": "f2c57870308dc87f432e5912d4de6f8e322721ba",
|
||||
"is_verified": false,
|
||||
"line_number": 55,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/app/test_cloudfoundry_config.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/test_cloudfoundry_config.py",
|
||||
"hashed_secret": "5e44dae2de8b6e57c797b968035265c9f2cd2b3e",
|
||||
"is_verified": false,
|
||||
"line_number": 12,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/app/test_cloudfoundry_config.py",
|
||||
"hashed_secret": "e5e178db7317356946d13e5d2da037d39ac61c71",
|
||||
"is_verified": false,
|
||||
"line_number": 27,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"tests/conftest.py": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "tests/conftest.py",
|
||||
"hashed_secret": "f8377c90fcfd699f0ddbdcb30c2c9183d2d933ea",
|
||||
"is_verified": false,
|
||||
"line_number": 3289,
|
||||
"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": "2024-05-20T16:03:05Z"
|
||||
}
|
||||
95
.github/workflows/codeql.yml
vendored
Normal file
95
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "production" ]
|
||||
pull_request:
|
||||
branches: [ "main", "production" ]
|
||||
schedule:
|
||||
- cron: '18 5 * * 3'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: javascript-typescript
|
||||
build-mode: none
|
||||
- language: python
|
||||
build-mode: none
|
||||
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
@@ -2,7 +2,7 @@
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
@@ -11,3 +11,14 @@ repos:
|
||||
- id: debug-statements
|
||||
- id: check-merge-conflict
|
||||
- id: check-toml
|
||||
- id: check-ast
|
||||
- id: fix-byte-order-marker
|
||||
- id: detect-aws-credentials
|
||||
args: [--allow-missing-credentials]
|
||||
- id: detect-private-key
|
||||
- id: mixed-line-ending
|
||||
- repo: https://github.com/Yelp/detect-secrets
|
||||
rev: v1.5.0
|
||||
hooks:
|
||||
- id: detect-secrets
|
||||
args: ['--baseline', '.ds.baseline']
|
||||
|
||||
3
Makefile
3
Makefile
@@ -76,9 +76,10 @@ py-test: ## Run python unit tests
|
||||
poetry run coverage html -d .coverage_cache
|
||||
|
||||
.PHONY: dead-code
|
||||
dead-code:
|
||||
dead-code: ## 60% is our aspirational goal, but currently breaks the build
|
||||
poetry run vulture ./app ./notifications_utils --min-confidence=100
|
||||
|
||||
|
||||
.PHONY: e2e-test
|
||||
e2e-test: export NEW_RELIC_ENVIRONMENT=test
|
||||
e2e-test: ## Run end-to-end integration tests; note that --browser webkit isn't currently working
|
||||
|
||||
@@ -38,7 +38,7 @@ class Config(object):
|
||||
NR_MONITOR_ON = settings and settings.monitor_mode
|
||||
COMMIT_HASH = getenv("COMMIT_HASH", "--------")[0:7]
|
||||
|
||||
GOVERNMENT_EMAIL_DOMAIN_NAMES = ["gov"]
|
||||
GOVERNMENT_EMAIL_DOMAIN_NAMES = ["gov", "mil", "si.edu"]
|
||||
|
||||
# Logging
|
||||
NOTIFY_LOG_LEVEL = getenv("NOTIFY_LOG_LEVEL", "INFO")
|
||||
|
||||
@@ -26,6 +26,7 @@ from app.main.views import sign_in
|
||||
from app.main.views.verify import activate_user
|
||||
from app.models.user import InvitedOrgUser, InvitedUser, User
|
||||
from app.utils import hide_from_search_engines, hilite
|
||||
from app.utils.user import is_gov_user
|
||||
|
||||
|
||||
@main.route("/register", methods=["GET", "POST"])
|
||||
@@ -147,6 +148,11 @@ def check_invited_user_email_address_matches_expected(
|
||||
flash("You cannot accept an invite for another person.")
|
||||
abort(403)
|
||||
|
||||
if not is_gov_user(user_email):
|
||||
debug_msg("invited user has a non-government email address.")
|
||||
flash("You must use a government email address.")
|
||||
abort(403)
|
||||
|
||||
|
||||
@main.route("/set-up-your-profile", methods=["GET", "POST"])
|
||||
@hide_from_search_engines
|
||||
|
||||
@@ -948,7 +948,9 @@ def send_notification(service_id, template_id):
|
||||
vals = ",".join(values)
|
||||
data = f"{data}\r\n{vals}"
|
||||
|
||||
filename = f"one-off-{current_user.name}-{uuid.uuid4()}.csv"
|
||||
filename = (
|
||||
f"one-off-{uuid.uuid4()}.csv" # {current_user.name} removed from filename
|
||||
)
|
||||
my_data = {"filename": filename, "template_id": template_id, "data": data}
|
||||
upload_id = s3upload(service_id, my_data)
|
||||
form = CsvUploadForm()
|
||||
|
||||
@@ -4,7 +4,16 @@ import uuid
|
||||
|
||||
import jwt
|
||||
import requests
|
||||
from flask import Response, current_app, redirect, render_template, request, url_for
|
||||
from flask import (
|
||||
Response,
|
||||
abort,
|
||||
current_app,
|
||||
flash,
|
||||
redirect,
|
||||
render_template,
|
||||
request,
|
||||
url_for,
|
||||
)
|
||||
from flask_login import current_user
|
||||
|
||||
from app import login_manager, user_api_client
|
||||
@@ -15,6 +24,7 @@ from app.models.user import User
|
||||
from app.utils import hide_from_search_engines
|
||||
from app.utils.login import is_safe_redirect_url
|
||||
from app.utils.time import is_less_than_days_ago
|
||||
from app.utils.user import is_gov_user
|
||||
from notifications_utils.url_safe_token import generate_token
|
||||
|
||||
|
||||
@@ -88,6 +98,12 @@ def _do_login_dot_gov():
|
||||
try:
|
||||
access_token = _get_access_token(code, state)
|
||||
user_email, user_uuid = _get_user_email_and_uuid(access_token)
|
||||
if not is_gov_user(user_email):
|
||||
current_app.logger.error(
|
||||
"invited user has a non-government email address."
|
||||
)
|
||||
flash("You must use a government email address.")
|
||||
abort(403)
|
||||
redirect_url = request.args.get("next")
|
||||
user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ def using_notify_nav():
|
||||
"link": "main.trial_mode_new",
|
||||
},
|
||||
{
|
||||
"name": "Pricing",
|
||||
"name": "Tracking usage",
|
||||
"link": "main.pricing",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% block flash_messages %}
|
||||
{% include 'flash_messages.html' %}
|
||||
{% include 'new/components/flash_messages.html' %}
|
||||
{% endblock %}
|
||||
{% block maincolumn_content %}
|
||||
<div class="grid-row">
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
{% extends "/new/base.html" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{% block service_page_title %}{% endblock %}{% if current_service.name %} – {{ current_service.name }}{% endif %}
|
||||
{% block org_page_title %}{% endblock %}{% if current_org.name %} – {{ current_org.name }}{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="grid-container">
|
||||
{% block serviceNavigation %}
|
||||
{% if current_org.name %}
|
||||
{% else %}
|
||||
{% include "new/components/service_navigation.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{#
|
||||
The withnav_template can serve as a replacement for both settings_template and org_template.html.
|
||||
|
||||
The file service_navigation.html is included only in withnav_template. It's not used in settings_template. That is one out of the two differences between settings template and withnav template. As a result, when other templates extend settings_template, they include the serviceNavigation block but keep it empty. The settings_template.html is specifically used for these pages in the app: manage-users.html, service-settings.html, and user-profile.html.
|
||||
|
||||
In addition, serviceNavigation should be empty on templates that previously extended org_template. For templates that previously extended org_template.html, there's an addition of the orgNavBreadcrumb block.
|
||||
{% block orgNavBreadcrumb %}
|
||||
{% include "/new/components/org_nav_breadcrumb.html" %}
|
||||
{% endblock %}
|
||||
#}
|
||||
{% if current_org.name %}
|
||||
{% block orgNavBreadcrumb %}{% include "/new/components/org_nav_breadcrumb.html" %}{% endblock %}
|
||||
{% endif %}
|
||||
<div class="grid-row margin-top-5">
|
||||
<div class="tablet:grid-col-3">
|
||||
{% block sideNavigation %}
|
||||
{% if org_navigation_links %}
|
||||
{% include "/new/components/org_nav.html" %}
|
||||
{% else %}
|
||||
{% include "/new/components/main_nav.html" %}
|
||||
{% endif %}
|
||||
{#
|
||||
Include settings_nav.html for child templates that previously extended settings_template.
|
||||
|
||||
Include "org_nav.html" for child templates that previously extended org_template html
|
||||
#}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="tablet:grid-col-9 tablet:padding-left-4">
|
||||
{% block beforeContent %}
|
||||
{% block backLink %}{% endblock %}
|
||||
{% endblock %}
|
||||
<main id="main-content" role="main" class="usa-prose site-prose margin-bottom-10">
|
||||
{% block content %}
|
||||
{% include 'flash_messages.html' %}
|
||||
{% block maincolumn_content %}{% endblock %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,3 +1,4 @@
|
||||
{# This template is an old version #}
|
||||
{% if help %}
|
||||
{% include 'partials/tour.html' %}
|
||||
{% else %}
|
||||
@@ -1,3 +1,4 @@
|
||||
{# This template is an old version #}
|
||||
<nav class="navigation">
|
||||
<ul>
|
||||
<li><a class="usa-link{{ org_navigation.is_selected('dashboard') }}" href="{{ url_for('.organization_dashboard', org_id=current_org.id) }}">Usage</a></li>
|
||||
@@ -1,3 +1,4 @@
|
||||
{# This template is an old version #}
|
||||
{% macro navigation_service_name(service) %}
|
||||
<div class="font-body-2xl text-bold">
|
||||
{{ service.name }}
|
||||
@@ -1,3 +1,4 @@
|
||||
{# This template is an old version #}
|
||||
{% if help %}
|
||||
{% include 'partials/tour.html' %}
|
||||
{% else %}
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{# This template is an old version #}
|
||||
{% extends "admin_template.html" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{% block service_page_title %}{% endblock %} – {{ current_service.name }}
|
||||
36
app/templates/old/withnav_template.html
Normal file
36
app/templates/old/withnav_template.html
Normal file
@@ -0,0 +1,36 @@
|
||||
{# This template is an old version #}
|
||||
{% extends "admin_template.html" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{% block service_page_title %}{% endblock %} – {{ current_service.name }}
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="grid-container">
|
||||
{% include "service_navigation.html" %}
|
||||
<div class="grid-row margin-top-5">
|
||||
{% if help %}
|
||||
<div class="tablet:grid-col-3">
|
||||
{% else %}
|
||||
<div class="tablet:grid-col-3">
|
||||
{% endif %}
|
||||
{% include "main_nav.html" %}
|
||||
</div>
|
||||
{% if help %}
|
||||
<div class="grid-col-8">
|
||||
{% else %}
|
||||
<div class="tablet:grid-col-9 tablet:padding-left-4">
|
||||
{% endif %}
|
||||
{% block beforeContent %}
|
||||
{% block backLink %}{% endblock %}
|
||||
{% endblock %}
|
||||
<main id="main-content" role="main" class="usa-prose site-prose margin-bottom-10">
|
||||
{% block content %}
|
||||
{% include 'flash_messages.html' %}
|
||||
{% block maincolumn_content %}{% endblock %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -59,7 +59,7 @@
|
||||
{% set notification = job.notifications[0] %}
|
||||
<tr class="table-row" id="{{ job.job_id }}">
|
||||
<td class="table-field file-name">
|
||||
{{ notification.job.original_file_name if notification.job.original_file_name else 'Manually entered number'}}
|
||||
{{ notification.job.original_file_name[:12] if notification.job.original_file_name else 'Manually entered number'}}
|
||||
<br>
|
||||
<a class="usa-link file-list-filename" href="{{ job.view_job_link }}">View Batch</a>
|
||||
</td>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "settings_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/tick-cross.html" import tick_cross %}
|
||||
{% from "components/live-search.html" import live_search %}
|
||||
{% from "components/components/button/macro.njk" import usaButton %}
|
||||
@@ -7,6 +7,12 @@
|
||||
Team members
|
||||
{% endblock %}
|
||||
|
||||
{% block serviceNavigation %}{% endblock %}
|
||||
|
||||
{% block sideNavigation %}
|
||||
{% include "/new/components/settings_nav.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<div class="button-flex-header">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
|
||||
{% block org_page_title %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% from "components/big-number.html" import big_number %}
|
||||
{% from "components/live-search.html" import live_search %}
|
||||
{% from "components/pill.html" import pill %}
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
|
||||
{% block org_page_title %}
|
||||
Usage
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/list-entry.html" import list_entry %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/table.html" import mapping_table, optional_text_field, row, text_field, edit_field with context %}
|
||||
|
||||
{% block org_page_title %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/live-search.html" import live_search %}
|
||||
|
||||
{% block org_page_title %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/table.html" import list_table, row, field, hidden_field_heading %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/live-search.html" import live_search %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
{% block backLink %}{% endblock %}
|
||||
<main id="main-content" role="main">
|
||||
{% block content %}
|
||||
{% include 'flash_messages.html' %}
|
||||
{% include 'new/components/flash_messages.html' %}
|
||||
{% block platform_admin_content %}{% endblock %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
|
||||
@@ -15,7 +15,7 @@ Message parts
|
||||
|
||||
{{ content_metadata(
|
||||
data={
|
||||
"Last updated": "February 5, 2024"
|
||||
"Last updated": "April 10, 2024"
|
||||
}
|
||||
) }}
|
||||
|
||||
@@ -26,13 +26,15 @@ more parts towards the allowance if you:</p>
|
||||
<ul class="list list-bullet">
|
||||
<li>send text messages longer than 160 characters</a></li>
|
||||
<li>use certain <a class="usa-link" href="#symbols">signs and symbols</a></li>
|
||||
<li>use <a class="usa-link" href="#accents">accents and accented letters</a></li>
|
||||
<li>use <a class="usa-link" href="#accents">accents and accented letters, including non-romanized scripts</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 class="font-body-lg" id="long-text-messages">Long text messages</h3>
|
||||
<p>If a text message is longer than 160 characters (including spaces and service name), it counts as more than one message
|
||||
part.</p>
|
||||
|
||||
<h4>Calculation of message parts without special characters</h4>
|
||||
|
||||
<div class="bottom-gutter-3-2">
|
||||
{% call mapping_table(
|
||||
caption='Text message pricing',
|
||||
@@ -72,12 +74,17 @@ and the number of parts you’ll have left.</p>
|
||||
|
||||
<p>Using them can increase the cost of sending text messages.</p>
|
||||
|
||||
<h3 class="font-body-lg" id="accents">Accents and accented characters</h3>
|
||||
<p>Some languages use accented characters.</p>
|
||||
<h3 class="font-body-lg" id="accents">Accented characters and non-romanized scripts</h3>
|
||||
<p>Notify can handle a wide range of different languages and scripts. However, occasionally some phone carriers may
|
||||
struggle to display special characters or non-romanized scripts. (Languages such as Arabic, Chinese, Japanese, Korean,
|
||||
and Russian use non-romanized scripts with different characters.) Best practices encourage communication in the
|
||||
recipient’s preferred language, but we are aware that, rarely, a phone carrier will not be able to handle the message.</p>
|
||||
<p>The following accented characters do not affect the cost of sending text messages: Ä, É, Ö, Ü, à, ä, é, è, ì, ò, ö,
|
||||
ù, ü.</p>
|
||||
<p>Using other accented characters can increase the cost of sending text messages.
|
||||
<p>
|
||||
<p>Using other accented characters or scripts will increase the cost of sending text messages. Even one accented character
|
||||
(with the exception of those noted above), or use of a non-romanized or logographic script will cause the entire message
|
||||
to be calculated as detailed below.<p>
|
||||
<h4>Calculation of message parts with special characters or non-romanized scripts</h4>
|
||||
{% set accentedChars %}
|
||||
<div class="bottom-gutter-3-2">
|
||||
{% call mapping_table(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "settings_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/banner.html" import banner_wrapper %}
|
||||
{% from "components/table.html" import mapping_table, row, settings_row, text_field, optional_text_field, edit_field, field, boolean_field with context %}
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
Settings
|
||||
{% endblock %}
|
||||
|
||||
{% block serviceNavigation %}{% endblock %}
|
||||
|
||||
{% block sideNavigation %}
|
||||
{% include "/new/components/settings_nav.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<h1 class="font-body-lg">Settings</h1>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "settings_template.html" %}
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/table.html" import list_table, row, field %}
|
||||
{% from "components/table.html" import mapping_table, row, text_field, optional_text_field, edit_field, field, boolean_field with context %}
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
User profile
|
||||
{% endblock %}
|
||||
|
||||
{% block serviceNavigation %}{% endblock %}
|
||||
|
||||
{% block sideNavigation %}
|
||||
{% include "/new/components/settings_nav.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<h1 class="font-body-2xl margin-bottom-3">User profile</h1>
|
||||
|
||||
@@ -1,31 +1,56 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{% block service_page_title %}{% endblock %} – {{ current_service.name }}
|
||||
{% if current_org.name %}
|
||||
{% block org_page_title %}{% endblock %} – {{ current_org.name }}
|
||||
{% else %}
|
||||
{% block service_page_title %}{% endblock %} – {{ current_service.name }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="grid-container">
|
||||
{% include "service_navigation.html" %}
|
||||
{% block serviceNavigation %}
|
||||
{% if current_org.name %}
|
||||
{% else %}
|
||||
{% include "new/components/service_nav.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{#
|
||||
The withnav_template can serve as a replacement for both settings_template and org_template.html.
|
||||
|
||||
The file service_navigation.html is included only in withnav_template. It's not used in settings_template. That is one out of the two differences between settings template and withnav template. As a result, when other templates extend settings_template, they include the serviceNavigation block but keep it empty. The settings_template.html is specifically used for these pages in the app: manage-users.html, service-settings.html, and user-profile.html.
|
||||
|
||||
In addition, serviceNavigation should be empty on templates that previously extended org_template. For templates that previously extended org_template.html, there's an addition of the orgNavBreadcrumb block.
|
||||
{% block orgNavBreadcrumb %}
|
||||
{% include "/new/components/org_nav_breadcrumb.html" %}
|
||||
{% endblock %}
|
||||
#}
|
||||
{% if current_org.name %}
|
||||
{% block orgNavBreadcrumb %}{% include "/new/components/org_nav_breadcrumb.html" %}{% endblock %}
|
||||
{% endif %}
|
||||
<div class="grid-row margin-top-5">
|
||||
{% if help %}
|
||||
<div class="tablet:grid-col-3">
|
||||
{% else %}
|
||||
<div class="tablet:grid-col-3">
|
||||
{% endif %}
|
||||
{% include "main_nav.html" %}
|
||||
</div>
|
||||
{% if help %}
|
||||
<div class="grid-col-8">
|
||||
{% else %}
|
||||
<div class="tablet:grid-col-9 tablet:padding-left-4">
|
||||
{% endif %}
|
||||
<div class="tablet:grid-col-3">
|
||||
{% block sideNavigation %}
|
||||
{% if current_org.name %}
|
||||
{% include "/new/components/org_nav.html" %}
|
||||
{% else %}
|
||||
{% include "/new/components/main_nav.html" %}
|
||||
{% endif %}
|
||||
{#
|
||||
Include settings_nav.html for child templates that previously extended settings_template.
|
||||
|
||||
Include "org_nav.html" for child templates that previously extended org_template html
|
||||
#}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="tablet:grid-col-9 tablet:padding-left-4">
|
||||
{% block beforeContent %}
|
||||
{% block backLink %}{% endblock %}
|
||||
{% endblock %}
|
||||
<main id="main-content" role="main" class="usa-prose site-prose margin-bottom-10">
|
||||
{% block content %}
|
||||
{% include 'flash_messages.html' %}
|
||||
{% include 'new/components/flash_messages.html' %}
|
||||
{% block maincolumn_content %}{% endblock %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
|
||||
@@ -4,7 +4,6 @@ from flask import abort, current_app
|
||||
from flask_login import current_user, login_required
|
||||
|
||||
from app import config
|
||||
from app.notify_client.organizations_api_client import organizations_client
|
||||
|
||||
user_is_logged_in = login_required
|
||||
|
||||
@@ -51,7 +50,7 @@ def user_is_platform_admin(f):
|
||||
def is_gov_user(email_address):
|
||||
return _email_address_ends_with(
|
||||
email_address, config.Config.GOVERNMENT_EMAIL_DOMAIN_NAMES
|
||||
) or _email_address_ends_with(email_address, organizations_client.get_domains())
|
||||
) # or _email_address_ends_with(email_address, organizations_client.get_domains())
|
||||
|
||||
|
||||
def _email_address_ends_with(email_address, known_domains):
|
||||
|
||||
25
poetry.lock
generated
25
poetry.lock
generated
@@ -611,6 +611,25 @@ files = [
|
||||
{file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "detect-secrets"
|
||||
version = "1.5.0"
|
||||
description = "Tool for detecting secrets in the codebase"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "detect_secrets-1.5.0-py3-none-any.whl", hash = "sha256:e24e7b9b5a35048c313e983f76c4bd09dad89f045ff059e354f9943bf45aa060"},
|
||||
{file = "detect_secrets-1.5.0.tar.gz", hash = "sha256:6bb46dcc553c10df51475641bb30fd69d25645cc12339e46c824c1e0c388898a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pyyaml = "*"
|
||||
requests = "*"
|
||||
|
||||
[package.extras]
|
||||
gibberish = ["gibberish-detector"]
|
||||
word-list = ["pyahocorasick"]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.3.8"
|
||||
@@ -1647,12 +1666,12 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "notifications-python-client"
|
||||
version = "9.0.0"
|
||||
version = "9.1.0"
|
||||
description = "Python API client for GOV.UK Notify."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "notifications_python_client-9.0.0-py3-none-any.whl", hash = "sha256:664a5b5da2aa1a00efa8106bfa4855db04da95d79586e5edfb0411637d20d2d9"},
|
||||
{file = "notifications_python_client-9.1.0-py3-none-any.whl", hash = "sha256:43b8f738dfa81ae3aa656d91e361dbc51316194f8b9a430706b03347fa7a01bc"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2909,4 +2928,4 @@ files = [
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.12.2"
|
||||
content-hash = "17d4fa911a9aba6f956ef316583babd63f31a849372ae47a0a79e260295dad45"
|
||||
content-hash = "dbfc0e66e41f6da3845785157b95ef70193bc66c91b53fe0afb0eac0a1ea5490"
|
||||
|
||||
@@ -23,7 +23,7 @@ humanize = "~=4.9"
|
||||
itsdangerous = "~=2.2"
|
||||
jinja2 = "~=3.1"
|
||||
newrelic = "*"
|
||||
notifications-python-client = "==9.0.0"
|
||||
notifications-python-client = "==9.1.0"
|
||||
pyexcel = "==0.7.0"
|
||||
pyexcel-io = "==0.6.6"
|
||||
pyexcel-ods3 = "==0.6.1"
|
||||
@@ -39,8 +39,8 @@ wtforms = "~=3.1"
|
||||
markdown = "^3.5.2"
|
||||
async-timeout = "^4.0.3"
|
||||
bleach = "^6.1.0"
|
||||
boto3 = "^1.34.106"
|
||||
botocore = "^1.34.106"
|
||||
boto3 = "^1.34.115"
|
||||
botocore = "^1.34.116"
|
||||
cachetools = "^5.3.3"
|
||||
cffi = "^1.16.0"
|
||||
cryptography = "^42.0.7"
|
||||
@@ -50,7 +50,7 @@ jmespath = "^1.0.1"
|
||||
mistune = "0.8.4"
|
||||
numpy = "^1.26.4"
|
||||
ordered-set = "^4.1.0"
|
||||
phonenumbers = "^8.13.36"
|
||||
phonenumbers = "^8.13.37"
|
||||
pycparser = "^2.22"
|
||||
python-json-logger = "^2.0.7"
|
||||
redis = "^5.0.4"
|
||||
@@ -65,7 +65,7 @@ idna = "^3.7"
|
||||
markupsafe = "^2.1.5"
|
||||
python-dateutil = "^2.9.0.post0"
|
||||
pyyaml = "^6.0.1"
|
||||
requests = "^2.31.0"
|
||||
requests = "^2.32.3"
|
||||
six = "^1.16.0"
|
||||
urllib3 = "^2.2.1"
|
||||
webencodings = "^0.5.1"
|
||||
@@ -84,7 +84,7 @@ isort = "^5.13.2"
|
||||
jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
|
||||
pip-audit = "*"
|
||||
pre-commit = "^3.7.1"
|
||||
pytest = "^8.1.1"
|
||||
pytest = "^8.2.1"
|
||||
pytest-env = "^1.1.3"
|
||||
pytest-mock = "^3.14.0"
|
||||
pytest-playwright = "^0.5.0"
|
||||
@@ -92,6 +92,7 @@ pytest-xdist = "^3.5.0"
|
||||
radon = "^6.0.1"
|
||||
requests-mock = "^1.11.0"
|
||||
vulture = "^2.11"
|
||||
detect-secrets = "^1.5.0"
|
||||
|
||||
|
||||
[build-system]
|
||||
|
||||
@@ -148,7 +148,7 @@ def test_should_return_200_when_email_is_not_gov_uk(
|
||||
"email_address",
|
||||
[
|
||||
"notfound@example.gsa.gov",
|
||||
"example@lsquo.net",
|
||||
"example@lsquo.si.edu",
|
||||
],
|
||||
)
|
||||
def test_should_add_user_details_to_session(
|
||||
@@ -401,6 +401,26 @@ def test_check_invited_user_email_address_doesnt_match_expected(mocker):
|
||||
mock_abort.assert_called_once_with(403)
|
||||
|
||||
|
||||
def test_check_user_email_address_fails_if_not_government_address(mocker):
|
||||
mock_flash = mocker.patch("app.main.views.register.flash")
|
||||
mock_abort = mocker.patch("app.main.views.register.abort")
|
||||
|
||||
check_invited_user_email_address_matches_expected(
|
||||
"fake@fake.bogus", "Fake@Fake.BOGUS"
|
||||
)
|
||||
mock_flash.assert_called_once_with("You must use a government email address.")
|
||||
mock_abort.assert_called_once_with(403)
|
||||
|
||||
|
||||
def test_check_user_email_address_succeeds_if_government_address(mocker):
|
||||
mock_flash = mocker.patch("app.main.views.register.flash")
|
||||
mock_abort = mocker.patch("app.main.views.register.abort")
|
||||
|
||||
check_invited_user_email_address_matches_expected("fake@fake.mil", "Fake@Fake.MIL")
|
||||
mock_flash.assert_not_called()
|
||||
mock_abort.assert_not_called()
|
||||
|
||||
|
||||
def decode_invite_data(state):
|
||||
state = state.encode("utf8")
|
||||
state = base64.b64decode(state)
|
||||
|
||||
@@ -191,7 +191,7 @@ def handle_no_existing_template_case(page):
|
||||
in content
|
||||
)
|
||||
assert "12025555555" in content
|
||||
assert "one-off-e2e_test_user" in content
|
||||
assert "one-off-" in content
|
||||
os.remove("download_test_file")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user