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