mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 21:26:15 -08:00
fix(server-storage): read migration maps by own playlist ids only
The browser's legacy maps and the server's user-state entries are read into null-prototype maps, so a playlist id such as `toString` is not taken for an entry and a missing server value no longer resolves to an inherited function. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a94673b4ab
commit
61c3f844d6
2 files changed
+40
-5
No files matched your search
@@ -418,4 +418,34 @@ describe('ServerMigrationService', () => {
|
||||
expect.objectContaining({ _id: 's1', isFullStalkerPortal: true })
|
||||
);
|
||||
});
|
||||
|
||||
it("does not take an inherited name for a playlist id's data", async () => {
|
||||
TestBed.overrideProvider(NgxIndexedDBService, {
|
||||
useValue: {
|
||||
getAll: () =>
|
||||
of([{ _id: 'toString', title: 'Odd id', url: 'http://x' }]),
|
||||
},
|
||||
});
|
||||
localStorage.setItem(
|
||||
'xtream-favorites',
|
||||
JSON.stringify({ toString: ['live:1'] })
|
||||
);
|
||||
// The server has the namespace, but no entry for that id.
|
||||
session.api.getJson.mockResolvedValue({
|
||||
entries: { 'xtream-favorites': {} },
|
||||
tags: { 'xtream-favorites': {} },
|
||||
});
|
||||
|
||||
const result = await TestBed.inject(
|
||||
ServerMigrationService
|
||||
).moveBrowserData();
|
||||
|
||||
expect(result.failed).toBe(0);
|
||||
expect(session.api.sendJson).toHaveBeenCalledWith(
|
||||
'PUT',
|
||||
'/user-state/xtream-favorites/toString',
|
||||
{ value: ['live:1'] },
|
||||
{ 'If-None-Match': '*' }
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -16,7 +16,8 @@ import {
|
||||
unionItems,
|
||||
} from './server-migration-merge';
|
||||
import { planServerMigration } from './server-migration-plan';
|
||||
import { preconditionHeaders } from './server-user-data-entries';
|
||||
import { withoutDeleted } from './server-user-data-edit';
|
||||
import { idMap, preconditionHeaders } from './server-user-data-entries';
|
||||
import {
|
||||
typeLegacyXtreamRefs,
|
||||
type XtreamUserData,
|
||||
@@ -205,10 +206,14 @@ export class ServerMigrationService {
|
||||
if (targets.size === 0) {
|
||||
return 0;
|
||||
}
|
||||
const { entries, tags } =
|
||||
// Maps keyed by playlist id without a prototype: an id such as
|
||||
// `toString` is not mistaken for an entry.
|
||||
const { entries, tags } = withoutDeleted(
|
||||
await this.session.api.getJson<ServerUserStateResponse>(
|
||||
'/user-state'
|
||||
);
|
||||
),
|
||||
[]
|
||||
);
|
||||
// A map this browser has but cannot read fails the move, so it
|
||||
// stays on offer instead of being marked done without it.
|
||||
let unreadable = 0;
|
||||
@@ -369,12 +374,12 @@ function readLegacyMap(key: string): Record<string, unknown> | null {
|
||||
return null;
|
||||
}
|
||||
if (value === null) {
|
||||
return {};
|
||||
return idMap();
|
||||
}
|
||||
try {
|
||||
const parsed: unknown = JSON.parse(value);
|
||||
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
||||
? (parsed as Record<string, unknown>)
|
||||
? idMap(parsed as Record<string, unknown>)
|
||||
: null;
|
||||
} catch {
|
||||
return null;
|
||||
|
||||
Reference in new issue
Block a user