Updated version

This commit is contained in:
louai98 2023-07-31 09:58:36 +02:00
parent cd8d7b0e2c
commit 49eb16d0ac
53 changed files with 430 additions and 69360 deletions

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

15
admin_api/api/urls.py Normal file
View File

@ -0,0 +1,15 @@
from django.urls import path
from . import views
from .views import MyTokenObtainPairView
from rest_framework_simplejwt.views import (
TokenRefreshView,
)
urlpatterns = [
path('', views.getRoutes, name="routes"),
path('token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

29
admin_api/api/views.py Normal file
View File

@ -0,0 +1,29 @@
from django.http import JsonResponse
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
# Add custom claims
token['username'] = user.username
# ...
return token
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
@api_view(['GET'])
def getRoutes(request):
routes = [
'/api/token',
'/api/token/refresh',
]
return Response(routes)

View File

@ -25,6 +25,8 @@ urlpatterns = [
path('pre-process/', views.preprocess, name='pre-process'), path('pre-process/', views.preprocess, name='pre-process'),
path('api/', include('admin_api.api.urls')),
path('login/', views.loginPage, name='login'), path('login/', views.loginPage, name='login'),
path('logout/', views.logoutPage, name='logout'), path('logout/', views.logoutPage, name='logout'),
] ]

View File

@ -10,16 +10,18 @@ from django.views.decorators.csrf import csrf_exempt
import json import json
import os import os
from pathlib import Path from pathlib import Path
from rest_framework.decorators import api_view from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from django.db.models import Max from django.db.models import Max
import shutil import shutil
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib import messages from django.contrib import messages
from .preprocessData import PreprocessData from .preprocessData import PreprocessData
# Create your views here. # Create your views here.
@permission_classes([IsAuthenticated])
class LevelViewSet(viewsets.ModelViewSet): class LevelViewSet(viewsets.ModelViewSet):
queryset = Level.objects.all() queryset = Level.objects.all()
serializer_class = LevelSerializer serializer_class = LevelSerializer
@ -35,6 +37,10 @@ class NewContentTrackerViewSet(viewsets.ModelViewSet):
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
# ################################################################
# #######################Contents#################################
# ################################################################
@csrf_exempt @csrf_exempt
@api_view(['GET']) @api_view(['GET'])
def contentList(request): def contentList(request):
@ -202,11 +208,11 @@ def levelDelete(request):
haveToPreProcess(data['id'], data['levelNumber'], 'No', 'LevelDeleted') haveToPreProcess(data['id'], data['levelNumber'], 'No', 'LevelDeleted')
return Response('Item successfully deleted!') return Response('')
# ################################################################ # ################################################################
# #######################Standards################################### # #######################Standards################################
# ################################################################ # ################################################################
@csrf_exempt @csrf_exempt
@ -254,7 +260,7 @@ def standardDelete(request):
return Response('Item successfully deleted!') return Response('Item successfully deleted!')
# ################################################################ # ################################################################
# #######################pre-process################################### # #######################pre-process##############################
# ################################################################ # ################################################################
@csrf_exempt @csrf_exempt
@api_view(['POST']) @api_view(['POST'])
@ -265,7 +271,7 @@ def preprocess(request):
return Response('Procssed successfully') return Response('Procssed successfully')
# ################################################################ # ################################################################
# #######################Login/out################################### # #######################Authentication###########################
# ################################################################ # ################################################################
def loginPage(request): def loginPage(request):
@ -275,6 +281,10 @@ def loginPage(request):
def logoutPage(request): def logoutPage(request):
pass pass
# ################################################################
# ################################################################
# ################################################################
def filePath(level_input, standard_input): def filePath(level_input, standard_input):
standards_dir = os.path.join(BASE_DIR, 'static/data/') standards_dir = os.path.join(BASE_DIR, 'static/data/')
file_path = '' file_path = ''

Binary file not shown.

View File

@ -11,6 +11,9 @@ https://docs.djangoproject.com/en/4.1/ref/settings/
""" """
from pathlib import Path from pathlib import Path
from datetime import timedelta
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@ -30,9 +33,9 @@ ALLOWED_HOSTS = []
# In this particular case, it is allowing cross-origin requests from # In this particular case, it is allowing cross-origin requests from
# the specified origin http://localhost:3000, which is the default origin # the specified origin http://localhost:3000, which is the default origin
# for a locally served React application during development. # for a locally served React application during development.
CORS_ALLOWED_ORIGINS = [ #CORS_ALLOWED_ORIGINS = [
'http://localhost:3000', # 'http://localhost:3000',
] #]
CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_CREDENTIALS = True
@ -47,13 +50,65 @@ INSTALLED_APPS = [
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'rest_framework', 'rest_framework',
'rest_framework_simplejwt.token_blacklist',
'django_filters', 'django_filters',
'search_tfidf', 'search_tfidf',
'admin_api', 'admin_api',
'user_auth',
'corsheaders', 'corsheaders',
] ]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
"REFRESH_TOKEN_LIFETIME": timedelta(days=90),
"ROTATE_REFRESH_TOKENS": True,
"BLACKLIST_AFTER_ROTATION": True,
"UPDATE_LAST_LOGIN": False,
"ALGORITHM": "HS256",
"VERIFYING_KEY": "",
"AUDIENCE": None,
"ISSUER": None,
"JSON_ENCODER": None,
"JWK_URL": None,
"LEEWAY": 0,
"AUTH_HEADER_TYPES": ("Bearer",),
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
"USER_ID_FIELD": "id",
"USER_ID_CLAIM": "user_id",
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
"TOKEN_TYPE_CLAIM": "token_type",
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
"JTI_CLAIM": "jti",
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
"TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
"TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
"TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
"TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
"SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
"SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
}
MIDDLEWARE = [ MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
@ -62,16 +117,15 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
] ]
ROOT_URLCONF = 'iddrs_api.urls' ROOT_URLCONF = 'iddrs_api.urls'
print(BASE_DIR)
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], 'DIRS': [os.path.join(BASE_DIR,'templates')],
'APP_DIRS': True, 'APP_DIRS': True,
'OPTIONS': { 'OPTIONS': {
'context_processors': [ 'context_processors': [
@ -97,6 +151,17 @@ DATABASES = {
} }
} }
## User model
## AUTH_USER_MODEL = 'user_auth.AppUser'
##
## REST_FRAMEWORK = {
## 'DEFAULT_AUTHENTICATION_CLASSES': (
## 'rest_framework.authentication.SessionAuthentication',
## ),
## 'DEFAULT_PERMISSION_CLASSES': (
## 'rest_framework.permissions.IsAuthenticated',
## )}
# Password validation # Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

View File

@ -20,4 +20,5 @@ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('client_api/', include('search_tfidf.urls')), path('client_api/', include('search_tfidf.urls')),
path('admin_api/', include('admin_api.urls')), path('admin_api/', include('admin_api.urls')),
path('user_auth/', include('user_auth.urls')),
] ]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -109,8 +109,8 @@ def cosine_similarity(phrase, title):
results = dff.reset_index().to_json(orient ='records') results = dff.reset_index().to_json(orient ='records')
results = json.loads(results) results = json.loads(results)
with open(os.path.join(BASE_DIR, 'media/usersResults/'+phrase+'.json'), 'w', encoding='utf-8') as f: #with open(os.path.join(BASE_DIR, 'media/usersResults/'+phrase+'.json'), 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=True, indent=4) # json.dump(results, f, ensure_ascii=True, indent=4)
'''The results are returned from the function.''' '''The results are returned from the function.'''
return results return results

View File

@ -11,4 +11,5 @@ router.register(r'standards', StandardsViewSet)
urlpatterns = [ urlpatterns = [
path('', include(router.urls)), path('', include(router.urls)),
path('get_input/', views.get_input, name='get_input'), path('get_input/', views.get_input, name='get_input'),
path('exportPDF/', views.exportPDF, name='exportPDF'),
] ]

View File

@ -6,6 +6,18 @@ from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
import json import json
from .tfidfSearch import cosine_similarity from .tfidfSearch import cosine_similarity
from rest_framework.decorators import api_view
from pathlib import Path
import os
from django.template.loader import render_to_string
from weasyprint import HTML
from django.http import HttpResponse
from django.views.generic import View
from io import BytesIO
from django.template.loader import get_template
from xhtml2pdf import pisa
# Create your views here. # Create your views here.
@ -37,4 +49,29 @@ def get_input(request):
return JsonResponse({"message": "Data received", "results":searchResults}) return JsonResponse({"message": "Data received", "results":searchResults})
return JsonResponse({"message": "Invalid request"}) return JsonResponse({"message": "Invalid request"})
@csrf_exempt
@api_view(['POST'])
def exportPDF(request):
if request.method == "POST":
filteredResults = request.data['params']['filteredResults']
phrase = request.data['params']['phrase']
template = get_template('export/outputPDF.html')
html = template.render({'results': filteredResults, 'phrase': phrase})
#html = template.render()
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename="output.pdf"'
try:
pisa_status = pisa.CreatePDF(html, dest=response)
if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
#response['Content-Type'] = 'application/pdf' # Set the Content-Type after generating the PDF
print(response)
return response
except Exception as e:
return HttpResponse(f'Error generating PDF: {str(e)}', status=500)

68
templates/export/outputPDF.html Executable file
View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Bootstrap CSS -->
<title>{{ phrase }}</title>
<style>
@media print {
body{
width: 21cm;
height: 29.7cm;
margin: 15mm 15mm 15mm 15mm;
/* change the margins as you want them to be. */
}
}
p{
font-family: Arial, Helvetica, sans-serif;
font-size: 12px !important;
}
.indent{
margin-left: 15px;
}
.level{
font-size: 14px !important;
}
.level-text-1 {
color: #F07F4E;
}
.level-text-2 {
color: #008DCA;
}
.level-text-3 {
color: #00A554;
}
.level-text-4 {
color: #7366A3;
}
.level-text-5 {
color: #D10007;
}
.level-text-6 {
color: #CF7AB2;
}
</style>
</head>
<body>
<h1>{{ phrase }}</h1>
{% for result in results %}
<p>
<span class="level level-text-{{result.Level}}">Level {{ result.Level }} {{ result.LevelName }}</span>
<br />
IDDRS {{ result.Module }} <br /><span class="indent">{{ result.Heading1 }}
</span>
<br /><span class="indent">Page: {{ result.PageNum }} </span> <br />{{result.Paragraph|safe|linebreaks }}
</p>
<hr />
{% endfor %}
</body>
</html>

0
user_auth/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

6
user_auth/admin.py Normal file
View File

@ -0,0 +1,6 @@
from django.contrib import admin
from .models import *
# Register your models here.
admin.site.register(AppUser)
#admin.site.register(AppUserManager)

6
user_auth/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class UserAuthConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'user_auth'

View File

@ -0,0 +1,31 @@
# Generated by Django 4.1.3 on 2023-07-13 11:30
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name='AppUser',
fields=[
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('user_id', models.AutoField(primary_key=True, serialize=False)),
('email', models.EmailField(max_length=50, unique=True)),
('username', models.CharField(max_length=50)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to.', related_name='iddrs_users', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='iddrs_users', to='auth.permission', verbose_name='user permissions')),
],
options={
'abstract': False,
},
),
]

View File

51
user_auth/models.py Normal file
View File

@ -0,0 +1,51 @@
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, Group, Permission
from django.contrib.auth.base_user import BaseUserManager
# Create your models here.
class AppUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('The email must be set')
if not password:
raise ValueError('The password must be set')
email = self.normalize_email(email)
user = self.model(email=email)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password=None):
if not email:
raise ValueError('The email must be set')
if not password:
raise ValueError('The password must be set')
user = self.create_user(email, password)
user.is_superuser = True
user.save()
return user
class AppUser(AbstractBaseUser, PermissionsMixin):
user_id = models.AutoField(primary_key=True)
email = models.EmailField(max_length=50, unique=True)
username = models.CharField(max_length=50)
groups = models.ManyToManyField(
Group,
verbose_name='groups',
blank=True,
help_text='The groups this user belongs to.',
related_name='iddrs_users' # Add a unique related_name
)
user_permissions = models.ManyToManyField(
Permission,
verbose_name='user permissions',
blank=True,
help_text='Specific permissions for this user.',
related_name='iddrs_users' # Add a unique related_name
)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = AppUserManager()
def __str__(self):
return self.username

32
user_auth/serializers.py Normal file
View File

@ -0,0 +1,32 @@
from rest_framework import serializers
from django.contrib.auth import get_user_model, authenticate
USERModel = get_user_model()
class UserRegisterSerializer(serializers.ModelSerializer):
class Meta:
model = USERModel
fields = '__all__'
extra_kwargs = {'password': {'write_only': True, 'min_length': 8}}
def create(self, clean_data):
user_obj = USERModel.objects.create_user(email=clean_data['email'], password=clean_data['password'])
user_obj.username = clean_data['username']
user_obj.save()
return user_obj
class UserLoginSerializer(serializers.Serializer):
email = serializers.EmailField()
password = serializers.CharField()
##
def check_user(self, clean_data):
user = authenticate(username=clean_data['email'], password=clean_data['password'])
if user:
return user
if not user:
raise serializers.ValidationError("Incorrect Credentials")
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = USERModel
fields = ('email', 'username')

3
user_auth/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
user_auth/urls.py Normal file
View File

@ -0,0 +1,9 @@
from django.urls import path
from . import views
urlpatterns = [
path('register/', views.UserRegister.as_view(), name='register'),
path('login/', views.UserLogin.as_view(), name='login'),
path('logout/', views.UserLogout.as_view(), name='logout'),
path('user/', views.UserView.as_view(), name='view'),
]

48
user_auth/views.py Normal file
View File

@ -0,0 +1,48 @@
from django.shortcuts import render
from rest_framework import permissions, status
from django.contrib.auth import get_user_model, login, logout
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import UserRegisterSerializer, UserLoginSerializer, UserSerializer
from rest_framework.authentication import SessionAuthentication
# Create your views here.
class UserRegister(APIView):
permission_classes = (permissions.AllowAny,)
serializer_class = UserRegisterSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
user = serializer.create(serializer.validated_data)
if user:
return Response({'message': 'User Created Successfully'}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class UserLogin(APIView):
permission_classes = (permissions.AllowAny,)
authentication_classes = (SessionAuthentication,)
##
serializer_class = UserLoginSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
user = serializer.check_user(serializer.validated_data)
if user:
login(request, user)
return Response({'message': 'User Logged In Successfully'}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class UserLogout(APIView):
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get(self, request):
logout(request)
return Response({'message': 'User Logged Out Successfully'}, status=status.HTTP_200_OK)
class UserView(APIView):
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get(self, request):
serializer = UserSerializer(request.user)
return Response(serializer.data, status=status.HTTP_200_OK)