mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-17 02:05:22 -04:00
fix: backup import dropping a user's skill on cross-tenant title/id collision (#2057)
* Fix backup import dropping a user's skill on cross-tenant title/id collision The skills block of import_data deduped incoming skills against skills_manager.load_all(), which returns EVERY tenant's skills. So when a user imports their own backup, any skill whose id or title collides with another user's skill was silently skipped — the importing user lost their own data. This is the same cross-tenant bug already fixed for the memories block just above (#1743); the skills block was left with the old pattern. Filter the dedup sets to the importing user's own skills (owner == user); the full store is still saved back, preserving other users' skills. * Restore sys.modules after stubbing so backup test does not break collection of later src.* test modules * Patch backup_routes auth helpers via monkeypatch instead of sys.modules stubs so the test is import-order robust * Give FakeSkillsManager an add_skill method matching the disk-backed skills API
This commit is contained in:
@@ -101,11 +101,17 @@ def setup_backup_routes(memory_manager, preset_manager, skills_manager) -> APIRo
|
||||
# ── Skills ──
|
||||
if "skills" in body and isinstance(body["skills"], list):
|
||||
existing = skills_manager.load_all()
|
||||
existing_names = {s.get("name") for s in existing if s.get("name")}
|
||||
existing_ids = {s.get("id") for s in existing if s.get("id")}
|
||||
# Dedup against THIS user's own skills only. Using every tenant's
|
||||
# rows (load_all) meant a skill whose id/name/title matched any
|
||||
# other user's was silently skipped, so the importing user lost
|
||||
# their own data — same cross-tenant bug fixed for memories above.
|
||||
# The full store is still saved back below.
|
||||
own = [s for s in existing if s.get("owner") == user]
|
||||
existing_names = {s.get("name") for s in own if s.get("name")}
|
||||
existing_ids = {s.get("id") for s in own if s.get("id")}
|
||||
existing_titles = {
|
||||
(s.get("title") or s.get("description") or "").strip().lower()
|
||||
for s in existing
|
||||
for s in own
|
||||
}
|
||||
added = 0
|
||||
for skill in body["skills"]:
|
||||
|
||||
Reference in New Issue
Block a user