From d5bfaa7391f37ebdb1050913157cf0516d2c1a07 Mon Sep 17 00:00:00 2001 From: hanfi <ccc@spahan.ch> Date: Fri, 16 Jun 2023 08:23:17 +0200 Subject: [PATCH] allow signed updates --- backend/main.py | 14 ++++++++++++-- backend/models.py | 3 +-- backend/schemas.py | 11 +++++++++-- backend/utils.py | 23 +++++++++++++++++++++++ requirements.txt | 1 + 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/backend/main.py b/backend/main.py index e889389..3b9af59 100644 --- a/backend/main.py +++ b/backend/main.py @@ -37,12 +37,22 @@ def add_item(item: schemas.ItemCreatePrepareShipping, db: Session = Depends(get_ return utils.prepare_item_shipping(db, item) +@app.post("/item/update/{item_uuid}", response_model=schemas.Item) +def update_item( + item_uuid: str, data: schemas.ItemUpdate, db: Session = Depends(get_db) +): + item = utils.get_item_by_uuid(db, UUID(item_uuid)) + if not item: + raise HTTPException(status_code=404, detail="Item not found") + return utils.update_item(db, item, data) + + @app.get("/item/{item_uuid}", response_model=schemas.Item) def get_item(item_uuid: str, db: Session = Depends(get_db)): item = utils.get_item_by_uuid(db, UUID(item_uuid)) if not item: raise HTTPException(status_code=404, detail="Item not found") - return utils.get_item_by_uuid(db, UUID(item_uuid)) + return item @app.get("/tag/{tag}", response_model=schemas.Item) @@ -50,7 +60,7 @@ def get_item_by_tag(tag: str, db: Session = Depends(get_db)): item = utils.get_item_by_tag(db, tag) if not item: raise HTTPException(status_code=404, detail="Item not found") - return utils.get_item_by_tag(db, tag) + return item @app.get("/storages", response_model=list[schemas.Storage]) diff --git a/backend/models.py b/backend/models.py index fafdc65..84c1cdb 100644 --- a/backend/models.py +++ b/backend/models.py @@ -4,7 +4,6 @@ from sqlalchemy import Column as sql_Column from sqlalchemy import DateTime as sql_DateTime from sqlalchemy import ForeignKey as sql_ForeignKey from sqlalchemy import Integer as sql_Integer -from sqlalchemy import LargeBinary as sql_LargeBinary from sqlalchemy import String as sql_String from sqlalchemy import Uuid as sql_Uuid from sqlalchemy.orm import relationship as sql_relationship @@ -28,7 +27,7 @@ class Item(db_Base): deployed = sql_Column(sql_String(64), nullable=True, default=None) deployed_at = sql_Column(sql_DateTime(timezone=True), nullable=True, default=None) - verification = sql_Column(sql_LargeBinary(57), nullable=True, default=None) + verification = sql_Column(sql_String(114), nullable=True, default=None) tag = sql_Column(sql_String(6), nullable=True, default=None) storage = sql_Column( diff --git a/backend/schemas.py b/backend/schemas.py index 5ecec4a..27f025e 100644 --- a/backend/schemas.py +++ b/backend/schemas.py @@ -12,7 +12,7 @@ class Image(BaseModel): class ItemCreatePrepareShipping(BaseModel): - verification: bytes + verification: str addressee: Union[str, None] = None team: Union[str, None] = None @@ -28,6 +28,13 @@ class ItemCheckin(BaseModel): amount: Union[int, None] = 1 +class ItemUpdate(BaseModel): + addressee: Union[str, None] = None + team: Union[str, None] = None + amount: Union[int, None] = None + signature: str + + class Item(BaseModel): uuid: UUID4 amount: int @@ -41,7 +48,7 @@ class Item(BaseModel): deployed: Union[str, None] = None deployed_at: Union[datetime, None] = None - verification: Union[bytes, None] = None + verification: Union[str, None] = None tag: Union[str, None] = None storage: Union[str, None] = None diff --git a/backend/utils.py b/backend/utils.py index 35e435f..26068dd 100644 --- a/backend/utils.py +++ b/backend/utils.py @@ -1,6 +1,8 @@ from datetime import datetime from secrets import token_hex +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PublicKey from pydantic import UUID4 from sqlalchemy.orm import Session @@ -40,6 +42,27 @@ def prepare_item_shipping(db: Session, item: schemas.ItemCreatePrepareShipping): return new_item +def update_item(db: Session, item: schemas.Item, data: schemas.ItemUpdate): + public_key = Ed448PublicKey.from_public_bytes(bytes.fromhex(item.verification)) + verify = "" + if data.addressee: + verify += data.addressee + item.addressee = data.addressee + if data.team: + verify += data.team + item.team = data.team + if data.amount: + verify += str(data.amount) + item.amount = data.amount + try: + public_key.verify(bytes.fromhex(data.signature), bytes(verify, "utf-8")) + except InvalidSignature: + return None + db.commit() + db.refresh(item) + return item + + def receive_item_with_image(db: Session, item: schemas.ItemCreateByImageAtStorage): new_item = models.Item(storage_uuid=item.storage_uuid) db.add(new_item) diff --git a/requirements.txt b/requirements.txt index 0b123ed..eab79be 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +cryptography==41.0.1 fastapi==0.95.1 Jinja2==3.1.2 python-multipart==0.0.6 -- GitLab