From b4fda5f1d6c2b218625c1faaf1e21519b4442e5f Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 17 Oct 2025 00:01:54 +0000 Subject: [PATCH] subtract users/groups from access; closes #845 --- README.md | 3 +++ copyparty/__main__.py | 7 +++++-- copyparty/authsrv.py | 21 +++++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 94b7f29a..63c7b903 100644 --- a/README.md +++ b/README.md @@ -523,6 +523,9 @@ examples: if you want to grant access to all users who are logged in, the group `acct` will always contain all known users, so for example `-v /mnt/music:music:r,@acct` +* to do the opposite, granting access to everyone who is NOT logged in. `*,-@acct` does the trick, for example `-v /srv/welcome:welcome:r,*,-@acct` +* single users can also be subtracted from a group: `@admins,-james` + anyone trying to bruteforce a password gets banned according to `--ban-pw`; default is 24h ban for 9 failed attempts in 1 hour and if you want to use config files instead of commandline args (good!) then here's the same examples as a configfile; save it as `foobar.conf` and use it like this: `python copyparty-sfx.py -c foobar.conf` diff --git a/copyparty/__main__.py b/copyparty/__main__.py index a36462c7..48f4dea0 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -649,8 +649,11 @@ def get_sects(): if no accounts or volumes are configured, current folder will be read/write for everyone - the group @acct will always have every user with an account - (the name of that group can be changed with --grp-all) + the group \033[33m@acct\033[0m will always have every user with an account + (the name of that group can be changed with \033[32m--grp-all\033[0m) + + to hide a volume from authenticated users, specify \033[33m*,-@acct\033[0m + to subtract \033[33m@acct\033[0m from \033[33m*\033[0m (can subtract users from groups too) consider the config file for more flexible account/volume management, including dynamic reload at runtime (and being more readable w) diff --git a/copyparty/authsrv.py b/copyparty/authsrv.py index 979fd042..117b4308 100644 --- a/copyparty/authsrv.py +++ b/copyparty/authsrv.py @@ -1972,9 +1972,18 @@ class AuthSrv(object): axs_key = "u" + perm for vp, vol in vfs.all_vols.items(): zx = getattr(vol.axs, axs_key) - if "*" in zx: + if "*" in zx and "-@acct" not in zx: for usr in unames: zx.add(usr) + for zs in list(zx): + if zs.startswith("-"): + zx.discard(zs) + zs = zs[1:] + zx.discard(zs) + if zs.startswith("@"): + zs = zs[1:] + for zs in grps.get(zs) or []: + zx.discard(zs) # aread,... = dict[uname, list[volnames] or []] umap: dict[str, list[str]] = {x: [] for x in unames} @@ -2754,9 +2763,13 @@ class AuthSrv(object): ["uadmin", "uadmin"], ]: u = list(sorted(getattr(zv.axs, attr))) - u = ["*"] if "*" in u else u - u = ", ".join("\033[35meverybody\033[0m" if x == "*" else x for x in u) - u = u if u else "\033[36m--none--\033[0m" + if u == ["*"] and acct: + u = ["\033[35monly-anonymous\033[0m"] + elif "*" in u: + u = ["\033[35meverybody\033[0m"] + if not u: + u = ["\033[36m--none--\033[0m"] + u = ", ".join(u) t += "\n| {}: {}".format(txt, u) if "e2d" in zv.flags: