- •ВВЕДЕНИЕ
- •1. ПОДГОТОВКА К РАЗРАБОТКЕ
- •1.1. НАЧАЛО РАБОТЫ
- •1.2. ИСПОЛЬЗОВАНИЕ КОНТЕЙНЕРОВ DOCKER
- •1.3. НАСТРОЙКА СУБД POSTGRESQL
- •1.4. НАСТРОЙКА ТЕСТОВ
- •1.6. СОЗДАНИЕ RESTFUL-МАРШРУТОВ
- •1.6.1. МАРШРУТ POST /USERS
- •1.6.3. МАРШРУТ GET /USERS
- •1.6.2. МАРШРУТ GET /USERS/:ID
- •1.7. ИСПОЛЬЗОВАНИЕ ШАБЛОНОВ JINJA
- •1.8. СТРУКТУРА ПРОЕКТА
- •2. ОТЛАДКА ПРИЛОЖЕНИЯ
- •2.1. ПОКРЫТИЕ ТЕСТАМИ И КАЧЕСТВО КОДА
- •2.1.1. ПОКРЫТИЕ КОДА ТЕСТАМИ
- •2.1.2. КАЧЕСТВО КОДА
- •2.2. НЕПРЕРЫВНАЯ ИНТЕГРАЦИЯ
- •2.3. ПАНЕЛЬ ИНСТРУМЕНТОВ ОТЛАДКИ FLASK
- •2.4. СТРУКТУРА ПРИЛОЖЕНИЯ
- •3. РАЗВИТИЕ ПРИЛОЖЕНИЯ
- •3.1. ПАКЕТ FLASK MIGRATE
- •3.1.1. ИЗМЕНЕНИЕ МОДЕЛИ
- •3.1.2. НАСТРОЙКА FLASK MIGRATE
- •3.2. РЕФАКТОРИНГ КОДА
- •3.3. ПАКЕТ FLASK BCRYPT
- •3.4. НАСТРОЙКА LOG ROUNDS
- •3.5. ИСПОЛЬЗОВАНИЕ ТОКЕНОВ JWT
- •3.5.1. ПАКЕТ PYJWT
- •3.5.2. РАСШИФРОВКА ТОКЕНА
- •3.6. МАРШРУТЫ ДЛЯ АУТЕНТИФИКАЦИИ
- •3.6.1. МАРШРУТ POST /AUTH/REGISTER
- •3.6.2. МАРШРУТ POST /AUTH/LOGIN
- •3.6.3. МАРШРУТ GET /AUTH/LOGOUT
- •3.6.4. МАРШРУТ GET /AUTH/STATUS
- •ЗАКЛЮЧЕНИЕ
- •СПИСОК ЛИТЕРАТУРЫ
# выход из системы с неверным токеном
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)
Добавим соответствующий импорт:
from flask import current_app
Импорт пакета time теперь больше не требуется:
import time
Убедимся, что все тесты выполняются успешно:
------------------------------------------------------------------
Ran 35 tests in 1.015s
OK
3.6.4. МАРШРУТ GET /AUTH/STATUS
Не забывайте о том, что для получения сведения о текущем вошедшем в систему, пользователю, вместе с запросом должен быть отправлен токен аутен-
тификации. Создание маршрута начнём с нескольких тестов:
def test_user_status(self): add_user('test', 'test@test.com', 'test') with self.client:
resp_login = self.client.post( '/auth/login', data=json.dumps({
'email': 'test@test.com', 'password': 'test'
}), content_type='application/json'
)
72
token = json.loads(resp_login.data.decode())['auth_token'] response = self.client.get(
'/auth/status',
headers={'Authorization': f'Bearer {token}'}
)
data = json.loads(response.data.decode()) self.assertTrue(data['status'] == 'success') self.assertTrue(data['data'] is not None) self.assertTrue(data['data']['username'] == 'test') self.assertTrue(data['data']['email'] == 'test@test.com') self.assertTrue(data['data']['active'] is True) self.assertEqual(response.status_code, 200)
def test_invalid_status(self): with self.client:
response = self.client.get( '/auth/status',
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)
После запуска тесты должны завершиться неудачно. Теперь в обработчи-
ке маршрута мы должны:
1)извлечь токен аутентификации и проверить его действительность;
2)взять идентификатор пользователя из полезной нагрузки и получить подробную информацию о пользователе (конечно, если токен действителен).
@auth_blueprint.route('/auth/status', methods=['GET']) def get_user_status():
# get auth token
auth_header = request.headers.get('Authorization') response_object = {
'status': 'fail',
'message': 'Provide a valid auth token.'
}
if auth_header:
73
auth_token = auth_header.split(' ')[1] resp = User.decode_auth_token(auth_token) if not isinstance(resp, str):
user = User.query.filter_by(id=resp).first() response_object['status'] = 'success' response_object['message'] = 'Success.' response_object['data'] = user.to_json() return jsonify(response_object), 200 response_object['message'] = resp
return jsonify(response_object), 401 else:
return jsonify(response_object), 401
Запустим тесты ещё раз.
------------------------------------------------------------------
Ran 37 tests in 1.144s
OK
Затем проверим покрытие кода тестами:
Coverage Summary: |
|
Name |
Stmts Miss Branch BrPart Cover |
---------------------------------------------------------
project/__init__.py |
26 |
12 |
0 |
0 |
54% |
project/api/auth.py |
78 |
15 |
18 |
4 |
80% |
project/api/models.py |
31 |
17 |
2 |
0 |
30% |
project/api/users.py |
50 |
10 |
10 |
0 |
83% |
---------------------------------------------------------
TOTAL |
185 54 |
30 |
4 |
73% |
И наконец, обновим функцию seed_db () в файле manage.py:
cli.command()
def seed_db():
"""Заполнение базы данных."""
db.session.add(User(
username='testname1',
email='testname1@reallyflaskapp.com',
password='testpassword'
))
db.session.add(User(
74
username='testname1herman',
email='testname1@flaskapp.org',
password='testpassword'
))
db.session.commit()
Сделайте коммит, а затем отправьте код на GitHub. Убедитесь, что сборка
Travis успешно создаётся.
75
