Scan manually added accounts
Build — Windows, Linux & macOS / GDPRScanner / linux (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / macos (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / windows (push) Has been cancelled
Build — Windows, Linux & macOS / Create GitHub Release (push) Has been cancelled

Manual accounts were never scanned:
- Sidebar "add user" entries had no platform, and getSelectedUsers()
  required platform === 'm365', so they were dropped from every scan.
- Profile-editor manual accounts were stored as "manual:<email>", which
  is not a Graph user id, and applying the profile never put them in the
  sidebar list, so they could not be selected.

Now the editor looks the email up via /api/users/lookup and stores the
directory id plus name/email (falling back to manual:<email> only when the
lookup fails). Applying a profile adds its manual accounts to the sidebar
and resolves legacy manual:<email> entries, logging any that can't be
found. The scan engine resolves remaining manual:<email> ids (e.g. from
scheduled scans) via the new M365Connector.lookup_user(), skipping and
reporting failures without widening to all users.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit was merged in pull request #1.
This commit is contained in:
StyxX65andClaude Opus 5.5 committed 2026-09-28 09:27:56 +02:00
1 parent bbe9c62ff9
commit 1c79ac15b7
11 files changed
+234 -18

No files matched your search

+32
View File
@@ -41,6 +41,37 @@ except ImportError:
from routes import state as _state
_MANUAL_PREFIX = "manual:"
def _resolve_manual_users(conn, user_ids: list[dict]) -> list[dict]:
"""Resolve profile accounts saved as "manual:<email>" to their directory id.
Older profile-editor saves (and saves made while M365 was not connected)
store manual accounts by email only; Graph needs the user id. Accounts that
can't be resolved are reported and skipped — never widened to "all users".
"""
resolved, seen = [], set()
for u in user_ids:
uid = u.get("id", "")
if uid.startswith(_MANUAL_PREFIX):
upn = uid[len(_MANUAL_PREFIX):]
try:
data = conn.lookup_user(upn)
_email = data.get("mail") or data.get("userPrincipalName", upn)
u = {**u, "id": data["id"],
"displayName": _resolve_display_name(data.get("displayName", ""), _email, upn)}
except Exception as e:
logger.warning("[run_scan] manual account %r not found: %s", upn, e)
broadcast("scan_error", {"file": upn, "error": f"Manual account not found in M365: {e}"})
continue
if u["id"] in seen:
continue
seen.add(u["id"])
resolved.append(u)
return resolved
def _get_scan_abort():
return _state._scan_abort
@@ -645,6 +676,7 @@ def run_scan(options: dict):
me_info.get("displayName", ""),
me_info.get("mail") or me_info.get("userPrincipalName", "me"))}]
else:
user_ids = _resolve_manual_users(conn, user_ids)
sample = user_ids[0] if user_ids else None
logger.info("[run_scan] user_ids: %d entries, type=%s, sample=%s",
len(user_ids), type(user_ids).__name__, sample)