Skip to content

CM-44175 - Add tree view filtering by severity #125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

- Add proper support for disabled modules
- Add tree view filtering by severity
- Fix auth required state of status bar

## [v1.14.0]

- Add the "Ignore this violation" button for violation card of SCA
Expand Down
216 changes: 207 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,41 +63,149 @@
}
],
"view/item/context": [
{
"command": "cycode.enableFilterByCriticalSeverity",
"when": "viewItem == FilterNode && !cycode:filter.severity.isCriticalEnabled",
"group": "inline@1"
},
{
"command": "cycode.disableFilterByCriticalSeverity",
"when": "viewItem == FilterNode && cycode:filter.severity.isCriticalEnabled",
"group": "inline@1"
},
{
"command": "cycode.enableFilterByHighSeverity",
"when": "viewItem == FilterNode && !cycode:filter.severity.isHighEnabled",
"group": "inline@2"
},
{
"command": "cycode.disableFilterByHighSeverity",
"when": "viewItem == FilterNode && cycode:filter.severity.isHighEnabled",
"group": "inline@2"
},
{
"command": "cycode.enableFilterByMediumSeverity",
"when": "viewItem == FilterNode && !cycode:filter.severity.isMediumEnabled",
"group": "inline@3"
},
{
"command": "cycode.disableFilterByMediumSeverity",
"when": "viewItem == FilterNode && cycode:filter.severity.isMediumEnabled",
"group": "inline@3"
},
{
"command": "cycode.enableFilterByLowSeverity",
"when": "viewItem == FilterNode && !cycode:filter.severity.isLowEnabled",
"group": "inline@4"
},
{
"command": "cycode.disableFilterByLowSeverity",
"when": "viewItem == FilterNode && cycode:filter.severity.isLowEnabled",
"group": "inline@4"
},
{
"command": "cycode.enableFilterByInfoSeverity",
"when": "viewItem == FilterNode && !cycode:filter.severity.isInfoEnabled",
"group": "inline@5"
},
{
"command": "cycode.disableFilterByInfoSeverity",
"when": "viewItem == FilterNode && cycode:filter.severity.isInfoEnabled",
"group": "inline@5"
},
{
"command": "cycode.secretScanForProject",
"when": "viewItem == secretScanTypeNode",
"when": "viewItem == secretScanTypeNode && cycode:modules.isSecretScanningEnabled",
"group": "inline"
},
{
"command": "cycode.scaScan",
"when": "viewItem == scaScanTypeNode",
"when": "viewItem == scaScanTypeNode && cycode:modules.isScaScanningEnabled",
"group": "inline"
},
{
"command": "cycode.iacScanForProject",
"when": "viewItem == iacScanTypeNode",
"when": "viewItem == iacScanTypeNode && cycode:modules.isIacScanningEnabled",
"group": "inline"
},
{
"command": "cycode.sastScanForProject",
"when": "viewItem == sastScanTypeNode",
"when": "viewItem == sastScanTypeNode && cycode:modules.isSastScanningEnabled",
"group": "inline"
},
{
"command": "cycode.secretScanForProject",
"when": "view == cycode.view.tree && viewItem == secretScanTypeNode"
"when": "view == cycode.view.tree && viewItem == secretScanTypeNode && cycode:modules.isSecretScanningEnabled"
},
{
"command": "cycode.scaScan",
"when": "view == cycode.view.tree && viewItem == scaScanTypeNode"
"when": "view == cycode.view.tree && viewItem == scaScanTypeNode && cycode:modules.isScaScanningEnabled"
},
{
"command": "cycode.iacScanForProject",
"when": "view == cycode.view.tree && viewItem == iacScanTypeNode"
"when": "view == cycode.view.tree && viewItem == iacScanTypeNode && cycode:modules.isIacScanningEnabled"
},
{
"command": "cycode.sastScanForProject",
"when": "view == cycode.view.tree && viewItem == sastScanTypeNode"
"when": "view == cycode.view.tree && viewItem == sastScanTypeNode && cycode:modules.isSastScanningEnabled"
}
],
"commandPalette": [
{
"command": "cycode.secretScanForProject",
"when": "cycode:modules.isSecretScanningEnabled"
},
{
"command": "cycode.iacScanForProject",
"when": "cycode:modules.isIacScanningEnabled"
},
{
"command": "cycode.sastScanForProject",
"when": "cycode:modules.isSastScanningEnabled"
},
{
"command": "cycode.scaScan",
"when": "cycode:modules.isScaScanningEnabled"
},
{
"command": "cycode.enableFilterByCriticalSeverity",
"when": "false"
},
{
"command": "cycode.enableFilterByHighSeverity",
"when": "false"
},
{
"command": "cycode.enableFilterByMediumSeverity",
"when": "false"
},
{
"command": "cycode.enableFilterByLowSeverity",
"when": "false"
},
{
"command": "cycode.enableFilterByInfoSeverity",
"when": "false"
},
{
"command": "cycode.disableFilterByCriticalSeverity",
"when": "false"
},
{
"command": "cycode.disableFilterByHighSeverity",
"when": "false"
},
{
"command": "cycode.disableFilterByMediumSeverity",
"when": "false"
},
{
"command": "cycode.disableFilterByLowSeverity",
"when": "false"
},
{
"command": "cycode.disableFilterByInfoSeverity",
"when": "false"
}
]
},
Expand Down Expand Up @@ -198,6 +306,96 @@
{
"command": "cycode.auth",
"title": "Authenticate with service"
},
{
"command": "cycode.enableFilterByCriticalSeverity",
"category": "Cycode",
"title": "Enable filter by Critical severity",
"icon": {
"light": "resources/severity/Critical.png",
"dark": "resources/severity/Critical.png"
}
},
{
"command": "cycode.enableFilterByHighSeverity",
"category": "Cycode",
"title": "Enable filter by High severity",
"icon": {
"light": "resources/severity/High.png",
"dark": "resources/severity/High.png"
}
},
{
"command": "cycode.enableFilterByMediumSeverity",
"category": "Cycode",
"title": "Enable filter by Medium severity",
"icon": {
"light": "resources/severity/Medium.png",
"dark": "resources/severity/Medium.png"
}
},
{
"command": "cycode.enableFilterByLowSeverity",
"category": "Cycode",
"title": "Enable filter by Low severity",
"icon": {
"light": "resources/severity/Low.png",
"dark": "resources/severity/Low.png"
}
},
{
"command": "cycode.enableFilterByInfoSeverity",
"category": "Cycode",
"title": "Enable filter by Info severity",
"icon": {
"light": "resources/severity/Info.png",
"dark": "resources/severity/Info.png"
}
},
{
"command": "cycode.disableFilterByCriticalSeverity",
"category": "Cycode",
"title": "Disable filter by Critical severity",
"icon": {
"light": "resources/severity/outline/Critical.png",
"dark": "resources/severity/outline/Critical.png"
}
},
{
"command": "cycode.disableFilterByHighSeverity",
"category": "Cycode",
"title": "Disable filter by High severity",
"icon": {
"light": "resources/severity/outline/High.png",
"dark": "resources/severity/outline/High.png"
}
},
{
"command": "cycode.disableFilterByMediumSeverity",
"category": "Cycode",
"title": "Disable filter by Medium severity",
"icon": {
"light": "resources/severity/outline/Medium.png",
"dark": "resources/severity/outline/Medium.png"
}
},
{
"command": "cycode.disableFilterByLowSeverity",
"category": "Cycode",
"title": "Disable filter by Low severity",
"icon": {
"light": "resources/severity/outline/Low.png",
"dark": "resources/severity/outline/Low.png"
}
},
{
"command": "cycode.disableFilterByInfoSeverity",
"category": "Cycode",
"title": "Disable filter by Info severity",
"icon": {
"light": "resources/severity/outline/Info.png",
"dark": "resources/severity/outline/Info.png"
}
}
],
"viewsContainers": {
Expand Down Expand Up @@ -246,7 +444,7 @@
},
"icons": {
"cycode-logo": {
"description": "Cycode icon",
"description": "Cycode Logo",
"default": {
"fontPath": "./resources/cycode.woff",
"fontCharacter": "\\E800"
Expand Down
Binary file added resources/severity/outline/Critical.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/severity/outline/High.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/severity/outline/Info.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/severity/outline/Low.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/severity/outline/Medium.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/commands/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const getCommonCommand = (command: (...args: never[]) => void | Promise<v
}

const stateService = container.resolve<IStateService>(StateServiceSymbol);
if (requiredAuth && !stateService.globalState.CliAuthed) {
if (requiredAuth && !stateService.tempState.CliAuthed) {
vscode.window.showErrorMessage('Please authenticate with Cycode first');
return;
}
Expand Down
3 changes: 3 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import treeViewExpandAllCommand from './tree-view-expand-all-command';
import treeViewCollapseAllCommand from './tree-view-collapse-all-command';
import runAllScansCommand from './run-all-scans-command';
import clearAllScanResultsCommand from './clear-all-scan-results-command';
import registerTreeViewSeverityFilterCommands from './tree-view-filter-by-severity-command';

export enum VscodeCommands {
SecretScanCommandId = 'cycode.secretScan',
Expand Down Expand Up @@ -74,4 +75,6 @@ export const registerCommands = (context: vscode.ExtensionContext): void => {
for (const [commandId, commandCallback] of Object.entries(_VS_CODE_COMMANDS_ID_TO_CALLBACK)) {
context.subscriptions.push(vscode.commands.registerCommand(commandId, commandCallback));
}

registerTreeViewSeverityFilterCommands(context);
};
21 changes: 17 additions & 4 deletions src/commands/run-all-scans-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@ import { container } from 'tsyringe';
import { CycodeService, ICycodeService } from '../services/cycode-service';
import { CliScanType } from '../cli/models/cli-scan-type';
import { getCommonCommand } from './common';
import { IStateService } from '../services/state-service';
import { StateServiceSymbol } from '../symbols';

export default getCommonCommand(async () => {
const cycodeService = container.resolve<ICycodeService>(CycodeService);
const stateService = container.resolve<IStateService>(StateServiceSymbol);

const scanPromises = [];
scanPromises.push(cycodeService.startScanForCurrentProject(CliScanType.Secret));
scanPromises.push(cycodeService.startScanForCurrentProject(CliScanType.Sca));
scanPromises.push(cycodeService.startScanForCurrentProject(CliScanType.Iac));
scanPromises.push(cycodeService.startScanForCurrentProject(CliScanType.Sast));

if (stateService.tempState.IsSecretScanningEnabled) {
scanPromises.push(cycodeService.startScanForCurrentProject(CliScanType.Secret));
}
if (stateService.tempState.IsScaScanningEnabled) {
scanPromises.push(cycodeService.startScanForCurrentProject(CliScanType.Sca));
}
if (stateService.tempState.IsIacScanningEnabled) {
scanPromises.push(cycodeService.startScanForCurrentProject(CliScanType.Iac));
}
if (stateService.tempState.IsSastScanningEnabled) {
scanPromises.push(cycodeService.startScanForCurrentProject(CliScanType.Sast));
}

await Promise.all(scanPromises);
});
52 changes: 52 additions & 0 deletions src/commands/tree-view-filter-by-severity-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { container } from 'tsyringe';
import { ExtensionServiceSymbol, StateServiceSymbol } from '../symbols';
import vscode from 'vscode';
import { IStateService } from '../services/state-service';
import { IExtensionService } from '../services/extension-service';

const _SEVERITY_NAMES: readonly string[] = ['Critical', 'High', 'Medium', 'Low', 'Info'];

const treeViewFilterBySeverityCallback = (severityName: string, enabled: boolean) => {
const extension = container.resolve<IExtensionService>(ExtensionServiceSymbol);
const stateService = container.resolve<IStateService>(StateServiceSymbol);
const tempState = stateService.tempState;

switch (severityName) {
case 'Critical':
tempState.IsTreeViewFilterByCriticalSeverityEnabled = enabled;
break;
case 'High':
tempState.IsTreeViewFilterByHighSeverityEnabled = enabled;
break;
case 'Medium':
tempState.IsTreeViewFilterByMediumSeverityEnabled = enabled;
break;
case 'Low':
tempState.IsTreeViewFilterByLowSeverityEnabled = enabled;
break;
case 'Info':
tempState.IsTreeViewFilterByInfoSeverityEnabled = enabled;
break;
}

stateService.save();
extension.treeDataProvider.refresh();
};

export default (context: vscode.ExtensionContext): void => {
for (const severity of _SEVERITY_NAMES) {
const enableFilterCommandId = `cycode.enableFilterBy${severity}Severity`;
context.subscriptions.push(
vscode.commands.registerCommand(
enableFilterCommandId, () => { treeViewFilterBySeverityCallback(severity, true); },
),
);

const disableFilterCommandId = `cycode.disableFilterBy${severity}Severity`;
context.subscriptions.push(
vscode.commands.registerCommand(
disableFilterCommandId, () => { treeViewFilterBySeverityCallback(severity, false); },
),
);
}
};
Loading