Skip to content

Commit

Permalink
Use HTTPStatus enums for backend responses
Browse files Browse the repository at this point in the history
  • Loading branch information
mshriver committed Jun 17, 2024
1 parent 2f34bbd commit ff2742d
Show file tree
Hide file tree
Showing 23 changed files with 202 additions and 163 deletions.
17 changes: 9 additions & 8 deletions backend/ibutsu_server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from http import HTTPStatus
from importlib import import_module
from pathlib import Path
from typing import Any, Optional
Expand Down Expand Up @@ -137,31 +138,31 @@ def run_task():
# get params
params = request.get_json(force=True, silent=True)
if not params:
return "Bad request", 400
return HTTPStatus.BAD_REQUEST.phrase, HTTPStatus.BAD_REQUEST
# get user info
token = params.get("token")
if not token:
return "Unauthorized", 401
return HTTPStatus.UNAUTHORIZED.phrase, HTTPStatus.UNAUTHORIZED
user_id = decode_token(token).get("sub")
if not user_id:
return "Unauthorized", 401
return HTTPStatus.UNAUTHORIZED.phrase, HTTPStatus.UNAUTHORIZED
user = User.query.get(user_id)
if not user or not user.is_superadmin:
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
# get task info
task_path = params.get("task")
task_params = params.get("params", {})
if not task_path:
return "Bad request", 400
return HTTPStatus.BAD_REQUEST.phrase, HTTPStatus.BAD_REQUEST
task_module, task_name = task_path.split(".", 2)
try:
mod = import_module(f"ibutsu_server.tasks.{task_module}")
except ImportError:
return "Not found", 404
return HTTPStatus.NOT_FOUND.phrase, HTTPStatus.NOT_FOUND
if not hasattr(mod, task_name):
return "Not found", 404
return HTTPStatus.NOT_FOUND.phrase, HTTPStatus.NOT_FOUND
task = getattr(mod, task_name)
task.delay(**task_params)
return "Accepted", 202
return HTTPStatus.ACCEPTED.phrase, HTTPStatus.ACCEPTED

return app.app
3 changes: 2 additions & 1 deletion backend/ibutsu_server/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from http import HTTPStatus

LOCALHOST = "127.0.0.1"

OAUTH_CONFIG = {
Expand Down Expand Up @@ -396,4 +397,4 @@
},
}

RESPONSE_JSON_REQ = f"{HTTPStatus.BAD_REQUEST.phrase} JSON required", HTTPStatus.BAD_REQUEST
RESPONSE_JSON_REQ = f"{HTTPStatus.BAD_REQUEST.phrase} JSON required", HTTPStatus.BAD_REQUEST
16 changes: 9 additions & 7 deletions backend/ibutsu_server/controllers/admin/project_controller.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from http import HTTPStatus

import connexion
from flask import abort

from ibutsu_server.constants import RESPONSE_JSON_REQ
from ibutsu_server.db.base import session
from ibutsu_server.db.models import Group, Project, User
from ibutsu_server.filters import convert_filter
from ibutsu_server.util.admin import check_user_is_admin
from ibutsu_server.util.query import get_offset
from ibutsu_server.util.uuid import convert_objectid_to_uuid, is_uuid, validate_uuid
from ibutsu_server.constants import RESPONSE_JSON_REQ


def admin_add_project(project=None, token_info=None, user=None):
Expand All @@ -24,19 +26,19 @@ def admin_add_project(project=None, token_info=None, user=None):
project = Project.from_dict(**connexion.request.get_json())
# check if project already exists
if project.id and Project.query.get(project.id):
return f"Project id {project.id} already exist", 400
return f"Project id {project.id} already exist", HTTPStatus.BAD_REQUEST
user = User.query.get(user)
if project.group_id:
# check if the group exists
group = Group.query.get(project.group_id)
if not group:
return f"Group id {project.group_id} doesn't exist", 400
return f"Group id {project.group_id} doesn't exist", HTTPStatus.BAD_REQUEST
if user:
project.owner = user
project.users.append(user)
session.add(project)
session.commit()
return project.to_dict(), 201
return project.to_dict(), HTTPStatus.CREATED


@validate_uuid
Expand Down Expand Up @@ -96,7 +98,7 @@ def admin_get_project_list(
total_items = query.count()
total_pages = (total_items // page_size) + (1 if total_items % page_size > 0 else 0)
if offset > 9223372036854775807: # max value of bigint
return "The page number is too big.", 400
return "The page number is too big.", HTTPStatus.BAD_REQUEST
projects = query.offset(offset).limit(page_size).all()
return {
"projects": [project.to_dict(with_owner=True) for project in projects],
Expand Down Expand Up @@ -160,10 +162,10 @@ def admin_delete_project(id_, token_info=None, user=None):
"""Delete a single project"""
check_user_is_admin(user)
if not is_uuid(id_):
return f"Project ID {id_} is not in UUID format", 400
return f"Project ID {id_} is not in UUID format", HTTPStatus.BAD_REQUEST
project = Project.query.get(id_)
if not project:
abort(404)
session.delete(project)
session.commit()
return "OK", 200
return HTTPStatus.OK.phrase, HTTPStatus.OK
10 changes: 6 additions & 4 deletions backend/ibutsu_server/controllers/admin/user_controller.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from http import HTTPStatus

import connexion
from flask import abort

from ibutsu_server.constants import RESPONSE_JSON_REQ
from ibutsu_server.db.base import session
from ibutsu_server.db.models import Project, User
from ibutsu_server.filters import convert_filter
from ibutsu_server.util.admin import check_user_is_admin
from ibutsu_server.util.query import get_offset
from ibutsu_server.util.uuid import validate_uuid
from ibutsu_server.constants import RESPONSE_JSON_REQ

HIDDEN_FIELDS = ["_password", "password", "activation_code"]

Expand Down Expand Up @@ -68,10 +70,10 @@ def admin_add_user(new_user=None, token_info=None, user=None):
new_user = User.from_dict(**connexion.request.get_json())
user_exists = User.query.filter_by(email=new_user.email).first()
if user_exists:
return f"The user with email {new_user.email} already exists", 400
return f"The user with email {new_user.email} already exists", HTTPStatus.BAD_REQUEST
session.add(new_user)
session.commit()
return _hide_sensitive_fields(new_user.to_dict()), 201
return _hide_sensitive_fields(new_user.to_dict()), HTTPStatus.CREATED


@validate_uuid
Expand Down Expand Up @@ -101,4 +103,4 @@ def admin_delete_user(id_, token_info=None, user=None):
abort(404)
session.delete(requested_user)
session.commit()
return "OK", 200
return HTTPStatus.OK.phrase, HTTPStatus.OK
33 changes: 17 additions & 16 deletions backend/ibutsu_server/controllers/artifact_controller.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from datetime import datetime
from http import HTTPStatus

import connexion
import magic
Expand All @@ -16,9 +17,9 @@ def _build_artifact_response(id_):
"""Build a response for the artifact"""
artifact = Artifact.query.get(id_)
if not artifact:
return "Not Found", 404
return HTTPStatus.NOT_FOUND.phrase, HTTPStatus.NOT_FOUND
# Create a response with the contents of this file
response = make_response(artifact.content, 200)
response = make_response(artifact.content, HTTPStatus.OK)
# Set the content type and the file name
file_type = magic.from_buffer(artifact.content, mime=True)
response.headers["Content-Type"] = file_type
Expand All @@ -36,9 +37,9 @@ def view_artifact(id_, token_info=None, user=None):
"""
artifact, response = _build_artifact_response(id_)
if artifact.result and not project_has_user(artifact.result.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
elif artifact.run and not project_has_user(artifact.run.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
return response


Expand All @@ -53,7 +54,7 @@ def download_artifact(id_, token_info=None, user=None):
"""
artifact, response = _build_artifact_response(id_)
if not project_has_user(artifact.result.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
response.headers["Content-Disposition"] = f"attachment; filename={artifact.filename}"
return response

Expand All @@ -69,9 +70,9 @@ def get_artifact(id_, token_info=None, user=None):
"""
artifact = Artifact.query.get(id_)
if not artifact:
return "Not Found", 404
return HTTPStatus.NOT_FOUND.phrase, HTTPStatus.NOT_FOUND
if not project_has_user(artifact.result.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
return artifact.to_dict()


Expand Down Expand Up @@ -129,12 +130,12 @@ def upload_artifact(body, token_info=None, user=None):
result_id = body.get("result_id") or body.get("resultId")
run_id = body.get("run_id") or body.get("runId")
if result_id and not is_uuid(result_id):
return f"Result ID {result_id} is not in UUID format", 400
return f"Result ID {result_id} is not in UUID format", HTTPStatus.BAD_REQUEST
if run_id and not is_uuid(run_id):
return f"Run ID {run_id} is not in UUID format", 400
return f"Run ID {run_id} is not in UUID format", HTTPStatus.BAD_REQUEST
result = Result.query.get(result_id)
if result and not project_has_user(result.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
filename = body.get("filename")
additional_metadata = body.get("additional_metadata", {})
file_ = connexion.request.files["file"]
Expand All @@ -150,9 +151,9 @@ def upload_artifact(body, token_info=None, user=None):
try:
additional_metadata = json.loads(additional_metadata)
except (ValueError, TypeError):
return "Bad request, additionalMetadata is not valid JSON", 400
return "Bad request, additionalMetadata is not valid JSON", HTTPStatus.BAD_REQUEST
if not isinstance(additional_metadata, dict):
return "Bad request, additionalMetadata is not a JSON object", 400
return "Bad request, additionalMetadata is not a JSON object", HTTPStatus.BAD_REQUEST
data["additionalMetadata"] = additional_metadata
# Reset the file pointer
file_.seek(0)
Expand All @@ -175,7 +176,7 @@ def upload_artifact(body, token_info=None, user=None):

session.add(artifact)
session.commit()
return artifact.to_dict(), 201
return artifact.to_dict(), HTTPStatus.CREATED


@validate_uuid
Expand All @@ -189,9 +190,9 @@ def delete_artifact(id_, token_info=None, user=None):
"""
artifact = Artifact.query.get(id_)
if not artifact:
return "Not Found", 404
return HTTPStatus.NOT_FOUND.phrase, HTTPStatus.NOT_FOUND
if not project_has_user(artifact.result.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
session.delete(artifact)
session.commit()
return "OK", 200
return HTTPStatus.OK.phrase, HTTPStatus.OK
28 changes: 15 additions & 13 deletions backend/ibutsu_server/controllers/dashboard_controller.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from http import HTTPStatus

import connexion

from ibutsu_server.constants import RESPONSE_JSON_REQ
from ibutsu_server.db.base import session
from ibutsu_server.db.models import Dashboard, Project, User, WidgetConfig
from ibutsu_server.filters import convert_filter
from ibutsu_server.util.projects import project_has_user
from ibutsu_server.util.query import get_offset
from ibutsu_server.util.uuid import validate_uuid
from ibutsu_server.constants import RESPONSE_JSON_REQ


def add_dashboard(dashboard=None, token_info=None, user=None):
Expand All @@ -21,12 +23,12 @@ def add_dashboard(dashboard=None, token_info=None, user=None):
return RESPONSE_JSON_REQ
dashboard = Dashboard.from_dict(**connexion.request.get_json())
if dashboard.project_id and not project_has_user(dashboard.project_id, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
if dashboard.user_id and not User.query.get(dashboard.user_id):
return f"User with ID {dashboard.user_id} doesn't exist", 400
return f"User with ID {dashboard.user_id} doesn't exist", HTTPStatus.BAD_REQUEST
session.add(dashboard)
session.commit()
return dashboard.to_dict(), 201
return dashboard.to_dict(), HTTPStatus.CREATED


@validate_uuid
Expand All @@ -40,9 +42,9 @@ def get_dashboard(id_, token_info=None, user=None):
"""
dashboard = Dashboard.query.get(id_)
if not dashboard:
return "Dashboard not found", 404
return "Dashboard not found", HTTPStatus.NOT_FOUND
if dashboard and dashboard.project and not project_has_user(dashboard.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
return dashboard.to_dict()


Expand All @@ -68,7 +70,7 @@ def get_dashboard_list(
project = Project.query.get(connexion.request.args["project_id"])
if project:
if not project_has_user(project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
query = query.filter(Dashboard.project_id == project_id)

if filter_:
Expand Down Expand Up @@ -110,12 +112,12 @@ def update_dashboard(id_, dashboard=None, token_info=None, user=None):
if dashboard_dict.get("metadata", {}).get("project") and not project_has_user(
dashboard_dict["metadata"]["project"], user
):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
dashboard = Dashboard.query.get(id_)
if not dashboard:
return "Dashboard not found", 404
return "Dashboard not found", HTTPStatus.NOT_FOUND
if project_has_user(dashboard.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
dashboard.update(connexion.request.get_json())
session.add(dashboard)
session.commit()
Expand All @@ -133,12 +135,12 @@ def delete_dashboard(id_, token_info=None, user=None):
"""
dashboard = Dashboard.query.get(id_)
if not dashboard:
return "Not Found", 404
return HTTPStatus.NOT_FOUND.phrase, HTTPStatus.NOT_FOUND
if not project_has_user(dashboard.project, user):
return "Forbidden", 403
return HTTPStatus.FORBIDDEN.phrase, HTTPStatus.FORBIDDEN
widget_configs = WidgetConfig.query.filter(WidgetConfig.dashboard_id == dashboard.id).all()
for widget_config in widget_configs:
session.delete(widget_config)
session.delete(dashboard)
session.commit()
return "OK", 200
return HTTPStatus.OK.phrase, HTTPStatus.OK
14 changes: 8 additions & 6 deletions backend/ibutsu_server/controllers/group_controller.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from http import HTTPStatus

import connexion

from ibutsu_server.constants import RESPONSE_JSON_REQ
from ibutsu_server.db.base import session
from ibutsu_server.db.models import Group
from ibutsu_server.util.query import get_offset
from ibutsu_server.util.uuid import is_uuid, validate_uuid
from ibutsu_server.constants import RESPONSE_JSON_REQ


def add_group(group=None):
Expand All @@ -19,12 +21,12 @@ def add_group(group=None):
return RESPONSE_JSON_REQ
group = Group.from_dict(**connexion.request.get_json())
if group.id and Group.query.get(group.id):
return f"The group with ID {group.id} already exists", 400
return f"The group with ID {group.id} already exists", HTTPStatus.BAD_REQUEST
if not is_uuid(group.id):
return f"Group ID {group.id} is not in UUID format", 400
return f"Group ID {group.id} is not in UUID format", HTTPStatus.BAD_REQUEST
session.add(group)
session.commit()
return group.to_dict(), 201
return group.to_dict(), HTTPStatus.CREATED


@validate_uuid
Expand All @@ -40,7 +42,7 @@ def get_group(id_, token_info=None, user=None):
if group:
return group.to_dict()
else:
return "Group not found", 404
return "Group not found", HTTPStatus.NOT_FOUND


def get_group_list(page=1, page_size=25, token_info=None, user=None):
Expand Down Expand Up @@ -88,7 +90,7 @@ def update_group(id_, group=None, **kwargs):
return RESPONSE_JSON_REQ
group = Group.query.get(id_)
if not group:
return "Group not found", 404
return "Group not found", HTTPStatus.NOT_FOUND
group.update(connexion.request.get_json())
session.add(group)
session.commit()
Expand Down
Loading

0 comments on commit ff2742d

Please sign in to comment.