fix: harden hoster confirmation and recovery
Require every successful upload to expose a validated HTTPS result and rebuild all Doodstream and DSVPlay output from the confirmed file code. Keep failed baselines distinct from empty accounts, reject stale, foreign, and ambiguous recovery candidates across Doodstream, Byse, VOE, and Vidmoly, and preserve exact filename recovery with normalized extensions. Emit bounded structured transport diagnostics without raw response bodies or tokenized URLs, and remove sensitive values from Doodstream debug traces. Tests: node --test tests/upload-confirmation.test.js tests/hosters.test.js tests/doodstream-api-upload.test.js tests/doodstream-upload.test.js tests/byse-reject-recovery.test.js tests/hoster-recovery-provenance.test.js tests/suspect-reject-alternates.test.js Lint: eslint lib/hoster-transport-error.js lib/hosters.js lib/doodstream-upload.js lib/voe-upload.js lib/vidmoly-upload.js lib/upload-confirmation.js
This commit is contained in:
@@ -64,6 +64,39 @@ test('happy path: link in result page wins', async () => {
|
||||
assert.equal(res.file_code, 'jjsuhr931ds9');
|
||||
});
|
||||
|
||||
test('JSON results rebuild canonical Doodstream URLs from the file code', () => {
|
||||
const up = new DoodstreamUploader();
|
||||
assert.deepEqual(
|
||||
up._extractFromJson({
|
||||
status: 200,
|
||||
result: {
|
||||
filecode: 'CANONICAL123',
|
||||
download_url: 'http://edge.dsvplay.com/result/CANONICAL123?token=SYNTHETIC_SECRET',
|
||||
protected_embed: 'https://dood.to/arbitrary/CANONICAL123'
|
||||
}
|
||||
}),
|
||||
{
|
||||
file_code: 'CANONICAL123',
|
||||
download_url: 'https://doodstream.com/d/CANONICAL123',
|
||||
embed_url: 'https://doodstream.com/e/CANONICAL123'
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('invalid web upload results expose safe structured diagnostics', async () => {
|
||||
const up = new DoodstreamUploader();
|
||||
await assert.rejects(
|
||||
() => up._parseUploadResponse('<html><input name="api_key" value="SYNTHETIC_WEB_SECRET"> https://doodstream.com/?session=SYNTHETIC_WEB_SESSION</html>'),
|
||||
(err) => {
|
||||
assert.doesNotMatch(err.message, /SYNTHETIC_WEB_SECRET|SYNTHETIC_WEB_SESSION|<html>/);
|
||||
assert.equal(err.diagnostic.phase, 'upload-result');
|
||||
assert.equal(err.diagnostic.responseKind, 'html');
|
||||
assert.doesNotMatch(err.diagnostic.payloadSnippet, /SYNTHETIC_WEB_SECRET|SYNTHETIC_WEB_SESSION/);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// --- _parseUploadFormFields: replicate the current upload form faithfully ---
|
||||
test('_parseUploadFormFields extracts the real form fields and excludes the file input', () => {
|
||||
const up = new DoodstreamUploader();
|
||||
@@ -212,3 +245,26 @@ test('getUploadServer: throws (no silent dead fallback) when discovery fails', a
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('getUploadServer: failures expose safe structured diagnostics without response secrets', async () => {
|
||||
const up = new DoodstreamUploader();
|
||||
up._fetch = async (url) => {
|
||||
if (/op=upload_server/.test(url)) {
|
||||
return fakeRes('<html>upstream-token=SYNTHETIC_DISCOVERY_SECRET</html>', { status: 503, ctype: 'text/html; charset=utf-8' });
|
||||
}
|
||||
return fakeRes('<input name="sess_id" value="SYNTHETIC_DISCOVERY_SESSION"><a href="https://node.invalid/upload?token=SYNTHETIC_QUERY">x</a>');
|
||||
};
|
||||
|
||||
await assert.rejects(
|
||||
() => up._getUploadServer(),
|
||||
(err) => {
|
||||
assert.doesNotMatch(err.message, /SYNTHETIC_DISCOVERY_SECRET|SYNTHETIC_DISCOVERY_SESSION|SYNTHETIC_QUERY|<html>/);
|
||||
assert.equal(err.diagnostic.phase, 'upload-server');
|
||||
assert.equal(err.diagnostic.http, 503);
|
||||
assert.equal(err.diagnostic.contentType, 'text/html; charset=utf-8');
|
||||
assert.equal(err.diagnostic.safeEndpointHost, 'doodstream.com');
|
||||
assert.equal(err.diagnostic.responseKind, 'html');
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user