mirror of
https://github.com/GSA/notifications-api.git
synced 2026-08-25 16:53:42 -04:00
initial
This commit is contained in:
@@ -46,7 +46,8 @@ def list_s3_objects():
|
|||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
f"An error occurred while regenerating cache #notify-admin-1200 {e}"
|
f"An error occurred while regenerating cache #notify-admin-1200",
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ def get_s3_files():
|
|||||||
JOBS[job_id] = object
|
JOBS[job_id] = object
|
||||||
except LookupError as le:
|
except LookupError as le:
|
||||||
# perhaps our key is not formatted as we expected. If so skip it.
|
# perhaps our key is not formatted as we expected. If so skip it.
|
||||||
current_app.logger.error(f"LookupError {le} #notify-admin-1200")
|
current_app.logger.error(f"LookupError #notify-admin-1200", exc_info=True)
|
||||||
|
|
||||||
current_app.logger.info(
|
current_app.logger.info(
|
||||||
f"JOBS cache length after regen: {len(JOBS)} #notify-admin-1200"
|
f"JOBS cache length after regen: {len(JOBS)} #notify-admin-1200"
|
||||||
@@ -110,14 +111,14 @@ def download_from_s3(
|
|||||||
result = s3.download_file(bucket_name, s3_key, local_filename)
|
result = s3.download_file(bucket_name, s3_key, local_filename)
|
||||||
current_app.logger.info(f"File downloaded successfully to {local_filename}")
|
current_app.logger.info(f"File downloaded successfully to {local_filename}")
|
||||||
except botocore.exceptions.NoCredentialsError as nce:
|
except botocore.exceptions.NoCredentialsError as nce:
|
||||||
current_app.logger.error("Credentials not found")
|
current_app.logger.error("Credentials not found", exc_info=True)
|
||||||
raise Exception(nce)
|
raise Exception(nce)
|
||||||
except botocore.exceptions.PartialCredentialsError as pce:
|
except botocore.exceptions.PartialCredentialsError as pce:
|
||||||
current_app.logger.error("Incomplete credentials provided")
|
current_app.logger.error("Incomplete credentials provided", exc_info=True)
|
||||||
raise Exception(pce)
|
raise Exception(pce)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.error(f"An error occurred {e}")
|
current_app.logger.error(f"An error occurred", exc_info=True)
|
||||||
text = f"EXCEPTION {e} local_filename {local_filename}"
|
text = f"EXCEPTION local_filename {local_filename}"
|
||||||
raise Exception(text)
|
raise Exception(text)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -191,7 +192,7 @@ def get_job_from_s3(service_id, job_id):
|
|||||||
time.sleep(sleep_time)
|
time.sleep(sleep_time)
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.error(f"Failed to get object from bucket {e}")
|
current_app.logger.error(f"Failed to get object from bucket", exc_info=True)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
raise Exception("Failed to get object after 5 attempts")
|
raise Exception("Failed to get object after 5 attempts")
|
||||||
@@ -231,7 +232,8 @@ def extract_phones(job):
|
|||||||
if phone_index >= len(row):
|
if phone_index >= len(row):
|
||||||
phones[job_row] = "Unavailable"
|
phones[job_row] = "Unavailable"
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
"Corrupt csv file, missing columns or possibly a byte order mark in the file"
|
"Corrupt csv file, missing columns or possibly a byte order mark in the file",
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -298,7 +300,7 @@ def get_phone_number_from_s3(service_id, job_id, job_row_number):
|
|||||||
return "Unavailable"
|
return "Unavailable"
|
||||||
else:
|
else:
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
f"Was unable to construct lookup dictionary for job {job_id}"
|
f"Was unable to construct lookup dictionary for job {job_id}", exc_info=True
|
||||||
)
|
)
|
||||||
return "Unavailable"
|
return "Unavailable"
|
||||||
|
|
||||||
@@ -345,7 +347,7 @@ def get_personalisation_from_s3(service_id, job_id, job_row_number):
|
|||||||
return {}
|
return {}
|
||||||
else:
|
else:
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
f"Was unable to construct lookup dictionary for job {job_id}"
|
f"Was unable to construct lookup dictionary for job {job_id}", exc_info=True
|
||||||
)
|
)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ def cleanup_unfinished_jobs():
|
|||||||
acceptable_finish_time = job.processing_started + timedelta(minutes=5)
|
acceptable_finish_time = job.processing_started + timedelta(minutes=5)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
f"Job ID {job.id} processing_started is {job.processing_started}."
|
f"Job ID {job.id} processing_started is {job.processing_started}.",
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
raise
|
raise
|
||||||
if now > acceptable_finish_time:
|
if now > acceptable_finish_time:
|
||||||
|
|||||||
@@ -161,7 +161,8 @@ def __total_sending_limits_for_job_exceeded(service, job, job_id):
|
|||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
"Job {} size {} error. Total sending limits {} exceeded".format(
|
"Job {} size {} error. Total sending limits {} exceeded".format(
|
||||||
job_id, job.notification_count, service.message_limit
|
job_id, job.notification_count, service.message_limit
|
||||||
)
|
),
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -361,7 +362,8 @@ def save_api_email_or_sms(self, encrypted_notification):
|
|||||||
self.retry(queue=QueueNames.RETRY)
|
self.retry(queue=QueueNames.RETRY)
|
||||||
except self.MaxRetriesExceededError:
|
except self.MaxRetriesExceededError:
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
f"Max retry failed Failed to persist notification {notification['id']}"
|
f"Max retry failed Failed to persist notification {notification['id']}",
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -381,7 +383,7 @@ def handle_exception(task, notification, notification_id, exc):
|
|||||||
try:
|
try:
|
||||||
task.retry(queue=QueueNames.RETRY, exc=exc)
|
task.retry(queue=QueueNames.RETRY, exc=exc)
|
||||||
except task.MaxRetriesExceededError:
|
except task.MaxRetriesExceededError:
|
||||||
current_app.logger.error("Max retry failed" + retry_msg)
|
current_app.logger.error("Max retry failed" + retry_msg, exc_info=True)
|
||||||
|
|
||||||
|
|
||||||
@notify_celery.task(
|
@notify_celery.task(
|
||||||
@@ -432,7 +434,8 @@ def send_inbound_sms_to_service(self, inbound_sms_id, service_id):
|
|||||||
except self.MaxRetriesExceededError:
|
except self.MaxRetriesExceededError:
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
"Retry: send_inbound_sms_to_service has retried the max number of"
|
"Retry: send_inbound_sms_to_service has retried the max number of"
|
||||||
+ f"times for service: {service_id} and inbound_sms {inbound_sms_id}"
|
+ f"times for service: {service_id} and inbound_sms {inbound_sms_id}",
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
current_app.logger.warning(
|
current_app.logger.warning(
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ class PerformancePlatformClient:
|
|||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
"Performance platform update request failed for payload with response details: {} '{}'".format(
|
"Performance platform update request failed for payload with response details: {} '{}'".format(
|
||||||
json.dumps(payload), resp.status_code
|
json.dumps(payload), resp.status_code
|
||||||
)
|
),
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
|
|
||||||
|
|||||||
@@ -81,10 +81,14 @@ class AwsSnsClient(SmsClient):
|
|||||||
PhoneNumber=to, Message=content, MessageAttributes=attributes
|
PhoneNumber=to, Message=content, MessageAttributes=attributes
|
||||||
)
|
)
|
||||||
except botocore.exceptions.ClientError as e:
|
except botocore.exceptions.ClientError as e:
|
||||||
self.current_app.logger.error(e)
|
self.current_app.logger.error(
|
||||||
|
"An error occurred sending sms", exc_info=True
|
||||||
|
)
|
||||||
raise str(e)
|
raise str(e)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.current_app.logger(e)
|
self.current_app.logger.error(
|
||||||
|
"An error occurred sending sms", exc_info=True
|
||||||
|
)
|
||||||
raise str(e)
|
raise str(e)
|
||||||
finally:
|
finally:
|
||||||
elapsed_time = monotonic() - start_time
|
elapsed_time = monotonic() - start_time
|
||||||
|
|||||||
112
app/commands.py
112
app/commands.py
@@ -127,7 +127,7 @@ def purge_functional_test_data(user_email_prefix):
|
|||||||
users, services, etc. Give an email prefix. Probably "notify-tests-preview".
|
users, services, etc. Give an email prefix. Probably "notify-tests-preview".
|
||||||
"""
|
"""
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
||||||
current_app.logger.error("Can only be run in development")
|
current_app.logger.error("Can only be run in development", exc_info=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
users = User.query.filter(User.email_address.like(f"{user_email_prefix}%")).all()
|
users = User.query.filter(User.email_address.like(f"{user_email_prefix}%")).all()
|
||||||
@@ -137,13 +137,15 @@ def purge_functional_test_data(user_email_prefix):
|
|||||||
try:
|
try:
|
||||||
uuid.UUID(usr.email_address.split("@")[0].split("+")[1])
|
uuid.UUID(usr.email_address.split("@")[0].split("+")[1])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print(
|
current_app.logger.warning(
|
||||||
f"Skipping {usr.email_address} as the user email doesn't contain a UUID."
|
f"Skipping {usr.email_address} as the user email doesn't contain a UUID."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
services = dao_fetch_all_services_by_user(usr.id)
|
services = dao_fetch_all_services_by_user(usr.id)
|
||||||
if services:
|
if services:
|
||||||
print(f"Deleting user {usr.id} which is part of services")
|
current_app.logger.info(
|
||||||
|
f"Deleting user {usr.id} which is part of services"
|
||||||
|
)
|
||||||
for service in services:
|
for service in services:
|
||||||
delete_service_and_all_associated_db_objects(service)
|
delete_service_and_all_associated_db_objects(service)
|
||||||
else:
|
else:
|
||||||
@@ -154,11 +156,13 @@ def purge_functional_test_data(user_email_prefix):
|
|||||||
# user is not part of any services but may still have been the one to create the service
|
# user is not part of any services but may still have been the one to create the service
|
||||||
# sometimes things get in this state if the tests fail half way through
|
# sometimes things get in this state if the tests fail half way through
|
||||||
# Remove the service they created (but are not a part of) so we can then remove the user
|
# Remove the service they created (but are not a part of) so we can then remove the user
|
||||||
print(f"Deleting services created by {usr.id}")
|
current_app.logger.info(f"Deleting services created by {usr.id}")
|
||||||
for service in services_created_by_this_user:
|
for service in services_created_by_this_user:
|
||||||
delete_service_and_all_associated_db_objects(service)
|
delete_service_and_all_associated_db_objects(service)
|
||||||
|
|
||||||
print(f"Deleting user {usr.id} which is not part of any services")
|
current_app.logger.info(
|
||||||
|
f"Deleting user {usr.id} which is not part of any services"
|
||||||
|
)
|
||||||
delete_user_verify_codes(usr)
|
delete_user_verify_codes(usr)
|
||||||
delete_model_user(usr)
|
delete_model_user(usr)
|
||||||
|
|
||||||
@@ -173,7 +177,7 @@ def purge_functional_test_data(user_email_prefix):
|
|||||||
def insert_inbound_numbers_from_file(file_name):
|
def insert_inbound_numbers_from_file(file_name):
|
||||||
# TODO maintainability what is the purpose of this command? Who would use it and why?
|
# TODO maintainability what is the purpose of this command? Who would use it and why?
|
||||||
|
|
||||||
print(f"Inserting inbound numbers from {file_name}")
|
current_app.logger.info(f"Inserting inbound numbers from {file_name}")
|
||||||
with open(file_name) as file:
|
with open(file_name) as file:
|
||||||
sql = text(
|
sql = text(
|
||||||
"insert into inbound_numbers values(:uuid, :line, 'sns', null, True, now(), null);"
|
"insert into inbound_numbers values(:uuid, :line, 'sns', null, True, now(), null);"
|
||||||
@@ -182,7 +186,7 @@ def insert_inbound_numbers_from_file(file_name):
|
|||||||
for line in file:
|
for line in file:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line:
|
if line:
|
||||||
print(line)
|
current_app.logger.info(line)
|
||||||
db.session.execute(sql, {"uuid": str(uuid.uuid4()), "line": line})
|
db.session.execute(sql, {"uuid": str(uuid.uuid4()), "line": line})
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
@@ -293,13 +297,14 @@ def bulk_invite_user_to_service(file_name, service_id, user_id, auth_type, permi
|
|||||||
response = create_invited_user(service_id)
|
response = create_invited_user(service_id)
|
||||||
current_app.logger.info(f"RESPONSE {response[1]}")
|
current_app.logger.info(f"RESPONSE {response[1]}")
|
||||||
if response[1] != 201:
|
if response[1] != 201:
|
||||||
print(
|
current_app.logger.warning(
|
||||||
f"*** ERROR occurred for email address: {email_address.strip()}"
|
f"*** ERROR occurred for email address: {email_address.strip()}"
|
||||||
)
|
)
|
||||||
print(response[0].get_data(as_text=True))
|
current_app.logger, info(response[0].get_data(as_text=True))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
current_app.logger.error(
|
||||||
f"*** ERROR occurred for email address: {email_address.strip()}. \n{e}"
|
f"*** ERROR occurred for email address: {email_address.strip()}.",
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
file.close()
|
file.close()
|
||||||
@@ -380,7 +385,7 @@ def populate_organizations_from_file(file_name):
|
|||||||
|
|
||||||
for line in itertools.islice(f, 1, None):
|
for line in itertools.islice(f, 1, None):
|
||||||
columns = line.split("|")
|
columns = line.split("|")
|
||||||
print(columns)
|
current_app.logger.info(columns)
|
||||||
email_branding = None
|
email_branding = None
|
||||||
email_branding_column = columns[5].strip()
|
email_branding_column = columns[5].strip()
|
||||||
if len(email_branding_column) > 0:
|
if len(email_branding_column) > 0:
|
||||||
@@ -399,7 +404,9 @@ def populate_organizations_from_file(file_name):
|
|||||||
db.session.add(org)
|
db.session.add(org)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
print("duplicate org", org.name)
|
current_app.logger.error(
|
||||||
|
f"Error duplicate org {org.name}", exc_info=True
|
||||||
|
)
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
domains = columns[4].split(",")
|
domains = columns[4].split(",")
|
||||||
for d in domains:
|
for d in domains:
|
||||||
@@ -409,7 +416,10 @@ def populate_organizations_from_file(file_name):
|
|||||||
db.session.add(domain)
|
db.session.add(domain)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
print("duplicate domain", d.strip())
|
current_app.logger.error(
|
||||||
|
f"Integrity error duplicate domain {d.strip()}",
|
||||||
|
exc_info=True,
|
||||||
|
)
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
|
|
||||||
|
|
||||||
@@ -463,7 +473,7 @@ def associate_services_to_organizations():
|
|||||||
service=service, organization_id=organization.id
|
service=service, organization_id=organization.id
|
||||||
)
|
)
|
||||||
|
|
||||||
print("finished associating services to organizations")
|
current_app.logger.info("finished associating services to organizations")
|
||||||
|
|
||||||
|
|
||||||
@notify_command(name="populate-service-volume-intentions")
|
@notify_command(name="populate-service-volume-intentions")
|
||||||
@@ -483,12 +493,12 @@ def populate_service_volume_intentions(file_name):
|
|||||||
with open(file_name, "r") as f:
|
with open(file_name, "r") as f:
|
||||||
for line in itertools.islice(f, 1, None):
|
for line in itertools.islice(f, 1, None):
|
||||||
columns = line.split(",")
|
columns = line.split(",")
|
||||||
print(columns)
|
current_app.logger.info(columns)
|
||||||
service = dao_fetch_service_by_id(columns[0])
|
service = dao_fetch_service_by_id(columns[0])
|
||||||
service.volume_sms = columns[1]
|
service.volume_sms = columns[1]
|
||||||
service.volume_email = columns[2]
|
service.volume_email = columns[2]
|
||||||
dao_update_service(service)
|
dao_update_service(service)
|
||||||
print("populate-service-volume-intentions complete")
|
current_app.logger.info("populate-service-volume-intentions complete")
|
||||||
|
|
||||||
|
|
||||||
@notify_command(name="populate-go-live")
|
@notify_command(name="populate-go-live")
|
||||||
@@ -500,32 +510,36 @@ def populate_go_live(file_name):
|
|||||||
# 6- Contact detail, 7-MOU, 8- LIVE date, 9- SMS, 10 - Email, 11 - Letters, 12 -CRM, 13 - Blue badge
|
# 6- Contact detail, 7-MOU, 8- LIVE date, 9- SMS, 10 - Email, 11 - Letters, 12 -CRM, 13 - Blue badge
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
print("Populate go live user and date")
|
current_app.logger.info("Populate go live user and date")
|
||||||
with open(file_name, "r") as f:
|
with open(file_name, "r") as f:
|
||||||
rows = csv.reader(
|
rows = csv.reader(
|
||||||
f,
|
f,
|
||||||
quoting=csv.QUOTE_MINIMAL,
|
quoting=csv.QUOTE_MINIMAL,
|
||||||
skipinitialspace=True,
|
skipinitialspace=True,
|
||||||
)
|
)
|
||||||
print(next(rows)) # ignore header row
|
current_app.logger.info(next(rows)) # ignore header row
|
||||||
for index, row in enumerate(rows):
|
for index, row in enumerate(rows):
|
||||||
print(index, row)
|
current_app.logger.info(index, row)
|
||||||
service_id = row[2]
|
service_id = row[2]
|
||||||
go_live_email = row[6]
|
go_live_email = row[6]
|
||||||
go_live_date = datetime.strptime(row[8], "%d/%m/%Y") + timedelta(hours=12)
|
go_live_date = datetime.strptime(row[8], "%d/%m/%Y") + timedelta(hours=12)
|
||||||
print(service_id, go_live_email, go_live_date)
|
current_app.logger.info(service_id, go_live_email, go_live_date)
|
||||||
try:
|
try:
|
||||||
if go_live_email:
|
if go_live_email:
|
||||||
go_live_user = get_user_by_email(go_live_email)
|
go_live_user = get_user_by_email(go_live_email)
|
||||||
else:
|
else:
|
||||||
go_live_user = None
|
go_live_user = None
|
||||||
except NoResultFound:
|
except NoResultFound:
|
||||||
print("No user found for email address: ", go_live_email)
|
current_app.logger.error(
|
||||||
|
f"No user found for email address", exc_info=True
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
service = dao_fetch_service_by_id(service_id)
|
service = dao_fetch_service_by_id(service_id)
|
||||||
except NoResultFound:
|
except NoResultFound:
|
||||||
print("No service found for: ", service_id)
|
current_app.logger.error(
|
||||||
|
f"No service found for service: {service_id}", exc_info=True
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
service.go_live_user = go_live_user
|
service.go_live_user = go_live_user
|
||||||
service.go_live_at = go_live_date
|
service.go_live_at = go_live_date
|
||||||
@@ -553,7 +567,7 @@ def fix_billable_units():
|
|||||||
prefix=notification.service.name,
|
prefix=notification.service.name,
|
||||||
show_prefix=notification.service.prefix_sms,
|
show_prefix=notification.service.prefix_sms,
|
||||||
)
|
)
|
||||||
print(
|
current_app.logger.info(
|
||||||
f"Updating notification: {notification.id} with {template.fragment_count} billable_units"
|
f"Updating notification: {notification.id} with {template.fragment_count} billable_units"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -561,13 +575,13 @@ def fix_billable_units():
|
|||||||
{"billable_units": template.fragment_count}
|
{"billable_units": template.fragment_count}
|
||||||
)
|
)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
print("End fix_billable_units")
|
current_app.logger.info("End fix_billable_units")
|
||||||
|
|
||||||
|
|
||||||
@notify_command(name="delete-unfinished-jobs")
|
@notify_command(name="delete-unfinished-jobs")
|
||||||
def delete_unfinished_jobs():
|
def delete_unfinished_jobs():
|
||||||
cleanup_unfinished_jobs()
|
cleanup_unfinished_jobs()
|
||||||
print("End cleanup_unfinished_jobs")
|
current_app.logger.info("End cleanup_unfinished_jobs")
|
||||||
|
|
||||||
|
|
||||||
@notify_command(name="process-row-from-job")
|
@notify_command(name="process-row-from-job")
|
||||||
@@ -655,7 +669,9 @@ def populate_annual_billing_with_the_previous_years_allowance(year):
|
|||||||
text(latest_annual_billing), {"service_id": row.id}
|
text(latest_annual_billing), {"service_id": row.id}
|
||||||
)
|
)
|
||||||
free_allowance = [x[0] for x in free_allowance_rows]
|
free_allowance = [x[0] for x in free_allowance_rows]
|
||||||
print(f"create free limit of {free_allowance[0]} for service: {row.id}")
|
current_app.logger.info(
|
||||||
|
f"create free limit of {free_allowance[0]} for service: {row.id}"
|
||||||
|
)
|
||||||
dao_create_or_update_annual_billing_for_year(
|
dao_create_or_update_annual_billing_for_year(
|
||||||
service_id=row.id,
|
service_id=row.id,
|
||||||
free_sms_fragment_limit=free_allowance[0],
|
free_sms_fragment_limit=free_allowance[0],
|
||||||
@@ -671,7 +687,7 @@ def dump_user_info(user_email_address):
|
|||||||
with open("user_download.json", "wb") as f:
|
with open("user_download.json", "wb") as f:
|
||||||
f.write(json.dumps(content).encode("utf8"))
|
f.write(json.dumps(content).encode("utf8"))
|
||||||
f.close()
|
f.close()
|
||||||
print("Successfully downloaded user info to user_download.json")
|
current_app.logger.info("Successfully downloaded user info to user_download.json")
|
||||||
|
|
||||||
|
|
||||||
@notify_command(name="populate-annual-billing-with-defaults")
|
@notify_command(name="populate-annual-billing-with-defaults")
|
||||||
@@ -731,14 +747,14 @@ def populate_annual_billing_with_defaults(year, missing_services_only):
|
|||||||
# set the free allowance for this year to 0 as well.
|
# set the free allowance for this year to 0 as well.
|
||||||
# Else use the default free allowance for the service.
|
# Else use the default free allowance for the service.
|
||||||
if service.id in [x.service_id for x in services_with_zero_free_allowance]:
|
if service.id in [x.service_id for x in services_with_zero_free_allowance]:
|
||||||
print(f"update service {service.id} to 0")
|
current_app.logger.info(f"update service {service.id} to 0")
|
||||||
dao_create_or_update_annual_billing_for_year(
|
dao_create_or_update_annual_billing_for_year(
|
||||||
service_id=service.id,
|
service_id=service.id,
|
||||||
free_sms_fragment_limit=0,
|
free_sms_fragment_limit=0,
|
||||||
financial_year_start=year,
|
financial_year_start=year,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(f"update service {service.id} with default")
|
current_app.logger.info(f"update service {service.id} with default")
|
||||||
set_default_free_allowance_for_service(service, year)
|
set_default_free_allowance_for_service(service, year)
|
||||||
|
|
||||||
|
|
||||||
@@ -770,7 +786,9 @@ def validate_mobile(ctx, param, value): # noqa
|
|||||||
@click.option("-d", "--admin", default=False, type=bool)
|
@click.option("-d", "--admin", default=False, type=bool)
|
||||||
def create_test_user(name, email, mobile_number, password, auth_type, state, admin):
|
def create_test_user(name, email, mobile_number, password, auth_type, state, admin):
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test", "staging"]:
|
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test", "staging"]:
|
||||||
current_app.logger.error("Can only be run in development, test, staging")
|
current_app.logger.error(
|
||||||
|
"Can only be run in development, test, staging", exc_info=True
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
@@ -787,16 +805,16 @@ def create_test_user(name, email, mobile_number, password, auth_type, state, adm
|
|||||||
db.session.add(user)
|
db.session.add(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
print("duplicate user", user.name)
|
current_app.logger.error("Integrity error duplicate user", exc_info=True)
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
|
|
||||||
|
|
||||||
@notify_command(name="create-admin-jwt")
|
@notify_command(name="create-admin-jwt")
|
||||||
def create_admin_jwt():
|
def create_admin_jwt():
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") != "development":
|
if getenv("NOTIFY_ENVIRONMENT", "") != "development":
|
||||||
current_app.logger.error("Can only be run in development")
|
current_app.logger.error("Can only be run in development", exc_info=True)
|
||||||
return
|
return
|
||||||
print(
|
current_app.logger.info(
|
||||||
create_jwt_token(
|
create_jwt_token(
|
||||||
current_app.config["SECRET_KEY"], current_app.config["ADMIN_CLIENT_ID"]
|
current_app.config["SECRET_KEY"], current_app.config["ADMIN_CLIENT_ID"]
|
||||||
)
|
)
|
||||||
@@ -807,11 +825,11 @@ def create_admin_jwt():
|
|||||||
@click.option("-t", "--token", required=True, prompt=False)
|
@click.option("-t", "--token", required=True, prompt=False)
|
||||||
def create_user_jwt(token):
|
def create_user_jwt(token):
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") != "development":
|
if getenv("NOTIFY_ENVIRONMENT", "") != "development":
|
||||||
current_app.logger.error("Can only be run in development")
|
current_app.logger.error("Can only be run in development", exc_info=True)
|
||||||
return
|
return
|
||||||
service_id = token[-73:-37]
|
service_id = token[-73:-37]
|
||||||
api_key = token[-36:]
|
api_key = token[-36:]
|
||||||
print(create_jwt_token(api_key, service_id))
|
current_app.logger.info(create_jwt_token(api_key, service_id))
|
||||||
|
|
||||||
|
|
||||||
def _update_template(id, name, template_type, content, subject):
|
def _update_template(id, name, template_type, content, subject):
|
||||||
@@ -883,7 +901,7 @@ def create_new_service(name, message_limit, restricted, email_from, created_by_i
|
|||||||
db.session.add(service)
|
db.session.add(service)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
print("duplicate service", service.name)
|
current_app.logger.info("duplicate service", service.name)
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
|
|
||||||
|
|
||||||
@@ -923,7 +941,7 @@ where possible to enable better maintainability.
|
|||||||
@click.option("-g", "--generate", required=True, prompt=True, default=1)
|
@click.option("-g", "--generate", required=True, prompt=True, default=1)
|
||||||
def add_test_organizations_to_db(generate):
|
def add_test_organizations_to_db(generate):
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
||||||
current_app.logger.error("Can only be run in development")
|
current_app.logger.error("Can only be run in development", exc_info=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
def generate_gov_agency():
|
def generate_gov_agency():
|
||||||
@@ -977,7 +995,7 @@ def add_test_organizations_to_db(generate):
|
|||||||
name=generate_gov_agency(),
|
name=generate_gov_agency(),
|
||||||
organization_type=secrets.choice(["federal", "state", "other"]),
|
organization_type=secrets.choice(["federal", "state", "other"]),
|
||||||
)
|
)
|
||||||
print(f"{num} {org.name} created")
|
current_app.logger.info(f"{num} {org.name} created")
|
||||||
|
|
||||||
|
|
||||||
# generate n number of test services into the dev DB
|
# generate n number of test services into the dev DB
|
||||||
@@ -985,13 +1003,13 @@ def add_test_organizations_to_db(generate):
|
|||||||
@click.option("-g", "--generate", required=True, prompt=True, default=1)
|
@click.option("-g", "--generate", required=True, prompt=True, default=1)
|
||||||
def add_test_services_to_db(generate):
|
def add_test_services_to_db(generate):
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
||||||
current_app.logger.error("Can only be run in development")
|
current_app.logger.error("Can only be run in development", exc_info=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
for num in range(1, int(generate) + 1):
|
for num in range(1, int(generate) + 1):
|
||||||
service_name = f"{fake.company()} sample service"
|
service_name = f"{fake.company()} sample service"
|
||||||
service = create_service(service_name=service_name)
|
service = create_service(service_name=service_name)
|
||||||
print(f"{num} {service.name} created")
|
current_app.logger.info(f"{num} {service.name} created")
|
||||||
|
|
||||||
|
|
||||||
# generate n number of test jobs into the dev DB
|
# generate n number of test jobs into the dev DB
|
||||||
@@ -999,14 +1017,14 @@ def add_test_services_to_db(generate):
|
|||||||
@click.option("-g", "--generate", required=True, prompt=True, default=1)
|
@click.option("-g", "--generate", required=True, prompt=True, default=1)
|
||||||
def add_test_jobs_to_db(generate):
|
def add_test_jobs_to_db(generate):
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
||||||
current_app.logger.error("Can only be run in development")
|
current_app.logger.error("Can only be run in development", exc_info=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
for num in range(1, int(generate) + 1):
|
for num in range(1, int(generate) + 1):
|
||||||
service = create_service(check_if_service_exists=True)
|
service = create_service(check_if_service_exists=True)
|
||||||
template = create_template(service=service)
|
template = create_template(service=service)
|
||||||
job = create_job(template)
|
job = create_job(template)
|
||||||
print(f"{num} {job.id} created")
|
current_app.logger.info(f"{num} {job.id} created")
|
||||||
|
|
||||||
|
|
||||||
# generate n number of notifications into the dev DB
|
# generate n number of notifications into the dev DB
|
||||||
@@ -1014,7 +1032,7 @@ def add_test_jobs_to_db(generate):
|
|||||||
@click.option("-g", "--generate", required=True, prompt=True, default=1)
|
@click.option("-g", "--generate", required=True, prompt=True, default=1)
|
||||||
def add_test_notifications_to_db(generate):
|
def add_test_notifications_to_db(generate):
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
||||||
current_app.logger.error("Can only be run in development")
|
current_app.logger.error("Can only be run in development", exc_info=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
for num in range(1, int(generate) + 1):
|
for num in range(1, int(generate) + 1):
|
||||||
@@ -1025,7 +1043,7 @@ def add_test_notifications_to_db(generate):
|
|||||||
template=template,
|
template=template,
|
||||||
job=job,
|
job=job,
|
||||||
)
|
)
|
||||||
print(f"{num} {notification.id} created")
|
current_app.logger.info(f"{num} {notification.id} created")
|
||||||
|
|
||||||
|
|
||||||
# generate n number of test users into the dev DB
|
# generate n number of test users into the dev DB
|
||||||
@@ -1035,7 +1053,7 @@ def add_test_notifications_to_db(generate):
|
|||||||
@click.option("-d", "--admin", default=False, type=bool)
|
@click.option("-d", "--admin", default=False, type=bool)
|
||||||
def add_test_users_to_db(generate, state, admin):
|
def add_test_users_to_db(generate, state, admin):
|
||||||
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
if getenv("NOTIFY_ENVIRONMENT", "") not in ["development", "test"]:
|
||||||
current_app.logger.error("Can only be run in development")
|
current_app.logger.error("Can only be run in development", exc_info=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
for num in range(1, int(generate) + 1):
|
for num in range(1, int(generate) + 1):
|
||||||
@@ -1052,4 +1070,4 @@ def add_test_users_to_db(generate, state, admin):
|
|||||||
state=state,
|
state=state,
|
||||||
platform_admin=admin,
|
platform_admin=admin,
|
||||||
)
|
)
|
||||||
print(f"{num} {user.email_address} created")
|
currente_app.logger.info(f"{num} {user.email_address} created")
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ def cronitor(task_name):
|
|||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
"Cronitor enabled but task_name {} not found in environment".format(
|
"Cronitor enabled but task_name {} not found in environment".format(
|
||||||
task_name
|
task_name
|
||||||
)
|
),
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,8 @@ def update_notification_status_by_reference(reference, status):
|
|||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
"notification not found for reference {} (update to {})".format(
|
"notification not found for reference {} (update to {})".format(
|
||||||
reference, status
|
reference, status
|
||||||
)
|
),
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ def get_login_gov_user(login_uuid, email_address):
|
|||||||
# address in login.gov.
|
# address in login.gov.
|
||||||
# But if we cannot change the email address, at least we don't
|
# But if we cannot change the email address, at least we don't
|
||||||
# want to fail here, otherwise the user will be locked out.
|
# want to fail here, otherwise the user will be locked out.
|
||||||
current_app.logger.error(ie)
|
current_app.logger.error("Error getting login.gov user", exc_info=True)
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ def send_sms_to_provider(notification):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
n = notification
|
n = notification
|
||||||
msg = f"FAILED send to sms, job_id: {n.job_id} row_number {n.job_row_number} message_id {message_id}"
|
msg = f"FAILED send to sms, job_id: {n.job_id} row_number {n.job_row_number} message_id {message_id}"
|
||||||
current_app.logger.error(hilite(f"{msg} {e}"))
|
current_app.logger.error(hilite(msg), exc_info=True)
|
||||||
|
|
||||||
notification.billable_units = template.fragment_count
|
notification.billable_units = template.fragment_count
|
||||||
dao_update_notification(notification)
|
dao_update_notification(notification)
|
||||||
|
|||||||
@@ -1568,7 +1568,8 @@ class Notification(db.Model):
|
|||||||
return encryption.decrypt(self._personalisation)
|
return encryption.decrypt(self._personalisation)
|
||||||
except EncryptionError:
|
except EncryptionError:
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
"Error decrypting notification.personalisation, returning empty dict"
|
"Error decrypting notification.personalisation, returning empty dict",
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|||||||
@@ -151,8 +151,6 @@ def persist_notification(
|
|||||||
def send_notification_to_queue_detached(
|
def send_notification_to_queue_detached(
|
||||||
key_type, notification_type, notification_id, queue=None
|
key_type, notification_type, notification_id, queue=None
|
||||||
):
|
):
|
||||||
if key_type == KeyType.TEST:
|
|
||||||
print("send_notification_to_queue_detached key is test key")
|
|
||||||
|
|
||||||
if notification_type == NotificationType.SMS:
|
if notification_type == NotificationType.SMS:
|
||||||
if not queue:
|
if not queue:
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ def fetch_potential_service(inbound_number, provider_name):
|
|||||||
|
|
||||||
if not has_inbound_sms_permissions(service.permissions):
|
if not has_inbound_sms_permissions(service.permissions):
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
'Service "{}" does not allow inbound SMS'.format(service.id)
|
'Service "{}" does not allow inbound SMS'.format(service.id), exc_info=True
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ def sns_notification_handler(data, headers):
|
|||||||
validate_sns_cert(message)
|
validate_sns_cert(message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.error(
|
current_app.logger.error(
|
||||||
f"SES-SNS callback failed: validation failed with error: Signature validation failed with error {e}"
|
f"SES-SNS callback failed: validation failed with error: Signature validation failed",
|
||||||
|
exc_info=True,
|
||||||
)
|
)
|
||||||
raise InvalidRequest("SES-SNS callback failed: validation failed", 400)
|
raise InvalidRequest("SES-SNS callback failed: validation failed", 400)
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ def handle_integrity_error(exc):
|
|||||||
"""
|
"""
|
||||||
Handle integrity errors caused by the unique constraint on ix_organization_name
|
Handle integrity errors caused by the unique constraint on ix_organization_name
|
||||||
"""
|
"""
|
||||||
print(exc)
|
current_app.logger.exception("Handling integrity error", exc_info=True)
|
||||||
current_app.logger.exception(exc)
|
|
||||||
if "ix_organization_name" in str(exc):
|
if "ix_organization_name" in str(exc):
|
||||||
return jsonify(result="error", message="Organization name already exists"), 400
|
return jsonify(result="error", message="Organization name already exists"), 400
|
||||||
if 'duplicate key value violates unique constraint "domain_pkey"' in str(exc):
|
if 'duplicate key value violates unique constraint "domain_pkey"' in str(exc):
|
||||||
|
|||||||
@@ -373,9 +373,6 @@ def get_users_for_service(service_id):
|
|||||||
def add_user_to_service(service_id, user_id):
|
def add_user_to_service(service_id, user_id):
|
||||||
service = dao_fetch_service_by_id(service_id)
|
service = dao_fetch_service_by_id(service_id)
|
||||||
user = get_user_by_id(user_id=user_id)
|
user = get_user_by_id(user_id=user_id)
|
||||||
# TODO REMOVE DEBUG
|
|
||||||
print(hilite(f"GOING TO ADD {user.name} to service {service.name}"))
|
|
||||||
# END DEBUG
|
|
||||||
if user in service.users:
|
if user in service.users:
|
||||||
error = "User id: {} already part of service id: {}".format(user_id, service_id)
|
error = "User id: {} already part of service id: {}".format(user_id, service_id)
|
||||||
raise InvalidRequest(error, status_code=400)
|
raise InvalidRequest(error, status_code=400)
|
||||||
@@ -390,9 +387,6 @@ def add_user_to_service(service_id, user_id):
|
|||||||
folder_permissions = data.get("folder_permissions", [])
|
folder_permissions = data.get("folder_permissions", [])
|
||||||
|
|
||||||
dao_add_user_to_service(service, user, permissions, folder_permissions)
|
dao_add_user_to_service(service, user, permissions, folder_permissions)
|
||||||
# TODO REMOVE DEBUG
|
|
||||||
print(hilite(f"ADDED {user.name} to service {service.name}"))
|
|
||||||
# END DEBUG
|
|
||||||
|
|
||||||
data = service_schema.dump(service)
|
data = service_schema.dump(service)
|
||||||
return jsonify(data=data), 201
|
return jsonify(data=data), 201
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ register_errors(service_invite)
|
|||||||
|
|
||||||
|
|
||||||
def _create_service_invite(invited_user, invite_link_host):
|
def _create_service_invite(invited_user, invite_link_host):
|
||||||
# TODO REMOVE DEBUG
|
|
||||||
print(hilite("ENTER _create_service_invite"))
|
|
||||||
# END DEBUG
|
|
||||||
|
|
||||||
template_id = current_app.config["INVITATION_EMAIL_TEMPLATE_ID"]
|
template_id = current_app.config["INVITATION_EMAIL_TEMPLATE_ID"]
|
||||||
|
|
||||||
|
|||||||
@@ -161,5 +161,7 @@ class JSONFormatter(BaseJSONFormatter):
|
|||||||
try:
|
try:
|
||||||
log_record["message"] = log_record["message"].format(**log_record)
|
log_record["message"] = log_record["message"].format(**log_record)
|
||||||
except (KeyError, IndexError) as e:
|
except (KeyError, IndexError) as e:
|
||||||
logger.exception("failed to format log message: {} not found".format(e))
|
logger.exception(
|
||||||
|
"failed to format log message: {} not found".format(e), exc_info=True
|
||||||
|
)
|
||||||
return log_record
|
return log_record
|
||||||
|
|||||||
@@ -81,11 +81,11 @@ class ResponseHeaderMiddleware(object):
|
|||||||
return self._app(environ, rewrite_response_headers)
|
return self._app(environ, rewrite_response_headers)
|
||||||
except BaseException as be: # noqa
|
except BaseException as be: # noqa
|
||||||
if "AuthError" in str(be): # notify-api-1135
|
if "AuthError" in str(be): # notify-api-1135
|
||||||
current_app.logger.error(be)
|
current_app.logger.error("AuthError", exc_info=True)
|
||||||
elif "AttributeError" in str(be): # notify-api-1394
|
elif "AttributeError" in str(be): # notify-api-1394
|
||||||
current_app.logger.error(be)
|
current_app.logger.error("AttributeError", exc_info=True)
|
||||||
elif "MethodNotAllowed" in str(be): # notify-admin-1392
|
elif "MethodNotAllowed" in str(be): # notify-admin-1392
|
||||||
current_app.logger.error(be)
|
current_app.logger.error("MethodNotAllowed", exc_info=True)
|
||||||
else:
|
else:
|
||||||
raise be
|
raise be
|
||||||
|
|
||||||
|
|||||||
@@ -57,9 +57,7 @@ def s3upload(
|
|||||||
try:
|
try:
|
||||||
key.put(**put_args)
|
key.put(**put_args)
|
||||||
except botocore.exceptions.ClientError as e:
|
except botocore.exceptions.ClientError as e:
|
||||||
current_app.logger.error(
|
current_app.logger.error("Unable to upload file to S3 bucket", exc_info=True)
|
||||||
"Unable to upload file to S3 bucket {}".format(bucket_name)
|
|
||||||
)
|
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user