wopi-accs + support unmapped root

This commit is contained in:
ed
2026-08-17 19:40:22 +00:00
parent 9ff6a71a2a
commit 78a4ee49a2
4 changed files with 31 additions and 6 deletions
+1
View File
@@ -1631,6 +1631,7 @@ def add_opds(ap):
def add_wopi(ap):
ap2 = ap.add_argument_group("WOPI options")
ap2.add_argument("--wopi", action="store_true", help="enable integration with office suites using WOPI")
ap2.add_argument("--wopi-accs", metavar="TXT", type=u, default="", help="restrict wopi to this comma-separated list of usernames; default is everyone")
ap2.add_argument("--wopi-api", metavar="URL", type=u, default="", help="URL that the WOPI-client should use to communicate with copyparty; default is same as user's webbrowser. Example: [\033[32mhttps://party.example.com/\033[0m]")
ap2.add_argument("--wopi-url", metavar="URL", type=u, default="", help="URL to your WOPI client; the host of e.g. Collabora Online. Example: [\033[32mhttps://code.example.com/\033[0m]")
ap2.add_argument("--wopi-urls", metavar="H=U", type=u, action="append", help="\033[34mREPEATABLE:\033[0m maps http \033[33mH\033[0mOST copyparty being accessed by to specific WOPI client instance \033[33mU\033[0mRL; falls back to \033[33m--wopi-url\033[0m; examples: [\033[32mparty.public.com=https://office.public.com/\033[0m], [\033[32mparty.internal.net:8443=https://office.internal.net:8443/\033[0m]")
+9
View File
@@ -2040,6 +2040,15 @@ class AuthSrv(object):
umap[usr].sort()
setattr(vfs, "a" + perm, umap)
if self.args.wopi:
zsl = unames[:]
if self.args.wopi_accs:
zsl = [x.strip() for x in self.args.wopi_accs.split(",")]
axs = AXS(zsl, zsl, None, zsl)
vn = VFS(self.log_func, "", "wopi", "", axs, self.vf0())
vn.flags["unlistcr"] = vn.flags["unlistcw"] = True
vfs.nodes["wopi"] = vfs.all_nodes["wopi"] = vn
for vol in vfs.all_nodes.values():
za = vol.axs
vol.uaxs = {
+20 -5
View File
@@ -849,6 +849,11 @@ class HttpCli(object):
self.asrv.vfs.get(
wopi_f["vp"], uname, True, True, False, self.args.wopi_wdel
)
vn, rem = self.asrv.vfs.get(
self.vpath, uname, True, True, False, self.args.wopi_wdel
)
if vn.vpath != "wopi":
raise Exception("bad url")
self.uname = uname
except Exception as ex:
self.conn.hsrv.wopi_files.pop(wopi_a, None)
@@ -1578,13 +1583,17 @@ class HttpCli(object):
if "wopi" in self.uparam:
return self.tx_wopi()
if self.vpath.startswith("wopi"):
if self.vn.vpath == "wopi":
return self.tx_wopi_api()
return self.tx_browser()
def tx_wopi_api(self) -> bool:
atoken = self.uparam["access_token"]
try:
atoken = self.uparam["access_token"]
except:
raise Pebkac(400, "wopi access_token is mandatory")
session = self.conn.hsrv.wopi_files[atoken]
if self.do_log:
self.log(" `-- wopi: %r" % (session["vp"],))
@@ -1620,6 +1629,7 @@ class HttpCli(object):
return self.tx_404()
def tx_wopi(self) -> bool:
self.asrv.vfs.get("wopi", self.uname, True, True, False, self.args.wopi_wdel)
vpath = vjoin(self.vpath, self.uparam["wopi"])
vfs, rem = self.asrv.vfs.get(
vpath, self.uname, True, True, False, self.args.wopi_wdel
@@ -3553,7 +3563,11 @@ class HttpCli(object):
return True
def rx_wopi(self, postsize: int) -> bool:
atoken = self.uparam["access_token"]
try:
atoken = self.uparam["access_token"]
except:
raise Pebkac(400, "wopi access_token is mandatory")
session = self.conn.hsrv.wopi_files[atoken]
if self.do_log:
self.log(" `-- wopi: %r" % (session["vp"],))
@@ -3562,8 +3576,7 @@ class HttpCli(object):
if not self.vpath.startswith(zs):
return self.tx_404()
vpath = self.conn.hsrv.wopi_files[self.uparam["access_token"]]["vp"]
vfs, rem = self.asrv.vfs.get(vpath, self.uname, False, True)
vfs, rem = self.asrv.vfs.get(session["vp"], self.uname, False, True)
vpath = vjoin(vfs.vpath, rem)
ap = vfs.canonical(rem)
st = bos.stat(ap)
@@ -6153,6 +6166,8 @@ class HttpCli(object):
continue
try:
dvn, drem = vfs.get(vjoin(top, x), self.uname, False, False)
if not dvn.realpath and not dvn.nodes:
continue
if (
self.uname not in dvn.axs.uread
and self.uname not in dvn.axs.uwrite
+1 -1
View File
@@ -180,7 +180,7 @@ class HttpSrv(object):
self.u2idx_free: dict[str, U2idx] = {}
self.u2idx_n = 0
self.wopi_files: dict[str, dict[str, str]] = {}
self.wopi_files: dict[str, dict[str, Any]] = {}
assert jinja2 # type: ignore # !rm
env = jinja2.Environment()