User logout endpoint + token blacklisting
This commit is contained in:
parent
e2951b4fa4
commit
253e61b2a1
@ -12,3 +12,12 @@ class CouldNotParse(Exception):
|
||||
|
||||
class KnownError(Exception):
|
||||
pass
|
||||
|
||||
class TokenBlacklisted(Exception):
|
||||
pass
|
||||
|
||||
class UserAuthFailed(Exception):
|
||||
pass
|
||||
|
||||
class NotTokenOwner(Exception):
|
||||
pass
|
||||
|
@ -28,3 +28,6 @@ class Paragraph(models.Model):
|
||||
label = models.CharField(max_length=255)
|
||||
user_updated = models.BooleanField(default=False)
|
||||
post = models.ForeignKey(Post, on_delete=models.CASCADE)
|
||||
|
||||
class Token(models.Model):
|
||||
token = models.TextField()
|
||||
|
@ -13,5 +13,20 @@ DatabaseAddSuccess = {"message": "Data successfully added to database",
|
||||
DatabaseAddFail = {"message": "Failed adding data to database",
|
||||
"statusCode": 500}
|
||||
|
||||
ParseFailed = {"messeger": "Couldn't parse data",
|
||||
ParseFailed = {"messege": "Couldn't parse data",
|
||||
"statusCode": 500}
|
||||
|
||||
TokenBlacklistCode = {"message": "Error: Token is blacklisted",
|
||||
"statusCode": 409}
|
||||
|
||||
UserAuthFailedCode = {"message": "Error: User authentication failed",
|
||||
"statusCode": 401}
|
||||
|
||||
InvalidFormCode = {"message": "Error: File is missing",
|
||||
"statusCode": 422}
|
||||
|
||||
UserLogoutSuccessCode = {"message": "User logout successully",
|
||||
"statusCode": 200}
|
||||
|
||||
NotTokenOwnerCode = {"message": "Error: Token ownership check failed",
|
||||
"statusCode": 401}
|
||||
|
@ -1,4 +1,8 @@
|
||||
import time
|
||||
import time, jwt
|
||||
from django.conf import settings
|
||||
from prototype.filehandler.models import Token
|
||||
from prototype.filehandler.statusCodes import UnknownError
|
||||
|
||||
def verifyExpiration(payload):
|
||||
if "exp" not in payload or int(time.time()) > int(payload["exp"]):
|
||||
return False
|
||||
@ -10,3 +14,39 @@ def verifyContent(payload):
|
||||
actualKeys = [*payload]
|
||||
isProperStructure = all([True if key in actualKeys else False for key in expectedKeys])
|
||||
return all([isProperStructure, payload["iss"] == "NKADF"])
|
||||
|
||||
def verifyIfBlacklisted(token):
|
||||
try:
|
||||
entry = Token.objects.get(token = token)
|
||||
if entry:
|
||||
return True
|
||||
except Token.MultipleObjectsReturned:
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def createToken(user_id):
|
||||
try:
|
||||
iat = int(time.time())
|
||||
exp = iat + 86400
|
||||
payload = {"iss": "NKADF",
|
||||
"iat": iat,
|
||||
"sub": user_id,
|
||||
"exp": exp}
|
||||
jwt_token = jwt.encode(payload, settings.SECRET_KEY, algorithm = "HS256").decode("utf-8")
|
||||
result = {"message": "User authenticated successfully",
|
||||
"statusCode": 200,
|
||||
"token": jwt_token,
|
||||
"exp": exp}
|
||||
except:
|
||||
result = UnknownError
|
||||
finally:
|
||||
return result
|
||||
|
||||
def blacklistToken(token):
|
||||
try:
|
||||
token = Token(token = token)
|
||||
token.save()
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
@ -3,7 +3,9 @@ import time
|
||||
from django.contrib.auth import authenticate
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from prototype.filehandler.tokenAuthModule import verifyExpiration, verifyContent
|
||||
from prototype.filehandler.tokenAuthModule import verifyExpiration, verifyContent, createToken, blacklistToken, verifyIfBlacklisted
|
||||
from prototype.filehandler.exceptions import TokenBlacklisted, UserAuthFailed, NotTokenOwner
|
||||
from prototype.filehandler.statusCodes import TokenBlacklistCode, UserAuthFailedCode, UserLogoutSuccessCode, NotTokenOwnerCode, UnknownError
|
||||
|
||||
def registerNewUser(login, password):
|
||||
try:
|
||||
@ -23,22 +25,11 @@ def loginUser(login, password):
|
||||
try:
|
||||
user = authenticate(username = login, password = password)
|
||||
if isinstance(user, User):
|
||||
iat = int(time.time())
|
||||
exp = iat + 86400
|
||||
payload = {"iss": "NKADF",
|
||||
"iat": iat,
|
||||
"sub": user.id,
|
||||
"exp": exp}
|
||||
jwt_token = jwt.encode(payload, settings.SECRET_KEY, algorithm = "HS256").decode("utf-8")
|
||||
result = {"message": "User authenticated successfully",
|
||||
"statusCode": 200,
|
||||
"token": jwt_token,
|
||||
"exp": exp}
|
||||
result = createToken(user.id)
|
||||
else:
|
||||
raise UserAuthFailed("Error: User authentication failed")
|
||||
raise UserAuthFailed
|
||||
except UserAuthFailed as error:
|
||||
result = {"message": str(error),
|
||||
"statusCode": 401}
|
||||
result = UserAuthFailedCode
|
||||
finally:
|
||||
return result
|
||||
|
||||
@ -46,6 +37,8 @@ def checkUserToken(request):
|
||||
try:
|
||||
if "HTTP_BEARER" not in request.META:
|
||||
raise Exception("Error: Token is missing", 401)
|
||||
if verifyIfBlacklisted(request.META["HTTP_BEARER"]):
|
||||
raise TokenBlacklisted
|
||||
payload = jwt.decode(request.META["HTTP_BEARER"], settings.SECRET_KEY, algorithm = "HS256")
|
||||
if not verifyExpiration(payload):
|
||||
raise Exception("Error: Token has expired", 401)
|
||||
@ -58,9 +51,30 @@ def checkUserToken(request):
|
||||
result = {"messege": "Error: Invalid token given",
|
||||
"statusCode": 400}
|
||||
user_id = None
|
||||
except Exception as error:
|
||||
result = {"message": str(error.args[0]),
|
||||
"statusCode": int(error.args[1])}
|
||||
except TokenBlacklisted:
|
||||
result = TokenBlacklistCode
|
||||
user_id = None
|
||||
except:
|
||||
result = UnknownError
|
||||
user_id = None
|
||||
finally:
|
||||
return result, user_id
|
||||
|
||||
def logoutUser(login, user_id, token):
|
||||
try:
|
||||
user = User.objects.get(pk = user_id)
|
||||
if not user.username == login:
|
||||
raise NotTokenOwner
|
||||
if blacklistToken(token):
|
||||
result = UserLogoutSuccessCode
|
||||
else:
|
||||
raise Exception
|
||||
except User.DoesNotExist:
|
||||
result = {"message": "Error: Invalid token given",
|
||||
"statusCode": 400}
|
||||
except NotTokenOwner:
|
||||
result = NotTokenOwnerCode
|
||||
except:
|
||||
result = UnknownError
|
||||
finally:
|
||||
return result
|
||||
|
@ -13,11 +13,11 @@ 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, checkUserToken
|
||||
from prototype.filehandler.userModule import registerNewUser, loginUser, logoutUser, 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
|
||||
from prototype.filehandler.statusCodes import MethodNotAllowed, FileUploadSuccess, UnknownError, ParseFailed, InvalidFormCode
|
||||
|
||||
|
||||
def home(request):
|
||||
@ -92,12 +92,37 @@ def user(request):
|
||||
|
||||
@csrf_exempt
|
||||
def login(request):
|
||||
if request.method == 'POST':
|
||||
data = json.loads(request.body.decode("utf-8"))
|
||||
result = loginUser(data["email"], data["password"])
|
||||
try:
|
||||
if request.method == 'POST':
|
||||
data = json.loads(request.body.decode("utf-8"))
|
||||
result = loginUser(data["email"], data["password"])
|
||||
if result["statusCode"] != 200:
|
||||
raise KnownError
|
||||
|
||||
elif request.method == 'DELETE':
|
||||
data = json.loads(request.body.decode("utf-8"))
|
||||
result, user_id = checkUserToken(request)
|
||||
if result["statusCode"] != 200:
|
||||
raise KnownError
|
||||
|
||||
result = logoutUser(data["email"], user_id, request.META["HTTP_BEARER"])
|
||||
if result["statusCode"] != 200:
|
||||
raise KnownError
|
||||
|
||||
else:
|
||||
raise InvalidMethod
|
||||
|
||||
except InvalidMethod:
|
||||
result = MethodNotAllowed
|
||||
|
||||
except KnownError:
|
||||
pass
|
||||
|
||||
except:
|
||||
result = UnknownError
|
||||
|
||||
finally:
|
||||
return JsonResponse(result, status = result["statusCode"])
|
||||
else:
|
||||
return JsonResponse(MethodNotAllowed, status = MethodNotAllowed["statusCode"])
|
||||
|
||||
@csrf_exempt
|
||||
def testToken(request):
|
||||
@ -135,8 +160,11 @@ def file(request):
|
||||
data = list(Document.objects.filter(user_id = user_id).values("id", "file", "uploaded_at"))
|
||||
noStatus = True
|
||||
|
||||
else:
|
||||
raise InvalidMethod
|
||||
|
||||
except InvalidForm:
|
||||
result = UnknownError
|
||||
result = InvalidFormCode
|
||||
|
||||
except InvalidMethod:
|
||||
result = MethodNotAllowed
|
||||
|
Loading…
Reference in New Issue
Block a user