diff --git a/Database/Функции/application_get.sql b/Database/Функции/application_get.sql new file mode 100644 index 0000000..7702b59 --- /dev/null +++ b/Database/Функции/application_get.sql @@ -0,0 +1,42 @@ +CREATE OR REPLACE FUNCTION nn_db.application_get( + in_pk_user nn_db.user.pk_user%TYPE) +RETURNS TABLE( + pk_application nn_db.application.pk_application%TYPE + , car_number nn_db.application.car_number%TYPE + , description nn_db.application.description%TYPE + , fk_status nn_db.application.fk_status%TYPE + , title nn_db.status.title%TYPE + , fk_user nn_db.application.fk_user%TYPE + , username nn_db.user.username%TYPE + , pk_image nn_db.image.pk_image%TYPE + , file_name nn_db.image.file_name%TYPE + , file_ext nn_db.image.file_ext%TYPE) +AS $$ +BEGIN + RETURN QUERY SELECT + nn_db.application.pk_application + , nn_db.application.car_number + , nn_db.application.description + , nn_db.application.fk_status + , nn_db.status.title + , nn_db.application.fk_user + , nn_db.user.username + , nn_db.image.pk_image + , nn_db.image.file_name + , nn_db.image.file_ext + FROM nn_db.application + INNER JOIN nn_db.status + ON nn_db.status.pk_status = nn_db.application.fk_status + INNER JOIN nn_db.user + ON nn_db.user.pk_user = nn_db.application.fk_user + LEFT JOIN nn_db.image + ON nn_db.image.fk_application = nn_db.application.pk_application + WHERE + CASE WHEN in_pk_user IS NULL + THEN nn_db.application.fk_user IN (SELECT nn_db.user.pk_user FROM nn_db.user) + ELSE + nn_db.application.fk_user = in_pk_user + END + ORDER BY nn_db.application.pk_application; +END; +$$ LANGUAGE plpgsql \ No newline at end of file diff --git a/Database/Функции/application_patch.sql b/Database/Функции/application_patch.sql new file mode 100644 index 0000000..a31406d --- /dev/null +++ b/Database/Функции/application_patch.sql @@ -0,0 +1,19 @@ +CREATE OR REPLACE FUNCTION nn_db.application_patch( + in_pk_application nn_db.application.pk_application%TYPE + , in_fk_status nn_db.application.fk_status%TYPE) +RETURNS TABLE(confirm boolean) +AS $$ +BEGIN + UPDATE nn_db.application + SET nn_db.application.fk_status = in_fk_status + WHERE + nn_db.application.pk_application = in_pk_application; + + RETURN QUERY SELECT ( + CASE WHEN + (SELECT fk_status FROM nn_db.application WHERE pk_application = in_pk_application LIMIT 1) = in_fk_status + THEN True + ELSE False + END); +END; +$$ LANGUAGE plpgsql \ No newline at end of file diff --git a/Database/Функции/application_post.sql b/Database/Функции/application_post.sql new file mode 100644 index 0000000..6665b06 --- /dev/null +++ b/Database/Функции/application_post.sql @@ -0,0 +1,22 @@ +CREATE OR REPLACE FUNCTION nn_db.application_post( + in_car_number nn_db.application.car_number%TYPE + , in_description nn_db.application.description%TYPE + , in_fk_user nn_db.application.fk_user%TYPE) +RETURNS TABLE(pk_application nn_db.application.pk_application%TYPE) +AS $$ +BEGIN + INSERT INTO nn_db.application ( + car_number + , description + , fk_status + , fk_user) + VALUES ( + in_car_number + , in_description + , (SELECT MIN(nn_db.status.pk_status) FROM nn_db.status) + , in_fk_user); + RETURN QUERY SELECT + MAX(nn_db.application.pk_application) + FROM nn_db.application; +END; +$$ LANGUAGE plpgsql; \ No newline at end of file diff --git a/Database/Функции/image_post.sql b/Database/Функции/image_post.sql new file mode 100644 index 0000000..7ea7752 --- /dev/null +++ b/Database/Функции/image_post.sql @@ -0,0 +1,12 @@ +CREATE OR REPLACE FUNCTION nn_db.image_post( + in_file_name nn_db.image.file_name%TYPE + , in_file_ext nn_db.image.file_ext%TYPE + , in_fk_application nn_db.image.fk_application%TYPE) +RETURNS TABLE(pk_image nn_db.image.pk_image%TYPE) +AS $$ +BEGIN + INSERT INTO nn_db.image (file_name, file_ext, fk_application) + VALUES (in_file_name, in_file_ext, in_fk_application); + RETURN QUERY SELECT MAX(nn_db.image.pk_image) FROM nn_db.image; +END; +$$ LANGUAGE plpgsql \ No newline at end of file diff --git a/Database/Функции/status_get.sql b/Database/Функции/status_get.sql new file mode 100644 index 0000000..11e93f5 --- /dev/null +++ b/Database/Функции/status_get.sql @@ -0,0 +1,12 @@ +CREATE OR REPLACE FUNCTION nn_db.status_get() +RETURNS TABLE( + pk_status nn_db.status.pk_status%TYPE + , title nn_db.status.title%TYPE) +AS $$ +BEGIN + RETURN QUERY SELECT + nn_db.status.pk_status, nn_db.status.title + FROM nn_db.status + ORDER BY nn_db.status.pk_status; +END; +$$ LANGUAGE plpgsql \ No newline at end of file diff --git a/Database/Функции/status_post.sql b/Database/Функции/status_post.sql new file mode 100644 index 0000000..9696c7d --- /dev/null +++ b/Database/Функции/status_post.sql @@ -0,0 +1,11 @@ +CREATE OR REPLACE FUNCTION nn_db.status_post( + in_title nn_db.status.title%TYPE) +RETURNS TABLE(pk_status nn_db.status.pk_status%TYPE) +AS $$ +BEGIN + INSERT INTO nn_db.status (title) + VALUES (in_title); + + RETURN QUERY SELECT MAX(nn_db.status.pk_status) FROM nn_db.status; +END; +$$ LANGUAGE plpgsql \ No newline at end of file diff --git a/Database/Функции/user_activate.sql b/Database/Функции/user_activate.sql new file mode 100644 index 0000000..c240959 --- /dev/null +++ b/Database/Функции/user_activate.sql @@ -0,0 +1,16 @@ +CREATE OR REPLACE FUNCTION nn_db.user_activate( + in_pk_user nn_db.user.pk_user%TYPE) +RETURNS TABLE(confirm boolean) +AS $$ +BEGIN + UPDATE nn_db.user + SET is_active = True + WHERE + pk_user = in_pk_user; + RETURN QUERY SELECT + is_active = True + FROM nn_db.user + WHERE + nn_db.user.pk_user = in_pk_user; +END; +$$ LANGUAGE plpgsql \ No newline at end of file diff --git a/Database/Функции/user_get.sql b/Database/Функции/user_get.sql new file mode 100644 index 0000000..f0b3cd2 --- /dev/null +++ b/Database/Функции/user_get.sql @@ -0,0 +1,32 @@ +CREATE OR REPLACE FUNCTION nn_db.user_get( + in_search_value nn_db.user.username%TYPE) +RETURNS TABLE( + pk_user nn_db.user.pk_user%TYPE + , lastname nn_db.user.lastname%TYPE + , firstname nn_db.user.firstname%TYPE + , middlename nn_db.user.middlename%TYPE + , username nn_db.user.username%TYPE + , password_hash nn_db.user.password_hash%TYPE + , email nn_db.user.email%TYPE + , phone nn_db.user.phone%TYPE + , is_admin nn_db.user.is_admin%TYPE + , is_active nn_db.user.is_active%TYPE) +AS $$ +BEGIN + RETURN QUERY SELECT + nn_db.user.pk_user + , nn_db.user.lastname + , nn_db.user.firstname + , nn_db.user.middlename + , nn_db.user.username + , nn_db.user.password_hash + , nn_db.user.email + , nn_db.user.phone + , nn_db.user.is_admin + , nn_db.user.is_active + FROM nn_db.user + WHERE + nn_db.user.username ILIKE in_search_value + OR nn_db.user.email ILIKE in_search_value; +END; +$$ LANGUAGE plpgsql \ No newline at end of file diff --git a/Database/Функции/user_post.sql b/Database/Функции/user_post.sql new file mode 100644 index 0000000..43d24ac --- /dev/null +++ b/Database/Функции/user_post.sql @@ -0,0 +1,35 @@ +CREATE OR REPLACE FUNCTION nn_db.user_post( + in_lastname nn_db.user.lastname%TYPE + , in_firstname nn_db.user.firstname%TYPE + , in_middlename nn_db.user.middlename%TYPE + , in_username nn_db.user.username%TYPE + , in_password_hash nn_db.user.password_hash%TYPE + , in_email nn_db.user.email%TYPE + , in_phone nn_db.user.phone%TYPE) +RETURNS TABLE(pk_user nn_db.user.pk_user%TYPE) +AS $$ +BEGIN + INSERT INTO nn_db.user( + lastname + , firstname + , middlename + , username + , password_hash + , email + , phone + , is_admin + , is_active) + VALUES( + in_lastname + , in_firstname + , in_middlename + , in_username + , in_password_hash + , in_email + , in_phone + , False + , False); + + RETURN QUERY SELECT MAX(nn_db.user.pk_user) FROM nn_db.user; +END; +$$ LANGUAGE plpgsql \ No newline at end of file diff --git a/Project/nn_project/api/__init__.py b/Project/nn_project/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Project/nn_project/api/__pycache__/__init__.cpython-314.pyc b/Project/nn_project/api/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..879a516 Binary files /dev/null and b/Project/nn_project/api/__pycache__/__init__.cpython-314.pyc differ diff --git a/Project/nn_project/api/__pycache__/admin.cpython-314.pyc b/Project/nn_project/api/__pycache__/admin.cpython-314.pyc new file mode 100644 index 0000000..a6b7c08 Binary files /dev/null and b/Project/nn_project/api/__pycache__/admin.cpython-314.pyc differ diff --git a/Project/nn_project/api/__pycache__/apps.cpython-314.pyc b/Project/nn_project/api/__pycache__/apps.cpython-314.pyc new file mode 100644 index 0000000..2322cd1 Binary files /dev/null and b/Project/nn_project/api/__pycache__/apps.cpython-314.pyc differ diff --git a/Project/nn_project/api/__pycache__/models.cpython-314.pyc b/Project/nn_project/api/__pycache__/models.cpython-314.pyc new file mode 100644 index 0000000..84cc166 Binary files /dev/null and b/Project/nn_project/api/__pycache__/models.cpython-314.pyc differ diff --git a/Project/nn_project/api/__pycache__/views.cpython-314.pyc b/Project/nn_project/api/__pycache__/views.cpython-314.pyc new file mode 100644 index 0000000..49186a9 Binary files /dev/null and b/Project/nn_project/api/__pycache__/views.cpython-314.pyc differ diff --git a/Project/nn_project/api/admin.py b/Project/nn_project/api/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/Project/nn_project/api/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/Project/nn_project/api/apps.py b/Project/nn_project/api/apps.py new file mode 100644 index 0000000..d87006d --- /dev/null +++ b/Project/nn_project/api/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ApiConfig(AppConfig): + name = 'api' diff --git a/Project/nn_project/api/migrations/__init__.py b/Project/nn_project/api/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Project/nn_project/api/migrations/__pycache__/__init__.cpython-314.pyc b/Project/nn_project/api/migrations/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..49fe690 Binary files /dev/null and b/Project/nn_project/api/migrations/__pycache__/__init__.cpython-314.pyc differ diff --git a/Project/nn_project/api/models.py b/Project/nn_project/api/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/Project/nn_project/api/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/Project/nn_project/api/tests.py b/Project/nn_project/api/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/Project/nn_project/api/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/Project/nn_project/api/views.py b/Project/nn_project/api/views.py new file mode 100644 index 0000000..2770b2b --- /dev/null +++ b/Project/nn_project/api/views.py @@ -0,0 +1,219 @@ +from django.shortcuts import render +from django.http import JsonResponse +from django.db import connection + +from django.middleware.csrf import get_token +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.views.decorators.csrf import csrf_exempt +import re + + +def call_func(name: str, parameters: dict): + with connection.cursor() as cursor: + if parameters: + this_params = [] + for param in list(parameters.values()): + if type(param) == str: + this_params.append(f"'{param}'") + elif param is None: + this_params.append("null") + else: + this_params.append(param) + + cursor.execute(f"SELECT * FROM {name}({', '.join(this_params)})") + else: + cursor.execute(f"SELECT * FROM {name}()") + columns = [col[0] for col in cursor.description] + return [dict(zip(columns, row)) for row in cursor.fetchall()] + +def api_get_xcsrf(request): + data = { 'X-CSFRToken': 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 + else: + params['pk_user'] = str(user['pk_user']) + # params['pk_user'] = None + results = call_func('nn_db.application_get', params) + + applications = [] + keys = [] + 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'] + application['fk_status'] = result['fk_status'] + 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['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 = {} + 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['car_number'] = request.POST.get('car_number') + params['description'] = request.POST.get('description') + params['fk_user'] = user['pk_user'] + confirm = call_func('nn_db.application_post', params) + return JsonResponse({"code": 201, "data": confirm}, safe=False, status=201) + +def api_users(request): + if is_auth(request): + return JsonResponse({ "code": 403, "message":"Доступ запрещен" }, safe=False, status=403) + if request.method == 'POST': + params = [] + + + lastname = request.POST.get('lastname') + firstname = request.POST.get('firstname') + middlename = request.POST.get('middlename') + username = request.POST.get('username') + password = request.POST.get('password') + email = request.POST.get('email') + phone = request.POST.get('phone') + + errors = [] + + if lastname is None: + errors.append({ "lastname": "Параметр обязателен для заполнения" }) + if firstname is None: + errors.append({ "firstname": "Параметр обязателен для заполнения" }) + if username is None: + errors.append({ "username": "Параметр обязателен для заполнения" }) + if password is None: + errors.append({ "password": "Параметр обязателен для заполнения" }) + if email is None: + errors.append({ "email": "Параметр обязателен для заполнения" }) + if phone is None: + errors.append({ "phone": "Параметр обязателен для заполнения" }) + + if errors: + return JsonResponse({"code": 409, "errors": errors}, safe=False, status=409) + + if len(lastname) < 6: + errors.append({ "lastname": "Фамилия должна быть длинее 6 символов" }) + elif len(lastname) > 60: + errors.append({ "lastname": "Фамилия должна быть короче 60 символов" }) + if len(firstname) < 6: + errors.append({ "firstname": "Имя должна быть длинее 6 символов" }) + elif len(firstname) > 60: + errors.append({ "firstname": "Имя должна быть короче 60 символов" }) + if middlename is not None: + if len(middlename) != 0: + if len(middlename) < 6: + errors.append({ "middlename": "Отчество должна быть длинее 6 символов" }) + elif len(middlename) > 60: + errors.append({ "middlename": "Отчество должна быть короче 60 символов" }) + + if len(username) < 6: + errors.append({ "username": "Имя пользователя должно быть длинее 6 символов" }) + elif len(username) > 60: + errors.append({ "username": "Имя пользователя должно быть короче 60 символов" }) + if len(password) < 8: + errors.append({ "password": "Пароль должен быть длинее 8 символов" }) + + + if len(email) < 5: + errors.append({ "email": "Адрес электронной почты должен быть длинее 5 символов" }) + elif re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', email) is None: + errors.append({ "email": "Адрес электронной почты имеет некорректный формат" }) + if len(phone) < 11: + errors.append({ "phone": "Номер телефона должен быть длинее 10 символов" }) + elif len(phone) > 12: + errors.append({ "phone": "Номер телефона должен быть короче 12 символов" }) + elif re.match(r'^(?:\+79|89)\d{9}$', phone) is None: + errors.append({ "phone": "Номер телефона имеет некорректный формат" }) + + if errors: + return JsonResponse({"code": 409, "errors": errors}, safe=False, status=409) + + + + user_username = call_func('nn_db.user_get', {"search_value": username}) + user_email = call_func('nn_db.user_get', {"search_value": email}) + if not(user_username) and not(user_email): + hasher = PBKDF2PasswordHasher() + password_hash = hasher.encode(password, salt='extra') + pk_user = call_func("nn_db.user_post", {"lastname": lastname, "firstname": firstname, "middlename": middlename, "username": username, "password_hash": password_hash, "email": email, "phone": phone})[0]['pk_user'] + user = call_func("nn_db.user_get", {"search_value": username})[0] + return JsonResponse(user, safe=False, status=201) + else: + return JsonResponse({"code": 409, "message":"Пользователь c таким именем или адресом электронной почты существует"}, safe=False, status=409) + +def api_auth(request): + if is_auth(request): + return JsonResponse({ "code": 403, "message":"Доступ запрещен" }, safe=False, status=403) + if request.method == 'POST': + response = {} + login = request.POST.get('login') + password = request.POST.get('password') + + errors = [] + + if len(login) < 6: + errors.append({ "login": "Имя пользователя должно быть длинее 6 символов" }) + elif len(login) > 60: + errors.append({ "login": "Имя пользователя должно быть короче 60 символов" }) + if len(password) < 8: + errors.append({ "password": "Пароль должен быть длинее 8 символов" }) + + if errors: + return JsonResponse({"code": 409, "errors": errors}, safe=False, status=409) + + user = call_func('nn_db.user_get', {'search_value': login}) + if user: + user = user[0] + hasher = PBKDF2PasswordHasher() + if not hasher.verify(password, user['password_hash']): + return JsonResponse({ "code": 401, "message":"Неверное имя пользователя или пароль" }, safe=False, status=401) + response = user + signer = TimestampSigner(salt='django.core.signing') + token = urlsafe_base64_encode(force_bytes(signer.sign(user['username']))) + response['token'] = token + return JsonResponse(response, safe=False, status=200) + else: + return JsonResponse({ "code": 401, "message":"Неверное имя пользователя или пароль" }, safe=False, status=401) \ No newline at end of file diff --git a/Project/nn_project/manage.py b/Project/nn_project/manage.py new file mode 100644 index 0000000..1a56756 --- /dev/null +++ b/Project/nn_project/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nn_project.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/Project/nn_project/nn_project/__init__.py b/Project/nn_project/nn_project/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Project/nn_project/nn_project/__pycache__/__init__.cpython-314.pyc b/Project/nn_project/nn_project/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..322b2a4 Binary files /dev/null and b/Project/nn_project/nn_project/__pycache__/__init__.cpython-314.pyc differ diff --git a/Project/nn_project/nn_project/__pycache__/settings.cpython-314.pyc b/Project/nn_project/nn_project/__pycache__/settings.cpython-314.pyc new file mode 100644 index 0000000..9476eac Binary files /dev/null and b/Project/nn_project/nn_project/__pycache__/settings.cpython-314.pyc differ diff --git a/Project/nn_project/nn_project/__pycache__/urls.cpython-314.pyc b/Project/nn_project/nn_project/__pycache__/urls.cpython-314.pyc new file mode 100644 index 0000000..2045b47 Binary files /dev/null and b/Project/nn_project/nn_project/__pycache__/urls.cpython-314.pyc differ diff --git a/Project/nn_project/nn_project/__pycache__/wsgi.cpython-314.pyc b/Project/nn_project/nn_project/__pycache__/wsgi.cpython-314.pyc new file mode 100644 index 0000000..1b3381f Binary files /dev/null and b/Project/nn_project/nn_project/__pycache__/wsgi.cpython-314.pyc differ diff --git a/Project/nn_project/nn_project/asgi.py b/Project/nn_project/nn_project/asgi.py new file mode 100644 index 0000000..ea0f701 --- /dev/null +++ b/Project/nn_project/nn_project/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for nn_project project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/6.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nn_project.settings') + +application = get_asgi_application() diff --git a/Project/nn_project/nn_project/settings.py b/Project/nn_project/nn_project/settings.py new file mode 100644 index 0000000..626a670 --- /dev/null +++ b/Project/nn_project/nn_project/settings.py @@ -0,0 +1,121 @@ +""" +Django settings for nn_project project. + +Generated by 'django-admin startproject' using Django 6.0.5. + +For more information on this file, see +https://docs.djangoproject.com/en/6.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/6.0/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-!k9d_ze3011xbu#lo71%5f+g8p#qsvsuqmnb@h3o&qdz@(vaay' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'api' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'nn_project.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'nn_project.wsgi.application' + +# Database +# https://docs.djangoproject.com/en/6.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'nn_db', + 'USER': 'postgres', + 'PASSWORD': 'postgres', + 'HOST': '127.0.0.1', + 'PORT': '5432' + } +} + + +# Password validation +# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/6.0/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/6.0/howto/static-files/ + +STATIC_URL = 'static/' diff --git a/Project/nn_project/nn_project/urls.py b/Project/nn_project/nn_project/urls.py new file mode 100644 index 0000000..b1a9cf3 --- /dev/null +++ b/Project/nn_project/nn_project/urls.py @@ -0,0 +1,26 @@ +""" +URL configuration for nn_project project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/6.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path +from api import views + +urlpatterns = [ + path('api/applications/', views.api_applications) + , path('api/get_xcsrf/', views.api_get_xcsrf) + , path('api/users/', views.api_users) + , path('api/auth/', views.api_auth) +] diff --git a/Project/nn_project/nn_project/wsgi.py b/Project/nn_project/nn_project/wsgi.py new file mode 100644 index 0000000..d13f005 --- /dev/null +++ b/Project/nn_project/nn_project/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for nn_project project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/6.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nn_project.settings') + +application = get_wsgi_application()