Skip to content

Commit

Permalink
Merge pull request #16 from GitGuardian/garancegourdel/scrt-4590-disp…
Browse files Browse the repository at this point in the history
…lay-custom-remediation-infos

Add sidebar to display custom remediation message
  • Loading branch information
salome-voltz authored Sep 24, 2024
2 parents d2e34b5 + c5ecf62 commit 54df13f
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 311 deletions.
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
"id": "gitguardianView",
"name": "gitguardian"
},
{
"type": "webview",
"id": "gitguardianRemediationMessageView",
"name": "remediation message"
},
{
"type": "webview",
"id": "gitguardianQuotaView",
Expand Down Expand Up @@ -133,5 +138,7 @@
"mocha": "^10.2.0",
"typescript": "^5.1.3"
},
"dependencies": {}
"dependencies": {
"axios": "^1.7.7"
}
}
12 changes: 11 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
GitGuardianSecretHoverProvider,
} from "./giguardian-interface/gitguardian-hover-provider";
import { GitGuardianQuotaWebviewProvider } from "./ggshield-webview/gitguardian-quota-webview";
import { GitGuardianRemediationMessageWebviewProvider } from "./ggshield-webview/gitguardian-remediation-message-view";

/**
* Extension diagnostic collection
Expand Down Expand Up @@ -135,16 +136,24 @@ export function activate(context: ExtensionContext) {
context.extensionUri
);

const ggshieldRemediationMessageViewProvider = new GitGuardianRemediationMessageWebviewProvider(
configuration,
context.extensionUri
);
const ggshieldQuotaViewProvider = new GitGuardianQuotaWebviewProvider(
configuration,
context.extensionUri
);
window.registerWebviewViewProvider("gitguardianView", ggshieldViewProvider);
window.registerWebviewViewProvider(
"gitguardianRemediationMessageView",
ggshieldRemediationMessageViewProvider
);
window.registerWebviewViewProvider(
"gitguardianQuotaView",
ggshieldQuotaViewProvider
);
context.subscriptions.push(ggshieldViewProvider, ggshieldQuotaViewProvider);
context.subscriptions.push(ggshieldViewProvider, ggshieldRemediationMessageViewProvider, ggshieldQuotaViewProvider);

statusBar = window.createStatusBarItem(StatusBarAlignment.Left, 0);
updateStatusBarItem(StatusBarStatus.initialization, statusBar);
Expand Down Expand Up @@ -241,6 +250,7 @@ export function activate(context: ExtensionContext) {
const ggshieldApi = ggshieldApiKey(configuration);
setApiKey(configuration, ggshieldApi);
ggshieldViewProvider.refresh();
ggshieldRemediationMessageViewProvider.refresh();
ggshieldQuotaViewProvider.refresh();
} else {
updateStatusBarItem(StatusBarStatus.unauthenticated, statusBar);
Expand Down
114 changes: 114 additions & 0 deletions src/ggshield-webview/gitguardian-remediation-message-view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { getRemediationMessage, ggshieldAuthStatus } from "../lib/ggshield-api";
import { GGShieldConfiguration } from "../lib/ggshield-configuration";
import * as vscode from "vscode";

export class GitGuardianRemediationMessageWebviewProvider
implements vscode.WebviewViewProvider
{
public static readonly viewType = "gitguardian.gitguardianRemediationMessageView";
private _view?: vscode.WebviewView;
private isAuthenticated: boolean = false;
private remediationMessage: string = "";
private isLoading: boolean = false;

constructor(
private ggshieldConfiguration: GGShieldConfiguration,
private readonly _extensionUri: vscode.Uri
) {
this.checkAuthenticationStatus();
this.updateRemediationMessage();
}

public async resolveWebviewView(
webviewView: vscode.WebviewView,
context: vscode.WebviewViewResolveContext,
_token: vscode.CancellationToken
) {
this._view = webviewView;
this.refresh();

webviewView.onDidChangeVisibility(() => {
if (webviewView.visible) {
// Refresh when the view becomes visible (e.g., after being collapsed and reopened)
this.refresh();
}
});
}

private async checkAuthenticationStatus() {
this.isAuthenticated = ggshieldAuthStatus(this.ggshieldConfiguration);
}

private async updateRemediationMessage() {
if (this.isAuthenticated) {
this.remediationMessage = await getRemediationMessage(this.ggshieldConfiguration);
}
}

private updateWebViewContent(webviewView?: vscode.WebviewView) {
if (webviewView) {
webviewView.webview.html = this.getHtmlForWebview();
}
}

private escapeHtml(unsafe: string):string {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}

private getHtmlForWebview(): string {
if (this.isLoading) {
return `
<!DOCTYPE html>
<html lang="en">
<body>
<p>Loading...</p>
</body>
</html>`;
}

if (this.isAuthenticated) {
return `
<!DOCTYPE html>
<html lang="en">
<body>
<pre style="white-space:pre-wrap">
${this.escapeHtml(this.remediationMessage)}
</pre>
</body>
</html>`;
} else {
return `
<!DOCTYPE html>
<html lang="en">
<body>
<p>Please authenticate to see your personalized remediation message.</p>
</body>
</html>`;
}
}

public async refresh() {
this.isLoading = true;
this.updateWebViewContent(this._view);

await this.checkAuthenticationStatus();
console.log("Well authentificated");
await this.updateRemediationMessage();

this.isLoading = false;
this.updateWebViewContent(this._view);
}

dispose(): void {
if (this._view) {
this._view.webview.onDidReceiveMessage(() => {});
this._view.webview.html = "";
this._view = undefined;
}
}
}
18 changes: 18 additions & 0 deletions src/lib/ggshield-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
spawnSync,
} from "child_process";
import { workspace, window } from "vscode";
import axios from 'axios';
import { GGShieldConfiguration } from "./ggshield-configuration";
import { GGShieldScanResults } from "./api-types";
import * as os from "os";
Expand Down Expand Up @@ -89,6 +90,23 @@ export async function getAPIquota(
}
}


export async function getRemediationMessage(
configuration: GGShieldConfiguration
): Promise<string> {
const path = require('node:path');
try {
const response = await axios.get(path.join(configuration.apiUrl,'v1/metadata'), {
headers: {
'authorization': `Token ${configuration.apiKey}`
}
});
return response.data.remediation_messages.pre_commit;
} catch (error) {
return "An error occured.";
}
}

/**
* Ignore last found secrets
*
Expand Down
Loading

0 comments on commit 54df13f

Please sign in to comment.