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}