def test_reset_password(self, mailgun_mock): mailgun_mock.return_value = None with app.app_context(): found_user = UserDAO().get(self.test_uid) self.assertIsNotNone(found_user) original_token = found_user.reset_token data = { 'email': self.test_user_email, } response = self.test_client.put( '/users/reset_password', content_type='application/json', data=json.dumps(data), ) self.assertEqual(response.status_code, HTTPStatus.OK) found_user = UserDAO().get(self.test_uid) self.assertIsNotNone(found_user) self.assertIsNotNone(found_user.reset_token) self.assertNotEqual(found_user.reset_token, original_token)
def test_reset_password_token_resets_password(self, mailgun_mock): mailgun_mock.return_value = None with app.app_context(): found_user = UserDAO().get(self.test_uid) self.assertIsNotNone(found_user) original_token = found_user.reset_token original_password = found_user.password data = { 'email': self.test_user_email, } response = self.test_client.put( '/users/reset_password', content_type='application/json', data=json.dumps(data), ) self.assertEqual(response.status_code, HTTPStatus.OK) found_user = UserDAO().get(self.test_uid) self.assertIsNotNone(found_user) self.assertIsNotNone(found_user.reset_token) self.assertNotEqual(found_user.reset_token, original_token) # Now reset the password and verify it worked.. data = { 'token': found_user.reset_token, 'plaintext_password': '******' } response = self.test_client.post( '/users/reset_password', content_type='application/json', data=json.dumps(data), ) self.assertEqual(response.status_code, HTTPStatus.OK) found_user = UserDAO().get(self.test_uid) self.assertIsNotNone(found_user) self.assertIsNone(found_user.reset_token) self.assertNotEqual(found_user.password, original_password) # Verify new password works. self.assertTrue( User.bcrypt_compare(data['plaintext_password'], found_user.password)) # Kind of a duplicate, but verify old doesn't work. self.assertFalse( User.bcrypt_compare(data['plaintext_password'], original_password))
def authenticate(username, password): user = UserDAO().get_by_username(username) if User.bcrypt_compare(password, user.password): jwt_claim = uuid.uuid4() db.session.query(User).filter_by(public_id=user.public_id).update( {'jwt_claim': jwt_claim}) db.session.commit() user.jwt_claim = jwt_claim return user
def setUpClass(cls): with app.app_context(): db.drop_all() db.create_all() cls.test_dao = UserDAO() test_user = User('*****@*****.**', 'testpw', 'test-{0}-username'.format(uuid.uuid4())) deleted_user = User('*****@*****.**', 'testpassword', 'test-{0}-username'.format(uuid.uuid4())) deleted_user.is_deleted = True user_to_delete = User('*****@*****.**', 'testpw', 'test-{0}-username'.format(uuid.uuid4())) cls.test_uid = test_user.public_id cls.deleted_uid = deleted_user.public_id cls.to_delete_uid = user_to_delete.public_id db.session.add(test_user) db.session.add(deleted_user) db.session.add(user_to_delete) db.session.commit()
def regenerate_verification_token(self, email): """ Handles generating a new verification token should a user ever forget theirs. :param str email: The email of the user who forgot/lost their verification email. :rtype: str :return: The newly generated verification token. """ try: new_token, user = UserDAO().regenerate_token(email, 'verify_token') MailgunIntegration.send_email( current_app.config['MAILGUN_ORIGIN_EMAIL'], user.email, 'Please verify your account', current_app.config['VERIFY_EMAIL_CONTENT'].format(new_token)) return new_token except IntegrationException as e: logging.error( 'Failed to generate token for user with exception: {0}'.format( e)) raise FacadeException( 'Failed to generate new token. Email sending failed.', e.status_code) except DAOException as e: logging.error( 'Failed to generate token for user with exception: {0}'.format( e)) raise FacadeException( 'Failed to generate new token: {0}'.format(e), e.status_code)
def setUpClass(cls): with app.app_context(): db.drop_all() db.create_all() cls.test_client = app.test_client() cls.test_dao = UserDAO()
def regenerate_reset_password_token(self, email): """ Regenerates a reset password token and sends another email. :param str email: The email of the user who forgot/lost their reset password email token. :rtype: str :return: The newly generated token. """ try: new_token, user = UserDAO().regenerate_token(email, 'reset_token') MailgunIntegration().send_email( current_app.config['MAILGUN_ORIGIN_EMAIL'], user.email, 'Reset your password', current_app.config['RESET_EMAIL_CONTENT'].format( '{0}/users/reset_password/{1}'.format( current_app.config['HOST'], new_token, ))) return new_token except IntegrationException as e: logging.error('Failed to send email with exception: {0}'.format(e)) raise FacadeException('Failed to send reset token email.', e.status_code) except DAOException as e: logging.error( 'Failed to regenerate reset token with exception: {0}'.format( e)) raise FacadeException('Failed to regenerate reset token.', e.status_code)
def delete(self, user_id): user_info = UserDAO().soft_delete(user_id) logging.info( 'Successfully soft deleted user {0} for requesting user.'.format( user_id)) return jsonify(UserMarshal().dump(user_info).data)
def delete(self): """ Logs a user out and invalidates their JWT. """ UserDAO().logout_current_user() logging.info('Successfully logged out user') return jsonify({'success': True})
def put(self, user_id): arg_fields = { 'email': String(), 'current_password': String(), 'plaintext_password': String() } args = parser.parse(arg_fields) user_info = UserDAO().update_user_data(user_id, **args) logging.info( 'Successfully updated information for user {0}'.format(user_info)) return jsonify(UserMarshal().dump(user_info).data)
def setUpClass(cls): with app.app_context(): db.drop_all() db.create_all() cls.test_client = app.test_client() cls.test_dao = UserDAO() test_user = User('*****@*****.**', 'testpw', 'test-verify') cls.test_user_token = test_user.verify_token cls.test_uid = test_user.public_id db.session.add(test_user) db.session.commit()
def post(self): """ Validate a user by providing the correct token. """ arg_fields = { 'token': String(required=True), } args = parser.parse(arg_fields) validated_user = UserDAO().verify_token(args['token']) logging.info('Successfully validated token {0} for user {1}.'.format( args['token'], validated_user, )) return jsonify(UserMarshal().dump(validated_user).data)
def post(self): """ Reset a users password. """ arg_fields = { 'token': String(required=True), 'plaintext_password': String(required=True) } args = parser.parse(arg_fields) validated_user = UserDAO().reset_user_password(**args) logging.info('Successfully validated token {0} for user {1}.'.format( args['token'], validated_user, )) return jsonify(UserMarshal().dump(validated_user).data)
def get(self, user_id): user_info = UserDAO().get(user_id) if user_info is None: logging.info('Requested user ({0} does not exist.'.format(user_id)) raise EndpointException('Requested user does not exist.', HTTPStatus.NOT_FOUND) if not user_info.is_validated: logging.info('Requested unvalidated account: {0}'.format(user_id)) raise EndpointException('Account is not validated.', HTTPStatus.FORBIDDEN) logging.info('Retrieved user info for {0}'.format(user_id)) return jsonify(UserMarshal().dump(user_info).data)
def test_token_verification_fail_invalid_token(self): with app.app_context(): data = { 'token': 'asldkfjalksdjf', } response = self.test_client.post( '/users/verify'.format(self.test_uid), content_type='application/json', data=json.dumps(data), ) self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) found_user = UserDAO().get(self.test_uid) self.assertIsNotNone(found_user) self.assertIsNotNone(found_user.verify_token) self.assertFalse(found_user.is_validated)
def create_new_user(self, email, plaintext_password, username): """ Handles creation of a new user and sending the verification token to the user. :param str email: The user's email :param str plaintext_password: The plaintext password. Is hashed at the model level. :param str username: The requested username for the user. :rtype: UserTable :return: The newly created user. """ try: new_user = UserDAO().create_new_user(email, plaintext_password, username) MailgunIntegration().send_email( current_app.config['MAILGUN_ORIGIN_EMAIL'], new_user.email, 'Please verify your account', current_app.config['VERIFY_EMAIL_CONTENT'].format( '{0}/users/verify/{1}'.format( current_app.config['HOST'], new_user.verify_token, ))) return new_user except IntegrationException as e: db.session.rollback() logging.error( 'Failed to send mail when creating new user: {0}'.format(e)) raise FacadeException('Failed to create user. Cannot send email.', e.status_code) except DAOException as e: db.session.rollback() logging.error( 'Failed to create new user with exception: {0}'.format(e)) raise FacadeException( 'Failed to create user. User creation failed.', e.status_code) finally: self._safe_commit()
def test_token_verification(self): with app.app_context(): data = { 'token': self.test_user_token, } response = self.test_client.post( '/users/verify', content_type='application/json', data=json.dumps(data), ) self.assertEqual(response.status_code, HTTPStatus.OK) self.assertIsNotNone(response) found_user = UserDAO().get(self.test_uid) self.assertIsNotNone(found_user) self.assertIsNone(found_user.verify_token) self.assertTrue(found_user.is_validated)