def user_add(): form = RegistrationForm() if request.method == 'POST' and form.validate(): existing_user = User.get_by_email(form.email.data) if existing_user is None: user_data = { 'username': form.username.data, 'email': form.email.data, 'password': form.password.data } user = User(**user_data).save() try: was_sent, error_msg = user.send_confirmation_email() except (ValueError, socket.error) as e: was_sent = False error_msg = str(e) # Enviamos el email de confirmación al usuario. if was_sent: flash(_('Se envío un correo de confirmación a: %(email)s', email=user.email), 'info') else: flash(_('Ocurrió un error en el envío del correo de ' 'confirmación a: %(email)s %(error_msg)s', email=user.email, error_msg=error_msg), 'error') return redirect(url_for('main.user_add')) else: flash(_('El correo electrónico ya esta registrado'), 'error') return render_template('forms/register.html', form=form)
def user_edit(user_id): # TODO: permitir la actualización de usuarios sin actualizar contraseña user = User.get_by_id(user_id) form = RegistrationForm(obj=user) if request.method == 'POST' and form.validate(): existing_user = User.get_by_email(form.email.data) if existing_user is None or user.id == existing_user.id: update_user = User.get_by_id(user_id) update_user.username = form.username.data update_user.email = form.email.data update_user.password = form.password.data update_user.save() flash(_('Usuario actualizado correctamente!'), 'info') if user.email != update_user.email: user.email_confirmed = False user.save() try: # TODO: enviar email de actualización was_sent, error_msg = update_user.send_confirmation_email() except (ValueError, socket.error) as e: was_sent = False error_msg = str(e) # Enviamos el email de confirmación al usuario. if was_sent: flash(_('Se envío un correo de confirmación a: %(email)s', email=update_user.email), 'info') else: flash(_('Ocurrió un error en el envío del correo de ' 'confirmación a: %(email)s %(error_msg)s', email=update_user.email, error_msg=error_msg), 'error') else: flash(_('El correo electrónico ya esta registrado'), 'error') return render_template('forms/register.html', form=form)
def test_confirmation_email_invalid_user(self): """Test de error cuando se trata de activar un usuario no registrado""" fake_email = '*****@*****.**' expected_error_msg = 'Usuario no encontrado' with current_app.app_context(): with self.client as c: with mail.record_messages() as outbox: notifications.send_confirmation_email(fake_email) email_msg = outbox[0] links_found = url_pattern.findall(email_msg.html) self.assertGreaterEqual(1, len(links_found)) confirm_url_with_token = [ url for url in links_found if '/user/confirm/' in url ] self.assertEqual(1, len(confirm_url_with_token)) confirm_url_with_token = confirm_url_with_token[0] # tratamos de activar con el enlace response = c.get(confirm_url_with_token, follow_redirects=True) self.assertStatus(response, 404) self.assertEqual('text/html', response.content_type) user = User.get_by_email(fake_email) self.assertIsNone(user) self.assertIn(expected_error_msg, response.data.decode('utf-8'))
def test_user_add_insert_one(self): """Test para registro de un usuario""" user_data = { 'email': '*****@*****.**', 'password': '******', } new_user_data = { 'username': '******', 'email': '*****@*****.**', 'password': '******', 'confirm': 'F00barbaz$' } create_user(user_data['email'], user_data['password'], True) login_url = url_for('main.login') user_add_url = (url_for('main.user_add')) expected_msg = 'Se envío un correo de confirmación a: %s' % new_user_data[ 'email'] with current_app.app_context(): with self.client as c: # login de usuario c.post(login_url, data=user_data, follow_redirects=True) # registro de usuario response = c.post(user_add_url, data=new_user_data, follow_redirects=True) self.assertStatus(response, 200) self.assertEqual('text/html; charset=utf-8', response.content_type) self.assert_template_used("forms/register.html") self.assertIn(expected_msg, response.data.decode('utf-8')) user = User.get_by_email(new_user_data['email']) self.assertIsInstance(user, User)
def test_user_edit(self): """Test para la vista user_edit""" user_data = { 'email': '*****@*****.**', 'password': '******', } create_user(user_data['email'], user_data['password'], True) login_url = url_for('main.login') with current_app.app_context(): with self.client as c: # login de usuario login_response = c.post(login_url, data=user_data, follow_redirects=True) self.assertStatus(login_response, 200) # vista user_edit user = User.get_by_email(user_data['email']) user_edit_url = url_for('main.user_edit', user_id=user.id) response = c.get(user_edit_url) self.assertStatus(response, 200) self.assertEqual('text/html; charset=utf-8', response.content_type) self.assertEqual([i.url for i in current_breadcrumbs], ['/', '/usuarios', user_edit_url]) self.assert_template_used("forms/register.html") context_form = self.get_context_variable('form') self.assertIsInstance(context_form, forms.RegistrationForm)
def test_reset_with_valid_token_update_ok(self): """Test de recuperación de contraseña""" user_data = { 'email': '*****@*****.**', 'password': '******', } create_user(user_data['email'], user_data['password'], True) reset_url = url_for('main.reset') with current_app.app_context(): with self.client as c: with mail.record_messages() as outbox: c.post(reset_url, data=user_data, follow_redirects=True) # Obtenemos url del correo email_msg = outbox[0] links_found = url_pattern.findall(email_msg.html) self.assertGreaterEqual(1, len(links_found)) reset_url_with_token = [ url for url in links_found if reset_url in url ] self.assertEqual(1, len(reset_url_with_token)) reset_url_with_token = reset_url_with_token[0] # Llamamos a la vista reset_with_token con la contraseña new_password = '******' response = c.post(reset_url_with_token, data={ 'password': new_password, 'confirm': new_password }, follow_redirects=True) self.assertStatus(response, 200) self.assertTemplateUsed('auth/login.html') user = User.get_by_email(user_data['email']) self.assertTrue(user.check_password_hash(new_password))
def reset_with_token(token): try: ts = get_timed_serializer() email = ts.loads(token, salt=current_app.config.get('TOKEN_EMAIL_SALT'), max_age=current_app.config.get('TOKEN_MAX_AGE')) except Exception: abort(404, _('Token inválido')) form = PasswordForm() if request.method == 'POST' and form.validate(): user = User.get_by_email(email) if not user.email_confirmed: user.send_confirmation_email() return render_template('auth/unconfirmed_email.html') controllers.set_user_password(user, form.password.data) flash(_('Nueva contraseña guardada con éxito!'), 'success') return redirect(url_for('.index')) data = { 'form': form, 'token': token } return render_template('auth/reset_with_token.html', **data)
def reset(): form = EmailForm() if request.method == 'POST' and form.validate(): user = User.get_by_email(form.email.data) if not user: flash(_('Usuario no registrado'), 'error') return render_template('auth/reset.html', form=form) if not user.email_confirmed: user.send_confirmation_email() return render_template('auth/unconfirmed_email.html') was_sent, error_msg = user.send_reset_password_email() if was_sent: flash(_('Se enviaron instrucciones para recuperar su contraseña ' 'al correo: %(email)s', email=user.email), 'info') else: flash(_('Ocurrió un problema al enviar el correo con las ' 'instrucciones de recuperación de contraseña a la ' 'dirección: %(email)s. Erro: %(error)s', email=user.email, error=error_msg), 'error') return redirect(url_for('.index')) return render_template('auth/reset.html', form=form)
def test_user_edit_update_raise_value_error(self): """Test para actualizar un usuario""" user_data = { 'email': '*****@*****.**', 'password': '******', } create_user(user_data['email'], user_data['password'], True) user = User.get_by_email(user_data['email']) login_url = url_for('main.login') with current_app.app_context(): with self.client as c: with patch('biblat_manager.webapp.models.User' '.send_confirmation_email') as mock: mock.side_effect = ValueError( 'recipient_email es inválido!') # login de usuario c.post(login_url, data=user_data, follow_redirects=True) # edición de usuario user_data_update = {} user_data_update.update(user_data) user_data_update.update({ 'email': '*****@*****.**', 'username': '******', 'password': '******', 'confirm': 'Quxquuxc0rge$' }) user_edit_url = url_for('main.user_edit', user_id=user.id) response = c.post(user_edit_url, data=user_data_update, follow_redirects=True) self.assertRaises(ValueError) self.assertStatus(response, 200) self.assertEqual('text/html; charset=utf-8', response.content_type) self.assert_template_used("forms/register.html") expected_error_msg = 'Ocurrió un error en el envío del ' \ 'correo de confirmación a: %s' % \ user_data_update['email'] self.assertIn(expected_error_msg, response.data.decode('utf-8')) updated_user = User.get_by_id(user.id) self.assertEqual(user_data_update['email'], updated_user.email)
def test_user_add_insert_one_with_confirmation_email(self): """Test para registro de un usuario con confirmación de correo""" user_data = { 'email': '*****@*****.**', 'password': '******', } new_user_data = { 'username': '******', 'email': '*****@*****.**', 'password': '******', 'confirm': 'F00barbaz$' } create_user(user_data['email'], user_data['password'], True) login_url = url_for('main.login') logout_url = url_for('main.logout') user_add_url = (url_for('main.user_add')) expected_email = { 'subject': 'Confirmación de correo electrónico', 'recipients': [new_user_data['email']], } with current_app.app_context(): with self.client as c: with mail.record_messages() as outbox: # login de usuario c.post(login_url, data=user_data, follow_redirects=True) # registro de usuario c.post(user_add_url, data=new_user_data, follow_redirects=True) # logout de usuario c.get(logout_url) # confirmación de correo electrónico email_msg = outbox[0] self.assertEqual(1, len(outbox)) self.assertEqual(expected_email['subject'], email_msg.subject) self.assertEqual(expected_email['recipients'], email_msg.recipients) links_found = url_pattern.findall(email_msg.html) self.assertGreaterEqual(1, len(links_found)) confirm_url_with_token = [ url for url in links_found if '/user/confirm/' in url ] self.assertEqual(1, len(confirm_url_with_token)) confirm_url_with_token = confirm_url_with_token[0] # activamos correo electrónico response = c.get(confirm_url_with_token, follow_redirects=True) self.assertStatus(response, 200) self.assertEqual('text/html; charset=utf-8', response.content_type) self.assert_template_used("auth/login.html") user = User.get_by_email(new_user_data['email']) self.assertTrue(user.email_confirmed)
def test_user_edit_duplicated_email(self): """Test para registro de un usuario""" user_data = { 'email': '*****@*****.**', 'password': '******', } create_user(user_data['email'], user_data['password'], True) create_user('*****@*****.**', 'F00barbaz$', True) user = User.get_by_email(user_data['email']) login_url = url_for('main.login') expected_error_msg = 'El correo electrónico ya esta registrado' with current_app.app_context(): with self.client as c: # login de usuario c.post(login_url, data=user_data, follow_redirects=True) # edición de usuario user_data_update = {} user_data_update.update(user_data) user_data_update.update({ 'email': '*****@*****.**', 'username': '******', 'password': '******', 'confirm': 'Quxquuxc0rge$' }) user_edit_url = url_for('main.user_edit', user_id=user.id) response = c.post(user_edit_url, data=user_data_update, follow_redirects=True) self.assertStatus(response, 200) self.assertEqual('text/html; charset=utf-8', response.content_type) self.assert_template_used("forms/register.html") self.assertIn(expected_error_msg, response.data.decode('utf-8')) updated_user = User.get_by_id(user.id) self.assertEqual(user_data['email'], updated_user.email)
def confirm_email(token): try: ts = get_timed_serializer() email = ts.loads(token, salt=current_app.config.get('TOKEN_EMAIL_SALT'), max_age=current_app.config.get('TOKEN_MAX_AGE')) except Exception: # posibles exepciones: https://pythonhosted.org/itsdangerous/#exceptions abort(404) user = User.get_by_email(email) if not user: abort(404, _('Usuario no encontrado')) controllers.set_user_email_confirmed(user) flash(_('Email: %(email)s confirmado com éxito!', email=user.email), 'success') return redirect(url_for('.index'))
def login(): if current_user.is_authenticated: return redirect(url_for('.index')) form = LoginForm() if request.method == 'POST' and form.validate(): user = User.objects(email=form.email.data).first() if user and user.check_password_hash(form.password.data) \ and user.email_confirmed: login_user(user, remember=form.remember.data) flash(_('Sesión iniciada como %s' % user.email), 'success') return redirect(session.get('next') or url_for('.index')) if not user: flash(_('Usuario no registrado'), 'error') if user and not user.check_password_hash(form.password.data): flash(_('Contraseña incorrecta'), 'error') if user and not user.email_confirmed: flash(_('Correo electrónico no verificado'), 'error') return render_template('auth/login.html', form=form)
def test_user_add_insert_one_raise_value_error(self): """Test para registro de un usuario""" user_data = { 'email': '*****@*****.**', 'password': '******', } new_user_data = { 'username': '******', 'email': '*****@*****.**', 'password': '******', 'confirm': 'F00barbaz$' } create_user(user_data['email'], user_data['password'], True) login_url = url_for('main.login') user_add_url = (url_for('main.user_add')) expected_error_msg = 'Ocurrió un error en el envío del correo de ' \ 'confirmación a: %s' % new_user_data['email'] with current_app.app_context(): with self.client as c: with patch('biblat_manager.webapp.models.User' '.send_confirmation_email') as mock: mock.side_effect = ValueError( 'recipient_email es inválido!') # login de usuario c.post(login_url, data=user_data, follow_redirects=True) # registro de usuario response = c.post(user_add_url, data=new_user_data, follow_redirects=True) self.assertRaises(ValueError) self.assertStatus(response, 200) self.assertEqual('text/html; charset=utf-8', response.content_type) self.assert_template_used("forms/register.html") self.assertIn(expected_error_msg, response.data.decode('utf-8')) user = User.get_by_email(new_user_data['email']) self.assertIsInstance(user, User)
def user_detail(user_id): user = User.get_by_id(user_id) data = { 'user': user } return render_template('main/user.html', **data)