Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions cms/djangoapps/course_creators/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,11 @@ def send_user_notification_callback(sender, **kwargs): # pylint: disable=unused

try:
user.email_user(subject, message, studio_request_email)
except: # pylint: disable=bare-except
log.warning("Unable to send course creator status e-mail to %s", user.email)
except: # lint-amnesty, pylint: disable=bare-except
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.warning("Unable to send course creator status e-mail to user ID %s", user.id)
else:
log.warning("Unable to send course creator status e-mail to %s", user.email)


@receiver(send_admin_notification, sender=CourseCreator)
Expand All @@ -185,7 +188,10 @@ def send_admin_notification_callback(sender, **kwargs): # pylint: disable=unuse
fail_silently=False
)
except SMTPException:
log.warning("Failure sending 'pending state' e-mail for %s to %s", user.email, studio_request_email)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.warning("Failure sending 'pending state' e-mail for user ID %s to [REDACTED]", user.id)
else:
log.warning("Failure sending 'pending state' e-mail for %s to %s", user.email, studio_request_email)


@receiver(m2m_changed, sender=CourseCreator.organizations.through)
Expand Down
10 changes: 8 additions & 2 deletions common/djangoapps/student/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ def send_proctoring_requirements_email(context):
user_context={'full_name': user.profile.name}
)
ace.send(msg)
log.info('Proctoring requirements email sent to user: %r', user.username)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info('Proctoring requirements email sent to user ID: %r', user.id)
else:
log.info('Proctoring requirements email sent to user: %r', user.username)
return True
except Exception: # pylint: disable=broad-except
log.exception('Could not send email for proctoring requirements to user %s', user.username)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.exception('Could not send email for proctoring requirements to user ID %s', user.id)
else:
log.exception('Could not send email for proctoring requirements to user %s', user.username)
return False
14 changes: 10 additions & 4 deletions common/djangoapps/student/models/course_enrollment.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,15 +731,18 @@ def enroll(cls, user, course_key, mode=None, check_access=False, can_upgrade=Fal
course_key=course.id,
display_name=course.display_name,
)
except CourseOverview.DoesNotExist:
except CourseOverview.DoesNotExist as err:
# This is here to preserve legacy behavior which allowed enrollment in courses
# announced before the start of content creation.
course_data = CourseData(
course_key=course_key,
)
if check_access:
log.warning("User %s failed to enroll in non-existent course %s", user.username, str(course_key))
raise NonExistentCourseError # pylint: disable=raise-missing-from # noqa: B904
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.warning("User %s failed to enroll in non-existent course %s", user.id, str(course_key))
else:
log.warning("User %s failed to enroll in non-existent course %s", user.username, str(course_key))
raise NonExistentCourseError from err # lint-amnesty, pylint: disable=raise-missing-from

if check_access:
if cls.is_enrollment_closed(user, course) and not can_upgrade:
Expand Down Expand Up @@ -829,7 +832,10 @@ def enroll_by_email(cls, email, course_id, mode=None, ignore_errors=True):
return cls.enroll(user, course_id, mode)
except User.DoesNotExist:
err_msg = "Tried to enroll email {} into course {}, but user not found"
log.error(err_msg.format(email, course_id))
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.error(err_msg.format('[PII_REDACTED]', course_id))
else:
log.error(err_msg.format(email, course_id))
if ignore_errors:
return None
raise
Expand Down
5 changes: 4 additions & 1 deletion common/djangoapps/student/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,10 @@ def activate(self): # pylint: disable=missing-function-docstring
self.activation_timestamp = datetime.utcnow()
self.save()
USER_ACCOUNT_ACTIVATED.send_robust(self.__class__, user=self.user)
log.info('User %s (%s) account is successfully activated.', self.user.username, self.user.email)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info('User %s account is successfully activated.', self.user.id)
else:
log.info('User %s (%s) account is successfully activated.', self.user.username, self.user.email)


class PendingNameChange(DeletableByUserValue, models.Model): # noqa: DJ008
Expand Down
41 changes: 31 additions & 10 deletions common/djangoapps/student/views/management.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,10 @@ def change_enrollment(request, check_access=True):
except UnenrollmentNotAllowed as exc:
return HttpResponseBadRequest(str(exc))

log.info("User %s unenrolled from %s; sending REFUND_ORDER", user.username, course_id)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info("User %s unenrolled from %s; sending REFUND_ORDER", user.id, course_id)
else:
log.info("User %s unenrolled from %s; sending REFUND_ORDER", user.username, course_id)
REFUND_ORDER.send(sender=None, course_enrollment=enrollment)
return HttpResponse()
else:
Expand Down Expand Up @@ -557,11 +560,17 @@ def disable_account_ajax(request):
if account_action == 'disable':
user_account.account_status = UserStanding.ACCOUNT_DISABLED
context['message'] = _("Successfully disabled {}'s account").format(username)
log.info("%s disabled %s's account", request.user, username)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info("%s disabled user %s's account", request.user.id, '[PII_REDACTED]')
else:
log.info("%s disabled %s's account", request.user, username)
elif account_action == 'reenable':
user_account.account_status = UserStanding.ACCOUNT_ENABLED
context['message'] = _("Successfully reenabled {}'s account").format(username)
log.info("%s reenabled %s's account", request.user, username)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info("%s reenabled user %s's account", request.user.id, '[PII_REDACTED]')
else:
log.info("%s reenabled %s's account", request.user, username)
else:
context['message'] = _("Unexpected account status")
return JsonResponse(context, status=400)
Expand Down Expand Up @@ -847,11 +856,17 @@ def do_email_change_request(user, new_email, activation_key=None, secondary_emai

try:
ace.send(msg)
log.info("Email activation link sent to user [%s].", new_email)
except Exception:
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info("Email activation link sent for user ID: [%s].", user.id)
else:
log.info("Email activation link sent to user [%s].", new_email)
except Exception as err:
from_address = configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
log.error('Unable to send email activation link to user from "%s"', from_address, exc_info=True)
raise ValueError(_('Unable to send email activation link. Please try again later.')) # pylint: disable=raise-missing-from # noqa: B904
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.error('Unable to send email activation link from a redacted address', exc_info=True)
else:
log.error('Unable to send email activation link to user from "%s"', from_address, exc_info=True)
raise ValueError(_('Unable to send email activation link. Please try again later.')) from err # lint-amnesty, pylint: disable=raise-missing-from

if not secondary_email_change_request:
# When the email address change is complete, a "edx.user.settings.changed" event will be emitted.
Expand Down Expand Up @@ -900,7 +915,7 @@ def activate_secondary_email(request, key):


@ensure_csrf_cookie
def confirm_email_change(request, key):
def confirm_email_change(request, key): # pylint: disable=too-many-statements
"""
User requested a new e-mail. This is called when the activation
link is clicked. We confirm with the old e-mail, and update
Expand Down Expand Up @@ -960,7 +975,10 @@ def confirm_email_change(request, key):
try:
ace.send(msg)
except Exception: # pylint: disable=broad-except
log.warning('Unable to send confirmation email to old address', exc_info=True)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.warning('Unable to send confirmation email to old address [REDACTED]', exc_info=True)
else:
log.warning('Unable to send confirmation email to old address', exc_info=True)
response = render_to_response("email_change_failed.html", {'email': user.email})
transaction.set_rollback(True)
return response
Expand All @@ -976,7 +994,10 @@ def confirm_email_change(request, key):
try:
ace.send(msg)
except Exception: # pylint: disable=broad-except
log.warning('Unable to send confirmation email to new address', exc_info=True)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.warning('Unable to send confirmation email to new address [REDACTED]', exc_info=True)
else:
log.warning('Unable to send confirmation email to new address', exc_info=True)
response = render_to_response("email_change_failed.html", {'email': user.email})
transaction.set_rollback(True)
return response
Expand Down
15 changes: 12 additions & 3 deletions lms/djangoapps/bulk_user_retirement/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
import logging

from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import transaction
from rest_framework import permissions, status
Expand Down Expand Up @@ -56,11 +57,19 @@ def post(self, request, **kwargs): # pylint: disable=unused-argument
user_to_retire = User.objects.get(username=username)
with transaction.atomic():
create_retirement_request_and_deactivate_account(user_to_retire)
log.info(f'The user "{username}" has been added to the retirement pipeline \
by "{request.user}"')
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info('A user has been added to the retirement pipeline')
else:
log.info('The user "%s" has been added to the retirement pipeline by "%s"',
username,
request.user,
)

except User.DoesNotExist:
log.exception(f'The user "{username}" does not exist.')
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.exception('A user does not exist for bulk retirement.')
else:
log.exception(f'The user "{username}" does not exist.')
failed_user_retirements.append(username)

except Exception as exc: # pylint: disable=broad-except
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ def send_ace_message(goal, session_id):
"""
user = goal.user
if not user.has_usable_password():
log.info(f'Goal Reminder User is disabled {user.username} course {goal.course_key}')
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info(f'Goal Reminder User is disabled user ID {user.id} course {goal.course_key}')
else:
log.info(f'Goal Reminder User is disabled {user.username} course {goal.course_key}')
return False
try:
course = CourseOverview.get_from_id(goal.course_key)
Expand Down
10 changes: 7 additions & 3 deletions lms/djangoapps/courseware/model_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from abc import ABCMeta, abstractmethod
from collections import defaultdict, namedtuple

from django.conf import settings
from django.db import DatabaseError, IntegrityError, transaction
from opaque_keys.edx.asides import AsideUsageKeyV1, AsideUsageKeyV2
from opaque_keys.edx.block_types import BlockTypeKeyV1
Expand Down Expand Up @@ -404,9 +405,12 @@ def set_many(self, kv_dict):
self.user.username,
pending_updates
)
except DatabaseError:
log.exception("Saving user state failed for %s", self.user.username)
raise KeyValueMultiSaveError([]) # pylint: disable=raise-missing-from # noqa: B904
except DatabaseError as err:
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.exception("Saving user state failed for user ID %s", self.user.id)
else:
log.exception("Saving user state failed for %s", self.user.username)
raise KeyValueMultiSaveError([]) from err # lint-amnesty, pylint: disable=raise-missing-from
finally:
self._cache.update(pending_updates)

Expand Down
5 changes: 4 additions & 1 deletion lms/djangoapps/courseware/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1479,7 +1479,10 @@ def generate_user_cert(request, course_id):
return HttpResponseBadRequest(str(e))

if not is_course_passed(student, course):
log.info("User %s has not passed the course: %s", student.username, course_id)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info("User ID %s has not passed the course: %s", student.id, course_id)
else:
log.info("User %s has not passed the course: %s", student.username, course_id)
return HttpResponseBadRequest(_("Your certificate will be available when you pass the course."))

certificate_status = certs_api.certificate_downloadable_status(student, course.id)
Expand Down
5 changes: 4 additions & 1 deletion lms/djangoapps/instructor/views/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,10 @@ def post(self, request, course_id): # pylint: disable=too-many-statements
warnings.append({
'username': username, 'email': email, 'response': warning_message
})
log.warning('email %s already exist', email)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.warning('email [REDACTED] already exist')
else:
log.warning('email %s already exist', email)
else:
log.info(
"user already exists with username '%s' and email '%s'",
Expand Down
11 changes: 9 additions & 2 deletions lms/djangoapps/instructor/views/instructor_task_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import json
import logging

from django.conf import settings
from django.utils.translation import gettext as _
from django.utils.translation import ngettext

Expand Down Expand Up @@ -55,7 +56,10 @@ def extract_email_features(email_task):
try:
task_input_information = json.loads(email_task.task_input)
except ValueError:
log.error("Could not parse task input as valid json; task input: %s", email_task.task_input)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.error("Could not parse task input as valid json; task input: [REDACTED]")
else:
log.error("Could not parse task input as valid json; task input: %s", email_task.task_input)
return email_error_information()

email = CourseEmail.objects.get(id=task_input_information['email_id'])
Expand All @@ -82,7 +86,10 @@ def extract_email_features(email_task):
try:
task_output = json.loads(email_task.task_output)
except ValueError:
log.error("Could not parse task output as valid json; task output: %s", email_task.task_output)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.error("Could not parse task output as valid json; task output: [REDACTED]")
else:
log.error("Could not parse task output as valid json; task output: %s", email_task.task_output)
else:
if 'succeeded' in task_output and task_output['succeeded'] > 0:
num_emails = task_output['succeeded']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
from pprint import pformat

from django.conf import settings
from django.contrib.auth.models import User # pylint: disable=imported-auth-user
from django.core.management.base import BaseCommand, CommandError

Expand Down Expand Up @@ -53,7 +54,10 @@ def handle(self, *args, **options):
if single_email:
successfully_verified = self._add_user_to_manual_verification(single_email)
if successfully_verified is False:
log.error(f'Manual verification of {single_email} failed')
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.error('Manual verification of [REDACTED_EMAIL] failed')
else:
log.error(f'Manual verification of {single_email} failed')
return

email_ids_file = options['email_ids_file']
Expand All @@ -70,7 +74,10 @@ def handle(self, *args, **options):
len(failed_emails),
total_emails
))
log.error(f'Failed emails:{pformat(failed_emails)}')
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.error('Failed emails: [REDACTED]')
else:
log.error(f'Failed emails:{pformat(failed_emails)}')
else:
log.info(f'Successfully generated manual verification for {total_emails} emails.')

Expand Down Expand Up @@ -122,7 +129,10 @@ def _add_users_to_manual_verification(self, email_ids):
status='approved',
))
else:
log.info(f'Skipping email {user.email}, existing verification found.')
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.info(f'Skipping user ID {user.id}, existing verification found.')
else:
log.info(f'Skipping email {user.email}, existing verification found.')
ManualVerification.objects.bulk_create(verifications_to_create)
failed_emails = set(email_ids) - set(users.values_list('email', flat=True))
return list(failed_emails)
Expand All @@ -147,5 +157,8 @@ def _add_user_to_manual_verification(self, email_id):
)
return True
except User.DoesNotExist:
log.error(f'Tried to verify email {email_id}, but user not found')
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
log.error('Tried to verify email [REDACTED_EMAIL], but user not found')
else:
log.error(f'Tried to verify email {email_id}, but user not found')
return False
5 changes: 4 additions & 1 deletion openedx/core/djangoapps/user_authn/views/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ def _enforce_password_policy_compliance(request, user): # pylint: disable=missi
if LoginFailures.is_feature_enabled():
LoginFailures.increment_lockout_counter(user)

AUDIT_LOG.info("Password reset initiated for email %s.", user.email)
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
AUDIT_LOG.info("Password reset initiated for user ID %s.", user.id)
else:
AUDIT_LOG.info("Password reset initiated for email %s.", user.email)
tracker.emit(
PASSWORD_RESET_INITIATED,
{
Expand Down
Loading