def post(self): ''' Someone forgot their password, generate a token and send email ''' email = self.request.get('email') logging.info("(ProviderResetPasswordHandler.post) got password reset request for email: %s" % email) if email: user = db.get_user_from_email(email) if user: self.create_token(user, 'reset') # resetpassword url url_obj = urlparse.urlparse(self.request.url) passwordreset_url = urlparse.urlunparse((url_obj.scheme, url_obj.netloc, '/user/resetpassword/' + user.resetpassword_token, '', '', '')) logging.info('(ProviderResetPasswordHandler.post) password reset URL:' + passwordreset_url) # send email mail.email_user_password_reset(self.jinja2, user, passwordreset_url) # render the login page with success message success_message = _('Password reset instructions have been sent to your address on file.') logging.info("(ProviderResetPasswordHandler.post) " + success_message) self.render_login(success_message=success_message) else: logging.info("(ProviderResetPasswordHandler.post) Can't reset password, no provider exists for email: %s" % email) self.render_login()
def test_provider_reset_password_twice_with_same_token(self): self.create_complete_provider_profile() self.logout_admin() self.logout_provider() login_response = self.testapp.get("/login") resetpassword_form = login_response.forms[ 'resetpassword_form'] # reset passwod is 3rd form on page resetpassword_form['email'] = self._TEST_PROVIDER_EMAIL response = resetpassword_form.submit() # terms agreement response.mustcontain( "Password reset instructions have been sent to your address on file." ) messages = self.mail_stub.get_sent_messages( to=self._TEST_PROVIDER_EMAIL) self.assertEqual(1, len(messages)) m = messages[0] user = db.get_user_from_email(self._TEST_PROVIDER_EMAIL) self.assertEqual(m.subject, 'Veosan - Password reset instructions') self.assertEqual(m.sender, '*****@*****.**') self.assertIn('Please click the link below to choose a new password', m.body.payload) self.assertTrue('/user/resetpassword/%s' % user.resetpassword_token in m.body.payload) # terms page reset_url = '/user/resetpassword/%s' % user.resetpassword_token reset_response = self.testapp.get(reset_url) reset_response.mustcontain("Select your password") reset_response.mustcontain(user.resetpassword_token) # set password and all that password_form = reset_response.forms[0] password_form['password'] = '******' password_form['password_confirm'] = '654321' reset_post_response = password_form.submit() reset_post_response = reset_post_response.follow() self.assertEqual(reset_post_response.status_int, 200) reset_post_response.mustcontain( 'Content de vous revoir! Votre mot de passe à été réinitialisé.') reset_post_response.mustcontain('Profil') # try to re-use the same password reset token reset_response = self.testapp.get(reset_url) reset_response.mustcontain( "Désolé, votre lien est expiré, veuillez essayer de nouveau.")
def render_administration(handler, provider, **kw): user_from_provider = db.get_user_from_email(provider.email) domain_form = ProviderDomainForm().get_form(obj=provider) handler.render_template('provider/administration.html', provider=provider, user_from_provider=user_from_provider, domain_form=domain_form, **kw)
def post(self, vanity_url=None): provider = db.get_provider_from_vanity_url(vanity_url) new_password = self.request.get('password') if provider and new_password: user = db.get_user_from_email(provider.email) if user: # hash password (same as passing password_raw to user_create) password_hash = security.generate_password_hash(new_password, length=12) user.password = password_hash user.put() self.redirect('/admin/provider/admin/' + provider.vanity_url)
def get(self, patient_key=None): patient = ndb.Key(urlsafe=patient_key).get() user = db.get_user_from_email(patient.email) if patient: if auth.PROVIDER_ROLE in user.roles: provider = db.get_provider_from_user(user) self.render_bookings(self, provider=provider, patient=patient) else: self.render_bookings(self, patient=patient) else: logging.info("(ListPatientBookings) No patient associated to logged in user: %s" % user.get_email()) self.redirect("/")
def get(self, vanity_url=None): provider = db.get_provider_from_vanity_url(vanity_url) user = db.get_user_from_email(provider.email) token = self.create_token(user, 'set_new_password') # claim url url_obj = urlparse.urlparse(self.request.url) claim_url = urlparse.urlunparse((url_obj.scheme, url_obj.netloc, '/claim/' + token, '', '', '')) user.claim_url = claim_url user.put() self.redirect('/admin/provider/admin/' + provider.vanity_url)
def get(self, vanity_url=None): provider = db.get_provider_from_vanity_url(vanity_url) user = db.get_user_from_email(provider.email) token = self.create_token(user, 'set_new_password') # claim url url_obj = urlparse.urlparse(self.request.url) claim_url = urlparse.urlunparse( (url_obj.scheme, url_obj.netloc, '/claim/' + token, '', '', '')) user.claim_url = claim_url user.put() self.redirect('/admin/provider/admin/' + provider.vanity_url)
def test_provider_reset_password_twice_with_same_token(self): self.create_complete_provider_profile() self.logout_admin() self.logout_provider() login_response = self.testapp.get("/login") resetpassword_form = login_response.forms['resetpassword_form'] # reset passwod is 3rd form on page resetpassword_form['email'] = self._TEST_PROVIDER_EMAIL response = resetpassword_form.submit() # terms agreement response.mustcontain("Password reset instructions have been sent to your address on file.") messages = self.mail_stub.get_sent_messages(to=self._TEST_PROVIDER_EMAIL) self.assertEqual(1, len(messages)) m = messages[0] user = db.get_user_from_email(self._TEST_PROVIDER_EMAIL) self.assertEqual(m.subject, 'Veosan - Password reset instructions') self.assertEqual(m.sender, '*****@*****.**') self.assertIn('Please click the link below to choose a new password', m.body.payload) self.assertTrue('/user/resetpassword/%s' % user.resetpassword_token in m.body.payload) # terms page reset_url = '/user/resetpassword/%s' % user.resetpassword_token reset_response = self.testapp.get(reset_url) reset_response.mustcontain("Select your password") reset_response.mustcontain(user.resetpassword_token) # set password and all that password_form = reset_response.forms[0] password_form['password'] = '******' password_form['password_confirm'] = '654321' reset_post_response = password_form.submit() reset_post_response = reset_post_response.follow() self.assertEqual(reset_post_response.status_int, 200) reset_post_response.mustcontain('Content de vous revoir! Votre mot de passe à été réinitialisé.') reset_post_response.mustcontain('Profil') # try to re-use the same password reset token reset_response = self.testapp.get(reset_url) reset_response.mustcontain("Désolé, votre lien est expiré, veuillez essayer de nouveau.")
def test_admin_generate_claim_url_for_provider(self): # setup a provider self.self_signup_provider() # login as admin self.login_as_admin() # get the provider key provider = db.get_provider_from_email(self._TEST_PROVIDER_EMAIL) # request the admin page response = self.testapp.get('/admin/provider/admin/%s' % provider.vanity_url) # generate a claim url response = self.testapp.get('/admin/provider/generateclaim/%s' % provider.vanity_url) response = response.follow() user = db.get_user_from_email(self._TEST_PROVIDER_EMAIL) response.mustcontain(user.claim_url) self.logout_admin() self.logout_provider() claim_page = self.testapp.get(user.claim_url) login_form = claim_page.forms[0] login_form['email'] = self._TEST_PROVIDER_EMAIL login_form['password'] = self._TEST_PROVIDER_PASSWORD login_form['password_confirm'] = self._TEST_PROVIDER_PASSWORD login_success = login_form.submit().follow() # default page for provider after login is welcome # (in french because profile is set to french) login_success.mustcontain("Profil") login_success.mustcontain(self._TEST_PROVIDER_EMAIL) login_success.mustcontain("Bienvenue!") login_success.mustcontain("Comment naviguer sur le site")
def post(self, vanity_url=None): ''' Booking process from public profile ''' appointment_details_form = None provider = db.get_provider_from_vanity_url(vanity_url) user = self.get_current_user() if user: appointment_details_form = AppointmentDetailsForLoggedInUser( ).get_form(self.request.POST, provider=provider) else: appointment_details_form = AppointmentDetails().get_form( self.request.POST, provider=provider) provider = db.get_provider_from_vanity_url(vanity_url) if appointment_details_form.validate(): # create the booking object booking = Booking() booking.provider = provider.key booking.booking_source = 'profile' booking_date = appointment_details_form['booking_date'].data booking_time = appointment_details_form['booking_time'].data booking.datetime = to_utc( datetime.strptime(booking_date + " " + booking_time, '%Y-%m-%d %H:%M')) booking.comments = appointment_details_form['comments'].data schedule = db.get_schedule_for_date_time(provider, booking_date, booking_time) booking.schedule = schedule.key if appointment_details_form.__contains__('service'): service_key_from_form = appointment_details_form[ 'service'].data if service_key_from_form: service_key = ndb.Key(urlsafe=service_key_from_form) provider_service = service_key.get() if provider_service: booking.service = service_key if user: # user is logged in, is this a patient? existing_patient = db.get_patient_from_user(user) if existing_patient: booking.patient = existing_patient.key else: self.link_user_to_new_patient(appointment_details_form, user, booking) # confirm the booking since it is a "known" user booking.confirmed = True booking.email_sent_to_patient = False booking.email_sent_to_provider = False # save booking booking.put() # already logged in so go directly to bookings list self.redirect('/patient/bookings/' + booking.patient.urlsafe()) # mail it to the patient mail.email_booking_to_patient(self, booking) # mail it to the provider mail.email_booking_to_provider(self, booking) else: # no user is logged in, check if the email address exists, this means they just didn't log in email = appointment_details_form['email'].data existing_user = db.get_user_from_email(email) if existing_user: existing_patient = db.get_patient_from_user(existing_user) if existing_patient: # email is in datastore, but not logged in # link booking to existing patient booking.patient = existing_patient.key booking.put() else: self.link_user_to_new_patient(appointment_details_form, user, booking) # confirm the booking since it is a "known" user booking.confirmed = True booking.email_sent_to_patient = False booking.email_sent_to_provider = False # save booking booking.put() # get the user to login key = booking.key.urlsafe() self.redirect('/login/booking/' + key) else: # no patient, no user. get them to fill a profile in the form booking.put() patient_form = RegistrationDetailsForNewPatient().get_form( ) patient_form['terms_agreement'].data = True patient_form['booking_date'].data = booking_date patient_form['booking_time'].data = booking_time patient_form['booking_key'].data = booking.key.urlsafe() patient_form['email'].data = email self.render_template( 'provider/public/booking_new_patient.html', provider=provider, patient_form=patient_form) logging.info('Created booking from public profile: %s' % booking) else: self.render_template('provider/public/booking_details.html', provider=provider, booking_form=appointment_details_form)
def book_from_public_profile(self, date_string, time_string, patient_email=_TEST_PATIENT_EMAIL, patient_telephone=_TEST_PATIENT_TELEPHONE): public_profile = self.testapp.get('/' + self._TEST_PROVIDER_VANITY_URL) schedule_page = public_profile.click(linkid='book_button') # Check if a user is logged in is_french = 'Déconnexion' in schedule_page is_english = 'Logout' in schedule_page user_logged_in = False if is_english: user_logged_in = 'Logout' in schedule_page elif is_french: user_logged_in = 'Déconnexion' in schedule_page if is_english: schedule_page.mustcontain("Choose your appointment date and time") elif is_french: schedule_page.mustcontain("Choisissez la date et l'heure de votre rendez-vous") # find the form for next Monday at 10 form_id = "button-" + date_string + '-' + str(time_string) new_patient_page = schedule_page.click(linkid=form_id) # fill patient info step1_form = new_patient_page.forms[0] existing_patient = db.get_patient_from_email(patient_email) existing_user = db.get_user_from_email(patient_email) if not user_logged_in: step1_form['email'] = patient_email step1_form['comments'] = 'I would like to receive care related to boat accident' response = step1_form.submit() if user_logged_in: response = response.follow() if is_english: response.mustcontain("Upcoming Appointments") elif is_french: response.mustcontain("Rendez-vous à venir") elif existing_patient: if existing_user: response = response.follow() if is_english: response.mustcontain("Login to Veosan") elif is_french: response.mustcontain("Connexion à Veosan") login_form = response.forms['login_form'] login_form['password'] = self._TEST_PATIENT_PASSWORD response = login_form.submit().follow() if is_english: response.mustcontain("Upcoming Appointments") elif is_french: response.mustcontain("Rendez-vous à venir") response.mustcontain('Fantastic Fox') else: # new user form (no user is logged in) response.mustcontain("New Patient") response.mustcontain('Password') response.mustcontain('First Name') # fill the form login_form = response.forms['patient_form'] login_form['first_name'] = 'Pat' login_form['last_name'] = 'Patient' login_form['phone'] = patient_telephone login_form['password'] = self._TEST_PATIENT_PASSWORD login_form['password_confirm'] = self._TEST_PATIENT_PASSWORD response = login_form.submit() response.mustcontain("Almost done!") response.mustcontain('An email was sent to') response.mustcontain(patient_email) response.mustcontain('for any questions relating to your appointment')
def post(self, vanity_url=None): ''' Booking process from public profile ''' appointment_details_form = None provider = db.get_provider_from_vanity_url(vanity_url) user = self.get_current_user() if user: appointment_details_form = AppointmentDetailsForLoggedInUser().get_form(self.request.POST, provider=provider) else: appointment_details_form = AppointmentDetails().get_form(self.request.POST, provider=provider) provider = db.get_provider_from_vanity_url(vanity_url) if appointment_details_form.validate(): # create the booking object booking = Booking() booking.provider = provider.key booking.booking_source = 'profile' booking_date = appointment_details_form['booking_date'].data booking_time = appointment_details_form['booking_time'].data booking.datetime = to_utc(datetime.strptime(booking_date + " " + booking_time, '%Y-%m-%d %H:%M')) booking.comments = appointment_details_form['comments'].data schedule = db.get_schedule_for_date_time(provider, booking_date, booking_time) booking.schedule = schedule.key if appointment_details_form.__contains__('service'): service_key_from_form = appointment_details_form['service'].data if service_key_from_form: service_key = ndb.Key(urlsafe=service_key_from_form) provider_service = service_key.get() if provider_service: booking.service = service_key if user: # user is logged in, is this a patient? existing_patient = db.get_patient_from_user(user) if existing_patient: booking.patient = existing_patient.key else: self.link_user_to_new_patient(appointment_details_form, user, booking) # confirm the booking since it is a "known" user booking.confirmed = True booking.email_sent_to_patient = False booking.email_sent_to_provider = False # save booking booking.put() # already logged in so go directly to bookings list self.redirect('/patient/bookings/' + booking.patient.urlsafe()) # mail it to the patient mail.email_booking_to_patient(self, booking) # mail it to the provider mail.email_booking_to_provider(self, booking) else: # no user is logged in, check if the email address exists, this means they just didn't log in email = appointment_details_form['email'].data existing_user = db.get_user_from_email(email) if existing_user: existing_patient = db.get_patient_from_user(existing_user) if existing_patient: # email is in datastore, but not logged in # link booking to existing patient booking.patient = existing_patient.key booking.put() else: self.link_user_to_new_patient(appointment_details_form, user, booking) # confirm the booking since it is a "known" user booking.confirmed = True booking.email_sent_to_patient = False booking.email_sent_to_provider = False # save booking booking.put() # get the user to login key = booking.key.urlsafe() self.redirect('/login/booking/' + key) else: # no patient, no user. get them to fill a profile in the form booking.put() patient_form = RegistrationDetailsForNewPatient().get_form() patient_form['terms_agreement'].data = True patient_form['booking_date'].data = booking_date patient_form['booking_time'].data = booking_time patient_form['booking_key'].data = booking.key.urlsafe() patient_form['email'].data = email self.render_template('provider/public/booking_new_patient.html', provider=provider, patient_form=patient_form) logging.info('Created booking from public profile: %s' % booking) else: self.render_template('provider/public/booking_details.html', provider=provider, booking_form=appointment_details_form)
def test_provider_reset_password(self): self.create_complete_provider_profile() self.logout_admin() self.logout_provider() login_response = self.testapp.get("/login") is_french = 'Connexion' in login_response is_english = 'Login' in login_response resetpassword_form = login_response.forms['resetpassword_form'] # reset passwod is 3rd form on page resetpassword_form['email'] = self._TEST_PROVIDER_EMAIL response = resetpassword_form.submit() # terms agreement if is_english: response.mustcontain("Password reset instructions have been sent to your address on file.") elif is_french: response.mustcontain("Un courriel a été envoyé à votre adresse courriel afin de réinitialiser votre mot de passe.") messages = self.mail_stub.get_sent_messages(to=self._TEST_PROVIDER_EMAIL) self.assertEqual(1, len(messages)) m = messages[0] user = db.get_user_from_email(self._TEST_PROVIDER_EMAIL) self.assertEqual(m.subject, 'Veosan - Password reset instructions' ) self.assertEqual(m.sender, '*****@*****.**') self.assertIn('Please click the link below to choose a new password', m.body.payload) self.assertTrue('/user/resetpassword/%s' % user.resetpassword_token in m.body.payload) # terms page reset_url = '/user/resetpassword/%s' % user.resetpassword_token reset_response = self.testapp.get(reset_url) reset_response.mustcontain("Select your password") reset_response.mustcontain(user.resetpassword_token) #reset_response.mustcontain(self._TEST_PROVIDER_EMAIL) # set password and all that password_form = reset_response.forms[0] password_form['password'] = '******' password_form['password_confirm'] = '654321' reset_post_response = password_form.submit() reset_post_response = reset_post_response.follow() self.assertEqual(reset_post_response.status_int, 200) reset_post_response.mustcontain('Content de vous revoir! Votre mot de passe à été réinitialisé.') reset_post_response.mustcontain('Profil') # try to login with old credentials logout_response = self.testapp.get("/logout") logout_response = logout_response.follow() login_response = self.testapp.get("/login") login_form = login_response.forms['login_form'] login_form['email'] = self._TEST_PROVIDER_EMAIL login_form['password'] = self._TEST_PROVIDER_PASSWORD response = login_form.submit() # login should fail response.mustcontain("Login failed. Try again.") # login again with new credentials resetpassword_form = response.forms['login_form'] resetpassword_form['email'] = self._TEST_PROVIDER_EMAIL resetpassword_form['password'] = '******' response = resetpassword_form.submit() # follow response redirect after successful login response = response.follow() response.mustcontain("Profil")
def test_provider_reset_password(self): self.create_complete_provider_profile() self.logout_admin() self.logout_provider() login_response = self.testapp.get("/login") is_french = 'Connexion' in login_response is_english = 'Login' in login_response resetpassword_form = login_response.forms[ 'resetpassword_form'] # reset passwod is 3rd form on page resetpassword_form['email'] = self._TEST_PROVIDER_EMAIL response = resetpassword_form.submit() # terms agreement if is_english: response.mustcontain( "Password reset instructions have been sent to your address on file." ) elif is_french: response.mustcontain( "Un courriel a été envoyé à votre adresse courriel afin de réinitialiser votre mot de passe." ) messages = self.mail_stub.get_sent_messages( to=self._TEST_PROVIDER_EMAIL) self.assertEqual(1, len(messages)) m = messages[0] user = db.get_user_from_email(self._TEST_PROVIDER_EMAIL) self.assertEqual(m.subject, 'Veosan - Password reset instructions') self.assertEqual(m.sender, '*****@*****.**') self.assertIn('Please click the link below to choose a new password', m.body.payload) self.assertTrue('/user/resetpassword/%s' % user.resetpassword_token in m.body.payload) # terms page reset_url = '/user/resetpassword/%s' % user.resetpassword_token reset_response = self.testapp.get(reset_url) reset_response.mustcontain("Select your password") reset_response.mustcontain(user.resetpassword_token) #reset_response.mustcontain(self._TEST_PROVIDER_EMAIL) # set password and all that password_form = reset_response.forms[0] password_form['password'] = '******' password_form['password_confirm'] = '654321' reset_post_response = password_form.submit() reset_post_response = reset_post_response.follow() self.assertEqual(reset_post_response.status_int, 200) reset_post_response.mustcontain( 'Content de vous revoir! Votre mot de passe à été réinitialisé.') reset_post_response.mustcontain('Profil') # try to login with old credentials logout_response = self.testapp.get("/logout") logout_response = logout_response.follow() login_response = self.testapp.get("/login") login_form = login_response.forms['login_form'] login_form['email'] = self._TEST_PROVIDER_EMAIL login_form['password'] = self._TEST_PROVIDER_PASSWORD response = login_form.submit() # login should fail response.mustcontain("Login failed. Try again.") # login again with new credentials resetpassword_form = response.forms['login_form'] resetpassword_form['email'] = self._TEST_PROVIDER_EMAIL resetpassword_form['password'] = '******' response = resetpassword_form.submit() # follow response redirect after successful login response = response.follow() response.mustcontain("Profil")
def patient_confirms_latest_booking(self, date_string, time_string, new_user=True, logged_in=False): # check email to patient booking_datetime = datetime.strptime(testutil.next_monday_date_string() + " " + str(time_string), '%Y-%m-%d %H') french_datetime_string = format_datetime(booking_datetime, "EEEE 'le' d MMMM yyyy", locale='fr_CA') + " à " + format_datetime(booking_datetime, "H:mm", locale='fr_CA') english_datetime_string = format_datetime(booking_datetime, "EEEE d MMMM yyyy", locale='en') + " at " + format_datetime(booking_datetime, "H:mm", locale='en') booking_datetime = datetime.strptime(testutil.next_monday_date_string(), '%Y-%m-%d') booking_datetime_string = format_date(booking_datetime, format="d MMM yyyy", locale='fr_CA') booking_time = datetime.strptime(str(time_string), '%H') booking_time_string = format_time(booking_time, format="short", locale='fr') logging.info('French date time of booking: %s' % french_datetime_string) # check that confirmation emails was sent to patient messages = self.mail_stub.get_sent_messages(to=self._TEST_PATIENT_EMAIL) patient_email_count = len(messages) # get last email sent m = messages[patient_email_count - 1] self.assertEqual(self._TEST_PATIENT_EMAIL, m.to) # activate account messages = self.mail_stub.get_sent_messages(to=self._TEST_PATIENT_EMAIL) self.assertEquals(m.subject, 'Veosan Appointment - Osteopath') user = db.get_user_from_email(self._TEST_PATIENT_EMAIL) # check email content self.assertIn('Hi', m.body.payload) self.assertIn('Thank you', m.body.payload) self.assertIn(english_datetime_string, m.body.payload) self.assertNotIn('None', m.body.payload) patient = db.get_patient_from_user(user) bookings = db.get_bookings_for_patient(patient) booking = bookings[0] if new_user: self.assertTrue('/login/booking/%s' % booking.key.urlsafe() in m.body.payload) response = self.testapp.get('/') is_french = 'Déconnexion' in response is_english = 'Logout' in response user_logged_in = False if is_english: user_logged_in = 'Logout' in response elif is_french: user_logged_in = 'Déconnexion' in response # click the link response = self.testapp.get('/login/booking/%s' % booking.key.urlsafe()) # is user logged in? if not user_logged_in: if is_english: response.mustcontain("Login to Veosan") elif is_french: response.mustcontain("Connexion à Veosan") login_form = response.forms['login_form'] login_form['password'] = self._TEST_PATIENT_PASSWORD response = login_form.submit().follow() else: response = response.follow() response.mustcontain("Upcoming Appointments") response.mustcontain('Fantastic Fox') #response.mustcontain(booking_time_string) response.mustcontain(english_datetime_string) # patient email in navbar response.mustcontain(self._TEST_PATIENT_EMAIL) response.mustcontain('Logout')