1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! Contains the structs and traits that define a "locksystem" backend.
//!
//! Note that the methods DO NOT return futures, they are sychronous.
//! This is because currently only two locksystems exist, `MemLs` and `FakeLs`.
//! Both of them do not do any I/O, all methods return instantly.
//!
//! If ever anyone implements a locksystem that does I/O (to a filesystem,
//! a database, or over the network) we'll need to revisit this.
//!
use crate::webpath::WebPath;
use std::fmt::Debug;
use std::time::{Duration, SystemTime};
use xmltree::Element;

/// Type of the locks returned by DavLockSystem methods.
#[derive(Debug, Clone)]
pub struct DavLock {
    pub token:      String,
    pub path:       WebPath,
    pub principal:  Option<String>,
    pub owner:      Option<Element>,
    pub timeout_at: Option<SystemTime>,
    pub timeout:    Option<Duration>,
    pub shared:     bool,
    pub deep:       bool,
}

/// The trait that defines a locksystem.
pub trait DavLockSystem: Debug + Sync + Send + BoxCloneLs {
    /// Lock a node. Returns Ok(new_lock) if succeeded,
    /// or Err(conflicting_lock) if failed.
    fn lock(
        &self,
        path: &WebPath,
        principal: Option<&str>,
        owner: Option<&Element>,
        timeout: Option<Duration>,
        shared: bool,
        deep: bool,
    ) -> Result<DavLock, DavLock>;

    /// Unlock a node. Returns empty Ok if succeeded, empty Err if failed
    /// (because lock doesn't exist)
    fn unlock(&self, path: &WebPath, token: &str) -> Result<(), ()>;

    /// Refresh lock. Returns updated lock if succeeded.
    fn refresh(&self, path: &WebPath, token: &str, timeout: Option<Duration>) -> Result<DavLock, ()>;

    /// Check if node is locked and if so, if we own all the locks.
    /// If not, returns as Err one conflicting lock.
    fn check(
        &self,
        path: &WebPath,
        principal: Option<&str>,
        ignore_principal: bool,
        deep: bool,
        submitted_tokens: Vec<&str>,
    ) -> Result<(), DavLock>;

    /// Find and return all locks that cover a given path.
    fn discover(&self, path: &WebPath) -> Vec<DavLock>;

    /// Delete all locks at this path and below (after MOVE or DELETE)
    fn delete(&self, path: &WebPath) -> Result<(), ()>;
}

#[doc(hidden)]
pub trait BoxCloneLs {
    fn box_clone(&self) -> Box<dyn DavLockSystem>;
}

// generic Clone, calls implementation-specific box_clone().
impl Clone for Box<dyn DavLockSystem> {
    fn clone(&self) -> Box<dyn DavLockSystem> {
        self.box_clone()
    }
}

// implementation-specific clone.
#[doc(hidden)]
impl<LS: Clone + DavLockSystem + 'static> BoxCloneLs for LS {
    fn box_clone(&self) -> Box<dyn DavLockSystem> {
        Box::new((*self).clone())
    }
}