feat: scan history browser, user-scoped viewer tokens, export fixes, email fixes (v1.6.20)
- Scan history browser (history.js, GET /api/db/sessions, get_sessions(), get_session_items(ref_scan_id)) — review any past session without rescanning - User-scoped viewer tokens (#34) — scope by individual employee across M365 and GWS; autocomplete from Accounts list; dual-email support - Fix: GWS scan never marked finished (end_scan → finish_scan) and emitted wrong SSE event (scan_done → google_scan_done), excluding GWS items from all exports - Fix: file scan begin_scan called with wrong keyword args (TypeError swallowed), so local/SMB items were never written to DB - Fix: Graph sendMail reported failure on success — _post() now returns {} on empty 202 response instead of raising JSONDecodeError - Fix: Graph error hidden behind generic "No SMTP host" message when both Graph and SMTP were unavailable - Fix: Gmail vs Google Workspace SMTP error messages distinguished by username domain; Workspace errors point to admin console, not personal security settings - Docs: update README, MANUAL-EN, MANUAL-DA, CLAUDE.md, TODO.md, CHANGELOG.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
e64d7eb958
commit
c9aab19a97
24 files changed
+753
-70
No files matched your search
+19
-1
@@ -78,9 +78,27 @@ def create_token():
|
||||
if not isinstance(raw_scope, dict):
|
||||
return jsonify({"error": "scope must be an object"}), 400
|
||||
role = str(raw_scope.get("role", "")).strip()
|
||||
# user may be a single email string (legacy) or a list of email strings
|
||||
raw_user = raw_scope.get("user", "")
|
||||
if isinstance(raw_user, str):
|
||||
user_emails = [raw_user.strip().lower()] if raw_user.strip() else []
|
||||
elif isinstance(raw_user, list):
|
||||
user_emails = [str(e).strip().lower() for e in raw_user if str(e).strip()]
|
||||
else:
|
||||
user_emails = []
|
||||
display_name = str(raw_scope.get("display_name", "")).strip()
|
||||
if role and user_emails:
|
||||
return jsonify({"error": "scope.role and scope.user are mutually exclusive"}), 400
|
||||
if role not in ("", "student", "staff"):
|
||||
return jsonify({"error": "scope.role must be '', 'student', or 'staff'"}), 400
|
||||
scope = {"role": role} if role else {}
|
||||
if user_emails and not all("@" in e for e in user_emails):
|
||||
return jsonify({"error": "scope.user entries must be valid email addresses"}), 400
|
||||
if user_emails:
|
||||
scope = {"user": user_emails, "display_name": display_name or user_emails[0]}
|
||||
elif role:
|
||||
scope = {"role": role}
|
||||
else:
|
||||
scope = {}
|
||||
entry = create_viewer_token(label=label, expires_days=expires_days, scope=scope)
|
||||
return jsonify(entry), 201
|
||||
|
||||
|
||||
Reference in new issue
Block a user