From d1718becde4a88f62ae446b442e9b1bb51318413 Mon Sep 17 00:00:00 2001 From: ewandor Date: Fri, 11 Apr 2025 21:58:04 +0200 Subject: [PATCH] Refactoring Hub Firms routes --- api/rpk-api/hub/firm/__init__.py | 14 ++++++--- api/rpk-api/hub/firm/routes.py | 52 +++++++++++++++----------------- api/rpk-api/hub/user/schemas.py | 6 ++++ 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/api/rpk-api/hub/firm/__init__.py b/api/rpk-api/hub/firm/__init__.py index 7c6ff9c..75a1a50 100644 --- a/api/rpk-api/hub/firm/__init__.py +++ b/api/rpk-api/hub/firm/__init__.py @@ -5,25 +5,29 @@ from pymongo import IndexModel from hub.core import CrudDocument class Firm(CrudDocument): - name: str = Field() instance: str = Field() + firm: str = Field() owner: PydanticObjectId = Field() + @classmethod + def get_by_name(cls, instance, firm): + return cls.find_one({"instance": instance, "firm": firm}) + def compute_label(self) -> str: - return self.name + return f"{self.instance} / {self.firm}" class Settings: indexes = [ - IndexModel(["name", "instance"], unique=True), + IndexModel(["instance", "firm"], unique=True), ] class FirmRead(BaseModel): instance: str = Field() - name: str = Field() + firm: str = Field() class FirmCreate(FirmRead): instance: str = Field(max_length=32, min_length=3, pattern="^[0-9a-z-]+$") - name: str = Field(max_length=32, min_length=3, pattern="^[0-9a-z-]+$") + firm: str = Field(max_length=32, min_length=3, pattern="^[0-9a-z-]+$") class FirmUpdate(BaseModel): owner: PydanticObjectId = Field() diff --git a/api/rpk-api/hub/firm/routes.py b/api/rpk-api/hub/firm/routes.py index 14641d2..52f661f 100644 --- a/api/rpk-api/hub/firm/routes.py +++ b/api/rpk-api/hub/firm/routes.py @@ -1,4 +1,3 @@ -from beanie import PydanticObjectId from fastapi import APIRouter, Depends, HTTPException from hub.auth import get_current_user @@ -7,42 +6,41 @@ from hub.firm import Firm, FirmRead, FirmCreate, FirmUpdate router = APIRouter() -@router.get("/", response_model=list[FirmRead], response_description="{} records retrieved".format(Firm.__name__)) +@router.get("/", response_model=list[FirmRead], response_description="List of firms owned by the current user") async def read_list(user=Depends(get_current_user)) -> list[FirmRead]: return await Firm.find({ "owner": user.id}).to_list() -@router.post("/", response_description="{} added to the database".format(Firm.__name__)) +@router.post("/", response_description="Firm added to the database") async def create(item: FirmCreate, user=Depends(get_current_user)) -> FirmRead: - firm_dict = {"name": item.name, "instance": item.instance} - exists = await Firm.find_one(firm_dict) + exists = await Firm.get_by_name(item.instance, item.firm) if exists: raise HTTPException(status_code=400, detail="Firm already exists") record = Firm(created_by=user.id, updated_by=user.id, owner=user.id, **item.model_dump()) o = await record.create() - user.firms.append(firm_dict) + user.firms.append({"instance": item.instance, "firm": item.firm}) await user.save() return FirmRead(**o.model_dump()) -@router.get("/{id}", response_description="{} record retrieved".format(Firm.__name__)) -async def read_id(id: PydanticObjectId, user=Depends(get_current_user)) -> FirmRead: - item = await Firm.get(id) +@router.get("/{instance}/{firm}", response_description="Firm retrieved") +async def read_id(instance: str, firm: str, user=Depends(get_current_user)) -> FirmRead: + item = await Firm.get_by_name(instance, firm) + if not item or not user.belong_to(item) not in user.firms: + raise HTTPException(status_code=404, detail="Item not found") + return FirmRead(**item.model_dump()) -@router.put("/{id}", response_description="{} record updated".format(Firm.__name__)) -async def update(id: PydanticObjectId, req: FirmUpdate, user=Depends(get_current_user)) -> FirmRead: - item = await Firm.get(id) - if not item: - raise HTTPException( - status_code=404, - detail="{} record not found!".format(Firm.__name__) - ) +@router.put("/{instance}/{firm}", response_description="Firm updated") +async def update(instance: str, firm: str, req: FirmUpdate, user=Depends(get_current_user)) -> FirmRead: + item = await Firm.get_by_name(instance, firm) + if not item or not user.belong_to(item) not in user.firms: + raise HTTPException(status_code=404, detail="Item not found") if item.owner != user.id: raise HTTPException( status_code=403, - detail="Insufficient credentials to modify {} record".format(Firm.__name__) + detail="Insufficient credentials to modify Firm" ) req = {k: v for k, v in req.model_dump().items() if v is not None} @@ -53,21 +51,19 @@ async def update(id: PydanticObjectId, req: FirmUpdate, user=Depends(get_current await item.update(update_query) return FirmRead(**item.dict()) -@router.delete("/{id}", response_description="{} record deleted from the database".format(Firm.__name__)) -async def delete(id: PydanticObjectId, user=Depends(get_current_user)) -> dict: - item = await Firm.get(id) - if not item: - raise HTTPException( - status_code=404, - detail="{} record not found!".format(Firm.__name__) - ) +@router.delete("/{instance}/{firm}", response_description="Firm deleted from the database") +async def delete(instance: str, firm: str, user=Depends(get_current_user)) -> dict: + item = await Firm.get_by_name(instance, firm) + if not item or not user.belong_to(item) not in user.firms: + raise HTTPException(status_code=404, detail="Firm not found") + if item.owner != user.id: raise HTTPException( status_code=403, - detail="Insufficient credentials delete {} record".format(Firm.__name__) + detail="Insufficient credentials delete Firm" ) await item.delete() return { - "message": "{} deleted successfully".format(Firm.__name__) + "message": "Firm deleted successfully" } diff --git a/api/rpk-api/hub/user/schemas.py b/api/rpk-api/hub/user/schemas.py index d4d515c..d235d8d 100644 --- a/api/rpk-api/hub/user/schemas.py +++ b/api/rpk-api/hub/user/schemas.py @@ -8,5 +8,11 @@ from hub.firm import FirmRead class UserSchema(BaseUser[PydanticObjectId]): firms: list[FirmRead] = Field() + def belongs_to(self, firm): + for f in self.firms: + if f.instance == firm.instance and f.firm == firm.firm : + return True + return False + class UserUpdateSchema(BaseUserUpdate): pass