mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-18 04:43:55 +00:00
71 lines
2.4 KiB
JavaScript
71 lines
2.4 KiB
JavaScript
// Normal builds only read committed files. No Rust or network required.
|
|
import { createHash } from 'node:crypto';
|
|
import { readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
import { join, relative } from 'node:path';
|
|
const root = new URL('../../', import.meta.url).pathname;
|
|
const source = 'crypto/encryption';
|
|
const artifact = 'src/lib/encryption/vendor';
|
|
const hash = (data) => createHash('sha256').update(data).digest('hex');
|
|
function files(dir) {
|
|
return readdirSync(join(root, dir), { withFileTypes: true })
|
|
.flatMap((e) => {
|
|
if (e.name === 'target' || e.name.startsWith('.')) return [];
|
|
const path = join(dir, e.name);
|
|
return e.isDirectory() ? files(path) : [path];
|
|
})
|
|
.sort();
|
|
}
|
|
const inputs = [
|
|
...files(source),
|
|
'scripts/encryption/build.py',
|
|
'scripts/encryption/artifact.mjs'
|
|
].sort();
|
|
const sourceFingerprint = hash(
|
|
inputs.map((p) => `${p}\0${hash(readFileSync(join(root, p)))}`).join('\n')
|
|
);
|
|
const manifestPath = join(root, artifact, 'manifest.json');
|
|
if (process.argv.includes('--write')) {
|
|
const metadata = JSON.parse(
|
|
readFileSync(process.argv[process.argv.indexOf('--metadata') + 1], 'utf8')
|
|
);
|
|
const checksums = Object.fromEntries(
|
|
files(artifact)
|
|
.filter((p) => !p.endsWith('/manifest.json'))
|
|
.map((p) => [relative(artifact, p), hash(readFileSync(join(root, p)))])
|
|
);
|
|
writeFileSync(
|
|
manifestPath,
|
|
JSON.stringify(
|
|
{
|
|
format: 1,
|
|
sourceFingerprint,
|
|
sourceRevision: process.env.CRYPTO_SOURCE_REVISION,
|
|
toolchain: '1.95.0',
|
|
wasmBindgen: '0.2.126',
|
|
dependencies: metadata.packages.map(({ name, version, license }) => ({
|
|
name,
|
|
version,
|
|
license
|
|
})),
|
|
checksums
|
|
},
|
|
null,
|
|
2
|
|
) + '\n'
|
|
);
|
|
} else {
|
|
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
if (manifest.sourceFingerprint !== sourceFingerprint)
|
|
throw Error('Encryption source changed: rebuild and review the artifact.');
|
|
const actual = files(artifact)
|
|
.filter((p) => !p.endsWith('/manifest.json'))
|
|
.map((p) => relative(artifact, p))
|
|
.sort();
|
|
if (JSON.stringify(actual) !== JSON.stringify(Object.keys(manifest.checksums).sort()))
|
|
throw Error('Unexpected crypto artifact files');
|
|
for (const [p, digest] of Object.entries(manifest.checksums)) {
|
|
if (hash(readFileSync(join(root, artifact, p))) !== digest)
|
|
throw Error(`Crypto artifact checksum mismatch: ${p}`);
|
|
}
|
|
console.log('Encryption artifact source and checksums verified');
|
|
}
|