Token authentication + send file endpoint

This commit is contained in:
Marcin Armacki 2020-11-14 20:15:59 +01:00
parent 81c83e3313
commit d8c49b1bd7
10 changed files with 165 additions and 60 deletions

View File

@ -1,2 +0,0 @@
MethodNotAllowed = {"message": "Error: Method not allowed",
"statusCode": 405}

View File

@ -1,6 +0,0 @@
class UserAuthFailed(Exception):
def __init__(self, message, payload = None):
self.message = message
self.payload = payload
def __str__(self):
return str(self.message)

View File

@ -0,0 +1,29 @@
from prototype.filehandler.statusCodes import DatabaseAddSuccess, DatabaseAddFail
from prototype.filehandler.models import Forum, Discussion, Post, Paragraph
def addDataToDatabase(data, file_id):
try:
out = {}
para_id = []
messages = []
forum = Forum(forum_id = data['id'], name = data['name'], document_id = file_id)
print(forum)
forum.save()
for discussion_ in data['discussions']:
discussion = Discussion(discussion_id = discussion_['id'], title = discussion_['title'], first_post = discussion_['first_post'], forum_id = forum.pk)
discussion.save()
for post_ in discussion_['posts']:
post = Post(post_id = post_['id'], parent = post_['parent'], author = post_['author'], discussion_id = discussion.pk)
post.save()
for paragraph_ in post_['message']:
paragraph = Paragraph(message = paragraph_, label = '', post_id = post.pk)
paragraph.save()
para_id.append(paragraph.pk)
messages.append(paragraph_)
out['para_id'] = para_id
out['messages'] = messages
result = DatabaseAddSuccess
except:
result = UnknownError
finally:
return result

View File

@ -4,4 +4,4 @@ from prototype.filehandler.models import Document
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ('file', )
fields = ('file', 'user_id',)

View File

@ -4,6 +4,7 @@ from django.db import models
class Document(models.Model):
file = models.FileField(upload_to='documents/')
uploaded_at = models.DateTimeField(auto_now_add=True)
user_id = models.IntegerField()
class Forum(models.Model):
forum_id = models.IntegerField()

View File

@ -0,0 +1,12 @@
import time
def verifyExpiration(payload):
if "exp" not in payload or int(time.time()) > int(payload["exp"]):
return False
else:
return True
def verifyContent(payload):
expectedKeys = ["iss", "iat", "sub"]
actualKeys = [*payload]
isProperStructure = all([True if key in actualKeys else False for key in expectedKeys])
return all([isProperStructure, payload["iss"] == "NKADF"])

View File

@ -3,7 +3,7 @@ import time
from django.contrib.auth import authenticate
from django.conf import settings
from django.contrib.auth.models import User
from prototype.filehandler.exceptions import UserAuthFailed
from prototype.filehandler.tokenAuthModule import verifyExpiration, verifyContent
def registerNewUser(login, password):
try:
@ -42,13 +42,25 @@ def loginUser(login, password):
finally:
return result
def decodeToken(token):
def checkUserToken(request):
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorith = "HS256")
result = payload
return payload
if "HTTP_BEARER" not in request.META:
raise Exception("Error: Token is missing", 401)
payload = jwt.decode(request.META["HTTP_BEARER"], settings.SECRET_KEY, algorithm = "HS256")
if not verifyExpiration(payload):
raise Exception("Error: Token has expired", 401)
if not verifyContent(payload):
raise Exception("Error: Token payload is invalid", 401)
result = {"message": "Token authenticated successfully",
"statusCode": 200}
user_id = payload["sub"]
except jwt.exceptions.DecodeError:
result = {"messege": "Error: Invalid token given",
"statusCode": 400}
user_id = None
except Exception as error:
result = {"message": str(error),
"statusCode": 500}
result = {"message": str(error.args[0]),
"statusCode": int(error.args[1])}
user_id = None
finally:
return result
return result, user_id

View File

@ -1,16 +1,23 @@
from django.shortcuts import render, redirect
from django.conf import settings
from django.core import serializers
from django.core.files.storage import FileSystemStorage
from django.views.decorators.csrf import csrf_exempt
from django.forms.models import model_to_dict
from django.http import JsonResponse, HttpResponse
import json
from prototype.filehandler.serializers import ExtendedEncoder
from prototype.filehandler.models import Document, Forum
from prototype.filehandler.forms import DocumentForm
from prototype.filehandler.xmlParser import parseData
from prototype.filehandler.functions import addToDatabase, listDiscussionsFromFile, listParagraphsFromDiscussion, createLabels, listPostsFromDiscussion, updateLabelsByParagraphId
from prototype.filehandler.userModule import registerNewUser, loginUser, decodeToken
from prototype.filehandler.errorCodes import MethodNotAllowed
from prototype.filehandler.userModule import registerNewUser, loginUser, checkUserToken
from prototype.filehandler.fileModule import addDataToDatabase
from prototype.filehandler.exceptions import InvalidForm, CouldNotParse, InvalidMethod, KnownError
from prototype.filehandler.statusCodes import MethodNotAllowed, FileUploadSuccess, UnknownError, ParseFailed
def home(request):
@ -95,7 +102,55 @@ def login(request):
@csrf_exempt
def testToken(request):
if request.method == 'POST':
result = decodeToken(request.POST["token"])
result = testToken(request)
return JsonResponse(result, status = 200)
else:
return JsonResponse(MethodNotAllowed, status = MethodNotAllowed["statusCode"])
@csrf_exempt
def file(request):
try:
noStatus = False
if request.method == 'POST':
result, user_id = checkUserToken(request)
if result["statusCode"] != 200:
raise KnownError
form = DocumentForm({"user_id": user_id}, request.FILES)
if not form.is_valid():
raise InvalidForm
data = parseData(request.FILES["file"])
if data == False:
raise CouldNotParse
file_id = (form.save()).pk
result = addDataToDatabase(data, file_id)
if result["statusCode"] != 200:
raise KnownError
else:
result = FileUploadSuccess
elif request.method == 'GET':
result, user_id = checkUserToken(request)
if result["statusCode"] != 200:
raise KnownError
data = list(Document.objects.filter(user_id = user_id).values("id", "file", "uploaded_at"))
noStatus = True
except InvalidForm:
result = UnknownError
except InvalidMethod:
result = MethodNotAllowed
except CouldNotParse:
result = ParseFailed
except KnownError:
pass
except:
result = UnknownError
finally:
if noStatus:
return JsonResponse({"files": data}, safe=False, status=200)
return JsonResponse(result, status = result["statusCode"])

View File

@ -9,43 +9,46 @@ import re
import tempfile
def parseData(file):
# arguments
parser = argparse.ArgumentParser(description='Process some xml files.')
parser.add_argument('filename', help='xml forum file')
args = parser.parse_args()
try:
# arguments
parser = argparse.ArgumentParser(description='Process some xml files.')
parser.add_argument('filename', help='xml forum file')
args = parser.parse_args()
# write file first
fd = tempfile.NamedTemporaryFile()
f = open(fd.name, "wb+")
for chunk in file.chunks():
f.write(chunk)
f.close()
# write file first
fd = tempfile.NamedTemporaryFile()
f = open(fd.name, "wb+")
for chunk in file.chunks():
f.write(chunk)
f.close()
# make a soup:
with open(fd.name) as forum:
soup = BeautifulSoup(forum, "xml")
# make a soup:
with open(fd.name) as forum:
soup = BeautifulSoup(forum, "xml")
# put json together
out = {}
out['id'] = soup.forum.get('id')
out['name'] = soup.forum.find('name').text
out['discussions'] = []
for d in soup.forum.find_all('discussion'):
posts = []
for p in d.find_all('post'):
post_soup = BeautifulSoup(html.unescape(str(p.message)), "lxml")
paragraphs = [render_bbcode(x.text) for x in post_soup.find_all('p')]
posts.append({
'id': p.get('id'),
'parent': p.find('parent').text,
'author': p.userid.text,
'message': [x for x in paragraphs if x]
# put json together
out = {}
out['id'] = soup.forum.get('id')
out['name'] = soup.forum.find('name').text
out['discussions'] = []
for d in soup.forum.find_all('discussion'):
posts = []
for p in d.find_all('post'):
post_soup = BeautifulSoup(html.unescape(str(p.message)), "lxml")
paragraphs = [render_bbcode(x.text) for x in post_soup.find_all('p')]
posts.append({
'id': p.get('id'),
'parent': p.find('parent').text,
'author': p.userid.text,
'message': [x for x in paragraphs if x]
})
out['discussions'].append({
'id': d.get('id'),
'title': d.find('name').text,
'first_post': d.firstpost.text,
'posts': posts
})
out['discussions'].append({
'id': d.get('id'),
'title': d.find('name').text,
'first_post': d.firstpost.text,
'posts': posts
})
fd.close()
return(out)
fd.close()
return(out)
except:
return False

View File

@ -28,7 +28,8 @@ urlpatterns = [
path('visualize/<int:id>', views.visualize),
path('user/', views.user),
path('login/', views.login),
path('testToken/', views.testToken)
path('testToken/', views.testToken),
path('file/', views.file),
]
if settings.DEBUG: