diff --git a/backend/routes/agencies.py b/backend/routes/agencies.py index cd076edd8..aeacebc9a 100644 --- a/backend/routes/agencies.py +++ b/backend/routes/agencies.py @@ -8,9 +8,9 @@ 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 npdi_oas.agencies import CreateAgency, UpdateAgency from pydantic import BaseModel @@ -46,7 +46,7 @@ def create_agency(): body: CreateAgency = request.validated_body try: - agency = Agency.from_dict(body.dict()) + agency = Agency.from_dict(body.model_dump()) except NodeConflictException: abort(409, description="Agency already exists") except Exception as e: @@ -95,7 +95,7 @@ def update_agency(agency_uid: str): abort(404, description="Agency not found") try: - agency = Agency.from_dict(body.dict(), agency_uid) + agency = Agency.from_dict(body.model_dump(), agency_uid) agency.refresh() track_to_mp( request, diff --git a/backend/routes/officers.py b/backend/routes/officers.py index 9d53ddba3..95575b145 100644 --- a/backend/routes/officers.py +++ b/backend/routes/officers.py @@ -6,10 +6,10 @@ from backend.schemas import validate_request, ordered_jsonify, paginate_results from backend.database.models.user import UserRole, User from backend.database.models.officer import Officer -from .tmp.pydantic.officers import CreateOfficer, UpdateOfficer from flask import Blueprint, abort, request from flask_jwt_extended import get_jwt from flask_jwt_extended.view_decorators import jwt_required +from npdi_oas.officers import CreateOfficer, UpdateOfficer from pydantic import BaseModel @@ -138,7 +138,7 @@ def create_officer(): current_user = User.get(jwt_decoded["sub"]) # try: - officer = Officer.from_dict(body.dict()) + officer = Officer.from_dict(body.model_dump()) # except Exception as e: # abort(400, description=str(e)) @@ -200,7 +200,7 @@ def update_officer(officer_uid: str): abort(404, description="Officer not found") try: - o = Officer.from_dict(body.dict(), officer_uid) + o = Officer.from_dict(body.model_dump(), officer_uid) o.refresh() except Exception as e: abort(400, description=str(e)) diff --git a/backend/routes/sources.py b/backend/routes/sources.py index 2ee004a96..2ada0b86b 100644 --- a/backend/routes/sources.py +++ b/backend/routes/sources.py @@ -6,10 +6,10 @@ 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 from flask_jwt_extended import get_jwt from flask_jwt_extended.view_decorators import jwt_required +from npdi_oas.sources import CreateSource, UpdateSource from ..database import ( Source, @@ -39,11 +39,11 @@ def get_sources(source_uid: str): @bp.route("/", methods=["POST"]) @jwt_required() @min_role_required(UserRole.PUBLIC) -@validate_request(CreatePartner) +@validate_request(CreateSource) def create_source(): """Create a contributing source.""" logger = logging.getLogger("create_source") - body: CreatePartner = request.validated_body + body: CreateSource = request.validated_body jwt_decoded = get_jwt() current_user = User.get(jwt_decoded["sub"]) @@ -58,7 +58,7 @@ def create_source(): # Creates a new instance of the Source and saves it to the DB try: - new_p = Source.from_dict(body.dict()) + new_p = Source.from_dict(body.model_dump()) except NodeConflictException: abort(409, description="Source already exists") except Exception as e: @@ -114,10 +114,10 @@ def get_all_sources(): @bp.route("/", methods=["PATCH"]) @jwt_required() @min_role_required(UserRole.PUBLIC) -@validate_request(UpdatePartner) +@validate_request(UpdateSource) def update_source(source_uid: str): """Update a source's information.""" - body: UpdatePartner = request.validated_body + body: UpdateSource = request.validated_body current_user = User.get(get_jwt()["sub"]) p = Source.nodes.get_or_none(uid=source_uid) if p is None: @@ -131,7 +131,7 @@ def update_source(source_uid: str): abort(403, description="Not authorized to update source") try: - p.from_dict(body.dict(), source_uid) + p.from_dict(body.model_dump(), source_uid) p.refresh() return p.to_json() except Exception as e: @@ -284,10 +284,10 @@ def add_member_to_source(): @bp.route("/join", methods=["POST"]) @jwt_required() @min_role_required(UserRole.PUBLIC) -@validate_request(CreatePartner) +@validate_request(CreateSource) def join_organization(): logger = logging.getLogger("join_organization") - body: CreatePartner = request.validated_body + body: CreateSource = request.validated_body jwt_decoded = get_jwt() current_user = User.get(jwt_decoded["sub"]) source = Source.nodes.get_or_none(uid=body["source_uid"]) diff --git a/backend/routes/tmp/pydantic/agencies.py b/backend/routes/tmp/pydantic/agencies.py deleted file mode 100644 index d5b8efa25..000000000 --- a/backend/routes/tmp/pydantic/agencies.py +++ /dev/null @@ -1,133 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union -from .common import PaginatedResponse - - -class BaseAgency(BaseModel): - name: Optional[str] = Field(None, description="Name of the agency") - hq_address: Optional[str] = Field(None, description="Address of the agency") - hq_city: Optional[str] = Field(None, description="City of the agency") - hq_state: Optional[str] = Field(None, description="State of the agency") - hq_zip: Optional[str] = Field(None, description="Zip code of the agency") - jurisdiction: Optional[str] = Field(None, description="Jurisdiction of the agency") - phone: Optional[str] = Field(None, description="Phone number of the agency") - email: Optional[str] = Field(None, description="Email of the agency") - website_url: Optional[str] = Field(None, description="Website of the agency") - - -class CreateAgency(BaseAgency, BaseModel): - name: Optional[str] = Field(None, description="Name of the agency") - hq_address: Optional[str] = Field(None, description="Address of the agency") - hq_city: Optional[str] = Field(None, description="City of the agency") - hq_state: Optional[str] = Field(None, description="State of the agency") - hq_zip: Optional[str] = Field(None, description="Zip code of the agency") - jurisdiction: Optional[str] = Field(None, description="Jurisdiction of the agency") - phone: Optional[str] = Field(None, description="Phone number of the agency") - email: Optional[str] = Field(None, description="Email of the agency") - website_url: Optional[str] = Field(None, description="Website of the agency") - - -class UpdateAgency(BaseAgency, BaseModel): - name: Optional[str] = Field(None, description="Name of the agency") - hq_address: Optional[str] = Field(None, description="Address of the agency") - hq_city: Optional[str] = Field(None, description="City of the agency") - hq_state: Optional[str] = Field(None, description="State of the agency") - hq_zip: Optional[str] = Field(None, description="Zip code of the agency") - jurisdiction: Optional[str] = Field(None, description="Jurisdiction of the agency") - phone: Optional[str] = Field(None, description="Phone number of the agency") - email: Optional[str] = Field(None, description="Email of the agency") - website_url: Optional[str] = Field(None, description="Website of the agency") - - -class Agency(BaseAgency, BaseModel): - name: Optional[str] = Field(None, description="Name of the agency") - hq_address: Optional[str] = Field(None, description="Address of the agency") - hq_city: Optional[str] = Field(None, description="City of the agency") - hq_state: Optional[str] = Field(None, description="State of the agency") - hq_zip: Optional[str] = Field(None, description="Zip code of the agency") - jurisdiction: Optional[str] = Field(None, description="Jurisdiction of the agency") - phone: Optional[str] = Field(None, description="Phone number of the agency") - email: Optional[str] = Field(None, description="Email of the agency") - website_url: Optional[str] = Field(None, description="Website of the agency") - uid: Optional[str] = Field(None, description="Unique identifier for the agency") - officers_url: Optional[str] = Field(None, description="URL to get a list of officers for this agency") - units_url: Optional[str] = Field(None, description="URL to get a list of units for this agency") - - -class AgencyList(PaginatedResponse, BaseModel): - results: Optional[List[Agency]] = None - - -class BaseUnit(BaseModel): - """Base properties for a unit""" - name: Optional[str] = Field(None, description="Name of the unit") - website_url: Optional[str] = Field(None, description="Website of the unit") - phone: Optional[str] = Field(None, description="Phone number of the unit") - email: Optional[str] = Field(None, description="Email of the unit") - description: Optional[str] = Field(None, description="Description of the unit") - address: Optional[str] = Field(None, description="Street address of the unit") - zip: Optional[str] = Field(None, description="Zip code of the unit") - date_established: Optional[str] = Field(None, description="The date that this unit was established by its parent agency.") - - -class CreateUnit(BaseUnit, BaseModel): - name: str = Field(..., description="Name of the unit") - website_url: Optional[str] = Field(None, description="Website of the unit") - phone: Optional[str] = Field(None, description="Phone number of the unit") - email: Optional[str] = Field(None, description="Email of the unit") - description: Optional[str] = Field(None, description="Description of the unit") - address: Optional[str] = Field(None, description="Street address of the unit") - zip: Optional[str] = Field(None, description="Zip code of the unit") - date_established: Optional[str] = Field(None, description="The date that this unit was established by its parent agency.") - commander_uid: Optional[str] = Field(None, description="The UID of the unit's current commander.") - - -class UpdateUnit(BaseUnit, BaseModel): - name: Optional[str] = Field(None, description="Name of the unit") - website_url: Optional[str] = Field(None, description="Website of the unit") - phone: Optional[str] = Field(None, description="Phone number of the unit") - email: Optional[str] = Field(None, description="Email of the unit") - description: Optional[str] = Field(None, description="Description of the unit") - address: Optional[str] = Field(None, description="Street address of the unit") - zip: Optional[str] = Field(None, description="Zip code of the unit") - date_established: Optional[str] = Field(None, description="The date that this unit was established by its parent agency.") - commander_uid: Optional[str] = Field(None, description="The UID of the unit's current commander.") - - -class Unit(BaseUnit, BaseModel): - name: Optional[str] = Field(None, description="Name of the unit") - website_url: Optional[str] = Field(None, description="Website of the unit") - phone: Optional[str] = Field(None, description="Phone number of the unit") - email: Optional[str] = Field(None, description="Email of the unit") - description: Optional[str] = Field(None, description="Description of the unit") - address: Optional[str] = Field(None, description="Street address of the unit") - zip: Optional[str] = Field(None, description="Zip code of the unit") - date_established: Optional[str] = Field(None, description="The date that this unit was established by its parent agency.") - uid: Optional[str] = Field(None, description="Unique identifier for the unit") - commander_history_url: Optional[str] = Field(None, description="-| URL that returns the past commanders of the unit and the period of their respective commands.") - agency_url: Optional[str] = Field(None, description="URL to get the agency that this unit belongs to.") - officers_url: Optional[str] = Field(None, description="URL to get a list of officers for this unit.") - - -class UnitList(PaginatedResponse, BaseModel): - results: Optional[List[Unit]] = None - - -class AddOfficer(BaseModel): - officer_uid: str = Field(..., description="The uid of the officer") - earliest_employment: Optional[str] = Field(None, description="The earliest date of employment") - latest_employment: Optional[str] = Field(None, description="The latest date of employment") - badge_number: str = Field(..., description="The badge number of the officer") - unit_uid: str = Field(..., description="The UID of the unit the officer is assigned to.") - highest_rank: Optional[str] = Field(None, description="The highest rank the officer has held during their employment.") - commander: Optional[bool] = Field(None, description="-| If true, this officer will be added as the commander of the unit for the specified time period.") - - -class AddOfficerList(BaseModel): - officers: List[AddOfficer] = ... - - -class AddOfficerFailed(BaseModel): - officer_uid: Optional[str] = Field(None, description="The uid of the officer") - reason: Optional[str] = Field(None, description="The reason the employment record could not be added") - diff --git a/backend/routes/tmp/pydantic/common.py b/backend/routes/tmp/pydantic/common.py deleted file mode 100644 index 91aebc9b8..000000000 --- a/backend/routes/tmp/pydantic/common.py +++ /dev/null @@ -1,8 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union - - -class PaginatedResponse(BaseModel): - page: Optional[int] = Field(None, description="The current page number.") - per_page: Optional[int] = Field(None, description="The number of items per page.") - total: Optional[int] = Field(None, description="The total number of items.") \ No newline at end of file diff --git a/backend/routes/tmp/pydantic/officers.py b/backend/routes/tmp/pydantic/officers.py deleted file mode 100644 index 572761def..000000000 --- a/backend/routes/tmp/pydantic/officers.py +++ /dev/null @@ -1,115 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union -from .common import PaginatedResponse - - -class StateId(BaseModel): - uid: Optional[str] = Field(None, description="The UUID of this state id") - state: Optional[str] = Field(None, description="The state of the state id") - id_name: Optional[str] = Field(None, description="The name of the id. For example, Tax ID, Driver's License, etc.") - value: Optional[str] = Field(None, description="The value of the id.") - - -class BaseEmployment(BaseModel): - officer_uid: Optional[str] = Field(None, description="The UID of the officer.") - agency_uid: Optional[str] = Field(None, description="The UID of the agency the officer is employed by.") - unit_uid: Optional[str] = Field(None, description="The UID of the unit the officer is assigned to.") - earliest_employment: Optional[str] = Field(None, description="The earliest known date of employment") - latest_employment: Optional[str] = Field(None, description="The latest known date of employment") - badge_number: Optional[str] = Field(None, description="The badge number of the officer") - highest_rank: Optional[str] = Field(None, description="The highest rank the officer has held during this employment.") - commander: Optional[bool] = Field(None, description="Indicates that the officer commanded the unit during this employment.") - - -class AddEmployment(BaseEmployment, BaseModel): - officer_uid: Optional[str] = Field(None, description="The UID of the officer.") - agency_uid: Optional[str] = Field(None, description="The UID of the agency the officer is employed by.") - unit_uid: Optional[str] = Field(None, description="The UID of the unit the officer is assigned to.") - earliest_employment: Optional[str] = Field(None, description="The earliest known date of employment") - latest_employment: Optional[str] = Field(None, description="The latest known date of employment") - badge_number: Optional[str] = Field(None, description="The badge number of the officer") - highest_rank: Optional[str] = Field(None, description="The highest rank the officer has held during this employment.") - commander: Optional[bool] = Field(None, description="Indicates that the officer commanded the unit during this employment.") - - -class AddEmploymentFailed(BaseModel): - agency_uid: Optional[str] = Field(None, description="The uid of the agency that could not be added.") - reason: Optional[str] = Field(None, description="The reason the employment record could not be added") - - -class AddEmploymentList(BaseModel): - agencies: Optional[List[AddEmployment]] = Field(None, description="The units to add to the officer's employment history.") - - -class Employment(BaseEmployment, BaseModel): - officer_uid: Optional[str] = Field(None, description="The UID of the officer.") - agency_uid: Optional[str] = Field(None, description="The UID of the agency the officer is employed by.") - unit_uid: Optional[str] = Field(None, description="The UID of the unit the officer is assigned to.") - earliest_employment: Optional[str] = Field(None, description="The earliest known date of employment") - latest_employment: Optional[str] = Field(None, description="The latest known date of employment") - badge_number: Optional[str] = Field(None, description="The badge number of the officer") - highest_rank: Optional[str] = Field(None, description="The highest rank the officer has held during this employment.") - commander: Optional[bool] = Field(None, description="Indicates that the officer commanded the unit during this employment.") - - -class AddEmploymentResponse(BaseModel): - created: List[Employment] = ... - failed: List[AddEmploymentFailed] = ... - total_created: int = ... - total_failed: int = ... - - -class EmploymentList(PaginatedResponse, BaseModel): - results: Optional[List[Employment]] = None - - -class BaseOfficer(BaseModel): - first_name: Optional[str] = Field(None, description="First name of the officer") - middle_name: Optional[str] = Field(None, description="Middle name of the officer") - last_name: Optional[str] = Field(None, description="Last name of the officer") - suffix: Optional[str] = Field(None, description="Suffix of the officer's name") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the officer") - gender: Optional[str] = Field(None, description="The gender of the officer") - date_of_birth: Optional[str] = Field(None, description="The date of birth of the officer") - state_ids: Optional[List[StateId]] = Field(None, description="The state ids of the officer") - - -class CreateOfficer(BaseOfficer, BaseModel): - first_name: Optional[str] = Field(None, description="First name of the officer") - middle_name: Optional[str] = Field(None, description="Middle name of the officer") - last_name: Optional[str] = Field(None, description="Last name of the officer") - suffix: Optional[str] = Field(None, description="Suffix of the officer's name") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the officer") - gender: Optional[str] = Field(None, description="The gender of the officer") - date_of_birth: Optional[str] = Field(None, description="The date of birth of the officer") - state_ids: Optional[List[StateId]] = Field(None, description="The state ids of the officer") - - -class UpdateOfficer(BaseOfficer, BaseModel): - first_name: Optional[str] = Field(None, description="First name of the officer") - middle_name: Optional[str] = Field(None, description="Middle name of the officer") - last_name: Optional[str] = Field(None, description="Last name of the officer") - suffix: Optional[str] = Field(None, description="Suffix of the officer's name") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the officer") - gender: Optional[str] = Field(None, description="The gender of the officer") - date_of_birth: Optional[str] = Field(None, description="The date of birth of the officer") - state_ids: Optional[List[StateId]] = Field(None, description="The state ids of the officer") - - -class Officer(BaseOfficer, BaseModel): - first_name: Optional[str] = Field(None, description="First name of the officer") - middle_name: Optional[str] = Field(None, description="Middle name of the officer") - last_name: Optional[str] = Field(None, description="Last name of the officer") - suffix: Optional[str] = Field(None, description="Suffix of the officer's name") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the officer") - gender: Optional[str] = Field(None, description="The gender of the officer") - date_of_birth: Optional[str] = Field(None, description="The date of birth of the officer") - state_ids: Optional[List[StateId]] = Field(None, description="The state ids of the officer") - uid: Optional[str] = Field(None, description="The uid of the officer") - employment_history: Optional[str] = Field(None, description="A link to retrieve the employment history of the officer") - allegations: Optional[str] = Field(None, description="A link to retrieve the allegations against the officer") - litigation: Optional[str] = Field(None, description="A link to retrieve the litigation against the officer") - - -class OfficerList(PaginatedResponse, BaseModel): - results: Optional[List[Officer]] = None \ No newline at end of file diff --git a/backend/routes/tmp/pydantic/partners.py b/backend/routes/tmp/pydantic/partners.py deleted file mode 100644 index dd15519ae..000000000 --- a/backend/routes/tmp/pydantic/partners.py +++ /dev/null @@ -1,61 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union -from .common import PaginatedResponse - - -class BasePartner(BaseModel): - name: Optional[str] = Field(None, description="Name of the partner organization.") - url: Optional[str] = Field(None, description="Website URL of the partner.") - contact_email: Optional[str] = Field(None, description="Contact email for the partner organization.") - - -class CreatePartner(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the partner organization.") - url: Optional[str] = Field(None, description="Website URL of the partner.") - contact_email: Optional[str] = Field(None, description="Contact email for the partner organization.") - - -class UpdatePartner(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the partner organization.") - url: Optional[str] = Field(None, description="Website URL of the partner.") - contact_email: Optional[str] = Field(None, description="Contact email for the partner organization.") - - -class Partner(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the partner organization.") - url: Optional[str] = Field(None, description="Website URL of the partner.") - contact_email: Optional[str] = Field(None, description="Contact email for the partner organization.") - uid: Optional[str] = Field(None, description="Unique identifier for the partner.") - members: Optional[str] = Field(None, description="Url to get all members of the partner.") - reported_incidents: Optional[str] = Field(None, description="Url to get all incidents reported by the partner.") - - -class PartnerList(PaginatedResponse, BaseModel): - results: Optional[List[Partner]] = None - - -class MemberBase(BaseModel): - partner_uid: Optional[str] = Field(None, description="Unique identifier for the partner.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - - -class Member(MemberBase, BaseModel): - partner_uid: Optional[str] = Field(None, description="Unique identifier for the partner.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - uid: Optional[str] = Field(None, description="Unique identifier for the user.") - date_joined: Optional[str] = Field(None, description="Date the user joined the partner organizaation.") - - -class AddMember(MemberBase, BaseModel): - partner_uid: Optional[str] = Field(None, description="Unique identifier for the partner.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - - -class MemberList(PaginatedResponse, BaseModel): - results: Optional[List[Member]] = None diff --git a/backend/schemas.py b/backend/schemas.py index 4225a72ca..90bc2e207 100644 --- a/backend/schemas.py +++ b/backend/schemas.py @@ -138,7 +138,7 @@ def ordered_jsonify(*args, **kwargs): # A decorator to validate request bodies using Pydantic models -def validate_request(model: BaseModel): +def validate_request(model: type[BaseModel]): """ Validate the request body using a Pydantic model. @@ -170,7 +170,7 @@ def paginate_results( data: list[JsonSerializable], page: int, per_page: int = 20, max_per_page: int = 100): """ - Paginate a list of data and return a reponse dict. Items in the list must + Paginate a list of data and return a response dict. Items in the list must implement the JsonSerializable interface. Args: diff --git a/oas/2.0/agencies.yaml b/oas/2.0/agencies.yaml deleted file mode 100644 index 70d24925b..000000000 --- a/oas/2.0/agencies.yaml +++ /dev/null @@ -1,574 +0,0 @@ -openapi: "3.0.3" -info: - title: "Agencies" - description: "API Description" - version: "0.7.0" -servers: - - url: "http://127.0.0.1:5001/api/v1" - description: "Development environment" - - url: "https://dev.nationalpolicedata.org/api/v1" - description: "Staging environment" - - url: "https://api.nationalpolicedata.org" - description: "Production environment" -x-readme: - explorer-enabled: true - proxy-enabled: true - samples-enabled: true -security: - - bearerAuth: [] -tags: - - name: "Agencies" - description: "API for managing agencies" - - name: "Units" - description: "API for managing the units and officers of an agency." -paths: - /agencies: - get: - summary: "Get Agencies" - operationId: "getAgencies" - description: "Get a list of all agencies" - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - - $ref: '#/components/parameters/jurisdiction' - - $ref: '#/components/parameters/name' - - $ref: '#/components/parameters/zip_code' - - $ref: '#/components/parameters/city' - - $ref: '#/components/parameters/state' - tags: - - Agencies - responses: - "200": - description: "A JSON array of agency objects" - content: - application/json: - schema: - $ref: "#/components/schemas/AgencyList" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - post: - summary: "Create Agency" - operationId: "createAgency" - description: "Create a new law enforement agency. The user must be a contributor." - tags: - - Agencies - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/CreateAgency" - responses: - "201": - description: "Returns the created agency object." - content: - application/json: - schema: - $ref: "#/components/schemas/Agency" - "400": - $ref: '../common/error.yaml#/components/responses/validationError' - /agencies/{agency_uid}: - parameters: - - name: "agency_uid" - in: "path" - description: "The uid of the agency you want to retrieve." - required: true - schema: - type: "string" - get: - summary: "Get Agency" - operationId: "getAgency" - description: "Get a single agency by uid." - tags: - - Agencies - responses: - "200": - description: "An agency object" - content: - application/json: - schema: - $ref: "#/components/schemas/Agency" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - patch: - summary: "Update Agency" - operationId: "updateAgency" - description: "Update a single agency. User must be a contributor." - tags: - - Agencies - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateAgency" - responses: - '200': - description: 'Returns the updated agency object.' - content: - application/json: - schema: - $ref: '#/components/schemas/Agency' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - /agencies/{agency_uid}/officers: - get: - summary: "Get Officers" - operationId: "getOfficers" - parameters: - - name: "agency_uid" - in: "path" - description: "The uid of the agency you want to retrieve." - required: true - schema: - type: "string" - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - - $ref: 'officers.yaml#/components/parameters/active_after' - - $ref: 'officers.yaml#/components/parameters/active_before' - - $ref: 'officers.yaml#/components/parameters/agency' - - $ref: 'officers.yaml#/components/parameters/rank' - - $ref: 'officers.yaml#/components/parameters/unit' - - $ref: 'officers.yaml#/components/parameters/name' - - $ref: 'officers.yaml#/components/parameters/ethnicity' - - $ref: 'officers.yaml#/components/parameters/badge_number' - description: > - Get a list of all of the officers who have been employed - by a given agency. - tags: - - Units - responses: - "200": - description: "A JSON array of officer objects" - content: - application/json: - schema: - $ref: officers.yaml#/components/schemas/OfficerList - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - put: - summary: "Add Employment Records" - operationId: "addOfficers" - description: > - Adds officer employment records to an agency. Can only - add records for officers that already exist in the database. - User must be a contributor. - parameters: - - name: "agency_uid" - in: "path" - description: "The uid of the agency you want to retrieve." - required: true - schema: - type: "string" - tags: - - Units - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/AddOfficerList" - responses: - '200': - description: > - Returns the updated employment records. The response also includes - information about any records that could not be added. - content: - application/json: - schema: - $ref: '#/components/schemas/AddOfficerResponse' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - /agencies/{agency_uid}/units: - get: - summary: "Get Units" - operationId: "getUnits" - description: "Get a list of all units for a given agency." - parameters: - - name: "agency_uid" - in: "path" - description: "The uid of the agency you want to retrieve units for." - required: true - schema: - type: "string" - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - - $ref: '#/components/parameters/name' - - $ref: '#/components/parameters/zip_code' - - $ref: '#/components/parameters/city' - - $ref: '#/components/parameters/state' - tags: - - Units - responses: - "200": - description: "A JSON array of unit objects" - content: - application/json: - schema: - $ref: "#/components/schemas/UnitList" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - post: - summary: "Create Unit" - operationId: "createUnit" - description: "Adds a unit or command to an existing agency. User must be a contributor." - parameters: - - name: "agency_uid" - in: "path" - description: "The uid of the agency you want to retrieve units for." - required: true - schema: - type: "string" - tags: - - Units - requestBody: - description: "Officer object that needs to be added to the database" - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/CreateUnit" - responses: - "201": - description: "A JSON array of Unit objects" - content: - application/json: - schema: - $ref: "#/components/schemas/CreateUnit" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - /agencies/{agency_uid}/units/{unit_uid}: - get: - summary: "Get Unit" - operationId: "getUnit" - description: > - Retrieve detailed information about a single unit. - tags: - - Units - parameters: - - name: "agency_uid" - in: "path" - description: "The uid of the agency you want to retrieve units for." - required: true - schema: - type: "string" - - name: "unit_uid" - in: "path" - description: "The uid of the unit you want to retrieve." - required: true - schema: - type: "string" - responses: - "200": - description: "A JSON array of unit objects" - content: - application/json: - schema: - $ref: "#/components/schemas/Unit" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - patch: - summary: "Update Unit" - operationId: "updateUnit" - description: "Update an existing unit. User must be a contributor." - parameters: - - name: "agency_uid" - in: "path" - description: "The uid of the agency you want to retrieve units for." - required: true - schema: - type: "string" - - name: "unit_uid" - in: "path" - description: "The uid of the unit you want to retrieve." - required: true - schema: - type: "string" - tags: - - Units - requestBody: - description: "Fields that need to be updated." - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateUnit" - responses: - "200": - description: "A JSON array of Unit objects" - content: - application/json: - schema: - $ref: "#/components/schemas/Unit" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - parameters: - jurisdiction: - name: "jurisdiction" - in: "query" - description: "Filter agencies by jurisdiction" - required: false - schema: - type: "string" - zip_code: - name: "zip_code" - in: "query" - description: "Filter by zip code" - required: false - schema: - type: "string" - city: - name: "city" - in: "query" - description: "Filter by city" - required: false - schema: - type: "string" - state: - name: "state" - in: "query" - description: "Filter by state" - required: false - schema: - type: "string" - name: - name: "name" - in: "query" - description: "Filter by name" - required: false - schema: - type: "string" - schemas: - BaseAgency: - type: "object" - properties: - name: - type: "string" - description: "Name of the agency" - hq_address: - type: "string" - description: "Address of the agency" - hq_city: - type: "string" - description: "City of the agency" - hq_state: - type: "string" - description: "State of the agency" - hq_zip: - type: "string" - description: "Zip code of the agency" - jurisdiction: - type: "string" - description: "Jurisdiction of the agency" - phone: - type: "string" - description: "Phone number of the agency" - email: - type: "string" - description: "Email of the agency" - website_url: - type: "string" - description: "Website of the agency" - CreateAgency: - allOf: - - $ref: "#/components/schemas/BaseAgency" - - type: "object" - required: - - name - - hq_address - - hq_city - - hq_zip - - jurisdiction - - website_url - UpdateAgency: - allOf: - - $ref: "#/components/schemas/BaseAgency" - AgencyList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/Agency" - Agency: - allOf: - - $ref: "#/components/schemas/BaseAgency" - - type: "object" - properties: - uid: - type: string - description: Unique identifier for the agency - officers_url: - type: "string" - description: "URL to get a list of officers for this agency" - units_url: - type: "string" - description: "URL to get a list of units for this agency" - CreateUnit: - allOf: - - $ref: "#/components/schemas/BaseUnit" - - type: "object" - properties: - commander_uid: - type: "string" - description: "The UID of the unit's current commander." - required: - - name - UpdateUnit: - allOf: - - $ref: "#/components/schemas/BaseUnit" - - type: object - properties: - commander_uid: - type: string - description: The UID of the unit's current commander. - BaseUnit: - type: object - description: "Base properties for a unit" - properties: - name: - type: "string" - description: "Name of the unit" - website_url: - type: "string" - description: "Website of the unit" - phone: - type: "string" - description: "Phone number of the unit" - email: - type: "string" - description: "Email of the unit" - description: - type: "string" - description: "Description of the unit" - address: - type: "string" - description: "Street address of the unit" - zip: - type: "string" - description: "Zip code of the unit" - date_established: - type: string - description: The date that this unit was established by its parent agency. - format: date - Unit: - allOf: - - $ref: "#/components/schemas/BaseUnit" - - type: "object" - properties: - uid: - type: "string" - description: "Unique identifier for the unit" - commander: - allOf: - - $ref: officers.yaml#/components/schemas/Officer - - type: object - description: The current commander of the unit. - commander_history_url: - type: string - description: -| - URL that returns the past commanders of the unit and the period of their respective commands. - agency_url: - type: "string" - description: "URL to get the agency that this unit belongs to." - officers_url: - type: "string" - description: "URL to get a list of officers for this unit." - UnitList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/Unit" - AddOfficer: - type: object - required: - - officer_uid - - badge_number - - unit_uid - properties: - officer_uid: - type: "string" - description: "The uid of the officer" - earliest_employment: - type: "string" - format: "date" - description: "The earliest date of employment" - latest_employment: - type: "string" - format: "date" - description: "The latest date of employment" - badge_number: - type: "string" - description: "The badge number of the officer" - unit_uid: - type: "string" - description: "The UID of the unit the officer is assigned to." - highest_rank: - type: "string" - description: "The highest rank the officer has held during their employment." - commander: - type: boolean - description: -| - If true, this officer will be added as the commander of the unit for the specified time period. - AddOfficerList: - type: object - required: - - officers - properties: - officers: - type: array - items: - $ref: "#/components/schemas/AddOfficer" - AddOfficerFailed: - type: object - properties: - officer_uid: - type: "string" - description: "The uid of the officer" - reason: - type: "string" - description: "The reason the employment record could not be added" - AddOfficerResponse: - type: object - required: - - created - - failed - - total_created - - total_failed - properties: - created: - type: array - items: - $ref: officers.yaml#/components/schemas/Employment - failed: - type: array - items: - $ref: "#/components/schemas/AddOfficerFailed" - total_created: - type: integer - minimum: 0 - total_failed: - type: integer - minimum: 0 diff --git a/oas/2.0/authentication.yaml b/oas/2.0/authentication.yaml deleted file mode 100644 index 5ab89c5ad..000000000 --- a/oas/2.0/authentication.yaml +++ /dev/null @@ -1,198 +0,0 @@ -openapi: "3.0.3" -info: - title: "Authentication" - description: "API Description" - version: "0.7.0" -servers: - - url: "http://dev.nationalpolicedata.org/api/v1" - description: "Development environment" - - url: "https://dev.nationalpolicedata.org/api/v1" - description: "Staging environment" - - url: "https://api.nationalpolicedata.org" - description: "Production environment" -x-readme: - explorer-enabled: true - proxy-enabled: true - samples-enabled: true -tags: - - name: "Authentication" - description: "API for authenticating and creating user accounts." -paths: - /auth/register: - post: - summary: "Register New Account" - operationId: "register" - description: "Create a new user account." - tags: - - Authentication - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/RegisterRequest" - responses: - "200": - description: "Logs in and returns the created user object." - content: - application/json: - schema: - $ref: "#/components/schemas/RegisterResponse" - "400": - $ref: '../common/error.yaml#/components/responses/validationError' - "409": - $ref: '../common/error.yaml#/components/responses/conflictError' - /auth/login: - post: - summary: "Log In" - operationId: "login" - description: "Log in to an existing user account." - tags: - - Authentication - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/LoginRequest" - responses: - '200': - description: 'Returns JWT that may be used to authenticate future API requests.' - content: - application/json: - schema: - $ref: '#/components/schemas/LoginResponse' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - /auth/refresh: - post: - security: - - bearerAuth: [] - summary: "Refresh Access Token" - operationId: "refreshToken" - description: > - Refreshes the current access token to reset the expiration date. - tags: - - Authentication - responses: - '200': - description: > - Returns the updated employment records. The response also includes - information about any records that could not be added. - content: - application/json: - schema: - $ref: '#/components/schemas/LoginResponse' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /auth/logout: - post: - security: - - bearerAuth: [] - summary: "Log Out" - operationId: "logout" - description: "Revokes the access token used to autheticate this request." - tags: - - Authentication - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/LogoutResponse" - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /auth/whoami: - get: - security: - - bearerAuth: [] - summary: "Current User" - operationId: "whoami" - description: "Returns the user that matches the access token used to authenticate the request." - tags: - - Authentication - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/CurrentUser" - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - schemas: - RegisterRequest: - type: "object" - properties: - email: - type: "string" - description: "The user's email address." - password: - type: "string" - description: "The user's desired password." - first_name: - type: "string" - description: "The user's first name." - last_name: - type: "string" - description: "The user's last name." - phone_number: - type: "string" - description: "The user's phone number." - required: - - email - - first_name - - last_name - - password - - phone_number - RegisterResponse: - type: "object" - properties: - msg: - type: string - description: information about the registration action. - access_token: - type: string - description: The JWT that can be used to authenticate API requests on behalf of the user. - LoginRequest: - type: object - properties: - email: - type: string - description: The user's email address. - password: - type: string - description: The user's password. - required: - - email - - password - LoginResponse: - type: object - properties: - access_token: - type: string - description: The JWT that can be used to authenticate API requests on behalf of the user. - message: - type: string - description: Additional detail aboout the login action. - CurrentUser: - type: object - properties: - first_name: - type: string - description: The user's first name. - last_name: - type: string - description: The user's last name. - LogoutResponse: - type: object - properties: - msg: - type: string - description: A report of the logout action. - \ No newline at end of file diff --git a/oas/2.0/complaints.yaml b/oas/2.0/complaints.yaml deleted file mode 100644 index dc44f45f2..000000000 --- a/oas/2.0/complaints.yaml +++ /dev/null @@ -1,687 +0,0 @@ -openapi: "3.0.3" -info: - title: "Complaints" - description: "API Description" - version: "0.7.0" -servers: - - url: "http://127.0.0.1:5001/api/v1" - description: "Development environment" - - url: "https://dev.nationalpolicedata.org/api/v1" - description: "Staging environment" - - url: "https://api.nationalpolicedata.org" - description: "Production environment" -x-readme: - explorer-enabled: true - proxy-enabled: true - samples-enabled: true -security: - - bearerAuth: [] -tags: - - name: "Complaints" - description: "Complaints API" -paths: - /complaints/{complaint_uid}: - get: - parameters: - - name: complaint_uid - in: path - required: true - schema: - type: string - tags: - - "Complaints" - summary: "Get Complaint" - operationId: "getComplaint" - description: > - Returns information about a single complaint. - responses: - "200": - description: "A complaint object" - content: - application/json: - schema: - $ref: "#/components/schemas/Complaint" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - patch: - parameters: - - name: complaint_uid - in: path - required: true - schema: - type: string - tags: - - "Complaints" - summary: "Update Complaint" - operationId: "updateComplaint" - description: > - Update a single complaint. Only an admin of the contributing - organization or the original user who submitted the complaint - can update the complaint. - requestBody: - description: "Complaint object that needs to be updated in the database" - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateComplaint" - responses: - "200": - description: "A complaint object" - content: - application/json: - schema: - $ref: "#/components/schemas/Complaint" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /complaints: - post: - tags: - - "Complaints" - summary: "Create Complaint" - operationId: "createComplaint" - description: > - Create a single complaint. User must be a - contributor to create an complaint. - requestBody: - description: "Complaint object that needs to be added to the database" - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/CreateComplaint" - responses: - "200": - description: "A JSON array of user names" - content: - application/json: - schema: - $ref: "#/components/schemas/Complaint" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - '409': - $ref: '../common/error.yaml#/components/responses/conflictError' - get: - tags: - - "Complaints" - summary: "Get Complaints" - operationId: "getComplaints" - description: > - Returns all complaints in the database. Filters can be applied - to narrow down the results. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - - $ref: '#/components/parameters/source_uid' - - $ref: '#/components/parameters/source_type' - - $ref: '#/components/parameters/officers_involved' - - $ref: '#/components/parameters/category' - - $ref: '#/components/parameters/reason_for_contact' - - $ref: '#/components/parameters/outcome_of_contact' - - $ref: '#/components/parameters/date_gte' - - $ref: '#/components/parameters/date_lte' - responses: - "200": - description: "A JSON array of complaint objects" - content: - application/json: - schema: - $ref: "#/components/schemas/ComplaintList" - "401": - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - /complaints/latest: - get: - tags: - - "Complaints" - summary: "Latest Complaint Updates" - operationId: "getLatestComplaints" - description: > - Returns the most recently updated or added complaints. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - responses: - "200": - description: "A JSON array of complaint objects" - content: - application/json: - schema: - $ref: "#/components/schemas/ComplaintList" - "401": - $ref: '../common/error.yaml#/components/responses/unauthorizedError' -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - parameters: - source_uid: - name: source - in: query - description: "Filter by the source of the complaint. This should be the UID of the source." - required: false - schema: - type: string - source_type: - name: source_type - in: query - description: > - Filter by the type of source. This should be a comma separated list of source types. The valid - source types are 'legal', 'personal', 'news', and 'government'. - required: false - schema: - type: string - officers_involved: - name: officers_involved - in: query - description: > - Filter by the officers involved in the complaint. This should be a comma separated list of officer UIDs. - required: false - schema: - type: string - category: - name: category - in: query - description: "Filter by the category of the complaint." - required: false - schema: - type: string - reason_for_contact: - name: reason_for_contact - in: query - description: "Filter by the reason for contact." - required: false - schema: - type: string - outcome_of_contact: - name: outcome_of_contact - in: query - description: "Filter by the outcome of contact." - required: false - schema: - type: string - date_gte: - name: date_gte - in: query - description: "Only return complaints that occurred or were recieved after the selected date. This should be a date in the format YYYY-MM-DD." - required: false - schema: - type: string - format: date - date_lte: - name: date_lte - in: query - description: "Only return complaints that occurred or were recieved before the selected date. This should be a date in the format YYYY-MM-DD." - required: false - schema: - type: string - format: date - schemas: - BaseComplaint: - type: "object" - description: "Base complaint object" - properties: - record_id: - type: string - description: The ID that was given to this complaint by the orginal source of the data. - source_details: - $ref: '#/components/schemas/SourceDetails' - category: - type: "string" - description: "The category of the complaint." - incident_date: - type: "string" - format: "date-time" - description: "The date and time the incident occurred." - recieved_date: - type: "string" - format: "date-time" - description: "The date and time the complaint was received by the reporting source." - closed_date: - type: "string" - format: "date-time" - description: "The date and time the complaint was closed." - location: - type: object - properties: - address1: - type: "string" - description: "The address of the incident." - address2: - type: "string" - description: "The address of the incident." - city: - type: "string" - description: "The city of the incident." - state: - type: "string" - description: "The state of the incident." - zip: - type: "string" - description: "The zip code of the incident." - latitude: - type: "number" - description: "The latitude of the incident." - longitude: - type: "number" - description: "The longitude of the incident." - reason_for_contact: - type: "string" - description: "The reason for the contact." - outcome_of_contact: - type: "string" - description: "The outcome of the contact." - civilian_witnesses: - type: array - description: "The civilian witnesses associated with the complaint." - items: - $ref: "#/components/schemas/Civilian" - attachements: - type: "array" - description: "Documents and multimeida associated with the complaint." - items: - $ref: "#/components/schemas/Attachemnts" - CreateComplaint: - allOf: - - $ref: "#/components/schemas/BaseComplaint" - - type: object - properties: - source_uid: - type: "string" - description: "The UID of the source that reported the complaint." - civilian_review_board_uid: - type: "string" - description: "The UID of the civilian review board that reviewed the complaint." - police_witnesses: - type: "array" - description: "The UID of any police witnesses associated with the complaint." - items: - type: "string" - allegations: - type: "array" - description: "The allegations associated with the complaint." - items: - $ref: "#/components/schemas/CreateAllegation" - investigations: - type: "array" - description: "The investigations associated with the complaint." - items: - $ref: "#/components/schemas/CreateInvestigation" - penalties: - type: "array" - description: "The penalties associated with the complaint." - items: - $ref: "#/components/schemas/CreatePenalty" - UpdateComplaint: - allOf: - - $ref: "#/components/schemas/BaseComplaint" - - type: object - properties: - civilian_review_board_uid: - type: "string" - description: "The UID of the civilian review board that reviewed the complaint." - police_witnesses: - type: "array" - description: "The uid of any police witnesses associated with the complaint." - items: - type: "string" - allegations: - type: "array" - description: "The allegations associated with the complaint." - items: - $ref: "#/components/schemas/CreateAllegation" - investigations: - type: "array" - description: "The investigations associated with the complaint." - items: - $ref: "#/components/schemas/CreateInvestigation" - penalties: - type: "array" - description: "The penalties associated with the complaint." - items: - $ref: "#/components/schemas/CreatePenalty" - - Complaint: - allOf: - - $ref: "#/components/schemas/BaseComplaint" - - type: "object" - required: - - uid - - created_at - - updated_at - - source_uid - - category - - incident_date - - recieved_date - - location - - allegations - - penalties - - investigations - - police_witnesses - - civilian_witnesses - properties: - uid: - type: "string" - description: "Unique identifier for the complaint." - created_at: - type: "string" - format: "date-time" - description: "Date and time the complaint was created." - updated_at: - type: "string" - format: "date-time" - description: "Date and time the complaint was last updated." - source: - allOf: - - $ref: sources.yaml#/components/schemas/Source - - type: "object" - description: "The source that reported the complaint." - civilian_review_board: - allOf: - - $ref: '#/components/schemas/ReviewBoard' - - type: "object" - description: "The civilian review board that reviewed the complaint." - police_witnesses: - type: "array" - description: "The police witnesses associated with the complaint." - items: - $ref: officers.yaml#/components/schemas/Officer - allegations: - type: "array" - description: "The allegations associated with the complaint." - items: - $ref: "#/components/schemas/Allegation" - investigations: - type: "array" - description: "The investigations associated with the complaint." - items: - $ref: "#/components/schemas/Investigation" - penalties: - type: "array" - description: "The penalties associated with the complaint." - items: - $ref: "#/components/schemas/Penalty" - ComplaintList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - description: "List of complaints." - items: - $ref: "#/components/schemas/Complaint" - BaseAllegation: - type: "object" - properties: - record_id: - type: string - description: The ID that was given to this allegation by the orginal source of the data. - complaintant: - allOf: - - $ref: "#/components/schemas/Civilian" - - type: "object" - description: "Demographic information of the individual who filed the complaint." - allegation: - type: "string" - description: "The allegation made by the complaintant." - type: - type: string - description: The type of allegation. - sub_type: - type: string - description: The sub type of the allegation. - recomended_finding: - type: "string" - description: "The finding recomended by the review board." - recomended_outcome: - type: "string" - description: "The outcome recomended by the review board." - finding: - type: "string" - description: "The legal finding." - outcome: - type: "string" - description: "The final outcome of the allegation." - CreateAllegation: - allOf: - - $ref: "#/components/schemas/BaseAllegation" - - type: object - properties: - perpetrator_uid: - type: "string" - description: "The UID of the officer the allegation is made against." - Allegation: - allOf: - - $ref: "#/components/schemas/BaseAllegation" - - type: "object" - properties: - uid: - type: "string" - description: "Unique identifier for the allegation." - perpetrator: - allOf: - - $ref: officers.yaml#/components/schemas/Officer - - type: "object" - description: The officer who the allegation is made against. - Penalty: - type: "object" - properties: - uid: - type: string - description: UUID for the penalty. - officer: - allOf: - - $ref: officers.yaml#/components/schemas/Officer - - type: "object" - description: "The officer who the penalty is associated with." - description: - type: "string" - description: "A description of the penalty." - date_assesed: - type: string - format: date - CreatePenalty: - type: "object" - properties: - officer_uid: - type: "string" - description: "The UID of the officer the penalty is associated with." - description: - type: "string" - description: "A description of the penalty." - BaseInvestigation: - type: object - properties: - start_date: - type: "string" - format: "date-time" - description: "The date the investigation started." - end_date: - type: "string" - format: "date-time" - description: "The date the investigation ended." - CreateInvestigation: - allOf: - - $ref: "#/components/schemas/BaseInvestigation" - - type: object - properties: - investigator_uid: - type: "string" - description: "The UID of the officer who preformed the investigation." - Investigation: - allOf: - - $ref: "#/components/schemas/BaseInvestigation" - - type: "object" - properties: - uid: - type: "string" - description: "Unique identifier for the investigation." - investigator: - allOf: - - $ref: officers.yaml#/components/schemas/Officer - - type: "object" - description: "The officer who preformed the investigation." - Civilian: - type: "object" - properties: - age: - type: "string" - description: "Age range of the individual." - ethnicity: - type: "string" - description: "The ethnicity of the individual." - enum: - - American Indian or Alaska Native - - Asian - - Black or African American - - Hispanic or Latino - - Native Hawaiian or Other Pacific Islander - - White - gender: - type: "string" - description: The gender of the individual. - enum: - - Male - - Female - - Other - ReviewBoard: - type: "object" - properties: - uid: - type: "string" - description: "Unique identifier for the review board." - name: - type: "string" - description: "The name of the review board." - city: - type: "string" - description: "The city the review board is located in." - state: - type: "string" - description: "The state the review board is located in." - url: - type: string - description: The website URL for the review board. - Attachemnts: - type: "object" - properties: - type: - type: "string" - description: "The type of attachment." - url: - type: "string" - description: "The url of the attachment." - description: - type: "string" - description: "A description of the attachment." - SourceDetails: - oneOf: - - $ref: '#/components/schemas/LegalCaseEvent' - - $ref: '#/components/schemas/PersonalAccount' - - $ref: '#/components/schemas/NewsReport' - - $ref: '#/components/schemas/GovernmentRecord' - discriminator: - propertyName: record_type - mapping: - Legal Case Event: '#/components/schemas/LegalCaseEvent' - Personal Account: '#/components/schemas/PersonalAccount' - News Report: '#/components/schemas/NewsReport' - Government Record: '#/components/schemas/GovernmentRecord' - type: "object" - properties: - record_type: - type: "string" - description: "The type of record the complaint is associated with." - enum: - - Legal Action - - Personal Account - - News Report - - Government Record - LegalCaseEvent: - type: "object" - properties: - record_type: - type: "string" - description: "The type of record the complaint is associated with." - enum: - - Legal Case Event - court: - type: "string" - description: "The court the legal action was filed in." - judge: - type: "string" - description: "The judge who presided over the case." - docket_number: - type: "string" - description: "The docket number of the case." - event_summary: - type: "string" - description: "A summary of the event." - date_of_event: - type: "string" - format: "date-time" - description: "The date the legal action was filed." - PersonalAccount: - type: "object" - properties: - record_type: - type: "string" - description: "The type of record the complaint is associated with." - enum: - - Personal Account - GovernmentRecord: - type: "object" - properties: - record_type: - type: "string" - description: "The type of record the complaint is associated with." - enum: - - Government Record - reporting_agency: - type: "string" - description: "The agency that reported the record." - reporting_agency_url: - type: "string" - description: "The url of the agency that reported the record." - reporting_agency_email: - type: "string" - description: "The email of the agency that reported the record." - NewsReport: - type: "object" - properties: - record_type: - type: "string" - description: "The type of record the complaint is associated with." - enum: - - News Report - publication_name: - type: "string" - description: "The name of the publication." - publication_date: - type: "string" - format: "date-time" - description: "The date the publication was released." - publication_url: - type: "string" - description: "The url of the publication." - author: - type: "string" - description: "The author of the publication." - author_url: - type: "string" - description: "The url of the author." - author_email: - type: "string" - description: "The email of the author." diff --git a/oas/2.0/litigation.yaml b/oas/2.0/litigation.yaml deleted file mode 100644 index 72e14576c..000000000 --- a/oas/2.0/litigation.yaml +++ /dev/null @@ -1,507 +0,0 @@ -openapi: "3.0.3" -info: - title: "Litigation" - description: "API Description" - version: "0.7.0" -servers: - - url: "http://127.0.0.1:5001/api/v1" - description: "Development environment" - - url: "https://dev.nationalpolicedata.org/api/v1" - description: "Staging environment" - - url: "https://api.nationalpolicedata.org" - description: "Production environment" -x-readme: - explorer-enabled: true - proxy-enabled: true - samples-enabled: true -security: - - bearerAuth: [] -tags: - - name: "Litigation" - description: "Litigation API" - - name: "Documents" - description: "Document API" -paths: - /litigation: - get: - tags: - - "Litigation" - summary: "Get all Litigation" - operationId: "getLitigation" - description: > - Get a list of all litigation cases. You can use query parameters to filter the results by - including by forum, the officers involved, or the date range. - This endpoint supports - pagination to limit the number of results returned. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - - name: "court_level" - in: "query" - description: "Filter by court level" - schema: - type: "string" - - name: "jurisdiction" - in: "query" - description: "Filter by jurisdiction" - schema: - type: "string" - - name: "state" - in: "query" - description: "Filter by state" - schema: - type: "string" - - name: defendants - in: "query" - description: > - Filter by defendants. Include a comma seperated list - of the IDs of the officers whos cases you want returned. - schema: - type: array - items: - type: string - responses: - "200": - description: "Successful response" - content: - application/json: - schema: - $ref: "#/components/schemas/LitigationList" - "401": - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - post: - tags: - - "Litigation" - summary: "Create new Litigation" - operationId: "createLitigation" - description: > - Create a new litigation case. This endpoint requires a - case title and docket number to be provided. User must - be a contributor to create a litigation record. - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/CreateLitigation" - responses: - '201': - description: 'Successful response' - content: - application/json: - schema: - $ref: '#/components/schemas/Litigation' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /litigation/latest: - get: - tags: - - "Litigation" - summary: "Latest Litigation Updates" - operationId: "getLatestLitigation" - description: > - Get a list of the most recently updated or added litigation cases. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - responses: - "200": - description: "Successful response" - content: - application/json: - schema: - $ref: "#/components/schemas/LitigationList" - "401": - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /litigation/{uid}: - parameters: - - name: uid - in: path - description: ID of the litigation - required: true - schema: - type: string - get: - tags: - - "Litigation" - summary: "Get Litigation by ID" - operationId: "getLitigationById" - description: > - Retrieve a single litigation case by ID. - responses: - "200": - description: "Successful response" - content: - application/json: - schema: - $ref: "#/components/schemas/Litigation" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - patch: - tags: - - "Litigation" - summary: "Update Litigation" - operationId: "UpdateLitigation" - description: > - Update an existing litigation case. The user must be a - contributor to update a litigation record. - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateLitigation" - responses: - "200": - description: "Successful response" - content: - application/json: - schema: - $ref: "#/components/schemas/Litigation" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - delete: - tags: - - "Litigation" - summary: "Delete Litigation by ID" - operationId: "deleteLitigationById" - description: > - Delete a single litigation case by ID. The user must be a - contributor from the same organization that initially submitted - a litigation record to delete it. - responses: - "204": - description: "No content" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /litigation/{uid}/documents: - parameters: - - name: "uid" - in: "path" - description: "ID of the litigation" - required: true - schema: - type: string - get: - tags: - - "Documents" - summary: "Get Documents" - operationId: "getLitigationDocuments" - description: > - Get a list of documents associated with a litigation. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - responses: - "200": - description: "Successful response" - content: - application/json: - schema: - $ref: "#/components/schemas/DocumentList" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - post: - tags: - - "Documents" - summary: "Add Document" - operationId: "createLitigationDocument" - description: > - Add a new document to a litigation. - parameters: - - name: "uid" - in: "path" - description: "ID of the litigation" - required: true - schema: - type: "integer" - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/CreateDocument" - responses: - '201': - description: 'Successful response' - content: - application/json: - schema: - $ref: '#/components/schemas/Document' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /litigation/{uid}/documents/{document_uid}: - parameters: - - name: "uid" - in: "path" - description: "ID of the Litigation" - required: true - schema: - type: string - - name: "document_uid" - in: "path" - description: "ID of the document" - required: true - schema: - type: string - get: - summary: "Get Document by ID" - operationId: "getDocumentById" - description: > - Retrieve a single document associated with a litigation. - tags: - - "Documents" - responses: - '200': - description: 'Successful response' - content: - application/json: - schema: - $ref: '#/components/schemas/Document' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /litigation/{uid}/disposition: - parameters: - - name: uid - in: path - description: ID of the litigation - required: true - schema: - type: string - post: - tags: - - "Litigation" - summary: "Add Disposition" - operationId: "createDisposition" - description: > - Add a new disposition to a litigation. - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/Disposition" - responses: - '200': - description: 'Successful response' - content: - application/json: - schema: - $ref: '#/components/schemas/Litigation' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - schemas: - Disposition: - type: "object" - properties: - disposition: - type: "string" - description: > - The disposition of the litigation. - desceripton: - type: "string" - description: > - A description of the disposition. This could include - the terms of a settlement, the amount of a judgment, - or other relevant information. - date: - type: "string" - format: "date" - description: > - The date when this disposition was reached. - required: - - disposition - - date - BaseLitigation: - type: "object" - properties: - case_title: - type: "string" - description: > - The case title or caption for this litigation. Should - contain the names of the parties involved. - docket_number: - type: "string" - description: > - The docket number for this litigation. This is the - unique identifier for the case in the court system. - court_level: - type: "string" - description: > - The level of the court where this litigation is being - heard. This could be a state court, federal court, or - other court system. - jurisdiction: - type: "string" - description: > - The geographical or subject matter jurisdiction (e.g., - Eastern District, Northern District, County name for - state courts) of the court where litigation is being - heard. - state: - type: "string" - description: > - The state where this litigation is being heard. This - should be the two-letter abbreviation for the state. - description: - type: "string" - description: > - A description of the litigation. This could include - a summary of the case, the legal issues involved, or - other relevant information. - start_date: - type: "string" - format: "date" - description: > - The date when this litigation was filed or initiated. - dispositions: - type: "array" - description: > - A list of any dispositions in this litigation. This - could include a settlement, judgment, or other outcome. - items: - $ref: "#/components/schemas/Disposition" - settlement_amount: - type: "number" - description: > - The amount of any settlement or judgment in this - litigation. This should be in USD. - url: - type: "string" - format: "uri" - description: > - A URL to more information about this litigation. This - could be a link to a court website such as - [Court Listener](https://www.courtlistener.com/), - [PACER](https://www.pacer.gov/), or other legal research - resources. - CreateLitigation: - allOf: - - $ref: "#/components/schemas/BaseLitigation" - - type: object - - properties: - defendants: - type: "array" - items: - type: "string" - description: > - A list containing the IDs of any officers who are named - as defendants in the litigation. - - required: - - case_title - - docket_number - - defendants - - court_level - - jurisdiction - - state - UpdateLitigation: - allOf: - - $ref: "#/components/schemas/BaseLitigation" - - type: object - properties: - defendants: - type: array - items: - type: string - description: > - A list containing the IDs of any officers who are named - as defendants in the litigation. - Litigation: - allOf: - - $ref: "#/components/schemas/BaseLitigation" - - type: object - required: - - case_title - - docket_number - - defendants - - court_level - - jurisdiction - - state - properties: - uid: - type: "string" - description: "The uid of the litigation" - documents: - type: "string" - description: "A link to retrieve the documents associated with this litigation" - defendants: - type: "array" - description: > - A list of any officers who are named as defendants in the litigation. - items: - $ref: officers.yaml#/components/schemas/Officer - LitigationList: - allOf: - - $ref: ../common/pagination.yaml#/components/schemas/PaginatedResponse - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/Litigation" - BaseDocument: - type: "object" - properties: - title: - type: "string" - description: "The title of the document" - description: - type: "string" - description: "A description of the document" - url: - type: "string" - format: "uri" - description: "A URL to the document" - CreateDocument: - allOf: - - $ref: "#/components/schemas/BaseDocument" - - type: "object" - - required: - - title - - url - Document: - allOf: - - $ref: "#/components/schemas/BaseDocument" - - type: "object" - - required: - - title - - url - - uid - - properties: - uid: - type: "string" - description: "The uid of the document" - DocumentList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/Document" - \ No newline at end of file diff --git a/oas/2.0/officers.yaml b/oas/2.0/officers.yaml deleted file mode 100644 index 0aeeaec18..000000000 --- a/oas/2.0/officers.yaml +++ /dev/null @@ -1,661 +0,0 @@ -openapi: "3.0.3" -info: - title: "Officers" - description: "API Description" - version: "0.7.0" -servers: - - url: "http://127.0.0.1:5001/api/v1" - description: "Development environment" - - url: "https://dev.nationalpolicedata.org/api/v1" - description: "Staging environment" - - url: "https://api.nationalpolicedata.org" - description: "Production environment" -x-readme: - explorer-enabled: true - proxy-enabled: true - samples-enabled: true -security: - - bearerAuth: [] -tags: - - name: "Officers" - description: "Officer related endpoints" - - name: "Employment History" - description: "Employment related endpoints" -paths: - /officers: - get: - tags: - - "Officers" - summary: "Get officers" - operationId: "getOfficers" - description: > - Returns a list of officer. A number of simple filters can be applied to limit the results. If no filters - are applied, a random sample of officers will be returned. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - - $ref: '#/components/parameters/active_after' - - $ref: '#/components/parameters/active_before' - - $ref: '#/components/parameters/agency' - - $ref: '#/components/parameters/rank' - - $ref: '#/components/parameters/unit' - - $ref: '#/components/parameters/name' - - $ref: '#/components/parameters/ethnicity' - - $ref: '#/components/parameters/badge_number' - responses: - "200": - description: "Successful operation" - content: - application/json: - schema: - $ref: "#/components/schemas/OfficerList" - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - post: - tags: - - Officers - summary: "Create a new officer" - operationId: "createOfficer" - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/CreateOfficer" - responses: - '201': - description: 'Successful operation' - content: - application/json: - schema: - $ref: '#/components/schemas/Officer' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /officers/latest: - get: - tags: - - "Officers" - summary: "Latest Officer Updates" - description: > - Get the most recently updated or added officers. - operationId: "getLatestOfficers" - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - responses: - "200": - description: "Successful operation" - content: - application/json: - schema: - $ref: "#/components/schemas/OfficerList" - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /officers/filter: - post: - tags: - - "Officers" - summary: "Advanced Officer Filter" - operationId: "getOfficersByFilter" - description: > - Get officers by advanced filter. This endpoint allows for more complex queries - using a JSON body to specify the filters. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - - $ref: '#/components/parameters/active_after' - - $ref: '#/components/parameters/active_before' - - $ref: '#/components/parameters/agency' - - $ref: '#/components/parameters/rank' - - $ref: '#/components/parameters/unit' - - $ref: '#/components/parameters/name' - - $ref: '#/components/parameters/ethnicity' - - $ref: '#/components/parameters/badge_number' - requestBody: - description: > - A JSON object containing the filters to apply to the search. - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/OfficerFilter" - responses: - "200": - description: "Successful operation" - content: - application/json: - schema: - $ref: "#/components/schemas/OfficerList" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /officers/{uid}: - parameters: - - name: uid - in: path - description: UID of the officer - required: true - schema: - type: string - get: - tags: - - "Officers" - summary: "Get officer by uid" - operationId: "getOfficerById" - responses: - "200": - description: "Successful operation" - content: - application/json: - schema: - $ref: "#/components/schemas/Officer" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - patch: - tags: - - "Officers" - summary: "Update an existing officer" - operationId: "updateOfficer" - requestBody: - description: "Officer object that needs to be updated" - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/Officer" - responses: - "200": - description: "Successful operation" - content: - application/json: - schema: - $ref: "#/components/schemas/Officer" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - delete: - tags: - - "Officers" - summary: "Delete an officer" - operationId: "deleteOfficer" - description: "Delete an officer by uid" - parameters: - - name: "uid" - in: "path" - description: "UID of officer to delete" - required: true - schema: - type: "integer" - format: "int64" - responses: - "204": - description: "No content" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /officers/{uid}/employment: - parameters: - - name: uid - in: path - description: UID of the officer - required: true - schema: - type: string - get: - summary: "Get Employment History" - operationId: "getEmploymentHistory" - description: > - Get employment history for an officer. This includes all the agencies - the officer has worked for. - tags: - - "Employment History" - responses: - '200': - description: 'Successful operation' - content: - application/json: - schema: - $ref: '#/components/schemas/EmploymentList' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - put: - summary: "Update Employment History" - operationId: "updateEmploymentHistory" - description: > - Update the employment history for an officer. This includes all the agencies - the officer has worked for. - tags: - - "Employment History" - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/AddEmploymentList' - responses: - '200': - description: 'Successful operation' - content: - application/json: - schema: - $ref: '#/components/schemas/EmploymentList' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' -components: - parameters: - active_after: - name: active_after - in: query - description: > - Filter officers who were active after this date. The date should be in the format YYYY-MM-DD. - required: false - schema: - type: string - format: date - active_before: - name: active_before - in: query - description: > - Filter officers who were active before this date. The date should be in the format YYYY-MM-DD. - required: false - schema: - type: string - format: date - agency: - name: agency - in: query - description: > - Filter officers by the agency they are employed by. The value should be a comma-separated list of agency uids. - required: false - schema: - type: string - rank: - name: rank - in: query - description: > - Filter officers by their rank. The value should be a comma-separated list of ranks. - required: false - schema: - type: string - unit: - name: unit - in: query - description: > - Filter officers by their unit. The value should be a comma-separated list of unit uids. - required: false - schema: - type: string - name: - name: name - in: query - description: > - Filter officers by their name. The value should be a string in the format "first middle last suffix". - required: false - schema: - type: string - ethnicity: - name: ethnicity - in: query - description: > - Filter officers by their ethnicity. The value should be a comma-separated list of ethnicities. - required: false - schema: - type: string - badge_number: - name: badge_number - in: query - description: > - Filter officers by their badge number. The value should be a comma-separated list of badge numbers. - required: false - schema: - type: string - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - schemas: - NameFilter: - type: object - description: > - An advanced filter that can be applied to a officer list request. - properties: - first: - type: string - description: > - Filter officers by their first name. The value should be a string. - middle: - type: string - description: > - Filter officers by their middle name. The value should be a string. - last: - type: string - description: > - Filter officers by their last name. The value should be a string. - suffix: - type: string - description: > - Filter officers by their suffix. The value should be a string. - LocationFilter: - type: object - description: > - An advanced filter that can be applied to a officer list request. - properties: - state: - type: string - description: > - Filter locations by state. The value should be a string. - county: - type: string - description: > - Filter locations by county. The value should be a string. - city: - type: string - description: > - Filter locations by city. The value should be a string. - zip: - type: string - description: > - Filter locations by zip code. The value should be a string. - AllegationFilter: - type: object - description: > - An advanced filter that can be applied to an officer list request. - properties: - uid: - type: array - description: > - Return officers who have any of the selected allegations. - items: - type: string - status: - type: array - description: > - Return officers who have allegations with the selected statuses. - items: - type: string - category: - type: array - description: > - Return officers who have allegations with the selected categories. - items: - type: string - subcategory: - type: array - description: > - Return officers who have allegations with the selected subcategory. - items: - type: string - sustained: - type: boolean - description: > - Return officers who have allegations that are either sustained not sustained. The value must be a boolean. - count__gte: - type: integer - description: > - Return officers who have at least the selected number of allegations. The value must be an integer. - count__lte: - type: integer - description: > - Return officers who have at most the selected number of allegations. The value must be an integer. - StateIdFilter: - type: object - description: > - An advanced filter that can be applied to a officer list request. - properties: - state: - type: string - description: > - Filter officers by their ID state. The value should be a string. - id_name: - type: string - description: > - Filter officers by their ID name. The value should be a string. - values: - type: string - description: > - Return officers with the selected ID values. Must be sent in tandem - with the `id_name` and `state` properties. - OfficerFilter: - type: object - description: > - An advanced filter that can be applied to an officer list request. - properties: - names: - type: array - description: > - Return officers whose name matches any of these filters. - items: - $ref: "#/components/schemas/NameFilter" - location: - allOf: - - $ref: "#/components/schemas/LocationFilter" - - type: object - description: > - Filter officers by locations in which they have worked. This is assesed based on the operating theatre of the units to which they've been assigned. - state_ids_sets: - type: array - description: > - Filter officers by their state IDs. This can be used to filter by tax number, - officer training number, or any other unique identifier used by a state. - items: - $ref: "#/components/schemas/StateIdFilter" - ranks: - type: array - description: > - Return officers who have obtained the selected ranks. - items: - type: string - ethnicities: - type: array - description: > - Return officers who have the selected ethnicities. - items: - type: string - enum: - - American Indian or Alaska Native - - Asian - - Black or African American - - Hispanic or Latino - - Native Hawaiian or Other Pacific Islander - - White - commanders: - type: array - description: > - Return officers who have worked under the selected commanders. - items: - type: string - description: The UIDs of the commanders to filter by. - allegations: - allOf: - - $ref: "#/components/schemas/AllegationFilter" - - type: object - description: > - Filter officers by allegations made against them. - BaseEmployment: - type: "object" - properties: - officer_uid: - type: "string" - description: "The UID of the officer." - agency_uid: - type: "string" - description: "The UID of the agency the officer is employed by." - unit_uid: - type: "string" - description: "The UID of the unit the officer is assigned to." - earliest_employment: - type: "string" - format: "date" - description: "The earliest known date of employment" - latest_employment: - type: "string" - format: "date" - description: "The latest known date of employment" - badge_number: - type: "string" - description: "The badge number of the officer" - highest_rank: - type: "string" - description: "The highest rank the officer has held during this employment." - commander: - type: boolean - description: Indicates that the officer commanded the unit during this employment. - AddEmployment: - allOf: - - $ref: "#/components/schemas/BaseEmployment" - - type: "object" - - required: - - unit_uid - - badge_number - AddEmploymentFailed: - type: object - properties: - agency_uid: - type: "string" - description: "The uid of the agency that could not be added." - reason: - type: "string" - description: "The reason the employment record could not be added" - AddEmploymentList: - type: object - properties: - agencies: - type: "array" - description: "The units to add to the officer's employment history." - items: - $ref: "#/components/schemas/AddEmployment" - Employment: - allOf: - - $ref: "#/components/schemas/BaseEmployment" - AddEmploymentResponse: - type: object - required: - - created - - failed - - total_created - - total_failed - properties: - created: - type: array - items: - $ref: "#/components/schemas/Employment" - failed: - type: array - items: - $ref: "#/components/schemas/AddEmploymentFailed" - total_created: - type: integer - minimum: 0 - total_failed: - type: integer - minimum: 0 - EmploymentList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/Employment" - BaseOfficer: - type: "object" - properties: - first_name: - type: "string" - description: "First name of the officer" - middle_name: - type: "string" - description: "Middle name of the officer" - last_name: - type: "string" - description: "Last name of the officer" - suffix: - type: "string" - description: "Suffix of the officer's name" - ethnicity: - type: "string" - description: "The ethnicity of the officer" - enum: - - American Indian or Alaska Native - - Asian - - Black or African American - - Hispanic or Latino - - Native Hawaiian or Other Pacific Islander - - White - gender: - type: "string" - description: "The gender of the officer" - enum: - - Male - - Female - - Other - date_of_birth: - type: "string" - format: "date" - description: "The date of birth of the officer" - state_ids: - type: "array" - description: "The state ids of the officer" - items: - $ref: "#/components/schemas/StateId" - CreateOfficer: - allOf: - - $ref: "#/components/schemas/BaseOfficer" - - type: "object" - - required: - - first_name - - last_name - UpdateOfficer: - allOf: - - $ref: "#/components/schemas/BaseOfficer" - - type: "object" - Officer: - allOf: - - $ref: "#/components/schemas/BaseOfficer" - - type: "object" - - properties: - uid: - type: "string" - description: "The uid of the officer" - employment_history: - type: "string" - description: "A link to retrieve the employment history of the officer" - allegations: - type: "string" - description: "A link to retrieve the allegations against the officer" - litigation: - type: "string" - description: "A link to retrieve the litigation against the officer" - OfficerList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/Officer" - StateId: - type: "object" - properties: - uid: - type: "string" - description: "The UUID of this state id" - state: - type: "string" - description: "The state of the state id" - id_name: - type: "string" - description: "The name of the id. For example, Tax ID, Driver's License, etc." - value: - type: "string" - description: "The value of the id." diff --git a/oas/2.0/search.yaml b/oas/2.0/search.yaml deleted file mode 100644 index efd922a5b..000000000 --- a/oas/2.0/search.yaml +++ /dev/null @@ -1,181 +0,0 @@ -openapi: "3.0.3" -info: - title: "Search" - description: "API Description" - version: "0.7.0" -servers: - - url: "http://127.0.0.1:5001/api/v1" - description: "Local environment" - - url: "https://dev.nationalpolicedata.org/api/v1" - description: "Staging environment" - - url: "https://api.nationalpolicedata.org" - description: "Production environment" -x-readme: - explorer-enabled: true - proxy-enabled: true - samples-enabled: true -security: - - bearerAuth: [] -tags: - - name: "Search" - description: "Search API" -paths: - /search: - post: - tags: - - "Search" - summary: "Search All" - operationId: "searchAll" - description: > - Search the index for items that match the query. The search results can be filtered - by content type, location, data source, and date range. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - requestBody: - description: > - The search terms and the filters that should be applied to the search. - required: false - content: - application/json: - schema: - $ref: "#/components/schemas/SearchRequest" - responses: - "200": - description: "Search results." - content: - application/json: - schema: - $ref: "#/components/schemas/SearchResultList" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - /search/auto: - post: - tags: - - "Search" - summary: "Autocomplete Search Term" - operationId: "autocomplete" - description: > - Returns a list of suggestions based on the search term. - parameters: - - $ref: '../common/pagination.yaml#/components/parameters/page' - - $ref: '../common/pagination.yaml#/components/parameters/per_page' - requestBody: - description: > - The search term to get suggestions and any filters that should be applied to the search. - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/SearchRequest" - responses: - "200": - description: "A list of suggested search terms." - content: - application/json: - schema: - $ref: "#/components/schemas/SearchTerms" - '400': - $ref: '../common/error.yaml#/components/responses/validationError' -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - schemas: - SearchRequest: - type: "object" - properties: - query: - type: "string" - description: "The search terms." - filters: - type: "object" - properties: - content_type: - type: "string" - description: "The type of content to search." - enum: - - "complaint" - - "officer" - - "agency" - - "unit" - - "litigation" - location: - $ref: "#/components/schemas/Location" - data_source: - type: "string" - description: "The data source to search." - date_earliest: - type: "string" - description: "Lower bound of the date range." - date_latest: - type: "string" - description: "Upper bound of the date range." - SearchResultList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/SearchResult" - SearchResult: - type: "object" - properties: - uid: - type: "string" - description: The unique identifier for the search result. - title: - type: "string" - description: The title of the search result. - subtitle: - type: "string" - description: The subtitle of the search result. - details: - type: "string" - description: The details of the search result. - content_type: - type: "string" - description: The type of content. - source: - $ref: "#/components/schemas/SourceRef" - last_updated: - type: "string" - description: The date the content was last updated. - href: - type: "string" - description: The URL of the search result. - Location: - type: "object" - properties: - name: - type: "string" - description: The name of the location. - type: - type: "string" - description: The type of location. - enum: - - "city" - - "county" - - "state" - SourceRef: - type: "object" - properties: - name: - type: "string" - description: The name of the data source. - href: - type: "string" - description: The URL of the data source. - SearchTerms: - type: "object" - properties: - terms: - type: "array" - items: - type: "string" \ No newline at end of file diff --git a/oas/2.0/sources.yaml b/oas/2.0/sources.yaml deleted file mode 100644 index 5ec92eb3b..000000000 --- a/oas/2.0/sources.yaml +++ /dev/null @@ -1,259 +0,0 @@ -openapi: "3.0.3" -info: - title: "Sources" - description: "API Description" - version: "0.7.0" -servers: - - url: "http://127.0.0.1:5001/api/v1" - description: "Development environment" - - url: "https://dev.nationalpolicedata.org/api/v1" - description: "Staging environment" - - url: "https://api.nationalpolicedata.org" - description: "Production environment" -x-readme: - explorer-enabled: true - proxy-enabled: true - samples-enabled: true -security: - - bearerAuth: [] -tags: - - name: "Sources" - description: "Sources API" -paths: - /sources: - get: - tags: - - "Sources" - summary: "Get all sources" - operationId: "getSources" - responses: - "200": - description: "Successful operation" - content: - application/json: - schema: - type: "array" - items: - $ref: "#/components/schemas/SourceList" - post: - tags: - - "Sources" - summary: "Create a new source" - operationId: "createSource" - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/CreateSource" - responses: - '201': - description: 'Successful operation' - content: - application/json: - schema: - $ref: '#/components/schemas/Source' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - /sources/{uid}: - parameters: - - name: uid - in: path - description: UID of the source - required: true - schema: - type: string - get: - tags: - - "Sources" - summary: "Get Source" - operationId: "getSourceById" - description: > - Returns a single source. - responses: - '200': - description: "Successful operation" - content: - application/json: - schema: - $ref: "#/components/schemas/Source" - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - patch: - tags: - - "Sources" - summary: "Update an existing source" - operationId: "updateSource" - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateSource" - responses: - '200': - description: 'Successful operation' - content: - application/json: - schema: - $ref: '#/components/schemas/Source' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - /sources/{uid}/members: - parameters: - - name: uid - in: path - description: UID of the source - required: true - schema: - type: string - get: - tags: - - Sources - summary: "Get all members" - operationId: "getMembers" - description: > - Returns a list of all users who are members of a source. - responses: - '200': - description: 'Successful operation' - content: - application/json: - schema: - type: "array" - items: - $ref: '#/components/schemas/MemberList' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' - -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - schemas: - BaseSource: - type: "object" - properties: - name: - type: "string" - description: "Name of the source organization." - bio: - type: "string" - description: "Description of the source organization." - website_url: - type: "string" - description: "Website URL of the source." - contact_email: - type: "string" - description: "Contact email for the source organization." - contact_phone: - type: "string" - description: "Contact phone number for the source organization." - social_media: - type: "object" - description: The user's social media profiles. - properties: - twitter_url: - type: "string" - description: The user's Twitter handle. - facebook_url: - type: "string" - description: The user's Facebook profile. - linkedin_url: - type: "string" - description: The user's LinkedIn profile. - instagram_url: - type: "string" - description: The user's Instagram profile. - youtube_url: - type: "string" - description: The user's YouTube channel. - tiktok_url: - type: "string" - description: The user's TikTok profile. - - CreateSource: - allOf: - - $ref: "#/components/schemas/BaseSource" - - type: "object" - required: - - name - - contact_email - UpdateSource: - allOf: - - $ref: "#/components/schemas/BaseSource" - Source: - allOf: - - $ref: "#/components/schemas/BaseSource" - - type: "object" - properties: - uid: - type: "string" - description: "Unique identifier for the source." - members: - type: string - description: "Url to get all members of the source." - reported_complaints: - type: string - description: "Url to get all complaints reported by the source." - SourceList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/Source" - MemberBase: - type: "object" - properties: - source_uid: - type: "string" - description: "Unique identifier for the source." - user_uid: - type: "string" - description: "Unique identifier for the user." - role: - type: "string" - description: "Role of the user." - enum: [ - "Administrator", - "Publisher", - "Member", - "Subscriber" - ] - is_active: - type: "boolean" - description: "Whether the user is active." - Member: - allOf: - - $ref: "#/components/schemas/MemberBase" - - type: "object" - properties: - uid: - type: "string" - description: "Unique identifier for the user." - date_joined: - type: "string" - format: "date-time" - description: "Date the user joined the source organizaation." - AddMember: - allOf: - - $ref: "#/components/schemas/MemberBase" - - type: "object" - required: - - role - - user_uid - - source_uid - MemberList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/Member" diff --git a/oas/2.0/users.yaml b/oas/2.0/users.yaml deleted file mode 100644 index 295359445..000000000 --- a/oas/2.0/users.yaml +++ /dev/null @@ -1,189 +0,0 @@ -openapi: "3.0.3" -info: - title: "Users" - description: "User Management API" - version: "0.7.0" -servers: - - url: "http://127.0.0.1:5001/api/v1" - description: "Development environment" - - url: "https://dev.nationalpolicedata.org/api/v1" - description: "Staging environment" - - url: "https://api.nationalpolicedata.org" - description: "Production environment" -x-readme: - explorer-enabled: true - proxy-enabled: true - samples-enabled: true -security: - - bearerAuth: [] -tags: - - name: "Users" - description: "Users API" -paths: - /users/self: - get: - tags: - - "Users" - summary: "Get current user" - operationId: "getCurrentUser" - responses: - "200": - description: "Successful operation" - content: - application/json: - schema: - type: "array" - items: - $ref: "#/components/schemas/User" - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - patch: - tags: - - "Users" - summary: "Update the current user" - operationId: "updateCurrentUser" - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateUser" - responses: - '200': - description: 'Successful operation' - content: - application/json: - schema: - $ref: '#/components/schemas/User' - '400': - $ref: '../common/error.yaml#/components/responses/validationError' - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - /users/{uid}: - parameters: - - name: uid - in: path - description: UID of the user - required: true - schema: - type: string - get: - tags: - - "Users" - summary: "Get User" - operationId: "getUserById" - description: > - Returns a single user. - responses: - '200': - description: "Successful operation" - content: - application/json: - schema: - $ref: "#/components/schemas/User" - '401': - $ref: '../common/error.yaml#/components/responses/unauthorizedError' - '404': - $ref: '../common/error.yaml#/components/responses/notFoundError' -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - schemas: - BaseUser: - type: "object" - properties: - first_name: - type: "string" - description: The first name of the user. - last_name: - type: "string" - description: The last name of the user. - primary_email: - type: "string" - description: The primary email address of the user. This is the email address used for login. - contact_info: - type: "object" - description: Contact information for the user. - properties: - additional_emails: - type: "array" - items: - type: "string" - description: Additional email addresses for the user. - phone_numbers: - type: "array" - items: - type: "string" - description: Phone numbers for the user. - website: - type: "string" - description: The user's website. - location: - type: "object" - properties: - city: - type: "string" - description: The city where the user is located. - state: - type: "string" - description: The state where the user is located. This should be the two-letter abbreviation. - employment: - type: "object" - description: Employment information for the user. - properties: - employer: - type: "string" - description: The user's employer. - title: - type: "string" - description: The user's job title. - bio: - type: "string" - description: A short biography of the user. - profile_image: - type: "string" - description: URL to the user's profile image. - social_media: - type: "object" - description: The user's social media profiles. - properties: - twitter_url: - type: "string" - description: The user's Twitter handle. - facebook_url: - type: "string" - description: The user's Facebook profile. - linkedin_url: - type: "string" - description: The user's LinkedIn profile. - instagram_url: - type: "string" - description: The user's Instagram profile. - youtube_url: - type: "string" - description: The user's YouTube channel. - tiktok_url: - type: "string" - description: The user's TikTok profile. - UpdateUser: - allOf: - - $ref: "#/components/schemas/BaseUser" - User: - allOf: - - $ref: "#/components/schemas/BaseUser" - - type: "object" - properties: - uid: - type: "string" - description: "Unique identifier for the user." - UserList: - allOf: - - $ref: '../common/pagination.yaml#/components/schemas/PaginatedResponse' - - type: "object" - properties: - results: - type: "array" - items: - $ref: "#/components/schemas/User" \ No newline at end of file diff --git a/oas/README.md b/oas/README.md deleted file mode 100644 index da074a244..000000000 --- a/oas/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# NPDI OAS Schemas - -## How to Use OAS to Pydantic - -The OAS specifications can be used to generate the Pydantic models that validate updates to the database. - -### Runing the Script - - - Basic usage: - ```bash - python generate_pydantic_models.py path_to_your_oas.yaml generated_models.py - ``` - - With verbose output: - ```bash - python generate_pydantic_models.py path_to_your_oas.yaml generated_models.py --verbose - ``` - -### Example Usage - -```bash -python generate_pydantic_models.py 2.0/agencies.yaml pydantic/agencies.py --verbose -``` - -**Output:** - -``` -Loaded OpenAPI Specification from '2.0/agencies.yaml'. -Generating model code for BaseAgency -Generating model code for CreateAgency -Generating model code for UpdateAgency -Generating model code for AgencyList -Generating model code for Agency -Generating model code for CreateUnit -Generating model code for UpdateUnit -Generating model code for BaseUnit -Generating model code for Unit -Generating model code for UnitList -Generating model code for AddOfficer -Generating model code for AddOfficerList -Generating model code for AddOfficerFailed -Generating model code for AddOfficerResponse -Pydantic models have been successfully generated and saved to 'pydantic/agencies.py'. -``` - -## Caveats - -### Polymorphism -The converter doesn't handle polymorphic propeties yet. There's been a bit of effort put -into making sure it can follow 'allOf' refrences, but I haven't done any investigation -into how it handles 'oneOf' refs. For example, `SourceDetails` on complaints. - -### External File Refrences -The generator only looks at one file at a time. It will not follow refernces to other -files. The generator currently just assumes that those references exist and are valid. diff --git a/oas/common/auth.yaml b/oas/common/auth.yaml deleted file mode 100644 index 1485f06ce..000000000 --- a/oas/common/auth.yaml +++ /dev/null @@ -1,6 +0,0 @@ -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT \ No newline at end of file diff --git a/oas/common/error.yaml b/oas/common/error.yaml deleted file mode 100644 index fac33f59c..000000000 --- a/oas/common/error.yaml +++ /dev/null @@ -1,35 +0,0 @@ -components: - schemas: - ErrorResponse: - type: "object" - properties: - message: - type: "string" - description: "A message describing the error." - required: - - message - responses: - conflictError: - description: "Conflict" - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - validationError: - description: "Validation error" - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - notFoundError: - description: "Resource not found" - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - unauthorizedError: - description: "Unauthorized" - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" \ No newline at end of file diff --git a/oas/common/pagination.yaml b/oas/common/pagination.yaml deleted file mode 100644 index 7a42232ea..000000000 --- a/oas/common/pagination.yaml +++ /dev/null @@ -1,38 +0,0 @@ -components: - parameters: - page: - name: page - in: query - description: Page number - required: false - schema: - type: integer - minimum: 1 - default: 1 - per_page: - name: per_page - in: query - description: Number of items per page - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - schemas: - PaginatedResponse: - type: object - properties: - results: - type: array - items: {} - page: - type: integer - minimum: 1 - total_pages: - type: integer - minimum: 1 - maximum: 100 - total_results: - type: integer - minimum: 0 diff --git a/oas/gen_pydantic.sh b/oas/gen_pydantic.sh deleted file mode 100755 index c90d86928..000000000 --- a/oas/gen_pydantic.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -python oas_to_pydantic.py 2.0/sources.yaml pydantic/sources.py -python oas_to_pydantic.py 2.0/complaints.yaml pydantic/complaints.py -python oas_to_pydantic.py 2.0/officers.yaml pydantic/officers.py -python oas_to_pydantic.py 2.0/agencies.yaml pydantic/agencies.py -python oas_to_pydantic.py 2.0/litigation.yaml pydantic/litigation.py \ No newline at end of file diff --git a/oas/oas_to_pydantic.py b/oas/oas_to_pydantic.py deleted file mode 100644 index cc313ce0d..000000000 --- a/oas/oas_to_pydantic.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import yaml -import os -import sys - - -class OASModelGenerator: - def __init__(self, oas, verbose=False): - self.oas = oas - self.verbose = verbose - - def parse_property(self, prop_name, prop_details): - """Parse a single property from the schema to - generate a Pydantic field.""" - pydantic_type_map = { - "string": "str", - "number": "float", - "integer": "int", - "boolean": "bool", - "array": "List", - "object": "Dict" - } - - if 'type' in prop_details: - prop_type = pydantic_type_map.get(prop_details['type'], "Any") - if prop_details['type'] == "array": - items_type, _ = self.parse_property(None, prop_details['items']) - return f"List[{items_type}]", prop_details.get('description') - elif prop_details['type'] == "object": - if 'properties' in prop_details: - # For nested objects, we'll use - # Dict[str, Any] for simplicity. - return "Dict[str, Any]", prop_details.get('description') - else: - return "Dict[str, Any]", prop_details.get('description') - else: - return prop_type, prop_details.get('description') - elif '$ref' in prop_details: - # Handle references - ref = prop_details['$ref'].split('/')[-1] - return ref, prop_details.get('description') - elif 'oneOf' in prop_details: - # Handle oneOf by creating a Union type - union_types = [ - ref.split('/')[-1] if '$ref' in ref else "Any" - for ref in prop_details['oneOf'] - ] - union_str = "Union[" + ", ".join(union_types) + "]" - return union_str, prop_details.get('description') - elif 'allOf' in prop_details: - # Handle allOf by combining referenced schemas - combined_type = None - description = prop_details.get('description') - - # Process each part of allOf - for item in prop_details['allOf']: - if '$ref' in item: - ref = item['$ref'].split('/')[-1] - combined_type = ref - elif 'type' in item and not combined_type: - prop_type = pydantic_type_map.get(item['type'], "Any") - combined_type = prop_type - - if 'description' in item: - description = item['description'] - return combined_type, description - else: - return "Any", prop_details.get('description') - - def process_all_of(self, schema_details): - """Process 'allOf' by merging properties and handling inheritance. - """ - combined_properties = {} - required_props = set() - parent_classes = [] - - for item in schema_details['allOf']: - if '$ref' in item: - # Handle refrence in 'allOf' - ref = item['$ref'].split('/')[-1] - ref_schema = self.oas.get( - 'components', {}).get('schemas', {}).get(ref, {}) - if ref_schema: - # Parent class found - # Merge properties from the refernced schema - ref_properties = ref_schema.get('properties', {}) - combined_properties.update(ref_properties) - - # Merge required properties - required_props.update(ref_schema.get('required', [])) - parent_classes.append(ref) - else: - # Parent schema not found (likely in an external file) - # Keep the parent class name for inheritance but - # treat the child as defining the model - parent_classes.append(ref) - - elif 'properties' in item: - # If additional properties are defined within the 'allOf' - additional_properties = item.get('properties', {}) - combined_properties.update(additional_properties) - required_props.update(item.get('required', [])) - - return combined_properties, required_props, parent_classes - - def generate_pydantic_model(self, schema_name, schema_details, indent=4): - """Generate a Pydantic model for a given schema.""" - class_def = f"class {schema_name}(BaseModel):\n" - if self.verbose: - print(f"Generating model code for {schema_name}") - - if 'description' in schema_details: - class_def += f' """{schema_details["description"]}"""\n' - - if 'allOf' in schema_details: - # Handle allOf (merging or inheritance) - properties, required_props, parent_classes = self.process_all_of( - schema_details) - if parent_classes: - # Add parent classes to inheritance - class_def = "class {}({}, BaseModel):\n".format( - schema_name, - ', '.join(parent_classes) - ) - else: - # Handle regular properties if allOf is not present - properties = schema_details.get('properties', {}) - required_props = schema_details.get('required', []) - - if not properties: - class_def += " pass\n" - return class_def - - for prop_name, prop_details in properties.items(): - prop_type, prop_description = self.parse_property( - prop_name, prop_details) - - # Determine if the property is required - if prop_name in required_props: - default = "..." - else: - default = "None" - prop_type = f"Optional[{prop_type}]" - - field_str = f"{prop_name}: {prop_type}" - if prop_description: - field_str += " = Field({}, description=\"{}\")".format( - default, - prop_description, - ) - else: - field_str += f" = {default}" - class_def += f" {field_str}\n" - - return class_def - - def generate_models_from_oas(self): - """Generate Pydantic models from the OAS components/schemas.""" - schemas = self.oas.get('components', {}).get('schemas', {}) - - models = [] - for schema_name, schema_details in schemas.items(): - model_code = self.generate_pydantic_model( - schema_name, schema_details) - models.append(model_code) - - return models - - -def main(): - parser = argparse.ArgumentParser( - description="Generate Pydantic models from an " + - "OpenAPI Specification (OAS) YAML file." - ) - parser.add_argument( - "input_file", - type=str, - help="Path to the OpenAPI YAML file." - ) - parser.add_argument( - "output_file", - type=str, - help="Path to the output Python file where" + - "Pydantic models will be saved." - ) - parser.add_argument( - "-v", "--verbose", - action="store_true", - help="Enable verbose output." - ) - - args = parser.parse_args() - - input_path = args.input_file - output_path = args.output_file - verbose = args.verbose - - if not os.path.isfile(input_path): - print( - "Error: The input file '{}' does not exist.".format( - input_path - ), file=sys.stderr) - sys.exit(1) - - try: - with open(input_path, 'r') as f: - oas = yaml.safe_load(f) - except Exception as e: - print(f"Error reading the input file: {e}", file=sys.stderr) - sys.exit(1) - - if verbose: - print(f"Loaded OpenAPI Specification from '{input_path}'.") - - generator = OASModelGenerator(oas, verbose) - models = generator.generate_models_from_oas() - - if not models: - print("No schemas found in the OpenAPI Specification.", file=sys.stderr) - sys.exit(1) - - # Add necessary imports at the top of the output file - import_statements = [ - "from pydantic import BaseModel, Field", - "from typing import List, Optional, Dict, Any, Union", - "", - "", - ] - - try: - with open(output_path, 'w') as f: - for line in import_statements: - f.write(line + "\n") - for model in models: - f.write(model + "\n\n") - except Exception as e: - print(f"Error writing to the output file: {e}", file=sys.stderr) - sys.exit(1) - - print( - "Pydantic models have been successfully" + - " generated and saved to '{}'.".format( - output_path)) - - -if __name__ == "__main__": - main() diff --git a/oas/pydantic/agencies.py b/oas/pydantic/agencies.py deleted file mode 100644 index b13867fff..000000000 --- a/oas/pydantic/agencies.py +++ /dev/null @@ -1,141 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union - - -class BaseAgency(BaseModel): - name: Optional[str] = Field(None, description="Name of the agency") - hq_address: Optional[str] = Field(None, description="Address of the agency") - hq_city: Optional[str] = Field(None, description="City of the agency") - hq_state: Optional[str] = Field(None, description="State of the agency") - hq_zip: Optional[str] = Field(None, description="Zip code of the agency") - jurisdiction: Optional[str] = Field(None, description="Jurisdiction of the agency") - phone: Optional[str] = Field(None, description="Phone number of the agency") - email: Optional[str] = Field(None, description="Email of the agency") - website_url: Optional[str] = Field(None, description="Website of the agency") - - -class CreateAgency(BaseAgency, BaseModel): - name: Optional[str] = Field(None, description="Name of the agency") - hq_address: Optional[str] = Field(None, description="Address of the agency") - hq_city: Optional[str] = Field(None, description="City of the agency") - hq_state: Optional[str] = Field(None, description="State of the agency") - hq_zip: Optional[str] = Field(None, description="Zip code of the agency") - jurisdiction: Optional[str] = Field(None, description="Jurisdiction of the agency") - phone: Optional[str] = Field(None, description="Phone number of the agency") - email: Optional[str] = Field(None, description="Email of the agency") - website_url: Optional[str] = Field(None, description="Website of the agency") - - -class UpdateAgency(BaseAgency, BaseModel): - name: Optional[str] = Field(None, description="Name of the agency") - hq_address: Optional[str] = Field(None, description="Address of the agency") - hq_city: Optional[str] = Field(None, description="City of the agency") - hq_state: Optional[str] = Field(None, description="State of the agency") - hq_zip: Optional[str] = Field(None, description="Zip code of the agency") - jurisdiction: Optional[str] = Field(None, description="Jurisdiction of the agency") - phone: Optional[str] = Field(None, description="Phone number of the agency") - email: Optional[str] = Field(None, description="Email of the agency") - website_url: Optional[str] = Field(None, description="Website of the agency") - - -class AgencyList(PaginatedResponse, BaseModel): - results: Optional[List[Agency]] = None - - -class Agency(BaseAgency, BaseModel): - name: Optional[str] = Field(None, description="Name of the agency") - hq_address: Optional[str] = Field(None, description="Address of the agency") - hq_city: Optional[str] = Field(None, description="City of the agency") - hq_state: Optional[str] = Field(None, description="State of the agency") - hq_zip: Optional[str] = Field(None, description="Zip code of the agency") - jurisdiction: Optional[str] = Field(None, description="Jurisdiction of the agency") - phone: Optional[str] = Field(None, description="Phone number of the agency") - email: Optional[str] = Field(None, description="Email of the agency") - website_url: Optional[str] = Field(None, description="Website of the agency") - uid: Optional[str] = Field(None, description="Unique identifier for the agency") - officers_url: Optional[str] = Field(None, description="URL to get a list of officers for this agency") - units_url: Optional[str] = Field(None, description="URL to get a list of units for this agency") - - -class CreateUnit(BaseUnit, BaseModel): - name: str = Field(..., description="Name of the unit") - website_url: Optional[str] = Field(None, description="Website of the unit") - phone: Optional[str] = Field(None, description="Phone number of the unit") - email: Optional[str] = Field(None, description="Email of the unit") - description: Optional[str] = Field(None, description="Description of the unit") - address: Optional[str] = Field(None, description="Street address of the unit") - zip: Optional[str] = Field(None, description="Zip code of the unit") - date_established: Optional[str] = Field(None, description="The date that this unit was established by its parent agency.") - commander_uid: Optional[str] = Field(None, description="The UID of the unit's current commander.") - - -class UpdateUnit(BaseUnit, BaseModel): - name: Optional[str] = Field(None, description="Name of the unit") - website_url: Optional[str] = Field(None, description="Website of the unit") - phone: Optional[str] = Field(None, description="Phone number of the unit") - email: Optional[str] = Field(None, description="Email of the unit") - description: Optional[str] = Field(None, description="Description of the unit") - address: Optional[str] = Field(None, description="Street address of the unit") - zip: Optional[str] = Field(None, description="Zip code of the unit") - date_established: Optional[str] = Field(None, description="The date that this unit was established by its parent agency.") - commander_uid: Optional[str] = Field(None, description="The UID of the unit's current commander.") - - -class BaseUnit(BaseModel): - """Base properties for a unit""" - name: Optional[str] = Field(None, description="Name of the unit") - website_url: Optional[str] = Field(None, description="Website of the unit") - phone: Optional[str] = Field(None, description="Phone number of the unit") - email: Optional[str] = Field(None, description="Email of the unit") - description: Optional[str] = Field(None, description="Description of the unit") - address: Optional[str] = Field(None, description="Street address of the unit") - zip: Optional[str] = Field(None, description="Zip code of the unit") - date_established: Optional[str] = Field(None, description="The date that this unit was established by its parent agency.") - - -class Unit(BaseUnit, BaseModel): - name: Optional[str] = Field(None, description="Name of the unit") - website_url: Optional[str] = Field(None, description="Website of the unit") - phone: Optional[str] = Field(None, description="Phone number of the unit") - email: Optional[str] = Field(None, description="Email of the unit") - description: Optional[str] = Field(None, description="Description of the unit") - address: Optional[str] = Field(None, description="Street address of the unit") - zip: Optional[str] = Field(None, description="Zip code of the unit") - date_established: Optional[str] = Field(None, description="The date that this unit was established by its parent agency.") - uid: Optional[str] = Field(None, description="Unique identifier for the unit") - commander: Optional[Officer] = Field(None, description="The current commander of the unit.") - commander_history_url: Optional[str] = Field(None, description="-| URL that returns the past commanders of the unit and the period of their respective commands.") - agency_url: Optional[str] = Field(None, description="URL to get the agency that this unit belongs to.") - officers_url: Optional[str] = Field(None, description="URL to get a list of officers for this unit.") - - -class UnitList(PaginatedResponse, BaseModel): - results: Optional[List[Unit]] = None - - -class AddOfficer(BaseModel): - officer_uid: str = Field(..., description="The uid of the officer") - earliest_employment: Optional[str] = Field(None, description="The earliest date of employment") - latest_employment: Optional[str] = Field(None, description="The latest date of employment") - badge_number: str = Field(..., description="The badge number of the officer") - unit_uid: str = Field(..., description="The UID of the unit the officer is assigned to.") - highest_rank: Optional[str] = Field(None, description="The highest rank the officer has held during their employment.") - commander: Optional[bool] = Field(None, description="-| If true, this officer will be added as the commander of the unit for the specified time period.") - - -class AddOfficerList(BaseModel): - officers: List[AddOfficer] = ... - - -class AddOfficerFailed(BaseModel): - officer_uid: Optional[str] = Field(None, description="The uid of the officer") - reason: Optional[str] = Field(None, description="The reason the employment record could not be added") - - -class AddOfficerResponse(BaseModel): - created: List[Employment] = ... - failed: List[AddOfficerFailed] = ... - total_created: int = ... - total_failed: int = ... - - diff --git a/oas/pydantic/complaints.py b/oas/pydantic/complaints.py deleted file mode 100644 index 8f96120ad..000000000 --- a/oas/pydantic/complaints.py +++ /dev/null @@ -1,207 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union - - -class BaseComplaint(BaseModel): - """Base complaint object""" - record_id: Optional[str] = Field(None, description="The ID that was given to this complaint by the orginal source of the data.") - source_details: Optional[SourceDetails] = None - category: Optional[str] = Field(None, description="The category of the complaint.") - incident_date: Optional[str] = Field(None, description="The date and time the incident occurred.") - recieved_date: Optional[str] = Field(None, description="The date and time the complaint was received by the reporting source.") - closed_date: Optional[str] = Field(None, description="The date and time the complaint was closed.") - location: Optional[Dict[str, Any]] = None - reason_for_contact: Optional[str] = Field(None, description="The reason for the contact.") - outcome_of_contact: Optional[str] = Field(None, description="The outcome of the contact.") - civilian_witnesses: Optional[List[Civilian]] = Field(None, description="The civilian witnesses associated with the complaint.") - attachements: Optional[List[Attachemnts]] = Field(None, description="Documents and multimeida associated with the complaint.") - - -class CreateComplaint(BaseComplaint, BaseModel): - record_id: Optional[str] = Field(None, description="The ID that was given to this complaint by the orginal source of the data.") - source_details: Optional[SourceDetails] = None - category: Optional[str] = Field(None, description="The category of the complaint.") - incident_date: Optional[str] = Field(None, description="The date and time the incident occurred.") - recieved_date: Optional[str] = Field(None, description="The date and time the complaint was received by the reporting source.") - closed_date: Optional[str] = Field(None, description="The date and time the complaint was closed.") - location: Optional[Dict[str, Any]] = None - reason_for_contact: Optional[str] = Field(None, description="The reason for the contact.") - outcome_of_contact: Optional[str] = Field(None, description="The outcome of the contact.") - civilian_witnesses: Optional[List[Civilian]] = Field(None, description="The civilian witnesses associated with the complaint.") - attachements: Optional[List[Attachemnts]] = Field(None, description="Documents and multimeida associated with the complaint.") - source_uid: Optional[str] = Field(None, description="The UID of the source that reported the complaint.") - civilian_review_board_uid: Optional[str] = Field(None, description="The UID of the civilian review board that reviewed the complaint.") - police_witnesses: Optional[List[str]] = Field(None, description="The UID of any police witnesses associated with the complaint.") - allegations: Optional[List[CreateAllegation]] = Field(None, description="The allegations associated with the complaint.") - investigations: Optional[List[CreateInvestigation]] = Field(None, description="The investigations associated with the complaint.") - penalties: Optional[List[CreatePenalty]] = Field(None, description="The penalties associated with the complaint.") - - -class UpdateComplaint(BaseComplaint, BaseModel): - record_id: Optional[str] = Field(None, description="The ID that was given to this complaint by the orginal source of the data.") - source_details: Optional[SourceDetails] = None - category: Optional[str] = Field(None, description="The category of the complaint.") - incident_date: Optional[str] = Field(None, description="The date and time the incident occurred.") - recieved_date: Optional[str] = Field(None, description="The date and time the complaint was received by the reporting source.") - closed_date: Optional[str] = Field(None, description="The date and time the complaint was closed.") - location: Optional[Dict[str, Any]] = None - reason_for_contact: Optional[str] = Field(None, description="The reason for the contact.") - outcome_of_contact: Optional[str] = Field(None, description="The outcome of the contact.") - civilian_witnesses: Optional[List[Civilian]] = Field(None, description="The civilian witnesses associated with the complaint.") - attachements: Optional[List[Attachemnts]] = Field(None, description="Documents and multimeida associated with the complaint.") - civilian_review_board_uid: Optional[str] = Field(None, description="The UID of the civilian review board that reviewed the complaint.") - police_witnesses: Optional[List[str]] = Field(None, description="The uid of any police witnesses associated with the complaint.") - allegations: Optional[List[CreateAllegation]] = Field(None, description="The allegations associated with the complaint.") - investigations: Optional[List[CreateInvestigation]] = Field(None, description="The investigations associated with the complaint.") - penalties: Optional[List[CreatePenalty]] = Field(None, description="The penalties associated with the complaint.") - - -class Complaint(BaseComplaint, BaseModel): - record_id: Optional[str] = Field(None, description="The ID that was given to this complaint by the orginal source of the data.") - source_details: Optional[SourceDetails] = None - category: str = Field(..., description="The category of the complaint.") - incident_date: str = Field(..., description="The date and time the incident occurred.") - recieved_date: str = Field(..., description="The date and time the complaint was received by the reporting source.") - closed_date: Optional[str] = Field(None, description="The date and time the complaint was closed.") - location: Dict[str, Any] = ... - reason_for_contact: Optional[str] = Field(None, description="The reason for the contact.") - outcome_of_contact: Optional[str] = Field(None, description="The outcome of the contact.") - civilian_witnesses: List[Civilian] = Field(..., description="The civilian witnesses associated with the complaint.") - attachements: Optional[List[Attachemnts]] = Field(None, description="Documents and multimeida associated with the complaint.") - uid: str = Field(..., description="Unique identifier for the complaint.") - created_at: str = Field(..., description="Date and time the complaint was created.") - updated_at: str = Field(..., description="Date and time the complaint was last updated.") - source: Optional[Source] = Field(None, description="The source that reported the complaint.") - civilian_review_board: Optional[ReviewBoard] = Field(None, description="The civilian review board that reviewed the complaint.") - police_witnesses: List[Officer] = Field(..., description="The police witnesses associated with the complaint.") - allegations: List[Allegation] = Field(..., description="The allegations associated with the complaint.") - investigations: List[Investigation] = Field(..., description="The investigations associated with the complaint.") - penalties: List[Penalty] = Field(..., description="The penalties associated with the complaint.") - - -class ComplaintList(PaginatedResponse, BaseModel): - results: Optional[List[Complaint]] = Field(None, description="List of complaints.") - - -class BaseAllegation(BaseModel): - record_id: Optional[str] = Field(None, description="The ID that was given to this allegation by the orginal source of the data.") - complaintant: Optional[Civilian] = Field(None, description="Demographic information of the individual who filed the complaint.") - allegation: Optional[str] = Field(None, description="The allegation made by the complaintant.") - type: Optional[str] = Field(None, description="The type of allegation.") - sub_type: Optional[str] = Field(None, description="The sub type of the allegation.") - recomended_finding: Optional[str] = Field(None, description="The finding recomended by the review board.") - recomended_outcome: Optional[str] = Field(None, description="The outcome recomended by the review board.") - finding: Optional[str] = Field(None, description="The legal finding.") - outcome: Optional[str] = Field(None, description="The final outcome of the allegation.") - - -class CreateAllegation(BaseAllegation, BaseModel): - record_id: Optional[str] = Field(None, description="The ID that was given to this allegation by the orginal source of the data.") - complaintant: Optional[Civilian] = Field(None, description="Demographic information of the individual who filed the complaint.") - allegation: Optional[str] = Field(None, description="The allegation made by the complaintant.") - type: Optional[str] = Field(None, description="The type of allegation.") - sub_type: Optional[str] = Field(None, description="The sub type of the allegation.") - recomended_finding: Optional[str] = Field(None, description="The finding recomended by the review board.") - recomended_outcome: Optional[str] = Field(None, description="The outcome recomended by the review board.") - finding: Optional[str] = Field(None, description="The legal finding.") - outcome: Optional[str] = Field(None, description="The final outcome of the allegation.") - perpetrator_uid: Optional[str] = Field(None, description="The UID of the officer the allegation is made against.") - - -class Allegation(BaseAllegation, BaseModel): - record_id: Optional[str] = Field(None, description="The ID that was given to this allegation by the orginal source of the data.") - complaintant: Optional[Civilian] = Field(None, description="Demographic information of the individual who filed the complaint.") - allegation: Optional[str] = Field(None, description="The allegation made by the complaintant.") - type: Optional[str] = Field(None, description="The type of allegation.") - sub_type: Optional[str] = Field(None, description="The sub type of the allegation.") - recomended_finding: Optional[str] = Field(None, description="The finding recomended by the review board.") - recomended_outcome: Optional[str] = Field(None, description="The outcome recomended by the review board.") - finding: Optional[str] = Field(None, description="The legal finding.") - outcome: Optional[str] = Field(None, description="The final outcome of the allegation.") - uid: Optional[str] = Field(None, description="Unique identifier for the allegation.") - perpetrator: Optional[Officer] = Field(None, description="The officer who the allegation is made against.") - - -class Penalty(BaseModel): - uid: Optional[str] = Field(None, description="UUID for the penalty.") - officer: Optional[Officer] = Field(None, description="The officer who the penalty is associated with.") - description: Optional[str] = Field(None, description="A description of the penalty.") - date_assesed: Optional[str] = None - - -class CreatePenalty(BaseModel): - officer_uid: Optional[str] = Field(None, description="The UID of the officer the penalty is associated with.") - description: Optional[str] = Field(None, description="A description of the penalty.") - - -class BaseInvestigation(BaseModel): - start_date: Optional[str] = Field(None, description="The date the investigation started.") - end_date: Optional[str] = Field(None, description="The date the investigation ended.") - - -class CreateInvestigation(BaseInvestigation, BaseModel): - start_date: Optional[str] = Field(None, description="The date the investigation started.") - end_date: Optional[str] = Field(None, description="The date the investigation ended.") - investigator_uid: Optional[str] = Field(None, description="The UID of the officer who preformed the investigation.") - - -class Investigation(BaseInvestigation, BaseModel): - start_date: Optional[str] = Field(None, description="The date the investigation started.") - end_date: Optional[str] = Field(None, description="The date the investigation ended.") - uid: Optional[str] = Field(None, description="Unique identifier for the investigation.") - investigator: Optional[Officer] = Field(None, description="The officer who preformed the investigation.") - - -class Civilian(BaseModel): - age: Optional[str] = Field(None, description="Age range of the individual.") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the individual.") - gender: Optional[str] = Field(None, description="The gender of the individual.") - - -class ReviewBoard(BaseModel): - uid: Optional[str] = Field(None, description="Unique identifier for the review board.") - name: Optional[str] = Field(None, description="The name of the review board.") - city: Optional[str] = Field(None, description="The city the review board is located in.") - state: Optional[str] = Field(None, description="The state the review board is located in.") - url: Optional[str] = Field(None, description="The website URL for the review board.") - - -class Attachemnts(BaseModel): - type: Optional[str] = Field(None, description="The type of attachment.") - url: Optional[str] = Field(None, description="The url of the attachment.") - description: Optional[str] = Field(None, description="A description of the attachment.") - - -class SourceDetails(BaseModel): - record_type: Optional[str] = Field(None, description="The type of record the complaint is associated with.") - - -class LegalAction(BaseModel): - record_type: Optional[str] = Field(None, description="The type of record the complaint is associated with.") - court: Optional[str] = Field(None, description="The court the legal action was filed in.") - judge: Optional[str] = Field(None, description="The judge who presided over the case.") - docket_number: Optional[str] = Field(None, description="The docket number of the case.") - date_of_action: Optional[str] = Field(None, description="The date the legal action was filed.") - - -class PersonalAccount(BaseModel): - record_type: Optional[str] = Field(None, description="The type of record the complaint is associated with.") - - -class GovernmentRecord(BaseModel): - record_type: Optional[str] = Field(None, description="The type of record the complaint is associated with.") - reporting_agency: Optional[str] = Field(None, description="The agency that reported the record.") - reporting_agency_url: Optional[str] = Field(None, description="The url of the agency that reported the record.") - reporting_agency_email: Optional[str] = Field(None, description="The email of the agency that reported the record.") - - -class NewsReport(BaseModel): - record_type: Optional[str] = Field(None, description="The type of record the complaint is associated with.") - publication_name: Optional[str] = Field(None, description="The name of the publication.") - publication_date: Optional[str] = Field(None, description="The date the publication was released.") - publication_url: Optional[str] = Field(None, description="The url of the publication.") - author: Optional[str] = Field(None, description="The author of the publication.") - author_url: Optional[str] = Field(None, description="The url of the author.") - author_email: Optional[str] = Field(None, description="The email of the author.") - - diff --git a/oas/pydantic/litigation.py b/oas/pydantic/litigation.py deleted file mode 100644 index c90b93164..000000000 --- a/oas/pydantic/litigation.py +++ /dev/null @@ -1,140 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union - - -class Disposition(BaseModel): - disposition: str = Field(..., description="The disposition of the litigation. -") - desceripton: Optional[str] = Field(None, description="A description of the disposition. This could include the terms of a settlement, the amount of a judgment, or other relevant information. -") - date: str = Field(..., description="The date when this disposition was reached. -") - - -class BaseLitigation(BaseModel): - case_title: Optional[str] = Field(None, description="The case title or caption for this litigation. Should contain the names of the parties involved. -") - docket_number: Optional[str] = Field(None, description="The docket number for this litigation. This is the unique identifier for the case in the court system. -") - court_level: Optional[str] = Field(None, description="The level of the court where this litigation is being heard. This could be a state court, federal court, or other court system. -") - jurisdiction: Optional[str] = Field(None, description="The geographical or subject matter jurisdiction (e.g., Eastern District, Northern District, County name for state courts) of the court where litigation is being heard. -") - state: Optional[str] = Field(None, description="The state where this litigation is being heard. This should be the two-letter abbreviation for the state. -") - description: Optional[str] = Field(None, description="A description of the litigation. This could include a summary of the case, the legal issues involved, or other relevant information. -") - start_date: Optional[str] = Field(None, description="The date when this litigation was filed or initiated. -") - dispositions: Optional[List[Disposition]] = Field(None, description="A list of any dispositions in this litigation. This could include a settlement, judgment, or other outcome. -") - settlement_amount: Optional[float] = Field(None, description="The amount of any settlement or judgment in this litigation. This should be in USD. -") - url: Optional[str] = Field(None, description="A URL to more information about this litigation. This could be a link to a court website such as [Court Listener](https://www.courtlistener.com/), [PACER](https://www.pacer.gov/), or other legal research resources. -") - - -class CreateLitigation(BaseLitigation, BaseModel): - case_title: Optional[str] = Field(None, description="The case title or caption for this litigation. Should contain the names of the parties involved. -") - docket_number: Optional[str] = Field(None, description="The docket number for this litigation. This is the unique identifier for the case in the court system. -") - court_level: Optional[str] = Field(None, description="The level of the court where this litigation is being heard. This could be a state court, federal court, or other court system. -") - jurisdiction: Optional[str] = Field(None, description="The geographical or subject matter jurisdiction (e.g., Eastern District, Northern District, County name for state courts) of the court where litigation is being heard. -") - state: Optional[str] = Field(None, description="The state where this litigation is being heard. This should be the two-letter abbreviation for the state. -") - description: Optional[str] = Field(None, description="A description of the litigation. This could include a summary of the case, the legal issues involved, or other relevant information. -") - start_date: Optional[str] = Field(None, description="The date when this litigation was filed or initiated. -") - dispositions: Optional[List[Disposition]] = Field(None, description="A list of any dispositions in this litigation. This could include a settlement, judgment, or other outcome. -") - settlement_amount: Optional[float] = Field(None, description="The amount of any settlement or judgment in this litigation. This should be in USD. -") - url: Optional[str] = Field(None, description="A URL to more information about this litigation. This could be a link to a court website such as [Court Listener](https://www.courtlistener.com/), [PACER](https://www.pacer.gov/), or other legal research resources. -") - defendants: Optional[List[str]] = Field(None, description="A list containing the IDs of any officers who are named as defendants in the litigation. -") - - -class UpdateLitigation(BaseLitigation, BaseModel): - case_title: Optional[str] = Field(None, description="The case title or caption for this litigation. Should contain the names of the parties involved. -") - docket_number: Optional[str] = Field(None, description="The docket number for this litigation. This is the unique identifier for the case in the court system. -") - court_level: Optional[str] = Field(None, description="The level of the court where this litigation is being heard. This could be a state court, federal court, or other court system. -") - jurisdiction: Optional[str] = Field(None, description="The geographical or subject matter jurisdiction (e.g., Eastern District, Northern District, County name for state courts) of the court where litigation is being heard. -") - state: Optional[str] = Field(None, description="The state where this litigation is being heard. This should be the two-letter abbreviation for the state. -") - description: Optional[str] = Field(None, description="A description of the litigation. This could include a summary of the case, the legal issues involved, or other relevant information. -") - start_date: Optional[str] = Field(None, description="The date when this litigation was filed or initiated. -") - dispositions: Optional[List[Disposition]] = Field(None, description="A list of any dispositions in this litigation. This could include a settlement, judgment, or other outcome. -") - settlement_amount: Optional[float] = Field(None, description="The amount of any settlement or judgment in this litigation. This should be in USD. -") - url: Optional[str] = Field(None, description="A URL to more information about this litigation. This could be a link to a court website such as [Court Listener](https://www.courtlistener.com/), [PACER](https://www.pacer.gov/), or other legal research resources. -") - defendants: Optional[List[str]] = Field(None, description="A list containing the IDs of any officers who are named as defendants in the litigation. -") - - -class Litigation(BaseLitigation, BaseModel): - case_title: str = Field(..., description="The case title or caption for this litigation. Should contain the names of the parties involved. -") - docket_number: str = Field(..., description="The docket number for this litigation. This is the unique identifier for the case in the court system. -") - court_level: str = Field(..., description="The level of the court where this litigation is being heard. This could be a state court, federal court, or other court system. -") - jurisdiction: str = Field(..., description="The geographical or subject matter jurisdiction (e.g., Eastern District, Northern District, County name for state courts) of the court where litigation is being heard. -") - state: str = Field(..., description="The state where this litigation is being heard. This should be the two-letter abbreviation for the state. -") - description: Optional[str] = Field(None, description="A description of the litigation. This could include a summary of the case, the legal issues involved, or other relevant information. -") - start_date: Optional[str] = Field(None, description="The date when this litigation was filed or initiated. -") - dispositions: Optional[List[Disposition]] = Field(None, description="A list of any dispositions in this litigation. This could include a settlement, judgment, or other outcome. -") - settlement_amount: Optional[float] = Field(None, description="The amount of any settlement or judgment in this litigation. This should be in USD. -") - url: Optional[str] = Field(None, description="A URL to more information about this litigation. This could be a link to a court website such as [Court Listener](https://www.courtlistener.com/), [PACER](https://www.pacer.gov/), or other legal research resources. -") - uid: Optional[str] = Field(None, description="The uid of the litigation") - documents: Optional[str] = Field(None, description="A link to retrieve the documents associated with this litigation") - defendants: List[Officer] = Field(..., description="A list of any officers who are named as defendants in the litigation. -") - - -class LitigationList(PaginatedResponse, BaseModel): - results: Optional[List[Litigation]] = None - - -class BaseDocument(BaseModel): - title: Optional[str] = Field(None, description="The title of the document") - description: Optional[str] = Field(None, description="A description of the document") - url: Optional[str] = Field(None, description="A URL to the document") - - -class CreateDocument(BaseDocument, BaseModel): - title: Optional[str] = Field(None, description="The title of the document") - description: Optional[str] = Field(None, description="A description of the document") - url: Optional[str] = Field(None, description="A URL to the document") - - -class Document(BaseDocument, BaseModel): - title: Optional[str] = Field(None, description="The title of the document") - description: Optional[str] = Field(None, description="A description of the document") - url: Optional[str] = Field(None, description="A URL to the document") - uid: Optional[str] = Field(None, description="The uid of the document") - - -class DocumentList(PaginatedResponse, BaseModel): - results: Optional[List[Document]] = None - - diff --git a/oas/pydantic/officers.py b/oas/pydantic/officers.py deleted file mode 100644 index 1780acc7d..000000000 --- a/oas/pydantic/officers.py +++ /dev/null @@ -1,116 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union - - -class BaseEmployment(BaseModel): - officer_uid: Optional[str] = Field(None, description="The UID of the officer.") - agency_uid: Optional[str] = Field(None, description="The UID of the agency the officer is employed by.") - unit_uid: Optional[str] = Field(None, description="The UID of the unit the officer is assigned to.") - earliest_employment: Optional[str] = Field(None, description="The earliest known date of employment") - latest_employment: Optional[str] = Field(None, description="The latest known date of employment") - badge_number: Optional[str] = Field(None, description="The badge number of the officer") - highest_rank: Optional[str] = Field(None, description="The highest rank the officer has held during this employment.") - commander: Optional[bool] = Field(None, description="Indicates that the officer commanded the unit during this employment.") - - -class AddEmployment(BaseEmployment, BaseModel): - officer_uid: Optional[str] = Field(None, description="The UID of the officer.") - agency_uid: Optional[str] = Field(None, description="The UID of the agency the officer is employed by.") - unit_uid: Optional[str] = Field(None, description="The UID of the unit the officer is assigned to.") - earliest_employment: Optional[str] = Field(None, description="The earliest known date of employment") - latest_employment: Optional[str] = Field(None, description="The latest known date of employment") - badge_number: Optional[str] = Field(None, description="The badge number of the officer") - highest_rank: Optional[str] = Field(None, description="The highest rank the officer has held during this employment.") - commander: Optional[bool] = Field(None, description="Indicates that the officer commanded the unit during this employment.") - - -class AddEmploymentFailed(BaseModel): - agency_uid: Optional[str] = Field(None, description="The uid of the agency that could not be added.") - reason: Optional[str] = Field(None, description="The reason the employment record could not be added") - - -class AddEmploymentList(BaseModel): - agencies: Optional[List[AddEmployment]] = Field(None, description="The units to add to the officer's employment history.") - - -class Employment(BaseEmployment, BaseModel): - officer_uid: Optional[str] = Field(None, description="The UID of the officer.") - agency_uid: Optional[str] = Field(None, description="The UID of the agency the officer is employed by.") - unit_uid: Optional[str] = Field(None, description="The UID of the unit the officer is assigned to.") - earliest_employment: Optional[str] = Field(None, description="The earliest known date of employment") - latest_employment: Optional[str] = Field(None, description="The latest known date of employment") - badge_number: Optional[str] = Field(None, description="The badge number of the officer") - highest_rank: Optional[str] = Field(None, description="The highest rank the officer has held during this employment.") - commander: Optional[bool] = Field(None, description="Indicates that the officer commanded the unit during this employment.") - - -class AddEmploymentResponse(BaseModel): - created: List[Employment] = ... - failed: List[AddEmploymentFailed] = ... - total_created: int = ... - total_failed: int = ... - - -class EmploymentList(PaginatedResponse, BaseModel): - results: Optional[List[Employment]] = None - - -class BaseOfficer(BaseModel): - first_name: Optional[str] = Field(None, description="First name of the officer") - middle_name: Optional[str] = Field(None, description="Middle name of the officer") - last_name: Optional[str] = Field(None, description="Last name of the officer") - suffix: Optional[str] = Field(None, description="Suffix of the officer's name") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the officer") - gender: Optional[str] = Field(None, description="The gender of the officer") - date_of_birth: Optional[str] = Field(None, description="The date of birth of the officer") - state_ids: Optional[List[StateId]] = Field(None, description="The state ids of the officer") - - -class CreateOfficer(BaseOfficer, BaseModel): - first_name: Optional[str] = Field(None, description="First name of the officer") - middle_name: Optional[str] = Field(None, description="Middle name of the officer") - last_name: Optional[str] = Field(None, description="Last name of the officer") - suffix: Optional[str] = Field(None, description="Suffix of the officer's name") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the officer") - gender: Optional[str] = Field(None, description="The gender of the officer") - date_of_birth: Optional[str] = Field(None, description="The date of birth of the officer") - state_ids: Optional[List[StateId]] = Field(None, description="The state ids of the officer") - - -class UpdateOfficer(BaseOfficer, BaseModel): - first_name: Optional[str] = Field(None, description="First name of the officer") - middle_name: Optional[str] = Field(None, description="Middle name of the officer") - last_name: Optional[str] = Field(None, description="Last name of the officer") - suffix: Optional[str] = Field(None, description="Suffix of the officer's name") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the officer") - gender: Optional[str] = Field(None, description="The gender of the officer") - date_of_birth: Optional[str] = Field(None, description="The date of birth of the officer") - state_ids: Optional[List[StateId]] = Field(None, description="The state ids of the officer") - - -class Officer(BaseOfficer, BaseModel): - first_name: Optional[str] = Field(None, description="First name of the officer") - middle_name: Optional[str] = Field(None, description="Middle name of the officer") - last_name: Optional[str] = Field(None, description="Last name of the officer") - suffix: Optional[str] = Field(None, description="Suffix of the officer's name") - ethnicity: Optional[str] = Field(None, description="The ethnicity of the officer") - gender: Optional[str] = Field(None, description="The gender of the officer") - date_of_birth: Optional[str] = Field(None, description="The date of birth of the officer") - state_ids: Optional[List[StateId]] = Field(None, description="The state ids of the officer") - uid: Optional[str] = Field(None, description="The uid of the officer") - employment_history: Optional[str] = Field(None, description="A link to retrieve the employment history of the officer") - allegations: Optional[str] = Field(None, description="A link to retrieve the allegations against the officer") - litigation: Optional[str] = Field(None, description="A link to retrieve the litigation against the officer") - - -class OfficerList(PaginatedResponse, BaseModel): - results: Optional[List[Officer]] = None - - -class StateId(BaseModel): - uid: Optional[str] = Field(None, description="The UUID of this state id") - state: Optional[str] = Field(None, description="The state of the state id") - id_name: Optional[str] = Field(None, description="The name of the id. For example, Tax ID, Driver's License, etc.") - value: Optional[str] = Field(None, description="The value of the id.") - - diff --git a/oas/pydantic/partners.py b/oas/pydantic/partners.py deleted file mode 100644 index 28651fdcf..000000000 --- a/oas/pydantic/partners.py +++ /dev/null @@ -1,62 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union - - -class BasePartner(BaseModel): - name: Optional[str] = Field(None, description="Name of the partner organization.") - url: Optional[str] = Field(None, description="Website URL of the partner.") - contact_email: Optional[str] = Field(None, description="Contact email for the partner organization.") - - -class CreatePartner(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the partner organization.") - url: Optional[str] = Field(None, description="Website URL of the partner.") - contact_email: Optional[str] = Field(None, description="Contact email for the partner organization.") - - -class UpdatePartner(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the partner organization.") - url: Optional[str] = Field(None, description="Website URL of the partner.") - contact_email: Optional[str] = Field(None, description="Contact email for the partner organization.") - - -class Partner(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the partner organization.") - url: Optional[str] = Field(None, description="Website URL of the partner.") - contact_email: Optional[str] = Field(None, description="Contact email for the partner organization.") - uid: Optional[str] = Field(None, description="Unique identifier for the partner.") - members: Optional[str] = Field(None, description="Url to get all members of the partner.") - reported_incidents: Optional[str] = Field(None, description="Url to get all incidents reported by the partner.") - - -class PartnerList(PaginatedResponse, BaseModel): - results: Optional[List[Partner]] = None - - -class MemberBase(BaseModel): - partner_uid: Optional[str] = Field(None, description="Unique identifier for the partner.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - - -class Member(MemberBase, BaseModel): - partner_uid: Optional[str] = Field(None, description="Unique identifier for the partner.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - uid: Optional[str] = Field(None, description="Unique identifier for the user.") - date_joined: Optional[str] = Field(None, description="Date the user joined the partner organizaation.") - - -class AddMember(MemberBase, BaseModel): - partner_uid: Optional[str] = Field(None, description="Unique identifier for the partner.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - - -class MemberList(PaginatedResponse, BaseModel): - results: Optional[List[Member]] = None - - diff --git a/oas/pydantic/sources.py b/oas/pydantic/sources.py deleted file mode 100644 index 22cc96c80..000000000 --- a/oas/pydantic/sources.py +++ /dev/null @@ -1,62 +0,0 @@ -from pydantic import BaseModel, Field -from typing import List, Optional, Dict, Any, Union - - -class BasePartner(BaseModel): - name: Optional[str] = Field(None, description="Name of the source organization.") - url: Optional[str] = Field(None, description="Website URL of the source.") - contact_email: Optional[str] = Field(None, description="Contact email for the source organization.") - - -class CreatePartner(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the source organization.") - url: Optional[str] = Field(None, description="Website URL of the source.") - contact_email: Optional[str] = Field(None, description="Contact email for the source organization.") - - -class UpdatePartner(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the source organization.") - url: Optional[str] = Field(None, description="Website URL of the source.") - contact_email: Optional[str] = Field(None, description="Contact email for the source organization.") - - -class Source(BasePartner, BaseModel): - name: Optional[str] = Field(None, description="Name of the source organization.") - url: Optional[str] = Field(None, description="Website URL of the source.") - contact_email: Optional[str] = Field(None, description="Contact email for the source organization.") - uid: Optional[str] = Field(None, description="Unique identifier for the source.") - members: Optional[str] = Field(None, description="Url to get all members of the source.") - reported_complaints: Optional[str] = Field(None, description="Url to get all complaints reported by the source.") - - -class PartnerList(PaginatedResponse, BaseModel): - results: Optional[List[Source]] = None - - -class MemberBase(BaseModel): - source_uid: Optional[str] = Field(None, description="Unique identifier for the source.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - - -class Member(MemberBase, BaseModel): - source_uid: Optional[str] = Field(None, description="Unique identifier for the source.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - uid: Optional[str] = Field(None, description="Unique identifier for the user.") - date_joined: Optional[str] = Field(None, description="Date the user joined the source organizaation.") - - -class AddMember(MemberBase, BaseModel): - source_uid: Optional[str] = Field(None, description="Unique identifier for the source.") - user_uid: Optional[str] = Field(None, description="Unique identifier for the user.") - role: Optional[str] = Field(None, description="Role of the user.") - is_active: Optional[bool] = Field(None, description="Whether the user is active.") - - -class MemberList(PaginatedResponse, BaseModel): - results: Optional[List[Member]] = None - - diff --git a/requirements/_core.in b/requirements/_core.in index f5ed63c93..1f9871f4a 100644 --- a/requirements/_core.in +++ b/requirements/_core.in @@ -34,4 +34,5 @@ ua-parser ujson neo4j neomodel==5.3.3 +npdi-oas cffi==1.17.1 \ No newline at end of file diff --git a/requirements/dev_unix.txt b/requirements/dev_unix.txt index af79ba5e2..ca703b73b 100644 --- a/requirements/dev_unix.txt +++ b/requirements/dev_unix.txt @@ -124,6 +124,8 @@ neo4j==5.19.0 # neomodel neomodel==5.3.3 # via -r /requirements/_core.in +npdi-oas==0.0.4 + # via -r /requirements/_core.in numpy==1.26.4 # via -r /requirements/_core.in openpyxl==3.0.9 @@ -153,6 +155,7 @@ pycparser==2.21 pydantic==2.9.2 # via # -r /requirements/_core.in + # npdi-oas # spectree pydantic-core==2.23.4 # via pydantic diff --git a/requirements/dev_windows.txt b/requirements/dev_windows.txt index 6066fb3a7..66d0c1044 100644 --- a/requirements/dev_windows.txt +++ b/requirements/dev_windows.txt @@ -124,6 +124,8 @@ neo4j==5.19.0 # neomodel neomodel==5.3.3 # via -r /requirements/_core.in +npdi-oas==0.0.4 + # via -r /requirements/_core.in numpy==1.26.4 # via -r /requirements/_core.in openpyxl==3.0.9 @@ -153,6 +155,7 @@ pycparser==2.21 pydantic==2.9.2 # via # -r /requirements/_core.in + # npdi-oas # spectree pydantic-core==2.23.4 # via pydantic diff --git a/requirements/prod.txt b/requirements/prod.txt index e8ae3601d..7b96d68de 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -124,6 +124,8 @@ neo4j==5.19.0 # neomodel neomodel==5.3.3 # via -r /requirements/_core.in +npdi-oas==0.0.4 + # via -r /requirements/_core.in numpy==1.26.4 # via -r /requirements/_core.in openpyxl==3.0.9 @@ -153,6 +155,7 @@ pycparser==2.21 pydantic==2.9.2 # via # -r /requirements/_core.in + # npdi-oas # spectree pydantic-core==2.23.4 # via pydantic