diff --git a/src/api/endpoints/agencies/by_id/delete/request.py b/src/api/endpoints/agencies/by_id/delete/request.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/api/endpoints/agencies/by_id/put/request.py b/src/api/endpoints/agencies/by_id/put/request.py index b485e43c..8d1457fb 100644 --- a/src/api/endpoints/agencies/by_id/put/request.py +++ b/src/api/endpoints/agencies/by_id/put/request.py @@ -1,9 +1,8 @@ -from pydantic import BaseModel - +from src.api.shared.models.request_base import RequestBase from src.db.models.impl.agency.enums import AgencyType, JurisdictionType -class AgencyPutRequest(BaseModel): +class AgencyPutRequest(RequestBase): name: str | None = None type: AgencyType | None = None jurisdiction_type: JurisdictionType | None = None diff --git a/src/api/endpoints/agencies/root/post/request.py b/src/api/endpoints/agencies/root/post/request.py index 6d95eaf2..009c863c 100644 --- a/src/api/endpoints/agencies/root/post/request.py +++ b/src/api/endpoints/agencies/root/post/request.py @@ -1,9 +1,8 @@ -from pydantic import BaseModel - +from src.api.shared.models.request_base import RequestBase from src.db.models.impl.agency.enums import AgencyType, JurisdictionType -class AgencyPostRequest(BaseModel): +class AgencyPostRequest(RequestBase): name: str type: AgencyType jurisdiction_type: JurisdictionType diff --git a/src/api/endpoints/annotate/agency/post/dto.py b/src/api/endpoints/annotate/agency/post/dto.py index dc41720a..1a13f073 100644 --- a/src/api/endpoints/annotate/agency/post/dto.py +++ b/src/api/endpoints/annotate/agency/post/dto.py @@ -2,7 +2,9 @@ from pydantic import BaseModel +from src.api.shared.models.request_base import RequestBase -class URLAgencyAnnotationPostInfo(BaseModel): + +class URLAgencyAnnotationPostInfo(RequestBase): is_new: bool = False suggested_agency: int | None = None diff --git a/src/api/endpoints/annotate/all/post/models/request.py b/src/api/endpoints/annotate/all/post/models/request.py index 8de222de..32228bac 100644 --- a/src/api/endpoints/annotate/all/post/models/request.py +++ b/src/api/endpoints/annotate/all/post/models/request.py @@ -1,15 +1,15 @@ -from pydantic import BaseModel, model_validator, ConfigDict +from pydantic import model_validator from src.api.endpoints.annotate.all.post.models.agency import AnnotationPostAgencyInfo from src.api.endpoints.annotate.all.post.models.location import AnnotationPostLocationInfo from src.api.endpoints.annotate.all.post.models.name import AnnotationPostNameInfo +from src.api.shared.models.request_base import RequestBase from src.core.enums import RecordType from src.core.exceptions import FailedValidationException from src.db.models.impl.flag.url_validated.enums import URLType -class AllAnnotationPostInfo(BaseModel): - model_config = ConfigDict(extra='forbid') +class AllAnnotationPostInfo(RequestBase): suggested_status: URLType record_type: RecordType | None = None diff --git a/src/api/endpoints/collector/dtos/manual_batch/post.py b/src/api/endpoints/collector/dtos/manual_batch/post.py index 6ec62579..ce00e40b 100644 --- a/src/api/endpoints/collector/dtos/manual_batch/post.py +++ b/src/api/endpoints/collector/dtos/manual_batch/post.py @@ -2,6 +2,7 @@ from pydantic import BaseModel, Field +from src.api.shared.models.request_base import RequestBase from src.core.enums import RecordType @@ -16,7 +17,7 @@ class ManualBatchInnerInputDTO(BaseModel): supplying_entity: str | None = None -class ManualBatchInputDTO(BaseModel): +class ManualBatchInputDTO(RequestBase): name: str entries: list[ManualBatchInnerInputDTO] = Field( min_length=1, diff --git a/src/api/endpoints/submit/data_source/request.py b/src/api/endpoints/submit/data_source/request.py index fc649f74..409fe254 100644 --- a/src/api/endpoints/submit/data_source/request.py +++ b/src/api/endpoints/submit/data_source/request.py @@ -1,13 +1,12 @@ from datetime import date -from pydantic import BaseModel - +from src.api.shared.models.request_base import RequestBase from src.core.enums import RecordType from src.db.models.impl.url.optional_ds_metadata.enums import AgencyAggregationEnum, UpdateMethodEnum, \ RetentionScheduleEnum, AccessTypeEnum -class DataSourceSubmissionRequest(BaseModel): +class DataSourceSubmissionRequest(RequestBase): # Required name: str record_type: RecordType diff --git a/src/api/endpoints/submit/url/models/request.py b/src/api/endpoints/submit/url/models/request.py index 5b52d761..34ec9df9 100644 --- a/src/api/endpoints/submit/url/models/request.py +++ b/src/api/endpoints/submit/url/models/request.py @@ -1,9 +1,10 @@ from pydantic import BaseModel +from src.api.shared.models.request_base import RequestBase from src.core.enums import RecordType -class URLSubmissionRequest(BaseModel): +class URLSubmissionRequest(RequestBase): url: str record_type: RecordType | None = None name: str | None = None diff --git a/src/api/endpoints/suggest/__init__.py b/src/api/endpoints/suggest/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/api/endpoints/suggest/routes.py b/src/api/endpoints/suggest/routes.py deleted file mode 100644 index 8caeb8ac..00000000 --- a/src/api/endpoints/suggest/routes.py +++ /dev/null @@ -1,19 +0,0 @@ -from fastapi import APIRouter, Depends - -from src.api.dependencies import get_async_core -from src.api.endpoints.suggest.url.models.request import URLSuggestionRequest -from src.api.endpoints.suggest.url.models.response.model import URLSuggestResponse -from src.api.endpoints.suggest.url.wrapper import suggest_url_wrapper -from src.core.core import AsyncCore - -suggest_router = APIRouter(prefix="/suggest", tags=["suggest"]) - -@suggest_router.post("/url") -async def suggest_url( - request: URLSuggestionRequest, - async_core: AsyncCore = Depends(get_async_core), -) -> URLSuggestResponse: - return await suggest_url_wrapper( - request=request, - adb_client=async_core.adb_client, - ) diff --git a/src/api/endpoints/suggest/url/__init__.py b/src/api/endpoints/suggest/url/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/api/endpoints/suggest/url/models/__init__.py b/src/api/endpoints/suggest/url/models/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/api/endpoints/suggest/url/models/request.py b/src/api/endpoints/suggest/url/models/request.py deleted file mode 100644 index 4deec1d5..00000000 --- a/src/api/endpoints/suggest/url/models/request.py +++ /dev/null @@ -1,13 +0,0 @@ -from pydantic import BaseModel - -from src.core.enums import RecordType -from src.db.models.impl.flag.url_validated.enums import URLType - - -class URLSuggestionRequest(BaseModel): - url: str - url_type: URLType | None = None - record_type: RecordType | None = None - agency_ids: list[int] = [] - location_ids: list[int] = [] - name: str | None = None \ No newline at end of file diff --git a/src/api/endpoints/suggest/url/models/response/__init__.py b/src/api/endpoints/suggest/url/models/response/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/api/endpoints/suggest/url/models/response/enums.py b/src/api/endpoints/suggest/url/models/response/enums.py deleted file mode 100644 index 337d759a..00000000 --- a/src/api/endpoints/suggest/url/models/response/enums.py +++ /dev/null @@ -1,7 +0,0 @@ -from enum import Enum - - -class URLSuggestResultEnum(Enum): - ACCEPTED = "accepted" - ACCEPTED_WITH_ERRORS = "accepted_with_errors" - DUPLICATE = "duplicate" diff --git a/src/api/endpoints/suggest/url/models/response/model.py b/src/api/endpoints/suggest/url/models/response/model.py deleted file mode 100644 index 091734bb..00000000 --- a/src/api/endpoints/suggest/url/models/response/model.py +++ /dev/null @@ -1,9 +0,0 @@ -from pydantic import BaseModel - -from src.api.endpoints.suggest.url.models.response.enums import URLSuggestResultEnum - - -class URLSuggestResponse(BaseModel): - result: URLSuggestResultEnum - url_id: int | None - msg: str \ No newline at end of file diff --git a/src/api/endpoints/suggest/url/queries/__init__.py b/src/api/endpoints/suggest/url/queries/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/api/endpoints/suggest/url/queries/core.py b/src/api/endpoints/suggest/url/queries/core.py deleted file mode 100644 index 77b90128..00000000 --- a/src/api/endpoints/suggest/url/queries/core.py +++ /dev/null @@ -1,73 +0,0 @@ -from sqlalchemy.ext.asyncio import AsyncSession - -from src.api.endpoints.suggest.url.models.request import URLSuggestionRequest -from src.api.endpoints.suggest.url.models.response.enums import URLSuggestResultEnum -from src.api.endpoints.suggest.url.models.response.model import URLSuggestResponse -from src.db.models.impl.url.core.sqlalchemy import URL -from src.db.queries.base.builder import QueryBuilderBase -from src.db.queries.urls_exist.model import URLExistsResult -from src.db.queries.urls_exist.query import URLsExistInDBQueryBuilder -from src.db.queries.urls_exist.requester import URLSuggestRequester -from src.util.models.full_url import FullURL - - -class URLSuggestQueryBuilder(QueryBuilderBase): - - def __init__( - self, - request: URLSuggestionRequest - ): - super().__init__() - self.request = request - - async def run(self, session: AsyncSession) -> URLSuggestResponse: - # Clean URL - full_url = FullURL(self.request.url) - - # Check if already exists in database - url_exists_result: URLExistsResult = (await URLsExistInDBQueryBuilder( - [full_url] - ).run(session))[0] - if url_exists_result.url_id is not None: - return URLSuggestResponse( - url_id=url_exists_result.url_id, - result=URLSuggestResultEnum.DUPLICATE, - msg=f"URL Already Exists In Database with ID {url_exists_result.url_id}" - ) - - # Add URL - url = URL( - scheme=full_url.scheme, - url=full_url.id_form, - trailing_slash=full_url.has_trailing_slash, - ) - session.add(url) - await session.flush() - url_id: int = url.id - - try: - requester = URLSuggestRequester(session=session, url_id=url_id) - - # Optionally add other annotations - await requester.optionally_add_url_type_suggestion(self.request.url_type) - - await requester.optionally_add_record_type_suggestion(self.request.record_type) - - await requester.optionally_add_agency_id_suggestions(self.request.agency_ids) - - await requester.optionally_add_name_suggestion(self.request.name) - - # If cleaned URL matches original URL, return as ACCEPTED - return URLSuggestResponse( - url_id=url_id, - result=URLSuggestResultEnum.ACCEPTED, - msg="URL was accepted" - ) - - except Exception as e: - return URLSuggestResponse( - url_id=url_id, - result=URLSuggestResultEnum.ACCEPTED_WITH_ERRORS, - msg=f"The URL was accepted, but there were errors in adding provided annotations: {e}" - ) - diff --git a/src/api/endpoints/suggest/url/wrapper.py b/src/api/endpoints/suggest/url/wrapper.py deleted file mode 100644 index 7927db25..00000000 --- a/src/api/endpoints/suggest/url/wrapper.py +++ /dev/null @@ -1,24 +0,0 @@ -from http import HTTPStatus - -from fastapi import HTTPException - -from src.api.endpoints.suggest.url.models.request import URLSuggestionRequest -from src.api.endpoints.suggest.url.models.response.model import URLSuggestResponse -from src.api.endpoints.suggest.url.queries.core import URLSuggestQueryBuilder -from src.db.client.async_ import AsyncDatabaseClient -from src.util.url import is_valid_url - - -async def suggest_url_wrapper( - request: URLSuggestionRequest, - adb_client: AsyncDatabaseClient, -) -> URLSuggestResponse: - if not is_valid_url(request.url): - raise HTTPException( - status_code=HTTPStatus.BAD_REQUEST, - detail="Invalid URL" - ) - - return await adb_client.run_query_builder( - URLSuggestQueryBuilder(request) - ) \ No newline at end of file diff --git a/src/api/shared/models/request_base.py b/src/api/shared/models/request_base.py new file mode 100644 index 00000000..816cc226 --- /dev/null +++ b/src/api/shared/models/request_base.py @@ -0,0 +1,8 @@ +from pydantic import BaseModel, ConfigDict + + +class RequestBase(BaseModel): + model_config = ConfigDict( + extra="forbid", + frozen=True + ) \ No newline at end of file