mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
up2k: add volume flag to reject existing files
This commit is contained in:
parent
2163055dae
commit
de724a1ff3
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -15,7 +15,7 @@
|
||||||
"-a",
|
"-a",
|
||||||
"ed:wark",
|
"ed:wark",
|
||||||
"-v",
|
"-v",
|
||||||
"srv::r:aed"
|
"srv::r:aed:cnodupe"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,11 +12,12 @@ from .util import undot, Pebkac, fsdec, fsenc
|
||||||
class VFS(object):
|
class VFS(object):
|
||||||
"""single level in the virtual fs"""
|
"""single level in the virtual fs"""
|
||||||
|
|
||||||
def __init__(self, realpath, vpath, uread=[], uwrite=[]):
|
def __init__(self, realpath, vpath, uread=[], uwrite=[], flags={}):
|
||||||
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.uread = uread # users who can read this
|
self.uread = uread # users who can read this
|
||||||
self.uwrite = uwrite # users who can write this
|
self.uwrite = uwrite # users who can write this
|
||||||
|
self.flags = flags # config switches
|
||||||
self.nodes = {} # child nodes
|
self.nodes = {} # child nodes
|
||||||
|
|
||||||
def add(self, src, dst):
|
def add(self, src, dst):
|
||||||
|
@ -36,6 +37,7 @@ class VFS(object):
|
||||||
"{}/{}".format(self.vpath, name).lstrip("/"),
|
"{}/{}".format(self.vpath, name).lstrip("/"),
|
||||||
self.uread,
|
self.uread,
|
||||||
self.uwrite,
|
self.uwrite,
|
||||||
|
self.flags,
|
||||||
)
|
)
|
||||||
self.nodes[name] = vn
|
self.nodes[name] = vn
|
||||||
return vn.add(src, dst)
|
return vn.add(src, dst)
|
||||||
|
@ -161,7 +163,7 @@ class AuthSrv(object):
|
||||||
|
|
||||||
yield prev, True
|
yield prev, True
|
||||||
|
|
||||||
def _parse_config_file(self, fd, user, mread, mwrite, mount):
|
def _parse_config_file(self, fd, user, mread, mwrite, mflags, mount):
|
||||||
vol_src = None
|
vol_src = None
|
||||||
vol_dst = None
|
vol_dst = None
|
||||||
for ln in [x.decode("utf-8").strip() for x in fd]:
|
for ln in [x.decode("utf-8").strip() for x in fd]:
|
||||||
|
@ -191,6 +193,7 @@ class AuthSrv(object):
|
||||||
mount[vol_dst] = vol_src
|
mount[vol_dst] = vol_src
|
||||||
mread[vol_dst] = []
|
mread[vol_dst] = []
|
||||||
mwrite[vol_dst] = []
|
mwrite[vol_dst] = []
|
||||||
|
mflags[vol_dst] = {}
|
||||||
continue
|
continue
|
||||||
|
|
||||||
lvl, uname = ln.split(" ")
|
lvl, uname = ln.split(" ")
|
||||||
|
@ -198,6 +201,9 @@ class AuthSrv(object):
|
||||||
mread[vol_dst].append(uname)
|
mread[vol_dst].append(uname)
|
||||||
if lvl in "wa":
|
if lvl in "wa":
|
||||||
mwrite[vol_dst].append(uname)
|
mwrite[vol_dst].append(uname)
|
||||||
|
if lvl == "c":
|
||||||
|
# config option, currently switches only
|
||||||
|
mflags[vol_dst][uname] = True
|
||||||
|
|
||||||
def reload(self):
|
def reload(self):
|
||||||
"""
|
"""
|
||||||
|
@ -210,6 +216,7 @@ class AuthSrv(object):
|
||||||
user = {} # username:password
|
user = {} # username:password
|
||||||
mread = {} # mountpoint:[username]
|
mread = {} # mountpoint:[username]
|
||||||
mwrite = {} # mountpoint:[username]
|
mwrite = {} # mountpoint:[username]
|
||||||
|
mflags = {} # mountpoint:[flag]
|
||||||
mount = {} # dst:src (mountpoint:realpath)
|
mount = {} # dst:src (mountpoint:realpath)
|
||||||
|
|
||||||
if self.args.a:
|
if self.args.a:
|
||||||
|
@ -232,9 +239,13 @@ class AuthSrv(object):
|
||||||
mount[dst] = src
|
mount[dst] = src
|
||||||
mread[dst] = []
|
mread[dst] = []
|
||||||
mwrite[dst] = []
|
mwrite[dst] = []
|
||||||
|
mflags[dst] = {}
|
||||||
|
|
||||||
perms = perms.split(":")
|
perms = perms.split(":")
|
||||||
for (lvl, uname) in [[x[0], x[1:]] for x in perms]:
|
for (lvl, uname) in [[x[0], x[1:]] for x in perms]:
|
||||||
|
if lvl == "c":
|
||||||
|
# config option, currently switches only
|
||||||
|
mflags[dst][uname] = True
|
||||||
if uname == "":
|
if uname == "":
|
||||||
uname = "*"
|
uname = "*"
|
||||||
if lvl in "ra":
|
if lvl in "ra":
|
||||||
|
@ -245,14 +256,14 @@ class AuthSrv(object):
|
||||||
if self.args.c:
|
if self.args.c:
|
||||||
for cfg_fn in self.args.c:
|
for cfg_fn in self.args.c:
|
||||||
with open(cfg_fn, "rb") as f:
|
with open(cfg_fn, "rb") as f:
|
||||||
self._parse_config_file(f, user, mread, mwrite, mount)
|
self._parse_config_file(f, user, mread, mwrite, mflags, mount)
|
||||||
|
|
||||||
if not mount:
|
if not mount:
|
||||||
# -h says our defaults are CWD at root and read/write for everyone
|
# -h says our defaults are CWD at root and read/write for everyone
|
||||||
vfs = VFS(os.path.abspath("."), "", ["*"], ["*"])
|
vfs = VFS(os.path.abspath("."), "", ["*"], ["*"])
|
||||||
elif "" not in mount:
|
elif "" not in mount:
|
||||||
# there's volumes but no root; make root inaccessible
|
# there's volumes but no root; make root inaccessible
|
||||||
vfs = VFS(os.path.abspath("."), "", [], [])
|
vfs = VFS(os.path.abspath("."), "")
|
||||||
|
|
||||||
maxdepth = 0
|
maxdepth = 0
|
||||||
for dst in sorted(mount.keys(), key=lambda x: (x.count("/"), len(x))):
|
for dst in sorted(mount.keys(), key=lambda x: (x.count("/"), len(x))):
|
||||||
|
@ -262,12 +273,13 @@ class AuthSrv(object):
|
||||||
|
|
||||||
if dst == "":
|
if dst == "":
|
||||||
# rootfs was mapped; fully replaces the default CWD vfs
|
# rootfs was mapped; fully replaces the default CWD vfs
|
||||||
vfs = VFS(mount[dst], dst, mread[dst], mwrite[dst])
|
vfs = VFS(mount[dst], dst, mread[dst], mwrite[dst], mflags[dst])
|
||||||
continue
|
continue
|
||||||
|
|
||||||
v = vfs.add(mount[dst], dst)
|
v = vfs.add(mount[dst], dst)
|
||||||
v.uread = mread[dst]
|
v.uread = mread[dst]
|
||||||
v.uwrite = mwrite[dst]
|
v.uwrite = mwrite[dst]
|
||||||
|
v.flags = mflags[dst]
|
||||||
|
|
||||||
missing_users = {}
|
missing_users = {}
|
||||||
for d in [mread, mwrite]:
|
for d in [mread, mwrite]:
|
||||||
|
|
|
@ -387,6 +387,7 @@ class HttpCli(object):
|
||||||
body["vdir"] = self.vpath
|
body["vdir"] = self.vpath
|
||||||
body["rdir"] = os.path.join(vfs.realpath, rem)
|
body["rdir"] = os.path.join(vfs.realpath, rem)
|
||||||
body["addr"] = self.addr[0]
|
body["addr"] = self.addr[0]
|
||||||
|
body["flag"] = vfs.flags
|
||||||
|
|
||||||
x = self.conn.hsrv.broker.put(True, "up2k.handle_json", body)
|
x = self.conn.hsrv.broker.put(True, "up2k.handle_json", body)
|
||||||
response = x.get()
|
response = x.get()
|
||||||
|
|
|
@ -64,6 +64,12 @@ class Up2k(object):
|
||||||
job["vdir"], job["name"]
|
job["vdir"], job["name"]
|
||||||
)
|
)
|
||||||
raise Pebkac(400, err)
|
raise Pebkac(400, err)
|
||||||
|
elif "nodupe" in job["flag"]:
|
||||||
|
self.log("up2k", "dupe-reject:\n {0}\n {1}".format(src, dst))
|
||||||
|
err = "upload rejected, file already exists:\n{0}{1} ".format(
|
||||||
|
job["vdir"], job["name"]
|
||||||
|
)
|
||||||
|
raise Pebkac(400, err)
|
||||||
else:
|
else:
|
||||||
# symlink to the client-provided name,
|
# symlink to the client-provided name,
|
||||||
# returning the previous upload info
|
# returning the previous upload info
|
||||||
|
@ -80,6 +86,7 @@ class Up2k(object):
|
||||||
"addr": cj["addr"],
|
"addr": cj["addr"],
|
||||||
"vdir": cj["vdir"],
|
"vdir": cj["vdir"],
|
||||||
"rdir": cj["rdir"],
|
"rdir": cj["rdir"],
|
||||||
|
"flag": cj["flag"],
|
||||||
# client-provided, sanitized by _get_wark:
|
# client-provided, sanitized by _get_wark:
|
||||||
"name": cj["name"],
|
"name": cj["name"],
|
||||||
"size": cj["size"],
|
"size": cj["size"],
|
||||||
|
|
|
@ -670,7 +670,8 @@ function up2k_init(have_crypto) {
|
||||||
else {
|
else {
|
||||||
var err = "";
|
var err = "";
|
||||||
var rsp = (xhr.responseText + '');
|
var rsp = (xhr.responseText + '');
|
||||||
if (rsp.indexOf('partial upload exists') !== -1) {
|
if (rsp.indexOf('partial upload exists') !== -1 ||
|
||||||
|
rsp.indexOf('file already exists') !== -1) {
|
||||||
err = rsp.slice(5);
|
err = rsp.slice(5);
|
||||||
}
|
}
|
||||||
if (err != "") {
|
if (err != "") {
|
||||||
|
|
Loading…
Reference in a new issue