Add reviewed resolution for missing user identity links
This commit is contained in:
@@ -116,7 +116,10 @@ async def seerr_directory(runtime):
|
||||
return {"state": "unavailable", "users": []}
|
||||
|
||||
|
||||
def build_report(local, jellyfin, seerr, jellystat, runtime):
|
||||
def build_report(local, jellyfin, seerr, jellystat, runtime, selections=None):
|
||||
selections = selections or {}
|
||||
if any(user_id not in {user['id'] for user in local['users']} for user_id in selections):
|
||||
raise HTTPException(404, "This Magent account no longer exists. Run the check again.")
|
||||
jf_by_id = {row["id"]: row for row in jellyfin["users"]}
|
||||
jf_by_name = defaultdict(list)
|
||||
for row in jellyfin["users"]:
|
||||
@@ -155,6 +158,11 @@ def build_report(local, jellyfin, seerr, jellystat, runtime):
|
||||
candidate, basis = stored_seerr["jellyfin_id"], "stored_seerr_id"
|
||||
elif user["auth_provider"] == "jellyfin" and len(by_name) == 1:
|
||||
candidate, basis = by_name[0], "suggested_username"
|
||||
if user["id"] in selections:
|
||||
chosen = selections[user["id"]]
|
||||
if saved and chosen != saved["jellyfin_user_id"]:
|
||||
issues.append("A confirmed identity cannot be replaced through missing-link resolution.")
|
||||
candidate, basis = chosen, "admin_selected"
|
||||
if len(local_by_name[name_key(user["username"])]) > 1:
|
||||
issues.append("Multiple Magent rows share this username after case and whitespace normalization.")
|
||||
if len(local_by_seerr.get(user["jellyseerr_user_id"], [])) > 1:
|
||||
@@ -217,6 +225,7 @@ def build_report(local, jellyfin, seerr, jellystat, runtime):
|
||||
"not_checked" if not jellystat else
|
||||
"unavailable" if any(r["state"] == "unavailable" for r in jellystat.values()) else "available"}
|
||||
report = {"server_id": jellyfin.get("server_id"), "services": services, "rows": rows, "upstream": upstream,
|
||||
"jellyfin_users": jellyfin["users"],
|
||||
"counts": {"magent": len(rows), "jellyfin": len(jellyfin["users"]), "seerr": len(seerr["users"]),
|
||||
"jellystat_checked": sum(r["state"] in {"matched", "missing"} for r in jellystat.values()),
|
||||
**{state: sum(row["state"] == state for row in rows) for state in ("ready", "confirmed", "conflict", "unlinked", "unavailable")}}}
|
||||
@@ -225,7 +234,7 @@ def build_report(local, jellyfin, seerr, jellystat, runtime):
|
||||
return report
|
||||
|
||||
|
||||
async def review_identities():
|
||||
async def review_identities(selections=None):
|
||||
runtime = await asyncio.to_thread(get_runtime_settings)
|
||||
local, jf, seerr = await asyncio.gather(asyncio.to_thread(read_snapshot), jellyfin_directory(runtime), seerr_directory(runtime))
|
||||
if len(local["users"]) > MAX_USERS:
|
||||
@@ -238,7 +247,7 @@ async def review_identities():
|
||||
raise HTTPException(422, "There are too many upstream IDs for one identity check.")
|
||||
stats_client = JellystatClient(runtime.jellystat_base_url, runtime.jellystat_api_key)
|
||||
js = await stats_client.check_user_ids(sorted(ids)) if stats_client.configured() else {key: {"state": "not_configured"} for key in ids}
|
||||
return build_report(local, jf, seerr, js, runtime), local, runtime
|
||||
return build_report(local, jf, seerr, js, runtime, selections), local, runtime
|
||||
|
||||
|
||||
def save_confirmations(report, local, runtime, user_ids, admin):
|
||||
@@ -275,3 +284,13 @@ async def confirm_identities(revision, user_ids, admin):
|
||||
if report["revision"] != revision:
|
||||
raise HTTPException(409, "The identity check has changed. Run it again before confirming accounts.")
|
||||
return await asyncio.to_thread(save_confirmations, report, local, runtime, user_ids, admin)
|
||||
|
||||
|
||||
async def resolve_identity(user_id, jellyfin_user_id, revision=None, admin=None):
|
||||
report, local, runtime = await review_identities({user_id: jellyfin_user_id})
|
||||
if revision is not None:
|
||||
if report["revision"] != revision:
|
||||
raise HTTPException(409, "Accounts or service mappings changed. Check the selected account again before saving.")
|
||||
return await asyncio.to_thread(save_confirmations, report, local, runtime, [user_id], admin)
|
||||
return {"revision": report["revision"], "server_id": report["server_id"],
|
||||
"row": next(row for row in report["rows"] if row["user"]["id"] == user_id)}
|
||||
|
||||
Reference in New Issue
Block a user