chiark / gitweb /
bundles download: Token as query parameter rather than in path
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 4 May 2021 01:43:55 +0000 (02:43 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 4 May 2021 11:28:51 +0000 (12:28 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/main.rs
src/bundles.rs

index e78deef4b141c29636f1e29f58ce249641116596..8c77888d4a29fae46da6287c77ea3e53a6009de6 100644 (file)
@@ -174,6 +174,15 @@ impl<'r, T> FromParam<'r> for Parse<T>
   }
 }
 
+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?<ctoken>&<gen>")]
 #[throws(OER)]
 fn updates<'r>(ctoken: InstanceAccess<ClientId>, 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/<instance>/<id>/<token>")]
+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/<instance>/<id>")]
 #[throws(BundleDownloadError)]
 fn bundle<'r>(instance: Parse<InstanceName>,
               id: Parse<bundles::Id>,
-              token: Parse<AssetUrlToken>) -> impl Responder<'r> {
+              token: WholeQueryString<BundleToken>)
+              -> 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<InstanceName>,
   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 {
index fda794f586bff31eac15e84355644cc983914726..f4ed31fd865eb0492627d51dfe416242d302474c 100644 (file)
@@ -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();