Skip to content

Commit

Permalink
Add Update to routes
Browse files Browse the repository at this point in the history
- officers
- agencies
- partners
Fix temporary pydantic schema for agencies
  • Loading branch information
DMalone87 committed Sep 30, 2024
1 parent 4700ba8 commit 443e786
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 46 deletions.
51 changes: 24 additions & 27 deletions backend/routes/agencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
from operator import and_
from typing import Optional, List
from backend.auth.jwt import min_role_required
from backend.schemas import (
validate_request, paginate_results, ordered_jsonify,
NodeConflictException)
from backend.mixpanel.mix import track_to_mp
from backend.database.models.user import UserRole
from backend.database.models.agency import Agency
from .tmp.pydantic.agencies import CreateAgency, UpdateAgency
from flask import Blueprint, abort, request
from flask_jwt_extended.view_decorators import jwt_required
from pydantic import BaseModel
Expand Down Expand Up @@ -33,16 +37,19 @@ class AddOfficerListSchema(BaseModel):
@bp.route("/", methods=["POST"])
@jwt_required()
@min_role_required(UserRole.CONTRIBUTOR)
#@validate(json=CreateAgencySchema)
@validate_request(CreateAgency)
def create_agency():
logger = logging.getLogger("create_agency")
"""Create an agency profile.
User must be a Contributor to create an agency.
Must include a name and jurisdiction.
"""
body: CreateAgency = request.validated_body

try:
agency = Agency.from_dict(request.context.json)
agency = Agency.from_dict(body.dict())
except NodeConflictException:
abort(409, description="Agency already exists")
except Exception as e:
logger.error(f"Error, Agency.from_dict: {e}")
abort(400)
Expand All @@ -58,13 +65,13 @@ def create_agency():


# Get agency profile
@bp.route("/<int:agency_id>", methods=["GET"])
@bp.route("/<agency_id>", methods=["GET"])
@jwt_required()
@min_role_required(UserRole.PUBLIC)
# @validate()
def get_agency(agency_id: int):
def get_agency(agency_id: str):
"""Get an agency profile.
"""
logger = logging.getLogger("get_agency")
agency = Agency.nodes.get_or_none(uid=agency_id)
if agency is None:
abort(404, description="Agency not found")
Expand All @@ -75,19 +82,22 @@ def get_agency(agency_id: int):


# Update agency profile
@bp.route("/<int:agency_id>", methods=["PUT"])
@bp.route("/<agency_uid>", methods=["PUT"])
@jwt_required()
@min_role_required(UserRole.CONTRIBUTOR)
# @validate()
def update_agency(agency_id: int):
@validate_request(UpdateAgency)
def update_agency(agency_uid: str):
"""Update an agency profile.
"""
agency = Agency.nodes.get_or_none(uid=agency_id)
logger = logging.getLogger("update_agency")
body: UpdateAgency = request.validated_body
agency = Agency.nodes.get_or_none(uid=agency_uid)
if agency is None:
abort(404, description="Agency not found")

try:
agency = Agency.from_dict(request.context.json)
agency = Agency.from_dict(body.dict(), agency_uid)
agency.refresh()
track_to_mp(
request,
"update_agency",
Expand All @@ -101,11 +111,10 @@ def update_agency(agency_id: int):


# Delete agency profile
@bp.route("/<int:agency_id>", methods=["DELETE"])
@bp.route("/<agency_id>", methods=["DELETE"])
@jwt_required()
@min_role_required(UserRole.ADMIN)
# @validate()
def delete_agency(agency_id: int):
def delete_agency(agency_id: str):
"""Delete an agency profile.
Must be an admin to delete an agency.
"""
Expand All @@ -131,7 +140,6 @@ def delete_agency(agency_id: int):
@bp.route("/", methods=["GET"])
@jwt_required()
@min_role_required(UserRole.PUBLIC)
# @validate()
def get_all_agencies():
"""Get all agencies.
Accepts Query Parameters for pagination:
Expand All @@ -143,20 +151,9 @@ def get_all_agencies():
q_per_page = args.get("per_page", 20, type=int)

all_agencies = Agency.nodes.all()
pagination = all_agencies.paginate(
page=q_page, per_page=q_per_page, max_per_page=100
)
results = paginate_results(all_agencies, q_page, q_per_page)

try:
return {
"results": [
agency.to_json() for agency in pagination.items],
"page": pagination.page,
"totalPages": pagination.pages,
"totalResults": pagination.total,
}
except Exception as e:
abort(500, description=str(e))
return ordered_jsonify(results), 200


# # Add officer employment information
Expand Down
23 changes: 12 additions & 11 deletions backend/routes/officers.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,13 @@ def create_officer():


# Get an officer profile
@bp.route("/<officer_id>", methods=["GET"])
@bp.route("/<officer_uid>", methods=["GET"])
@jwt_required()
@min_role_required(UserRole.PUBLIC)
def get_officer(officer_id: int):
def get_officer(officer_uid: int):
"""Get an officer profile.
"""
o = Officer.nodes.get_or_none(uid=officer_id)
o = Officer.nodes.get_or_none(uid=officer_uid)
if o is None:
abort(404, description="Officer not found")
return o.to_json()
Expand All @@ -190,19 +190,21 @@ def get_all_officers():


# Update an officer profile
@bp.route("/<int:officer_id>", methods=["PUT"])
@bp.route("/<officer_uid>", methods=["PUT"])
@jwt_required()
@min_role_required(UserRole.CONTRIBUTOR)
@validate_request(UpdateOfficer)
def update_officer(officer_id: int):
def update_officer(officer_uid: str):
"""Update an officer profile.
"""
o = Officer.nodes.get_or_none(uid=officer_id)
body: UpdateOfficer = request.validated_body
o = Officer.nodes.get_or_none(uid=officer_uid)
if o is None:
abort(404, description="Officer not found")

try:
o = Officer.from_dict(request.context.json)
o = Officer.from_dict(body.dict(), officer_uid)
o.refresh()
except Exception as e:
abort(400, description=str(e))

Expand All @@ -217,15 +219,14 @@ def update_officer(officer_id: int):


# Delete an officer profile
@bp.route("/<int:officer_id>", methods=["DELETE"])
@bp.route("/<officer_uid>", methods=["DELETE"])
@jwt_required()
@min_role_required(UserRole.ADMIN)
# @validate()
def delete_officer(officer_id: int):
def delete_officer(officer_uid: str):
"""Delete an officer profile.
Must be an admin to delete an officer.
"""
o = Officer.nodes.get_or_none(uid=officer_id)
o = Officer.nodes.get_or_none(uid=officer_uid)
if o is None:
abort(404, description="Officer not found")
try:
Expand Down
48 changes: 40 additions & 8 deletions backend/routes/partners.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
from backend.auth.jwt import min_role_required
from backend.mixpanel.mix import track_to_mp
from backend.database.models.user import User, UserRole
from ..schemas import validate_request, paginate_results, ordered_jsonify
from .tmp.pydantic.partners import CreatePartner
from ..schemas import (
validate_request, paginate_results, ordered_jsonify,
NodeConflictException)
from .tmp.pydantic.partners import CreatePartner, UpdatePartner
from flask import Blueprint, abort, current_app, request, jsonify
from flask_jwt_extended import get_jwt
from flask_jwt_extended.view_decorators import jwt_required
Expand All @@ -26,12 +28,12 @@
bp = Blueprint("partner_routes", __name__, url_prefix="/api/v1/partners")


@bp.route("/<partner_id>", methods=["GET"])
@bp.route("/<partner_uid>", methods=["GET"])
@jwt_required()
@min_role_required(UserRole.PUBLIC)
def get_partners(partner_id: str):
"""Get a single partner by ID."""
p = Partner.nodes.get_or_none(uid=partner_id)
def get_partners(partner_uid: str):
"""Get a single partner by UID."""
p = Partner.nodes.get_or_none(uid=partner_uid)
if p is None:
abort(404, description="Partner not found")
return p.to_json()
Expand Down Expand Up @@ -60,6 +62,8 @@ def create_partner():
# Creates a new instance of the Partner and saves it to the DB
try:
new_p = Partner.from_dict(body.dict())
except NodeConflictException:
abort(409, description="Partner already exists")
except Exception as e:
abort(
400,
Expand All @@ -72,8 +76,9 @@ def create_partner():
}
)
# update to UserRole contributor status
current_user.role = UserRole.CONTRIBUTOR.value
current_user.save()
if current_user.role_enum.get_value() < UserRole.CONTRIBUTOR.get_value():
current_user.role = UserRole.CONTRIBUTOR.value
current_user.save()
logger.info(f"User {current_user.uid} created partner {new_p.name}")

track_to_mp(request, "create_partner", {
Expand Down Expand Up @@ -108,6 +113,33 @@ def get_all_partners():
return ordered_jsonify(results), 200


@bp.route("/<partner_uid>", methods=["PATCH"])
@jwt_required()
@min_role_required(UserRole.PUBLIC)
@validate_request(UpdatePartner)
def update_partner(partner_uid: str):
"""Update a partner's information."""
body: UpdatePartner = request.validated_body
current_user = User.get(get_jwt()["sub"])
p = Partner.nodes.get_or_none(uid=partner_uid)
if p is None:
abort(404, description="Partner not found")

if p.members.is_connected(current_user):
rel = p.members.relationship(current_user)
if not rel.is_administrator():
abort(403, description="Not authorized to update partner")
else:
abort(403, description="Not authorized to update partner")

try:
p.from_dict(body.dict(), partner_uid)
p.refresh()
return p.to_json()
except Exception as e:
abort(400, description=str(e))


@bp.route("/<int:partner_id>/members/", methods=["GET"])
@jwt_required()
@min_role_required(UserRole.PUBLIC)
Expand Down
Loading

0 comments on commit 443e786

Please sign in to comment.