Skip to content
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

feat: summary panel [IDE-892] #253

Merged
merged 20 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 16 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
@@ -1,5 +1,9 @@
# Snyk Security Changelog

## [3.0.1]
### Changes
- New Summary Panel for scan information and net new issues filter.

## [3.0.0]
### Changes
- process api URL from hasAuthenticated message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
public class TaskProcessor {
// left = taskToExecute, right = callback function
private final ConcurrentLinkedQueue<Pair<Consumer<SnykExtendedLanguageClient>, Consumer<Void>>> taskQueue = new ConcurrentLinkedQueue<>();

Check warning on line 20 in plugin/src/main/java/io/snyk/eclipse/plugin/analytics/TaskProcessor.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Avoid using implementation types like 'ConcurrentLinkedQueue'; use the interface instead

Excessive coupling to implementation types (e.g., `HashSet`) limits your ability to use alternate implementations in the future as requirements change. Whenever available, declare variables and parameters using a more general type (e.g, `Set`). This rule reports uses of concrete collection types. User-defined types that should be treated the same as interfaces can be configured with the property `allowedTypes`. LooseCoupling (Priority: 3, Ruleset: Best Practices) https://docs.pmd-code.org/pmd-doc-7.9.0/pmd_rules_java_bestpractices.html#loosecoupling

private TaskProcessor() {
CompletableFuture.runAsync(() -> {
Expand All @@ -41,7 +41,7 @@
private void start() {
while (true) {
String authToken = Preferences.getInstance().getAuthToken();
var lc = SnykExtendedLanguageClient.getInstance();
SnykExtendedLanguageClient lc = SnykExtendedLanguageClient.getInstance();
if (taskQueue.isEmpty() || authToken == null || authToken.isBlank() || lc == null) {
try {
Thread.sleep(1000);
Expand All @@ -50,8 +50,8 @@
}
continue;
}
List<Pair<Consumer<SnykExtendedLanguageClient>, Consumer<Void>>> copyForSending = new ArrayList<>(
taskQueue);

Check warning on line 54 in plugin/src/main/java/io/snyk/eclipse/plugin/analytics/TaskProcessor.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Avoid instantiating new objects inside loops

New objects created within loops should be checked to see if they can created outside them and reused. AvoidInstantiatingObjectsInLoops (Priority: 3, Ruleset: Performance) https://docs.pmd-code.org/pmd-doc-7.9.0/pmd_rules_java_performance.html#avoidinstantiatingobjectsinloops

for (Pair<Consumer<SnykExtendedLanguageClient>, Consumer<Void>> event : copyForSending) {
try {
Expand Down
277 changes: 143 additions & 134 deletions plugin/src/main/java/io/snyk/eclipse/plugin/html/BaseHtmlProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,33 @@
private final Random random = new Random();
private final Map<String, String> colorCache = new HashMap<>();
private String nonce = "";
public String getCss() {
return "";
}

public String getJs() {
return "";
}

public String getInitScript() {
return "";
}

public String getNonce() {
if(!nonce.isEmpty()) {
return nonce;
}
String allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder nonceBuilder = new StringBuilder(32);
for (int i = 0; i < 32; i++) {
nonceBuilder.append(allowedChars.charAt(random.nextInt(allowedChars.length())));
}
nonce = nonceBuilder.toString();
return nonce;
}
public String getNoDescriptionHtml() {

public String getCss() {
return "";
}

public String getJs() {
return "";
}

public String getInitScript() {
return "";
}

public String getNonce() {
if (!nonce.isEmpty()) {
return nonce;
}
String allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder nonceBuilder = new StringBuilder(32);
for (int i = 0; i < 32; i++) {
nonceBuilder.append(allowedChars.charAt(random.nextInt(allowedChars.length())));
}
nonce = nonceBuilder.toString();
return nonce;
}

public String getNoDescriptionHtml() {
String snykWarningText = Platform.getResourceString(Platform.getBundle("io.snyk.eclipse.plugin"),
"snyk.panel.auth.trust.warning.text");

Expand Down Expand Up @@ -75,7 +75,7 @@
a {
color: var(--link-color)
}

div {
padding: 20px
}
Expand All @@ -94,116 +94,125 @@
return html;
}

public String replaceCssVariables(String html) {
// Build the CSS with the nonce
String nonce = getNonce();
String css = "<style nonce=\"" + nonce + "\">" + getCss() + "</style>";
String htmlStyled = html.replace("${ideStyle}", css);
htmlStyled = htmlStyled.replace("<style nonce=\"ideNonce\" data-ide-style></style>", css);
htmlStyled = htmlStyled.replace("var(--default-font)",
" ui-sans-serif, \"SF Pro Text\", \"Segoe UI\", \"Ubuntu\", Tahoma, Geneva, Verdana, sans-serif;");

// Replace CSS variables with actual color values
htmlStyled = htmlStyled.replace("var(--text-color)",
getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_TEXT_COLOR", "#000000"));

htmlStyled = htmlStyled.replace("var(--ide-background-color)",
getColorAsHex("org.eclipse.ui.workbench.ACTIVE_NOFOCUS_TAB_BG_START", "#FFFFFF"));
htmlStyled = htmlStyled.replace("var(--background-color)",
getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_BG_END", "#FFFFFF"));
htmlStyled = htmlStyled.replace("var(--code-background-color)",
getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
htmlStyled = htmlStyled.replace("var(--button-color)",
getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
htmlStyled = htmlStyled.replace("var(--circle-color)",
getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));

htmlStyled = htmlStyled.replace("var(--border-color)",
getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_OUTER_KEYLINE_COLOR", "#CCCCCC"));
htmlStyled = htmlStyled.replace("var(--link-color)", getColorAsHex("ACTIVE_HYPERLINK_COLOR", "#0000FF"));
htmlStyled = htmlStyled.replace("var(--horizontal-border-color)",
getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_OUTER_KEYLINE_COLOR", "#CCCCCC"));

htmlStyled = htmlStyled.replace("${headerEnd}", "");
htmlStyled = htmlStyled.replace("${nonce}", nonce);
htmlStyled = htmlStyled.replace("ideNonce", nonce);

return htmlStyled;
}

public String replaceCssVariables(String html) {
// Build the CSS with the nonce
String nonce = getNonce();
String css = "<style nonce=\"" + nonce + "\">" + getCss() + "</style>";
html = html.replace("${ideStyle}", css);
html = html.replace("<style nonce=\"ideNonce\" data-ide-style></style>", css);
html = html.replace("var(--default-font)", " ui-sans-serif, \"SF Pro Text\", \"Segoe UI\", \"Ubuntu\", Tahoma, Geneva, Verdana, sans-serif;");


// Replace CSS variables with actual color values
html = html.replace("var(--text-color)", getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_TEXT_COLOR", "#000000"));
html = html.replace("var(--background-color)", getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_BG_END", "#FFFFFF"));
html = html.replace("var(--code-background-color)", getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
html = html.replace("var(--button-color)", getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
html = html.replace("var(--circle-color)", getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));

html = html.replace("var(--border-color)", getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_OUTER_KEYLINE_COLOR", "#CCCCCC"));
html = html.replace("var(--link-color)", getColorAsHex("ACTIVE_HYPERLINK_COLOR", "#0000FF"));
html = html.replace("var(--horizontal-border-color)", getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_OUTER_KEYLINE_COLOR", "#CCCCCC"));

html = html.replace("${headerEnd}", "");
html = html.replace("${nonce}", nonce);
html = html.replace("ideNonce", nonce);
html = html.replace("${ideScript}", "");

return html;
}

public String getColorAsHex(String colorKey, String defaultColor) {
if(Preferences.getInstance().isTest()) {
public String getColorAsHex(String colorKey, String defaultColor) {
if (Preferences.getInstance().isTest()) {
return "";
}
return colorCache.computeIfAbsent(colorKey, key -> {
ColorRegistry colorRegistry = getColorRegistry();
Color color = colorRegistry.get(colorKey);
if (color == null) {
return defaultColor;
} else {
RGB rgb = color.getRGB();
return String.format("#%02x%02x%02x", rgb.red, rgb.green, rgb.blue);
}
});
}

public Boolean isDarkTheme() {
var darkColor = getColorAsHex("org.eclipse.ui.workbench.DARK_BACKGROUND", "");
return darkColor.equals("true");
}

private ColorRegistry colorRegistry;
private ColorRegistry getColorRegistry() {
if(colorRegistry != null) {
return colorRegistry;
}
ITheme currentTheme = getCurrentTheme();
colorRegistry = currentTheme.getColorRegistry();
return colorRegistry;
}


private ITheme currentTheme;
public ITheme getCurrentTheme() {
if(currentTheme != null) {
return currentTheme;
}
IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
currentTheme = themeManager.getCurrentTheme();
return currentTheme;
}

public String getErrorHtml(String errorMessage, String path) {
return colorCache.computeIfAbsent(colorKey, key -> {
ColorRegistry colorRegistry = getColorRegistry();
Color color = colorRegistry.get(colorKey);
if (color == null) {
return defaultColor;
} else {
RGB rgb = color.getRGB();
return String.format("#%02x%02x%02x", rgb.red, rgb.green, rgb.blue);
}
});
}

public Boolean isDarkTheme() {
var darkColor = getColorAsHex("org.eclipse.ui.workbench.DARK_BACKGROUND", "");
return darkColor.equals("true");

Check warning on line 152 in plugin/src/main/java/io/snyk/eclipse/plugin/html/BaseHtmlProvider.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Position literals first in String comparisons

Position literals first in all String comparisons, if the second argument is null then NullPointerExceptions can be avoided, they will just return false. Note that switching literal positions for compareTo and compareToIgnoreCase may change the result, see examples. LiteralsFirstInComparisons (Priority: 3, Ruleset: Best Practices) https://docs.pmd-code.org/pmd-doc-7.9.0/pmd_rules_java_bestpractices.html#literalsfirstincomparisons
Fixed Show fixed Hide fixed
}

private ColorRegistry colorRegistry;

private ColorRegistry getColorRegistry() {
if (colorRegistry != null) {
return colorRegistry;
}
ITheme currentTheme = getCurrentTheme();
colorRegistry = currentTheme.getColorRegistry();
return colorRegistry;
}

private ITheme currentTheme;

public ITheme getCurrentTheme() {
if (currentTheme != null) {
return currentTheme;
}
IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
currentTheme = themeManager.getCurrentTheme();
return currentTheme;
}

public String getErrorHtml(String errorMessage, String path) {
var html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snyk for Eclipse</title>
<style>
body {
font-family: var(--default-font);
background-color: var(--background-color);
color: var(--text-color);
}
.container {
display: flex;
align-items: center;
}
.logo {
margin-right: 20px;
}
</style>
</head>
<body>
<div class="container">
<div>
<p><strong>An error occurred:</strong></p>
<p>
<table>
<tr><td width="150" >Error message:</td><td>%s</td></tr>
<tr></tr>
<tr><td>Path:</td><td>%s</td></tr>
</table>
</p>
</div>
</div>
</body>
</html>
""".formatted(errorMessage, path);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snyk for Eclipse</title>
<style>
body {
font-family: var(--default-font);
background-color: var(--background-color);
color: var(--text-color);
}
.container {
display: flex;
align-items: center;
}
.logo {
margin-right: 20px;
}
</style>
</head>
<body>
<div class="container">
<div>
<p><strong>An error occurred:</strong></p>
<p>
<table>
<tr><td width="150" >Error message:</td><td>%s</td></tr>
<tr></tr>
<tr><td>Path:</td><td>%s</td></tr>
</table>
</p>
</div>
</div>
</body>
</html>
""".formatted(errorMessage, path);
return replaceCssVariables(html);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package io.snyk.eclipse.plugin.html;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Bundle;
import io.snyk.eclipse.plugin.utils.SnykLogger;

import io.snyk.eclipse.plugin.utils.ResourceUtils;

public class StaticPageHtmlProvider extends BaseHtmlProvider {
private static StaticPageHtmlProvider instance = new StaticPageHtmlProvider();
private static ILog logger;

public static StaticPageHtmlProvider getInstance() {
synchronized (StaticPageHtmlProvider.class) {
Expand All @@ -18,7 +26,7 @@
}
return instance;
}

private String head = """
<head>
<meta charset="UTF-8">
Expand Down Expand Up @@ -148,6 +156,29 @@
""".formatted(head, base64Image, snykWarningText);
return replaceCssVariables(html);
}



public String getSummaryInitHtml() {
if (logger == null) {
logger = Platform.getLog(getClass());
}
StringBuilder content = new StringBuilder();

try (InputStream inputStream = getClass().getResourceAsStream("/ui/html/ScanSummaryInit.html");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {

String line;
while ((line = reader.readLine()) != null) {

Check warning on line 170 in plugin/src/main/java/io/snyk/eclipse/plugin/html/StaticPageHtmlProvider.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Avoid assignments in operands

Avoid assignments in operands; this can make code more complicated and harder to read. AssignmentInOperand (Priority: 3, Ruleset: Error Prone) https://docs.pmd-code.org/pmd-doc-7.9.0/pmd_rules_java_errorprone.html#assignmentinoperand
Fixed Show fixed Hide fixed
content.append(line).append("\n");

Check warning on line 171 in plugin/src/main/java/io/snyk/eclipse/plugin/html/StaticPageHtmlProvider.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Avoid appending characters as strings in StringBuffer.append.

Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods. AppendCharacterWithChar (Priority: 3, Ruleset: Performance) https://docs.pmd-code.org/pmd-doc-7.9.0/pmd_rules_java_performance.html#appendcharacterwithchar
Fixed Show fixed Hide fixed
}
} catch (IOException e) {
SnykLogger.logError(e);
}

return replaceCssVariables(content.toString());
}

public String getFormattedSummaryHtml(String summary) {
String summaryWithFunc = summary.replace("${ideFunc}", "window.enableDelta(isEnabled);");
return replaceCssVariables(summaryWithFunc);
ShawkyZ marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
public BaseBranchDialog() {
}

public void open(Display display, Path projectPath, String[] localBranches) {

Check warning on line 28 in plugin/src/main/java/io/snyk/eclipse/plugin/views/snyktoolview/BaseBranchDialog.java

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Consider using varargs for methods or constructors which take an array the last parameter.

Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic sugar provides flexibility for users of these methods and constructors, allowing them to avoid having to deal with the creation of an array. Byte arrays in any method and String arrays in `public static void main(String[])` methods are ignored. UseVarargs (Priority: 4, Ruleset: Best Practices) https://docs.pmd-code.org/pmd-doc-7.9.0/pmd_rules_java_bestpractices.html#usevarargs
Shell shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
shell.setText("Choose base branch for net-new issues scanning");
shell.setLayout(new GridLayout(1, false));
Expand All @@ -50,7 +50,8 @@
folderConfigs.setBaseBranch(projectPath, selectedBranch);
shell.close();
CompletableFuture.runAsync(() -> {
SnykExtendedLanguageClient.getInstance().triggerScan(projectPath);
SnykExtendedLanguageClient lc = SnykExtendedLanguageClient.getInstance();
lc.triggerScan(projectPath);
});
} else {
SnykLogger.logInfo("Branch is not a valid local branch for repository: " + projectPath);
Expand Down
Loading
Loading