diff --git a/apps/blog/api/views.py b/apps/blog/api/views.py index fd9ace0..2853951 100644 --- a/apps/blog/api/views.py +++ b/apps/blog/api/views.py @@ -94,6 +94,18 @@ def _validate_asset_file(file: UploadedFile) -> str | None: return None +def _validate_featured_image(file: UploadedFile) -> str | None: + suffix = Path(file.name).suffix.lower() + content_type = (file.content_type or mimetypes.guess_type(file.name)[0] or "").lower() + if not content_type.startswith("image/") and suffix not in IMAGE_EXTENSIONS: + return "Featured image must be an image file." + + image_max_size_mb = getattr(settings, "BLOG_IMAGE_ASSET_MAX_SIZE_MB", 10) + if file.size > image_max_size_mb * 1024 * 1024: + return f"Featured image size must be less than {image_max_size_mb}MB." + return None + + def _apply_post_payload(post: Post, data: PostCreateSchema, *, user, allow_status: bool = False) -> Post: payload = data.dict(exclude_unset=True) tag_ids = payload.pop("tag_ids", None) @@ -190,6 +202,32 @@ def update_admin_post(request, post_id: int, data: PostCreateSchema): return 400, {"error": "Failed to update post", "details": str(exc)} +@blog_router.post("/admin/posts/{post_id}/featured-image", response={200: PostDetailSchema, 400: ErrorSchema, 403: ErrorSchema}, auth=jwt_auth) +def upload_post_featured_image(request, post_id: int, file: UploadedFile = File(...)): + post = get_object_or_404(Post, id=post_id) + if not can_edit_post(request.auth, post): + return 403, {"error": "Permission denied"} + + error = _validate_featured_image(file) + if error: + return 400, {"error": error} + + post.featured_image = file + post.save(update_fields=["featured_image", "updated_at"]) + return 200, _post_queryset().get(pk=post.pk) + + +@blog_router.delete("/admin/posts/{post_id}/featured-image", response={200: PostDetailSchema, 403: ErrorSchema}, auth=jwt_auth) +def delete_post_featured_image(request, post_id: int): + post = get_object_or_404(Post, id=post_id) + if not can_edit_post(request.auth, post): + return 403, {"error": "Permission denied"} + + post.featured_image = None + post.save(update_fields=["featured_image", "updated_at"]) + return 200, _post_queryset().get(pk=post.pk) + + @blog_router.post("/admin/posts/{post_id}/submit", response={200: PostDetailSchema, 403: ErrorSchema}, auth=jwt_auth) def submit_post_for_review(request, post_id: int): post = get_object_or_404(Post, id=post_id)