diff --git a/markbase-core/src/webdav.rs b/markbase-core/src/webdav.rs index 52429e8..d5ea4ce 100644 --- a/markbase-core/src/webdav.rs +++ b/markbase-core/src/webdav.rs @@ -81,6 +81,7 @@ pub struct VfsDavFs { versioning: Option>, props_data: Arc>>>, props_path: PathBuf, + enable_acl: bool, } impl Clone for VfsDavFs { @@ -93,6 +94,7 @@ impl Clone for VfsDavFs { versioning: self.versioning.clone(), props_data: self.props_data.clone(), props_path: self.props_path.clone(), + enable_acl: self.enable_acl, } } } @@ -178,6 +180,7 @@ impl VfsDavFs { versioning: None, props_data, props_path, + enable_acl: true, }) } @@ -198,9 +201,14 @@ impl VfsDavFs { versioning: Some(versioning), props_data, props_path, + enable_acl: true, }) } + pub fn set_enable_acl(&mut self, enable: bool) { + self.enable_acl = enable; + } + fn rel_key(&self, path: &DavPath) -> String { let rel = path.as_pathbuf(); rel.to_string_lossy().to_string() @@ -617,6 +625,18 @@ impl VfsDavFs { xml: Some(Self::empty_acl_xml()), } } + + fn check_acl(&self, path: &Path, mask: crate::vfs::VfsAceMask) -> Result<(), FsError> { + if !self.enable_acl { + return Ok(()); + } + match self.vfs.check_acl(path, &self.user_uuid, mask) { + Ok(true) => Ok(()), + Ok(false) => Err(FsError::Forbidden), + Err(crate::vfs::VfsError::Unsupported(_)) => Ok(()), + Err(_) => Err(FsError::Forbidden), + } + } } impl DavFileSystem for VfsDavFs { @@ -631,6 +651,9 @@ impl DavFileSystem for VfsDavFs { }; if options.write { + if let Err(e) = self.check_acl(&full_path, crate::vfs::VfsAceMask::WriteData) { + return Box::pin(std::future::ready(Err(e))); + } let file = VfsDavFile::new_write( full_path, self.vfs.clone_boxed(), @@ -640,6 +663,9 @@ impl DavFileSystem for VfsDavFs { ); Box::pin(std::future::ready(Ok(Box::new(file) as Box))) } else { + if let Err(e) = self.check_acl(&full_path, crate::vfs::VfsAceMask::ReadData) { + return Box::pin(std::future::ready(Err(e))); + } let flags = OpenFlags::new().read(); match self.vfs.open_file(&full_path, &flags) { Ok(vfs_file) => { @@ -661,6 +687,10 @@ impl DavFileSystem for VfsDavFs { Err(e) => return Box::pin(std::future::ready(Err(e))), }; + if let Err(e) = self.check_acl(&full_path, crate::vfs::VfsAceMask::ListDirectory) { + return Box::pin(std::future::ready(Err(e))); + } + match self.vfs.read_dir(&full_path) { Ok(entries) => { let results: Vec> = entries @@ -698,6 +728,9 @@ impl DavFileSystem for VfsDavFs { Ok(p) => p, Err(e) => return Box::pin(std::future::ready(Err(e))), }; + if let Err(e) = self.check_acl(&full_path, crate::vfs::VfsAceMask::AddSubdirectory) { + return Box::pin(std::future::ready(Err(e))); + } if self.vfs.exists(&full_path) { return Box::pin(std::future::ready(Err(FsError::Exists))); } @@ -712,6 +745,9 @@ impl DavFileSystem for VfsDavFs { Ok(p) => p, Err(e) => return Box::pin(std::future::ready(Err(e))), }; + if let Err(e) = self.check_acl(&full_path, crate::vfs::VfsAceMask::DeleteChild) { + return Box::pin(std::future::ready(Err(e))); + } match self.vfs.remove_dir_all(&full_path) { Ok(_) => Box::pin(std::future::ready(Ok(()))), Err(e) => Box::pin(std::future::ready(Err(map_vfs_error(e)))), @@ -723,6 +759,9 @@ impl DavFileSystem for VfsDavFs { Ok(p) => p, Err(e) => return Box::pin(std::future::ready(Err(e))), }; + if let Err(e) = self.check_acl(&full_path, crate::vfs::VfsAceMask::Delete) { + return Box::pin(std::future::ready(Err(e))); + } match self.vfs.remove_file(&full_path) { Ok(_) => Box::pin(std::future::ready(Ok(()))), Err(e) => Box::pin(std::future::ready(Err(map_vfs_error(e)))), @@ -738,6 +777,12 @@ impl DavFileSystem for VfsDavFs { Ok(p) => p, Err(e) => return Box::pin(std::future::ready(Err(e))), }; + if let Err(e) = self.check_acl(&from_path, crate::vfs::VfsAceMask::Delete) { + return Box::pin(std::future::ready(Err(e))); + } + if let Err(e) = self.check_acl(&to_path, crate::vfs::VfsAceMask::AddFile) { + return Box::pin(std::future::ready(Err(e))); + } let from_key = self.rel_key(from); let to_key = self.rel_key(to); let props_data = self.props_data.clone();