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
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)),
}
}
}

View file

@ -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),
}
}
}

View file

@ -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)

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -18,8 +18,7 @@ pub fn request_nonce(client: &Client, url: Url)
.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),
}
}
}

View file

@ -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),
}
}
}