diff --git a/.ds.baseline b/.ds.baseline index b600f48f1..36b7821a7 100644 --- a/.ds.baseline +++ b/.ds.baseline @@ -133,7 +133,7 @@ "filename": ".github/workflows/checks.yml", "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", "is_verified": false, - "line_number": 66, + "line_number": 68, "is_secret": false } ], @@ -684,5 +684,5 @@ } ] }, - "generated_at": "2024-09-03T17:36:57Z" + "generated_at": "2024-10-07T20:44:40Z" } diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 8fa950942..f002bb3fc 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -53,11 +53,13 @@ jobs: end-to-end-tests: if: ${{ github.actor != 'dependabot[bot]' }} + permissions: checks: write pull-requests: write contents: write runs-on: ubuntu-latest + environment: staging services: postgres: image: postgres @@ -97,13 +99,17 @@ jobs: # insert this line: # tail -f admin-server.log & # above make e2e-test + + run: | make run-flask > admin-server.log 2>&1 & + tail -f admin-server.log & make e2e-test + env: API_HOST_NAME: https://notify-api-staging.app.cloud.gov/ - DANGEROUS_SALT: ${{ secrets.DANGEROUS_SALT }} SECRET_KEY: ${{ secrets.SECRET_KEY }} + DANGEROUS_SALT: ${{ secrets.DANGEROUS_SALT }} ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} ADMIN_CLIENT_USERNAME: notify-admin NOTIFY_ENVIRONMENT: e2etest @@ -111,7 +117,7 @@ jobs: NOTIFY_E2E_TEST_EMAIL: ${{ secrets.NOTIFY_E2E_TEST_EMAIL }} NOTIFY_E2E_TEST_PASSWORD: ${{ secrets.NOTIFY_E2E_TEST_PASSWORD }} NOTIFY_E2E_TEST_URI: http://localhost:6012/ - + VCAP_SERVICES: ${{ secrets.VCAP_SERVICES }} validate-new-relic-config: runs-on: ubuntu-latest environment: staging diff --git a/README.md b/README.md index 04458e394..e1a372fd3 100644 --- a/README.md +++ b/README.md @@ -507,3 +507,13 @@ insurance. For more information on what we're working on, the Notify tool, and how to get involved with our team, [see our flyer.](https://github.com/GSA/notifications-admin/blob/main/docs/notify-pilot-flyer.md) + +## Updating secrets for the E2E tests + +At some point, E2E tests will fail because the secrets held in VCAP_SERVICES have expired. To refresh +them, you will need to do the following: + +1. Log in the normal way to access cloudfoundry command line options +2. In your terminal, run `chmod +x print_vcap.sh` +3. In your terminal, run `./print_vcap.sh` +4. Copy the value in your terminal and paste it into the VCAP_SERVICES secret in Github on the staging tier. diff --git a/app/main/views/send.py b/app/main/views/send.py index 2582cfeff..3d83d10f3 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -802,9 +802,15 @@ def get_skip_link(step_index, template): ) @user_has_permissions("send_messages", restrict_admin_usage=True) def send_one_off_to_myself(service_id, template_id): - db_template = current_service.get_template_with_user_permission_or_403( - template_id, current_user - ) + current_app.logger.info("Send one off to myself") + try: + db_template = current_service.get_template_with_user_permission_or_403( + template_id, current_user + ) + except Exception: + current_app.logger.exception("Couldnt get template for one off") + # Use 406 just because we're limited to certain codes here and it will point us back to a problem here + abort(406) if db_template["template_type"] not in ("sms", "email"): abort(404) diff --git a/app/models/user.py b/app/models/user.py index ba478feda..468208d6e 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -201,7 +201,7 @@ class User(JSONModel, UserMixin): @property def is_gov_user(self): is_gov = is_gov_user(self.email_address) - current_app.logger.info(f"User {self.id} is_gov_user: {is_gov}") + # current_app.logger.info(f"User {self.id} is_gov_user: {is_gov}") return is_gov @property @@ -210,9 +210,9 @@ class User(JSONModel, UserMixin): @property def platform_admin(self): - current_app.logger.warn( - f"Checking User {self.id} for platform admin: {self._platform_admin}" - ) + # current_app.logger.warning( + # f"Checking User {self.id} for platform admin: {self._platform_admin}" + # ) return self._platform_admin and not session.get( "disable_platform_admin_view", False ) @@ -242,26 +242,31 @@ class User(JSONModel, UserMixin): # we shouldn't have any pages that require permissions, but don't specify a service or organization. # use @user_is_platform_admin for platform admin only pages # raise NotImplementedError - current_app.logger.warn(f"VIEW ARGS ARE {request.view_args}") + # current_app.logger.warning(f"VIEW ARGS ARE {request.view_args}") pass - log_msg = f"has_permissions user: {self.id} service: {service_id}" # platform admins should be able to do most things (except eg send messages, or create api keys) if self.platform_admin and not restrict_admin_usage: - current_app.logger.warn(f"{log_msg} true because user is platform_admin") + current_app.logger.debug( + "has_permissions is true because user is platform_admin" + ) return True if org_id: value = self.belongs_to_organization(org_id) - current_app.logger.warn(f"{log_msg} org: {org_id} returning {value}") + current_app.logger.debug( + f"has_permissions returns org: {org_id} returning {value}" + ) return value if not permissions and self.belongs_to_service(service_id): - current_app.logger.warn(f"{log_msg} True because belongs_to_service") + current_app.logger.debug("has_permissions True because belongs_to_service") return True if any(self.permissions_for_service(service_id) & set(permissions)): - current_app.logger.warn(f"{log_msg} permissions valid") + current_app.logger.debug( + "has_permissions returns True because permissions valid" + ) return True from app.models.service import Service @@ -269,7 +274,7 @@ class User(JSONModel, UserMixin): org_value = allow_org_user and self.belongs_to_organization( Service.from_id(service_id).organization_id ) - current_app.logger.warn(f"{log_msg} returning {org_value}") + current_app.logger.debug(f"has_permissions returning {org_value}") return org_value def permissions_for_service(self, service_id): @@ -277,7 +282,7 @@ class User(JSONModel, UserMixin): def has_permission_for_service(self, service_id, permission): has_permission = permission in self.permissions_for_service(service_id) - current_app.logger.warn( + current_app.logger.debug( f"has_permission_for_service user: {self.id} service: {service_id} " f"permission: {permission} retuning {has_permission}" ) @@ -558,17 +563,17 @@ class InvitedUser(JSONModel): return cls.by_id(invited_user_id) if invited_user_id else None def has_permissions(self, *permissions): - current_app.logger.warn( - f"Checking invited user {self.id} for permissions: {permissions}" - ) + # current_app.logger.warning( + # f"Checking invited user {self.id} for permissions: {permissions}" + # ) if self.status == "cancelled": return False return set(self.permissions) > set(permissions) def has_permission_for_service(self, service_id, permission): - current_app.logger.warn( - f"Checking invited user {self.id} for permission: {permission} on service {service_id}" - ) + # current_app.logger.warn( + # f"Checking invited user {self.id} for permission: {permission} on service {service_id}" + # ) if self.status == "cancelled": return False return self.service == service_id and permission in self.permissions diff --git a/app/s3_client/__init__.py b/app/s3_client/__init__.py index 7de3509d2..fda938ebe 100644 --- a/app/s3_client/__init__.py +++ b/app/s3_client/__init__.py @@ -29,7 +29,10 @@ def get_s3_object( aws_secret_access_key=secret_key, region_name=region, ) - s3 = session.resource("s3", config=AWS_CLIENT_CONFIG) + s3 = session.resource( + "s3", + config=AWS_CLIENT_CONFIG, + ) obj = s3.Object(bucket_name, filename) # This 'proves' that use of moto in the relevant tests in test_send.py # mocks everything related to S3. What you will see in the logs is: diff --git a/app/s3_client/s3_csv_client.py b/app/s3_client/s3_csv_client.py index 09454ade0..195ea3032 100644 --- a/app/s3_client/s3_csv_client.py +++ b/app/s3_client/s3_csv_client.py @@ -1,3 +1,4 @@ +import os import uuid from flask import current_app @@ -33,6 +34,14 @@ def s3upload(service_id, filedata): bucket_name, file_location, access_key, secret_key, region = get_csv_location( service_id, upload_id ) + if bucket_name == "": + exp_bucket = current_app.config["CSV_UPLOAD_BUCKET"]["bucket"] + exp_region = current_app.config["CSV_UPLOAD_BUCKET"]["region"] + tier = os.getenv("NOTIFY_ENVIRONMENT") + raise Exception( + f"NO BUCKET NAME SHOULD BE: {exp_bucket} WITH REGION {exp_region} TIER {tier}" + ) + utils_s3upload( filedata=filedata["data"], region=region, diff --git a/app/templates/partials/jobs/status.html b/app/templates/partials/jobs/status.html index 42cf4a4b7..69251a50a 100644 --- a/app/templates/partials/jobs/status.html +++ b/app/templates/partials/jobs/status.html @@ -25,7 +25,7 @@ {% if job.scheduled_for %}
{{ job.template_name }} - {{ current_service.name }} was scheduled on {{ job.scheduled_for|format_datetime_normal }} by {{ job.created_by.name }}
@@ -35,7 +35,7 @@ {% else %}
{{ job.template_name }} - {{ current_service.name }} was sent on {% if job.processing_started %}
{{ job.processing_started|format_datetime_table }} {% else %}
diff --git a/notifications_utils/s3.py b/notifications_utils/s3.py
index d33cbe25a..f7b342284 100644
--- a/notifications_utils/s3.py
+++ b/notifications_utils/s3.py
@@ -37,7 +37,10 @@ def s3upload(
aws_secret_access_key=secret_key,
region_name=region,
)
- _s3 = session.resource("s3", config=AWS_CLIENT_CONFIG)
+ _s3 = session.resource(
+ "s3",
+ config=AWS_CLIENT_CONFIG,
+ )
# This 'proves' that use of moto in the relevant tests in test_send.py
# mocks everything related to S3. What you will see in the logs is:
# Exception: CREATED AT