Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 31 additions & 27 deletions editoast/openapi.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 10 additions & 11 deletions editoast/src/views/fonts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@ use axum::extract::Path;
use axum::extract::Request;
use axum::extract::State;
use axum::response::IntoResponse;
use editoast_derive::EditoastError;
use editoast_derive::ViewError;
use thiserror::Error;
use tower::ServiceExt as _;
use tower_http::services::ServeFile;

use crate::AppState;
use crate::error::Result;

#[derive(Debug, Error, EditoastError)]
#[editoast_error(base_id = "fonts")]
enum FontErrors {
#[error("File '{file}' not found")]
#[editoast_error(status = 404)]
FileNotFound { file: String },
#[derive(Debug, Error, ViewError)]
#[error("File '{file}' not found")]
#[view_error(status = NOT_FOUND, context, path = fonts::file_not_found)]
pub(in crate::views) struct FileNotFound {
file: String,
}

/// This endpoint is used by map libre to retrieve the fonts. They are separated by font and unicode block
Expand All @@ -29,27 +28,27 @@ enum FontErrors {
),
responses(
(status = 200, description = "Glyphs in PBF format of the font at the requested unicode block"),
(status = 404, description = "Font not found"),
FileNotFound,
),
)]
pub(in crate::views) async fn fonts(
Path((font, file_name)): Path<(String, String)>,
State(AppState { config, .. }): State<AppState>,
request: Request,
) -> Result<impl IntoResponse> {
) -> Result<impl IntoResponse, FileNotFound> {
let path = config
.dynamic_assets_path
.join(format!("fonts/glyphs/{font}/{file_name}"));

if !path.is_file() {
return Err(FontErrors::FileNotFound { file: file_name }.into());
return Err(FileNotFound { file: file_name });
}

// Avoid path traversal attack by ensuring the path is within the dynamic assets directory
let canonical_path = path.canonicalize().unwrap();
let canonical_assets_path = config.dynamic_assets_path.canonicalize().unwrap();
if !canonical_path.starts_with(&canonical_assets_path) {
return Err(FontErrors::FileNotFound { file: file_name }.into());
return Err(FileNotFound { file: file_name });
}

Ok(ServeFile::new(&path).oneshot(request).await)
Expand Down
8 changes: 5 additions & 3 deletions front/public/locales/en/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,21 @@
"MqClientError": "Core: MQ client error",
"UnparsableErrorOutput": "Core returned an error in an unknown format"
},
"database": {
"internal": "Internal error (database)"
},
"delimited_area": {
"InvalidLocations": "Some locations are invalid"
},
"document": {
"Database": "Internal error (database)",
"NotFound": "Document '{{document_key}}' not found"
"not_found": "Document '{{document_key}}' not found"
},
"electrical_profiles": {
"Database": "Internal error (database)",
"NotFound": "Electrical Profile Set '{{electrical_profile_set_id}}', could not be found"
},
"fonts": {
"FileNotFound": "File for the requested font not found"
"file_not_found": "File for the requested font not found"
},
"geometry": {
"UnexpectedGeometry": "Expected geometry {{expected}} but got {{actual}}"
Expand Down
8 changes: 5 additions & 3 deletions front/public/locales/fr/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,21 @@
"MqClientError": "Core : erreur du client MQ",
"UnparsableErrorOutput": "Core : a renvoyé une erreur dans un format inconnu"
},
"database": {
"internal": "Erreur interne (base de données)"
},
"delimited_area": {
"InvalidLocations": "Certaines localisations sont invalides"
},
"document": {
"Database": "Erreur interne (base de données)",
"NotFound": "Document '{{document_key}}' non trouvé"
"not_found": "Document '{{document_key}}' non trouvé"
},
"electrical_profiles": {
"Database": "Erreur interne (base de données)",
"NotFound": "Profil électrique '{{electrical_profile_set_id}}' non trouvé"
},
"fonts": {
"FileNotFound": "Fichier pour la police de charactère demandée non trouvé"
"file_not_found": "Fichier pour la police de caractères demandée non trouvé"
},
"geometry": {
"UnexpectedGeometry": "Géometrie {{expected}} attendue mais {{actual}} reçue"
Expand Down
16 changes: 0 additions & 16 deletions osrd_schemas/osrd_schemas/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,20 +984,6 @@ class EditoastErrorInvalidInput(BaseModel):
)


class EditoastFontErrorsFileNotFoundContext(BaseModel):
file: str


class EditoastFontErrorsFileNotFound(BaseModel):
context: Annotated[
EditoastFontErrorsFileNotFoundContext | None,
Field(title="EditoastFontErrorsFileNotFoundContext"),
] = None
message: str
status: Literal[404] = 404
type: Literal["editoast:fonts:FileNotFound"] = "editoast:fonts:FileNotFound"


class EditoastGeometryErrorUnexpectedGeometryContext(BaseModel):
actual: str
expected: str
Expand Down Expand Up @@ -4994,7 +4980,6 @@ class EditoastError(
| EditoastErrorDatabase
| EditoastErrorInfraNotFound
| EditoastErrorInvalidInput
| EditoastFontErrorsFileNotFound
| EditoastGeometryErrorUnexpectedGeometry
| EditoastGetObjectsErrorsDuplicateIdsProvided
| EditoastGetObjectsErrorsObjectIdNotFound
Expand Down Expand Up @@ -5172,7 +5157,6 @@ class EditoastError(
| EditoastErrorDatabase
| EditoastErrorInfraNotFound
| EditoastErrorInvalidInput
| EditoastFontErrorsFileNotFound
| EditoastGeometryErrorUnexpectedGeometry
| EditoastGetObjectsErrorsDuplicateIdsProvided
| EditoastGetObjectsErrorsObjectIdNotFound
Expand Down
Loading