✨ Trip attachments, ensure Trip archived checks consistency
This commit is contained in:
parent
fe75f6f6b9
commit
9155219946
@ -1,13 +1,15 @@
|
|||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
from sqlalchemy import update
|
from sqlalchemy import update
|
||||||
from sqlalchemy.orm import selectinload
|
from sqlalchemy.orm import selectinload
|
||||||
from sqlmodel import select
|
from sqlmodel import select
|
||||||
|
|
||||||
from ..config import settings
|
from ..config import settings
|
||||||
from ..deps import SessionDep, get_current_username
|
from ..deps import SessionDep, get_current_username
|
||||||
from ..models.models import (Image, Place, Trip, TripChecklistItem,
|
from ..models.models import (Image, Place, Trip, TripAttachment,
|
||||||
|
TripAttachmentRead, TripChecklistItem,
|
||||||
TripChecklistItemCreate, TripChecklistItemRead,
|
TripChecklistItemCreate, TripChecklistItemRead,
|
||||||
TripChecklistItemUpdate, TripCreate, TripDay,
|
TripChecklistItemUpdate, TripCreate, TripDay,
|
||||||
TripDayBase, TripDayRead, TripInvitationRead,
|
TripDayBase, TripDayRead, TripInvitationRead,
|
||||||
@ -18,7 +20,8 @@ from ..models.models import (Image, Place, Trip, TripChecklistItem,
|
|||||||
TripPackingListItemRead,
|
TripPackingListItemRead,
|
||||||
TripPackingListItemUpdate, TripRead, TripReadBase,
|
TripPackingListItemUpdate, TripRead, TripReadBase,
|
||||||
TripShare, TripShareURL, TripUpdate, User)
|
TripShare, TripShareURL, TripUpdate, User)
|
||||||
from ..utils.utils import (b64img_decode, generate_urlsafe, remove_image,
|
from ..utils.utils import (attachments_trip_folder_path, b64img_decode,
|
||||||
|
generate_urlsafe, save_attachment,
|
||||||
save_image_to_file, utc_now)
|
save_image_to_file, utc_now)
|
||||||
|
|
||||||
router = APIRouter(prefix="/api/trips", tags=["trips"])
|
router = APIRouter(prefix="/api/trips", tags=["trips"])
|
||||||
@ -190,7 +193,6 @@ def update_trip(
|
|||||||
if db_trip.image_id:
|
if db_trip.image_id:
|
||||||
old_image = session.get(Image, db_trip.image_id)
|
old_image = session.get(Image, db_trip.image_id)
|
||||||
try:
|
try:
|
||||||
remove_image(old_image.filename)
|
|
||||||
session.delete(old_image)
|
session.delete(old_image)
|
||||||
db_trip.image_id = None
|
db_trip.image_id = None
|
||||||
session.refresh(db_trip)
|
session.refresh(db_trip)
|
||||||
@ -239,7 +241,6 @@ def delete_trip(
|
|||||||
|
|
||||||
if db_trip.image:
|
if db_trip.image:
|
||||||
try:
|
try:
|
||||||
remove_image(db_trip.image.filename)
|
|
||||||
session.delete(db_trip.image)
|
session.delete(db_trip.image)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
@ -329,9 +330,9 @@ def update_tripday(
|
|||||||
|
|
||||||
@router.delete("/{trip_id}/days/{day_id}")
|
@router.delete("/{trip_id}/days/{day_id}")
|
||||||
def delete_tripday(
|
def delete_tripday(
|
||||||
session: SessionDep,
|
|
||||||
trip_id: int,
|
trip_id: int,
|
||||||
day_id: int,
|
day_id: int,
|
||||||
|
session: SessionDep,
|
||||||
current_user: Annotated[str, Depends(get_current_username)],
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
):
|
):
|
||||||
db_trip = _get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
@ -452,7 +453,6 @@ def update_tripitem(
|
|||||||
if db_item.image_id:
|
if db_item.image_id:
|
||||||
old_image = session.get(Image, db_item.image_id)
|
old_image = session.get(Image, db_item.image_id)
|
||||||
try:
|
try:
|
||||||
remove_image(old_image.filename)
|
|
||||||
session.delete(old_image)
|
session.delete(old_image)
|
||||||
db_item.image_id = None
|
db_item.image_id = None
|
||||||
session.refresh(db_item)
|
session.refresh(db_item)
|
||||||
@ -465,7 +465,6 @@ def update_tripitem(
|
|||||||
if getattr(db_item, "image_id", None):
|
if getattr(db_item, "image_id", None):
|
||||||
old_image = session.get(Image, db_item.image_id)
|
old_image = session.get(Image, db_item.image_id)
|
||||||
try:
|
try:
|
||||||
remove_image(old_image.filename)
|
|
||||||
session.delete(old_image)
|
session.delete(old_image)
|
||||||
db_item.image_id = None
|
db_item.image_id = None
|
||||||
session.refresh(db_item)
|
session.refresh(db_item)
|
||||||
@ -501,10 +500,10 @@ def update_tripitem(
|
|||||||
|
|
||||||
@router.delete("/{trip_id}/days/{day_id}/items/{item_id}")
|
@router.delete("/{trip_id}/days/{day_id}/items/{item_id}")
|
||||||
def delete_tripitem(
|
def delete_tripitem(
|
||||||
session: SessionDep,
|
|
||||||
trip_id: int,
|
trip_id: int,
|
||||||
day_id: int,
|
day_id: int,
|
||||||
item_id: int,
|
item_id: int,
|
||||||
|
session: SessionDep,
|
||||||
current_user: Annotated[str, Depends(get_current_username)],
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
):
|
):
|
||||||
db_trip = _get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
@ -617,7 +616,11 @@ def create_packing_item(
|
|||||||
data: TripPackingListItemCreate,
|
data: TripPackingListItemCreate,
|
||||||
current_user: Annotated[str, Depends(get_current_username)],
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
) -> TripPackingListItemRead:
|
) -> TripPackingListItemRead:
|
||||||
_get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
item = TripPackingListItem(**data.model_dump(), trip_id=trip_id)
|
item = TripPackingListItem(**data.model_dump(), trip_id=trip_id)
|
||||||
session.add(item)
|
session.add(item)
|
||||||
session.commit()
|
session.commit()
|
||||||
@ -633,7 +636,11 @@ def update_packing_item(
|
|||||||
p_id: int,
|
p_id: int,
|
||||||
current_user: Annotated[str, Depends(get_current_username)],
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
) -> TripPackingListItemRead:
|
) -> TripPackingListItemRead:
|
||||||
_get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
db_item = session.exec(
|
db_item = session.exec(
|
||||||
select(TripPackingListItem).where(
|
select(TripPackingListItem).where(
|
||||||
TripPackingListItem.id == p_id, TripPackingListItem.trip_id == trip_id
|
TripPackingListItem.id == p_id, TripPackingListItem.trip_id == trip_id
|
||||||
@ -660,7 +667,11 @@ def delete_packing_item(
|
|||||||
p_id: int,
|
p_id: int,
|
||||||
current_user: Annotated[str, Depends(get_current_username)],
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
):
|
):
|
||||||
_get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
item = session.exec(
|
item = session.exec(
|
||||||
select(TripPackingListItem).where(
|
select(TripPackingListItem).where(
|
||||||
TripPackingListItem.id == p_id, TripPackingListItem.trip_id == trip_id
|
TripPackingListItem.id == p_id, TripPackingListItem.trip_id == trip_id
|
||||||
@ -706,7 +717,11 @@ def create_checklist_item(
|
|||||||
data: TripChecklistItemCreate,
|
data: TripChecklistItemCreate,
|
||||||
current_user: Annotated[str, Depends(get_current_username)],
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
) -> TripChecklistItemRead:
|
) -> TripChecklistItemRead:
|
||||||
_get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
item = TripChecklistItem(**data.model_dump(), trip_id=trip_id)
|
item = TripChecklistItem(**data.model_dump(), trip_id=trip_id)
|
||||||
session.add(item)
|
session.add(item)
|
||||||
session.commit()
|
session.commit()
|
||||||
@ -722,7 +737,11 @@ def update_checklist_item(
|
|||||||
id: int,
|
id: int,
|
||||||
current_user: Annotated[str, Depends(get_current_username)],
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
) -> TripChecklistItemRead:
|
) -> TripChecklistItemRead:
|
||||||
_get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
db_item = session.exec(
|
db_item = session.exec(
|
||||||
select(TripChecklistItem).where(TripChecklistItem.id == id, TripChecklistItem.trip_id == trip_id)
|
select(TripChecklistItem).where(TripChecklistItem.id == id, TripChecklistItem.trip_id == trip_id)
|
||||||
).one_or_none()
|
).one_or_none()
|
||||||
@ -747,7 +766,11 @@ def delete_checklist_item(
|
|||||||
id: int,
|
id: int,
|
||||||
current_user: Annotated[str, Depends(get_current_username)],
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
):
|
):
|
||||||
_get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
item = session.exec(
|
item = session.exec(
|
||||||
select(TripChecklistItem).where(
|
select(TripChecklistItem).where(
|
||||||
TripChecklistItem.id == id,
|
TripChecklistItem.id == id,
|
||||||
@ -787,6 +810,9 @@ def invite_trip_member(
|
|||||||
) -> TripMemberRead:
|
) -> TripMemberRead:
|
||||||
db_trip = _get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
if db_trip.user == data.user:
|
if db_trip.user == data.user:
|
||||||
raise HTTPException(status_code=409, detail="The resource already exists")
|
raise HTTPException(status_code=409, detail="The resource already exists")
|
||||||
|
|
||||||
@ -821,6 +847,9 @@ def delete_trip_member(
|
|||||||
):
|
):
|
||||||
db_trip = _get_verified_trip(session, trip_id, current_user)
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
if current_user == db_trip.user and current_user == username:
|
if current_user == db_trip.user and current_user == username:
|
||||||
raise HTTPException(status_code=400, detail="Bad request")
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
@ -884,3 +913,71 @@ def decline_invite(
|
|||||||
session.delete(db_member)
|
session.delete(db_member)
|
||||||
session.commit()
|
session.commit()
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{trip_id}/attachments", response_model=TripAttachmentRead)
|
||||||
|
async def create_trip_attachment(
|
||||||
|
trip_id: int,
|
||||||
|
session: SessionDep,
|
||||||
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
|
file: UploadFile = File(...),
|
||||||
|
):
|
||||||
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
|
db_attachment = TripAttachment(
|
||||||
|
filename=file.filename,
|
||||||
|
content_type=file.content_type,
|
||||||
|
file_size=file.size,
|
||||||
|
uploaded_by=current_user,
|
||||||
|
trip_id=trip_id,
|
||||||
|
)
|
||||||
|
stored_filename = await save_attachment(trip_id, file)
|
||||||
|
if not stored_filename:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
|
db_attachment.stored_filename = stored_filename
|
||||||
|
session.add(db_attachment)
|
||||||
|
session.commit()
|
||||||
|
session.refresh(db_attachment)
|
||||||
|
return TripAttachmentRead.serialize(db_attachment)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{trip_id}/attachments/{attachment_id}/download")
|
||||||
|
async def download_trip_attachment(
|
||||||
|
session: SessionDep,
|
||||||
|
trip_id: int,
|
||||||
|
attachment_id: int,
|
||||||
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
|
):
|
||||||
|
_get_verified_trip(session, trip_id, current_user)
|
||||||
|
attachment = session.get(TripAttachment, attachment_id)
|
||||||
|
if not attachment or attachment.trip_id != trip_id:
|
||||||
|
raise HTTPException(status_code=404, detail="Attachment not found")
|
||||||
|
|
||||||
|
file_path = attachments_trip_folder_path(trip_id) / attachment.stored_filename
|
||||||
|
if not file_path.exists():
|
||||||
|
raise HTTPException(status_code=404, detail="Attachment not found")
|
||||||
|
|
||||||
|
return FileResponse(path=file_path, filename=attachment.filename, media_type="application/pdf")
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/{trip_id}/attachments/{attachment_id}")
|
||||||
|
async def delete_trip_attachment(
|
||||||
|
session: SessionDep,
|
||||||
|
trip_id: int,
|
||||||
|
attachment_id: int,
|
||||||
|
current_user: Annotated[str, Depends(get_current_username)],
|
||||||
|
):
|
||||||
|
db_trip = _get_verified_trip(session, trip_id, current_user)
|
||||||
|
if db_trip.archived:
|
||||||
|
raise HTTPException(status_code=400, detail="Bad request")
|
||||||
|
|
||||||
|
attachment = session.get(TripAttachment, attachment_id)
|
||||||
|
if not attachment or attachment.trip_id != trip_id:
|
||||||
|
raise HTTPException(status_code=404, detail="Attachment not found")
|
||||||
|
|
||||||
|
session.delete(attachment)
|
||||||
|
session.commit()
|
||||||
|
return {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user