Files
vendoo/tools/verify-catalog-services-1.41.2.mjs
Masterluke77andGitHub 6f48827f4d Vendoo 1.41.2 – Git Ignore Boundary & Module Tracking Hotfix (#18)
* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix

* fix: track native source modules with root-anchored runtime ignores
2026-07-09 17:09:00 +02:00

47 lines
4.1 KiB
JavaScript

import { mkdtempSync, writeFileSync, existsSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { ListingsService } from '../app/modules/listings/service.mjs';
import { InventoryService } from '../app/modules/inventory/service.mjs';
import { MediaService } from '../app/modules/media/service.mjs';
const failures=[]; const assert=(c,m)=>{if(!c)failures.push(m)}; const expectThrow=(fn,code,m)=>{try{fn();failures.push(m)}catch(e){if(code&&e.code!==code)failures.push(`${m} (${e.code||e.message})`)}};
let listings=[{id:1,title:'Aktiv',deleted_at:null,tags:[],photos:[]},{id:2,title:'Papierkorb',deleted_at:'2026-01-01',tags:[],photos:[]}];
const listRepo={
create(data){const row={id:3,...data,tags:data.tags||[],photos:data.photos||[]};listings.push(row);return row;},
get(id){return listings.find(x=>x.id===Number(id))||null;}, list(){return listings.filter(x=>!x.deleted_at);},
update(id,data){const row=this.get(id);Object.assign(row,data);return row;}, softDelete(id){this.get(id).deleted_at='now';},
restore(id){this.get(id).deleted_at=null;}, listDeleted(){return listings.filter(x=>x.deleted_at);},
permanentDelete(id){listings=listings.filter(x=>x.id!==Number(id));}, trashCount(){return this.listDeleted().length;},
duplicate(id){const row=this.get(id);return row?this.create({...row,id:undefined,title:`${row.title} (Kopie)`,deleted_at:null}):null;},
};
const ls=new ListingsService(listRepo);
expectThrow(()=>ls.validateCreate({platform:'ebay'}),'LISTING_INPUT_INVALID','Titelpflicht wurde nicht erzwungen');
expectThrow(()=>ls.validateCreate({title:'OK',hacker:true}),'LISTING_INPUT_INVALID','Unbekanntes Listingfeld wurde akzeptiert');
const cleaned=ls.validateCreate({title:'Test',description_html:'<script>alert(1)</script><p>Text</p>',tags:['a','b']});
assert(!cleaned.description_html.includes('<script'),'HTML-Sanitizer ließ Script durch');
expectThrow(()=>ls.permanentDelete(1),'LISTING_TRASH_NOT_FOUND','Aktiver Artikel konnte endgültig gelöscht werden');
assert(ls.permanentDelete(2).ok && !listRepo.get(2),'Papierkorbartikel wurde nicht endgültig gelöscht');
const inv=new InventoryService({locations(){return[]},unassigned(){return[]},byLocation(){return[]},bulkUpdateLocation(ids){return ids.length}});
expectThrow(()=>inv.validateBulk({ids:[1],location:'A',extra:true}),'INVENTORY_INPUT_INVALID','Unbekanntes Lagerfeld wurde akzeptiert');
expectThrow(()=>inv.validateBulk({ids:Array.from({length:501},(_,i)=>i+1),location:'A'}),'INVENTORY_BATCH_TOO_LARGE','Bulk-Limit wurde nicht erzwungen');
assert(inv.bulk({ids:[1,1,2],location:'Regal A'}).updated===2,'IDs wurden nicht dedupliziert');
const dir=mkdtempSync(join(tmpdir(),'vendoo-media-'));
try{
writeFileSync(join(dir,'free.jpg'),'x'); writeFileSync(join(dir,'used.jpg'),'x');
const removed=[];
const mediaRepo={list(){return[]},setFavorite(p,f){return{ok:true,image_path:p,favorite:f}},referenced(){return new Set(['used.jpg'])},removeRecords(paths){removed.push(...paths)}};
const media=new MediaService({uploadRoot:dir,sharp:null,repository:mediaRepo});
expectThrow(()=>media.validateDelete({image_paths:['../secret']}),'MEDIA_PATH_INVALID','Traversal-Pfad wurde akzeptiert');
expectThrow(()=>media.validateDelete({image_paths:['free.jpg'],extra:true}),null,'Unbekanntes Medienfeld wurde akzeptiert');
const result=media.delete({image_paths:['free.jpg','used.jpg']});
assert(result.deleted===1 && result.protected.includes('used.jpg'),'Referenzschutz liefert falsches Ergebnis');
assert(!existsSync(join(dir,'free.jpg')) && existsSync(join(dir,'used.jpg')),'Referenzschutz löschte falsche Datei');
assert(removed.length===1 && removed[0]==='free.jpg','Medienrecords wurden falsch bereinigt');
} finally { rmSync(dir,{recursive:true,force:true}); }
if(failures.length){console.error(`Catalog-Service-Regression 1.41.2 fehlgeschlagen (${failures.length}):`);failures.forEach(x=>console.error(`- ${x}`));process.exit(1)}
console.log('Catalog-Service-Regression 1.41.2 erfolgreich: Listing-Allowlist, HTML-Sanitizing, Papierkorbgrenze, Inventory-Bulk-Limit, Pfadschutz und Medienreferenzen geprüft.');