From 29e9243794a9b4c02e0f7b1593fc7f77b4b2f712 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 4 May 2021 02:43:55 +0100 Subject: [PATCH] bundles download: Token as query parameter rather than in path Signed-off-by: Ian Jackson --- daemon/main.rs | 32 ++++++++++++++++++++++++++++---- src/bundles.rs | 2 +- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/daemon/main.rs b/daemon/main.rs index e78deef4..8c77888d 100644 --- a/daemon/main.rs +++ b/daemon/main.rs @@ -174,6 +174,15 @@ impl<'r, T> FromParam<'r> for Parse } } +pub struct BundleToken(pub AssetUrlToken); +impl<'r> FromFormValue<'r> for BundleToken { + type Error = BundleDownloadError; + #[throws(BundleDownloadError)] + fn from_form_value(param: &'r RawStr) -> Self { + BundleToken(param.as_str().parse()?) + } +} + #[get("/_/updates?&")] #[throws(OER)] fn updates<'r>(ctoken: InstanceAccess, gen: u64, @@ -202,18 +211,33 @@ fn resource<'r>(leaf: CheckedResourceLeaf) -> impl Responder<'r> { } #[derive(Error,Debug)] -enum BundleDownloadError { +pub enum BundleDownloadError { BadAssetUrlToken(#[from] BadAssetUrlToken), NotFound, IE(#[from] IE), } display_as_debug!{BundleDownloadError} -#[get("/_/bundle///")] +impl From<&BundleDownloadError> for rocket::http::Status { + fn from(e: &BundleDownloadError) -> rocket::http::Status { + use BundleDownloadError as B; + use rocket::http::Status as S; + match e { + B::NotFound => S::NotFound, + B::BadAssetUrlToken(_) => S::Forbidden, + B::IE(_) => S::InternalServerError, + } + } +} + +#[get("/_/bundle//")] #[throws(BundleDownloadError)] fn bundle<'r>(instance: Parse, id: Parse, - token: Parse) -> impl Responder<'r> { + token: WholeQueryString) + -> impl Responder<'r> +{ + if_let!{ Some(BundleToken(token)) = token.0; else throw!(BadAssetUrlToken) }; let instance = &instance.0; let id = id.0; let gref = Instance::lookup_by_name_unauth(instance) @@ -221,7 +245,7 @@ fn bundle<'r>(instance: Parse, let auth = { let gref = gref.by_ref(Authorisation::authorise_any()); let ig = gref.lock().map_err(|_| BadAssetUrlToken)?; - ig.asset_url_key.check("bundle", &(instance, id), &token.0)? + ig.asset_url_key.check("bundle", &(instance, id), &token)? }.map(|(_,id)| id); let f = id.open_by_name(instance, auth).map_err(IE::from)?; let ctype = match id.kind { diff --git a/src/bundles.rs b/src/bundles.rs index fda794f5..f4ed31fd 100644 --- a/src/bundles.rs +++ b/src/bundles.rs @@ -435,7 +435,7 @@ impl MgmtBundleList { let BundleMeta { title } = meta; let title = Html::from_txt(title); let token = id.token(ig); - let url = hformat!("/_/bundle/{}/{}/{}", &*ig.name, &id, &token); + let url = hformat!("/_/bundle/{}/{}?{}", &*ig.name, &id, &token); let id = hformat!("{}", id); Some(RenderBundle { id, url, title }) }).collect(); -- 2.30.2