From c88355ea565fac03f747ef1b2a8004becce78b52 Mon Sep 17 00:00:00 2001 From: spwoodcock Date: Tue, 13 Feb 2024 17:51:59 +0000 Subject: [PATCH] fix: org creation using Form params --- .../app/organisations/organisation_crud.py | 7 ++-- .../app/organisations/organisation_routes.py | 10 ++++- .../app/organisations/organisation_schemas.py | 39 ++++++++++++++++--- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/backend/app/organisations/organisation_crud.py b/src/backend/app/organisations/organisation_crud.py index 7725cf78dc..b5de5ec413 100644 --- a/src/backend/app/organisations/organisation_crud.py +++ b/src/backend/app/organisations/organisation_crud.py @@ -18,8 +18,9 @@ """Logic for organisation management.""" from io import BytesIO +from typing import Optional -from fastapi import HTTPException, Response, UploadFile +from fastapi import File, HTTPException, Response, UploadFile from loguru import logger as log from sqlalchemy import update from sqlalchemy.orm import Session @@ -59,7 +60,7 @@ async def get_unapproved_organisations( async def upload_logo_to_s3( - db_org: db_models.DbOrganisation, logo_file: UploadFile(None) + db_org: db_models.DbOrganisation, logo_file: UploadFile ) -> str: """Upload logo using standardised /{org_id}/logo.png format. @@ -91,7 +92,7 @@ async def upload_logo_to_s3( async def create_organisation( - db: Session, org_model: OrganisationIn, logo: UploadFile(None) + db: Session, org_model: OrganisationIn, logo: Optional[UploadFile] = File(None) ) -> db_models.DbOrganisation: """Creates a new organisation with the given name, description, url, type, and logo. diff --git a/src/backend/app/organisations/organisation_routes.py b/src/backend/app/organisations/organisation_routes.py index b61207f473..1eb6f71e32 100644 --- a/src/backend/app/organisations/organisation_routes.py +++ b/src/backend/app/organisations/organisation_routes.py @@ -17,6 +17,8 @@ # """Routes for organisation management.""" +from typing import Optional + from fastapi import ( APIRouter, Depends, @@ -71,11 +73,15 @@ async def get_organisation_detail( async def create_organisation( # Depends required below to allow logo upload org: organisation_schemas.OrganisationIn = Depends(), - logo: UploadFile = File(None), + logo: Optional[UploadFile] = File(None), db: Session = Depends(database.get_db), current_user: DbUser = Depends(login_required), ) -> organisation_schemas.OrganisationOut: - """Create an organisation with the given details.""" + """Create an organisation with the given details. + + TODO refactor to use base64 encoded logo / no upload file. + TODO then we can use the pydantic model as intended. + """ return await organisation_crud.create_organisation(db, org, logo) diff --git a/src/backend/app/organisations/organisation_schemas.py b/src/backend/app/organisations/organisation_schemas.py index ab38d59c8e..78895a30d0 100644 --- a/src/backend/app/organisations/organisation_schemas.py +++ b/src/backend/app/organisations/organisation_schemas.py @@ -20,7 +20,8 @@ from re import sub from typing import Optional -from pydantic import BaseModel, computed_field +from fastapi import Form +from pydantic import BaseModel, Field, computed_field from app.config import HttpUrlStr from app.models.enums import CommunityType, OrganisationType @@ -33,10 +34,16 @@ class OrganisationIn(ODKCentralIn): """Organisation to create from user input.""" - name: str - description: Optional[str] = None - url: Optional[HttpUrlStr] = None - community_type: Optional[CommunityType] = None + name: str = Field(Form(..., description="Organisation name")) + description: Optional[str] = Field( + Form(None, description="Organisation description") + ) + url: Optional[HttpUrlStr] = Field( + Form(None, description=("Organisation website URL")) + ) + community_type: Optional[CommunityType] = Field( + Form(None, description=("Organisation community type")) + ) @computed_field @property @@ -50,6 +57,28 @@ def slug(self) -> str: slug = sub(r"[-\s]+", "-", slug) return slug + # TODO replace once computed logo complete below + odk_central_url: Optional[HttpUrlStr] = Field( + Form(None, description=("ODK Central URL")) + ) + odk_central_user: Optional[str] = Field( + Form(None, description=("ODK Central User")) + ) + odk_central_password: Optional[str] = Field( + Form(None, description=("ODK Central Password")) + ) + + # TODO decode base64 logo and upload in computed property + # @computed_field + # @property + # def logo(self) -> Optional[str]: + # """Decode and upload logo to S3, return URL.""" + # if not self.logo_base64: + # return None + # logo_decoded = base64.b64decode(self.logo_base64) + # # upload to S3 + # return url + class OrganisationEdit(OrganisationIn): """Organisation to edit via user input."""