Доработка API
This commit is contained in:
@@ -5,7 +5,7 @@ RETURNS TABLE(confirm boolean)
|
||||
AS $$
|
||||
BEGIN
|
||||
UPDATE nn_db.application
|
||||
SET nn_db.application.fk_status = in_fk_status
|
||||
SET fk_status = in_fk_status
|
||||
WHERE
|
||||
nn_db.application.pk_application = in_pk_application;
|
||||
|
||||
|
||||
@@ -7,9 +7,10 @@ from django.core.signing import TimestampSigner
|
||||
from django.utils.encoding import force_str, force_bytes
|
||||
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
|
||||
from django.contrib.auth.hashers import PBKDF2PasswordHasher
|
||||
from django.http.request import QueryDict
|
||||
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
import re
|
||||
import re, json
|
||||
|
||||
|
||||
def call_func(name: str, parameters: dict):
|
||||
@@ -31,41 +32,57 @@ def call_func(name: str, parameters: dict):
|
||||
return [dict(zip(columns, row)) for row in cursor.fetchall()]
|
||||
|
||||
def api_get_xcsrf(request):
|
||||
data = { 'X-CSFRToken': get_token(request) }
|
||||
data = { 'X-CSRFToken': get_token(request) }
|
||||
return JsonResponse(data, safe=False, status=200)
|
||||
|
||||
# Проверка авторизации
|
||||
def is_auth(request):
|
||||
# Проверяем наличие заголовка авторизации
|
||||
if not request.headers.get('Authorization'):
|
||||
# Если его нет - возвращаем "Ложь"
|
||||
return False
|
||||
# Если токен есть - получаем его, разбивая строку по пробелу, при этом извлекая только последнюю строку
|
||||
token = request.headers.get('Authorization').split(' ')[-1]
|
||||
# Инициализируем подписывающий объект
|
||||
signer = TimestampSigner(salt='django.core.signing')
|
||||
try:
|
||||
# Пробуем извлечь из токена имя пользователя
|
||||
login = signer.unsign(force_str(urlsafe_base64_decode(token)), max_age=1000)
|
||||
print(login)
|
||||
except:
|
||||
# Если не получилось - возвращаем "Ложь"
|
||||
return False
|
||||
else:
|
||||
# Если получилось - запрашиваем в базе данных информацию о пользователе
|
||||
user = call_func('nn_db.user_get', {'search_value': login})[0]
|
||||
# И возвращаем полученные данные
|
||||
return user
|
||||
|
||||
# Обработка заявок
|
||||
def api_applications(request):
|
||||
# Проверяем, авторизован ли пользователь
|
||||
user = is_auth(request)
|
||||
if not user:
|
||||
# Если пользователь не авторизован - возвращаем ответ с соответствующим сообщением
|
||||
return JsonResponse({"code": 403, "message":"Доступ запрещен" }, safe=False, status=403)
|
||||
|
||||
# Если пользователь авторизован, то проверяем, какой тип запроса был отправлен
|
||||
if request.method == 'GET':
|
||||
params = {}
|
||||
if user['is_admin']:
|
||||
params['pk_user'] = None
|
||||
# Если запрос на получение данных
|
||||
params = {} # Инициализируем объект, хранящий параметры запроса
|
||||
if user['is_admin']: # Если пользователь - администратор
|
||||
params['pk_user'] = None # Заполняем параметр null-значением (в Python - None)
|
||||
else:
|
||||
params['pk_user'] = str(user['pk_user'])
|
||||
# params['pk_user'] = None
|
||||
params['pk_user'] = str(user['pk_user']) # Иначе заполняем параметр идентификатором пользователя
|
||||
|
||||
# Запрашиваем данные по заявкам из базы данных по указанному пользователю
|
||||
results = call_func('nn_db.application_get', params)
|
||||
|
||||
# Определяем списки для возвращаемых заявок и ключей, заявки по которым уже есть в первом списке
|
||||
applications = []
|
||||
keys = []
|
||||
for result in results:
|
||||
if result['pk_application'] not in keys:
|
||||
application = {}
|
||||
for result in results: # Проходимся по каждой строке результата из БД
|
||||
if result['pk_application'] not in keys: # Если ключ текущей заявки не находится в списке ключей
|
||||
application = {} # Инициализируем словарь и заполняем его данными из ответа БД
|
||||
application['pk_application'] = result['pk_application']
|
||||
application['car_number'] = result['car_number']
|
||||
application['description'] = result['description']
|
||||
@@ -73,33 +90,140 @@ def api_applications(request):
|
||||
application['title'] = result['title']
|
||||
application['fk_user'] = result['fk_user']
|
||||
application['username'] = result['username']
|
||||
# Инициализируем список хранения данных об изображениях к заявке
|
||||
application['images'] = []
|
||||
|
||||
# Если есть данные о изображении
|
||||
if result['pk_image'] is not None:
|
||||
image = {}
|
||||
image = {} # Инициализируем словарь картинки и заполняем его данными из ответа БД
|
||||
image['pk_image'] = result['pk_image']
|
||||
image['file_name'] = result['file_name']
|
||||
image['file_ext'] = result['file_ext']
|
||||
# Добавляем словарь картинки в список картинок заявки
|
||||
application['images'].append(image)
|
||||
|
||||
# Добавляем словарь заявки в список заявок
|
||||
applications.append(application)
|
||||
# Добавляем ключ заявки в список обработанных ключей
|
||||
keys.append(application['pk_application'])
|
||||
else:
|
||||
for application in applications:
|
||||
if application['pk_application'] == result['pk_application']:
|
||||
image = {}
|
||||
# Если заявка уже обработана, т.е. эта строка обозначает следующее изображение
|
||||
for application in applications: # Проходимся по каждой заявке и ищем текущую заявку
|
||||
if application['pk_application'] == result['pk_application']: # Если ключи совпадают
|
||||
image = {} # Инициализируем словарь картинки и заполняем его данными из ответа БД
|
||||
image['pk_image'] = result['pk_image']
|
||||
image['file_name'] = result['file_name']
|
||||
image['file_ext'] = result['file_ext']
|
||||
# Добавляем словарь картинки в список картинок заявки
|
||||
application['images'].append(image)
|
||||
|
||||
# Возвращаем данные пользователю
|
||||
return JsonResponse({"code": 200, "data": applications}, safe=False, status=200)
|
||||
|
||||
# Если запрос на добавление данных
|
||||
if request.method == 'POST':
|
||||
params = {}
|
||||
params = {} # Инициализируем список параметров для запроса и заполняем его данными из POST-запроса
|
||||
params['car_number'] = request.POST.get('car_number')
|
||||
params['description'] = request.POST.get('description')
|
||||
params['fk_user'] = user['pk_user']
|
||||
params['fk_user'] = str(user['pk_user'])
|
||||
|
||||
# Инициализируем список ошибок валидации данных
|
||||
errors = []
|
||||
# Автоматическая проверка параметров на заполненность
|
||||
for key in params:
|
||||
if params[key] is None or params[key] == '':
|
||||
errors.append({ key: "Параметр обязателен для заполнения" })
|
||||
|
||||
# Если ошибки есть - то возвращаем ответ с ошибкой
|
||||
if errors:
|
||||
return JsonResponse({"code": 409, "errors": errors}, safe=False, status=409)
|
||||
|
||||
# Проверяем введенные данные на валидность
|
||||
if re.match(r'^[YETOPAHKXCBMУЕТОРАНКХСВМ]\d{3}[YETOPAHKXCBMУЕТОРАНКХСВМ]{2}\d{1,3}$', params['car_number']) is None:
|
||||
errors.append({ "car_number": "Государственный номер автомобиля имеет некорректный формат" })
|
||||
if len(params['description']) < 15:
|
||||
errors.append({ "description": "Описание нарушения должно быть длинее 5 символов" })
|
||||
|
||||
# Если ошибки есть - то возвращаем ответ с ошибкой
|
||||
if errors:
|
||||
return JsonResponse({"code": 409, "errors": errors}, safe=False, status=409)
|
||||
|
||||
# Отправляем запрос на добавление данных
|
||||
confirm = call_func('nn_db.application_post', params)
|
||||
return JsonResponse({"code": 201, "data": confirm}, safe=False, status=201)
|
||||
|
||||
# Проверяем, пришел ли в ответ на запрос первичный ключ добавленной заявки
|
||||
if any(confirm) and 'pk_application' in confirm[0]:
|
||||
# Если пришёл - то возвращаем данные
|
||||
return JsonResponse({"code": 201, "data": confirm}, safe=False, status=201)
|
||||
else:
|
||||
# Если нет - то возвращаем ошибку с сообщением
|
||||
return JsonResponse({"code": 520, "message": "Не удалось добавить запись в БД, попробуйте позднее"}, safe=False, status=520)
|
||||
|
||||
# Если запрос на изменение заявки:
|
||||
if request.method == 'PATCH':
|
||||
if not user['is_admin']: # Если пользователь - не администратор
|
||||
return JsonResponse({"code": 403, "message":"Доступ запрещен" }, safe=False, status=403) # По ТЗ смена статуса - только у администратора
|
||||
|
||||
# Запросы PUT, PATCH и DELETE не работают с Form-data нативно, по этому в теле запроса должен быть JSON объект
|
||||
data = json.loads(request.body)
|
||||
|
||||
params = {} # Инициализируем список параметров для запроса и заполняем его данными из JSON объекта
|
||||
params['pk_application'] = str(data.get('pk_application'))
|
||||
params['fk_status'] = str(data.get('fk_status'))
|
||||
|
||||
# Инициализируем список ошибок валидации данных
|
||||
errors = []
|
||||
# Автоматическая проверка параметров на заполненность
|
||||
for key in params:
|
||||
if params[key] is None or params[key] == '':
|
||||
errors.append({ key: "Параметр обязателен для заполнения" })
|
||||
|
||||
# Если ошибки есть - то возвращаем ответ с ошибкой
|
||||
if errors:
|
||||
return JsonResponse({"code": 409, "errors": errors}, safe=False, status=409)
|
||||
|
||||
confirm = call_func('nn_db.application_patch', params)
|
||||
|
||||
# Если ответ не пустой и есть поле подтверждения
|
||||
if any(confirm) and 'confirm' in confirm[0]:
|
||||
if confirm[0]['confirm']:
|
||||
# Если запись обновлена - возвращаем 202 ответ с сообщением
|
||||
return JsonResponse({"code": 202, "message": "Данные обновлены"}, safe=False, status=202)
|
||||
else:
|
||||
# Если запись не обновлена - то возвращаем ответ 304 с сообщением
|
||||
return JsonResponse({"code": 304, "message": "Данные не обновлены"}, safe=False, status=304)
|
||||
else:
|
||||
# Если нет - то возвращаем ошибку с сообщением
|
||||
return JsonResponse({"code": 520, "message": "Не удалось обновить запись в БД, попробуйте позднее"}, safe=False, status=520)
|
||||
|
||||
def api_statuses(request):
|
||||
user = is_auth(request)
|
||||
if not user:
|
||||
return JsonResponse({"code": 403, "message":"Доступ запрещен" }, safe=False, status=403)
|
||||
|
||||
if request.method == 'GET':
|
||||
results = call_func('nn_db.status_get', {})
|
||||
return JsonResponse({"code": 200, "data": results}, safe=False, status=200)
|
||||
|
||||
if request.method == 'POST':
|
||||
params = {}
|
||||
params['title'] = request.POST.get('title')
|
||||
|
||||
if params['title'] is None:
|
||||
return JsonResponse({"code": 409, "errors": [{"title": "Параметр обязателен для заполнения"}]}, safe=False, status=409)
|
||||
|
||||
if len(params['title']) <= 4:
|
||||
return JsonResponse({"code": 409, "errors": [{"title": "Описание статуса должно быть длинее 4 символов"}]}, safe=False, status=409)
|
||||
|
||||
confirm = call_func('nn_db.status_post', params)
|
||||
|
||||
# Проверяем, пришел ли в ответ на запрос первичный ключ добавленной заявки
|
||||
if any(confirm) and 'pk_status' in confirm[0]:
|
||||
# Если пришёл - то возвращаем данные
|
||||
return JsonResponse({"code": 201, "data": confirm}, safe=False, status=201)
|
||||
else:
|
||||
# Если нет - то возвращаем ошибку с сообщением
|
||||
return JsonResponse({"code": 520, "message": "Не удалось добавить запись в БД, попробуйте позднее"}, safe=False, status=520)
|
||||
|
||||
def api_users(request):
|
||||
if is_auth(request):
|
||||
|
||||
@@ -20,6 +20,7 @@ from api import views
|
||||
|
||||
urlpatterns = [
|
||||
path('api/applications/', views.api_applications)
|
||||
, path('api/statuses/', views.api_statuses)
|
||||
, path('api/get_xcsrf/', views.api_get_xcsrf)
|
||||
, path('api/users/', views.api_users)
|
||||
, path('api/auth/', views.api_auth)
|
||||
|
||||
Reference in New Issue
Block a user