Check for expired files everywehere, propogate their errors

This commit is contained in:
timvisee 2018-04-23 14:03:42 +02:00
parent 7526bdb5a3
commit cb2d5f7844
No known key found for this signature in database
GPG key ID: 109CBA0BF74036C2
8 changed files with 159 additions and 58 deletions

View file

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

View file

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

View file

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

View file

@ -74,12 +74,12 @@ impl<'a> Metadata<'a> {
/// Fetch the authentication nonce for the file from the remote server. /// Fetch the authentication nonce for the file from the remote server.
fn fetch_auth_nonce(&self, client: &Client) fn fetch_auth_nonce(&self, client: &Client)
-> Result<Vec<u8>, RequestError> -> Result<Vec<u8>, Error>
{ {
request_nonce( request_nonce(
client, client,
UrlBuilder::download(self.file, false), 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 /// 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)] #[derive(Fail, Debug)]
pub enum RequestError { pub enum RequestError {
/// Failed authenticating, in order to fetch the file data. /// Failed authenticating, in order to fetch the file data.

View file

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

View file

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

View file

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

View file

@ -51,10 +51,14 @@ impl<'a> Delete<'a> {
ensure_owner_token(file.owner_token_mut(), &matcher_main); ensure_owner_token(file.owner_token_mut(), &matcher_main);
// Send the file deletion request // 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 // Remove the file from the history manager
// TODO: also remove if it was expired
history_tool::remove(&matcher_main, &file); history_tool::remove(&matcher_main, &file);
// Print a success message // Print a success message
@ -71,6 +75,10 @@ pub enum Error {
#[fail(display = "Invalid share URL")] #[fail(display = "Invalid share URL")]
InvalidUrl(#[cause] FileParseError), 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. /// An error occurred while deleting the remote file.
#[fail(display = "Failed to delete the shared file")] #[fail(display = "Failed to delete the shared file")]
Delete(#[cause] DeleteError), Delete(#[cause] DeleteError),
@ -84,6 +92,9 @@ impl From<FileParseError> for Error {
impl From<DeleteError> for Error { impl From<DeleteError> for Error {
fn from(err: DeleteError) -> Error { fn from(err: DeleteError) -> Error {
Error::Delete(err) match err {
DeleteError::Expired => Error::Expired,
err => Error::Delete(err),
}
} }
} }