diff --git a/backend/app/graphql/auth.py b/backend/app/graphql/auth.py index 2002fcad..7c9cfad1 100644 --- a/backend/app/graphql/auth.py +++ b/backend/app/graphql/auth.py @@ -35,6 +35,10 @@ def mutate(self, info, email=None, password=None, id_token=None): id=auth_dto.id, info=auth_dto.info, ) + + if not services["user_service"].is_user_activated(auth_dto.id): + raise Exception("User is not activated! Please contact FCK.") + return Login(registered_user=registered_user) return LoginMutation diff --git a/backend/app/graphql/meal_request.py b/backend/app/graphql/meal_request.py index 0dbdff37..4c7bbd03 100644 --- a/backend/app/graphql/meal_request.py +++ b/backend/app/graphql/meal_request.py @@ -241,6 +241,7 @@ class Arguments: meal_request = graphene.Field(MealRequestResponse) @requires_role("Donor") + @secure_requestor_id def mutate(self, info, meal_request_id, requestor_id): user = services["user_service"] requestor_auth_id = user.get_auth_id_by_user_id(requestor_id) @@ -352,7 +353,6 @@ class MealRequestQueries(QueryList): ids=graphene.List(graphene.ID), ) - @secure_requestor_id @requires_role("Admin") def resolve_getMealRequests( self, diff --git a/backend/app/graphql/middleware/auth.py b/backend/app/graphql/middleware/auth.py index 40846f04..6bb6c4d8 100644 --- a/backend/app/graphql/middleware/auth.py +++ b/backend/app/graphql/middleware/auth.py @@ -7,6 +7,7 @@ """ +import traceback def secure_requestor_id(resolver): @wraps(resolver) def wrapper(parent, info, **kwargs): @@ -14,9 +15,18 @@ def wrapper(parent, info, **kwargs): authorized = services["auth_service"].is_authorized_by_user_id( info.context, kwargs.get("requestor_id") ) - - if not is_admin and not authorized: + user_id = kwargs.get("requestor_id") + print("user_id", user_id) + if not user_id: + print(traceback.format_exc()) + raise RuntimeError("You are not authorized to make this request. No user id provided!") + + if (not is_admin and not authorized) or not user_id: raise ClientError("You are not authorized to make this request.") + + if not services["user_service"].is_user_activated(user_id=user_id): + raise ClientError("You are not authorized to make this request. Your user has been deactivated. Please contact FCK.") + return resolver(parent, info, **kwargs) return wrapper diff --git a/backend/app/services/implementations/user_service.py b/backend/app/services/implementations/user_service.py index ec3b6a3a..38029a40 100644 --- a/backend/app/services/implementations/user_service.py +++ b/backend/app/services/implementations/user_service.py @@ -328,6 +328,12 @@ def activate_user_by_id(self, user_id): self.logger.error(f"Failed to activate user. Reason = {e}") raise e + def is_user_activated(self, user_id) -> bool: + user = User.objects(id=user_id).first() + if not user: + return False + return user.info.active + def deactivate_user_by_id(self, user_id): try: user = User.objects(id=user_id).first() @@ -480,9 +486,15 @@ def get_asp_near_location( # To debug queries like these, use MongoDB Compass. now = datetime.now(timezone.utc) future_cutoff = now + timedelta(weeks=12) - # TODO: Make sure user is not deactivated! pipeline += [ { + # Match only active ASPs + "$match": { + "info.active": { "$ne": False } + } + }, + { + # make sure that they have some meal requests "$lookup": { "from": "meal_requests", "localField": "_id", @@ -491,6 +503,7 @@ def get_asp_near_location( } }, { + # the meal requests should be open and within a certain time period "$addFields": { "meal_requests": { "$filter": { diff --git a/backend/app/services/interfaces/user_service.py b/backend/app/services/interfaces/user_service.py index 27570b63..44cc6bfb 100644 --- a/backend/app/services/interfaces/user_service.py +++ b/backend/app/services/interfaces/user_service.py @@ -126,6 +126,13 @@ def update_user_by_id(self, user_id, user): """ pass + @abstractmethod + def is_user_activated(self, user_id : str) -> bool: + """ + Check if a user is activated + """ + pass + @abstractmethod def activate_user_by_id(self, user_id): """ diff --git a/backend/requirements.txt b/backend/requirements.txt index 0dd832ca..234b5ac7 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -60,7 +60,7 @@ pyasn1-modules==0.2.8 pycodestyle==2.10.0 pycparser==2.20 pyflakes==3.0.0 -pymongo==3.11.3 +pymongo==4.8.0 pyparsing==2.4.7 pytest==6.2.4 pytest-mock==3.6.1 diff --git a/frontend/src/components/admin/UserList.tsx b/frontend/src/components/admin/UserList.tsx index 7a54800c..831bee80 100644 --- a/frontend/src/components/admin/UserList.tsx +++ b/frontend/src/components/admin/UserList.tsx @@ -185,8 +185,8 @@ const ActivateDeactivateModal = ({ {isActive - ? "Deactivating the user means they will no longer be in the system. " - : "Activating the user means they will be in the system. "} + ? "Deactivating the user means they will not be able to login and use the platform. Make sure to manually remove them from any meal requests and delete any meal requests they have made in the past." + : "Activating the user means they will be able to login and use the platform."} {isActive diff --git a/frontend/src/components/auth/Login.tsx b/frontend/src/components/auth/Login.tsx index 0c400742..2572348b 100644 --- a/frontend/src/components/auth/Login.tsx +++ b/frontend/src/components/auth/Login.tsx @@ -86,6 +86,9 @@ const Login = (): React.ReactElement => { if ((errorCasted?.message ?? "").indexOf("Failed to sign-in") !== -1) { setErrorMessage("Invalid email or password, please try again!") } + else if ((errorCasted?.message ?? "").indexOf("is not activated") !== -1) { + setErrorMessage("Your account has been deactivated. Please contact FCK!") + } else { setErrorMessage("An unexpected error occurred, please try again!") } diff --git a/frontend/src/utils/ErrorUtils.tsx b/frontend/src/utils/ErrorUtils.tsx index 32f547e0..61d7e712 100644 --- a/frontend/src/utils/ErrorUtils.tsx +++ b/frontend/src/utils/ErrorUtils.tsx @@ -4,8 +4,7 @@ import React from "react"; export const ErrorMessage = ({ children = "" }: { children?: string }) => (

- Sorry something went wrong. Please check your email and verify your email - if you have not already! Else, please let us know what happened at{" "} + Sorry something went wrong. Please retry by refreshing the page and let us know what happened at{" "} info@feedingcanadiankids.org