155 lines
4.5 KiB
Python
155 lines
4.5 KiB
Python
# retoor <retoor@molodetz.nl>
|
|||
|
|
from datetime import datetime, timedelta, timezone
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
from pypdf import PdfReader
|
||
|
|
|
||
|
|
from molodetz import config
|
||
|
|
from molodetz.attachments import orphan_blobs
|
||
|
|
from molodetz.bootstrap import bootstrap_admin
|
||
|
|
from molodetz.content import create_post
|
||
|
|
from molodetz.database import (
|
||
|
|
all_posts,
|
||
|
|
enqueue_backup,
|
||
|
|
generate_uid,
|
||
|
|
get_user_by_username,
|
||
|
|
init_db,
|
||
|
|
list_backups,
|
||
|
|
list_join_requests,
|
||
|
|
list_users,
|
||
|
|
prune_audit,
|
||
|
|
prune_expired_sessions,
|
||
|
|
set_role,
|
||
|
|
update_user,
|
||
|
|
)
|
||
|
|
from molodetz.database.sql_lint import lint
|
||
|
|
from molodetz.emoji_builder import write_js_module
|
||
|
|
from molodetz.services.backup import clear_backups, process_backup, prune_backups
|
||
|
|
from molodetz.utils.audit import record_system
|
||
|
|
|
||
|
|
|
||
|
|
def prepare():
|
||
|
|
config.ensure_data_dirs()
|
||
|
|
init_db()
|
||
|
|
|
||
|
|
|
||
|
|
def _user(username):
|
||
|
|
user = get_user_by_username(username)
|
||
|
|
if user is None:
|
||
|
|
raise SystemExit(f"Onbekende gebruiker: {username}")
|
||
|
|
return user
|
||
|
|
|
||
|
|
|
||
|
|
def role_get(args):
|
||
|
|
print(_user(args.username).get("role"))
|
||
|
|
|
||
|
|
|
||
|
|
def role_set(args):
|
||
|
|
user = _user(args.username)
|
||
|
|
set_role(user["uid"], args.role)
|
||
|
|
record_system("admin.user.role", actor_kind="cli", origin="cli", payload={"role": args.role}, targets=[("user", user["uid"])])
|
||
|
|
print(f"{user['username']} -> {args.role}")
|
||
|
|
|
||
|
|
|
||
|
|
def apikey_get(args):
|
||
|
|
print(_user(args.username).get("api_key"))
|
||
|
|
|
||
|
|
|
||
|
|
def apikey_reset(args):
|
||
|
|
user = _user(args.username)
|
||
|
|
key = generate_uid()
|
||
|
|
update_user(user["uid"], api_key=key)
|
||
|
|
record_system("profile.apikey.regenerate", actor_kind="cli", origin="cli", targets=[("user", user["uid"])])
|
||
|
|
print(key)
|
||
|
|
|
||
|
|
|
||
|
|
def apikey_backfill(args):
|
||
|
|
changed = 0
|
||
|
|
for user in list_users(limit=100000):
|
||
|
|
if not user.get("api_key"):
|
||
|
|
update_user(user["uid"], api_key=generate_uid())
|
||
|
|
changed += 1
|
||
|
|
print(f"{changed} sleutels aangevuld")
|
||
|
|
|
||
|
|
|
||
|
|
def posts_list(args):
|
||
|
|
for post in all_posts():
|
||
|
|
flag = " [placeholder]" if post.get("is_placeholder") else ""
|
||
|
|
print(f"{post['uid']} {post['status']:<9} {post['topic']:<9} {post['title']}{flag}")
|
||
|
|
|
||
|
|
|
||
|
|
def read_source(path):
|
||
|
|
path = Path(path)
|
||
|
|
if path.suffix.lower() == ".pdf":
|
||
|
|
reader = PdfReader(str(path))
|
||
|
|
return "\n\n".join((page.extract_text() or "").strip() for page in reader.pages).strip()
|
||
|
|
return path.read_text(encoding="utf-8")
|
||
|
|
|
||
|
|
|
||
|
|
def posts_import(args):
|
||
|
|
path = Path(args.path)
|
||
|
|
if not path.is_file():
|
||
|
|
raise SystemExit(f"Bestand niet gevonden: {path}")
|
||
|
|
body = read_source(path)
|
||
|
|
title = args.title or path.stem.replace("-", " ").replace("_", " ").strip().capitalize()
|
||
|
|
author = bootstrap_admin() or _user(config.ADMIN_USERNAME)
|
||
|
|
post = create_post(author, title, body, args.topic, "published" if args.publish else "draft")
|
||
|
|
print(f"Geimporteerd: {post['uid']} {post['title']}")
|
||
|
|
|
||
|
|
|
||
|
|
def joins_list(args):
|
||
|
|
for row in list_join_requests(limit=1000):
|
||
|
|
print(f"{row['created_at']} {row['status']:<9} {row['name']} {row['contact']} {row.get('repo_url') or '-'}")
|
||
|
|
|
||
|
|
|
||
|
|
def backups_list(args):
|
||
|
|
for row in list_backups(limit=1000):
|
||
|
|
print(f"{row['uid']} {row['status']:<8} {row['target']:<9} {row.get('stored_name') or '-'} {row.get('size_bytes') or 0}")
|
||
|
|
|
||
|
|
|
||
|
|
def backups_run(args):
|
||
|
|
row = enqueue_backup(args.target, None)
|
||
|
|
ok = process_backup(row, args.codec)
|
||
|
|
print("klaar" if ok else "mislukt")
|
||
|
|
return 0 if ok else 1
|
||
|
|
|
||
|
|
|
||
|
|
def backups_prune(args):
|
||
|
|
count = prune_backups(args.keep, dry_run=args.dry_run)
|
||
|
|
print(f"{count} archieven {'zouden worden verwijderd' if args.dry_run else 'verwijderd'}")
|
||
|
|
|
||
|
|
|
||
|
|
def backups_clear(args):
|
||
|
|
count = clear_backups(dry_run=args.dry_run)
|
||
|
|
print(f"{count} archieven {'zouden worden verwijderd' if args.dry_run else 'verwijderd'}")
|
||
|
|
|
||
|
|
|
||
|
|
def sessions_prune(args):
|
||
|
|
print(f"{prune_expired_sessions(dry_run=args.dry_run)} verlopen sessies")
|
||
|
|
|
||
|
|
|
||
|
|
def audit_prune(args):
|
||
|
|
cutoff = (datetime.now(timezone.utc) - timedelta(days=args.days)).isoformat()
|
||
|
|
print(f"{prune_audit(cutoff, dry_run=args.dry_run)} auditregels ouder dan {args.days} dagen")
|
||
|
|
|
||
|
|
|
||
|
|
def system_prune(args):
|
||
|
|
orphans = orphan_blobs()
|
||
|
|
for path in orphans:
|
||
|
|
print(("zou verwijderen: " if args.dry_run else "verwijderd: ") + str(path))
|
||
|
|
if not args.dry_run:
|
||
|
|
path.unlink(missing_ok=True)
|
||
|
|
print(f"{len(orphans)} wees-blobs")
|
||
|
|
|
||
|
|
|
||
|
|
def system_sql_lint(args):
|
||
|
|
problems = lint()
|
||
|
|
for problem in problems:
|
||
|
|
print(problem)
|
||
|
|
print(f"{len(problems)} problemen")
|
||
|
|
return 1 if problems else 0
|
||
|
|
|
||
|
|
|
||
|
|
def emoji_regenerate(args):
|
||
|
|
print(write_js_module())
|