Files
qinglong/cli/test/remote/rawCredentials.test.cjs
T
whyour 801a71d740 feat(cli): cover OpenAPI with a remote npm CLI and internal panel tools (#3074)
* feat(cli): add unified Commander CLI for QingLong 2.x

* fix(cli): publish via npm and address security review feedback

* ci(cli): package npm artifacts and remove evaluation collateral

* test(cli): use a fixed shell fixture for log retention

* refactor(cli): separate remote npm client from panel tools

* feat(cli): cover active panel OpenAPI resources

* docs(cli): unify authentication and skill guidance

* refactor(cli): isolate internal commands and generate Commander help

* refactor(cli): organize remote and internal modules by responsibility

* ci(cli): publish verified npm archives from master

* fix(cli): publish under the whyour npm scope

* ci: use npm trusted publishing for both packages

* docs: introduce the published CLI on the project homepage

* fix(cli): preserve server log truncation and correct login hints

* fix(cli): accept dashboard record request bodies

* fix(cli): preserve stdin for local task execution

* fix(cli): resolve task executables after changing directory

* fix(cli): preserve shell function tasks and sanitize test failures

* fix(cli): preserve shell hook state and resolve workdir after hooks

* fix(cli): preserve cleanup across shared shell task timeouts

* fix(cli): isolate shell control descriptors and reap timed-out descendants
2026-09-25 23:24:41 +08:00

86 lines
3.0 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs/promises');
const path = require('node:path');
const os = require('node:os');
const http = require('node:http');
const { randomUUID } = require('node:crypto');
const { createContext } = require('../../dist/internal/runtime/context');
const { syncRaw } = require('../../dist/internal/subscription/subscriptionRunner');
const { runProcess } = require('../../dist/internal/runtime/process');
test('raw subscriptions retain legacy netrc authentication and preserve files on denied access', async (t) => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'ql-raw-netrc-'));
t.after(() => fs.rm(root, { recursive: true, force: true }));
const password = randomUUID();
const authorization =
'Basic ' + Buffer.from('fixture:' + password).toString('base64');
let denied = false;
const server = http.createServer((req, res) => {
if (req.url === '/public.js') return res.end('public script');
if (denied || req.headers.authorization !== authorization)
return res
.writeHead(401, { 'WWW-Authenticate': 'Basic realm="fixture"' })
.end();
res.end('private script');
});
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
t.after(async () => {
server.closeAllConnections();
await new Promise((resolve) => server.close(resolve));
});
const env = { PATH: process.env.PATH, HOME: root, QL_LANG: 'en' };
await fs.writeFile(
path.join(root, '.netrc'),
`machine 127.0.0.1 login fixture password ${password}\n`,
{ mode: 0o600 },
);
const endpoint = `http://127.0.0.1:${server.address().port}`;
if (process.env.QL_WGET_COMPARE === '1') {
const original = await runProcess(
'wget',
['-q', '-O', path.join(root, 'original.js'), endpoint + '/private.js'],
{ env },
);
assert.equal(
original.code,
0,
'retained Shell wget authentication must work',
);
assert.equal(
await fs.readFile(path.join(root, 'original.js'), 'utf8'),
'private script',
);
}
const context = createContext({ root }, env);
const input = {
url: endpoint + '/private.js',
autoAdd: false,
autoDelete: false,
};
const result = await syncRaw(context, input);
const destination = path.join(context.paths.dir_scripts, result.file);
assert.equal(await fs.readFile(destination, 'utf8'), 'private script');
denied = true;
await assert.rejects(syncRaw(context, input));
assert.equal(await fs.readFile(destination, 'utf8'), 'private script');
assert.equal(
(await fs.readdir(context.paths.dir_raw)).filter((x) => x.endsWith('.tmp'))
.length,
0,
);
await fs.rm(path.join(root, '.netrc'));
await assert.rejects(syncRaw(context, input));
const publicResult = await syncRaw(context, {
...input,
url: endpoint + '/public.js',
});
assert.equal(
await fs.readFile(
path.join(context.paths.dir_scripts, publicResult.file),
'utf8',
),
'public script',
);
});