use async_trait::async_trait;
use endbasic_std::storage::{DiskSpace, FileAcls};
use serde::{Deserialize, Serialize};
use std::io;
mod cloud;
pub use cloud::CloudService;
mod cmds;
pub use cmds::add_all;
mod drive;
pub(crate) use drive::CloudDriveFactory;
#[cfg(test)]
pub(crate) mod testutils;
pub const PROD_API_ADDRESS: &str = "https://service.endbasic.dev/";
#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(PartialEq, Serialize))]
struct SerdeDiskSpace {
bytes: u64,
files: u64,
}
impl From<DiskSpace> for SerdeDiskSpace {
fn from(ds: DiskSpace) -> Self {
SerdeDiskSpace { bytes: ds.bytes, files: ds.files }
}
}
impl From<SerdeDiskSpace> for DiskSpace {
fn from(sds: SerdeDiskSpace) -> Self {
DiskSpace { bytes: sds.bytes, files: sds.files }
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
#[cfg_attr(test, derive(Serialize))]
pub struct AccessToken(String);
impl AccessToken {
#[cfg(test)]
pub(crate) fn new<S: Into<String>>(token: S) -> Self {
Self(token.into())
}
pub(crate) fn as_str(&self) -> &str {
&self.0
}
}
#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, Serialize))]
pub struct ErrorResponse {
pub(crate) message: String,
}
#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, Serialize))]
pub struct LoginResponse {
pub(crate) access_token: AccessToken,
motd: Vec<String>,
}
#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, Serialize))]
pub struct DirectoryEntry {
filename: String,
mtime: u64,
length: u64,
}
#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, Serialize))]
pub struct GetFilesResponse {
files: Vec<DirectoryEntry>,
disk_quota: Option<SerdeDiskSpace>,
disk_free: Option<SerdeDiskSpace>,
}
#[derive(Debug, Default, Eq, PartialEq, Serialize)]
#[cfg_attr(test, derive(Deserialize))]
pub struct SignupRequest {
username: String,
password: String,
email: String,
promotional_email: bool,
}
#[async_trait(?Send)]
pub trait Service {
async fn signup(&mut self, request: &SignupRequest) -> io::Result<()>;
async fn login(&mut self, username: &str, password: &str) -> io::Result<LoginResponse>;
async fn logout(&mut self) -> io::Result<()>;
fn is_logged_in(&self) -> bool;
fn logged_in_username(&self) -> Option<String>;
async fn get_files(&mut self, username: &str) -> io::Result<GetFilesResponse>;
async fn get_file(&mut self, username: &str, filename: &str) -> io::Result<Vec<u8>>;
async fn get_file_acls(&mut self, username: &str, filename: &str) -> io::Result<FileAcls>;
async fn patch_file_content(
&mut self,
username: &str,
filename: &str,
content: Vec<u8>,
) -> io::Result<()>;
async fn patch_file_acls(
&mut self,
username: &str,
filename: &str,
add: &FileAcls,
remove: &FileAcls,
) -> io::Result<()>;
async fn delete_file(&mut self, username: &str, filename: &str) -> io::Result<()>;
}