diff --git a/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/TypedApiImplementation.java b/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/TypedApiImplementation.java index d92ea79..4494c11 100644 --- a/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/TypedApiImplementation.java +++ b/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/TypedApiImplementation.java @@ -333,10 +333,9 @@ public String getAnalysisLogs(BinaryID binID) { } public JSONObject health(){ - // The health check has no version prefix URI uri; try { - uri = new URI(baseUrl); + uri = new URI(baseUrl + apiVersion); } catch (URISyntaxException e) { throw new RuntimeException(e); } diff --git a/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/types/ApiInfo.java b/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/types/ApiInfo.java index c33b836..5d15dd2 100644 --- a/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/types/ApiInfo.java +++ b/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/types/ApiInfo.java @@ -3,8 +3,6 @@ import ai.reveng.toolkit.ghidra.core.models.ReaiConfig; import ai.reveng.toolkit.ghidra.core.services.api.TypedApiImplementation; import com.google.gson.Gson; -import ghidra.util.Msg; -import org.checkerframework.checker.units.qual.A; import org.json.JSONException; import java.io.FileNotFoundException; @@ -23,10 +21,6 @@ public ApiInfo(String hostURI, String apiKey) { this(URI.create(hostURI), apiKey); } - - public boolean check(){ - return checkServer() && checkCredentials(); - } public boolean checkServer(){ var api = new TypedApiImplementation(this); try { @@ -36,20 +30,29 @@ public boolean checkServer(){ return false; } } - public boolean checkCredentials(){ + public void checkCredentials() throws InvalidAPIInfoException { if (hostURI == null || apiKey == null){ - throw new IllegalArgumentException("hostURI and apiKey must not be null"); + throw new InvalidAPIInfoException("hostURI and apiKey must not be null"); } + var api = new TypedApiImplementation(this); // Send quick health request + var health = api.health(); + if (!health.getBoolean("success")){ + throw new InvalidAPIInfoException("Server health check failed: " + health.getString("message")); + } - var api = new TypedApiImplementation(this); + Boolean credentialsValid = null; try { - return api.checkCredentials(); + credentialsValid = api.checkCredentials(); + } catch (JSONException e) { - throw new IllegalArgumentException("Invalid JSON response from server " + hostURI); + throw new InvalidAPIInfoException("Invalid JSON response from server " + hostURI, e); } catch (Exception e) { - throw new IllegalArgumentException("Failed to validate credentials", e); + throw new InvalidAPIInfoException("Failed to validate credentials", e); + } + if (!credentialsValid){ + throw new InvalidAPIInfoException("Invalid API key"); } } diff --git a/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/types/InvalidAPIInfoException.java b/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/types/InvalidAPIInfoException.java new file mode 100644 index 0000000..4de02f3 --- /dev/null +++ b/src/main/java/ai/reveng/toolkit/ghidra/core/services/api/types/InvalidAPIInfoException.java @@ -0,0 +1,11 @@ +package ai.reveng.toolkit.ghidra.core.services.api.types; + +public class InvalidAPIInfoException extends Exception { + public InvalidAPIInfoException(String message) { + super(message); + } + + public InvalidAPIInfoException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/ai/reveng/toolkit/ghidra/core/ui/wizard/panels/UserCredentialsPanel.java b/src/main/java/ai/reveng/toolkit/ghidra/core/ui/wizard/panels/UserCredentialsPanel.java index 6c27e74..b618ec7 100644 --- a/src/main/java/ai/reveng/toolkit/ghidra/core/ui/wizard/panels/UserCredentialsPanel.java +++ b/src/main/java/ai/reveng/toolkit/ghidra/core/ui/wizard/panels/UserCredentialsPanel.java @@ -1,8 +1,9 @@ package ai.reveng.toolkit.ghidra.core.ui.wizard.panels; -import javax.swing.JPanel; +import javax.swing.*; import ai.reveng.toolkit.ghidra.core.services.api.types.ApiInfo; +import ai.reveng.toolkit.ghidra.core.services.api.types.InvalidAPIInfoException; import ai.reveng.toolkit.ghidra.core.ui.wizard.SetupWizardStateKey; import docking.wizard.AbstractMageJPanel; import docking.wizard.IllegalPanelStateException; @@ -10,9 +11,6 @@ import docking.wizard.WizardState; import ghidra.framework.plugintool.PluginTool; import java.awt.BorderLayout; -import javax.swing.JLabel; -import javax.swing.BoxLayout; -import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; @@ -20,6 +18,7 @@ public class UserCredentialsPanel extends AbstractMageJPanel { + var apiInfo = new ApiInfo(tfHostname.getText(), tfApiKey.getText()); + try { + apiInfo.checkCredentials(); + credentialsValidated = true; + // TODO: Get the user for this key once the API exists + notifyListenersOfValidityChanged(); + + } catch (InvalidAPIInfoException ex) { + credentialsValidated = false; + notifyListenersOfStatusMessage("Problem with user info:\n" + ex.getMessage()); + } + + }); + userDetailsPanel.add(runTestsButton); + + } @Override @@ -130,20 +153,12 @@ public boolean isValidInformation() { notifyListenersOfStatusMessage("Please enter a hostname for you API server"); return false; } - var apiInfo = new ApiInfo(tfHostname.getText(), tfApiKey.getText()); - // test that the API Key is valid before moving on to model selection - if (apiInfo.checkServer()){ - if (apiInfo.checkCredentials()){ - return true; - } else { - notifyListenersOfStatusMessage("Problem with API key"); - return false; - } - } else { - notifyListenersOfStatusMessage("Problem with host"); + if (!credentialsValidated){ + notifyListenersOfStatusMessage("Please validate your credentials"); return false; } - + notifyListenersOfStatusMessage("Credentials are valid"); + return true; } @Override