1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

fix validation harder

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-11-24 18:03:48 +02:00
parent d050d6c0ea
commit 1c17420e6c
2 changed files with 33 additions and 21 deletions

View File

@ -4,23 +4,18 @@ import tar, { ExtractOptions, FileStat } from "tar";
import path from "path";
export interface ReadFileFromTarOpts {
fileName?: string;
fileMatcher?(path: string, entry: FileStat): boolean;
notFoundMessage?: string;
tarPath: string;
filePath: string;
parseJson?: boolean;
}
export function readFileFromTar(tarFilePath: string, opts: ReadFileFromTarOpts): Promise<Buffer> {
export function readFileFromTar<R = Buffer>({tarPath, filePath, parseJson}: ReadFileFromTarOpts): Promise<R> {
return new Promise(async (resolve, reject) => {
const fileChunks: Buffer[] = [];
const {
fileName,
fileMatcher = (path: string) => path === fileName,
notFoundMessage = "File not found",
} = opts;
await tar.list({
file: tarFilePath,
filter: fileMatcher,
file: tarPath,
filter: path => path === filePath,
onentry(entry: FileStat) {
entry.on("data", chunk => {
fileChunks.push(chunk);
@ -29,17 +24,28 @@ export function readFileFromTar(tarFilePath: string, opts: ReadFileFromTarOpts):
reject(`Reading ${entry.path} error: ${err}`);
});
entry.once("end", () => {
resolve(Buffer.concat(fileChunks));
const data = Buffer.concat(fileChunks);
const result = parseJson ? JSON.parse(data.toString("utf8")) : data;
resolve(result);
});
},
});
if (!fileChunks.length) {
reject(notFoundMessage);
reject(null);
}
});
}
export async function listTarEntries(filePath: string): Promise<string[]> {
const entries: string[] = [];
await tar.list({
file: filePath,
onentry: (entry: FileStat) => entries.push(entry.path as any as string),
});
return entries;
}
export function extractTar(filePath: string, opts: ExtractOptions & { sync?: boolean } = {}) {
return tar.extract({
file: filePath,

View File

@ -20,8 +20,8 @@ import { extensionLoader } from "../../../extensions/extension-loader";
import { extensionDiscovery, manifestFilename } from "../../../extensions/extension-discovery";
import { LensExtensionManifest, sanitizeExtensionName } from "../../../extensions/lens-extension";
import { Notifications } from "../notifications";
import { downloadFile, escapeRegExp } from "../../../common/utils";
import { extractTar, readFileFromTar } from "../../../common/utils/tar";
import { downloadFile } from "../../../common/utils";
import { extractTar, listTarEntries, readFileFromTar } from "../../../common/utils/tar";
import { docsUrl } from "../../../common/vars";
interface InstallRequest {
@ -142,14 +142,20 @@ export class Extensions extends React.Component {
}
async validatePackage(filePath: string): Promise<LensExtensionManifest> {
const manifestMatcher = RegExp(String.raw`^(\w+\/)?${escapeRegExp(manifestFilename)}$`);
const tarFiles = await listTarEntries(filePath);
const packageJson: Buffer = await readFileFromTar(filePath, {
notFoundMessage: `Invalid extension package, ${manifestFilename} not found`,
// tarball from npm contains single root folder "package/*"
fileMatcher: (path: string) => !!path.match(manifestMatcher),
// tarball from npm contains single root folder "package/*"
const hasSingleRootFolder = tarFiles.every(entry => entry.startsWith(tarFiles[0]));
const manifestLocation = hasSingleRootFolder ? path.join(tarFiles[0], manifestFilename) : manifestFilename;
if(!tarFiles.includes(manifestLocation)) {
throw `invalid package, ${manifestFilename} not found`;
}
const manifest = await readFileFromTar<LensExtensionManifest>({
tarPath: filePath,
filePath: manifestLocation,
parseJson: true,
});
const manifest: LensExtensionManifest = JSON.parse(packageJson.toString("utf8"));
if (!manifest.lens && !manifest.renderer) {
throw `${manifestFilename} must specify "main" and/or "renderer" fields`;
}