use std::sync::Arc;
use topcoat::{
context::Cx,
router::{
Body, RouteFuture,
error::{forbidden, not_found},
path_param_segment,
},
view::BoxView,
};
use super::actions::{input_options, run_header};
use crate::{
Page,
page::{MountedPage, mounted_page},
topcoat_compat::async_page,
};
fn admitted<P: Page>(cx: &Cx) -> topcoat::Result<&Arc<MountedPage>> {
crate::auth::guard(cx)?;
let page = mounted_page::<P>(cx).ok_or_else(not_found)?;
if !page.admits(cx) {
return Err(forbidden().into());
}
Ok(page)
}
pub(super) fn page_handler<P: Page>(cx: &Cx, _body: Body) -> BoxView<'_> {
async_page(async move {
admitted::<P>(cx)?;
P::render(cx).await
})
}
pub(super) fn page_action<P: Page>(cx: &Cx, body: Body) -> BoxView<'_> {
async_page(async move {
let page = admitted::<P>(cx)?;
let Some(action) = page
.header_actions
.find(path_param_segment(cx, "action"))
.copied()
else {
return Err(not_found().into());
};
if !(action.can_run)(cx) {
return Err(forbidden().into());
}
let Some(home) = crate::panel::url::page::<P>(cx) else {
return Err(not_found().into());
};
run_header(cx, body, action, &home, None).await
})
}
pub(super) fn page_action_options<P: Page>(cx: &Cx, _body: Body) -> RouteFuture<'_> {
Box::pin(async move {
let page = admitted::<P>(cx)?;
let Some(action) = page.header_actions.find(path_param_segment(cx, "action")) else {
return Err(not_found().into());
};
if !(action.can_run)(cx) {
return Err(forbidden().into());
}
input_options(cx, action.input).await
})
}
#[cfg(test)]
mod tests;