ocm_types/share/protocols/mod.rs
1// SPDX-FileCopyrightText: 2026 Matthias Kraus <info@opengeomesh.org>
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5//! Protocol Properties for access protocols specified within OpenCloudMesh
6//! The Protocol Properties are used in [crate::shares::NewShare] to inform the Receiving Server
7//! about how to access a shared Resource.
8
9mod ssh;
10mod webapp;
11mod webdav;
12pub use ssh::*;
13pub use webapp::*;
14pub use webdav::*;
15
16use std::collections::HashMap;
17
18use serde::{Deserialize, Serialize};
19use serde_json::{Map, Value};
20
21/// JSON object with specific options for each protocol.
22///
23/// The supported protocols are:
24/// - `webdav`, to access the data
25/// - `webapp`, to access remote web applications
26/// - `ssh`, to access the data via SFTP/SCP
27///
28/// Other custom protocols might be added in the future.
29///
30/// # Single Protocol Legacy
31/// ```
32/// use ocm_types::share::Protocol;
33/// use serde_json::Map;
34/// use serde_json::Value;
35/// use serde_json::json;
36///
37/// #[allow(deprecated)]
38/// let single_protocol_legacy = Protocol{
39/// name: "webdav".to_string(),
40/// options: Some(Map::from_iter(vec![
41/// ("sharedSecret".to_string(), Value::String("hfiuhworzwnur98d3wjiwhr".to_string())),
42/// ("permissions".to_string(), Value::String("some permissions scheme".to_string())),
43/// ].into_iter())),
44/// ..Default::default()
45/// };
46/// let json: Value = serde_json::from_str(r#"{
47/// "name": "webdav",
48/// "options": {
49/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
50/// "permissions": "some permissions scheme"
51/// }
52/// }"#).unwrap();
53/// assert_eq!(json!(single_protocol_legacy), json);
54/// ```
55///
56/// # Single Protocol New
57/// ```
58/// use ocm_types::share::Protocol;
59/// use ocm_types::share::WebDavProperties;
60/// use ocm_types::share::WebDavPermissions;
61/// use ocm_types::share::AccessType;
62/// use std::collections::HashMap;
63/// use serde_json::Value;
64/// use serde_json::json;
65/// use serde::de::Deserialize;
66///
67/// let single_protocol_new = Protocol{
68/// name: "multi".to_string(),
69/// webdav: Some(WebDavProperties{
70/// access_types: vec![AccessType::Remote],
71/// uri: "7c084226-d9a1-11e6-bf26-cec0c932ce01".to_string(),
72/// shared_secret: Some("hfiuhworzwnur98d3wjiwhr".to_string()),
73/// refresh_token: None,
74/// permissions: vec![
75/// WebDavPermissions::Read,
76/// WebDavPermissions::Write,
77/// ],
78/// requirements: vec![]
79/// }),
80/// ..Default::default()
81/// };
82/// let json: Value = serde_json::from_str(r#"{
83/// "name": "multi",
84/// "webdav": {
85/// "accessTypes": ["remote"],
86/// "uri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
87/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
88/// "permissions": ["read", "write"]
89/// }
90/// }"#).unwrap();
91/// assert_eq!(json!(single_protocol_new), json);
92/// ```
93///
94/// # Multi Protocol
95/// ```
96/// use ocm_types::share::Protocol;
97/// use ocm_types::share::WebDavProperties;
98/// use ocm_types::share::WebDavPermissions;
99/// use ocm_types::share::WebDavRequirements;
100/// use ocm_types::share::WebAppProperties;
101/// use ocm_types::share::WebAppViewMode;
102/// use ocm_types::share::SshProperties;
103/// use ocm_types::share::AccessType;
104/// use std::collections::HashMap;
105/// use serde_json::Value;
106/// use serde_json::json;
107///
108/// let single_protocol_new = Protocol{
109/// name: "multi".to_string(),
110/// webdav: Some(WebDavProperties{
111/// access_types: vec![AccessType::Remote],
112/// uri: "7c084226-d9a1-11e6-bf26-cec0c932ce01".to_string(),
113/// shared_secret: Some("hfiuhworzwnur98d3wjiwhr".to_string()),
114/// refresh_token: None,
115/// permissions: vec![
116/// WebDavPermissions::Read,
117/// WebDavPermissions::Write
118/// ],
119/// requirements: vec![
120/// WebDavRequirements::MustUseMfa
121/// ]
122/// }),
123/// webapp: Some(WebAppProperties{
124/// uri: "7c084226-d9a1-11e6-bf26-cec0c932ce01".to_string(),
125/// shared_secret: Some("hfiuhworzwnur98d3wjiwhr".to_string()),
126/// view_mode: WebAppViewMode::Read
127/// }),
128/// ssh: Some(SshProperties{
129/// access_types: vec![AccessType::DataTx],
130/// uri: "extuser@cloud.example.org:/7c084226-d9a1-11e6-bf26-cec0c932ce01".to_string()
131/// }),
132/// additional_protocols: HashMap::from_iter(vec![
133/// (
134/// "datatx".to_string(),
135/// json!({
136/// "srcUri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
137/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
138/// "size": 100000
139/// })
140/// )
141/// ].into_iter()),
142/// ..Default::default()
143/// };
144/// let json: Value = serde_json::from_str(r#"{
145/// "name": "multi",
146/// "webdav": {
147/// "accessTypes": ["remote"],
148/// "uri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
149/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
150/// "permissions": ["read", "write"],
151/// "requirements": ["must-use-mfa"]
152/// },
153/// "webapp": {
154/// "uri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
155/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
156/// "viewMode": "read"
157/// },
158/// "datatx": {
159/// "srcUri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
160/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
161/// "size": 100000
162/// },
163/// "ssh": {
164/// "accessTypes": ["datatx"],
165/// "uri": "extuser@cloud.example.org:/7c084226-d9a1-11e6-bf26-cec0c932ce01"
166/// }
167/// }"#).unwrap();
168/// assert_eq!(json!(single_protocol_new), json);
169/// ```
170///
171/// # WebDAV with refreshToken
172/// ```
173/// # use ocm_types::share::Protocol;
174/// # use ocm_types::share::AccessType;
175/// # use ocm_types::share::WebDavProperties;
176/// # use ocm_types::share::WebDavPermissions;
177/// # use ocm_types::share::WebDavRequirements;
178/// # use ocm_types::share::WebAppProperties;
179/// # use ocm_types::share::WebAppViewMode;
180/// # use std::collections::HashMap;
181/// # use serde_json::Value;
182/// # use serde_json::json;
183///
184/// let webdav_refresh_token = Protocol{
185/// name: "multi".to_string(),
186/// webdav: Some(WebDavProperties{
187/// access_types: vec![AccessType::Remote],
188/// uri: "7c084226-d9a1-11e6-bf26-cec0c932ce01".to_string(),
189/// shared_secret: None,
190/// refresh_token: Some("hfiuhworzwnur98d3wjiwhr".to_string()),
191/// permissions: vec![
192/// WebDavPermissions::Read,
193/// WebDavPermissions::Write
194/// ],
195/// requirements: vec![
196/// WebDavRequirements::MustUseMfa,
197/// WebDavRequirements::MustExchangeToken
198/// ]
199/// }),
200/// webapp: Some(WebAppProperties{
201/// uri: "7c084226-d9a1-11e6-bf26-cec0c932ce01".to_string(),
202/// shared_secret: Some("hfiuhworzwnur98d3wjiwhr".to_string()),
203/// view_mode: WebAppViewMode::Read
204/// }),
205/// additional_protocols: HashMap::from_iter(vec![
206/// (
207/// "datatx".to_string(),
208/// json!({
209/// "srcUri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
210/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
211/// "size": 100000
212/// })
213/// )
214/// ].into_iter()),
215/// ..Default::default()
216/// };
217/// let json: Value = serde_json::from_str(r#"{
218/// "name": "multi",
219/// "webdav": {
220/// "accessTypes": ["remote"],
221/// "uri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
222/// "refreshToken": "hfiuhworzwnur98d3wjiwhr",
223/// "permissions": ["read", "write"],
224/// "requirements": ["must-use-mfa", "must-exchange-token"]
225/// },
226/// "webapp": {
227/// "uri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
228/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
229/// "viewMode": "read"
230/// },
231/// "datatx": {
232/// "srcUri": "7c084226-d9a1-11e6-bf26-cec0c932ce01",
233/// "sharedSecret": "hfiuhworzwnur98d3wjiwhr",
234/// "size": 100000
235/// }
236/// }"#).unwrap();
237/// assert_eq!(json!(webdav_refresh_token), json);
238/// ```
239// example:
240// multipleProtocols:
241// name: multi
242// webapp:
243// uri: 7c084226-d9a1-11e6-bf26-cec0c932ce01
244// sharedSecret: hfiuhworzwnur98d3wjiwhr
245// viewMode: read
246// datatx:
247// srcUri: 7c084226-d9a1-11e6-bf26-cec0c932ce01
248// sharedSecret: hfiuhworzwnur98d3wjiwhr
249// size: 100000
250#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
251#[serde(rename_all = "camelCase")]
252pub struct Protocol {
253 /// The name of the protocol. Default: `multi`.
254 /// If `multi` is given, one or more protocol endpoints are expected
255 /// to be defined according to the optional properties specified below.
256 /// Otherwise, at least `webdav` is expected to be supported, and
257 /// its options MAY be given in the opaque `options` payload for
258 /// compatibility with v1.0 implementations (see examples). Note
259 /// though that this format is deprecated.
260 /// Warning: client implementers should be aware that v1.1 servers
261 /// MAY support both `webdav` and `multi`, but v1.0 servers MAY
262 /// only support `webdav`.
263 /// This field may be removed in a future major version of the spec.
264 pub name: String,
265 /// This property is now deprecated. Implementations are
266 /// encouraged to transition to the new optional properties
267 /// defined below, such that this field may be removed in a future major
268 /// version of the spec.
269 #[deprecated]
270 #[serde(skip_serializing_if = "Option::is_none", default)]
271 pub options: Option<Map<String, Value>>,
272 #[serde(skip_serializing_if = "Option::is_none", default)]
273 pub webdav: Option<WebDavProperties>,
274 #[serde(skip_serializing_if = "Option::is_none", default)]
275 pub webapp: Option<WebAppProperties>,
276 #[serde(skip_serializing_if = "Option::is_none", default)]
277 pub ssh: Option<SshProperties>,
278 /// Any optional additional protocols supported for this resource
279 /// MAY
280 /// be provided here, along with their custom payload. Appropriate
281 /// capabilities MUST be advertised in order for a sender to ensure
282 /// the recipient can parse such customized payloads.
283 #[serde(skip_serializing_if = "HashMap::is_empty", default)]
284 #[serde(flatten)]
285 pub additional_protocols: HashMap<String, Value>,
286}
287
288#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
289#[serde(rename_all = "lowercase")]
290pub enum AccessType {
291 /// signals the recipient that the resource is available
292 /// for remote access and interactive browsing.
293 Remote,
294 /// signals the recipient to transfer the resource
295 /// from the given URI. The recipient MAY delegate a third-party
296 /// service to execute the data transfer on their behalf.
297 DataTx,
298}
299
300fn default_access_types() -> Vec<AccessType> {
301 vec![AccessType::Remote]
302}