mirror of
https://github.com/ae-utbm/sith.git
synced 2025-04-16 02:50:22 +00:00
Use UploadedImage to check image correctness and better error responses
This commit is contained in:
parent
67bc49fb21
commit
6e39b59dd5
31
core/api.py
31
core/api.py
@ -1,15 +1,14 @@
|
|||||||
from typing import Annotated
|
from typing import Annotated, Any, Literal
|
||||||
|
|
||||||
import annotated_types
|
import annotated_types
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from ninja import Query, UploadedFile
|
from ninja import File, Query
|
||||||
from ninja_extra import ControllerBase, api_controller, paginate, route
|
from ninja_extra import ControllerBase, api_controller, paginate, route
|
||||||
from ninja_extra.exceptions import PermissionDenied
|
from ninja_extra.exceptions import PermissionDenied
|
||||||
from ninja_extra.pagination import PageNumberPaginationExtra
|
from ninja_extra.pagination import PageNumberPaginationExtra
|
||||||
from ninja_extra.schemas import PaginatedResponseSchema
|
from ninja_extra.schemas import PaginatedResponseSchema
|
||||||
from PIL import UnidentifiedImageError
|
|
||||||
|
|
||||||
from club.models import Mailing
|
from club.models import Mailing
|
||||||
from core.auth.api_permissions import CanAccessLookup, CanView, IsOldSubscriber
|
from core.auth.api_permissions import CanAccessLookup, CanView, IsOldSubscriber
|
||||||
@ -20,6 +19,7 @@ from core.schemas import (
|
|||||||
MarkdownSchema,
|
MarkdownSchema,
|
||||||
SithFileSchema,
|
SithFileSchema,
|
||||||
UploadedFileSchema,
|
UploadedFileSchema,
|
||||||
|
UploadedImage,
|
||||||
UserFamilySchema,
|
UserFamilySchema,
|
||||||
UserFilterSchema,
|
UserFilterSchema,
|
||||||
UserProfileSchema,
|
UserProfileSchema,
|
||||||
@ -39,25 +39,18 @@ class MarkdownController(ControllerBase):
|
|||||||
class UploadController(ControllerBase):
|
class UploadController(ControllerBase):
|
||||||
@route.post(
|
@route.post(
|
||||||
"/image",
|
"/image",
|
||||||
response=UploadedFileSchema,
|
response={
|
||||||
|
200: UploadedFileSchema,
|
||||||
|
422: dict[Literal["detail"], list[dict[str, Any]]],
|
||||||
|
403: dict[Literal["detail"], str],
|
||||||
|
},
|
||||||
permissions=[IsOldSubscriber],
|
permissions=[IsOldSubscriber],
|
||||||
url_name="quick_upload_image",
|
url_name="quick_upload_image",
|
||||||
)
|
)
|
||||||
def upload_image(self, file: UploadedFile):
|
def upload_image(self, file: File[UploadedImage]):
|
||||||
if file.content_type.split("/")[0] != "image":
|
image = QuickUploadImage.create_from_uploaded(
|
||||||
return self.create_response(
|
file, uploader=self.context.request.user
|
||||||
message=f"{file.name} isn't a file image", status_code=415
|
)
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
image = QuickUploadImage.create_from_uploaded(
|
|
||||||
file, uploader=self.context.request.user
|
|
||||||
)
|
|
||||||
except UnidentifiedImageError:
|
|
||||||
return self.create_response(
|
|
||||||
message=f"{file.name} can't be processed", status_code=415
|
|
||||||
)
|
|
||||||
|
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,11 @@ import { inheritHtmlElement, registerComponent } from "#core:utils/web-component
|
|||||||
import type CodeMirror from "codemirror";
|
import type CodeMirror from "codemirror";
|
||||||
// biome-ignore lint/style/useNamingConvention: This is how they called their namespace
|
// biome-ignore lint/style/useNamingConvention: This is how they called their namespace
|
||||||
import EasyMDE from "easymde";
|
import EasyMDE from "easymde";
|
||||||
import { markdownRenderMarkdown, uploadUploadImage } from "#openapi";
|
import {
|
||||||
|
type UploadUploadImageErrors,
|
||||||
|
markdownRenderMarkdown,
|
||||||
|
uploadUploadImage,
|
||||||
|
} from "#openapi";
|
||||||
|
|
||||||
const loadEasyMde = (textarea: HTMLTextAreaElement) => {
|
const loadEasyMde = (textarea: HTMLTextAreaElement) => {
|
||||||
const easymde = new EasyMDE({
|
const easymde = new EasyMDE({
|
||||||
@ -21,8 +25,18 @@ const loadEasyMde = (textarea: HTMLTextAreaElement) => {
|
|||||||
file: file,
|
file: file,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (response.response.status !== 200) {
|
if (!response.response.ok) {
|
||||||
onError(gettext("Invalid file"));
|
if (response.response.status === 422) {
|
||||||
|
onError(
|
||||||
|
(response.error as UploadUploadImageErrors[422]).detail
|
||||||
|
.map((err: Record<"ctx", Record<"error", string>>) => err.ctx.error)
|
||||||
|
.join(" ; "),
|
||||||
|
);
|
||||||
|
} else if (response.response.status === 403) {
|
||||||
|
onError(gettext("Not authorized, you need to have subscribed at least once"));
|
||||||
|
} else {
|
||||||
|
onError(gettext("Could not upload image"));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onSuccess(response.data.href);
|
onSuccess(response.data.href);
|
||||||
|
@ -306,19 +306,19 @@ def test_apply_rights_recursively():
|
|||||||
SimpleUploadedFile(
|
SimpleUploadedFile(
|
||||||
"test.jpg", content=b"invalid", content_type="image/jpg"
|
"test.jpg", content=b"invalid", content_type="image/jpg"
|
||||||
),
|
),
|
||||||
415,
|
422,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
lambda: old_subscriber_user.make(),
|
lambda: old_subscriber_user.make(),
|
||||||
SimpleUploadedFile(
|
SimpleUploadedFile(
|
||||||
"test.jpg", content=RED_PIXEL_PNG, content_type="invalid"
|
"test.jpg", content=RED_PIXEL_PNG, content_type="invalid"
|
||||||
),
|
),
|
||||||
415,
|
200, # PIL can guess
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
lambda: old_subscriber_user.make(),
|
lambda: old_subscriber_user.make(),
|
||||||
SimpleUploadedFile("test.jpg", content=b"invalid", content_type="invalid"),
|
SimpleUploadedFile("test.jpg", content=b"invalid", content_type="invalid"),
|
||||||
415,
|
422,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-08 11:42+0200\n"
|
"POT-Creation-Date: 2025-04-09 22:12+0200\n"
|
||||||
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
||||||
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@ -64,12 +64,18 @@ msgid "No results found"
|
|||||||
msgstr "Aucun résultat trouvé"
|
msgstr "Aucun résultat trouvé"
|
||||||
|
|
||||||
#: core/static/bundled/core/components/easymde-index.ts
|
#: core/static/bundled/core/components/easymde-index.ts
|
||||||
msgid "Invalid file"
|
msgid "Not authorized, you need to have subscribed at least once"
|
||||||
msgstr "Fichier invalide"
|
msgstr ""
|
||||||
|
|
||||||
|
#: core/static/bundled/core/components/easymde-index.ts
|
||||||
|
msgid "Could not upload image"
|
||||||
|
msgstr "L'image n'a pas pu être téléversée"
|
||||||
|
|
||||||
#: core/static/bundled/core/components/easymde-index.ts
|
#: core/static/bundled/core/components/easymde-index.ts
|
||||||
msgid "Attach files by drag and dropping or pasting from clipboard."
|
msgid "Attach files by drag and dropping or pasting from clipboard."
|
||||||
msgstr "Ajoutez des fichiez en glissant déposant ou collant depuis votre presse papier."
|
msgstr ""
|
||||||
|
"Ajoutez des fichiez en glissant déposant ou collant depuis votre presse "
|
||||||
|
"papier."
|
||||||
|
|
||||||
#: core/static/bundled/core/components/easymde-index.ts
|
#: core/static/bundled/core/components/easymde-index.ts
|
||||||
msgid "Drop image to upload it."
|
msgid "Drop image to upload it."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user