recipes/backend/src/services/mod.rs

167 lines
4.3 KiB
Rust

use askama::Template;
use axum::{
body, debug_handler,
extract::{Extension, Query, Request, State},
http::{StatusCode, header},
middleware::Next,
response::{Html, IntoResponse, Response},
};
use serde::{self, Deserialize};
use crate::{
app::{AppState, Context, Result},
data::db,
html_templates::*,
log::Log,
translation::Sentence,
};
pub mod fragments;
pub mod recipe;
pub mod ron;
pub mod user;
// Will embed RON error in HTML page.
pub async fn ron_error_to_html(
Extension(context): Extension<Context>,
req: Request,
next: Next,
) -> Result<Response> {
let response = next.run(req).await;
if let Some(content_type) = response.headers().get(header::CONTENT_TYPE) {
if content_type == common::consts::MIME_TYPE_RON {
let message = match body::to_bytes(response.into_body(), usize::MAX).await {
Ok(bytes) => String::from_utf8(bytes.to_vec()).unwrap_or_default(),
Err(error) => error.to_string(),
};
return Ok(Html(
MessageTemplate {
context,
message: &message,
as_code: true,
}
.render()?,
)
.into_response());
}
}
Ok(response)
}
///// HOME /////
#[debug_handler]
pub async fn home_page(
State(connection): State<db::Connection>,
Extension(context): Extension<Context>,
) -> Result<impl IntoResponse> {
Ok(Html(
HomeTemplate {
recipes: Recipes::new(
connection,
&context.user,
context.tr.current_lang_code(),
None,
)
.await?,
context,
}
.render()?,
))
}
///// DEV_PANEL /////
#[debug_handler(state = AppState)]
pub async fn dev_panel(
State(connection): State<db::Connection>,
Extension(context): Extension<Context>,
) -> Result<Response> {
if context.user.is_some() && context.user.as_ref().unwrap().is_admin {
Ok(Html(
DevPanelTemplate {
recipes: Recipes::new(
connection,
&context.user,
context.tr.current_lang_code(),
None,
)
.await?,
context,
}
.render()?,
)
.into_response())
} else {
Ok((
StatusCode::UNAUTHORIZED,
Html(
MessageTemplate::new(context.tr.t(Sentence::ActionNotAuthorized), context)
.render()?,
),
)
.into_response())
}
}
///// LOGS /////
#[derive(Deserialize)]
pub struct LogsParams {
#[serde(default)]
pub log_file: String,
}
#[debug_handler(state = AppState)]
pub async fn logs(
State(connection): State<db::Connection>,
State(log): State<Log>,
Extension(context): Extension<Context>,
Query(params): Query<LogsParams>,
) -> Result<Response> {
if context.user.is_some() && context.user.as_ref().unwrap().is_admin {
Ok(Html(
LogsTemplate {
recipes: Recipes::new(
connection,
&context.user,
context.tr.current_lang_code(),
None,
)
.await?,
context,
current_log_file: match (
params.log_file.is_empty(),
log.file_names().unwrap_or_default(),
) {
(true, file_names) if !file_names.is_empty() => file_names[0].clone(),
_ => params.log_file.clone(),
},
log,
}
.render()?,
)
.into_response())
} else {
Ok((
StatusCode::UNAUTHORIZED,
Html(
MessageTemplate::new(context.tr.t(Sentence::ActionNotAuthorized), context)
.render()?,
),
)
.into_response())
}
}
///// 404 /////
#[debug_handler]
pub async fn not_found(Extension(context): Extension<Context>) -> Result<impl IntoResponse> {
Ok((
StatusCode::NOT_FOUND,
Html(MessageTemplate::new("404: Not found", context).render()?),
))
}