Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Разработка веб-приложений с использованием фреймворка Flask. В 2 частях. Ч.2. Учебное пособие-1.pdf
Скачиваний:
2
Добавлен:
06.09.2026
Размер:
421 Кб
Скачать
☆

response_object['status'] = 'success' response_object['message'] = 'Successfully registered.' response_object['auth_token'] = auth_token.decode() return jsonify(response_object), 201

else:

response_object['message'] = 'Sorry. That user already ex-

ists.'

return jsonify(response_object), 400

# обработка ошибок

except (exc.IntegrityError, ValueError) as e: db.session.rollback()

return jsonify(response_object), 400

После этого тесты будут выполняться успешно.

3.6.2. МАРШРУТ POST /AUTH/LOGIN

Создание маршрута начнём с написания тестов:

def test_registered_user_login(self): with self.client:

add_user('test', 'test@test.com', 'test') response = self.client.post(

'/auth/login',

data=json.dumps({

'email': 'test@test.com', 'password': 'test'

}), content_type='application/json'

)

data = json.loads(response.data.decode()) self.assertTrue(data['status'] == 'success') self.assertTrue(data['message'] == 'Successfully logged in.') self.assertTrue(data['auth_token']) self.assertTrue(response.content_type == 'application/ json') self.assertEqual(response.status_code, 200)

def test_not_registered_user_login(self): with self.client:

response = self.client.post(

67

'/auth/login',

data=json.dumps({

'email': 'test@test.com', 'password': 'test'

}), content_type='application/json'

)

data = json.loads(response.data.decode()) self.assertTrue(data['status'] == 'fail') self.assertTrue(data['message'] == 'User does not exist.') self.assertTrue(response.content_type == 'application/json') self.assertEqual(response.status_code, 404)

Запустим тесты. Запуск тестов должен завершиться неудачей. Теперь до-

бавим соответствующее представление:

@auth_blueprint.route('/auth/login', methods=['POST']) def login_user():

# получение данных

post_data = request.get_json() response_object = {

'status': 'fail',

'message': 'Invalid payload.'

}

if not post_data:

return jsonify(response_object), 400 email = post_data.get('email') password = post_data.get('password') try:

# получение данных пользователя

user = User.query.filter_by(email=email).first()

if user and bcrypt.check_password_hash(user.password, password):

auth_token = user.encode_auth_token(user.id) if auth_token:

response_object['status'] = 'success' response_object['message'] = 'Successfully logged in.' response_object['auth_token'] = auth_token.decode() return jsonify(response_object), 200

else:

68

response_object['message'] = 'User does not exist.' return jsonify(response_object), 404

except Exception as e: response_object['message'] = 'Try again.' return jsonify(response_object), 500

После этого тесты будут выполняться успешно.

3.6.3. МАРШРУТ GET /AUTH/LOGOUT

Создание маршрута начнём с написания тестов. Первый тест служит для проверки корректного выхода из приложения:

def test_valid_logout(self): add_user('test', 'test@test.com', 'test') with self.client:

# user login

resp_login = self.client.post( '/auth/login', data=json.dumps({

'email': 'test@test.com', 'password': 'test'

}), content_type='application/json'

)

# выход из системы с действующим токеном

token = json.loads(resp_login.data.decode())['auth_token'] response = self.client.get(

'/auth/logout',

headers={'Authorization': f'Bearer {token}'}

)

data = json.loads(response.data.decode()) self.assertTrue(data['status'] == 'success') self.assertTrue(data['message'] == 'Successfully logged out.') self.assertEqual(response.status_code, 200)

Второй тест служит для проверки некорректного выхода из приложения:

def test_invalid_logout_expired_token(self):

add_user('test', 'test@test.com', 'test')

with self.client:

resp_login = self.client.post(

69

'/auth/login',

data=json.dumps({

'email': 'test@test.com', 'password': 'test'

}), content_type='application/json'

)

# выход из системы с неверным токеном time.sleep(4)

token = json.loads(resp_login.data.decode())['auth_token'] response = self.client.get(

'/auth/logout',

headers={'Authorization': f'Bearer {token}'}

)

data = json.loads(response.data.decode()) self.assertTrue(data['status'] == 'fail') self.assertTrue(

data['message'] == 'Signature expired. Please log in again.')

self.assertEqual(response.status_code, 401)

def test_invalid_logout(self): with self.client:

response = self.client.get( '/auth/logout',

headers={'Authorization': 'Bearer invalid'}) data = json.loads(response.data.decode()) self.assertTrue(data['status'] == 'fail') self.assertTrue(

data['message'] == 'Invalid token. Please log in again.') self.assertEqual(response.status_code, 401)

Добавим необходимый импорт в файл:

import time

Обновим представление:

@auth_blueprint.route('/auth/logout', methods=['GET']) def logout_user():

# получение токена аутентификации

auth_header = request.headers.get('Authorization')

70

response_object = { 'status': 'fail',

'message': 'Provide a valid auth token.'

}

if auth_header:

auth_token = auth_header.split(' ')[1] resp = User.decode_auth_token(auth_token) if not isinstance(resp, str):

response_object['status'] = 'success' response_object['message'] = 'Successfully logged out.' return jsonify(response_object), 200

else:

response_object['message'] = resp return jsonify(response_object), 401

else:

return jsonify(response_object), 403

Запустим тесты:

------------------------------------------------------------------

Ran 35 tests in 5.040s

OK

Обратите внимание на строку time.sleep (4) в тесте test_invalid_logout_expired_token. Этот код добавляет дополнительные 4 секун-

ды к набору тестов. Чтобы ускорить процесс, обновим значение переменной

TOKEN_EXPIRATION_SECONDS для этого конкретного теста:

def test_invalid_logout_expired_token(self): add_user('test', 'test@test.com', 'test') current_app.config['TOKEN_EXPIRATION_SECONDS'] = -1 with self.client:

resp_login = self.client.post( '/auth/login', data=json.dumps({

'email': 'test@test.com', 'password': 'test'

}), content_type='application/json'

)

71

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]