Changes in / [5a49eba:2365630] in Klonkt


Ignore:
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/services/ArchiveImportService.js

    r5a49eba r2365630  
    285285  rapport.origin = manifest.origin || null;
    286286
    287   // IDENTITEIT. Het INTERNE id blijft altijd (Robins besluit, 14-8).
    288   //
    289   // Dat is iets anders dan de AP-URI. Die is domeingebonden en wordt hoe dan
    290   // ook nieuw: https://nieuw/ap/notes/<id> is een ander adres dan
    291   // https://oud/ap/notes/<id>. Je claimt dus niets van een ander door het GUID
    292   // te hergebruiken, en je wint dat elke INTERNE verwijzing blijft kloppen:
    293   // [[track:]], [[playlist:]] en [[album:]] wijzen na een verhuizing nog naar
    294   // het goede ding.
    295   //
    296   // Voorheen hing dit aan de origin, en alleen voor posts; tracks en playlists
    297   // hielden hun id al wel. Die scheve tabel was precies waarom een post uit de
    298   // zip met [[track:oud]] naast een nummer uit de pull met een nieuw id kwam te
    299   // staan, en je de shorthand als kale tekst in je bericht zag.
    300   //
    301   // `idsBehouden` gaat hieronder alleen nog over de AP-URI: gelijke origin
    302   // betekent dat ook die identiek blijft, en dan valt er niets te vertalen.
     287  // IDENTITEIT. Gelijke origin -> de AP-ids blijven, en daarmee vinden de boosts
     288  // en antwoorden die er al naar wijzen hun post terug. Anders nieuwe ids, want
     289  // een id op andermans domein publiceren is een vervalsingsoppervlak en andere
     290  // servers halen het daar toch op.
    303291  const idsBehouden = !!(manifest.origin && eigenOrigin && manifest.origin === eigenOrigin);
    304292  rapport.idsBehouden = idsBehouden;
    305293  if (!idsBehouden) {
    306294    rapport.waarschuwingen.push(
    307       `origin verschilt (archief ${manifest.origin || '?'} vs deze site ${eigenOrigin || '?'}): de berichten krijgen een nieuw AP-adres. Hun interne id blijft, dus verwijzingen binnen je site blijven kloppen.`,
     295      `origin verschilt (archief ${manifest.origin || '?'} vs deze site ${eigenOrigin || '?'}): nieuwe AP-ids, de oude blijven als verwijzing staan`,
    308296    );
    309297  }
     
    319307    const o = JSON.parse(files.get(pad).toString('utf8'));
    320308    const oudId = decodeURIComponent(String(o.id || '').split('/ap/notes/')[1] || path.basename(pad, '.json'));
    321     // Altijd het id uit het archief. Staat er hier al iets met dat id, dan is
    322     // dat hetzelfde object, en dat handelt de botsingscontrole hieronder af.
    323     const nieuwId = oudId;
     309    const nieuwId = idsBehouden ? oudId : randomUUID();
    324310    idKaart.set(oudId, nieuwId);
    325311
  • src/services/MigrationService.js

    r5a49eba r2365630  
    417417        if (auteur && auteur !== bronActor.id) continue;              // alleen wat van HEM was
    418418        gezien++;
    419         // Het interne id BLIJFT (Robins besluit, 14-8). Daarmee is "staat hij
    420         // hier al" gewoon een blik in de tabel, en niet iets dat je uit een
    421         // aparte mapping moet afleiden. Verwijder je een bericht en haal je
    422         // opnieuw op, dan komt het gewoon terug: er staat immers niets meer.
    423         const id = ruwId(o.id) || crypto.randomUUID();
    424         if (db.prepare('SELECT 1 FROM posts WHERE id = ? AND site_id = ?').get(id, site.id)) {
    425           rapport.overgeslagen++;
    426           continue;
    427         }
    428         if (migrationTarget(site.slug, o.id)) rapport.opnieuw++;   // was er, is weg, komt terug
     419        // Al binnen? Alleen overslaan als het bericht er OOK nog staat. Heb je
     420        // het verwijderd, dan is opnieuw ophalen precies wat je bedoelt, en
     421        // een mapping die dat blokkeert is een val: opruimen hielp dan niet,
     422        // want de blokkade zat in ap_migration en niet in de posts.
     423        const eerderPost = migrationTarget(site.slug, o.id);
     424        if (eerderPost) {
     425          const postId = String(eerderPost).split('/').pop();
     426          if (db.prepare('SELECT 1 FROM posts WHERE id = ? AND site_id = ?').get(decodeURIComponent(postId), site.id)) {
     427            rapport.overgeslagen++;
     428            continue;
     429          }
     430          rapport.opnieuw++;   // weg hier, dus opnieuw binnenhalen
     431        }
    429432
    430433        // Media eerst, want een post die naar een plaatje wijst dat we niet
     
    448451        }
    449452
     453        const id = crypto.randomUUID();
    450454        const cover = binnen.find((b) => AFBEELDING.test(b.type || ''));
    451455        const rest = binnen.filter((b) => b !== cover);
     
    522526        // Alleen LEGE velden worden gevuld. Wat jij zelf hebt aangepast blijft
    523527        // staan; een migratie hoort je correcties niet terug te draaien.
    524         const trackId = ruwId(a.id) || crypto.randomUUID();
    525         {
     528        const eerder = migrationTarget(site.slug, a.id);
     529        if (eerder) {
     530          const lokaalId = String(eerder).split('/').pop();
    526531          const rij = db.prepare('SELECT id, cover_url, duration, artist FROM audio_tracks WHERE id = ? AND site_id = ?')
    527             .get(trackId, site.id);
     532            .get(lokaalId, site.id);
    528533          if (rij) {
    529534            trackKaart.set(String(a.id), rij.id);   // MOET, anders vinden de playlists hem niet
     
    552557            continue;
    553558          }
     559          // De rij is weg maar de mapping staat er nog. Dan is opnieuw ophalen
     560          // precies wat je wilt, dus we vallen door naar de gewone tak.
    554561        }
    555562        const bron = a.url && (typeof a.url === 'string' ? a.url : (Array.isArray(a.url) ? (a.url[0] && (a.url[0].href || a.url[0])) : a.url.href));
     
    576583          else rapport.waarschuwingen.push(`hoes niet opgehaald: ${a.name || hoesUrl}`);
    577584        }
     585        const trackId = crypto.randomUUID();
    578586        const mediaId = crypto.randomUUID();
    579587        try {
     
    643651          continue;
    644652        }
     653        // Bestond hij al? Dan dezelfde rij bijwerken. Zonder deze stap levert
     654        // elke tweede ronde een dubbele plaat op.
     655        const eerderPl = migrationTarget(site.slug, uri);
    645656        // De hoes van de plaat, net als bij een nummer.
    646657        let plHoes = null;
     
    654665          else rapport.waarschuwingen.push(`hoes van playlist niet opgehaald: ${plc.name || uri}`);
    655666        }
    656         // Ook hier het id van de bron. Dan blijft [[playlist:<id>]] in een
    657         // bericht wijzen, en is een tweede ronde vanzelf dezelfde rij.
    658         const plId = ruwId(uri) || crypto.randomUUID();
     667        const plId = (() => {
     668          if (!eerderPl) return crypto.randomUUID();
     669          const bestaand = String(eerderPl).split('/').pop();
     670          return db.prepare('SELECT 1 FROM playlists WHERE id = ? AND site_id = ?').get(bestaand, site.id)
     671            ? bestaand : crypto.randomUUID();
     672        })();
    659673        try {
    660674          db.prepare(`INSERT INTO playlists (id, site_id, title, artist, year, kind, cover_url) VALUES (?,?,?,?,?,?,?)
  • test/archive-import.test.js

    r5a49eba r2365630  
    126126});
    127127
    128 test('een andere origin geeft een nieuw AP-adres, maar het interne id BLIJFT', () => {
    129   // Omgedraaid op 14-8 (Robin: "altijd behouden"). Het interne id is niet
    130   // hetzelfde als de AP-URI: https://nieuw/ap/notes/<id> is een ander adres dan
    131   // https://oud/ap/notes/<id>, dus je claimt niets van een ander door het GUID
    132   // te hergebruiken. Wat je wint is dat elke INTERNE verwijzing blijft kloppen.
    133   //
    134   // Het oude gedrag brak precies dat: een post uit de zip hield
    135   // [[track:<oud id>]] in zijn tekst terwijl het nummer een nieuw id kreeg, en
    136   // dan zie je de shorthand als kale tekst in je bericht staan.
     128test('een andere origin levert NIEUWE ids op, met een waarschuwing', () => {
     129  // Oude ids houden op een ander domein zou objecten publiceren onder een id dat
     130  // je niet beheert -- andere servers halen dat daar op, en het is bovendien een
     131  // vervalsingsoppervlak.
    137132  leeg();
    138133  const files = new Map(ARCHIEF.files);
     
    141136  files.set('manifest.json', Buffer.from(JSON.stringify(m)));
    142137  const r = AI.importArchive(files, { slug: 'me' });
    143   assert.equal(r.idsBehouden, false, 'de AP-URI verandert wel, en dat blijft gemeld');
     138  assert.equal(r.idsBehouden, false);
    144139  assert.match(r.waarschuwingen.join(' '), /origin verschilt/);
    145   assert.equal(db.prepare("SELECT COUNT(*) AS n FROM posts WHERE id = 'zwaar'").get().n, 1,
    146     'het interne id komt ongewijzigd terug');
    147   assert.equal(db.prepare('SELECT COUNT(*) AS n FROM posts').get().n, 1);
     140  assert.equal(db.prepare("SELECT COUNT(*) AS n FROM posts WHERE id = 'zwaar'").get().n, 0);
     141  assert.equal(db.prepare('SELECT COUNT(*) AS n FROM posts').get().n, 1, 'wel geimporteerd, met een nieuw id');
    148142});
    149143
  • test/fep1580-migration.test.js

    r5a49eba r2365630  
    481481});
    482482
    483 test('de [[track:]]-verwijzing in een bericht blijft naar een bestaand nummer wijzen', async () => {
     483test('de [[track:]]-verwijzing in een bericht wordt bijgetrokken', async () => {
    484484  // Wat Robin op TikTik zag: het bericht toonde de shorthand zelf in plaats van
    485485  // een speler. Zijn posts kwamen uit de ZIP (die bewaart posts.content
     
    515515  }));
    516516
    517   // DE EIS, ongeacht hoe: na een verhuizing wijst de shorthand naar een nummer
    518   // dat hier bestaat. Sinds "altijd behouden" (14-8) klopt dat meestal vanzelf,
    519   // want het id verandert niet meer. Botst het id wel, dan trekt de ingest de
    520   // tekst bij. Deze test toetst de UITKOMST en niet de route ernaartoe.
    521517  const inhoud = db.prepare("SELECT content FROM posts WHERE id = 'pz'").get().content;
    522518  const m = /\[\[track:([^\]]+)\]\]/.exec(inhoud);
    523   assert.ok(m, 'de shorthand blijft staan');
     519  assert.ok(m, 'de shorthand blijft staan, alleen het id verandert');
     520  assert.notEqual(m[1], 't-oud', 'het oude id wijst hier nergens heen');
    524521  const bestaat = db.prepare('SELECT 1 FROM audio_tracks WHERE id = ? AND site_id = ?').get(m[1], 's1');
    525   assert.ok(bestaat, `[[track:${m[1]}]] hoort bij een nummer dat er echt is`);
    526   assert.equal(m[1], 't-oud', 'en omdat het id behouden blijft, hoefde er niets herschreven');
    527 });
    528 
    529 test('botst het track-id wel, dan wordt de tekst bijgetrokken', async () => {
    530   // Het vangnet. "Altijd behouden" kan niet als er hier al iets anders met dat
    531   // id staat; dan krijgt het nummer een ander id en moet de shorthand mee.
    532   const s2 = site({ aliases: [BRON] });
    533   db.prepare(`INSERT INTO posts (id, site_id, author_id, slug, title, content, status, published_at)
    534               VALUES ('pb','s1','u1','botsing','Botsing','<p>[[track:t-bots]]</p>','published','2026-08-13T10:00:00Z')`).run();
    535   // Een nummer dat hier AL bestaat onder datzelfde id, van iets anders.
    536   db.prepare("INSERT INTO media (id, site_id, filename, mime_type, size, storage_path) VALUES ('mx','s1','x.mp3','audio/mpeg',1,'/x')").run();
    537   db.prepare("INSERT INTO audio_tracks (id, site_id, title, media_id) VALUES ('t-bots','s1','Al van mij','mx')").run();
    538 
    539   const kaart2 = new Map([
    540     [BRON, { id: BRON, type: 'Person', movedTo: IK, outbox: `${BRON}/outbox`, streams: [`${BRON}/tracks`] }],
    541     [`${BRON}/outbox`, { type: 'OrderedCollection', orderedItems: [] }],
    542     [`${BRON}/tracks`, {
    543       type: 'OrderedCollection',
    544       orderedItems: [{
    545         id: `${BRON}/tracks/t-bots`, type: 'Audio', name: 'Van de bron',
    546         url: [{ type: 'Link', href: `${BRON}/audio/y.mp3`, mediaType: 'audio/mpeg' }],
    547       }],
    548     }],
    549   ]);
    550   await stil(() => Mig.ingestFromSource(s2, {
    551     deps: {
    552       getJson: async (_slug, url) => kaart2.get(url) || null,
    553       noteId: (b, id) => `${b}/ap/notes/${id}`,
    554       noteVisibility: AP.noteVisibility,
    555       audioRoot: '/nep/audio', mediaRoot: '/nep/media',
    556       signHeaders: () => ({ Signature: 'nep' }),
    557       safeFetch: async () => ({ ok: true, arrayBuffer: async () => Buffer.from('y'), headers: { get: () => 'audio/mpeg' } }),
    558       fs: { mkdirSync() {}, writeFileSync() {} },
    559       path,
    560     },
    561   }));
    562   // Het bestaande nummer blijft van jou; de tekst wijst naar iets dat bestaat.
    563   const inhoud = db.prepare("SELECT content FROM posts WHERE id = 'pb'").get().content;
    564   const m = /\[\[track:([^\]]+)\]\]/.exec(inhoud);
    565   assert.ok(m);
    566   assert.ok(db.prepare('SELECT 1 FROM audio_tracks WHERE id = ? AND site_id = ?').get(m[1], 's1'),
    567     'wat er ook gebeurde met het id, de verwijzing wijst naar een bestaand nummer');
     522  assert.ok(bestaat, 'en het nieuwe id hoort bij een nummer dat er echt is');
    568523});
    569524
Note: See TracChangeset for help on using the changeset viewer.