Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6f72711

Browse files
authoredJan 7, 2025
Merge pull request #248 from snyk/feat/add-login-button
feat: add login button to plugin welcome page [IDE-798]
2 parents 7d48ade + 6fa083b commit 6f72711

File tree

10 files changed

+194
-53
lines changed

10 files changed

+194
-53
lines changed
 

‎plugin/OSGI-INF/l10n/bundle.properties

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,4 @@ tooltip.showNetNewIssues=Show Only Net New Issues
5050
scanWorkspace.name=snykWorkspaceScan
5151
scanWorkspace.label=Snyk Test Workspace
5252

53-
snyk.trust.dialog.warning.text=When scanning project files for vulnerabilities, Snyk may automatically execute code such as invoking the package manager to get dependency information.<br><br>You should only scan projects you trust.<br><br>
54-
55-
53+
snyk.panel.auth.trust.warning.text=When scanning project files, Snyk may automatically execute code such as invoking the package manager to get dependency information.<br/>You should only scan projects you trust. <a href="https://docs.snyk.io/ide-tools/eclipse-plugin/folder-trust">More info</a>

‎plugin/src/main/java/io/snyk/eclipse/plugin/SnykStartup.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import org.eclipse.core.runtime.Platform;
1717
import org.eclipse.core.runtime.Status;
1818
import org.eclipse.core.runtime.jobs.Job;
19-
import org.eclipse.jface.wizard.WizardDialog;
2019
import org.eclipse.ui.IStartup;
2120
import org.eclipse.ui.IWorkbench;
2221
import org.eclipse.ui.IWorkbenchPage;
@@ -68,11 +67,7 @@ protected IStatus run(IProgressMonitor monitor) {
6867
Preferences prefs = Preferences.getInstance();
6968
if (prefs.getAuthToken().isBlank() && !prefs.isTest()) {
7069
monitor.subTask("Starting Snyk Wizard to configure initial settings...");
71-
SnykWizard wizard = new SnykWizard();
72-
WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(),
73-
wizard);
74-
dialog.setBlockOnOpen(true);
75-
dialog.open();
70+
SnykWizard.createAndLaunch();
7671
}
7772
});
7873
monitor.done();

‎plugin/src/main/java/io/snyk/eclipse/plugin/html/BaseHtmlProvider.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public String getNonce() {
4848

4949
public String getNoDescriptionHtml() {
5050
String snykWarningText = Platform.getResourceString(Platform.getBundle("io.snyk.eclipse.plugin"),
51-
"%snyk.trust.dialog.warning.text");
51+
"snyk.panel.auth.trust.warning.text");
5252

5353
Bundle bundle = Platform.getBundle("io.snyk.eclipse.plugin");
5454
String base64Image = ResourceUtils.getBase64Image(bundle, "logo_snyk.png");
@@ -107,8 +107,9 @@ public String replaceCssVariables(String html) {
107107
// Replace CSS variables with actual color values
108108
html = html.replace("var(--text-color)", getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_TEXT_COLOR", "#000000"));
109109
html = html.replace("var(--background-color)", getColorAsHex("org.eclipse.ui.workbench.ACTIVE_TAB_BG_END", "#FFFFFF"));
110-
html = html.replace("var(--code-background-color)", getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
111-
html = html.replace("var(--circle-color)", getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
110+
html = html.replace("var(--code-background-color)", getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
111+
html = html.replace("var(--button-color)", getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
112+
html = html.replace("var(--circle-color)", getColorAsHex("org.eclipse.ui.workbench.INACTIVE_TAB_BG_START", "#F0F0F0"));
112113

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

‎plugin/src/main/java/io/snyk/eclipse/plugin/html/StaticPageHtmlProvider.java

Lines changed: 101 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,56 +19,133 @@ public static StaticPageHtmlProvider getInstance() {
1919
return instance;
2020
}
2121

22-
public String getInitHtml() {
23-
String snykWarningText = Platform.getResourceString(Platform.getBundle("io.snyk.eclipse.plugin"),
24-
"%snyk.trust.dialog.warning.text");
25-
26-
Bundle bundle = Platform.getBundle("io.snyk.eclipse.plugin");
27-
String base64Image = ResourceUtils.getBase64Image(bundle, "logo_snyk.png");
28-
29-
var html = """
30-
<!DOCTYPE html>
31-
<html lang="en">
22+
private String head = """
3223
<head>
3324
<meta charset="UTF-8">
3425
<meta name="viewport" content="width=device-width, initial-scale=1.0">
3526
<title>Snyk for Eclipse</title>
3627
<style>
28+
html {
29+
height:100%;
30+
}
3731
body {
38-
font-family: var(--default-font);
32+
font-family: var(--default-font);
3933
background-color: var(--background-color);
4034
color: var(--text-color);
35+
display: flex;
36+
align-items: center;
37+
justify-content: center;
38+
height: 100%;
4139
}
4240
.container {
4341
display: flex;
4442
align-items: center;
43+
justify-content: center;
44+
}
45+
.status {
46+
text-align: center;
47+
}
48+
.welcome-text {
49+
width: 520px;
50+
}
51+
.agreement-text {
52+
font-size: smaller;
53+
display: inline-block;
54+
width: 350px;
4555
}
4656
.logo {
4757
margin-right: 20px;
4858
}
49-
a {
50-
color: var(--link-color)
51-
}
52-
53-
div {
54-
padding: 20px
55-
}
59+
a {
60+
color: var(--link-color);
61+
}
62+
div {
63+
padding: 20px;
64+
}
65+
button {
66+
text-align: center;
67+
text-decoration: none;
68+
background-color: var(--button-color);
69+
display: inline-block;
70+
border-color: var(--border-color);
71+
border-style: solid;
72+
border-radius: 5px;
73+
font-family: inherit;
74+
font-size: inherit;
75+
color: inherit;
76+
}
5677
</style>
5778
</head>
79+
""";
80+
81+
public String getScanningHtml() {
82+
var html = """
83+
<!DOCTYPE html>
84+
<html lang="en">
85+
%s
86+
<body>
87+
<div class="container">
88+
<p>
89+
Scanning project for vulnerabilities...<br/>
90+
<a class="stop_scan" onclick="window.stopScan();">Stop Scanning</a>
91+
</p>
92+
</div>
93+
</body>
94+
</html>
95+
""".formatted(head);
96+
return replaceCssVariables(html);
97+
}
98+
99+
public String getDefaultHtml() {
100+
var html = """
101+
<!DOCTYPE html>
102+
<html lang="en">
103+
%s
104+
<body>
105+
<div class="container">
106+
<p>
107+
Select an issue and start improving your project.
108+
</p>
109+
</div>
110+
</body>
111+
</html>
112+
""".formatted(head);
113+
return replaceCssVariables(html);
114+
}
115+
116+
public String getInitHtml() {
117+
String snykWarningText = Platform.getResourceString(Platform.getBundle("io.snyk.eclipse.plugin"),
118+
"%snyk.panel.auth.trust.warning.text");
119+
120+
Bundle bundle = Platform.getBundle("io.snyk.eclipse.plugin");
121+
String base64Image = ResourceUtils.getBase64Image(bundle, "logo_snyk.png");
122+
123+
var html = """
124+
<!DOCTYPE html>
125+
<html lang="en">
126+
%s
58127
<body>
59128
<div class="container">
60129
<img src='data:image/png;base64,%s' alt='Snyk Logo'>
61-
<div>
62-
<p><strong>Welcome to Snyk for Eclipse</strong></p>
130+
<div class="welcome-text">
131+
<p><strong>Welcome to Snyk for Eclipse!</strong></p>
132+
<ol>
133+
<li align="left">Authenticate to Snyk.io</li>
134+
<li align="left">Analyze code for issues and vulnerabilities</li>
135+
<li align="left">Improve your code and upgrade dependencies</li>
136+
</ol>
63137
<p>%s</p>
64-
By connecting your account with Snyk, you agree to<br>
65-
the Snyk <a href="https://snyk.io/policies/privacy/">Privacy Policy</a>,
66-
and the Snyk <a href="https://snyk.io/policies/terms-of-service/">Terms of Service</a>.
138+
<button type="button" onclick="window.initiateLogin()">Trust project and scan</button>
139+
<p class="agreement-text">
140+
By connecting your account with Snyk, you agree to
141+
the Snyk <a href="https://snyk.io/policies/privacy/">Privacy Policy</a>,
142+
and the Snyk <a href="https://snyk.io/policies/terms-of-service/">Terms of Service</a>.
143+
</p>
67144
</div>
68145
</div>
69146
</body>
70147
</html>
71-
""".formatted(base64Image, snykWarningText);
148+
""".formatted(head, base64Image, snykWarningText);
72149
return replaceCssVariables(html);
73150
}
74151

‎plugin/src/main/java/io/snyk/eclipse/plugin/views/snyktoolview/BrowserHandler.java

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
import java.nio.file.Paths;
66
import java.util.concurrent.CompletableFuture;
77

8+
import org.eclipse.core.commands.ExecutionException;
9+
import org.eclipse.core.commands.NotEnabledException;
10+
import org.eclipse.core.commands.NotHandledException;
11+
import org.eclipse.core.commands.common.CommandException;
12+
import org.eclipse.core.commands.common.NotDefinedException;
813
import org.eclipse.jface.viewers.TreeNode;
914
import org.eclipse.lsp4e.LSPEclipseUtils;
1015
import org.eclipse.lsp4j.Location;
@@ -18,13 +23,18 @@
1823
import org.eclipse.swt.browser.ProgressEvent;
1924
import org.eclipse.swt.program.Program;
2025
import org.eclipse.swt.widgets.Display;
26+
import org.eclipse.ui.PlatformUI;
27+
import org.eclipse.ui.handlers.IHandlerService;
2128

2229
import com.google.gson.Gson;
2330

2431
import io.snyk.eclipse.plugin.html.BaseHtmlProvider;
2532
import io.snyk.eclipse.plugin.html.HtmlProviderFactory;
2633
import io.snyk.eclipse.plugin.html.StaticPageHtmlProvider;
34+
import io.snyk.eclipse.plugin.preferences.Preferences;
2735
import io.snyk.eclipse.plugin.utils.SnykLogger;
36+
import io.snyk.eclipse.plugin.views.snyktoolview.handlers.IHandlerCommands;
37+
import io.snyk.eclipse.plugin.wizards.SnykWizard;
2838

2939
@SuppressWarnings("restriction")
3040
public class BrowserHandler {
@@ -66,6 +76,28 @@ public Object function(Object[] arguments) {
6676
}
6777
};
6878

79+
new BrowserFunction(browser, "initiateLogin") {
80+
@Override
81+
public Object function(Object[] arguments) {
82+
SnykWizard.createAndLaunch();
83+
return null;
84+
}
85+
};
86+
87+
new BrowserFunction(browser, "stopScan") {
88+
@Override
89+
public Object function(Object[] arguments) {
90+
IHandlerService handlerService =
91+
(IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
92+
try {
93+
handlerService.executeCommand(IHandlerCommands.STOP_SCAN, null);
94+
} catch (CommandException e) {
95+
SnykLogger.logError(e);
96+
}
97+
return null;
98+
}
99+
};
100+
69101
browser.addLocationListener(new LocationListener() {
70102
@Override
71103
public void changing(LocationEvent event) {
@@ -89,7 +121,8 @@ public void completed(ProgressEvent event) {
89121
}
90122
}
91123
});
92-
initBrowserText();
124+
125+
setDefaultBrowserText();
93126
}
94127

95128
private record ErrorMessage(String error, String path) {
@@ -99,10 +132,12 @@ public CompletableFuture<Void> updateBrowserContent(TreeNode node) {
99132
// Generate HTML content based on the selected node
100133
var htmlProvider = getHtmlProvider(node);
101134
initScript = htmlProvider.getInitScript();
135+
boolean shouldShowDefaultMessage = true;
102136
if (node instanceof ProductTreeNode) {
103137
var ptn = (ProductTreeNode) node;
104138
String errorJson = ptn.getErrorMessage();
105139
if (errorJson != null && !errorJson.isBlank()) {
140+
shouldShowDefaultMessage = false;
106141
var error = new Gson().fromJson(errorJson, ErrorMessage.class);
107142
String errorHtml = htmlProvider.getErrorHtml(error.error, error.path);
108143
Display.getDefault().syncExec(() -> {
@@ -111,8 +146,12 @@ public CompletableFuture<Void> updateBrowserContent(TreeNode node) {
111146
}
112147
}
113148

114-
if (!(node instanceof IssueTreeNode))
149+
if (!(node instanceof IssueTreeNode)) {
150+
if (shouldShowDefaultMessage) {
151+
setDefaultBrowserText();
152+
}
115153
return CompletableFuture.completedFuture(null);
154+
}
116155

117156
return CompletableFuture.supplyAsync(() -> {
118157
return generateHtmlContent(node);
@@ -127,7 +166,6 @@ public CompletableFuture<Void> updateBrowserContent(TreeNode node) {
127166
browser.setText(browserContent);
128167
});
129168
});
130-
131169
}
132170

133171
private BaseHtmlProvider getHtmlProvider(TreeNode node) {
@@ -155,7 +193,16 @@ public String generateHtmlContent(String text) {
155193
return "<html><body<p>" + text + "</p></body></html>";
156194
}
157195

158-
public void initBrowserText() {
159-
browser.setText(StaticPageHtmlProvider.getInstance().getInitHtml());
196+
public void setDefaultBrowserText() {
197+
// If we are not authenticated, show the welcome page, else show the issue placeholder.
198+
if (Preferences.getInstance().getAuthToken().isBlank()) {
199+
browser.setText(StaticPageHtmlProvider.getInstance().getInitHtml());
200+
} else {
201+
browser.setText(StaticPageHtmlProvider.getInstance().getDefaultHtml());
202+
}
203+
}
204+
205+
public void setScanningBrowserText() {
206+
browser.setText(StaticPageHtmlProvider.getInstance().getScanningHtml());
160207
}
161208
}

‎plugin/src/main/java/io/snyk/eclipse/plugin/views/snyktoolview/ISnykToolView.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ public interface ISnykToolView {
7575
*/
7676
abstract void refreshTree();
7777

78+
/**
79+
* Refreshes the browser
80+
*/
81+
abstract void refreshBrowser(String status);
82+
7883
/**
7984
* Returns the tree root
8085
*

‎plugin/src/main/java/io/snyk/eclipse/plugin/views/snyktoolview/SnykToolView.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.snyk.eclipse.plugin.views.snyktoolview;
22

3+
import static io.snyk.eclipse.plugin.domain.ProductConstants.SCAN_STATE_IN_PROGRESS;
4+
35
import java.nio.file.Path;
46
import java.nio.file.Paths;
57
import java.util.Map;
@@ -305,6 +307,17 @@ public void refreshTree() {
305307
});
306308
}
307309

310+
@Override
311+
public void refreshBrowser(String status) {
312+
Display.getDefault().asyncExec(() -> {
313+
if (status != null && status.equals(SCAN_STATE_IN_PROGRESS)) {
314+
this.browserHandler.setScanningBrowserText();
315+
} else {
316+
this.browserHandler.setDefaultBrowserText();
317+
}
318+
});
319+
};
320+
308321
@Override
309322
public void resetNode(BaseTreeNode node) {
310323
if (node != null)

‎plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizard.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import org.eclipse.core.runtime.jobs.Job;
77
import org.eclipse.jface.viewers.IStructuredSelection;
88
import org.eclipse.jface.wizard.Wizard;
9+
import org.eclipse.jface.wizard.WizardDialog;
910
import org.eclipse.ui.INewWizard;
1011
import org.eclipse.ui.IWorkbench;
12+
import org.eclipse.ui.PlatformUI;
1113

1214
import io.snyk.eclipse.plugin.SnykStartup;
1315
import io.snyk.eclipse.plugin.utils.ResourceUtils;
@@ -92,4 +94,11 @@ protected IStatus run(IProgressMonitor monitor) {
9294
}.schedule();
9395
return true;
9496
}
97+
98+
public static void createAndLaunch() {
99+
SnykWizard wizard = new SnykWizard();
100+
WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), wizard);
101+
dialog.setBlockOnOpen(true);
102+
dialog.open();
103+
}
95104
}

0 commit comments

Comments
 (0)