mirror of
https://github.com/9001/copyparty.git
synced 2025-11-24 07:23:22 -07:00
show h vols in ls and tree,
and compensate with some optimizations
This commit is contained in:
parent
7f5810f1a7
commit
fff7291dcf
|
|
@ -393,11 +393,15 @@ class VFS(object):
|
||||||
axs: AXS,
|
axs: AXS,
|
||||||
flags: dict[str, Any],
|
flags: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
|
nss: set[str] = set()
|
||||||
self.log = log
|
self.log = log
|
||||||
self.realpath = realpath # absolute path on host filesystem
|
self.realpath = realpath # absolute path on host filesystem
|
||||||
self.vpath = vpath # absolute path in the virtual filesystem
|
self.vpath = vpath # absolute path in the virtual filesystem
|
||||||
self.vpath0 = vpath0 # original vpath (before idp expansion)
|
self.vpath0 = vpath0 # original vpath (before idp expansion)
|
||||||
self.axs = axs
|
self.axs = axs
|
||||||
|
self.uaxs: dict[
|
||||||
|
str, tuple[bool, bool, bool, bool, bool, bool, bool, bool, bool]
|
||||||
|
] = {}
|
||||||
self.flags = flags # config options
|
self.flags = flags # config options
|
||||||
self.root = self
|
self.root = self
|
||||||
self.dev = 0 # st_dev
|
self.dev = 0 # st_dev
|
||||||
|
|
@ -555,29 +559,19 @@ class VFS(object):
|
||||||
|
|
||||||
def can_access(
|
def can_access(
|
||||||
self, vpath: str, uname: str
|
self, vpath: str, uname: str
|
||||||
) -> tuple[bool, bool, bool, bool, bool, bool, bool, bool]:
|
) -> tuple[bool, bool, bool, bool, bool, bool, bool, bool, bool]:
|
||||||
"""can Read,Write,Move,Delete,Get,Upget,Admin,Dot"""
|
"""can Read,Write,Move,Delete,Get,Upget,Html,Admin,Dot"""
|
||||||
|
# NOTE: only used by get_perms, which is only used by hooks; the lowest of fruits
|
||||||
if vpath:
|
if vpath:
|
||||||
vn, _ = self._find(undot(vpath))
|
vn, _ = self._find(undot(vpath))
|
||||||
else:
|
else:
|
||||||
vn = self
|
vn = self
|
||||||
|
|
||||||
c = vn.axs
|
return vn.uaxs[uname]
|
||||||
return (
|
|
||||||
uname in c.uread,
|
|
||||||
uname in c.uwrite,
|
|
||||||
uname in c.umove,
|
|
||||||
uname in c.udel,
|
|
||||||
uname in c.uget,
|
|
||||||
uname in c.upget,
|
|
||||||
uname in c.uadmin,
|
|
||||||
uname in c.udot,
|
|
||||||
)
|
|
||||||
# skip uhtml because it's rarely needed
|
|
||||||
|
|
||||||
def get_perms(self, vpath: str, uname: str) -> str:
|
def get_perms(self, vpath: str, uname: str) -> str:
|
||||||
zbl = self.can_access(vpath, uname)
|
zbl = self.can_access(vpath, uname)
|
||||||
ret = "".join(ch for ch, ok in zip("rwmdgGa.", zbl) if ok)
|
ret = "".join(ch for ch, ok in zip("rwmdgGha.", zbl) if ok)
|
||||||
if "rwmd" in ret and "a." in ret:
|
if "rwmd" in ret and "a." in ret:
|
||||||
ret += "A"
|
ret += "A"
|
||||||
return ret
|
return ret
|
||||||
|
|
@ -772,19 +766,16 @@ class VFS(object):
|
||||||
virt_vis[name] = vn2
|
virt_vis[name] = vn2
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ok = False
|
u_has = vn2.uaxs.get(uname) or [False] * 9
|
||||||
zx = vn2.axs
|
|
||||||
axs = [zx.uread, zx.uwrite, zx.umove, zx.udel, zx.uget]
|
|
||||||
for pset in permsets:
|
for pset in permsets:
|
||||||
ok = True
|
ok = True
|
||||||
for req, lst in zip(pset, axs):
|
for req, zb in zip(pset, u_has):
|
||||||
if req and uname not in lst:
|
if req and not zb:
|
||||||
ok = False
|
ok = False
|
||||||
if ok:
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if ok:
|
if ok:
|
||||||
virt_vis[name] = vn2
|
virt_vis[name] = vn2
|
||||||
|
break
|
||||||
|
|
||||||
if ".hist" in abspath:
|
if ".hist" in abspath:
|
||||||
p = abspath.replace("\\", "/") if WINDOWS else abspath
|
p = abspath.replace("\\", "/") if WINDOWS else abspath
|
||||||
|
|
@ -1995,6 +1986,23 @@ class AuthSrv(object):
|
||||||
umap[usr].sort()
|
umap[usr].sort()
|
||||||
setattr(vfs, "a" + perm, umap)
|
setattr(vfs, "a" + perm, umap)
|
||||||
|
|
||||||
|
for vol in vfs.all_nodes.values():
|
||||||
|
za = vol.axs
|
||||||
|
vol.uaxs = {
|
||||||
|
un: (
|
||||||
|
un in za.uread,
|
||||||
|
un in za.uwrite,
|
||||||
|
un in za.umove,
|
||||||
|
un in za.udel,
|
||||||
|
un in za.uget,
|
||||||
|
un in za.upget,
|
||||||
|
un in za.uhtml,
|
||||||
|
un in za.uadmin,
|
||||||
|
un in za.udot,
|
||||||
|
)
|
||||||
|
for un in unames
|
||||||
|
}
|
||||||
|
|
||||||
all_users = {}
|
all_users = {}
|
||||||
missing_users = {}
|
missing_users = {}
|
||||||
associated_users = {}
|
associated_users = {}
|
||||||
|
|
@ -3436,7 +3444,7 @@ class AuthSrv(object):
|
||||||
raise Exception("volume not found: " + zs)
|
raise Exception("volume not found: " + zs)
|
||||||
|
|
||||||
self.log(str({"users": users, "vols": vols, "flags": flags}))
|
self.log(str({"users": users, "vols": vols, "flags": flags}))
|
||||||
t = "/{}: read({}) write({}) move({}) del({}) dots({}) get({}) upGet({}) uadmin({})"
|
t = "/{}: read({}) write({}) move({}) del({}) dots({}) get({}) upGet({}) html({}) uadmin({})"
|
||||||
for k, zv in self.vfs.all_vols.items():
|
for k, zv in self.vfs.all_vols.items():
|
||||||
vc = zv.axs
|
vc = zv.axs
|
||||||
vs = [
|
vs = [
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ class FtpFs(AbstractedFS):
|
||||||
if not avfs:
|
if not avfs:
|
||||||
raise FSE(t.format(vpath), 1)
|
raise FSE(t.format(vpath), 1)
|
||||||
|
|
||||||
cr, cw, cm, cd, _, _, _, _ = avfs.can_access("", self.h.uname)
|
cr, cw, cm, cd, _, _, _, _, _ = avfs.uaxs[self.h.uname]
|
||||||
if r and not cr or w and not cw or m and not cm or d and not cd:
|
if r and not cr or w and not cw or m and not cm or d and not cd:
|
||||||
raise FSE(t.format(vpath), 1)
|
raise FSE(t.format(vpath), 1)
|
||||||
|
|
||||||
|
|
@ -250,6 +250,7 @@ class FtpFs(AbstractedFS):
|
||||||
td = 0
|
td = 0
|
||||||
|
|
||||||
if w and need_unlink:
|
if w and need_unlink:
|
||||||
|
assert td # type: ignore # !rm
|
||||||
if td >= -1 and td <= self.args.ftp_wt:
|
if td >= -1 and td <= self.args.ftp_wt:
|
||||||
# within permitted timeframe; allow overwrite or resume
|
# within permitted timeframe; allow overwrite or resume
|
||||||
do_it = True
|
do_it = True
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,12 @@ RE_MDV = re.compile(r"(.*)\.([0-9]+\.[0-9]{3})(\.[Mm][Dd])$")
|
||||||
|
|
||||||
UPARAM_CC_OK = set("doc move tree".split())
|
UPARAM_CC_OK = set("doc move tree".split())
|
||||||
|
|
||||||
|
PERMS_rwh = [
|
||||||
|
[True, False],
|
||||||
|
[False, True],
|
||||||
|
[False, False, False, False, False, False, True],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class HttpCli(object):
|
class HttpCli(object):
|
||||||
"""
|
"""
|
||||||
|
|
@ -229,6 +235,7 @@ class HttpCli(object):
|
||||||
self.can_delete = False
|
self.can_delete = False
|
||||||
self.can_get = False
|
self.can_get = False
|
||||||
self.can_upget = False
|
self.can_upget = False
|
||||||
|
self.can_html = False
|
||||||
self.can_admin = False
|
self.can_admin = False
|
||||||
self.can_dot = False
|
self.can_dot = False
|
||||||
self.out_headerlist: list[tuple[str, str]] = []
|
self.out_headerlist: list[tuple[str, str]] = []
|
||||||
|
|
@ -737,6 +744,7 @@ class HttpCli(object):
|
||||||
if "bcasechk" in vn.flags and not vn.casechk(rem, True):
|
if "bcasechk" in vn.flags and not vn.casechk(rem, True):
|
||||||
return self.tx_404() and False
|
return self.tx_404() and False
|
||||||
|
|
||||||
|
try:
|
||||||
(
|
(
|
||||||
self.can_read,
|
self.can_read,
|
||||||
self.can_write,
|
self.can_write,
|
||||||
|
|
@ -744,11 +752,13 @@ class HttpCli(object):
|
||||||
self.can_delete,
|
self.can_delete,
|
||||||
self.can_get,
|
self.can_get,
|
||||||
self.can_upget,
|
self.can_upget,
|
||||||
|
self.can_html,
|
||||||
self.can_admin,
|
self.can_admin,
|
||||||
self.can_dot,
|
self.can_dot,
|
||||||
) = (
|
) = avn.uaxs[self.uname]
|
||||||
avn.can_access("", self.uname) if avn else [False] * 8
|
except:
|
||||||
)
|
pass # default is all-false
|
||||||
|
|
||||||
self.avn = avn
|
self.avn = avn
|
||||||
self.vn = vn # note: do not dbv due to walk/zipgen
|
self.vn = vn # note: do not dbv due to walk/zipgen
|
||||||
self.rem = rem
|
self.rem = rem
|
||||||
|
|
@ -5560,7 +5570,7 @@ class HttpCli(object):
|
||||||
rem,
|
rem,
|
||||||
self.uname,
|
self.uname,
|
||||||
not self.args.no_scandir,
|
not self.args.no_scandir,
|
||||||
[[True, False], [False, True]],
|
PERMS_rwh,
|
||||||
)
|
)
|
||||||
dots = self.uname in vn.axs.udot
|
dots = self.uname in vn.axs.udot
|
||||||
dk_sz = vn.flags.get("dk")
|
dk_sz = vn.flags.get("dk")
|
||||||
|
|
@ -5592,7 +5602,13 @@ class HttpCli(object):
|
||||||
for x in vfs_virt:
|
for x in vfs_virt:
|
||||||
if x != excl:
|
if x != excl:
|
||||||
try:
|
try:
|
||||||
dvn, drem = vfs.get(vjoin(top, x), self.uname, True, False)
|
dvn, drem = vfs.get(vjoin(top, x), self.uname, False, False)
|
||||||
|
if (
|
||||||
|
self.uname not in dvn.axs.uread
|
||||||
|
and self.uname not in dvn.axs.uwrite
|
||||||
|
and self.uname not in dvn.axs.uhtml
|
||||||
|
):
|
||||||
|
raise Exception()
|
||||||
bos.stat(dvn.canonical(drem, False))
|
bos.stat(dvn.canonical(drem, False))
|
||||||
except:
|
except:
|
||||||
x += "\n"
|
x += "\n"
|
||||||
|
|
@ -6518,8 +6534,7 @@ class HttpCli(object):
|
||||||
return self.tx_svg("upload\nonly")
|
return self.tx_svg("upload\nonly")
|
||||||
|
|
||||||
if not self.can_read and self.can_get and self.avn:
|
if not self.can_read and self.can_get and self.avn:
|
||||||
axs = self.avn.axs
|
if not self.can_html:
|
||||||
if self.uname not in axs.uhtml:
|
|
||||||
pass
|
pass
|
||||||
elif is_dir:
|
elif is_dir:
|
||||||
for fn in ("index.htm", "index.html"):
|
for fn in ("index.htm", "index.html"):
|
||||||
|
|
@ -6734,7 +6749,7 @@ class HttpCli(object):
|
||||||
rem,
|
rem,
|
||||||
self.uname,
|
self.uname,
|
||||||
not self.args.no_scandir,
|
not self.args.no_scandir,
|
||||||
[[True, False], [False, True]],
|
PERMS_rwh,
|
||||||
lstat="lt" in self.uparam,
|
lstat="lt" in self.uparam,
|
||||||
throw=True,
|
throw=True,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -187,9 +187,9 @@ class TestVFS(unittest.TestCase):
|
||||||
self.assertEqual(n.realpath, os.path.join(td, "a"))
|
self.assertEqual(n.realpath, os.path.join(td, "a"))
|
||||||
self.assertAxs(n.axs.uread, ["*", "k"])
|
self.assertAxs(n.axs.uread, ["*", "k"])
|
||||||
self.assertAxs(n.axs.uwrite, [])
|
self.assertAxs(n.axs.uwrite, [])
|
||||||
perm_na = (False, False, False, False, False, False, False, False)
|
perm_na = (False, False, False, False, False, False, False, False, False)
|
||||||
perm_rw = (True, True, False, False, False, False, False, False)
|
perm_rw = (True, True, False, False, False, False, False, False, False)
|
||||||
perm_ro = (True, False, False, False, False, False, False, False)
|
perm_ro = (True, False, False, False, False, False, False, False, False)
|
||||||
self.assertEqual(vfs.can_access("/", "*"), perm_na)
|
self.assertEqual(vfs.can_access("/", "*"), perm_na)
|
||||||
self.assertEqual(vfs.can_access("/", "k"), perm_rw)
|
self.assertEqual(vfs.can_access("/", "k"), perm_rw)
|
||||||
self.assertEqual(vfs.can_access("/a", "*"), perm_ro)
|
self.assertEqual(vfs.can_access("/a", "*"), perm_ro)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue