Initial commit: SHARED library with LFS for binary assets
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import secrets
|
||||
from pathlib import Path
|
||||
|
||||
from relay_gateway.keys import hash_token, CHANNELS_FOR_LEVEL
|
||||
|
||||
|
||||
def _read(path: Path) -> dict:
|
||||
try:
|
||||
return json.loads(Path(path).read_text(encoding="utf-8"))
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
return {}
|
||||
|
||||
|
||||
def _write(path: Path, body: dict) -> None:
|
||||
Path(path).write_text(json.dumps(body, indent=2), encoding="utf-8")
|
||||
|
||||
|
||||
def add_key(path: Path, *, name: str, level: str) -> str:
|
||||
if level not in CHANNELS_FOR_LEVEL:
|
||||
raise ValueError(f"level must be one of {sorted(CHANNELS_FOR_LEVEL)}")
|
||||
token = secrets.token_urlsafe(32)
|
||||
body = _read(path)
|
||||
body[hash_token(token)] = {"name": name, "level": level}
|
||||
_write(path, body)
|
||||
return token
|
||||
|
||||
|
||||
def list_keys(path: Path) -> list[dict]:
|
||||
return [{"hash": h, **meta} for h, meta in _read(path).items()]
|
||||
|
||||
|
||||
def revoke(path: Path, name: str) -> int:
|
||||
body = _read(path)
|
||||
to_remove = [h for h, meta in body.items() if meta.get("name") == name]
|
||||
for h in to_remove:
|
||||
del body[h]
|
||||
_write(path, body)
|
||||
return len(to_remove)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Manage relay gateway keys")
|
||||
ap.add_argument("--file", required=True, type=Path)
|
||||
sub = ap.add_subparsers(dest="cmd", required=True)
|
||||
a = sub.add_parser("add"); a.add_argument("--name", required=True); a.add_argument("--level", required=True)
|
||||
sub.add_parser("list")
|
||||
r = sub.add_parser("revoke"); r.add_argument("--name", required=True)
|
||||
args = ap.parse_args()
|
||||
if args.cmd == "add":
|
||||
token = add_key(args.file, name=args.name, level=args.level)
|
||||
print(f"Token for {args.name!r} (level={args.level}) — store it now, shown once:\n{token}")
|
||||
elif args.cmd == "list":
|
||||
for e in list_keys(args.file):
|
||||
print(f"{e['name']:20s} {e['level']:4s} {e['hash'][:12]}…")
|
||||
elif args.cmd == "revoke":
|
||||
print(f"Removed {revoke(args.file, args.name)} key(s) named {args.name!r}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user