diff --git a/app/main/views/new_password.py b/app/main/views/new_password.py index ed45c3c1d..7b3c701f9 100644 --- a/app/main/views/new_password.py +++ b/app/main/views/new_password.py @@ -1,5 +1,4 @@ import json -from datetime import datetime from flask import ( current_app, @@ -29,8 +28,7 @@ def new_password(token): email_address = json.loads(token_data)['email'] user = User.from_email_address(email_address) - if user.password_changed_at and datetime.strptime(user.password_changed_at, '%Y-%m-%d %H:%M:%S.%f') > \ - datetime.strptime(json.loads(token_data)['created_at'], '%Y-%m-%d %H:%M:%S.%f'): + if user.password_changed_more_recently_than(json.loads(token_data)['created_at']): flash('The link in the email has already been used') return redirect(url_for('main.index')) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 79447ebe5..707d92a3b 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -14,6 +14,7 @@ from flask import ( ) from flask_login import current_user from notifications_python_client.errors import HTTPError +from notifications_utils.timezones import utc_string_to_aware_gmt_datetime from app import ( billing_api_client, @@ -475,8 +476,10 @@ def get_service_verify_reply_to_address_partials(service_id, notification_id): email_address=notification["to"], is_default=is_default ) - created_at_no_tz = notification["created_at"][:-6] - seconds_since_sending = (datetime.utcnow() - datetime.strptime(created_at_no_tz, '%Y-%m-%dT%H:%M:%S.%f')).seconds + seconds_since_sending = ( + utc_string_to_aware_gmt_datetime(datetime.utcnow().isoformat()) - + utc_string_to_aware_gmt_datetime(notification['created_at']) + ).seconds if notification["status"] in FAILURE_STATUSES or ( notification["status"] in SENDING_STATUSES and seconds_since_sending > current_app.config['REPLY_TO_EMAIL_ADDRESS_VALIDATION_TIMEOUT'] diff --git a/app/models/job.py b/app/models/job.py index 76ca7d2f1..ecb72dd95 100644 --- a/app/models/job.py +++ b/app/models/job.py @@ -5,6 +5,10 @@ from notifications_utils.letter_timings import ( get_letter_timings, letter_can_be_cancelled, ) +from notifications_utils.timezones import ( + local_timezone, + utc_string_to_aware_gmt_datetime, +) from werkzeug.utils import cached_property from app.models import JSONModel, ModelList @@ -23,6 +27,7 @@ class Job(JSONModel): 'template_version', 'original_file_name', 'created_at', + 'processing_started', 'notification_count', 'job_status', 'created_by', @@ -52,7 +57,7 @@ class Job(JSONModel): def processing_started(self): if not self._dict.get('processing_started'): return None - return datetime.strptime(self._dict['processing_started'][:-6], '%Y-%m-%dT%H:%M:%S') + return utc_string_to_aware_gmt_datetime(self._dict['processing_started']) def _aggregate_statistics(self, *statuses): return sum( @@ -109,7 +114,7 @@ class Job(JSONModel): # notifications yet return True return ( - datetime.utcnow() - self.processing_started + datetime.utcnow().astimezone(local_timezone) - self.processing_started ).days < 1 @property @@ -142,7 +147,8 @@ class Job(JSONModel): return False if not letter_can_be_cancelled( - 'created', datetime.strptime(self.created_at[:-6], '%Y-%m-%dT%H:%M:%S.%f') + 'created', + utc_string_to_aware_gmt_datetime(self.created_at).replace(tzinfo=None) ): return False diff --git a/app/models/user.py b/app/models/user.py index 61674ce30..ac465000a 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -1,6 +1,7 @@ from flask import abort, current_app, request, session from flask_login import AnonymousUserMixin, UserMixin, login_user from notifications_python_client.errors import HTTPError +from notifications_utils.timezones import utc_string_to_aware_gmt_datetime from werkzeug.utils import cached_property from app.models import JSONModel, ModelList @@ -108,6 +109,15 @@ class User(JSONModel, UserMixin): response = user_api_client.update_password(self.id, password) self.__init__(response) + def password_changed_more_recently_than(self, datetime_string): + if not self.password_changed_at: + return False + return utc_string_to_aware_gmt_datetime( + self.password_changed_at + ) > utc_string_to_aware_gmt_datetime( + datetime_string + ) + def set_permissions(self, service_id, permissions, folder_permissions): user_api_client.set_user_permissions( self.id,