use std::collections::HashMap;
use std::collections::HashSet;
use http::Uri;
use ocm_types::share::SshProperties;
use ocm_types::{
discovery::Discovery,
error::{Error, ValidationError},
share::{NewShare, WebAppProperties, WebDavProperties},
};
use serde::Deserialize;
use serde::Serialize;
use serde_json::Value;
use super::shares::ProviderId;
pub trait Protocol: Send + Sync + 'static {
fn new(endpoint: Uri) -> Self
where
Self: Sized;
fn share_resource(
&self,
// TODO pass resource as ref as well?
provider_id: &ProviderId,
permissions: &HashSet<Permission>
) -> Result<MultiProtocol, &'static str>;
fn endpoint(&self) -> &Uri;
fn identifier(&self) -> &'static str;
fn supported_resource_types(&self) -> &[&str];
fn resolve_client_properties(
&self,
sending_server: &Discovery,
new_share: &NewShare,
) -> Result<MultiProtocol, ProtocolError>;
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
pub enum Permission {
Read,
Write
}
#[derive(Debug, Clone, Default)]
pub struct MultiProtocol {
pub webdav: Option<WebDavProperties>,
pub webapp: Option<WebAppProperties>,
pub ssh: Option<SshProperties>,
pub additional_protocols: HashMap<String, Value>,
}
impl MultiProtocol {
pub fn merge(self, mut other: Self) -> Self {
let Self {
webdav,
webapp,
ssh,
additional_protocols,
} = self;
other.additional_protocols.extend(additional_protocols);
Self {
webdav: webdav.or(other.webdav),
webapp: webapp.or(other.webapp),
ssh: ssh.or(other.ssh),
additional_protocols: other.additional_protocols,
}
}
pub fn is_empty(&self) -> bool {
self.webdav.is_none()
& self.webapp.is_none()
& self.ssh.is_none()
& self.additional_protocols.is_empty()
}
}
impl From<MultiProtocol> for ocm_types::share::Protocol {
fn from(value: MultiProtocol) -> Self {
let MultiProtocol {
webdav,
webapp,
ssh,
additional_protocols,
} = value;
ocm_types::share::Protocol {
name: "multi".to_string(),
webdav,
webapp,
ssh,
additional_protocols,
..Default::default()
}
}
}
pub fn get_share_protocol<'a>(
share: &'a NewShare,
protocol: &'static str,
) -> Option<&'a serde_json::Map<String, serde_json::Value>> {
#[allow(deprecated)]
let protocol_properties = if share.protocol.name == "multi" {
share
.protocol
.additional_protocols
.get(protocol)
.and_then(|p| p.as_object())
} else if share.protocol.name == protocol
&& let Some(ref options) = share.protocol.options
{
Some(options)
} else {
None
};
protocol_properties
}
pub enum ProtocolError {
NotSupported,
InvalidProtocolProperties(String),
}
impl From<ProtocolError> for Error {
fn from(value: ProtocolError) -> Self {
match value {
ProtocolError::NotSupported => Error {
message: "SHARE_PROTOCOL_UNSUPPORTED".to_string(),
validation_errors: vec![ValidationError {
name: None,
message: Some("Protocol not suppored for this share".to_string()),
}],
},
ProtocolError::InvalidProtocolProperties(e) => Error {
message: "INVALID_SHARE_PROTOCOL".to_string(),
validation_errors: vec![ValidationError {
name: None,
message: Some(e),
}],
},
}
}
}