|
|
@@ -1658,13 +1658,17 @@ async def update_archive(
|
|
|
async def toggle_favorite(
|
|
|
archive_id: int,
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_UPDATE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_UPDATE_ALL,
|
|
|
+ Permission.ARCHIVES_UPDATE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Toggle favorite status for an archive."""
|
|
|
+ user, can_modify_all = auth_result
|
|
|
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
|
|
- archive = result.scalar_one_or_none()
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(result.scalar_one_or_none(), user, can_modify_all)
|
|
|
|
|
|
archive.is_favorite = not archive.is_favorite
|
|
|
await db.commit()
|
|
|
@@ -2213,13 +2217,17 @@ async def get_timelapse(
|
|
|
async def delete_timelapse(
|
|
|
archive_id: int,
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_DELETE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_DELETE_ALL,
|
|
|
+ Permission.ARCHIVES_DELETE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Remove the timelapse video from an archive."""
|
|
|
+ user, can_modify_all = auth_result
|
|
|
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
|
|
- archive = result.scalar_one_or_none()
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(result.scalar_one_or_none(), user, can_modify_all)
|
|
|
|
|
|
if not archive.timelapse_path:
|
|
|
raise HTTPException(404, "No timelapse attached to this archive")
|
|
|
@@ -2727,13 +2735,17 @@ async def upload_photo(
|
|
|
archive_id: int,
|
|
|
file: UploadFile = File(...),
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_UPDATE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_UPDATE_ALL,
|
|
|
+ Permission.ARCHIVES_UPDATE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Upload a photo of the printed result."""
|
|
|
+ user, can_modify_all = auth_result
|
|
|
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
|
|
- archive = result.scalar_one_or_none()
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(result.scalar_one_or_none(), user, can_modify_all)
|
|
|
|
|
|
if not file.filename or not file.filename.lower().endswith((".jpg", ".jpeg", ".png", ".webp")):
|
|
|
raise HTTPException(400, "File must be an image (.jpg, .jpeg, .png, .webp)")
|
|
|
@@ -2817,13 +2829,17 @@ async def delete_photo(
|
|
|
archive_id: int,
|
|
|
filename: str,
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_DELETE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_DELETE_ALL,
|
|
|
+ Permission.ARCHIVES_DELETE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Delete a photo."""
|
|
|
+ user, can_modify_all = auth_result
|
|
|
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
|
|
- archive = result.scalar_one_or_none()
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(result.scalar_one_or_none(), user, can_modify_all)
|
|
|
|
|
|
if not archive.photos or filename not in archive.photos:
|
|
|
raise HTTPException(404, "Photo not found")
|
|
|
@@ -4091,15 +4107,19 @@ async def update_project_page(
|
|
|
archive_id: int,
|
|
|
update_data: dict,
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_UPDATE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_UPDATE_ALL,
|
|
|
+ Permission.ARCHIVES_UPDATE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Update project page metadata in the 3MF file."""
|
|
|
from backend.app.services.archive import ProjectPageParser
|
|
|
|
|
|
+ user, can_modify_all = auth_result
|
|
|
service = ArchiveService(db)
|
|
|
- archive = await service.get_archive(archive_id)
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(await service.get_archive(archive_id), user, can_modify_all)
|
|
|
|
|
|
file_path = settings.base_dir / archive.file_path
|
|
|
if not file_path.is_file():
|
|
|
@@ -4209,13 +4229,17 @@ async def upload_source_3mf(
|
|
|
archive_id: int,
|
|
|
file: UploadFile = File(...),
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_UPDATE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_UPDATE_ALL,
|
|
|
+ Permission.ARCHIVES_UPDATE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Upload the original source 3MF project file for an archive."""
|
|
|
+ user, can_modify_all = auth_result
|
|
|
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
|
|
- archive = result.scalar_one_or_none()
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(result.scalar_one_or_none(), user, can_modify_all)
|
|
|
|
|
|
if not file.filename or not file.filename.endswith(".3mf"):
|
|
|
raise HTTPException(400, "File must be a .3mf file")
|
|
|
@@ -4470,13 +4494,17 @@ async def upload_source_3mf_by_name(
|
|
|
async def delete_source_3mf(
|
|
|
archive_id: int,
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_DELETE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_DELETE_ALL,
|
|
|
+ Permission.ARCHIVES_DELETE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Delete the source 3MF project file from an archive."""
|
|
|
+ user, can_modify_all = auth_result
|
|
|
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
|
|
- archive = result.scalar_one_or_none()
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(result.scalar_one_or_none(), user, can_modify_all)
|
|
|
|
|
|
if not archive.source_3mf_path:
|
|
|
raise HTTPException(404, "No source 3MF attached to this archive")
|
|
|
@@ -4503,13 +4531,17 @@ async def upload_f3d(
|
|
|
archive_id: int,
|
|
|
file: UploadFile = File(...),
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_UPDATE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_UPDATE_ALL,
|
|
|
+ Permission.ARCHIVES_UPDATE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Upload a Fusion 360 design file for an archive."""
|
|
|
+ user, can_modify_all = auth_result
|
|
|
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
|
|
- archive = result.scalar_one_or_none()
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(result.scalar_one_or_none(), user, can_modify_all)
|
|
|
|
|
|
if not file.filename or not file.filename.endswith(".f3d"):
|
|
|
raise HTTPException(400, "File must be a .f3d file")
|
|
|
@@ -4583,13 +4615,17 @@ async def download_f3d(
|
|
|
async def delete_f3d(
|
|
|
archive_id: int,
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
- _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_DELETE_OWN),
|
|
|
+ auth_result: tuple[User | None, bool] = Depends(
|
|
|
+ require_ownership_permission(
|
|
|
+ Permission.ARCHIVES_DELETE_ALL,
|
|
|
+ Permission.ARCHIVES_DELETE_OWN,
|
|
|
+ )
|
|
|
+ ),
|
|
|
):
|
|
|
"""Delete the Fusion 360 design file from an archive."""
|
|
|
+ user, can_modify_all = auth_result
|
|
|
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
|
|
- archive = result.scalar_one_or_none()
|
|
|
- if not archive:
|
|
|
- raise HTTPException(404, "Archive not found")
|
|
|
+ archive = _ensure_archive_visible(result.scalar_one_or_none(), user, can_modify_all)
|
|
|
|
|
|
if not archive.f3d_path:
|
|
|
raise HTTPException(404, "No F3D file attached to this archive")
|