ocm_types/
discovery.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::common::ShareType;
6
7/// This is the response payload of the discovery endpoint, representing the
8/// properties and capabilities offered by this server.
9#[allow(rustdoc::bare_urls)]
10#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct Discovery {
13    /// Whether the OCM service is enabled at this endpoint
14    pub enabled: bool,
15    /// The OCM API version this endpoint supports
16    pub api_version: String,
17    /// The URI of the OCM API available at this endpoint
18    /// Example: https://my-cloud-storage.org/ocm
19    pub end_point: String,
20    /// A friendly branding name of this endpoint
21    /// Example: MyCloudStorage
22    #[serde(skip_serializing_if = "Option::is_none", default)]
23    pub provider: Option<String>, 
24    /// A list of all supported resource types with their access protocols.
25    /// Each resource type is identified by its `name`: the list MUST NOT
26    /// contain more than one resource type object per given `name`.
27    pub resource_types: Vec<Resource>,
28    /// The optional capabilities exposed at this endpoint according to the
29    /// present specifications.
30    /// ```
31    /// use ocm_types::discovery::Capability;
32    ///
33    /// let capabilities = vec![
34    ///     Capability::WebdavUri,
35    ///     Capability::ProtocolObject,
36    /// ];
37    /// let json: Vec<Capability> = serde_json::from_str(r#"[
38    ///     "webdav-uri",
39    ///     "protocol-object"
40    /// ]"#).unwrap();
41    /// assert_eq!(capabilities, json);
42    /// ```
43    #[serde(skip_serializing_if = "Option::is_none", default)]
44    pub capabilities: Option<Vec<Capability>>,
45    /// The criteria for accepting a Share Creation Notification.
46    /// As all Receiving Servers should require the use of TLS in API calls,
47    /// it is not necessary to expose that as a criterium.
48    ///
49    /// example:
50    /// - allowlist
51    /// - invite
52    /// ```
53    /// use ocm_types::discovery::Criterium;
54    ///
55    /// let criteria = vec![
56    ///     Criterium::Allowlist,
57    ///     Criterium::Invite,
58    /// ];
59    /// let json: Vec<Criterium> = serde_json::from_str(r#"[
60    ///     "allowlist",
61    ///     "invite"
62    /// ]"#).unwrap();
63    /// assert_eq!(criteria, json);
64    /// ```
65    #[serde(skip_serializing_if = "Option::is_none", default)]
66    pub criteria: Option<Vec<Criterium>>,
67    /// The signatory used to sign outgoing request to confirm its origin.
68    /// The signatory is optional but it MUST contain `id` and `publicKeyPem`.
69    #[serde(skip_serializing_if = "Option::is_none", default)]
70    pub public_key: Option<PublicKey>,
71    /// Optional URL path of a web page where a user can accept an invite, when
72    /// query parameters "token" and "providerDomain" are provided. 
73    /// Implementations that offer the invites capability SHOULD provide this URL
74    /// as well in order to enhance the UX of the Invite Flow. If for example 
75    /// "/index.php/apps/sciencemesh/accept" is specified here then a 
76    /// Where-Are-You-From page could redirect the end-user to 
77    /// /index.php/apps/sciencemesh/accept?token=zi5kooKu3ivohr9a&providerDomain=example.com.
78    #[serde(skip_serializing_if = "Option::is_none", default)]
79    pub invite_accept_dialog: Option<String>,
80}
81
82#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
83pub struct ApiVersion(pub String);
84
85#[allow(rustdoc::bare_urls)]
86#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct PublicKey {
89    /// unique id of the key in URI format. The hostname set the origin
90    /// of the request and MUST be identical to the current discovery endpoint.
91    /// example: https://my-cloud-storage.org/ocm#signature
92    pub key_id: String,
93    /// PEM-encoded version of the public key.
94    /// example:
95    ///  -----BEGIN PUBLIC KEY-----
96    ///     MII...QDD
97    ///  -----END PUBLIC KEY-----
98    pub public_key_pem: String,
99}
100
101#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
102#[serde(rename_all = "kebab-case")]
103pub enum Criterium {
104    HttpRequestSignatures,
105    Code,
106    Denylist,
107    Allowlist,
108    Invite,
109}
110
111#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
112#[serde(rename_all = "kebab-case")]
113pub enum Capability {
114    /// to indicate that this OCM sServer can apply a Sending Server's MFA requirements for 
115    /// a Share on their behalf.
116    EnforceMfa,
117    /// to indicate that this OCM sServer can append a relative URI to the path listed for 
118    /// WebDAV in the appropriate resourceTypes entry
119    WebdavUri,
120    /// to indicate that this OCM Server can receive a Share Creation Notification whose 
121    /// protocol object contains one property per supported protocol instead of containing 
122    /// the standard name and options properties.
123    ProtocolObject,
124    /// to indicate the server would support acting as an Invite Sender or Invite Receiver 
125    /// OCM Server. This might be useful for suggesting to a user that existing contacts 
126    /// might be upgraded to the more secure (and possibly required) invite flow.
127    Invites,
128    /// to indicate that this OCM Server can receive a code as part of a Share Creation 
129    /// Notification, and exchange it for a bearer token at the Sending Server's /token 
130    /// API endpoint. 
131    ReceiveCode,
132    /// to indicate that this OCM Server exposes a WAYF Page to facilitate the Invite flow. 
133    InviteWayf,
134}
135
136#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
137#[serde(rename_all = "camelCase")]
138pub struct Resource {
139    /// A supported resource type (file, folder, calendar, contact,
140    /// ...).
141    /// Implementations MUST support `file` at a minimum.
142    /// Example: file
143    pub name: String,
144    /// The supported recipient share types.
145    /// Implementations MUST support `user` at a minimum.
146    /// Example: user
147    pub share_types: Vec<ShareType>,
148    /// The supported protocols to access shared resources at this
149    /// endpoint.
150    /// Implementations MUST support at least `webdav` for `file` resources,
151    /// any other combination of resources and protocols is optional.
152    ///
153    // properties:
154    //   webdav:
155    //     type: string
156    //     description: >
157    //       The top-level WebDAV path at this endpoint. In order to
158    //       access
159    //       a remote shared resource, implementations SHOULD
160
161    //     use this path
162    //       as a prefix (see sharing examples).
163    //   webapp:
164    //     type: string
165    //     description: >
166    //       The top-level path for web apps at this endpoint. In order
167    //       to
168    //       access a remote web app, implementations SHOULD use this path
169    //       as a prefix (see sharing examples).
170    //   datatx:
171    //     type: string
172    //     description: >
173    //       The top-level path to be used for data transfers. In order
174    //       to
175    //       access a remote shared resource, implementations SHOULD use
176    //       this path as a prefix (see sharing examples). In addition,
177    //       implementations are expected to execute the transfer using
178    //       WebDAV as the wire protocol.
179    // patternProperties:
180    //   ^.*$:
181    //     type: string
182    //     description: >
183    //       Any additional protocol supported for this resource type
184    //       MAY
185    //       be advertised here, where the value MAY correspond to a top-level
186    //       URI to be used for that protocol.
187    /// ```
188    /// use std::collections::HashMap;
189    ///
190    /// let resources = HashMap::from_iter(vec![
191    ///     ("webdav".to_string(), "/remote/dav/ocm/".to_string()),
192    ///     ("webapp".to_string(), "/apps/ocm/".to_string()),
193    ///     ("talk".to_string(), "/apps/speed/api/".to_string()),
194    /// ].into_iter());
195    ///
196    /// let json: HashMap<String,String> = serde_json::from_str(r#"{
197    ///     "webdav": "/remote/dav/ocm/",
198    ///     "webapp": "/apps/ocm/",
199    ///     "talk": "/apps/speed/api/"
200    /// }"#).unwrap();
201    /// assert_eq!(resources, json);
202    /// ```
203    pub protocols: HashMap<String, String>,
204}