Skip to content

Commit 035c1fb

Browse files
committed
fix: fix correct checking/unlocking radicle identity
1 parent 3b3c6f1 commit 035c1fb

File tree

19 files changed

+309
-191
lines changed

19 files changed

+309
-191
lines changed

jrad/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ pub extern "system" fn issueCommentReact(inp: *const c_char) -> *const c_char {
104104
}
105105
}
106106

107+
#[derive(Serialize, Deserialize, Clone, Debug)]
108+
struct BaseProfileInfo {
109+
home: Option<String>,
110+
passphrase: Option<String>,
111+
}
112+
107113
#[derive(Serialize, Deserialize, Clone, Debug)]
108114
struct ChangeIssueTitleDesc {
109115
repo_id: RepoId,
@@ -371,6 +377,14 @@ pub fn resolve_embed(repo: &Repository, embed: ContentEmbed) -> Result<Embed<Uri
371377
fn read_input(input: *const c_char) -> Result<String, anyhow::Error> {
372378
let input_str = unsafe { std::ffi::CStr::from_ptr(input) };
373379
let input_string = input_str.to_str()?;
380+
let base_info: BaseProfileInfo = serde_json::from_str(input_string)?;
381+
if base_info.home.is_some() {
382+
std::env::set_var("RAD_HOME", base_info.home.unwrap());
383+
}
384+
if base_info.passphrase.is_some() {
385+
std::env::set_var("RAD_PASSPHRASE", base_info.passphrase.unwrap());
386+
}
387+
374388
Ok(String::from(input_string))
375389
}
376390

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadAction.java

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -92,52 +92,61 @@ private RadicleProjectSettings getProjectSettings() {
9292
return projectHandler.loadSettings();
9393
}
9494

95+
9596
private ProcessOutput unlockIdentity(String radHome, String radPath, IdentityDialog dialog) {
9697
if (project == null && repo == null) {
9798
return new ProcessOutput(0);
9899
}
99100
var pr = project != null ? project : repo.getProject();
100-
var output = rad.self(radHome, radPath);
101-
var lines = output.getStdoutLines(true);
101+
final var idOutput = rad.self(radHome, radPath);
102+
final var hasIdentity = RadAction.isSuccess(idOutput);
103+
var lines = idOutput.getStdoutLines(true);
102104
var radDetails = new RadDetails(lines);
103-
var isIdentityUnlocked = rad.isIdentityUnlocked(radDetails.keyHash);
104-
var hasIdentity = RadAction.isSuccess(output);
105-
var projectSettings = new RadicleProjectSettingsHandler(pr);
105+
final var isIdentityUnlocked = rad.isIdentityUnlocked(radDetails.keyHash);
106+
if (isIdentityUnlocked) {
107+
return new ProcessOutput(0);
108+
}
109+
final var projectSettings = new RadicleProjectSettingsHandler(pr);
106110
String storedPassword = null;
107111
if (hasIdentity) {
112+
// check if key has no passphrase
113+
var ok = rad.isPassphraseCorrect("", radHome);
114+
if (ok) {
115+
projectSettings.savePassphrase(radDetails.nodeId, "");
116+
rad.auth("", "", radHome, radPath);
117+
return new ProcessOutput(0);
118+
}
119+
// the key has a non-empty passphrase, check if we have saved a password
108120
storedPassword = projectSettings.getPassword(radDetails.nodeId);
109121
}
110-
var hasStoredPassword = storedPassword != null;
111-
var showDialog = ((!hasIdentity || !isIdentityUnlocked) && !hasStoredPassword);
112-
IdentityDialog.IdentityDialogData dialogData = null;
113-
if (showDialog) {
114-
var authService = project.getService(AuthService.class);
115-
var title = !hasIdentity ? RadicleBundle.message("newIdentity") :
116-
RadicleBundle.message("unlockIdentity");
117-
dialogData = authService.showIdentityDialog(title, hasIdentity, dialog);
122+
final var hasStoredPassword = storedPassword != null;
123+
boolean hasCorrectStoredPassword = hasStoredPassword;
124+
if (hasIdentity && hasStoredPassword) {
125+
hasCorrectStoredPassword = rad.isPassphraseCorrect(storedPassword, radHome);
118126
}
119-
if (!isIdentityUnlocked && hasIdentity && hasStoredPassword) {
120-
var authOutput = rad.auth(storedPassword, "", radHome, radPath);
121-
var success = RadAuth.validateOutput(authOutput);
122-
if (!RadAction.isSuccess(success)) {
123-
projectSettings.savePassphrase(radDetails.nodeId, null);
124-
}
125-
return success;
127+
var showDialog = !hasIdentity || !hasStoredPassword || !hasCorrectStoredPassword;
128+
if (!showDialog) {
129+
// attempt to unlock identity (add key to ssh-agent)
130+
rad.auth(storedPassword, "", radHome, radPath);
131+
return new ProcessOutput(0);
126132
}
127-
if (dialogData != null) {
128-
var authOutput = rad.auth(dialogData.passphrase(), dialogData.alias(), radHome, radPath);
129-
var success = RadAuth.validateOutput(authOutput);
130-
if (RadAction.isSuccess(success)) {
131-
output = rad.self(radHome, radPath);
132-
lines = output.getStdoutLines(true);
133-
radDetails = new RadDetails(lines);
134-
projectSettings.savePassphrase(radDetails.nodeId, dialogData.passphrase());
135-
}
136-
return success;
133+
var authService = project.getService(AuthService.class);
134+
var title = !hasIdentity ? RadicleBundle.message("newIdentity") : RadicleBundle.message("unlockIdentity");
135+
final var dialogData = authService.showIdentityDialog(title, hasIdentity, dialog);
136+
if (hasIdentity) {
137+
// we already had an identity, so check the passphrase again
138+
hasCorrectStoredPassword = rad.isPassphraseCorrect(dialogData.passphrase(), radHome);
139+
if (!hasCorrectStoredPassword) {
140+
return new ProcessOutput(-1);
141+
}
137142
}
138-
var newOutput = new ProcessOutput(showDialog ? -1 : 0);
139-
newOutput.appendStderr(RadicleBundle.message("unableToUnlock"));
140-
return newOutput;
143+
// either create the new identity, or attempt to unlock the existing one
144+
rad.auth(dialogData.passphrase(), dialogData.alias(), radHome, radPath);
145+
var output = rad.self(radHome, radPath);
146+
lines = output.getStdoutLines(true);
147+
radDetails = new RadDetails(lines);
148+
projectSettings.savePassphrase(radDetails.nodeId, dialogData.passphrase());
149+
return new ProcessOutput(0);
141150
}
142151

143152
public ProcessOutput perform(CountDownLatch latch, String radHome, String radPath, IdentityDialog dialog) {
@@ -292,6 +301,18 @@ public static boolean isSuccess(ProcessOutput out) {
292301
return !out.isTimeout() && !out.isCancelled() && out.getExitCode() == 0;
293302
}
294303

304+
public static ProcessOutput validateAuthOutput(ProcessOutput output) {
305+
/* rad auth return success exit code (0) and a failed msg if the password is wrong */
306+
var isSuccess = RadAction.isSuccess(output) && !output.getStdout().contains("failed") &&
307+
!output.getStdout().contains("Nothing to do, ssh-agent is not running.");
308+
var pr = new ProcessOutput(isSuccess ? 0 : -1);
309+
/* Write from stdOut to stdErr in order to appear the message in the notification */
310+
var stdOut = output.getStdout();
311+
var errorMessage = !Strings.isNullOrEmpty(stdOut) ? stdOut : RadicleBundle.message("radCliError");
312+
pr.appendStderr(errorMessage);
313+
return pr;
314+
}
315+
295316
public static class ConfigureRadCliNotificationAction extends NotificationAction {
296317
final Project project;
297318

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadAuth.java

Lines changed: 0 additions & 69 deletions
This file was deleted.

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import com.google.common.base.Charsets;
44
import com.google.common.base.Strings;
5+
import com.intellij.execution.CommandLineUtil;
56
import com.intellij.execution.configurations.GeneralCommandLine;
6-
import com.intellij.execution.util.ExecUtil;
77
import com.intellij.openapi.project.Project;
88
import com.intellij.openapi.util.io.FileUtil;
99
import network.radicle.jetbrains.radiclejetbrainsplugin.config.RadicleProjectSettingsHandler;
@@ -104,7 +104,7 @@ private String getExportRadPassphrase() {
104104
if (Strings.isNullOrEmpty(password)) {
105105
return "";
106106
}
107-
return "export RAD_PASSPHRASE=" + ExecUtil.escapeUnixShellArgument(password);
107+
return "export RAD_PASSPHRASE=" + CommandLineUtil.posixQuote(password);
108108
}
109109

110110
private String getRandomScriptName() {

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/config/RadicleSettingsView.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,18 @@ private void unlockOrCreateIdentity() {
119119
var radHome = getPathFromTextField(radHomeField);
120120
var radPath = getPathFromTextField(radPathField);
121121
var radSelf = new RadSelf(radHome, radPath, myProject);
122-
var output = radSelf.perform(radHome, radPath, dialog);
122+
final var output = radSelf.perform(radHome, radPath, dialog);
123123
var lines = output.getStdoutLines(true);
124124
radDetails = new RadDetails(lines);
125-
logger.debug("got rad details: {}", radDetails.did);
126125
var cli = myProject.getService(RadicleCliService.class);
127126
if (cli != null) {
128127
cli.resetIdentity();
129128
}
130129
myLatch.countDown();
130+
if (!RadAction.isSuccess(output)) {
131+
ApplicationManager.getApplication().invokeLater(() -> this.msgLabel.setText(RadicleBundle.message("unableToUnlock")), ModalityState.any());
132+
return;
133+
}
131134
// check if rad home is non-default
132135
if (Strings.isNullOrEmpty(autoDetectRadHome.detected)) {
133136
autoDetectRadHome.detect();

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/overview/IssueComponent.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public JComponent createCommentSection(List<RadDiscussion> discussionList) {
118118
}
119119
var panel = new BorderLayoutPanel();
120120
panel.setOpaque(false);
121-
var editorPane = new MarkDownEditorPaneFactory(message, radIssue.project, radIssue.projectId, file);
121+
var editorPane = new MarkDownEditorPaneFactory(message, radIssue.project, radIssue.projectId, file, panel);
122122
panel.addToCenter(StatusMessageComponentFactory.INSTANCE.create(editorPane.htmlEditorPane(), StatusMessageType.WARNING));
123123
emojiPanel = new IssueEmojiPanel(issueModel, com.reactions, com.id, radDetails);
124124
var verticalPanel = getVerticalPanel(5);
@@ -173,8 +173,7 @@ public boolean createComment(DragAndDropField field) {
173173

174174
private JComponent getDescription() {
175175
var bodyIssue = radIssue.getDescription();
176-
var editorPane = new MarkDownEditorPaneFactory(bodyIssue, radIssue.project, radIssue.projectId, file);
177-
descPanel = Utils.descriptionPanel(editorPane, radIssue.project, "issue.change.description", f -> {
176+
descPanel = Utils.descriptionPanel(bodyIssue, radIssue.project, radIssue.projectId, file, "issue.change.description", f -> {
178177
var newDesc = f.getText();
179178
if (Strings.isNullOrEmpty(newDesc)) {
180179
return false;

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/patches/CreatePatchPanel.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ private void updateCommitFileComponents(LinkLabel<?> fromLabel, JLabel toLabel)
134134
ApplicationManager.getApplication().executeOnPooledThread(() -> {
135135
//Start loading indicator
136136
progressStripe.startLoading();
137-
//Get project information from httpd
137+
//Get project information
138138
projectInfo = getProjectInfo(mySelectedRepo);
139139
if (projectInfo == null) {
140140
return;
@@ -305,7 +305,8 @@ private void createPatch() {
305305
RadicleBundle.message("findRemoteErrorDesc"));
306306
return;
307307
}
308-
ApplicationManager.getApplication().executeOnPooledThread(() -> {
308+
// execute in background via rad, so that the jobs get assigned a progress indicator and ij stops throwing useless errors
309+
radicleProjectService.executeInBackground(() -> {
309310
newPatchButton.setEnabled(false);
310311
loadingPanel.setVisible(true);
311312
var cli = project.getService(RadicleCliService.class);

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/patches/PatchComponentFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.intellij.collaboration.ui.codereview.commits.CommitsBrowserComponentBuilder;
55
import com.intellij.openapi.Disposable;
66
import com.intellij.openapi.application.ApplicationManager;
7+
import com.intellij.openapi.progress.Task;
78
import com.intellij.openapi.project.Project;
89
import com.intellij.openapi.util.Key;
910
import com.intellij.openapi.vcs.VcsException;
@@ -98,7 +99,7 @@ public JComponent createCommitComponent() {
9899
}
99100

100101
public void updateFileAndCommitComponents(GitRepository repo, String revNumber, String mainBranchHead, int retriesAttempt) {
101-
ApplicationManager.getApplication().executeOnPooledThread(() -> {
102+
radicleProjectService.executeInBackground(() -> {
102103
try {
103104
var changes = calculatePatchCommits(repo, mainBranchHead, revNumber);
104105
calculatePatchChanges(repo, mainBranchHead, revNumber);

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/patches/review/PatchReviewThreadComponentFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ public JComponent getThreadActionsComponent(ThreadModel myThreadsModel) {
126126
}
127127

128128
private JComponent createComponent(RadDiscussion disc) {
129-
var editorPane = new MarkDownEditorPaneFactory(disc.body, patch.project, patch.radProject.id, patch.repo.getRoot());
129+
final var verticalPanel = getVerticalPanel(5);
130+
var editorPane = new MarkDownEditorPaneFactory(disc.body, patch.project, patch.radProject.id, patch.repo.getRoot(), verticalPanel);
130131
var revisionId = patch.findRevisionId(disc.id);
131132
var isOutDated = !patch.isDiscussionBelongedToLatestRevision(disc);
132133
var panelHandle = new EditablePanelHandler.PanelBuilder(patch.project, editorPane.htmlEditorPane(),
@@ -171,7 +172,6 @@ private JComponent createComponent(RadDiscussion disc) {
171172
titleText.append(" (OUTDATED)");
172173
}
173174
builder.withHeader(new JLabel(MarkDownEditorPaneFactory.wrapHtml(titleText.toString())), actionsPanel);
174-
var verticalPanel = getVerticalPanel(5);
175175
verticalPanel.add(builder.build());
176176
var emojiJPanel = emojiPanel.getEmojiPanel();
177177
emojiJPanel.setBorder(BorderFactory.createEmptyBorder(PADDING_TOP_BOTTOM, PADDING_LEFT, PADDING_TOP_BOTTOM, 0));

src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/patches/timeline/TimelineComponentFactory.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ public JComponent createDescSection() {
7676
if (Strings.isNullOrEmpty(description)) {
7777
description = RadicleBundle.message("noDescription");
7878
}
79-
var editorPane = new MarkDownEditorPaneFactory(description, patch.project, patch.radProject.id, file);
80-
descSection = Utils.descriptionPanel(editorPane, patch.project, "patch.proposal.change.description", f -> {
79+
descSection = Utils.descriptionPanel(description, patch.project, patch.radProject.id, file, "patch.proposal.change.description", f -> {
8180
var newDesc = f.getText();
8281
if (Strings.isNullOrEmpty(newDesc)) {
8382
return false;
@@ -153,8 +152,8 @@ private JComponent createReviewComponent(RadPatch.Review review) {
153152
var message = Strings.nullToEmpty(review.summary());
154153
var panel = new BorderLayoutPanel();
155154
panel.setOpaque(false);
156-
var editorPane = new MarkDownEditorPaneFactory(message, patch.project, patch.radProject.id, file);
157155
var myPanel = Utils.getVerticalPanel(1);
156+
var editorPane = new MarkDownEditorPaneFactory(message, patch.project, patch.radProject.id, file, myPanel);
158157
myPanel.setOpaque(false);
159158
myPanel.add(editorPane.htmlEditorPane());
160159
var verdictMsg = review.verdict() == RadPatch.Review.Verdict.ACCEPT ? RadicleBundle.message("approved") : RadicleBundle.message("requestChanges");
@@ -182,7 +181,7 @@ private JComponent createCommentComponent(RadDiscussion com) {
182181
}
183182
var panel = new BorderLayoutPanel();
184183
panel.setOpaque(false);
185-
var editorPane = new MarkDownEditorPaneFactory(message, patch.project, patch.radProject.id, file);
184+
var editorPane = new MarkDownEditorPaneFactory(message, patch.project, patch.radProject.id, file, panel);
186185
panel.addToCenter(StatusMessageComponentFactory.INSTANCE.create(editorPane.htmlEditorPane(), StatusMessageType.WARNING));
187186
emojiPanel = new PatchEmojiPanel(patchModel, com.reactions, com.id, radDetails);
188187
var verticalPanel = Utils.getVerticalPanel(5);

0 commit comments

Comments
 (0)