Skip to main content

ocm_types/share/protocols/
webdav.rs

1// SPDX-FileCopyrightText: 2026 Matthias Kraus <info@opengeomesh.org>
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5use serde::{Deserialize, Serialize};
6use serde_json::{Map, Value, json};
7
8use super::AccessType;
9use super::default_access_types;
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "camelCase")]
13pub struct WebDavProperties {
14    /// The type of access being granted to the remote resource.
15    /// If omitted, it defaults to `['remote']`.
16    /// - `remote` signals the recipient that the resource is available
17    ///   for remote access and interactive browsing.
18    /// - `datatx` signals the recipient to transfer the resource
19    ///   from the given URI. The recipient MAY delegate a third-party
20    ///   service to execute the data transfer on their behalf.
21    #[serde(
22        skip_serializing_if = "Vec::is_empty",
23        default = "default_access_types"
24    )]
25    pub access_types: Vec<AccessType>,
26    /// An URI to access the remote resource. The URI SHOULD be
27    /// relative,
28    /// such as a key or a UUID, in which case the prefix exposed by the
29    /// `/.well-known/ocm` endpoint MUST be used to access the resource,
30    /// or it MAY be absolute, including a hostname. The latter is NOT
31    /// recommended because of security concerns.
32    /// In all cases, for a `folder` resource, the composed URI acts
33    /// as the root path, such that other files located within SHOULD
34    /// be accessible by appending their relative path to that URI.
35    pub uri: String,
36    /// An optional secret to be used to access the resource, such
37    /// as
38    /// a bearer token. If a `refreshToken` is provided, it SHOULD be used
39    /// instead via the code flow interaction, and the `sharedSecret`
40    /// SHOULD be omitted. To prevent leaking it in logs it MUST NOT
41    /// appear in any URI.
42    #[serde(skip_serializing_if = "Option::is_none", default)]
43    pub shared_secret: Option<String>,
44    /// A Token to be exchanged for a short-lived bearer token at the tokenEndPoint
45    /// of the Sending Server for access to the shared resource.
46    #[serde(skip_serializing_if = "Option::is_none", default)]
47    pub refresh_token: Option<String>,
48    /// The permissions granted to the sharee.
49    #[serde(skip_serializing_if = "Vec::is_empty", default)]
50    pub permissions: Vec<WebDavPermissions>,
51    /// A list of requirements that the recipient provider MUST
52    /// fulfill
53    /// to access the resource. Requirements are optional, but if it is
54    /// present it MUST NOT be empty. A recipient provider MUST reject
55    /// a share whose requirements it does not understand.
56    #[serde(skip_serializing_if = "Vec::is_empty", default)]
57    pub requirements: Vec<WebDavRequirements>,
58}
59
60#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
61#[serde(rename_all = "kebab-case")]
62pub enum WebDavRequirements {
63    /// `must-use-mfa` requires the user accessing the resource to be
64    /// MFA-authenticated. This requirement MAY be used if the
65    /// recipient provider exposes the `enforce-mfa` capability.
66    MustUseMfa,
67    /// `must-exchange-token` requires the recipient to exchange the given
68    /// `refreshToken` via a signed HTTPS request to tokenEndPoint at the Sending
69    /// Server, in order to get a short-lived token to be used for
70    /// subsequent access. This requirement MAY be used if the
71    /// recipient provider exposes the [`exchange-token`
72    /// capability](crate::discovery::Capability::ExchangeToken).
73    MustExchangeToken,
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
77#[serde(rename_all = "kebab-case")]
78pub enum WebDavPermissions {
79    /// allows read-only access including download of a copy.
80    Read,
81    /// allows create, update, and delete rights on the resource.
82    Write,
83    /// allows re-share rights on the resource.
84    Share,
85}
86
87impl TryFrom<WebDavProperties> for Map<String, Value> {
88    // FIXME use proper error
89    type Error = String;
90
91    fn try_from(value: WebDavProperties) -> Result<Self, Self::Error> {
92        let json = json!(value);
93        serde_json::from_value(json).map_err(|e| e.to_string())
94    }
95}