def create_user_and_user_profile(self, email, username, password, custom_field, complete_name, first_name, last_name): """ Create a new user, add a new Registration instance for letting user verify its identity and create a user profile. :param email: user's email address :param username: user's username :param name: user's name :param country: user's country :param password: user's password :return: User instance of the new user. """ user = User( username=username, email=email, is_active=True, first_name=first_name, last_name=last_name, ) user.set_password(password) user.save() registration = Registration() registration.register(user) """ reg = Registration() reg.register(user) """ #user.save() profile = UserProfile(user=user) profile.custom_field = json.dumps(custom_field) profile.name = complete_name profile.save() return user
def setUp(self): """ Setup components used by each test.""" super(SendActivationEmailTestCase, self).setUp() self.student = UserFactory() registration = Registration() registration.register(self.student) self.msg = compose_activation_email("http://www.example.com", self.student, registration)
def import_user_submit(request): message={} if request.method == 'POST': f=request.FILES['file'] try: count_success=0 # --- THIS FAILS ON SING COLUMN CVS --- # dialect = csv.Sniffer().sniff(f.read(1024), delimiters=";,") # f.seek(0) # r=csv.reader(f,dialect) r=csv.reader(f,delimiter='\t', quotechar='|', quoting=csv.QUOTE_MINIMAL) rl = [] rl.extend(r) cohort_id=request.POST.get("cohort_id") cohort=Cohort.objects.get(id=cohort_id) if cohort.licences < UserProfile.objects.filter(~Q(subscription_status = "Inactive"),cohort_id=cohort_id).count() + len(rl): raise Exception("Licences limit exceeded") for line in rl: exist=validate_user_cvs_line(line) # if(exist): # raise Exception("An user already exists, or duplicate lines.") email=line[USER_CSV_COL_EMAIL] import random username=random_mark(20) user = User(username=username, email=email, is_active=False) user.set_password(username) user.save() registration = Registration() registration.register(user) profile=UserProfile(user=user) # profile.transaction_id=transaction_id # profile.email=email # profile.username=username profile.cohort_id=cohort_id profile.subscription_status="Imported" profile.save() cea, _ = CourseEnrollmentAllowed.objects.get_or_create(course_id='PCG_Education/PEP101.1/S2016', email=email) cea.is_active = True cea.auto_enroll = True cea.save() count_success=count_success+1 # reg = Registration.objects.get(user=user) # d = {'name': profile.name, 'key': reg.activation_key} # subject = render_to_string('emails/activation_email_subject.txt', d) # subject = ''.join(subject.splitlines()) # message = render_to_string('emails/activation_emailh.txt', d) db.transaction.commit() message={"success": True, "message":"Success! %s users imported." % (count_success), "count_success":count_success, } except Exception as e: db.transaction.rollback() message={'success': False,'error':'Import error: %s. At cvs line: %s, Nobody imported.' % (e,count_success+1)} return HttpResponse(json.dumps(message))
def _do_create_account(post_vars): """ Given cleaned post variables, create the User and UserProfile objects, as well as the registration for this user. Returns a tuple (User, UserProfile, Registration). Note: this function is also used for creating test users. """ user = User(username=post_vars['username'], email=post_vars['email'], is_active=False) user.set_password(post_vars['password']) registration = Registration() # TODO: Rearrange so that if part of the process fails, the whole process fails. # Right now, we can have e.g. no registration e-mail sent out and a zombie # account try: user.save() except IntegrityError: js = {'success': False} # Figure out the cause of the integrity error if len(User.objects.filter(username=post_vars['username'])) > 0: js['value'] = "An account with the Public Username '" + post_vars[ 'username'] + "' already exists." js['field'] = 'username' return HttpResponse(json.dumps(js)) if len(User.objects.filter(email=post_vars['email'])) > 0: js['value'] = "An account with the Email '" + post_vars[ 'email'] + "' already exists." js['field'] = 'email' return HttpResponse(json.dumps(js)) raise registration.register(user) profile = UserProfile(user=user) profile.name = post_vars['name'] profile.level_of_education = post_vars.get('level_of_education') profile.gender = post_vars.get('gender') profile.mailing_address = post_vars.get('mailing_address') profile.goals = post_vars.get('goals') try: profile.year_of_birth = int(post_vars['year_of_birth']) except (ValueError, KeyError): # If they give us garbage, just ignore it instead # of asking them to put an integer. profile.year_of_birth = None try: profile.save() except Exception: log.exception( "UserProfile creation failed for user {0}.".format(user.id)) return (user, profile, registration)
def import_user_submit(request): message = {} if request.method == "POST": f = request.FILES["file"] try: count_success = 0 count_exist = 0 # --- THIS FAILS ON SING COLUMN CVS --- # dialect = csv.Sniffer().sniff(f.read(1024), delimiters=";,") # f.seek(0) # r=csv.reader(f,dialect) r = csv.reader(f, delimiter="\t", quotechar="|", quoting=csv.QUOTE_MINIMAL) rl = [] rl.extend(r) cohort_id = request.POST.get("cohort_id") cohort = Cohort.objects.get(id=cohort_id) if cohort.licences < UserProfile.objects.filter(cohort_id=cohort_id).count() + len(rl): raise Exception("Licences limit exceeded") for line in rl: exist = validate_user_cvs_line(line) # if(exist): # raise Exception("An user already exists, or duplicate lines.") email = line[USER_CVS_COL_EMAIL] import random username = "".join(random.sample("abcdefg&#%^*f1234567890", 20)) user = User(username=username, email=email, is_active=True) user.set_password(username) user.save() registration = Registration() registration.register(user) profile = UserProfile(user=user) # profile.transaction_id=transaction_id # profile.email=email # profile.username=username profile.cohort_id = cohort_id profile.subscription_status = "Imported" profile.save() # reg = Registration.objects.get(user=user) # d = {'name': profile.name, 'key': reg.activation_key} # subject = render_to_string('emails/activation_email_subject.txt', d) # subject = ''.join(subject.splitlines()) # message = render_to_string('emails/activation_email.txt', d) db.transaction.commit() message = { "success": True, "message": "Success! %s users imported." % (count_success), "count_exist": count_exist, "count_success": count_success, } except Exception as e: db.transaction.rollback() message = { "success": False, "error": "Import error: %s. At cvs line: %s, Nobody imported." % (e, count_success + 1), } return HttpResponse(json.dumps(message))
def _do_create_account(post_vars): """ Given cleaned post variables, create the User and UserProfile objects, as well as the registration for this user. Returns a tuple (User, UserProfile, Registration). Note: this function is also used for creating test users. """ user = User(username=post_vars['username'], email=post_vars['email'], is_active=False) user.set_password(post_vars['password']) registration = Registration() # TODO: Rearrange so that if part of the process fails, the whole process fails. # Right now, we can have e.g. no registration e-mail sent out and a zombie # account try: user.save() except IntegrityError: js = {'success': False} # Figure out the cause of the integrity error if len(User.objects.filter(username=post_vars['username'])) > 0: js['value'] = "An account with the Public Username '" + post_vars[ 'username'] + "' already exists." js['field'] = 'username' return HttpResponse(json.dumps(js)) if len(User.objects.filter(email=post_vars['email'])) > 0: js['value'] = "An account with the Email '" + post_vars[ 'email'] + "' already exists." js['field'] = 'email' return HttpResponse(json.dumps(js)) raise registration.register(user) profile = UserProfile(user=user) profile.name = post_vars['name'] profile.level_of_education = post_vars.get('level_of_education') profile.gender = post_vars.get('gender') profile.mailing_address = post_vars.get('mailing_address') profile.goals = post_vars.get('goals') try: profile.year_of_birth = int(post_vars['year_of_birth']) except (ValueError, KeyError): # If they give us garbage, just ignore it instead # of asking them to put an integer. profile.year_of_birth = None try: profile.save() except Exception: log.exception("UserProfile creation failed for user {0}.".format( user.id)) return (user, profile, registration)
def do_create_account_no_registration(data): """ Given cleaned post variables, create the User and UserProfile objects, as well as the registration for this user. Returns a tuple (User, UserProfile, Registration). Note: this function is also used for creating test users. """ # Check if ALLOW_PUBLIC_ACCOUNT_CREATION flag turned off to restrict user account creation proposed_username = data["username"] user = User(username=proposed_username, email=data["phone_number"] + settings.DEFAULT_EMAIL_ACCOUNT_DOMAIN, is_active=True) log.warning("phone: " + data["phone_number"]) password = normalize_password(data["password"]) user.set_password(password) registration = Registration() try: with transaction.atomic(): user.save() except IntegrityError: # Figure out the cause of the integrity error # TODO duplicate email is already handled by form.errors above as a ValidationError. # The checks for duplicate email/username should occur in the same place with an # AccountValidationError and a consistent user message returned (i.e. both should # return "It looks like {username} belongs to an existing account. Try again with a # different username.") if username_exists_or_retired(user.username): raise AccountValidationError( USERNAME_EXISTS_MSG_FMT.format(username=proposed_username), field="username") elif email_exists_or_retired(user.email): raise AccountValidationError(_( "An account with the Email '{email}' already exists.").format( email=user.email), field="email") else: raise registration.register(user) profile_fields = [ "name", "level_of_education", "gender", "mailing_address", "city", "country", "goals", "year_of_birth", "phone_number", "web_accelerator_name", "web_accelerator_link" ] profile = UserProfile(user=user, **{key: data.get(key) for key in profile_fields}) profile.save() # except Exception: # log.exception("UserProfile creation failed for user {id}.".format(id=user.id)) # raise log.warning("Testing the process to register {id}".format(id=user.id)) return user, profile
def create_user(username,password,email,name): user = User(username=username, email=email, is_active=True, ) user.set_password(password) user.save() registration = Registration() registration.register(user) profile = UserProfile(user=user) profile.name = name profile.save()
def create_user(username, password, email, name): user = User( username=username, email=email, is_active=True, ) user.set_password(password) user.save() registration = Registration() registration.register(user) profile = UserProfile(user=user) profile.name = name profile.save()
def create_user(self, uname, name, password=None): """ Creates a user """ if not uname: return _('Must provide username') if not name: return _('Must provide full name') msg = u'' if not password: return _('Password must be supplied') email = uname if '@' not in email: msg += _('email address required (not username)') return msg new_password = password user = User(username=uname, email=email, is_active=True) user.set_password(new_password) try: user.save() except IntegrityError: msg += _(u'Oops, failed to create user {user}, {error}').format( user=user, error="IntegrityError" ) return msg reg = Registration() reg.register(user) profile = UserProfile(user=user) profile.name = name profile.save() msg += _(u'User {user} created successfully!').format(user=user) return msg
def _do_create_account_custom(form, custom_form=None): """ Given cleaned post variables, create the User and UserProfile objects, as well as the registration for this user. Returns a tuple (User, UserProfile, Registration). Note: this function is also used for creating test users. """ errors = {} errors.update(form.errors) if custom_form: errors.update(custom_form.errors) if errors: raise ValidationError(errors) user = User(username=form.cleaned_data["username"], email=form.cleaned_data["email"], is_active=False) user.set_password(form.cleaned_data["password"]) registration = Registration() # TODO: Rearrange so that if part of the process fails, the whole process fails. # Right now, we can have e.g. no registration e-mail sent out and a zombie account try: with transaction.atomic(): user.save() custom_model = custom_form.save(user=user, commit=True) # Fix: recall user.save to avoid transaction management related exception, if we call user.save under atomic block # (in custom_from.save )a random transaction exception generated if custom_model.organization: custom_model.organization.save() user.save() except IntegrityError: # Figure out the cause of the integrity error if len(User.objects.filter(username=user.username)) > 0: raise AccountValidationError(_( "An account with the Public Username '{username}' already exists." ).format(username=user.username), field="username") elif len(User.objects.filter(email=user.email)) > 0: raise AccountValidationError(_( "An account with the Email '{email}' already exists.").format( email=user.email), field="email") else: raise # add this account creation to password history # NOTE, this will be a NOP unless the feature has been turned on in configuration password_history_entry = PasswordHistory() password_history_entry.create(user) registration.register(user) profile_fields = [ "name", "level_of_education", "gender", "mailing_address", "city", "country", "goals", "year_of_birth" ] profile = UserProfile( user=user, **{key: form.cleaned_data.get(key) for key in profile_fields}) extended_profile = form.cleaned_extended_profile if extended_profile: profile.meta = json.dumps(extended_profile) try: profile.save() except Exception: # pylint: disable=broad-except log.exception( "UserProfile creation failed for user {id}.".format(id=user.id)) raise return (user, profile, registration)
def do_create_account(form, custom_form=None): """ Given cleaned post variables, create the User and UserProfile objects, as well as the registration for this user. Returns a tuple (User, UserProfile, Registration). Note: this function is also used for creating test users. """ # Check if ALLOW_PUBLIC_ACCOUNT_CREATION flag turned off to restrict user account creation if not configuration_helpers.get_value( 'ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION', True) ): raise PermissionDenied() errors = {} errors.update(form.errors) if custom_form: errors.update(custom_form.errors) if errors: raise ValidationError(errors) proposed_username = form.cleaned_data["username"] user = User( username=proposed_username, email=form.cleaned_data["email"], is_active=False ) password = normalize_password(form.cleaned_data["password"]) user.set_password(password) registration = Registration() # TODO: Rearrange so that if part of the process fails, the whole process fails. # Right now, we can have e.g. no registration e-mail sent out and a zombie account try: with transaction.atomic(): user.save() if custom_form: custom_model = custom_form.save(commit=False) custom_model.user = user custom_model.save() except IntegrityError: # Figure out the cause of the integrity error # TODO duplicate email is already handled by form.errors above as a ValidationError. # The checks for duplicate email/username should occur in the same place with an # AccountValidationError and a consistent user message returned (i.e. both should # return "It looks like {username} belongs to an existing account. Try again with a # different username.") if username_exists_or_retired(user.username): raise AccountValidationError( USERNAME_EXISTS_MSG_FMT.format(username=proposed_username), field="username" ) elif email_exists_or_retired(user.email): raise AccountValidationError( _("An account with the Email '{email}' already exists.").format(email=user.email), field="email" ) else: raise registration.register(user) profile_fields = [ "name", "level_of_education", "gender", "mailing_address", "city", "country", "goals", "year_of_birth" ] profile = UserProfile( user=user, **{key: form.cleaned_data.get(key) for key in profile_fields} ) extended_profile = form.cleaned_extended_profile if extended_profile: profile.meta = json.dumps(extended_profile) try: profile.save() except Exception: log.exception("UserProfile creation failed for user {id}.".format(id=user.id)) raise return user, profile, registration
def create_user(self, uname, name, is_tempuser, password='******', request=None): """ Creates a user (both SSL and regular)""" if not uname: return _('Must provide username') if not name: return _('Must provide full name') msg = u'' if '@' not in uname: msg += _('Email address must contain @') return msg elif not password: msg += _('Password must be supplied if not using certificates') return msg email = uname new_password = password try: from django.db import transaction with transaction.atomic(): user = User(username=uname, email=email, is_active=True) user.set_password(new_password) user.save() except IntegrityError: msg += _('Oops, failed to create user {user}, {error}').format( user=uname, error="{} already exist.".format(email)) return msg reg = Registration() reg.register(user) profile = UserProfile(user=user) profile.name = name profile.save() mosouser = MosoUser(user=user, creted_by=request.user) mosouser.save() msg += _('User {user} created successfully!').format(user=user) if is_tempuser: try: task_result = deactivate_task(user.id) if task_result: msg += "<br> Configure Deactivate Task successfully!" print("*" * 50) print("Configure Deactivate Task successfully!") except: msg += "<br> Failed to Configure Deactivate Task!" print("Failed to Configure Deactivate Task!") else: msg += "<br> Failed to Configure Deactivate Task!" return msg
def create_unknown_user(request, ms, data): '''Create the sso user who\'s not exists in pepper''' try: attribute_setting = ms.get('attributes') # Parse to mapped attribute parsed_data = {} for attr in attribute_setting: mapped_name = attr['map'] if 'map' in attr else attr['name'] if attr['name']: parsed_data[mapped_name] = data.get(attr['name']) print attribute_setting print data print parsed_data # Generate username if not provided if not parsed_data.get('username'): username = random_mark(20) else: username = parsed_data['username'] # Email must be profided email = parsed_data['email'] user = User(username=username, email=email, is_active=False) user.set_password(username) # Set password the same with username user.save() registration = Registration() registration.register(user) profile = UserProfile(user=user) profile.subscription_status = "Imported" profile.sso_type = ms.get('sso_type') profile.sso_idp = ms.get('sso_name') # Save mapped attributes for k, v in parsed_data.items(): if k == 'first_name': user.first_name = parsed_data['first_name'] elif k == 'last_name': user.last_name = parsed_data['last_name'] elif k == 'sso_user_id': profile.sso_user_id = parsed_data['sso_user_id'] elif k == 'district': profile.district = District.object.get(name=parsed_data['district']) elif k == 'school': profile.school = School.object.get(name=parsed_data['school']) elif k == 'grade_level': ids = GradeLevel.object.filter(name__in=parsed_data['grade_level'].split(',')).values_list('id', flat=True) profile.grade_level = ','.join(ids) elif k == 'major_subject_area': ids = SubjectArea.object.filter(name__in=parsed_data['major_subject_area'].split(',')).values_list('id', flat=True) profile.major_subject_area = ','.join(ids) elif k == 'years_in_education': profile.years_in_education = YearsInEducation.object.get(name=parsed_data['years_in_education']) elif k == 'percent_lunch': profile.percent_lunch = Enum.object.get(name='percent_lunch', content=parsed_data['percent_lunch']) elif k == 'percent_iep': profile.percent_iep = Enum.object.get(name='percent_iep', content=parsed_data['percent_iep']) elif k == 'percent_eng_learner': profile.percent_eng_learner = Enum.object.get(name='percent_eng_learner', content=parsed_data['percent_eng_learner']) user.save() profile.save() cea, _ = CourseEnrollmentAllowed.objects.get_or_create(course_id='PCG_Education/PEP101.1/S2016', email=email) cea.is_active = True cea.auto_enroll = True cea.save() return https_redirect(request, reverse('register_sso_user', args=[registration.activation_key])) except Exception as e: raise e db.transaction.rollback() log.error("error: failed to create SSO user: %s" % e)
def import_user_submit(request): # http://www.cnblogs.com/yijun-boxing/archive/2011/04/18/2020155.html CONTRACT_CVS_COL_CONTRACT_ID=0 CONTRACT_CVS_COL_DISTRICT_ID=1 CONTRACT_CVS_COL_EMAIL=2 CONTRACT_CVS_COL_USERNAME=3 CONTRACT_CVS_COUNT_COL=4 message={} n=0 if request.method == 'POST': f=request.FILES['file'] dialect = csv.Sniffer().sniff(f.read(1024), delimiters=";,") f.seek(0) r=csv.reader(f,dialect) try: for i,line in enumerate(r): n=n+1 contract_id=line[CONTRACT_CVS_COL_CONTRACT_ID] district_id=line[CONTRACT_CVS_COL_DISTRICT_ID] email=line[CONTRACT_CVS_COL_EMAIL] username=line[CONTRACT_CVS_COL_USERNAME] for value in line: if len(value.strip())==0: raise Exception("Catch csv line with empty fields line") if len(line) != CONTRACT_CVS_COUNT_COL: raise Exception("Catch csv line of wrong fields count") user = User(username=username, email=email, is_active=True) user.set_password(username) registration = Registration() try: user.save() except IntegrityError: if len(User.objects.filter(username=username)) > 0: raise Exception("An account with the Public Username '{username}' already exists.".format(username=username)) if len(User.objects.filter(email=email)) > 0: raise Exception("An account with the Email '{email}' already exists.".format(email=email)) registration.register(user) profile=UserProfile(user=user) profile.contract_id=contract_id profile.district_id=district_id profile.email=email profile.username=username profile.save() reg = Registration.objects.get(user=user) d = {'name': profile.name, 'key': reg.activation_key} subject = render_to_string('emails/activation_email_subject.txt', d) subject = ''.join(subject.splitlines()) message = render_to_string('emails/activation_email.txt', d) try: _res = user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) except: log.warning('Unable to send reactivation email', exc_info=True) return HttpResponse(json.dumps({'success': False, 'error': _('Unable to send reactivation email')})) message={'success': True, "message":"Success! %s users imported." % (n)} except Exception as e: transaction.rollback() message={'success': False,'message':'Import error: %s, At cvs line: %s' % (e,n)} # title = forms.CharField(max_length=50) # file = forms.FileField() return HttpResponse(json.dumps(message))
def create_user(self, uname, name, password=None): """ Creates a user (both SSL and regular)""" if not uname: return _('Must provide username') if not name: return _('Must provide full name') email_domain = getattr(settings, 'SSL_AUTH_EMAIL_DOMAIN', 'MIT.EDU') msg = u'' if settings.FEATURES['AUTH_USE_CERTIFICATES']: if '@' not in uname: email = '{0}@{1}'.format(uname, email_domain) else: email = uname if not email.endswith('@{0}'.format(email_domain)): # Translators: Domain is an email domain, such as "@gmail.com" msg += _('Email address must end in {domain}').format(domain="@{0}".format(email_domain)) return msg mit_domain = 'ssl:MIT' if ExternalAuthMap.objects.filter(external_id=email, external_domain=mit_domain): msg += _('Failed - email {email_addr} already exists as {external_id}').format( email_addr=email, external_id="external_id" ) return msg new_password = generate_password() else: if not password: return _('Password must be supplied if not using certificates') email = uname if '@' not in email: msg += _('email address required (not username)') return msg new_password = password user = User(username=uname, email=email, is_active=True) user.set_password(new_password) try: user.save() except IntegrityError: msg += _('Oops, failed to create user {user}, {error}').format( user=user, error="IntegrityError" ) return msg reg = Registration() reg.register(user) profile = UserProfile(user=user) profile.name = name profile.save() if settings.FEATURES['AUTH_USE_CERTIFICATES']: credential_string = getattr(settings, 'SSL_AUTH_DN_FORMAT_STRING', '/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}') credentials = credential_string.format(name, email) eamap = ExternalAuthMap( external_id=email, external_email=email, external_domain=mit_domain, external_name=name, internal_password=new_password, external_credentials=json.dumps(credentials), ) eamap.user = user eamap.dtsignup = timezone.now() eamap.save() msg += _('User {user} created successfully!').format(user=user) return msg
def create_user(self, uname, name, password=None): """ Creates a user (both SSL and regular)""" if not uname: return _("Must provide username") if not name: return _("Must provide full name") email_domain = getattr(settings, "SSL_AUTH_EMAIL_DOMAIN", "MIT.EDU") msg = u"" if settings.FEATURES["AUTH_USE_CERTIFICATES"]: if not "@" in uname: email = "{0}@{1}".format(uname, email_domain) else: email = uname if not email.endswith("@{0}".format(email_domain)): msg += u"{0} @{1}".format(_("email must end in"), email_domain) return msg mit_domain = "ssl:MIT" if ExternalAuthMap.objects.filter(external_id=email, external_domain=mit_domain): msg += _("Failed - email {0} already exists as " "external_id").format(email) return msg new_password = generate_password() else: if not password: return _("Password must be supplied if not using certificates") email = uname if not "@" in email: msg += _("email address required (not username)") return msg new_password = password user = User(username=uname, email=email, is_active=True) user.set_password(new_password) try: user.save() except IntegrityError: msg += _("Oops, failed to create user {0}, " "IntegrityError").format(user) return msg reg = Registration() reg.register(user) profile = UserProfile(user=user) profile.name = name profile.save() if settings.FEATURES["AUTH_USE_CERTIFICATES"]: credential_string = getattr( settings, "SSL_AUTH_DN_FORMAT_STRING", "/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}", ) credentials = credential_string.format(name, email) eamap = ExternalAuthMap( external_id=email, external_email=email, external_domain=mit_domain, external_name=name, internal_password=new_password, external_credentials=json.dumps(credentials), ) eamap.user = user eamap.dtsignup = timezone.now() eamap.save() msg += _("User {0} created successfully!").format(user) return msg
def handle(self, *args, **options): while True: uname = raw_input('username: '******'Create MIT ExternalAuth? [n] ').lower() == 'y': email = '*****@*****.**' % uname if not email.endswith('@MIT.EDU'): print "Failed - email must be @MIT.EDU" sys.exit(-1) mit_domain = 'ssl:MIT' if ExternalAuthMap.objects.filter(external_id=email, external_domain=mit_domain): print "Failed - email %s already exists as external_id" % email sys.exit(-1) make_eamap = True password = GenPasswd(12) # get name from kerberos try: kname = os.popen("finger %s | grep 'name:'" % email).read().strip().split('name: ')[1].strip() except: kname = '' name = raw_input('Full name: [%s] ' % kname).strip() if name == '': name = kname print "name = %s" % name else: while True: password = getpass() password2 = getpass() if password == password2: break print "Oops, passwords do not match, please retry" while True: email = raw_input('email: ') if email_exists_or_retired(email): print "email %s already taken" % email else: break name = raw_input('Full name: ') user = User(username=uname, email=email, is_active=True) user.set_password(password) try: user.save() except IntegrityError: print "Oops, failed to create user %s, IntegrityError" % user raise r = Registration() r.register(user) up = UserProfile(user=user) up.name = name up.save() if make_eamap: credentials = "/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN=%s/emailAddress=%s" % (name, email) eamap = ExternalAuthMap( external_id=email, external_email=email, external_domain=mit_domain, external_name=name, internal_password=password, external_credentials=json.dumps(credentials), ) eamap.user = user eamap.dtsignup = datetime.datetime.now(UTC) eamap.save() print "User %s created successfully!" % user if not raw_input('Add user %s to any groups? [n] ' % user).lower() == 'y': sys.exit(0) print "Here are the groups available:" groups = [str(g.name) for g in Group.objects.all()] print groups completer = MyCompleter(groups) readline.set_completer(completer.complete) readline.parse_and_bind('tab: complete') while True: gname = raw_input("Add group (tab to autocomplete, empty line to end): ") if not gname: break if gname not in groups: print "Unknown group %s" % gname continue g = Group.objects.get(name=gname) user.groups.add(g) print "Added %s to group %s" % (user, g) print "Done!"
class TestActivateAccount(TestCase): """Tests for account creation""" def setUp(self): super(TestActivateAccount, self).setUp() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = UserFactory.create( username=self.username, email=self.email, password=self.password, is_active=False, ) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() self.platform_name = configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) self.activation_email_support_link = configuration_helpers.get_value( 'ACTIVATION_EMAIL_SUPPORT_LINK', settings.ACTIVATION_EMAIL_SUPPORT_LINK ) or settings.SUPPORT_SITE_LINK def login(self): """ Login with test user. Since, only active users can login, so we must activate the user before login. This method does the following tasks in order, 1. Stores user's active/in-active status in a variable. 2. Makes sure user account is active. 3. Authenticated user with the client. 4. Reverts user's original active/in-active status. """ is_active = self.user.is_active # Make sure user is active before login self.user.is_active = True self.user.save() self.client.login(username=self.username, password=self.password) # Revert user activation status self.user.is_active = is_active self.user.save() def assert_no_tracking(self, mock_segment_identify): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) self.assertFalse(mock_segment_identify.called) @override_settings( LMS_SEGMENT_KEY="testkey", MAILCHIMP_NEW_USER_LIST_ID="listid" ) @patch('student.models.analytics.identify') def test_activation_with_keys(self, mock_segment_identify): expected_segment_payload = { 'email': self.email, 'username': self.username, 'activated': 1, } expected_segment_mailchimp_list = { "MailChimp": { "listId": settings.MAILCHIMP_NEW_USER_LIST_ID } } # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) mock_segment_identify.assert_called_with( self.user.id, expected_segment_payload, expected_segment_mailchimp_list ) @override_settings(LMS_SEGMENT_KEY="testkey") @patch('student.models.analytics.identify') def test_activation_without_mailchimp_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @override_settings(MAILCHIMP_NEW_USER_LIST_ID="listid") @patch('student.models.analytics.identify') def test_activation_without_segment_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @patch('student.models.analytics.identify') def test_activation_without_keys(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @override_settings(FEATURES=dict(settings.FEATURES, DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR=True)) def test_account_activation_message(self): """ Verify that account correct activation message is displayed. If logged in user has not activated his/her account, make sure that an account activation message is displayed on dashboard sidebar. """ # Log in with test user. self.login() expected_message = render_to_string( 'registration/account_activation_sidebar_notice.html', { 'email': self.user.email, 'platform_name': self.platform_name, 'activation_email_support_link': self.activation_email_support_link } ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message, html=True) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() expected_message = render_to_string( 'registration/account_activation_sidebar_notice.html', { 'email': self.user.email, 'platform_name': self.platform_name, 'activation_email_support_link': self.activation_email_support_link } ) response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message, html=True) @override_settings(FEATURES=dict(settings.FEATURES, DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR=False)) def test_account_activation_message_disabled(self): """ Verify that old account activation message is displayed when DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR is disabled. """ # Log in with test user. self.login() expected_message = render_to_string( 'registration/activate_account_notice.html', {'email': self.user.email} ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message, html=True) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() expected_message = render_to_string( 'registration/activate_account_notice.html', {'email': self.user.email} ) response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message, html=True) def test_account_activation_notification_on_logistration(self): """ Verify that logistration page displays success/error/info messages about account activation. """ login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) # Access activation link, message should say that account has been activated. response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Success! You have activated your account.') # Access activation link again, message should say that account is already active. response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'This account has already been activated.') # Open account activation page with an invalid activation link, # there should be an error message displayed. response = self.client.get(reverse('activate', args=[uuid4().hex]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Your account could not be activated')
class EmailMarketingTests(TestCase): """ Tests for the EmailMarketing signals and tasks classes. """ shard = 4 def setUp(self): update_email_marketing_config(enabled=False) self.request_factory = RequestFactory() self.user = UserFactory.create(username='******', email=TEST_EMAIL) self.registration = Registration() self.registration.register(self.user) self.request = self.request_factory.get("foo") update_email_marketing_config(enabled=True) # create some test course objects self.course_id_string = 'edX/toy/2012_Fall' self.course_id = CourseKey.from_string(self.course_id_string) self.course_url = 'http://testserver/courses/edX/toy/2012_Fall/info' self.site = Site.objects.get_current() self.site_domain = self.site.domain self.request.site = self.site super(EmailMarketingTests, self).setUp() @freeze_time(datetime.datetime.now()) @patch('email_marketing.signals.crum.get_current_request') @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_drop_cookie(self, mock_sailthru, mock_get_current_request): """ Test add_email_marketing_cookies """ response = JsonResponse({ "success": True, "redirect_url": 'test.com/test', }) self.request.COOKIES['anonymous_interest'] = 'cookie_content' mock_get_current_request.return_value = self.request cookies = {'cookie': 'test_cookie'} mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': cookies})) with LogCapture(LOGGER_NAME, level=logging.INFO) as logger: add_email_marketing_cookies(None, response=response, user=self.user) logger.check( (LOGGER_NAME, 'INFO', 'Started at {start} and ended at {end}, time spent:{delta} milliseconds'.format( start=datetime.datetime.now().isoformat(' '), end=datetime.datetime.now().isoformat(' '), delta=0) ), (LOGGER_NAME, 'INFO', 'sailthru_hid cookie:{cookies[cookie]} successfully retrieved for user {user}'.format( cookies=cookies, user=TEST_EMAIL) ) ) mock_sailthru.assert_called_with('user', {'fields': {'keys': 1}, 'cookies': {'anonymous_interest': 'cookie_content'}, 'id': TEST_EMAIL, 'vars': {'last_login_date': ANY}}) self.assertTrue('sailthru_hid' in response.cookies) self.assertEquals(response.cookies['sailthru_hid'].value, "test_cookie") @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_get_cookies_via_sailthu(self, mock_sailthru): cookies = {'cookie': 'test_cookie'} mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': cookies})) post_parms = { 'id': self.user.email, 'fields': {'keys': 1}, 'vars': {'last_login_date': datetime.datetime.now().strftime("%Y-%m-%d")}, 'cookies': {'anonymous_interest': 'cookie_content'} } expected_cookie = get_email_cookies_via_sailthru.delay(self.user.email, post_parms) mock_sailthru.assert_called_with('user', {'fields': {'keys': 1}, 'cookies': {'anonymous_interest': 'cookie_content'}, 'id': TEST_EMAIL, 'vars': {'last_login_date': ANY}}) self.assertEqual(cookies['cookie'], expected_cookie.result) @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_drop_cookie_error_path(self, mock_sailthru): """ test that error paths return no cookie """ response = JsonResponse({ "success": True, "redirect_url": 'test.com/test', }) mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': {'cookiexx': 'test_cookie'}})) add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': "error", "errormsg": "errormsg"})) add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) mock_sailthru.side_effect = SailthruClientError add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') @patch('email_marketing.tasks.SailthruClient.api_get') def test_add_user(self, mock_sailthru_get, mock_sailthru_post, mock_log_error): """ test async method in tasks that actually updates Sailthru """ site_dict = {'id': self.site.id, 'domain': self.site.domain, 'name': self.site.name} mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) mock_sailthru_get.return_value = SailthruResponse(JsonResponse({'lists': [{'name': 'new list'}], 'ok': True})) update_user.delay( {'gender': 'm', 'username': '******', 'activated': 1}, TEST_EMAIL, site_dict, new_user=True ) self.assertFalse(mock_log_error.called) self.assertEquals(mock_sailthru_post.call_args[0][0], "user") userparms = mock_sailthru_post.call_args[0][1] self.assertEquals(userparms['key'], "email") self.assertEquals(userparms['id'], TEST_EMAIL) self.assertEquals(userparms['vars']['gender'], "m") self.assertEquals(userparms['vars']['username'], "test") self.assertEquals(userparms['vars']['activated'], 1) self.assertEquals(userparms['lists']['new list'], 1) @patch('lms.djangoapps.email_marketing.signals.get_email_cookies_via_sailthru.delay') def test_drop_cookie_task_error(self, mock_email_cookies): """ Tests that task error is handled """ mock_email_cookies.return_value = {} mock_email_cookies.get.side_effect = Exception with LogCapture(LOGGER_NAME, level=logging.INFO) as logger: add_email_marketing_cookies(None, response=None, user=self.user) logger.check(( LOGGER_NAME, 'ERROR', 'Exception Connecting to celery task for {}'.format( self.user.email ) )) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') @patch('email_marketing.tasks.SailthruClient.api_get') def test_email_not_sent_to_white_label(self, mock_sailthru_get, mock_sailthru_post, mock_log_error): """ tests that welcome email is not sent to the white-label site learner """ white_label_site = Site.objects.create(domain='testwhitelabel.com', name='White Label') site_dict = {'id': white_label_site.id, 'domain': white_label_site.domain, 'name': white_label_site.name} mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) mock_sailthru_get.return_value = SailthruResponse(JsonResponse({'lists': [{'name': 'new list'}], 'ok': True})) update_user.delay( {'gender': 'm', 'username': '******', 'activated': 1}, TEST_EMAIL, site_dict, new_user=True ) self.assertFalse(mock_log_error.called) self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send") @patch('email_marketing.tasks.SailthruClient.api_post') def test_email_not_sent_to_enterprise_learners(self, mock_sailthru_post): """ tests that welcome email is not sent to the enterprise learner """ mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) update_user.delay( sailthru_vars={ 'is_enterprise_learner': True, 'enterprise_name': 'test name', }, email=self.user.email ) self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send") @patch('email_marketing.tasks.SailthruClient.api_post') @patch('email_marketing.tasks.SailthruClient.api_get') def test_add_user_list_existing_domain(self, mock_sailthru_get, mock_sailthru_post): """ test non existing domain name updates Sailthru user lists with default list """ existing_site = Site.objects.create(domain='testing.com', name='testing.com') site_dict = {'id': existing_site.id, 'domain': existing_site.domain, 'name': existing_site.name} mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) mock_sailthru_get.return_value = SailthruResponse( JsonResponse({'lists': [{'name': 'new list'}, {'name': 'testing_com_user_list'}], 'ok': True}) ) update_user.delay( {'gender': 'm', 'username': '******', 'activated': 1}, TEST_EMAIL, site=site_dict, new_user=True ) self.assertEquals(mock_sailthru_post.call_args[0][0], "user") userparms = mock_sailthru_post.call_args[0][1] self.assertEquals(userparms['lists']['testing_com_user_list'], 1) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_logging(self, mock_sailthru, mock_log_error): """ Ensure that error returned from Sailthru api is logged """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) # force Sailthru API exception mock_log_error.reset_mock() mock_sailthru.side_effect = SailthruClientError update_user.delay({}, self.user.email, self.site_domain) self.assertTrue(mock_log_error.called) # force Sailthru API exception on 2nd call mock_log_error.reset_mock() mock_sailthru.side_effect = [SailthruResponse(JsonResponse({'ok': True})), SailthruClientError] update_user.delay({}, self.user.email, activation=True) self.assertTrue(mock_log_error.called) # force Sailthru API error return on 2nd call mock_log_error.reset_mock() mock_sailthru.side_effect = [SailthruResponse(JsonResponse({'ok': True})), SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'}))] update_user.delay({}, self.user.email, activation=True) self.assertTrue(mock_log_error.called) @patch('email_marketing.tasks.update_user.retry') @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_retryable(self, mock_sailthru, mock_log_error, mock_retry): """ Ensure that retryable error is retried """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) self.assertTrue(mock_retry.called) @patch('email_marketing.tasks.update_user.retry') @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_nonretryable(self, mock_sailthru, mock_log_error, mock_retry): """ Ensure that non-retryable error is not retried """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 1, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) self.assertFalse(mock_retry.called) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_just_return_tasks(self, mock_sailthru, mock_log_error): """ Ensure that disabling Sailthru just returns """ update_email_marketing_config(enabled=False) update_user.delay(self.user.username) self.assertFalse(mock_log_error.called) self.assertFalse(mock_sailthru.called) update_user_email.delay(self.user.username, "*****@*****.**") self.assertFalse(mock_log_error.called) self.assertFalse(mock_sailthru.called) update_email_marketing_config(enabled=True) @patch('email_marketing.signals.log.error') def test_just_return_signals(self, mock_log_error): """ Ensure that disabling Sailthru just returns """ update_email_marketing_config(enabled=False) add_email_marketing_cookies(None) self.assertFalse(mock_log_error.called) email_marketing_register_user(None, None, None) self.assertFalse(mock_log_error.called) update_email_marketing_config(enabled=True) # test anonymous users anon = AnonymousUser() email_marketing_register_user(None, anon, None) self.assertFalse(mock_log_error.called) email_marketing_user_field_changed(None, user=anon) self.assertFalse(mock_log_error.called) @patch('email_marketing.tasks.SailthruClient.api_post') def test_change_email(self, mock_sailthru): """ test async method in task that changes email in Sailthru """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'ok': True})) update_user_email.delay(TEST_EMAIL, "*****@*****.**") self.assertEquals(mock_sailthru.call_args[0][0], "user") userparms = mock_sailthru.call_args[0][1] self.assertEquals(userparms['key'], "email") self.assertEquals(userparms['id'], "*****@*****.**") self.assertEquals(userparms['keys']['email'], TEST_EMAIL) @patch('email_marketing.tasks.SailthruClient') def test_get_or_create_sailthru_list(self, mock_sailthru_client): """ Test the task the create sailthru lists. """ mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) _get_or_create_user_list(mock_sailthru_client, 'test1_user_list') mock_sailthru_client.api_get.assert_called_with("list", {}) mock_sailthru_client.api_post.assert_called_with( "list", {'list': 'test1_user_list', 'primary': 0, 'public_name': 'test1_user_list'} ) # test existing user list mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'lists': [{'name': 'test1_user_list'}]})) _get_or_create_user_list(mock_sailthru_client, 'test2_user_list') mock_sailthru_client.api_get.assert_called_with("list", {}) mock_sailthru_client.api_post.assert_called_with( "list", {'list': 'test2_user_list', 'primary': 0, 'public_name': 'test2_user_list'} ) # test get error from Sailthru mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) self.assertEqual(_get_or_create_user_list( mock_sailthru_client, 'test1_user_list'), None ) # test post error from Sailthru mock_sailthru_client.api_post.return_value = \ SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) self.assertEqual(_get_or_create_user_list(mock_sailthru_client, 'test2_user_list'), None) @patch('email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_no_list(self, mock_sailthru_client): """Test when no list returned from sailthru""" mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) mock_sailthru_client.api_get.assert_called_with("list", {}) @patch('email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_error(self, mock_sailthru_client): """Test when error occurred while fetching data from sailthru""" mock_sailthru_client.api_get.return_value = SailthruResponse( JsonResponse({'error': 43, 'errormsg': 'Got an error'}) ) self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) @patch('email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_exception(self, mock_sailthru_client): """Test when exception raised while fetching data from sailthru""" mock_sailthru_client.api_get.side_effect = SailthruClientError self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) @patch('email_marketing.tasks.SailthruClient') def test_get_sailthru_list(self, mock_sailthru_client): """Test fetch list data from sailthru""" mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'lists': [{'name': 'test1_user_list'}]})) self.assertEqual( _get_list_from_email_marketing_provider(mock_sailthru_client), {'test1_user_list': {'name': 'test1_user_list'}} ) mock_sailthru_client.api_get.assert_called_with("list", {}) @patch('email_marketing.tasks.SailthruClient') def test_create_sailthru_list(self, mock_sailthru_client): """Test create list in sailthru""" mock_sailthru_client.api_post.return_value = SailthruResponse(JsonResponse({'ok': True})) self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), True) self.assertEquals(mock_sailthru_client.api_post.call_args[0][0], "list") listparms = mock_sailthru_client.api_post.call_args[0][1] self.assertEqual(listparms['list'], 'test_list_name') self.assertEqual(listparms['primary'], 0) self.assertEqual(listparms['public_name'], 'test_list_name') @patch('email_marketing.tasks.SailthruClient') def test_create_sailthru_list_error(self, mock_sailthru_client): """Test error occurrence while creating sailthru list""" mock_sailthru_client.api_post.return_value = SailthruResponse( JsonResponse({'error': 43, 'errormsg': 'Got an error'}) ) self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False) @patch('email_marketing.tasks.SailthruClient') def test_create_sailthru_list_exception(self, mock_sailthru_client): """Test exception raised while creating sailthru list""" mock_sailthru_client.api_post.side_effect = SailthruClientError self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_error_logging(self, mock_sailthru, mock_log_error): """ Ensure that error returned from Sailthru api is logged """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'})) update_user_email.delay(self.user.username, "*****@*****.**") self.assertTrue(mock_log_error.called) mock_sailthru.side_effect = SailthruClientError update_user_email.delay(self.user.username, "*****@*****.**") self.assertTrue(mock_log_error.called) @patch('email_marketing.signals.crum.get_current_request') @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user(self, mock_update_user, mock_get_current_request): """ make sure register user call invokes update_user and includes activation_key """ mock_get_current_request.return_value = self.request email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertTrue(mock_update_user.called) self.assertEqual(mock_update_user.call_args[0][0]['activation_key'], self.registration.activation_key) self.assertLessEqual(mock_update_user.call_args[0][0]['signupNumber'], 9) @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user_no_request(self, mock_update_user): """ make sure register user call invokes update_user and includes activation_key """ email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertTrue(mock_update_user.called) self.assertEqual(mock_update_user.call_args[0][0]['activation_key'], self.registration.activation_key) @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user_language_preference(self, mock_update_user): """ make sure register user call invokes update_user and includes language preference """ # If the user hasn't set an explicit language preference, we should send the application's default. self.assertIsNone(self.user.preferences.model.get_value(self.user, LANGUAGE_KEY)) email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], settings.LANGUAGE_CODE) # If the user has set an explicit language preference, we should send it. self.user.preferences.create(key=LANGUAGE_KEY, value='es-419') email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'es-419') @patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False}) @patch('email_marketing.signals.crum.get_current_request') @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') @ddt.data(('auth_userprofile', 'gender', 'f', True), ('auth_user', 'is_active', 1, True), ('auth_userprofile', 'shoe_size', 1, False), ('user_api_userpreference', 'pref-lang', 'en', True)) @ddt.unpack def test_modify_field(self, table, setting, value, result, mock_update_user, mock_get_current_request): """ Test that correct fields call update_user """ mock_get_current_request.return_value = self.request email_marketing_user_field_changed(None, self.user, table=table, setting=setting, new_value=value) self.assertEqual(mock_update_user.called, result) @patch('email_marketing.tasks.SailthruClient.api_post') @patch('email_marketing.signals.third_party_auth.provider.Registry.get_from_pipeline') @patch('email_marketing.signals.third_party_auth.pipeline.get') @patch('email_marketing.signals.crum.get_current_request') @ddt.data(True, False) def test_modify_field_with_sso(self, send_welcome_email, mock_get_current_request, mock_pipeline_get, mock_registry_get_from_pipeline, mock_sailthru_post): """ Test that welcome email is sent appropriately in the context of SSO registration """ mock_get_current_request.return_value = self.request mock_pipeline_get.return_value = 'saml-idp' mock_registry_get_from_pipeline.return_value = Mock(send_welcome_email=send_welcome_email) mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) email_marketing_user_field_changed(None, self.user, table='auth_user', setting='is_active', new_value=True) if send_welcome_email: self.assertEqual(mock_sailthru_post.call_args[0][0], "send") else: self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send") @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_modify_language_preference(self, mock_update_user): """ Test that update_user is called with new language preference """ # If the user hasn't set an explicit language preference, we should send the application's default. self.assertIsNone(self.user.preferences.model.get_value(self.user, LANGUAGE_KEY)) email_marketing_user_field_changed( None, self.user, table='user_api_userpreference', setting=LANGUAGE_KEY, new_value=None ) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], settings.LANGUAGE_CODE) # If the user has set an explicit language preference, we should send it. self.user.preferences.create(key=LANGUAGE_KEY, value='fr') email_marketing_user_field_changed( None, self.user, table='user_api_userpreference', setting=LANGUAGE_KEY, new_value='fr' ) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'fr') @patch('lms.djangoapps.email_marketing.tasks.update_user_email.delay') def test_modify_email(self, mock_update_user): """ Test that change to email calls update_user_email """ email_marketing_user_field_changed(None, self.user, table='auth_user', setting='email', old_value='*****@*****.**') mock_update_user.assert_called_with(self.user.email, '*****@*****.**') # make sure nothing called if disabled mock_update_user.reset_mock() update_email_marketing_config(enabled=False) email_marketing_user_field_changed(None, self.user, table='auth_user', setting='email', old_value='*****@*****.**') self.assertFalse(mock_update_user.called) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_sailthru_on_success(self, mock_sailthru, mock_log_error): """ Ensure that a successful unsubscribe does not trigger an error log """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'ok': True})) force_unsubscribe_all(sender=self.__class__, email=self.user.email) self.assertTrue(mock_sailthru.called) self.assertFalse(mock_log_error.called) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_sailthru_on_connection_error(self, mock_sailthru, mock_log_error): mock_sailthru.side_effect = SailthruClientError with self.assertRaises(Exception): force_unsubscribe_all(sender=self.__class__, email=self.user.email) self.assertTrue(mock_log_error.called) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_sailthru_on_bad_response(self, mock_sailthru, mock_log_error): mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'})) with self.assertRaises(Exception): force_unsubscribe_all(sender=self.__class__, email=self.user.email) self.assertTrue(mock_sailthru.called) self.assertTrue(mock_log_error.called) @patch('email_marketing.tasks.log.error') @patch('email_marketing.tasks.SailthruClient.api_post') def test_sailthru_with_email_changed(self, mock_sailthru, mock_log_error): mock_sailthru.return_value = SailthruResponse(JsonResponse({'ok': True})) force_unsubscribe_all(sender=self.__class__, email=self.user.email, new_email='*****@*****.**') mock_sailthru.assert_called_with("user", { "id": self.user.email, "optout_email": "all", "keys": { "email": "*****@*****.**" }, "fields": { "optout_email": 1, "keys": 1 }, "keysconflict": "merge" }) self.assertFalse(mock_log_error.called)
class EmailMarketingTests(TestCase): """ Tests for the EmailMarketing signals and tasks classes. """ def setUp(self): update_email_marketing_config(enabled=False) self.request_factory = RequestFactory() self.user = UserFactory.create(username='******', email=TEST_EMAIL) self.registration = Registration() self.registration.register(self.user) self.request = self.request_factory.get("foo") update_email_marketing_config(enabled=True) # create some test course objects self.course_id_string = 'edX/toy/2012_Fall' self.course_id = CourseKey.from_string(self.course_id_string) self.course_url = 'http://testserver/courses/edX/toy/2012_Fall/info' self.site = Site.objects.get_current() self.request.site = self.site super(EmailMarketingTests, self).setUp() @freeze_time(datetime.datetime.now()) @patch('lms.djangoapps.email_marketing.signals.crum.get_current_request') @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_drop_cookie(self, mock_sailthru, mock_get_current_request): """ Test add_email_marketing_cookies """ response = JsonResponse({ "success": True, "redirect_url": 'test.com/test', }) self.request.COOKIES['anonymous_interest'] = 'cookie_content' mock_get_current_request.return_value = self.request cookies = {'cookie': 'test_cookie'} mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': cookies})) with LogCapture(LOGGER_NAME, level=logging.INFO) as logger: add_email_marketing_cookies(None, response=response, user=self.user) logger.check( (LOGGER_NAME, 'INFO', 'Started at {start} and ended at {end}, time spent:{delta} milliseconds'.format( start=datetime.datetime.now().isoformat(' '), end=datetime.datetime.now().isoformat(' '), delta=0 if six.PY2 else 0.0) ), (LOGGER_NAME, 'INFO', 'sailthru_hid cookie:{cookies[cookie]} successfully retrieved for user {user}'.format( cookies=cookies, user=TEST_EMAIL) ) ) mock_sailthru.assert_called_with('user', {'fields': {'keys': 1}, 'cookies': {'anonymous_interest': 'cookie_content'}, 'id': TEST_EMAIL, 'vars': {'last_login_date': ANY}}) self.assertTrue('sailthru_hid' in response.cookies) self.assertEqual(response.cookies['sailthru_hid'].value, "test_cookie") @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_get_cookies_via_sailthu(self, mock_sailthru): cookies = {'cookie': 'test_cookie'} mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': cookies})) post_parms = { 'id': self.user.email, 'fields': {'keys': 1}, 'vars': {'last_login_date': datetime.datetime.now().strftime("%Y-%m-%d")}, 'cookies': {'anonymous_interest': 'cookie_content'} } expected_cookie = get_email_cookies_via_sailthru.delay(self.user.email, post_parms) mock_sailthru.assert_called_with('user', {'fields': {'keys': 1}, 'cookies': {'anonymous_interest': 'cookie_content'}, 'id': TEST_EMAIL, 'vars': {'last_login_date': ANY}}) self.assertEqual(cookies['cookie'], expected_cookie.result) @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_drop_cookie_error_path(self, mock_sailthru): """ test that error paths return no cookie """ response = JsonResponse({ "success": True, "redirect_url": 'test.com/test', }) mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': {'cookiexx': 'test_cookie'}})) add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': "error", "errormsg": "errormsg"})) add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) mock_sailthru.side_effect = SailthruClientError add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_get') def test_add_user(self, mock_sailthru_get, mock_sailthru_post, mock_log_error): """ test async method in tasks that actually updates Sailthru """ site_dict = {'id': self.site.id, 'domain': self.site.domain, 'name': self.site.name} mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) mock_sailthru_get.return_value = SailthruResponse(JsonResponse({'lists': [{'name': 'new list'}], 'ok': True})) update_user.delay( {'gender': 'm', 'username': '******', 'activated': 1}, TEST_EMAIL, site_dict, new_user=True ) self.assertFalse(mock_log_error.called) self.assertEqual(mock_sailthru_post.call_args[0][0], "user") userparms = mock_sailthru_post.call_args[0][1] self.assertEqual(userparms['key'], "email") self.assertEqual(userparms['id'], TEST_EMAIL) self.assertEqual(userparms['vars']['gender'], "m") self.assertEqual(userparms['vars']['username'], "test") self.assertEqual(userparms['vars']['activated'], 1) self.assertEqual(userparms['lists']['new list'], 1) @patch('lms.djangoapps.email_marketing.signals.get_email_cookies_via_sailthru.delay') def test_drop_cookie_task_error(self, mock_email_cookies): """ Tests that task error is handled """ mock_email_cookies.return_value = {} mock_email_cookies.get.side_effect = Exception with LogCapture(LOGGER_NAME, level=logging.INFO) as logger: add_email_marketing_cookies(None, response=None, user=self.user) logger.check(( LOGGER_NAME, 'ERROR', 'Exception Connecting to celery task for {}'.format( self.user.email ) )) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_email_not_sent_to_enterprise_learners(self, mock_sailthru_post): """ tests that welcome email is not sent to the enterprise learner """ mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) update_user.delay( sailthru_vars={ 'is_enterprise_learner': True, 'enterprise_name': 'test name', }, email=self.user.email ) self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send") @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_add_user_list_not_called_on_white_label_domain(self, mock_sailthru_post): """ test user is not added to Sailthru user lists if registered from a whitel labe site """ existing_site = Site.objects.create(domain='testwhitelabel.com', name='White Label') site_dict = {'id': existing_site.id, 'domain': existing_site.domain, 'name': existing_site.name} update_user.delay( {'gender': 'm', 'username': '******', 'activated': 1}, TEST_EMAIL, site=site_dict, new_user=True ) self.assertFalse(mock_sailthru_post.called) @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_logging(self, mock_sailthru, mock_log_error): """ Ensure that error returned from Sailthru api is logged """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) # force Sailthru API exception mock_log_error.reset_mock() mock_sailthru.side_effect = SailthruClientError update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) # force Sailthru API exception on 2nd call mock_log_error.reset_mock() mock_sailthru.side_effect = [SailthruResponse(JsonResponse({'ok': True})), SailthruClientError] update_user.delay({}, self.user.email, activation=True) self.assertTrue(mock_log_error.called) # force Sailthru API error return on 2nd call mock_log_error.reset_mock() mock_sailthru.side_effect = [SailthruResponse(JsonResponse({'ok': True})), SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'}))] update_user.delay({}, self.user.email, activation=True) self.assertTrue(mock_log_error.called) @patch('lms.djangoapps.email_marketing.tasks.update_user.retry') @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_retryable(self, mock_sailthru, mock_log_error, mock_retry): """ Ensure that retryable error is retried """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) self.assertTrue(mock_retry.called) @patch('lms.djangoapps.email_marketing.tasks.update_user.retry') @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_nonretryable(self, mock_sailthru, mock_log_error, mock_retry): """ Ensure that non-retryable error is not retried """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 1, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) self.assertFalse(mock_retry.called) @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_just_return_tasks(self, mock_sailthru, mock_log_error): """ Ensure that disabling Sailthru just returns """ update_email_marketing_config(enabled=False) update_user.delay(self.user.username, self.user.email) self.assertFalse(mock_log_error.called) self.assertFalse(mock_sailthru.called) update_user_email.delay(self.user.username, "*****@*****.**") self.assertFalse(mock_log_error.called) self.assertFalse(mock_sailthru.called) update_email_marketing_config(enabled=True) @patch('lms.djangoapps.email_marketing.signals.log.error') def test_just_return_signals(self, mock_log_error): """ Ensure that disabling Sailthru just returns """ update_email_marketing_config(enabled=False) add_email_marketing_cookies(None) self.assertFalse(mock_log_error.called) email_marketing_register_user(None, None, None) self.assertFalse(mock_log_error.called) update_email_marketing_config(enabled=True) # test anonymous users anon = AnonymousUser() email_marketing_register_user(None, anon, None) self.assertFalse(mock_log_error.called) email_marketing_user_field_changed(None, user=anon) self.assertFalse(mock_log_error.called) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_change_email(self, mock_sailthru): """ test async method in task that changes email in Sailthru """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'ok': True})) update_user_email.delay(TEST_EMAIL, "*****@*****.**") self.assertEqual(mock_sailthru.call_args[0][0], "user") userparms = mock_sailthru.call_args[0][1] self.assertEqual(userparms['key'], "email") self.assertEqual(userparms['id'], "*****@*****.**") self.assertEqual(userparms['keys']['email'], TEST_EMAIL) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_or_create_sailthru_list(self, mock_sailthru_client): """ Test the task the create sailthru lists. """ mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) _get_or_create_user_list(mock_sailthru_client, 'test1_user_list') mock_sailthru_client.api_get.assert_called_with("list", {}) mock_sailthru_client.api_post.assert_called_with( "list", {'list': 'test1_user_list', 'primary': 0, 'public_name': 'test1_user_list'} ) # test existing user list mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'lists': [{'name': 'test1_user_list'}]})) _get_or_create_user_list(mock_sailthru_client, 'test2_user_list') mock_sailthru_client.api_get.assert_called_with("list", {}) mock_sailthru_client.api_post.assert_called_with( "list", {'list': 'test2_user_list', 'primary': 0, 'public_name': 'test2_user_list'} ) # test get error from Sailthru mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) self.assertEqual(_get_or_create_user_list( mock_sailthru_client, 'test1_user_list'), None ) # test post error from Sailthru mock_sailthru_client.api_post.return_value = \ SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) self.assertEqual(_get_or_create_user_list(mock_sailthru_client, 'test2_user_list'), None) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_no_list(self, mock_sailthru_client): """Test when no list returned from sailthru""" mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) mock_sailthru_client.api_get.assert_called_with("list", {}) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_error(self, mock_sailthru_client): """Test when error occurred while fetching data from sailthru""" mock_sailthru_client.api_get.return_value = SailthruResponse( JsonResponse({'error': 43, 'errormsg': 'Got an error'}) ) self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_exception(self, mock_sailthru_client): """Test when exception raised while fetching data from sailthru""" mock_sailthru_client.api_get.side_effect = SailthruClientError self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_sailthru_list(self, mock_sailthru_client): """Test fetch list data from sailthru""" mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'lists': [{'name': 'test1_user_list'}]})) self.assertEqual( _get_list_from_email_marketing_provider(mock_sailthru_client), {'test1_user_list': {'name': 'test1_user_list'}} ) mock_sailthru_client.api_get.assert_called_with("list", {}) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_create_sailthru_list(self, mock_sailthru_client): """Test create list in sailthru""" mock_sailthru_client.api_post.return_value = SailthruResponse(JsonResponse({'ok': True})) self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), True) self.assertEqual(mock_sailthru_client.api_post.call_args[0][0], "list") listparms = mock_sailthru_client.api_post.call_args[0][1] self.assertEqual(listparms['list'], 'test_list_name') self.assertEqual(listparms['primary'], 0) self.assertEqual(listparms['public_name'], 'test_list_name') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_create_sailthru_list_error(self, mock_sailthru_client): """Test error occurrence while creating sailthru list""" mock_sailthru_client.api_post.return_value = SailthruResponse( JsonResponse({'error': 43, 'errormsg': 'Got an error'}) ) self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_create_sailthru_list_exception(self, mock_sailthru_client): """Test exception raised while creating sailthru list""" mock_sailthru_client.api_post.side_effect = SailthruClientError self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False) @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_error_logging(self, mock_sailthru, mock_log_error): """ Ensure that error returned from Sailthru api is logged """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'})) update_user_email.delay(self.user.username, "*****@*****.**") self.assertTrue(mock_log_error.called) mock_sailthru.side_effect = SailthruClientError update_user_email.delay(self.user.username, "*****@*****.**") self.assertTrue(mock_log_error.called) @patch('lms.djangoapps.email_marketing.signals.crum.get_current_request') @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user(self, mock_update_user, mock_get_current_request): """ make sure register user call invokes update_user and includes activation_key """ mock_get_current_request.return_value = self.request email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertTrue(mock_update_user.called) self.assertEqual(mock_update_user.call_args[0][0]['activation_key'], self.registration.activation_key) self.assertLessEqual(mock_update_user.call_args[0][0]['signupNumber'], 9) @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user_no_request(self, mock_update_user): """ make sure register user call invokes update_user and includes activation_key """ email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertTrue(mock_update_user.called) self.assertEqual(mock_update_user.call_args[0][0]['activation_key'], self.registration.activation_key) @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user_language_preference(self, mock_update_user): """ make sure register user call invokes update_user and includes language preference """ # If the user hasn't set an explicit language preference, we should send the application's default. self.assertIsNone(self.user.preferences.model.get_value(self.user, LANGUAGE_KEY)) email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], settings.LANGUAGE_CODE) # If the user has set an explicit language preference, we should send it. self.user.preferences.create(key=LANGUAGE_KEY, value='es-419') email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'es-419') @patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False}) @patch('lms.djangoapps.email_marketing.signals.crum.get_current_request') @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') @ddt.data(('auth_userprofile', 'gender', 'f', True), ('auth_user', 'is_active', 1, True), ('auth_userprofile', 'shoe_size', 1, False), ('user_api_userpreference', 'pref-lang', 'en', True)) @ddt.unpack def test_modify_field(self, table, setting, value, result, mock_update_user, mock_get_current_request): """ Test that correct fields call update_user """ mock_get_current_request.return_value = self.request email_marketing_user_field_changed(None, self.user, table=table, setting=setting, new_value=value) self.assertEqual(mock_update_user.called, result) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') @patch('lms.djangoapps.email_marketing.signals.third_party_auth.provider.Registry.get_from_pipeline') @patch('lms.djangoapps.email_marketing.signals.third_party_auth.pipeline.get') @patch('lms.djangoapps.email_marketing.signals.crum.get_current_request') @ddt.data(True, False) def test_modify_field_with_sso(self, send_welcome_email, mock_get_current_request, mock_pipeline_get, mock_registry_get_from_pipeline, mock_sailthru_post): """ Test that welcome email is sent appropriately in the context of SSO registration """ mock_get_current_request.return_value = self.request mock_pipeline_get.return_value = 'saml-idp' mock_registry_get_from_pipeline.return_value = Mock(send_welcome_email=send_welcome_email) mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) email_marketing_user_field_changed(None, self.user, table='auth_user', setting='is_active', new_value=True) if send_welcome_email: self.assertEqual(mock_sailthru_post.call_args[0][0], "send") else: self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send") @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_modify_language_preference(self, mock_update_user): """ Test that update_user is called with new language preference """ # If the user hasn't set an explicit language preference, we should send the application's default. self.assertIsNone(self.user.preferences.model.get_value(self.user, LANGUAGE_KEY)) email_marketing_user_field_changed( None, self.user, table='user_api_userpreference', setting=LANGUAGE_KEY, new_value=None ) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], settings.LANGUAGE_CODE) # If the user has set an explicit language preference, we should send it. self.user.preferences.create(key=LANGUAGE_KEY, value='fr') email_marketing_user_field_changed( None, self.user, table='user_api_userpreference', setting=LANGUAGE_KEY, new_value='fr' ) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'fr') @patch('lms.djangoapps.email_marketing.tasks.update_user_email.delay') def test_modify_email(self, mock_update_user): """ Test that change to email calls update_user_email """ email_marketing_user_field_changed(None, self.user, table='auth_user', setting='email', old_value='*****@*****.**') mock_update_user.assert_called_with(self.user.email, '*****@*****.**') # make sure nothing called if disabled mock_update_user.reset_mock() update_email_marketing_config(enabled=False) email_marketing_user_field_changed(None, self.user, table='auth_user', setting='email', old_value='*****@*****.**') self.assertFalse(mock_update_user.called)
def handle(self, *args, **options): while True: uname = raw_input('username: '******'Create MIT ExternalAuth? [n] ').lower() == 'y': email = '*****@*****.**' % uname if not email.endswith('@MIT.EDU'): print "Failed - email must be @MIT.EDU" sys.exit(-1) mit_domain = 'ssl:MIT' if ExternalAuthMap.objects.filter(external_id=email, external_domain=mit_domain): print "Failed - email %s already exists as external_id" % email sys.exit(-1) make_eamap = True password = GenPasswd(12) # get name from kerberos try: kname = os.popen("finger %s | grep 'name:'" % email).read().strip().split('name: ')[1].strip() except: kname = '' name = raw_input('Full name: [%s] ' % kname).strip() if name == '': name = kname print "name = %s" % name else: while True: password = getpass() password2 = getpass() if password == password2: break print "Oops, passwords do not match, please retry" while True: email = raw_input('email: ') if User.objects.filter(email=email): print "email %s already taken" % email else: break name = raw_input('Full name: ') user = User(username=uname, email=email, is_active=True) user.set_password(password) try: user.save() except IntegrityError: print "Oops, failed to create user %s, IntegrityError" % user raise r = Registration() r.register(user) up = UserProfile(user=user) up.name = name up.save() if make_eamap: credentials = "/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN=%s/emailAddress=%s" % (name, email) eamap = ExternalAuthMap(external_id=email, external_email=email, external_domain=mit_domain, external_name=name, internal_password=password, external_credentials=json.dumps(credentials), ) eamap.user = user eamap.dtsignup = datetime.datetime.now(UTC) eamap.save() print "User %s created successfully!" % user if not raw_input('Add user %s to any groups? [n] ' % user).lower() == 'y': sys.exit(0) print "Here are the groups available:" groups = [str(g.name) for g in Group.objects.all()] print groups completer = MyCompleter(groups) readline.set_completer(completer.complete) readline.parse_and_bind('tab: complete') while True: gname = raw_input("Add group (tab to autocomplete, empty line to end): ") if not gname: break if not gname in groups: print "Unknown group %s" % gname continue g = Group.objects.get(name=gname) user.groups.add(g) print "Added %s to group %s" % (user, g) print "Done!"
def _do_cme_create_account(post_vars): """ Given cleaned post variables, create the User, UserProfile and CmeUserProfile objects, as well as the registration for this user. Returns a tuple (User, CmeUserProfile, Registration). Since CmeUserProfile is implemented using multi-table inheritence of UserProfile, the CmeUserProfile object will also contain all the UserProfile fields. """ user = User(username=post_vars['username'], email=post_vars['email'], is_active=False) user.set_password(post_vars['password']) registration = Registration() # @todo: Rearrange so that if part of the process fails, the whole process fails. # Right now, we can have e.g. no registration e-mail sent out and a zombie account try: user.save() except IntegrityError: json_string = {'success': False} # Figure out the cause of the integrity error if len(User.objects.filter(username=post_vars['username'])) > 0: json_string['value'] = "An account with the Public Username '" + post_vars['username'] + "' already exists." json_string['field'] = 'username' return HttpResponse(json.dumps(json_string)) if len(User.objects.filter(email=post_vars['email'])) > 0: json_string['value'] = "An account with the Email '" + post_vars['email'] + "' already exists." json_string['field'] = 'email' return HttpResponse(json.dumps(json_string)) registration.register(user) cme_user_profile = CmeUserProfile(user=user) #UserProfile fields cme_user_profile.name = post_vars['name'] cme_user_profile.gender = post_vars.get('gender') #CmeUserProfile fields cme_user_profile.last_name = post_vars['last_name'] cme_user_profile.first_name = post_vars['first_name'] cme_user_profile.middle_initial = post_vars.get('middle_initial') cme_user_profile.birth_date = post_vars['birth_date'] cme_user_profile.professional_designation = post_vars.get('professional_designation') cme_user_profile.license_number = post_vars.get('license_number') cme_user_profile.license_country = post_vars.get('license_country') cme_user_profile.license_state = post_vars.get('license_state') cme_user_profile.physician_status = post_vars.get('physician_status') cme_user_profile.patient_population = post_vars.get('patient_population') if post_vars.get('specialty') == 'Other': cme_user_profile.specialty = post_vars.get('specialty_free') else: cme_user_profile.specialty = post_vars.get('specialty') if post_vars.get('sub_specialty') == 'Other': cme_user_profile.sub_specialty = post_vars.get('sub_specialty_free') else: cme_user_profile.sub_specialty = post_vars.get('sub_specialty') cme_user_profile.affiliation = post_vars.get('affiliation') if post_vars.get('affiliation') == 'Other': cme_user_profile.other_affiliation = post_vars.get('other_affiliation') else: cme_user_profile.other_affiliation = None cme_user_profile.sub_affiliation = post_vars.get('sub_affiliation') cme_user_profile.sunet_id = post_vars.get('sunet_id') cme_user_profile.stanford_department = post_vars.get('stanford_department') cme_user_profile.address_1 = post_vars.get('address_1') cme_user_profile.address_2 = post_vars.get('address_2') cme_user_profile.city_cme = post_vars.get('city') cme_user_profile.state = post_vars.get('state') cme_user_profile.county_province = post_vars.get('county_province') cme_user_profile.postal_code = post_vars.get('postal_code') cme_user_profile.country_cme = post_vars.get('country') try: cme_user_profile.save() except Exception: print "Could not create cme_user_profile" log.exception("UserProfile creation failed for user {0}.".format(user.email)) return (user, cme_user_profile, registration)
def create_user(self, uname, name, password=None): """ Creates a user (both SSL and regular)""" if not uname: return _('Must provide username') if not name: return _('Must provide full name') email_domain = getattr(settings, 'SSL_AUTH_EMAIL_DOMAIN', 'MIT.EDU') msg = u'' if settings.FEATURES['AUTH_USE_CERTIFICATES']: if not '@' in uname: email = '{0}@{1}'.format(uname, email_domain) else: email = uname if not email.endswith('@{0}'.format(email_domain)): msg += u'{0} @{1}'.format(_('email must end in'), email_domain) return msg mit_domain = 'ssl:MIT' if ExternalAuthMap.objects.filter(external_id=email, external_domain=mit_domain): msg += _('Failed - email {0} already exists as ' 'external_id').format(email) return msg new_password = generate_password() else: if not password: return _('Password must be supplied if not using certificates') email = uname if not '@' in email: msg += _('email address required (not username)') return msg new_password = password user = User(username=uname, email=email, is_active=True) user.set_password(new_password) try: user.save() except IntegrityError: msg += _('Oops, failed to create user {0}, ' 'IntegrityError').format(user) return msg reg = Registration() reg.register(user) profile = UserProfile(user=user) profile.name = name profile.save() if settings.FEATURES['AUTH_USE_CERTIFICATES']: credential_string = getattr( settings, 'SSL_AUTH_DN_FORMAT_STRING', '/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}' ) credentials = credential_string.format(name, email) eamap = ExternalAuthMap( external_id=email, external_email=email, external_domain=mit_domain, external_name=name, internal_password=new_password, external_credentials=json.dumps(credentials), ) eamap.user = user eamap.dtsignup = timezone.now() eamap.save() msg += _('User {0} created successfully!').format(user) return msg
class TestActivateAccount(TestCase): """Tests for account creation""" def setUp(self): super(TestActivateAccount, self).setUp() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = UserFactory.create( username=self.username, email=self.email, password=self.password, is_active=False, ) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() self.platform_name = configuration_helpers.get_value( 'PLATFORM_NAME', settings.PLATFORM_NAME) self.activation_email_support_link = configuration_helpers.get_value( 'ACTIVATION_EMAIL_SUPPORT_LINK', settings. ACTIVATION_EMAIL_SUPPORT_LINK) or settings.SUPPORT_SITE_LINK def login(self): """ Login with test user. Since, only active users can login, so we must activate the user before login. This method does the following tasks in order, 1. Stores user's active/in-active status in a variable. 2. Makes sure user account is active. 3. Authenticated user with the client. 4. Reverts user's original active/in-active status. """ is_active = self.user.is_active # Make sure user is active before login self.user.is_active = True self.user.save() self.client.login(username=self.username, password=self.password) # Revert user activation status self.user.is_active = is_active self.user.save() def assert_no_tracking(self, mock_segment_identify): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) self.assertFalse(mock_segment_identify.called) @patch('student.models.USER_ACCOUNT_ACTIVATED') def test_activation_signal(self, mock_signal): """ Verify that USER_ACCOUNT_ACTIVATED is emitted upon account email activation. """ assert not self.user.is_active, 'Ensure that the user starts inactive' assert not mock_signal.send_robust.call_count, 'Ensure no signal is fired before activation' self.registration.activate() # Until you explicitly activate it assert self.user.is_active, 'Sanity check for .activate()' mock_signal.send_robust.assert_called_once_with( Registration, user=self.user) # Ensure the signal is emitted def test_account_activation_message(self): """ Verify that account correct activation message is displayed. If logged in user has not activated his/her account, make sure that an account activation message is displayed on dashboard sidebar. """ # Log in with test user. self.login() expected_message = ( u"Check your {email_start}{email}{email_end} inbox for an account activation link from " u"{platform_name}. If you need help, contact {link_start}{platform_name} Support{link_end}." ).format( platform_name=self.platform_name, email_start="<strong>", email_end="</strong>", email=self.user.email, link_start= "<a target='_blank' href='{activation_email_support_link}'>". format(activation_email_support_link=self. activation_email_support_link, ), link_end="</a>", ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message) def _assert_user_active_state(self, expected_active_state): user = User.objects.get(username=self.user.username) self.assertEqual(user.is_active, expected_active_state) def test_account_activation_notification_on_logistration(self): """ Verify that logistration page displays success/error/info messages about account activation. """ login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) self._assert_user_active_state(expected_active_state=False) # Access activation link, message should say that account has been activated. response = self.client.get(reverse( 'activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Success! You have activated your account.') self._assert_user_active_state(expected_active_state=True) # Access activation link again, message should say that account is already active. response = self.client.get(reverse( 'activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'This account has already been activated.') self._assert_user_active_state(expected_active_state=True) # Open account activation page with an invalid activation link, # there should be an error message displayed. response = self.client.get(reverse('activate', args=[uuid4().hex]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Your account could not be activated')
def create_account(username, password, email): """Create a new user account. This will implicitly create an empty profile for the user. WARNING: This function does NOT yet implement all the features in `student/views.py`. Until it does, please use this method ONLY for tests of the account API, not in production code. In particular, these are currently missing: * 3rd party auth * External auth (shibboleth) * Complex password policies (ENFORCE_PASSWORD_POLICY) In addition, we assume that some functionality is handled at higher layers: * Analytics events * Activation email * Terms of service / honor code checking * Recording demographic info (use profile API) * Auto-enrollment in courses (if invited via instructor dash) Args: username (unicode): The username for the new account. password (unicode): The user's password. email (unicode): The email address associated with the account. Returns: unicode: an activation key for the account. Raises: errors.AccountUserAlreadyExists errors.AccountUsernameInvalid errors.AccountEmailInvalid errors.AccountPasswordInvalid errors.UserAPIInternalError: the operation failed due to an unexpected error. """ # Check if ALLOW_PUBLIC_ACCOUNT_CREATION flag turned off to restrict user account creation if not configuration_helpers.get_value( 'ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION', True)): return HttpResponseForbidden(_("Account creation not allowed.")) if waffle().is_enabled(PREVENT_AUTH_USER_WRITES): raise errors.UserAPIInternalError(SYSTEM_MAINTENANCE_MSG) # Validate the username, password, and email # This will raise an exception if any of these are not in a valid format. _validate_username(username) _validate_password(password, username) _validate_email(email) # Create the user account, setting them to "inactive" until they activate their account. user = User(username=username, email=email, is_active=False) user.set_password(password) try: user.save() except IntegrityError: raise errors.AccountUserAlreadyExists # Create a registration to track the activation process # This implicitly saves the registration. registration = Registration() registration.register(user) # Create an empty user profile with default values UserProfile(user=user).save() # Return the activation key, which the caller should send to the user return registration.activation_key
class TestActivateAccount(TestCase): """Tests for account creation""" def setUp(self): super(TestActivateAccount, self).setUp() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = UserFactory.create( username=self.username, email=self.email, password=self.password, is_active=False, ) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() self.platform_name = configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) self.activation_email_support_link = configuration_helpers.get_value( 'ACTIVATION_EMAIL_SUPPORT_LINK', settings.ACTIVATION_EMAIL_SUPPORT_LINK ) or settings.SUPPORT_SITE_LINK def login(self): """ Login with test user. Since, only active users can login, so we must activate the user before login. This method does the following tasks in order, 1. Stores user's active/in-active status in a variable. 2. Makes sure user account is active. 3. Authenticated user with the client. 4. Reverts user's original active/in-active status. """ is_active = self.user.is_active # Make sure user is active before login self.user.is_active = True self.user.save() self.client.login(username=self.username, password=self.password) # Revert user activation status self.user.is_active = is_active self.user.save() def assert_no_tracking(self, mock_segment_identify): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) self.assertFalse(mock_segment_identify.called) @override_settings( LMS_SEGMENT_KEY="testkey", MAILCHIMP_NEW_USER_LIST_ID="listid" ) @patch('student.models.segment.identify') def test_activation_with_keys(self, mock_segment_identify): expected_segment_payload = { 'email': self.email, 'username': self.username, 'activated': 1, } expected_segment_mailchimp_list = { "MailChimp": { "listId": settings.MAILCHIMP_NEW_USER_LIST_ID } } # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) mock_segment_identify.assert_called_with( self.user.id, expected_segment_payload, expected_segment_mailchimp_list ) @override_settings(LMS_SEGMENT_KEY="testkey") @patch('student.models.segment.identify') def test_activation_without_mailchimp_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @override_settings(MAILCHIMP_NEW_USER_LIST_ID="listid") @patch('student.models.segment.identify') def test_activation_without_segment_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @patch('student.models.segment.identify') def test_activation_without_keys(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) def test_account_activation_message(self): """ Verify that account correct activation message is displayed. If logged in user has not activated his/her account, make sure that an account activation message is displayed on dashboard sidebar. """ # Log in with test user. self.login() expected_message = ( u"Check your {email_start}{email}{email_end} inbox for an account activation link from " u"{platform_name}. If you need help, contact {link_start}{platform_name} Support{link_end}." ).format( platform_name=self.platform_name, email_start="<strong>", email_end="</strong>", email=self.user.email, link_start="<a target='_blank' href='{activation_email_support_link}'>".format( activation_email_support_link=self.activation_email_support_link, ), link_end="</a>", ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message) def test_account_activation_notification_on_logistration(self): """ Verify that logistration page displays success/error/info messages about account activation. """ login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) # Access activation link, message should say that account has been activated. response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Success! You have activated your account.') # Access activation link again, message should say that account is already active. response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'This account has already been activated.') # Open account activation page with an invalid activation link, # there should be an error message displayed. response = self.client.get(reverse('activate', args=[uuid4().hex]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Your account could not be activated') def test_account_activation_prevent_auth_user_writes(self): login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) with waffle().override(PREVENT_AUTH_USER_WRITES, True): response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, SYSTEM_MAINTENANCE_MSG) assert not self.user.is_active
def create_account(username, password, email): """Create a new user account. This will implicitly create an empty profile for the user. WARNING: This function does NOT yet implement all the features in `student/views.py`. Until it does, please use this method ONLY for tests of the account API, not in production code. In particular, these are currently missing: * 3rd party auth * External auth (shibboleth) * Complex password policies (ENFORCE_PASSWORD_POLICY) In addition, we assume that some functionality is handled at higher layers: * Analytics events * Activation email * Terms of service / honor code checking * Recording demographic info (use profile API) * Auto-enrollment in courses (if invited via instructor dash) Args: username (unicode): The username for the new account. password (unicode): The user's password. email (unicode): The email address associated with the account. Returns: unicode: an activation key for the account. Raises: AccountUserAlreadyExists AccountUsernameInvalid AccountEmailInvalid AccountPasswordInvalid UserAPIInternalError: the operation failed due to an unexpected error. """ # Validate the username, password, and email # This will raise an exception if any of these are not in a valid format. _validate_username(username) _validate_password(password, username) _validate_email(email) # Create the user account, setting them to "inactive" until they activate their account. user = User(username=username, email=email, is_active=False) user.set_password(password) try: user.save() except IntegrityError: raise AccountUserAlreadyExists # Create a registration to track the activation process # This implicitly saves the registration. registration = Registration() registration.register(user) # Create an empty user profile with default values UserProfile(user=user).save() # Return the activation key, which the caller should send to the user return registration.activation_key
class TestActivateAccount(TestCase): """Tests for account creation""" def setUp(self): super(TestActivateAccount, self).setUp() self.username = "******" self.email = "*****@*****.**" self.user = User.objects.create(username=self.username, email=self.email, is_active=False) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() def assert_no_tracking(self, mock_segment_identify): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) self.assertFalse(mock_segment_identify.called) @override_settings( LMS_SEGMENT_KEY="testkey", MAILCHIMP_NEW_USER_LIST_ID="listid" ) @patch('student.models.analytics.identify') def test_activation_with_keys(self, mock_segment_identify): expected_segment_payload = { 'email': self.email, 'username': self.username, 'activated': 1, } expected_segment_mailchimp_list = { "MailChimp": { "listId": settings.MAILCHIMP_NEW_USER_LIST_ID } } # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) mock_segment_identify.assert_called_with( self.user.id, expected_segment_payload, expected_segment_mailchimp_list ) @override_settings(LMS_SEGMENT_KEY="testkey") @patch('student.models.analytics.identify') def test_activation_without_mailchimp_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @override_settings(MAILCHIMP_NEW_USER_LIST_ID="listid") @patch('student.models.analytics.identify') def test_activation_without_segment_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @patch('student.models.analytics.identify') def test_activation_without_keys(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify)
class TestActivateAccount(TestCase): """Tests for account creation""" def setUp(self): super(TestActivateAccount, self).setUp() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = UserFactory.create( username=self.username, email=self.email, password=self.password, is_active=False, ) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() self.platform_name = configuration_helpers.get_value( 'PLATFORM_NAME', settings.PLATFORM_NAME) self.activation_email_support_link = configuration_helpers.get_value( 'ACTIVATION_EMAIL_SUPPORT_LINK', settings. ACTIVATION_EMAIL_SUPPORT_LINK) or settings.SUPPORT_SITE_LINK def login(self): """ Login with test user. Since, only active users can login, so we must activate the user before login. This method does the following tasks in order, 1. Stores user's active/in-active status in a variable. 2. Makes sure user account is active. 3. Authenticated user with the client. 4. Reverts user's original active/in-active status. """ is_active = self.user.is_active # Make sure user is active before login self.user.is_active = True self.user.save() self.client.login(username=self.username, password=self.password) # Revert user activation status self.user.is_active = is_active self.user.save() def assert_no_tracking(self, mock_segment_identify): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) self.assertFalse(mock_segment_identify.called) @override_settings(LMS_SEGMENT_KEY="testkey", MAILCHIMP_NEW_USER_LIST_ID="listid") @patch('student.models.analytics.identify') def test_activation_with_keys(self, mock_segment_identify): expected_segment_payload = { 'email': self.email, 'username': self.username, 'activated': 1, } expected_segment_mailchimp_list = { "MailChimp": { "listId": settings.MAILCHIMP_NEW_USER_LIST_ID } } # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) mock_segment_identify.assert_called_with( self.user.id, expected_segment_payload, expected_segment_mailchimp_list) @override_settings(LMS_SEGMENT_KEY="testkey") @patch('student.models.analytics.identify') def test_activation_without_mailchimp_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @override_settings(MAILCHIMP_NEW_USER_LIST_ID="listid") @patch('student.models.analytics.identify') def test_activation_without_segment_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @patch('student.models.analytics.identify') def test_activation_without_keys(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) def test_account_activation_message(self): """ Verify that account correct activation message is displayed. If logged in user has not activated his/her account, make sure that an account activation message is displayed on dashboard sidebar. """ # Log in with test user. self.login() expected_message = ( u"Check your {email_start}{email}{email_end} inbox for an account activation link from " u"{platform_name}. If you need help, contact {link_start}{platform_name} Support{link_end}." ).format( platform_name=self.platform_name, email_start="<strong>", email_end="</strong>", email=self.user.email, link_start= "<a target='_blank' href='{activation_email_support_link}'>". format(activation_email_support_link=self. activation_email_support_link, ), link_end="</a>", ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message) def test_account_activation_notification_on_logistration(self): """ Verify that logistration page displays success/error/info messages about account activation. """ login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) # Access activation link, message should say that account has been activated. response = self.client.get(reverse( 'activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Success! You have activated your account.') # Access activation link again, message should say that account is already active. response = self.client.get(reverse( 'activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'This account has already been activated.') # Open account activation page with an invalid activation link, # there should be an error message displayed. response = self.client.get(reverse('activate', args=[uuid4().hex]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Your account could not be activated') def test_account_activation_prevent_auth_user_writes(self): login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) with waffle().override(PREVENT_AUTH_USER_WRITES, True): response = self.client.get(reverse( 'activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, SYSTEM_MAINTENANCE_MSG) assert not self.user.is_active
def create_account(username, password, email): """Create a new user account. This will implicitly create an empty profile for the user. WARNING: This function does NOT yet implement all the features in `student/views.py`. Until it does, please use this method ONLY for tests of the account API, not in production code. In particular, these are currently missing: * 3rd party auth * External auth (shibboleth) * Complex password policies (ENFORCE_PASSWORD_POLICY) In addition, we assume that some functionality is handled at higher layers: * Analytics events * Activation email * Terms of service / honor code checking * Recording demographic info (use profile API) * Auto-enrollment in courses (if invited via instructor dash) Args: username (unicode): The username for the new account. password (unicode): The user's password. email (unicode): The email address associated with the account. Returns: unicode: an activation key for the account. Raises: errors.AccountUserAlreadyExists errors.AccountUsernameInvalid errors.AccountEmailInvalid errors.AccountPasswordInvalid errors.UserAPIInternalError: the operation failed due to an unexpected error. """ # Check if ALLOW_PUBLIC_ACCOUNT_CREATION flag turned off to restrict user account creation if not configuration_helpers.get_value( 'ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION', True) ): return HttpResponseForbidden(_("Account creation not allowed.")) if waffle().is_enabled(PREVENT_AUTH_USER_WRITES): raise errors.UserAPIInternalError(SYSTEM_MAINTENANCE_MSG) # Validate the username, password, and email # This will raise an exception if any of these are not in a valid format. _validate_username(username) _validate_password(password, username) _validate_email(email) # Create the user account, setting them to "inactive" until they activate their account. user = User(username=username, email=email, is_active=False) user.set_password(password) try: user.save() except IntegrityError: raise errors.AccountUserAlreadyExists # Create a registration to track the activation process # This implicitly saves the registration. registration = Registration() registration.register(user) # Create an empty user profile with default values UserProfile(user=user).save() # Return the activation key, which the caller should send to the user return registration.activation_key
class TestActivateAccount(TestCase): """Tests for account creation""" def setUp(self): super(TestActivateAccount, self).setUp() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = UserFactory.create( username=self.username, email=self.email, password=self.password, is_active=False, ) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() def login(self): """ Login with test user. Since, only active users can login, so we must activate the user before login. This method does the following tasks in order, 1. Stores user's active/in-active status in a variable. 2. Makes sure user account is active. 3. Authenticated user with the client. 4. Reverts user's original active/in-active status. """ is_active = self.user.is_active # Make sure user is active before login self.user.is_active = True self.user.save() self.client.login(username=self.username, password=self.password) # Revert user activation status self.user.is_active = is_active self.user.save() def assert_no_tracking(self, mock_segment_identify): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) self.assertFalse(mock_segment_identify.called) @override_settings( LMS_SEGMENT_KEY="testkey", MAILCHIMP_NEW_USER_LIST_ID="listid" ) @patch('student.models.analytics.identify') def test_activation_with_keys(self, mock_segment_identify): expected_segment_payload = { 'email': self.email, 'username': self.username, 'activated': 1, } expected_segment_mailchimp_list = { "MailChimp": { "listId": settings.MAILCHIMP_NEW_USER_LIST_ID } } # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) mock_segment_identify.assert_called_with( self.user.id, expected_segment_payload, expected_segment_mailchimp_list ) @override_settings(LMS_SEGMENT_KEY="testkey") @patch('student.models.analytics.identify') def test_activation_without_mailchimp_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @override_settings(MAILCHIMP_NEW_USER_LIST_ID="listid") @patch('student.models.analytics.identify') def test_activation_without_segment_key(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @patch('student.models.analytics.identify') def test_activation_without_keys(self, mock_segment_identify): self.assert_no_tracking(mock_segment_identify) @override_settings(FEATURES=dict(settings.FEATURES, DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR=True)) def test_account_activation_message(self): """ Verify that account correct activation message is displayed. If logged in user has not activated his/her account, make sure that an account activation message is displayed on dashboard sidebar. """ # Log in with test user. self.login() expected_message = render_to_string( 'registration/account_activation_sidebar_notice.html', {'email': self.user.email} ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message, html=True) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() expected_message = render_to_string( 'registration/account_activation_sidebar_notice.html', {'email': self.user.email} ) response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message, html=True) @override_settings(FEATURES=dict(settings.FEATURES, DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR=False)) def test_account_activation_message_disabled(self): """ Verify that old account activation message is displayed when DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR is disabled. """ # Log in with test user. self.login() expected_message = render_to_string( 'registration/activate_account_notice.html', {'email': self.user.email} ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message, html=True) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() expected_message = render_to_string( 'registration/activate_account_notice.html', {'email': self.user.email} ) response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message, html=True) def test_account_activation_notification_on_logistration(self): """ Verify that logistration page displays success/error/info messages about account activation. """ login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) # Access activation link, message should say that account has been activated. response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Success! You have activated your account.') # Access activation link again, message should say that account is already active. response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'This account has already been activated.') # Open account activation page with an invalid activation link, # there should be an error message displayed. response = self.client.get(reverse('activate', args=[uuid4().hex]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Your account could not be activated')