use std::path::Path;
use std::sync::Arc;
use async_trait::async_trait;
use wildland_corex::dfs::interface::{DirEntry, FsStat, SpaceUsage};
use super::interface::EncryptionModule;
use crate::storage_backends::models::*;
use crate::storage_backends::StorageBackend;
use crate::{IStream, OStream, ProgressReporter, UnixTimestamp, WlPermissions};
pub struct EncryptStorageDriver {
inner: Arc<dyn StorageBackend>,
encryption_module: Arc<dyn EncryptionModule + Send + Sync>,
}
impl EncryptStorageDriver {
pub fn new(
inner: Arc<dyn StorageBackend>,
encryption_module: Arc<dyn EncryptionModule + Send + Sync>,
) -> Self {
Self {
inner,
encryption_module,
}
}
}
fn map_to_storage_backend_error(err: impl Into<anyhow::Error>) -> StorageBackendError {
StorageBackendError::Generic {
backend_type: "EncryptionDriver".into(),
inner: err.into(),
}
}
#[async_trait]
impl StorageBackend for EncryptStorageDriver {
async fn read_dir(&self, path: &Path) -> Result<ReadDirResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
let response = self.inner.read_dir(path.as_path()).await;
match response {
Ok(ReadDirResponse::Entries(entries)) => Ok(ReadDirResponse::Entries(
entries
.into_iter()
.map(|entry| {
Ok(DirEntry {
item_name: self
.encryption_module
.decode_plain(entry.item_name)
.map_err(map_to_storage_backend_error)?,
stat: entry.stat,
})
})
.collect::<Result<_, _>>()?,
)),
Ok(ReadDirResponse::NoSuchPath) => Ok(ReadDirResponse::NoSuchPath),
Ok(ReadDirResponse::NotADirectory) => Ok(ReadDirResponse::NotADirectory),
Err(e) => Err(e),
}
}
async fn metadata(&self, path: &Path) -> Result<MetadataResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
self.inner.metadata(path.as_path()).await
}
async fn create_dir(&self, path: &Path) -> Result<CreateDirResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
self.inner.create_dir(path.as_path()).await
}
async fn set_wildland_object_id(
&self,
path: &Path,
new_wildland_object_id: String,
) -> Result<SetWildlandObjectIdResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
self.inner
.set_wildland_object_id(path.as_path(), new_wildland_object_id)
.await
}
async fn remove_dir(
&self,
path: &Path,
is_recursive: bool,
) -> Result<RemoveDirResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
self.inner.remove_dir(path.as_path(), is_recursive).await
}
async fn path_exists(&self, path: &Path) -> Result<bool, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
self.inner.path_exists(path.as_path()).await
}
async fn remove_file(&self, path: &Path) -> Result<RemoveFileResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
self.inner.remove_file(path.as_path()).await
}
async fn rename(
&self,
oldpath: &Path,
newpath: &Path,
) -> Result<RenameResponse, StorageBackendError> {
let oldpath = self
.encryption_module
.encode_path(oldpath)
.map_err(map_to_storage_backend_error)?;
let newpath = self
.encryption_module
.encode_path(newpath)
.map_err(map_to_storage_backend_error)?;
self.inner
.rename(oldpath.as_path(), newpath.as_path())
.await
}
async fn set_permissions(
&self,
path: &Path,
permissions: WlPermissions,
) -> Result<SetPermissionsResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
self.inner
.set_permissions(path.as_path(), permissions)
.await
}
async fn mount(&self) -> Result<(), StorageBackendError> {
self.inner.mount().await
}
async fn get_space_usage(&self) -> Result<SpaceUsage, StorageBackendError> {
self.inner.get_space_usage().await
}
async fn download(
&self,
path: &Path,
output_stream: Box<dyn OStream>,
progress_reporter: Box<dyn ProgressReporter>,
) -> Result<DownloadResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
let transition_stream = self.encryption_module.wrap_ostream(output_stream);
self.inner
.download(path.as_path(), transition_stream, progress_reporter)
.await
}
async fn upload(
&self,
path: &Path,
input_stream: Box<dyn IStream>,
progress_reporter: Box<dyn ProgressReporter>,
creation_time: Option<UnixTimestamp>,
) -> Result<UploadResponse, StorageBackendError> {
let path = self
.encryption_module
.encode_path(path)
.map_err(map_to_storage_backend_error)?;
let transition_stream = self.encryption_module.wrap_istream(input_stream);
self.inner
.upload(
path.as_path(),
transition_stream,
progress_reporter,
creation_time,
)
.await
}
async fn get_path_by_uuid(&self, uuid: String) -> Result<GetInfoResponse, StorageBackendError> {
self.inner.get_path_by_uuid(uuid).await.map(|v| match v {
GetInfoResponse::Found(out) => Ok(GetInfoResponse::Found(
self.encryption_module
.decode_path(&out)
.map_err(map_to_storage_backend_error)?,
)),
GetInfoResponse::NotFound => Ok(GetInfoResponse::NotFound),
})?
}
async fn stat_fs(&self) -> Result<FsStat, StorageBackendError> {
self.inner.stat_fs().await
}
}