```
dufs -a admin:admin@/:rw -a guest:guest@/
-dufs -a user:pass@/:rw,/dir1,/dir2:- -a @/
+dufs -a user:pass@/:rw,/dir1 -a @/
```
1. Use `@` to separate the account and paths. No account means anonymous user.
2. Use `:` to separate the username and password of the account.
3. Use `,` to separate paths.
-4. Use path suffix `:rw`, `:ro`, `:-` to set permissions: `read-write`, `read-only`, `forbidden`. `:ro` can be omitted.
+4. Use path suffix `:rw`/`:ro` set permissions: `read-write`/`read-only`. `:ro` can be omitted.
- `-a admin:admin@/:rw`: `admin` has complete permissions for all paths.
- `-a guest:guest@/`: `guest` has read-only permissions for all paths.
-- `-a user:pass@/:rw,/dir1,/dir2:-`: `user` has read-write permissions for `/*`, has read-only permissions for `/dir1/*`, but is fordden for `/dir2/*`.
+- `-a user:pass@/:rw,/dir1`: `user` has read-write permissions for `/*`, has read-only permissions for `/dir1/*`.
- `-a @/`: All paths is publicly accessible, everyone can view/download it.
> There are no restrictions on using ':' and '@' characters in a password. For example, `user:pa:ss@1@/:rw` is valid, the password is `pa:ss@1`.
}
pub fn set_perm(&mut self, perm: AccessPerm) {
- if !perm.inherit() {
+ if !perm.indexonly() {
self.perm = perm;
}
}
None => (item, AccessPerm::ReadOnly),
Some((path, "ro")) => (path, AccessPerm::ReadOnly),
Some((path, "rw")) => (path, AccessPerm::ReadWrite),
- Some((path, "-")) => (path, AccessPerm::Forbidden),
_ => return None,
};
self.add(path, perm);
.filter(|v| !v.is_empty())
.collect();
let target = self.find_impl(&parts, self.perm)?;
- if target.perm().forbidden() {
- return None;
- }
if writable && !target.perm().readwrite() {
return None;
}
}
fn find_impl(&self, parts: &[&str], perm: AccessPerm) -> Option<AccessPaths> {
- let perm = if !self.perm.inherit() {
+ let perm = if !self.perm.indexonly() {
self.perm
} else {
perm
};
if parts.is_empty() {
- if perm.inherit() {
+ if perm.indexonly() {
return Some(self.clone());
} else {
return Some(AccessPaths::new(perm));
let child = match self.children.get(parts[0]) {
Some(v) => v,
None => {
- if perm.inherit() {
+ if perm.indexonly() {
return None;
} else {
return Some(AccessPaths::new(perm));
}
pub fn child_paths(&self, base: &Path) -> Vec<PathBuf> {
- if !self.perm().inherit() {
+ if !self.perm().indexonly() {
return vec![base.to_path_buf()];
}
let mut output = vec![];
fn child_paths_impl(&self, output: &mut Vec<PathBuf>, base: &Path) {
for (name, child) in self.children.iter() {
let base = base.join(name);
- if child.perm().inherit() {
+ if child.perm().indexonly() {
child.child_paths_impl(output, &base);
} else {
output.push(base)
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum AccessPerm {
#[default]
- Inherit,
+ IndexOnly,
ReadOnly,
ReadWrite,
- Forbidden,
}
impl AccessPerm {
- pub fn inherit(&self) -> bool {
- self == &AccessPerm::Inherit
+ pub fn indexonly(&self) -> bool {
+ self == &AccessPerm::IndexOnly
}
pub fn readwrite(&self) -> bool {
self == &AccessPerm::ReadWrite
}
-
- pub fn forbidden(&self) -> bool {
- self == &AccessPerm::Forbidden
- }
}
pub fn www_authenticate(res: &mut Response, args: &Args) -> Result<()> {
paths.add("/dir1", AccessPerm::ReadWrite);
paths.add("/dir2/dir21", AccessPerm::ReadWrite);
paths.add("/dir2/dir21/dir211", AccessPerm::ReadOnly);
- paths.add("/dir2/dir21/dir212", AccessPerm::Forbidden);
paths.add("/dir2/dir22", AccessPerm::ReadOnly);
paths.add("/dir2/dir22/dir221", AccessPerm::ReadWrite);
paths.add("/dir2/dir23/dir231", AccessPerm::ReadWrite);
Some(AccessPaths::new(AccessPerm::ReadOnly))
);
assert_eq!(paths.find("dir2/dir21/dir211/file", true), None);
- assert_eq!(paths.find("dir2/dir21/dir212", false), None);
}
}
"PROPFIND" => {
if is_dir {
let access_paths =
- if access_paths.perm().inherit() && authorization.is_none() {
+ if access_paths.perm().indexonly() && authorization.is_none() {
// see https://github.com/sigoden/dufs/issues/229
AccessPaths::new(AccessPerm::ReadOnly)
} else {
access_paths: AccessPaths,
) -> Result<Vec<PathItem>> {
let mut paths: Vec<PathItem> = vec![];
- if access_paths.perm().inherit() {
+ if access_paths.perm().indexonly() {
for name in access_paths.child_names() {
let entry_path = entry_path.join(name);
self.add_pathitem(&mut paths, base_path, &entry_path).await;
Ok(())
}
-#[rstest]
-fn auth_forbidden(
- #[with(&["--auth", "user:pass@/:rw,/dir1:-", "-A"])] server: TestServer,
-) -> Result<(), Error> {
- let url = format!("{}file1", server.url());
- let resp = fetch!(b"PUT", &url)
- .body(b"abc".to_vec())
- .send_with_digest_auth("user", "pass")?;
- assert_eq!(resp.status(), 201);
- let url = format!("{}dir1/file1", server.url());
- let resp = fetch!(b"PUT", &url)
- .body(b"abc".to_vec())
- .send_with_digest_auth("user", "pass")?;
- assert_eq!(resp.status(), 403);
- Ok(())
-}
-
#[rstest]
fn auth_nest(
#[with(&["--auth", "user:pass@/:rw", "--auth", "user2:pass2@/", "--auth", "user3:pass3@/dir1:rw", "-A"])]