mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
add idp-cache editor ui
This commit is contained in:
parent
d27144340f
commit
4f264a0a9c
|
@ -80,6 +80,7 @@ web/deps/prismd.css
|
||||||
web/deps/scp.woff2
|
web/deps/scp.woff2
|
||||||
web/deps/sha512.ac.js
|
web/deps/sha512.ac.js
|
||||||
web/deps/sha512.hw.js
|
web/deps/sha512.hw.js
|
||||||
|
web/idp.html
|
||||||
web/iiam.gif
|
web/iiam.gif
|
||||||
web/md.css
|
web/md.css
|
||||||
web/md.html
|
web/md.html
|
||||||
|
|
|
@ -1102,6 +1102,7 @@ def add_auth(ap):
|
||||||
ap2.add_argument("--idp-gsep", metavar="RE", type=u, default="|:;+,", help="if there are multiple groups in \033[33m--idp-h-grp\033[0m, they are separated by one of the characters in \033[33mRE\033[0m")
|
ap2.add_argument("--idp-gsep", metavar="RE", type=u, default="|:;+,", help="if there are multiple groups in \033[33m--idp-h-grp\033[0m, they are separated by one of the characters in \033[33mRE\033[0m")
|
||||||
ap2.add_argument("--idp-db", metavar="PATH", type=u, default=idp_db, help="where to store the known IdP users/groups (if you run multiple copyparty instances, make sure they use different DBs)")
|
ap2.add_argument("--idp-db", metavar="PATH", type=u, default=idp_db, help="where to store the known IdP users/groups (if you run multiple copyparty instances, make sure they use different DBs)")
|
||||||
ap2.add_argument("--idp-store", metavar="N", type=int, default=1, help="how to use \033[33m--idp-db\033[0m; [\033[32m0\033[0m] = entirely disable, [\033[32m1\033[0m] = write-only (effectively disabled), [\033[32m2\033[0m] = remember users, [\033[32m3\033[0m] = remember users and groups.\nNOTE: Will remember and restore the IdP-volumes of all users for all eternity if set to 2 or 3, even when user is deleted from your IdP")
|
ap2.add_argument("--idp-store", metavar="N", type=int, default=1, help="how to use \033[33m--idp-db\033[0m; [\033[32m0\033[0m] = entirely disable, [\033[32m1\033[0m] = write-only (effectively disabled), [\033[32m2\033[0m] = remember users, [\033[32m3\033[0m] = remember users and groups.\nNOTE: Will remember and restore the IdP-volumes of all users for all eternity if set to 2 or 3, even when user is deleted from your IdP")
|
||||||
|
ap2.add_argument("--idp-adm", metavar="U,U", type=u, default="", help="comma-separated list of users allowed to use /?idp (the cache management UI)")
|
||||||
ap2.add_argument("--no-bauth", action="store_true", help="disable basic-authentication support; do not accept passwords from the 'Authenticate' header at all. NOTE: This breaks support for the android app")
|
ap2.add_argument("--no-bauth", action="store_true", help="disable basic-authentication support; do not accept passwords from the 'Authenticate' header at all. NOTE: This breaks support for the android app")
|
||||||
ap2.add_argument("--bauth-last", action="store_true", help="keeps basic-authentication enabled, but only as a last-resort; if a cookie is also provided then the cookie wins")
|
ap2.add_argument("--bauth-last", action="store_true", help="keeps basic-authentication enabled, but only as a last-resort; if a cookie is also provided then the cookie wins")
|
||||||
ap2.add_argument("--ses-db", metavar="PATH", type=u, default=ses_db, help="where to store the sessions database (if you run multiple copyparty instances, make sure they use different DBs)")
|
ap2.add_argument("--ses-db", metavar="PATH", type=u, default=ses_db, help="where to store the sessions database (if you run multiple copyparty instances, make sure they use different DBs)")
|
||||||
|
|
|
@ -956,7 +956,7 @@ class AuthSrv(object):
|
||||||
broker.ask("reload", False, True).get()
|
broker.ask("reload", False, True).get()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _update_idp_db(self, uname, gname):
|
def _update_idp_db(self, uname: str, gname: str) -> None:
|
||||||
if not self.args.idp_store:
|
if not self.args.idp_store:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -2657,10 +2657,16 @@ class AuthSrv(object):
|
||||||
|
|
||||||
db = sqlite3.connect(self.args.idp_db)
|
db = sqlite3.connect(self.args.idp_db)
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
|
from_cache = cur.execute("select un, gs from us").fetchall()
|
||||||
|
cur.close()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
self.idp_accs.clear()
|
||||||
|
self.idp_usr_gh.clear()
|
||||||
|
|
||||||
gsep = self.args.idp_gsep
|
gsep = self.args.idp_gsep
|
||||||
n = []
|
n = []
|
||||||
for uname, gname in cur.execute("select un, gs from us"):
|
for uname, gname in from_cache:
|
||||||
if level < 3:
|
if level < 3:
|
||||||
if uname in self.idp_accs:
|
if uname in self.idp_accs:
|
||||||
continue
|
continue
|
||||||
|
@ -2672,9 +2678,6 @@ class AuthSrv(object):
|
||||||
self.idp_accs[uname] = gnames
|
self.idp_accs[uname] = gnames
|
||||||
n.append(uname)
|
n.append(uname)
|
||||||
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
|
|
||||||
if n and not quiet:
|
if n and not quiet:
|
||||||
t = ", ".join(n[:9])
|
t = ", ".join(n[:9])
|
||||||
if len(n) > 9:
|
if len(n) > 9:
|
||||||
|
|
|
@ -1299,6 +1299,9 @@ class HttpCli(object):
|
||||||
if "ru" in self.uparam:
|
if "ru" in self.uparam:
|
||||||
return self.tx_rups()
|
return self.tx_rups()
|
||||||
|
|
||||||
|
if "idp" in self.uparam:
|
||||||
|
return self.tx_idp()
|
||||||
|
|
||||||
if "h" in self.uparam:
|
if "h" in self.uparam:
|
||||||
return self.tx_mounts()
|
return self.tx_mounts()
|
||||||
|
|
||||||
|
@ -5537,6 +5540,32 @@ class HttpCli(object):
|
||||||
self.reply(html.encode("utf-8"), status=200)
|
self.reply(html.encode("utf-8"), status=200)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def tx_idp(self) -> bool:
|
||||||
|
if self.uname.lower() not in self.args.idp_adm_set:
|
||||||
|
raise Pebkac(403, "'idp' not allowed for user " + self.uname)
|
||||||
|
|
||||||
|
cmd = self.uparam["idp"]
|
||||||
|
if cmd.startswith("rm="):
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
|
db = sqlite3.connect(self.args.idp_db)
|
||||||
|
db.execute("delete from us where un=?", (cmd[3:],))
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
self.conn.hsrv.broker.ask("reload", False, False).get()
|
||||||
|
|
||||||
|
self.redirect("", "?idp")
|
||||||
|
return True
|
||||||
|
|
||||||
|
rows = [
|
||||||
|
[k, "[%s]" % ("], [".join(v))]
|
||||||
|
for k, v in sorted(self.asrv.idp_accs.items())
|
||||||
|
]
|
||||||
|
html = self.j2s("idp", this=self, rows=rows, now=int(time.time()))
|
||||||
|
self.reply(html.encode("utf-8"), status=200)
|
||||||
|
return True
|
||||||
|
|
||||||
def tx_shares(self) -> bool:
|
def tx_shares(self) -> bool:
|
||||||
if self.uname == "*":
|
if self.uname == "*":
|
||||||
self.loud_reply("you're not logged in")
|
self.loud_reply("you're not logged in")
|
||||||
|
@ -5611,7 +5640,7 @@ class HttpCli(object):
|
||||||
self.conn.hsrv.broker.ask("reload", False, False).get()
|
self.conn.hsrv.broker.ask("reload", False, False).get()
|
||||||
self.conn.hsrv.broker.ask("up2k.wake_rescanner").get()
|
self.conn.hsrv.broker.ask("up2k.wake_rescanner").get()
|
||||||
|
|
||||||
self.redirect(self.args.SRS + "?shares")
|
self.redirect("", "?shares")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def handle_share(self, req: dict[str, str]) -> bool:
|
def handle_share(self, req: dict[str, str]) -> bool:
|
||||||
|
|
|
@ -175,6 +175,7 @@ class HttpSrv(object):
|
||||||
"browser",
|
"browser",
|
||||||
"browser2",
|
"browser2",
|
||||||
"cf",
|
"cf",
|
||||||
|
"idp",
|
||||||
"md",
|
"md",
|
||||||
"mde",
|
"mde",
|
||||||
"msg",
|
"msg",
|
||||||
|
|
|
@ -949,6 +949,12 @@ class SvcHub(object):
|
||||||
vs = os.path.expandvars(os.path.expanduser(vs))
|
vs = os.path.expandvars(os.path.expanduser(vs))
|
||||||
setattr(al, k, vs)
|
setattr(al, k, vs)
|
||||||
|
|
||||||
|
for k in "idp_adm".split(" "):
|
||||||
|
vs = getattr(al, k)
|
||||||
|
vsa = [x.strip() for x in vs.split(",")]
|
||||||
|
vsa = [x.lower() for x in vsa if x]
|
||||||
|
setattr(al, k + "_set", set(vsa))
|
||||||
|
|
||||||
zs = "dav_ua1 sus_urls nonsus_urls ua_nodoc ua_nozip"
|
zs = "dav_ua1 sus_urls nonsus_urls ua_nodoc ua_nozip"
|
||||||
for k in zs.split(" "):
|
for k in zs.split(" "):
|
||||||
vs = getattr(al, k)
|
vs = getattr(al, k)
|
||||||
|
|
55
copyparty/web/idp.html
Normal file
55
copyparty/web/idp.html
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ s_doctitle }}</title>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=0.8">
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta name="theme-color" content="#{{ tcolor }}">
|
||||||
|
<link rel="stylesheet" media="screen" href="{{ r }}/.cpr/shares.css?_={{ ts }}">
|
||||||
|
<link rel="stylesheet" media="screen" href="{{ r }}/.cpr/ui.css?_={{ ts }}">
|
||||||
|
{{ html_head }}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="wrap">
|
||||||
|
<a href="{{ r }}/?idp">refresh</a>
|
||||||
|
<a href="{{ r }}/?h">control-panel</a>
|
||||||
|
|
||||||
|
<table id="tab"><thead><tr>
|
||||||
|
<th>forget</th>
|
||||||
|
<th>user</th>
|
||||||
|
<th>groups</th>
|
||||||
|
</tr></thead><tbody>
|
||||||
|
{% for un, gn in rows %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{{ r }}/?idp=rm={{ un|e }}">forget</a></td>
|
||||||
|
<td>{{ un|e }}</td>
|
||||||
|
<td>{{ gn|e }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody></table>
|
||||||
|
{% if not rows %}
|
||||||
|
(there are no IdP users in the cache)
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<a href="#" id="repl">π</a>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var SR="{{ r }}",
|
||||||
|
lang="{{ lang }}",
|
||||||
|
dfavico="{{ favico }}";
|
||||||
|
|
||||||
|
var STG = window.localStorage;
|
||||||
|
document.documentElement.className = (STG && STG.cpp_thm) || "{{ this.args.theme }}";
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script src="{{ r }}/.cpr/util.js?_={{ ts }}"></script>
|
||||||
|
{%- if js %}
|
||||||
|
<script src="{{ js }}_={{ ts }}"></script>
|
||||||
|
{%- endif %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -135,6 +135,10 @@
|
||||||
|
|
||||||
<h1 id="cc">other stuff:</h1>
|
<h1 id="cc">other stuff:</h1>
|
||||||
<ul>
|
<ul>
|
||||||
|
{%- if this.uname in this.args.idp_adm_set %}
|
||||||
|
<li><a id="ag" href="{{ r }}/?idp">view idp cache</a></li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{%- if this.uname != '*' and this.args.shr %}
|
{%- if this.uname != '*' and this.args.shr %}
|
||||||
<li><a id="y" href="{{ r }}/?shares">edit shares</a></li>
|
<li><a id="y" href="{{ r }}/?shares">edit shares</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -39,6 +39,7 @@ var Ls = {
|
||||||
"ad1": "no304 stopper all bruk av cache. Hvis ikke k304 var nok, prøv denne. Vil mangedoble dataforbruk!",
|
"ad1": "no304 stopper all bruk av cache. Hvis ikke k304 var nok, prøv denne. Vil mangedoble dataforbruk!",
|
||||||
"ae1": "utgående:",
|
"ae1": "utgående:",
|
||||||
"af1": "vis nylig opplastede filer",
|
"af1": "vis nylig opplastede filer",
|
||||||
|
"ag1": "vis kjente IdP-brukere",
|
||||||
},
|
},
|
||||||
"eng": {
|
"eng": {
|
||||||
"d2": "shows the state of all active threads",
|
"d2": "shows the state of all active threads",
|
||||||
|
@ -90,6 +91,7 @@ var Ls = {
|
||||||
"ad1": "启用 no304 将禁用所有缓存;如果 k304 不够,可以尝试此选项。这将消耗大量的网络流量!", //m
|
"ad1": "启用 no304 将禁用所有缓存;如果 k304 不够,可以尝试此选项。这将消耗大量的网络流量!", //m
|
||||||
"ae1": "正在下载:", //m
|
"ae1": "正在下载:", //m
|
||||||
"af1": "显示最近上传的文件", //m
|
"af1": "显示最近上传的文件", //m
|
||||||
|
"ag1": "查看已知 IdP 用户", //m
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ copyparty/web/deps/prismd.css,
|
||||||
copyparty/web/deps/scp.woff2,
|
copyparty/web/deps/scp.woff2,
|
||||||
copyparty/web/deps/sha512.ac.js,
|
copyparty/web/deps/sha512.ac.js,
|
||||||
copyparty/web/deps/sha512.hw.js,
|
copyparty/web/deps/sha512.hw.js,
|
||||||
|
copyparty/web/idp.html,
|
||||||
copyparty/web/iiam.gif,
|
copyparty/web/iiam.gif,
|
||||||
copyparty/web/md.css,
|
copyparty/web/md.css,
|
||||||
copyparty/web/md.html,
|
copyparty/web/md.html,
|
||||||
|
|
Loading…
Reference in a new issue