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:
parent
d050d6c0ea
commit
1c17420e6c
@ -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,
|
||||||
|
|||||||
@ -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`;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user