show h vols in ls and tree,

and compensate with some optimizations
This commit is contained in:
ed 2025-10-23 21:44:28 +00:00
parent 7f5810f1a7
commit fff7291dcf
4 changed files with 69 additions and 45 deletions

View file

@ -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,20 +766,17 @@ 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
break
if ok: if ok:
virt_vis[name] = vn2
break break
if ok:
virt_vis[name] = vn2
if ".hist" in abspath: if ".hist" in abspath:
p = abspath.replace("\\", "/") if WINDOWS else abspath p = abspath.replace("\\", "/") if WINDOWS else abspath
if p.endswith("/.hist"): if p.endswith("/.hist"):
@ -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 = [

View file

@ -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

View file

@ -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,18 +744,21 @@ 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_write, self.can_read,
self.can_move, self.can_write,
self.can_delete, self.can_move,
self.can_get, self.can_delete,
self.can_upget, self.can_get,
self.can_admin, self.can_upget,
self.can_dot, self.can_html,
) = ( self.can_admin,
avn.can_access("", self.uname) if avn else [False] * 8 self.can_dot,
) ) = avn.uaxs[self.uname]
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,
) )

View file

@ -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)