Forráskód Böngészése

Check for expired files everywehere, propogate their errors

timvisee 7 éve
szülő
commit
cb2d5f7844

+ 29 - 15
api/src/action/delete.rs

@@ -37,7 +37,9 @@ impl<'a> Delete<'a> {
 
         // Create owned data, to send to the server for authentication
         let data = OwnedData::from(DeleteData::new(), &self.file)
-            .map_err(|err| -> PrepareError { err.into() })?;
+            .map_err(|err| PrepareError::DeleteData(
+                DeleteDataError::Owned(err),
+            ))?;
 
         // Send the delete request
         self.request_delete(client, data).map_err(|err| err.into())
@@ -45,12 +47,12 @@ impl<'a> Delete<'a> {
 
     /// Fetch the authentication nonce for the file from the remote server.
     fn fetch_auth_nonce(&self, client: &Client)
-        -> Result<Vec<u8>, PrepareError>
+        -> Result<Vec<u8>, Error>
     {
         request_nonce(
             client,
             UrlBuilder::download(self.file, false),
-        ).map_err(|err| PrepareError::Auth(err))
+        ).map_err(|err| err.into())
     }
 
     /// Send a request to delete the remote file, with the given data.
@@ -58,7 +60,7 @@ impl<'a> Delete<'a> {
         &self,
         client: &Client,
         data: OwnedData<DeleteData>,
-    ) -> Result<(), DeleteError> {
+    ) -> Result<(), Error> {
         // Get the delete URL, and send the request
         let url = UrlBuilder::api_delete(self.file);
         let response = client.post(url)
@@ -68,7 +70,7 @@ impl<'a> Delete<'a> {
 
         // Ensure the status code is succesful
         ensure_success(&response)
-            .map_err(|err| DeleteError::Response(err))
+            .map_err(|err| err.into())
     }
 }
 
@@ -91,16 +93,25 @@ pub enum Error {
     #[fail(display = "Failed to prepare the action")]
     Prepare(#[cause] PrepareError),
 
-    // /// The given Send file has expired, or did never exist in the first place.
-    // /// Therefore the file could not be downloaded.
-    // #[fail(display = "The file has expired or did never exist")]
-    // Expired,
+    /// The given Send file has expired, or did never exist in the first place.
+    /// Therefore the file could not be downloaded.
+    #[fail(display = "The file has expired or did never exist")]
+    Expired,
 
     /// An error has occurred while sending the filedeletion request.
     #[fail(display = "Failed to send the file deletion request")]
     Delete(#[cause] DeleteError),
 }
 
+impl From<NonceError> for Error {
+    fn from(err: NonceError) -> Error {
+        match err {
+            NonceError::Expired => Error::Expired,
+            err => Error::Prepare(PrepareError::Auth(err)),
+        }
+    }
+}
+
 impl From<PrepareError> for Error {
     fn from(err: PrepareError) -> Error {
         Error::Prepare(err)
@@ -134,12 +145,6 @@ pub enum PrepareError {
     DeleteData(#[cause] DeleteDataError),
 }
 
-impl From<DataError> for PrepareError {
-    fn from(err: DataError) -> PrepareError {
-        PrepareError::DeleteData(DeleteDataError::Owned(err))
-    }
-}
-
 #[derive(Fail, Debug)]
 pub enum DeleteError {
     /// Sending the file deletion request failed.
@@ -150,3 +155,12 @@ pub enum DeleteError {
     #[fail(display = "Bad response from server while deleting file")]
     Response(#[cause] ResponseError),
 }
+
+impl From<ResponseError> for Error {
+    fn from(err: ResponseError) -> Self {
+        match err {
+            ResponseError::Expired => Error::Expired,
+            err => Error::Delete(DeleteError::Response(err)),
+        }
+    }
+}

+ 9 - 8
api/src/action/download.rs

@@ -81,12 +81,7 @@ impl<'a> Download<'a> {
                         self.password.clone(),
                         self.check_exists,
                     )
-                    .invoke(&client)
-                    .map_err(|err| match err {
-                        MetadataError::PasswordRequired => Error::PasswordRequired,
-                        MetadataError::Expired => Error::Expired,
-                        _ => err.into(),
-                    })?
+                    .invoke(&client)?
             };
         key.set_iv(metadata.metadata().iv());
 
@@ -149,6 +144,7 @@ impl<'a> Download<'a> {
             return self.target.clone();
         }
 
+        // TODO: are these todos below already implemented in CLI client?
         // TODO: canonicalize the path when possible
         // TODO: allow using `file.toml` as target without directory indication
         // TODO: return a nice error here as the path may be invalid
@@ -235,7 +231,8 @@ impl<'a> Download<'a> {
             .start(len);
 
         // Write to the output file
-        io::copy(&mut reader, &mut writer).map_err(|_| DownloadError::Download)?;
+        io::copy(&mut reader, &mut writer)
+            .map_err(|_| DownloadError::Download)?;
 
         // Finish
         reporter.lock()
@@ -284,7 +281,11 @@ pub enum Error {
 
 impl From<MetadataError> for Error {
     fn from(err: MetadataError) -> Error {
-        Error::Meta(err)
+        match err {
+            MetadataError::Expired => Error::Expired,
+            MetadataError::PasswordRequired => Error::PasswordRequired,
+            err => Error::Meta(err),
+        }
     }
 }
 

+ 27 - 10
api/src/action/info.rs

@@ -50,12 +50,12 @@ impl<'a> Info<'a> {
 
     /// Fetch the authentication nonce for the file from the remote server.
     fn fetch_auth_nonce(&self, client: &Client)
-        -> Result<Vec<u8>, PrepareError>
+        -> Result<Vec<u8>, Error>
     {
         request_nonce(
             client,
             UrlBuilder::download(self.file, false),
-        ).map_err(|err| PrepareError::Auth(err))
+        ).map_err(|err| err.into())
     }
 
     /// Send the request for fetching the remote file info.
@@ -63,7 +63,7 @@ impl<'a> Info<'a> {
         &self,
         client: &Client,
         data: OwnedData<InfoData>,
-    ) -> Result<InfoResponse, InfoError> {
+    ) -> Result<InfoResponse, Error> {
         // Get the info URL, and send the request
         let url = UrlBuilder::api_info(self.file);
         let mut response = client.post(url)
@@ -72,13 +72,12 @@ impl<'a> Info<'a> {
             .map_err(|_| InfoError::Request)?;
 
         // Ensure the response is successful
-        ensure_success(&response)
-            .map_err(|err| InfoError::Response(err))?;
+        ensure_success(&response)?;
 
         // Decode the JSON response
         let response: InfoResponse = match response.json() {
             Ok(response) => response,
-            Err(err) => return Err(InfoError::Decode(err)),
+            Err(err) => return Err(InfoError::Decode(err).into()),
         };
 
         Ok(response)
@@ -143,22 +142,40 @@ pub enum Error {
     #[fail(display = "Failed to prepare the action")]
     Prepare(#[cause] PrepareError),
 
-    // /// The given Send file has expired, or did never exist in the first place.
-    // /// Therefore the file could not be downloaded.
-    // #[fail(display = "The file has expired or did never exist")]
-    // Expired,
+    /// The given Send file has expired, or did never exist in the first place.
+    /// Therefore the file could not be downloaded.
+    #[fail(display = "The file has expired or did never exist")]
+    Expired,
 
     /// An error has occurred while sending the info request to the server.
     #[fail(display = "Failed to send the file info request")]
     Info(#[cause] InfoError),
 }
 
+impl From<NonceError> for Error {
+    fn from(err: NonceError) -> Error {
+        match err {
+            NonceError::Expired => Error::Expired,
+            err => Error::Prepare(PrepareError::Auth(err)),
+        }
+    }
+}
+
 impl From<PrepareError> for Error {
     fn from(err: PrepareError) -> Error {
         Error::Prepare(err)
     }
 }
 
+impl From<ResponseError> for Error {
+    fn from(err: ResponseError) -> Error {
+        match err {
+            ResponseError::Expired => Error::Expired,
+            err => Error::Info(InfoError::Response(err)),
+        }
+    }
+}
+
 impl From<InfoError> for Error {
     fn from(err: InfoError) -> Error {
         Error::Info(err)

+ 11 - 2
api/src/action/metadata.rs

@@ -74,12 +74,12 @@ impl<'a> Metadata<'a> {
 
     /// Fetch the authentication nonce for the file from the remote server.
     fn fetch_auth_nonce(&self, client: &Client)
-        -> Result<Vec<u8>, RequestError>
+        -> Result<Vec<u8>, Error>
     {
         request_nonce(
             client,
             UrlBuilder::download(self.file, false),
-        ).map_err(|err| RequestError::Auth(err))
+        ).map_err(|err| err.into())
     }
 
     /// Create a metadata nonce, and fetch the metadata for the file from the
@@ -235,6 +235,15 @@ impl From<MetaError> for Error {
     }
 }
 
+impl From<NonceError> for Error {
+    fn from(err: NonceError) -> Error {
+        match err {
+            NonceError::Expired => Error::Expired,
+            err => Error::Request(RequestError::Auth(err)),
+        }
+    }
+}
+
 #[derive(Fail, Debug)]
 pub enum RequestError {
     /// Failed authenticating, in order to fetch the file data.

+ 27 - 9
api/src/action/params.rs

@@ -67,12 +67,12 @@ impl<'a> Params<'a> {
 
     /// Fetch the authentication nonce for the file from the remote server.
     fn fetch_auth_nonce(&self, client: &Client)
-        -> Result<Vec<u8>, PrepareError>
+        -> Result<Vec<u8>, Error>
     {
         request_nonce(
             client,
             UrlBuilder::download(self.file, false),
-        ).map_err(|err| PrepareError::Auth(err))
+        ).map_err(|err| err.into())
     }
 
     /// Send the request for changing the parameters.
@@ -80,7 +80,7 @@ impl<'a> Params<'a> {
         &self,
         client: &Client,
         data: OwnedData<ParamsData>,
-    ) -> Result<(), ChangeError> {
+    ) -> Result<(), Error> {
         // Get the params URL, and send the change
         let url = UrlBuilder::api_params(self.file);
         let response = client.post(url)
@@ -90,7 +90,7 @@ impl<'a> Params<'a> {
 
         // Ensure the response is successful
         ensure_success(&response)
-            .map_err(|err| ChangeError::Response(err))
+            .map_err(|err| err.into())
     }
 }
 
@@ -165,10 +165,10 @@ pub enum Error {
     #[fail(display = "Failed to prepare setting the parameters")]
     Prepare(#[cause] PrepareError),
 
-    // /// The given Send file has expired, or did never exist in the first place.
-    // /// Therefore the file could not be downloaded.
-    // #[fail(display = "The file has expired or did never exist")]
-    // Expired,
+    /// The given Send file has expired, or did never exist in the first place.
+    /// Therefore the file could not be downloaded.
+    #[fail(display = "The file has expired or did never exist")]
+    Expired,
 
     /// An error has occurred while sending the parameter change request to
     /// the server.
@@ -176,6 +176,15 @@ pub enum Error {
     Change(#[cause] ChangeError),
 }
 
+impl From<NonceError> for Error {
+    fn from(err: NonceError) -> Error {
+        match err {
+            NonceError::Expired => Error::Expired,
+            err => Error::Prepare(PrepareError::Auth(err)),
+        }
+    }
+}
+
 impl From<PrepareError> for Error {
     fn from(err: PrepareError) -> Error {
         Error::Prepare(err)
@@ -183,11 +192,20 @@ impl From<PrepareError> for Error {
 }
 
 impl From<ChangeError> for Error {
-    fn from(err: ChangeError) -> Error {
+    fn from(err:ChangeError) -> Error {
         Error::Change(err)
     }
 }
 
+impl From<ResponseError> for Error {
+    fn from(err: ResponseError) -> Error {
+        match err {
+            ResponseError::Expired => Error::Expired,
+            err => Error::Change(ChangeError::Response(err)),
+        }
+    }
+}
+
 #[derive(Debug, Fail)]
 pub enum ParamsDataError {
     /// The number of downloads is invalid, as it was out of the allowed

+ 26 - 8
api/src/action/password.rs

@@ -61,12 +61,12 @@ impl<'a> Password<'a> {
 
     /// Fetch the authentication nonce for the file from the Send server.
     fn fetch_auth_nonce(&self, client: &Client)
-        -> Result<Vec<u8>, PrepareError>
+        -> Result<Vec<u8>, Error>
     {
         request_nonce(
             client,
             UrlBuilder::download(self.file, false),
-        ).map_err(|err| PrepareError::Auth(err))
+        ).map_err(|err| err.into())
     }
 
     /// Send the request for changing the file password.
@@ -74,7 +74,7 @@ impl<'a> Password<'a> {
         &self,
         client: &Client,
         data: OwnedData<PasswordData>,
-    ) -> Result<(), ChangeError> {
+    ) -> Result<(), Error> {
         // Get the password URL, and send the change
         let url = UrlBuilder::api_password(self.file);
         let response = client.post(url)
@@ -84,7 +84,7 @@ impl<'a> Password<'a> {
 
         // Ensure the response is successful
         ensure_success(&response)
-            .map_err(|err| ChangeError::Response(err))
+            .map_err(|err| err.into())
     }
 }
 
@@ -111,10 +111,10 @@ pub enum Error {
     #[fail(display = "Failed to prepare setting the password")]
     Prepare(#[cause] PrepareError),
 
-    // /// The given Send file has expired, or did never exist in the first place.
-    // /// Therefore the file could not be downloaded.
-    // #[fail(display = "The file has expired or did never exist")]
-    // Expired,
+    /// The given Send file has expired, or did never exist in the first place.
+    /// Therefore the file could not be downloaded.
+    #[fail(display = "The file has expired or did never exist")]
+    Expired,
 
     /// An error has occurred while sending the password change request to
     /// the server.
@@ -122,6 +122,15 @@ pub enum Error {
     Change(#[cause] ChangeError),
 }
 
+impl From<NonceError> for Error {
+    fn from(err: NonceError) -> Error {
+        match err {
+            NonceError::Expired => Error::Expired,
+            err => Error::Prepare(PrepareError::Auth(err)),
+        }
+    }
+}
+
 impl From<PrepareError> for Error {
     fn from(err: PrepareError) -> Error {
         Error::Prepare(err)
@@ -134,6 +143,15 @@ impl From<ChangeError> for Error {
     }
 }
 
+impl From<ResponseError> for Error {
+    fn from(err: ResponseError) -> Error {
+        match err {
+            ResponseError::Expired => Error::Expired,
+            err => Error::Change(ChangeError::Response(err)),
+        }
+    }
+}
+
 #[derive(Fail, Debug)]
 pub enum PrepareError {
     /// Failed authenticating, needed to set a new password.

+ 16 - 3
api/src/api/nonce.rs

@@ -15,11 +15,10 @@ pub fn request_nonce(client: &Client, url: Url)
     // Make the request
     let response = client.get(url)
         .send()
-        .map_err(|_| NonceError::Request)?;
+        .map_err(|_| NonceError::Request)?; 
 
     // Ensure the response is successful
-    ensure_success(&response)
-        .map_err(|err| NonceError::Response(err))?;
+    ensure_success(&response)?;
 
     // Extract the nonce
     header_nonce(&response)
@@ -48,6 +47,11 @@ pub fn header_nonce(response: &Response)
 
 #[derive(Fail, Debug)]
 pub enum NonceError {
+    /// Sending the request to fetch a nonce failed,
+    /// as the file has expired or did never exist.
+    #[fail(display = "The file has expired or did never exist")]
+    Expired,
+
     /// Sending the request to fetch a nonce failed.
     #[fail(display = "Failed to request encryption nonce")]
     Request,
@@ -67,3 +71,12 @@ pub enum NonceError {
     #[fail(display = "Received malformed nonce")]
     MalformedNonce,
 }
+
+impl From<ResponseError> for NonceError {
+    fn from(err: ResponseError) -> Self {
+        match err {
+            ResponseError::Expired => NonceError::Expired,
+            err => NonceError::Response(err),
+        }
+    }
+}

+ 14 - 3
cli/src/action/delete.rs

@@ -51,10 +51,14 @@ impl<'a> Delete<'a> {
         ensure_owner_token(file.owner_token_mut(), &matcher_main);
 
         // Send the file deletion request
-        ApiDelete::new(&file, None).invoke(&client)?;
+        let result = ApiDelete::new(&file, None).invoke(&client);
+        if let Err(DeleteError::Expired) = result {
+            // Remove the file from the history manager if it does not exist
+            history_tool::remove(&matcher_main, &file);
+        }
+        result?;
 
         // Remove the file from the history manager
-        // TODO: also remove if it was expired
         history_tool::remove(&matcher_main, &file);
 
         // Print a success message
@@ -71,6 +75,10 @@ pub enum Error {
     #[fail(display = "Invalid share URL")]
     InvalidUrl(#[cause] FileParseError),
 
+    /// Could not delete, the file has expired or did never exist.
+    #[fail(display = "The file has expired or did never exist")]
+    Expired,
+
     /// An error occurred while deleting the remote file.
     #[fail(display = "Failed to delete the shared file")]
     Delete(#[cause] DeleteError),
@@ -84,6 +92,9 @@ impl From<FileParseError> for Error {
 
 impl From<DeleteError> for Error {
     fn from(err: DeleteError) -> Error {
-        Error::Delete(err)
+        match err {
+            DeleteError::Expired => Error::Expired,
+            err => Error::Delete(err),
+        }
     }
 }