Skip to content

Commit

Permalink
12 hover provider for manifest files (#39)
Browse files Browse the repository at this point in the history
* refactored

* Added vulnerabilities data in hover menu

* refactored
  • Loading branch information
rajpreet-s authored Aug 12, 2024
1 parent c13981f commit 64814eb
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 20 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
"capabilities": {
"hoverProvider": "true"
},
"activationEvents": [],
"activationEvents": [
"*"
],
"main": "./dist/extension.js",
"repository": {
"type": "git",
Expand Down
6 changes: 5 additions & 1 deletion src/constants/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import * as os from "os";
export class Organization {
static readonly name = "debricked";
static readonly apiVersion = "1.0";
static readonly baseUrl = `https://debricked.com/api/${Organization.apiVersion}/`;
static readonly debrickedBaseUrl = "https://debricked.com";
static readonly baseUrl = `${Organization.debrickedBaseUrl}/api/${Organization.apiVersion}/`;

static readonly dependencyUrl = "open/dependencies/get-dependencies-hierarchy";
static readonly vulnerableUrl = "open/vulnerabilities/get-vulnerabilities";

static readonly nameCaps = "Debricked";
// Command and OS-specific constants
Expand Down
4 changes: 4 additions & 0 deletions src/helpers/apiHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export class ApiHelper {
params.push(`commitId=${requestParam.commitId}`);
}

if (requestParam.dependencyId) {
params.push(`dependencyId=${requestParam.dependencyId}`);
}

if (params.length > 0) {
url += `?${params.join("&")}`;
}
Expand Down
3 changes: 3 additions & 0 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ErrorHandler } from "./errorHandler";
import { ApiClient } from "./apiClient";
import { GlobalStore } from "./globalStore";
import { Organization } from "../constants";
import { Template } from "./template";

class IndexHelper {
constructor(
Expand Down Expand Up @@ -61,6 +62,7 @@ const installHelper = new InstallHelper(Logger, statusBarMessageHelper, commandH
const fileHelper = new FileHelper(debrickedDataHelper, Logger, globalStore);
const indexHelper = new IndexHelper(debrickedDataHelper, commonHelper, gitHelper);
const showQuickPickHelper = new ShowQuickPickHelper();
const template = new Template();

export {
authHelper,
Expand All @@ -81,4 +83,5 @@ export {
apiClient,
globalStore,
indexHelper,
template,
};
33 changes: 33 additions & 0 deletions src/helpers/template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Organization } from "../constants";
import { DependencyVulnerability } from "types/vulnerability";
import * as vscode from "vscode";

export class Template {
constructor() {}
public licenseContent(data: string, contents: vscode.MarkdownString) {
contents.appendMarkdown(`License: **${data}**`);
contents.appendText("\n______________________________\n");
}

public vulnerableContent(data: DependencyVulnerability[], contents: vscode.MarkdownString): void {
if (data.length === 0) {
contents.appendMarkdown("No vulnerabilities found");
return;
}

contents.appendMarkdown(`Vulnerabilities Found: **${data.length}**\n\n`);

const vulnerabilitiesToShow = data.slice(0, 2);
vulnerabilitiesToShow.forEach((vulnerability) => {
contents.appendMarkdown(
`[**${vulnerability.cveId}**](${Organization.debrickedBaseUrl + vulnerability.name.link})`,
);

if (vulnerability.cvss) {
contents.appendMarkdown(` - CVSS: ${vulnerability.cvss.text} (${vulnerability.cvss.type})`);
}

contents.appendMarkdown("\n\n");
});
}
}
38 changes: 26 additions & 12 deletions src/providers/manifestDependencyHoverProvider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as vscode from "vscode";
import * as path from "path";
import { globalStore } from "../helpers";
import { globalStore, template } from "../helpers";
import { DependencyService } from "services";
import { DependencyVulnerability } from "types/vulnerability";

export class ManifestDependencyHoverProvider implements vscode.HoverProvider {
private manifestFiles: string[] = [];
Expand Down Expand Up @@ -30,22 +32,34 @@ export class ManifestDependencyHoverProvider implements vscode.HoverProvider {
const lineText = document.lineAt(position.line).text;
const dependencyName = this.parseDependencyName(lineText, currentManifestFile);

if (dependencyName) {
const depData = globalStore.getDependencyData().get(dependencyName);
const licenseData = depData?.licenses[0]?.name ?? "License information unavailable";
if (!dependencyName) {
return null;
}

const depData = globalStore.getDependencyData().get(dependencyName);
const licenseData = depData?.licenses[0]?.name ?? "License information unavailable";
const vulnerableData = await this.getVulnerableData(depData?.id);

const contents = new vscode.MarkdownString(
`<span style="color:#000;background-color:#fff;">Debricked</span>`,
);
contents.supportHtml = true;
contents.isTrusted = true;
const contents = this.createMarkdownString();
template.licenseContent(licenseData, contents);
template.vulnerableContent(vulnerableData, contents);

const hoverContent = [`**${dependencyName}**`, contents, `License: ${licenseData}`];
return new vscode.Hover(contents);
}

return new vscode.Hover(hoverContent);
private async getVulnerableData(dependencyId?: number): Promise<DependencyVulnerability[]> {
if (dependencyId) {
return await DependencyService.getVulnerableData(dependencyId);
}
return [];
}

return null;
private createMarkdownString(): vscode.MarkdownString {
const contents = new vscode.MarkdownString();
contents.supportHtml = true;
contents.isTrusted = true;
contents.supportThemeIcons = true;
return contents;
}

private parseDependencyName(lineText: string, fileName: string): string | null {
Expand Down
21 changes: 19 additions & 2 deletions src/services/dependencyService.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Dependency, DependencyResponse, IndirectDependency } from "types/dependency";
import { apiHelper, globalStore, Logger } from "../helpers";
import { RequestParam } from "../types";
import { DependencyVulnerabilityWrapper } from "types/vulnerability";
import { Organization } from "../constants";

export class DependencyService {
static async getDependencyData(repoID: number, commitId: number) {
Logger.logInfo("Started fetching the Dependency Data");
const requestParam: RequestParam = {
endpoint: "open/dependencies/get-dependencies-hierarchy",
endpoint: Organization.dependencyUrl,
repoId: repoID,
commitId: commitId,
};
Expand All @@ -24,6 +26,21 @@ export class DependencyService {
});

globalStore.setDependencyData(dependencyMap);
Logger.logObj(response);
}

static async getVulnerableData(depId: number) {
Logger.logInfo("Started fetching the Vulnerable Data");
const repoId = await globalStore.getRepoId();
const commitId = await globalStore.getCommitId();

const requestParam: RequestParam = {
endpoint: Organization.vulnerableUrl,
repoId: repoId,
commitId: commitId,
dependencyId: depId,
};
const response: DependencyVulnerabilityWrapper = await apiHelper.get(requestParam);
const vulnerableData = response.vulnerabilities;
return vulnerableData;
}
}
20 changes: 18 additions & 2 deletions src/services/scanService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import {
commonHelper,
commandHelper,
authHelper,
fileHelper,
} from "../helpers";
import { DebrickedCommands, MessageStatus, Organization } from "../constants/index";
import { DebrickedCommandNode, Flag, RepositoryInfo } from "../types";
import * as vscode from "vscode";
import * as fs from "fs";
import { DependencyService } from "./dependencyService";

export class ScanService {
static async scanService() {
Expand All @@ -36,7 +39,6 @@ export class ScanService {
await ScanService.handleFlags(command.flags[2], cmdParams, currentRepoData);
await ScanService.handleFlags(command.flags[3], cmdParams, currentRepoData);
await ScanService.handleFlags(command.flags[4], cmdParams, currentRepoData);
await ScanService.handleFlags(command.flags[4], cmdParams, currentRepoData);
await ScanService.handleFlags(command.global_flags[0], cmdParams, currentRepoData);
}
} else {
Expand All @@ -61,7 +63,21 @@ export class ScanService {
},
async (progress) => {
progress.report({ message: "Scanning Manifest Files🚀" });
await commandHelper.executeAsyncCommand(`${Organization.debrickedCli} ${cmdParams.join(" ")}`);
const output = await commandHelper.executeAsyncCommand(
`${Organization.debrickedCli} ${cmdParams.join(" ")}`,
);
if (!output.includes("https://debricked.com/app/en/repository/")) {
if (await fs.existsSync(`${Organization.reportsFolderPath}/scan-output.json`)) {
await fileHelper.setRepoID();

const repoId = await globalStore.getRepoId();
const commitId = await globalStore.getCommitId();

await DependencyService.getDependencyData(repoId, commitId);
} else {
throw new Error("No reports file exists");
}
}
statusBarMessageHelper.setStatusBarMessage(`Debricked: Scanning Completed $(pass-filled)`, 1000);
},
);
Expand Down
4 changes: 2 additions & 2 deletions src/types/dependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ export interface DependencyResponse {
commitName: string;
dependencies: Dependency[];
}
export interface DependencyName {
interface DependencyName {
name: string;
shortName: string;
link: string;
}

export interface DependencyLicense {
interface DependencyLicense {
name: string;
}

Expand Down
1 change: 1 addition & 0 deletions src/types/requestParam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export interface RequestParam {
repoId?: number;
endpoint: string;
commitId?: number;
dependencyId?: number;
}
20 changes: 20 additions & 0 deletions src/types/vulnerability.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export interface DependencyVulnerabilityWrapper {
vulnerabilities: DependencyVulnerability[];
}

export interface DependencyVulnerability {
cveId: string;
cvss: CVSS;
cpeVersions: string[];
name: VulnerabilityName
}

interface CVSS {
text: number;
type: string;
}

interface VulnerabilityName {
name: string;
link: string;
}

0 comments on commit 64814eb

Please sign in to comment.