Skip to content

Commit

Permalink
Make credential validation in Wizard more responsive
Browse files Browse the repository at this point in the history
  • Loading branch information
fmagin committed Oct 4, 2024
1 parent 98e1b59 commit f955a14
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand All @@ -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");
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
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;
import docking.wizard.WizardPanelDisplayability;
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;

public class UserCredentialsPanel extends AbstractMageJPanel<SetupWizardStateKey> {
private static final long serialVersionUID = -9045013459967405703L;
private JTextField tfApiKey;
private JTextField tfHostname;
private Boolean credentialsValidated = false;

public UserCredentialsPanel(PluginTool tool) {
setLayout(new BorderLayout(0, 0));
Expand All @@ -40,19 +39,24 @@ public UserCredentialsPanel(PluginTool tool) {
JLabel lblApiKey = new JLabel("API Key:");
apiKeyPanel.add(lblApiKey);



DocumentListener documentListener = new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
credentialsValidated = false;
notifyListenersOfValidityChanged();
}

@Override
public void removeUpdate(DocumentEvent e) {
credentialsValidated = false;
notifyListenersOfValidityChanged();
}

@Override
public void changedUpdate(DocumentEvent e) {
credentialsValidated = false;
notifyListenersOfValidityChanged();
}
};
Expand All @@ -61,7 +65,7 @@ public void changedUpdate(DocumentEvent e) {
tfApiKey.getDocument().addDocumentListener(documentListener);
tfApiKey.setToolTipText("API key from your account settings");
apiKeyPanel.add(tfApiKey);
tfApiKey.setColumns(10);
tfApiKey.setColumns(20);

JPanel hostnamePanel = new JPanel();
userDetailsPanel.add(hostnamePanel);
Expand All @@ -74,7 +78,26 @@ public void changedUpdate(DocumentEvent e) {
tfHostname.setToolTipText("URL hosting the RevEng.AI Server");
tfHostname.setText("https://api.reveng.ai");
hostnamePanel.add(tfHostname);
tfHostname.setColumns(10);
tfHostname.setColumns(20);

JButton runTestsButton = new JButton("Validate Credentials");
runTestsButton.addActionListener(e -> {
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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit f955a14

Please sign in to comment.