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"; import path from "path";
export interface ReadFileFromTarOpts { export interface ReadFileFromTarOpts {
fileName?: string; tarPath: string;
fileMatcher?(path: string, entry: FileStat): boolean; filePath: string;
notFoundMessage?: 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) => { return new Promise(async (resolve, reject) => {
const fileChunks: Buffer[] = []; const fileChunks: Buffer[] = [];
const {
fileName,
fileMatcher = (path: string) => path === fileName,
notFoundMessage = "File not found",
} = opts;
await tar.list({ await tar.list({
file: tarFilePath, file: tarPath,
filter: fileMatcher, filter: path => path === filePath,
onentry(entry: FileStat) { onentry(entry: FileStat) {
entry.on("data", chunk => { entry.on("data", chunk => {
fileChunks.push(chunk); fileChunks.push(chunk);
@ -29,17 +24,28 @@ export function readFileFromTar(tarFilePath: string, opts: ReadFileFromTarOpts):
reject(`Reading ${entry.path} error: ${err}`); reject(`Reading ${entry.path} error: ${err}`);
}); });
entry.once("end", () => { 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) { 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 } = {}) { export function extractTar(filePath: string, opts: ExtractOptions & { sync?: boolean } = {}) {
return tar.extract({ return tar.extract({
file: filePath, file: filePath,

View File

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