Skip to content

Commit

Permalink
Apply new NotFound exception replacing the prev impelementation.
Browse files Browse the repository at this point in the history
------------------------------------
We defined custom HttpExceptions on hotosm#5899 to better handle errors but these exceptions were not used anywhere. This commit has replaced the previous NotFound custom exception which was simply a basic exceptio class with the new implementation.
  • Loading branch information
Aadesh-Baral committed Aug 7, 2023
1 parent fff19e8 commit 4118cc9
Show file tree
Hide file tree
Showing 47 changed files with 212 additions and 135 deletions.
2 changes: 1 addition & 1 deletion backend/api/campaigns/resources.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from flask_restful import Resource, request, current_app
from schematics.exceptions import DataError

from backend.exceptions import NotFound
from backend.models.dtos.campaign_dto import CampaignDTO, NewCampaignDTO
from backend.services.campaign_service import CampaignService
from backend.services.organisation_service import OrganisationService
from backend.models.postgis.utils import NotFound
from backend.services.users.authentication_service import token_auth


Expand Down
2 changes: 1 addition & 1 deletion backend/api/comments/resources.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from flask_restful import Resource, request, current_app
from schematics.exceptions import DataError

from backend.exceptions import NotFound
from backend.models.dtos.message_dto import ChatMessageDTO
from backend.models.dtos.mapping_dto import TaskCommentDTO
from backend.models.postgis.utils import NotFound
from backend.services.messaging.chat_service import ChatService
from backend.services.users.user_service import UserService
from backend.services.project_service import ProjectService
Expand Down
2 changes: 1 addition & 1 deletion backend/api/interests/resources.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from flask_restful import Resource, current_app, request
from schematics.exceptions import DataError

from backend.exceptions import NotFound
from backend.models.dtos.interests_dto import InterestDTO
from backend.models.postgis.utils import NotFound
from backend.services.interests_service import InterestService
from backend.services.organisation_service import OrganisationService
from backend.services.users.authentication_service import token_auth
Expand Down
2 changes: 1 addition & 1 deletion backend/api/issues/resources.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from flask_restful import Resource, current_app, request
from schematics.exceptions import DataError

from backend.exceptions import NotFound
from backend.models.dtos.mapping_issues_dto import MappingIssueCategoryDTO
from backend.models.postgis.utils import NotFound
from backend.services.mapping_issues_service import MappingIssueCategoryService
from backend.services.users.authentication_service import token_auth, tm

Expand Down
2 changes: 1 addition & 1 deletion backend/api/licenses/resources.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from flask_restful import Resource, current_app, request
from schematics.exceptions import DataError

from backend.exceptions import NotFound
from backend.models.dtos.licenses_dto import LicenseDTO
from backend.models.postgis.utils import NotFound
from backend.services.license_service import LicenseService
from backend.services.users.authentication_service import token_auth, tm

Expand Down
2 changes: 1 addition & 1 deletion backend/api/organisations/campaigns.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from flask_restful import Resource

from backend.exceptions import NotFound
from backend.services.campaign_service import CampaignService
from backend.services.organisation_service import OrganisationService
from backend.models.postgis.utils import NotFound
from backend.services.users.authentication_service import token_auth


Expand Down
3 changes: 2 additions & 1 deletion backend/api/projects/activities.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from flask_restful import Resource, current_app, request

from backend.exceptions import NotFound
from backend.services.stats_service import StatsService
from backend.services.project_service import ProjectService
from backend.models.postgis.utils import NotFound


class ProjectsActivitiesAPI(Resource):
Expand Down
2 changes: 1 addition & 1 deletion backend/api/projects/campaigns.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from flask_restful import Resource, current_app
from schematics.exceptions import DataError

from backend.exceptions import NotFound
from backend.models.dtos.campaign_dto import CampaignProjectDTO
from backend.services.campaign_service import CampaignService
from backend.services.project_admin_service import ProjectAdminService
from backend.models.postgis.utils import NotFound
from backend.services.users.authentication_service import token_auth


Expand Down
2 changes: 1 addition & 1 deletion backend/api/projects/favorites.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from flask_restful import Resource

from backend.models.postgis.utils import NotFound
from backend.exceptions import NotFound
from backend.models.dtos.project_dto import ProjectFavoriteDTO
from backend.services.project_service import ProjectService
from backend.services.users.authentication_service import token_auth
Expand Down
14 changes: 0 additions & 14 deletions backend/api/projects/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,6 @@ def get(self, project_id):
return {"Error": "Project Not Found", "SubCode": "NotFound"}, 404
except ProjectServiceError as e:
return {"Error": str(e).split("-")[1], "SubCode": str(e).split("-")[0]}, 403
except Exception as e:
error_msg = f"Project GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {
"Error": "Unable to fetch project",
"SubCode": "InternalServerError",
}, 500
finally:
# this will try to unlock tasks that have been locked too long
try:
Expand Down Expand Up @@ -981,13 +974,6 @@ def get(self, project_id):
return {"Error": "Project Not Found", "SubCode": "NotFound"}, 404
except ProjectServiceError as e:
return {"Error": str(e).split("-")[1], "SubCode": str(e).split("-")[0]}, 403
except Exception as e:
error_msg = f"Project GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {
"Error": "Unable to fetch project",
"SubCode": "InternalServerError",
}, 500
finally:
# this will try to unlock tasks that have been locked too long
try:
Expand Down
3 changes: 2 additions & 1 deletion backend/api/tasks/actions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from flask_restful import Resource, current_app, request
from schematics.exceptions import DataError

from backend.exceptions import NotFound
from backend.models.dtos.grid_dto import SplitTaskDTO
from backend.models.postgis.utils import NotFound, InvalidGeoJson
from backend.models.postgis.utils import InvalidGeoJson
from backend.services.grid.split_service import SplitService, SplitServiceError
from backend.services.users.user_service import UserService
from backend.services.project_admin_service import ProjectAdminService
Expand Down
21 changes: 19 additions & 2 deletions backend/error_messages.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
{
"NOT_FOUND": "The requested resource was not found.",
"NOT_FOUND": "The requested resource was not found on the server.",
"APPLICATION_NOT_FOUND": "The requested application was not found on the server.",
"CAMPAIGN_NOT_FOUND": "The requested campaign was not found on the server.",
"COMMENTS_NOT_FOUND": "The comments associated with the requested resource were not found on the server.",
"INTEREST_NOT_FOUND": "The requested interest was not found on the server.",
"ISSUE_CATEGORY_NOT_FOUND": "The requested mapping issue category was not found on the server.",
"JOIN_REQUEST_NOT_FOUND": "Team join request by the user was not found on the server.",
"LICENSE_NOT_FOUND": "The requested license was not found on the server.",
"MESSAGE_NOT_FOUND": "The requested message was not found on the server.",
"MESSAGES_NOT_FOUND": "The messages associated with the requested resource were not found on the server.",
"NOTIFICATIONS_NOT_FOUND": "The notifications associated with the requested resource were not found on the server.",
"ORGANISATION_NOT_FOUND": "The requested organisation was not found on the server.",
"PROJECT_NOT_FOUND": "The requested project was not found on the server.",
"PROJECTS_NOT_FOUND": "The projects associated with the requested resource were not found on the server.",
"TASK_NOT_FOUND": "The requested task was not found on the server.",
"TASKS_NOT_FOUND": "The tasks associated with the requested resource were not found on the server.",
"TEAM_NOT_FOUND": "The requested team was not found on the server.",
"USER_NOT_FOUND": "The requested user was not found on the server.",
"BAD_REQUEST": "The request was invalid or cannot be otherwise served.",
"UNAUTHORIZED": "Authentication credentials were missing or incorrect.",
"FORBIDDEN": "The request is understood, but it has been refused or access is not allowed.",
"CONFLICT": "The request could not be completed due to a conflict with the current state of the resource.",
"INTERNAL_SERVER_ERROR": "An unexpected error occurred while processing the request. Please contact the system administrator."
}
}
6 changes: 3 additions & 3 deletions backend/models/postgis/interests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from backend import db
from backend.exceptions import NotFound
from backend.models.dtos.interests_dto import InterestDTO, InterestsListDTO
from backend.models.postgis.utils import NotFound

# Secondary table defining many-to-many join for interests of a user.
user_interests = db.Table(
Expand Down Expand Up @@ -32,7 +32,7 @@ def get_by_id(interest_id: int):
"""Get interest by id"""
interest = db.session.get(Interest, interest_id)
if interest is None:
raise NotFound(f"Interest id {interest_id} not found")
raise NotFound(sub_code="INTEREST_NOT_FOUND", interest_id=interest_id)

return interest

Expand All @@ -41,7 +41,7 @@ def get_by_name(name: str):
"""Get interest by name"""
interest = Interest.query.filter(Interest.name == name).first()
if interest is None:
raise NotFound(f"Interest name {name} not found")
raise NotFound(sub_code="INTEREST_NOT_FOUND", interest_name=name)

return interest

Expand Down
4 changes: 2 additions & 2 deletions backend/models/postgis/licenses.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from backend import db
from backend.exceptions import NotFound
from backend.models.dtos.licenses_dto import LicenseDTO, LicenseListDTO
from backend.models.postgis.utils import NotFound

# Secondary table defining the many-to-many join
user_licenses_table = db.Table(
Expand Down Expand Up @@ -32,7 +32,7 @@ def get_by_id(license_id: int):
map_license = db.session.get(License, license_id)

if map_license is None:
raise NotFound()
raise NotFound(sub_code="LICENSE_NOT_FOUND", license_id=license_id)

return map_license

Expand Down
9 changes: 7 additions & 2 deletions backend/models/postgis/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
from backend import db
from flask import current_app
from enum import Enum

from backend.exceptions import NotFound
from backend.models.dtos.message_dto import MessageDTO, MessagesDTO
from backend.models.postgis.user import User
from backend.models.postgis.task import Task, TaskHistory, TaskAction
from backend.models.postgis.project import Project
from backend.models.postgis.utils import timestamp, NotFound
from backend.models.postgis.utils import timestamp


class MessageType(Enum):
Expand Down Expand Up @@ -156,7 +158,10 @@ def get_all_messages(user_id: int) -> MessagesDTO:
user_messages = Message.query.filter(Message.to_user_id == user_id).all()

if len(user_messages) == 0:
raise NotFound()
raise NotFound(
sub_code="MESSAGES_NOT_FOUND",
user_id=user_id,
)

messages_dto = MessagesDTO()
for message in user_messages:
Expand Down
6 changes: 3 additions & 3 deletions backend/models/postgis/organisation.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from slugify import slugify

from backend import db
from backend.exceptions import NotFound
from backend.models.dtos.organisation_dto import (
OrganisationDTO,
NewOrganisationDTO,
OrganisationManagerDTO,
)
from backend.models.postgis.user import User
from backend.models.postgis.campaign import Campaign, campaign_organisations
from backend.models.postgis.utils import NotFound
from backend.models.postgis.statuses import OrganisationType


Expand Down Expand Up @@ -77,7 +77,7 @@ def create_from_dto(cls, new_organisation_dto: NewOrganisationDTO):
user = User.get_by_username(manager)

if user is None:
raise NotFound(f"User {manager} Not Found")
raise NotFound(sub_code="USER_NOT_FOUND", username=manager)

new_org.managers.append(user)

Expand Down Expand Up @@ -109,7 +109,7 @@ def update(self, organisation_dto: OrganisationDTO):
new_manager = User.get_by_username(manager)

if new_manager is None:
raise NotFound(f"User {manager} Not Found")
raise NotFound(sub_code="USER_NOT_FOUND", username=manager)

self.managers.append(new_manager)

Expand Down
13 changes: 8 additions & 5 deletions backend/models/postgis/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import requests

from backend import db
from backend.exceptions import NotFound
from backend.models.dtos.campaign_dto import CampaignDTO
from backend.models.dtos.project_dto import (
ProjectDTO,
Expand Down Expand Up @@ -57,7 +58,6 @@
ST_GeomFromGeoJSON,
timestamp,
ST_Centroid,
NotFound,
)
from backend.services.grid.grid_service import GridService
from backend.models.postgis.interests import Interest, project_interests
Expand Down Expand Up @@ -297,7 +297,7 @@ def clone(project_id: int, author_id: int):

orig = db.session.get(Project, project_id)
if orig is None:
raise NotFound()
raise NotFound(sub_code="PROJECT_NOT_FOUND", project_id=project_id)

# Transform into dictionary.
orig_metadata = orig.__dict__.copy()
Expand Down Expand Up @@ -412,7 +412,10 @@ def update(self, project_dto: ProjectDTO):
if project_dto.organisation:
org = Organisation.get(project_dto.organisation)
if org is None:
raise NotFound("Organisation does not exist")
raise NotFound(
sub_code="ORGANISATION_NOT_FOUND",
organisation_id=project_dto.organisation,
)
self.organisation = org

# Cast MappingType strings to int array
Expand Down Expand Up @@ -446,7 +449,7 @@ def update(self, project_dto: ProjectDTO):
team = Team.get(team_dto.team_id)

if team is None:
raise NotFound("Team not found")
raise NotFound(sub_code="TEAM_NOT_FOUND", team_id=team_dto.team_id)

role = TeamRoles[team_dto.role].value
project_team = ProjectTeams(project=self, team=team, role=role)
Expand Down Expand Up @@ -588,7 +591,7 @@ def get_projects_for_admin(
admins_projects = query.all()

if admins_projects is None:
raise NotFound("No projects found for admin")
raise NotFound(sub_code="PROJECTS_NOT_FOUND")

admin_projects_dto = PMDashboardDTO()
for project in admins_projects:
Expand Down
15 changes: 9 additions & 6 deletions backend/models/postgis/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
from sqlalchemy.orm.session import make_transient
from geoalchemy2 import Geometry
from backend import db
from typing import List

from backend import db
from backend.exceptions import NotFound
from backend.models.dtos.mapping_dto import TaskDTO, TaskHistoryDTO
from backend.models.dtos.validator_dto import MappedTasksByUser, MappedTasks
from backend.models.dtos.project_dto import (
Expand All @@ -28,7 +30,6 @@
ST_SetSRID,
timestamp,
parse_duration,
NotFound,
)
from backend.models.postgis.task_annotation import TaskAnnotation

Expand Down Expand Up @@ -892,17 +893,19 @@ def get_tasks_as_geojson_feature_collection(
filters = [Task.project_id == project_id]

if task_ids_str:
task_ids = map(int, task_ids_str.split(","))
task_ids = list(map(int, task_ids_str.split(",")))
tasks = Task.get_tasks(project_id, task_ids)
if not tasks or len(tasks) == 0:
raise NotFound()
raise NotFound(
sub_code="TASKS_NOT_FOUND", tasks=task_ids, project_id=project_id
)
else:
tasks_filters = [task.id for task in tasks]
filters = [Task.project_id == project_id, Task.id.in_(tasks_filters)]
else:
tasks = Task.get_all_tasks(project_id)
if not tasks or len(tasks) == 0:
raise NotFound()
raise NotFound(sub_code="TASKS_NOT_FOUND", project_id=project_id)

if status:
filters.append(Task.task_status == status)
Expand Down Expand Up @@ -1038,7 +1041,7 @@ def get_max_task_id_for_project(project_id: int):
.group_by(Task.project_id)
)
if result.count() == 0:
raise NotFound()
raise NotFound(sub_code="TASKS_NOT_FOUND", project_id=project_id)
for row in result:
return row[0]

Expand Down
6 changes: 4 additions & 2 deletions backend/models/postgis/team.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from backend import db
from backend.exceptions import NotFound
from backend.models.dtos.team_dto import (
TeamDTO,
NewTeamDTO,
Expand All @@ -14,7 +15,6 @@
TeamRoles,
)
from backend.models.postgis.user import User
from backend.models.postgis.utils import NotFound


class TeamMembers(db.Model):
Expand Down Expand Up @@ -144,7 +144,9 @@ def update(self, team_dto: TeamDTO):
for member in team_dto.members:
user = User.get_by_username(member["username"])
if user is None:
raise NotFound("User not found")
raise NotFound(
sub_code="USER_NOT_FOUND", username=member["username"]
)
team_member = TeamMembers.get(self.id, user.id)
if team_member:
team_member.join_request_notifications = member[
Expand Down
Loading

0 comments on commit 4118cc9

Please sign in to comment.