def clean_email_or_username(self): """ Clean email form field Returns: str: the cleaned value, converted to an email address (or an empty string) """ email_or_username = self.cleaned_data[ self.Fields.EMAIL_OR_USERNAME].strip() if not email_or_username: # The field is blank; we just return the existing blank value. return email_or_username email = email_or_username__to__email(email_or_username) bulk_entry = len(split_usernames_and_emails(email)) > 1 if bulk_entry: for email in split_usernames_and_emails(email): validate_email_to_link( email, None, ValidationMessages.INVALID_EMAIL_OR_USERNAME, ignore_existing=True) email = email_or_username else: validate_email_to_link( email, email_or_username, ValidationMessages.INVALID_EMAIL_OR_USERNAME, ignore_existing=True) return email
def test_validate_email_to_link_invalid_email(self, email, raw_email, msg_template): assert EnterpriseCustomerUser.objects.get_link_by_email(email) is None, \ "Precondition check - should not have EnterpriseCustomerUser or PendingEnterpriseCustomerUser" expected_message = msg_template.format(argument=raw_email) with raises(ValidationError, match=expected_message): validate_email_to_link(email, raw_email)
def _handle_singular(cls, request, enterprise_customer, manage_learners_form): """ Link single user by email or username. Arguments: enterprise_customer (EnterpriseCustomer): learners will be linked to this Enterprise Customer instance manage_learners_form (ManageLearnersForm): bound ManageLearners form instance """ form_field_value = manage_learners_form.cleaned_data[ ManageLearnersForm.Fields.EMAIL_OR_USERNAME] email = email_or_username__to__email(form_field_value) try: existing_record = validate_email_to_link( email, form_field_value, ValidationMessages.INVALID_EMAIL_OR_USERNAME, True) except ValidationError as exc: manage_learners_form.add_error( ManageLearnersForm.Fields.EMAIL_OR_USERNAME, exc) else: if isinstance(existing_record, PendingEnterpriseCustomerUser) and existing_record.enterprise_customer \ != enterprise_customer: messages.warning( request, ValidationMessages.PENDING_USER_ALREADY_LINKED.format( user_email=email, ec_name=existing_record.enterprise_customer.name)) return None EnterpriseCustomerUser.objects.link_user(enterprise_customer, email) return [email]
def _handle_singular(cls, enterprise_customer, manage_learners_form): """ Link single user by email or username. Arguments: enterprise_customer (EnterpriseCustomer): learners will be linked to this Enterprise Customer instance manage_learners_form (ManageLearnersForm): bound ManageLearners form instance """ form_field_value = manage_learners_form.cleaned_data[ManageLearnersForm.Fields.EMAIL_OR_USERNAME] email = email_or_username__to__email(form_field_value) try: validate_email_to_link(email, form_field_value, ValidationMessages.INVALID_EMAIL_OR_USERNAME) except ValidationError as exc: manage_learners_form.add_error(ManageLearnersForm.Fields.EMAIL_OR_USERNAME, exc.message) else: EnterpriseCustomerUser.objects.link_user(enterprise_customer, email) return [email]
def test_validate_email_to_link_existing_pending_record(self, ignore_existing): email = FAKER.email() # pylint: disable=no-member existing_record = PendingEnterpriseCustomerUserFactory(user_email=email) assert PendingEnterpriseCustomerUser.objects.get(user_email=email) == existing_record, \ "Precondition check - should have PendingEnterpriseCustomerUser" assert not EnterpriseCustomerUser.objects.exists(), \ "Precondition check - should not have EnterpriseCustomerUser" if ignore_existing: exists = validate_email_to_link(email, ignore_existing=True) assert exists else: expected_message = ValidationMessages.USER_ALREADY_REGISTERED.format( email=email, ec_name=existing_record.enterprise_customer.name ) with raises(ValidationError, match=expected_message): exists = validate_email_to_link(email)
def test_validate_email_to_link_normal(self): email = FAKER.email() # pylint: disable=no-member assert PendingEnterpriseCustomerUser.objects.filter(user_email=email).count() == 0, \ "Precondition check - should not have PendingEnterpriseCustomerUser" assert EnterpriseCustomerUser.objects.count() == 0, \ "Precondition check - should not have EnterpriseCustomerUser" exists = validate_email_to_link(email) # should not raise any Exceptions assert exists is False
def test_validate_email_to_link_normal(self): email = FAKER.email() assert len(PendingEnterpriseCustomerUser.objects.filter(user_email=email)) == 0, \ "Precondition check - should not have PendingEnterpriseCustomerUser" assert len(EnterpriseCustomerUser.objects.all()) == 0, \ "Precondition check - should not have EnterpriseCustomerUser" exists = validate_email_to_link(email) # should not raise any Exceptions assert exists is False
def test_validate_email_to_link_existing_user_record(self, ignore_existing): user = UserFactory() email = user.email existing_record = EnterpriseCustomerUserFactory(user_id=user.id) assert not PendingEnterpriseCustomerUser.objects.exists(), \ "Precondition check - should not have PendingEnterpriseCustomerUser" assert EnterpriseCustomerUser.objects.get(user_id=user.id) == existing_record, \ "Precondition check - should have EnterpriseCustomerUser" if ignore_existing: exists = validate_email_to_link(email, ignore_existing=True) assert exists else: expected_message = ValidationMessages.USER_ALREADY_REGISTERED.format( email=email, ec_name=existing_record.enterprise_customer.name ) with raises(ValidationError, match=expected_message): validate_email_to_link(email)
def clean_email_or_username(self): """ Clean email form field Returns: str: the cleaned value, converted to an email address (or an empty string) """ email_or_username = self.cleaned_data[ self.Fields.EMAIL_OR_USERNAME].strip() if not email_or_username: # The field is blank; we just return the existing blank value. return email_or_username email = email_or_username__to__email(email_or_username) validate_email_to_link(email, email_or_username, ValidationMessages.INVALID_EMAIL_OR_USERNAME) return email
def _handle_bulk_upload(cls, enterprise_customer, manage_learners_form, request): """ Bulk link users by email. Arguments: enterprise_customer (EnterpriseCustomer): learners will be linked to this Enterprise Customer instance manage_learners_form (ManageLearnersForm): bound ManageLearners form instance request (django.http.request.HttpRequest): HTTP Request instance """ errors = [] emails = set() already_linked_emails = [] duplicate_emails = [] csv_file = manage_learners_form.cleaned_data[ ManageLearnersForm.Fields.BULK_UPLOAD] try: parsed_csv = parse_csv( csv_file, expected_columns={ManageLearnersForm.CsvColumns.EMAIL}) for index, row in enumerate(parsed_csv): email = row[ManageLearnersForm.CsvColumns.EMAIL] try: already_linked = validate_email_to_link( email, ignore_existing=True) except ValidationError as exc: message = _("Error at line {line}: {message}\n").format( line=index + 1, message=exc.message) errors.append(message) else: if already_linked: already_linked_emails.append(email) elif email in emails: duplicate_emails.append(email) else: emails.add(email) except ValidationError as exc: errors.append(exc.message) if errors: manage_learners_form.add_error( ManageLearnersForm.Fields.GENERAL_ERRORS, ValidationMessages.BULK_LINK_FAILED) for error in errors: manage_learners_form.add_error( ManageLearnersForm.Fields.BULK_UPLOAD, error) return # There were no errors. Now do the actual linking: for email in emails: EnterpriseCustomerUser.objects.link_user(enterprise_customer, email) # Report what happened: count = len(emails) messages.success( request, ungettext( "{count} new user was linked to {enterprise_customer_name}.", "{count} new users were linked to {enterprise_customer_name}.", count).format( count=count, enterprise_customer_name=enterprise_customer.name)) if already_linked_emails: messages.warning( request, _("Some users were already linked to this Enterprise Customer: {list_of_emails}" ).format(list_of_emails=", ".join(already_linked_emails))) if duplicate_emails: messages.warning( request, _("Some duplicate emails in the CSV were ignored: {list_of_emails}" ).format(list_of_emails=", ".join(duplicate_emails))) return list(emails) + already_linked_emails
def _handle_bulk_upload(cls, enterprise_customer, manage_learners_form, request, email_list=None): """ Bulk link users by email. Arguments: enterprise_customer (EnterpriseCustomer): learners will be linked to this Enterprise Customer instance manage_learners_form (ManageLearnersForm): bound ManageLearners form instance request (django.http.request.HttpRequest): HTTP Request instance email_list (iterable): A list of pre-processed email addresses to handle using the form """ errors = [] emails = set() already_linked_emails = [] duplicate_emails = [] csv_file = manage_learners_form.cleaned_data[ ManageLearnersForm.Fields.BULK_UPLOAD] if email_list: parsed_csv = [{ ManageLearnersForm.CsvColumns.EMAIL: email } for email in email_list] else: parsed_csv = parse_csv( csv_file, expected_columns={ManageLearnersForm.CsvColumns.EMAIL}) try: for index, row in enumerate(parsed_csv): email = row[ManageLearnersForm.CsvColumns.EMAIL] try: already_linked = validate_email_to_link( email, ignore_existing=True) except ValidationError as exc: message = _("Error at line {line}: {message}\n").format( line=index + 1, message=exc) errors.append(message) else: if already_linked: already_linked_emails.append( (email, already_linked.enterprise_customer)) elif email in emails: duplicate_emails.append(email) else: emails.add(email) except ValidationError as exc: errors.append(exc) if errors: manage_learners_form.add_error( ManageLearnersForm.Fields.GENERAL_ERRORS, ValidationMessages.BULK_LINK_FAILED) for error in errors: manage_learners_form.add_error( ManageLearnersForm.Fields.BULK_UPLOAD, error) return # There were no errors. Now do the actual linking: for email in emails: EnterpriseCustomerUser.objects.link_user(enterprise_customer, email) # Report what happened: count = len(emails) messages.success( request, ungettext( "{count} new learner was added to {enterprise_customer_name}.", "{count} new learners were added to {enterprise_customer_name}.", count).format( count=count, enterprise_customer_name=enterprise_customer.name)) this_customer_linked_emails = [ email for email, customer in already_linked_emails if customer == enterprise_customer ] other_customer_linked_emails = [ email for email, __ in already_linked_emails if email not in this_customer_linked_emails ] if this_customer_linked_emails: messages.warning( request, _("The following learners were already associated with this Enterprise " "Customer: {list_of_emails}").format( list_of_emails=", ".join(this_customer_linked_emails))) if other_customer_linked_emails: messages.warning( request, _("The following learners are already associated with " "another Enterprise Customer. These learners were not " "added to {enterprise_customer_name}: {list_of_emails}"). format( enterprise_customer_name=enterprise_customer.name, list_of_emails=", ".join(other_customer_linked_emails), )) if duplicate_emails: messages.warning( request, _("The following duplicate email addresses were not added: " "{list_of_emails}").format( list_of_emails=", ".join(duplicate_emails))) # Build a list of all the emails that we can act on further; that is, # emails that we either linked to this customer, or that were linked already. all_processable_emails = list(emails) + this_customer_linked_emails return all_processable_emails