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}