Skip to content

Commit

Permalink
Account authorization (#277)
Browse files Browse the repository at this point in the history
* Account activation has been enabled.

On branch account_authorization
Changes to be committed:
	modified:   api/urls.py
	modified:   api/views.py
	modified:   authentication/apis.py
	modified:   authentication/selectors.py
	modified:   authentication/services.py
	modified:   authentication/urls.py

* get_new_user
  • Loading branch information
HadleyKing authored Mar 13, 2024
1 parent b3abd90 commit 011e97b
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 188 deletions.
53 changes: 0 additions & 53 deletions api/scripts/method_specific/GET_activate_account.py

This file was deleted.

27 changes: 0 additions & 27 deletions api/scripts/method_specific/POST_api_accounts_describe.py

This file was deleted.

2 changes: 0 additions & 2 deletions api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from drf_yasg import openapi

from api.views import (
ApiAccountsDescribe,
ApiGroupsCreate,
ApiGroupsInfo,
ApiGroupsDelete,
Expand Down Expand Up @@ -126,7 +125,6 @@
ObjectIdRootObjectIdVersion.as_view(),
),
path("<str:object_id_root>", ObjectIdRootObjectId.as_view()),
path("api/accounts/describe/", ApiAccountsDescribe.as_view()),
path("api/groups/group_info/", ApiGroupsInfo.as_view()),
path("api/groups/create/", ApiGroupsCreate.as_view()),
path("api/groups/delete/", ApiGroupsDelete.as_view()),
Expand Down
57 changes: 0 additions & 57 deletions api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,13 @@
Django views for BCODB API
"""

import jwt
from django.contrib.auth.models import User
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.authtoken.models import Token
from api.permissions import RequestorInPrefixAdminsGroup
from api.scripts.method_specific.GET_activate_account import GET_activate_account
from api.scripts.method_specific.GET_draft_object_by_id import get_draft_object_by_id
from api.scripts.method_specific.GET_published_object_by_id import (
GET_published_object_by_id,
Expand All @@ -42,9 +37,6 @@
post_api_prefixes_token_flat,
)

from api.scripts.method_specific.POST_api_accounts_describe import (
POST_api_accounts_describe,
)
from api.scripts.method_specific.POST_api_objects_drafts_create import (
post_api_objects_drafts_create,
)
Expand Down Expand Up @@ -130,55 +122,6 @@ def check_get(request) -> Response:
# Placeholder
return Response(status=status.HTTP_200_OK)

# Source: https://www.django-rest-framework.org/api-guide/authentication/#by-exposing-an-api-endpoint
class ApiAccountsDescribe(APIView):
"""
Account details
--------------------
No schema for this request since only the Authorization header is required.
The word 'Token' must be included in the header.
For example: 'Token 627626823549f787c3ec763ff687169206626149'
"""

auth = [
openapi.Parameter(
"Authorization",
openapi.IN_HEADER,
description="Authorization Token",
type=openapi.TYPE_STRING,
)
]

@swagger_auto_schema(
manual_parameters=auth,
responses={
200: "Authorization is successful.",
403: "Forbidden. Authentication credentials were not provided.",
403: "Invalid token"
},
tags=["Account Management"],
)
def post(self, request):
"""
Pass the request to the handling function
Source: https://stackoverflow.com/a/31813810
"""

if request.headers["Authorization"].split(" ")[0] == "Token" or request.headers["Authorization"].split(" ")[0] == "TOKEN":
return POST_api_accounts_describe(
token=request.META.get("HTTP_AUTHORIZATION")
)
if request.headers["Authorization"].split(" ")[0] == "Bearer":
jw_token=request.META.get("HTTP_AUTHORIZATION").split(" ")[1]
unverified_payload = jwt.decode(jw_token, None, False)
user = User.objects.get(email=unverified_payload['email'])
token = "Thing "+ str(Token.objects.get(user=user))
return POST_api_accounts_describe(token)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)


class ApiGroupsInfo(APIView):
"""Group Info
Expand Down
99 changes: 82 additions & 17 deletions authentication/apis.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# authentication/apis.py

import json
import jwt
import uuid
from django.contrib.auth.models import User
from drf_yasg import openapi
Expand All @@ -12,7 +13,11 @@
from rest_framework.views import APIView
from api.scripts.utilities.UserUtils import UserUtils
from authentication.models import Authentication, NewUser
from authentication.selectors import check_user_email, get_user_info, check_new_user
from authentication.selectors import (
check_user_email,
get_user_info,
check_new_user
)
from authentication.services import (
validate_token,
create_bcodb_user,
Expand Down Expand Up @@ -99,7 +104,10 @@ def post(self, request) -> Response:
if email == "[email protected]":
return Response(
status=status.HTTP_201_CREATED,
data={"message":"Testing account request successful!!"}
data={
"message":"Testing account request successful. Check" \
+ " your email fro the activation link."
}
)

if check_user_email(email) is True:
Expand Down Expand Up @@ -155,9 +163,9 @@ class AccountActivateApi(APIView):
auth = []
auth.append(
openapi.Parameter(
"username",
"email",
openapi.IN_PATH,
description="Username to be authenticated.",
description="Email to be authenticated.",
type=openapi.TYPE_STRING,
default="[email protected]"
)
Expand All @@ -177,28 +185,49 @@ class AccountActivateApi(APIView):
responses={
200: "Account has been activated.",
403: "Requestor's credentials were rejected.",
404: "That account, {email}, was not found.",
409: "CONFLICT: That account, {email}, has already been activated"
},
tags=["Authentication and Account Management"],
)

def get(self, request, username: str, temp_identifier: str) -> Response:
if check_user_email(username) is True:
def get(self, request, email: str, temp_identifier: str) -> Response:
if email == "[email protected]":
return Response(
status=status.HTTP_200_OK,
data={"message":f"Account for {email} has been activated"}
)
if check_user_email(email) is True:
return Response(
status=status.HTTP_409_CONFLICT,
data={
"message":f"CONFLICT: That account, {username}, has already "\
"message":f"CONFLICT: That account, {email}, has already "\
+ "been activated."
}
)
new_user = check_new_user(username, temp_identifier)
print(new_user)
create_bcodb_user(new_user.email)
new_user.delete()
return Response(
status=status.HTTP_200_OK,
data={"message":f"Account for {username} has been activated"}
)

if check_new_user(email) == False:
return Response(
status=status.HTTP_404_NOT_FOUND,
data={
"message":f"That account, {email}, was not found."\
}
)
try:
new_user = NewUser.objects.get(
email=email,
temp_identifier=temp_identifier
)
create_bcodb_user(new_user.email)
new_user.delete()
return Response(
status=status.HTTP_200_OK,
data={"message":f"Account for {email} has been activated"}
)
except NewUser.DoesNotExist:
return Response(
status=status.HTTP_403_FORBIDDEN,
data={"message": "Requestor's credentials were rejected."}
)

class RegisterUserNoVerificationAPI(APIView):
"""Register BCODB
Expand Down Expand Up @@ -260,6 +289,43 @@ def post(self, request):
if response.status_code == 200:
return Response(status=status.HTTP_201_CREATED, data={"message": "user account created"})

class AccountDescribeApi(APIView):
"""
Account details
--------------------
The word 'Token' or 'Bearer' must be included in the header.
For example: 'Token 627626823549f787c3ec763ff687169206626149'
'Bearer' indicates a JWT that will be verified with another service.
'Token' is the API token for this service.
"""

auth = [
openapi.Parameter(
"Authorization",
openapi.IN_HEADER,
description="Authorization Token",
type=openapi.TYPE_STRING,
default="Token 627626823549f787c3ec763ff687169206626149"
)
]

@swagger_auto_schema(
manual_parameters=auth,
responses={
200: "Authorization is successful.",
403: "Forbidden. Authentication credentials were not provided.",
403: "Invalid token"
},
tags=["Authentication and Account Management"],
)

def post(self, request):
user = request._user
user_info = get_user_info(user)

return Response(status=status.HTTP_200_OK, data=user_info)

class AddAuthenticationApi(APIView):
"""
Add Authentication Object
Expand Down Expand Up @@ -319,7 +385,6 @@ class Meta:
)

def post(self, request):
""""""

result = validate_auth_service(request.data)

Expand Down
12 changes: 4 additions & 8 deletions authentication/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,16 @@ def check_user_email(email: str)-> bool:
return True
except User.DoesNotExist:
return False
def check_new_user(email: str, temp_identifier:str=None):

def check_new_user(email: str) -> bool:
"""Check for new user
Using the provided email check for a new user in the DB.
If the temp id is supplied and matches it will return the new user object.
"""

try:
new_user = NewUser.objects.get(email=email)
if new_user.temp_identifier == temp_identifier:
return new_user
else:
return True
NewUser.objects.get(email=email)
return True
except NewUser.DoesNotExist:
return False

Expand Down
9 changes: 0 additions & 9 deletions authentication/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,6 @@ def authenticate_google(token: str) -> bool:
except User.DoesNotExist:
return None

def custom_jwt_handler(token, user=None, request=None, public_key=None):
"""Custom JWT Handler
Triggered by any user authentication. This will gater all the associated
user information and return that along with the validated JWT
"""

print('hadley', token)
return request

def validate_token(token: str, url: str)-> bool:
"""
"""
Expand Down
Loading

0 comments on commit 011e97b

Please sign in to comment.