From de857033174818c95702a4c59999bdbfa4f35e76 Mon Sep 17 00:00:00 2001 From: andxu Date: Fri, 25 Jun 2021 18:41:40 +0800 Subject: [PATCH] Fix bug 1854234: Edit json textbox when sign in with service principal pops error --- .../ui/ServicePrincipalLoginDialog.java | 50 +++---- .../microsoft/intellij/ui/SignInWindow.java | 124 +++++++++--------- 2 files changed, 89 insertions(+), 85 deletions(-) diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/ui/ServicePrincipalLoginDialog.java b/PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/ui/ServicePrincipalLoginDialog.java index cd39aeda626..a103f50ac45 100644 --- a/PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/ui/ServicePrincipalLoginDialog.java +++ b/PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/ui/ServicePrincipalLoginDialog.java @@ -25,7 +25,6 @@ import com.intellij.ui.EditorTextField; import com.intellij.ui.EditorTextFieldProvider; import com.intellij.ui.SoftWrapsEditorCustomization; -import com.intellij.util.ui.UIUtil; import com.microsoft.azure.toolkit.intellij.common.AzureCommentLabel; import com.microsoft.azure.toolkit.intellij.common.AzureDialog; import com.microsoft.azure.toolkit.intellij.common.TextDocumentListenerAdapter; @@ -61,6 +60,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -78,9 +78,8 @@ public class ServicePrincipalLoginDialog extends AzureDialog private TextFieldWithBrowseButton certFileTextField; private AzureCommentLabel comment; private final Project project; - private boolean intermediateState = false; private AuthConfiguration auth = new AuthConfiguration(); - + private AtomicBoolean intermediateState = new AtomicBoolean(false); protected ServicePrincipalLoginDialog(@Nonnull Project project) { super(project); @@ -256,24 +255,28 @@ public static String findTextInClipboard(Predicate func) { } private void uiTextComponents2Json() { - if (intermediateState) { + if (!intermediateState.compareAndSet(false, true)) { return; } - Map map = new LinkedHashMap<>(); - AuthConfiguration data = getData(); - - if (this.certificateRadioButton.isSelected()) { - map.put("fileWithCertAndPrivateKey", data.getCertificate()); - } else { - String password = StringUtils.isNotBlank(data.getKey()) ? "" : ""; - map.put("password", password); - } - map.put("appId", data.getClient()); - map.put("tenant", data.getTenant()); - String text = JsonUtils.getGson().toJson(map); - if (!StringUtils.equals(jsonDataEditor.getText(), text)) { - this.jsonDataEditor.setText(text); - this.jsonDataEditor.setCaretPosition(0); + try { + Map map = new LinkedHashMap<>(); + AuthConfiguration data = getData(); + + if (this.certificateRadioButton.isSelected()) { + map.put("fileWithCertAndPrivateKey", data.getCertificate()); + } else { + String password = StringUtils.isNotBlank(data.getKey()) ? "" : ""; + map.put("password", password); + } + map.put("appId", data.getClient()); + map.put("tenant", data.getTenant()); + String text = JsonUtils.getGson().toJson(map); + if (!StringUtils.equals(jsonDataEditor.getText(), text)) { + this.jsonDataEditor.setText(text); + this.jsonDataEditor.setCaretPosition(0); + } + } finally { + intermediateState.set(false); } } @@ -281,8 +284,11 @@ private void json2UIComponents(String json) { try { Map map = JsonUtils.fromJson(json, HashMap.class); if (map != null) { - UIUtil.invokeLaterIfNeeded(() -> { - intermediateState = true; + ApplicationManager.getApplication().invokeAndWait(() -> { + if (!intermediateState.compareAndSet(false, true)) { + return; + } + try { if (map.containsKey("appId")) { this.clientIdTextField.setText(StringUtils.defaultString(map.get("appId"))); @@ -302,7 +308,7 @@ private void json2UIComponents(String json) { this.certFileTextField.setText(StringUtils.defaultString(map.get("fileWithCertAndPrivateKey"))); } } finally { - intermediateState = false; + intermediateState.set(false); } }); diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/ui/SignInWindow.java b/PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/ui/SignInWindow.java index 3c156edc711..8958ed26a78 100644 --- a/PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/ui/SignInWindow.java +++ b/PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/ui/SignInWindow.java @@ -12,7 +12,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.ui.AnimatedIcon; -import com.intellij.util.ui.UIUtil; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.auth.Account; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; @@ -27,10 +26,15 @@ import com.microsoft.azure.toolkit.lib.common.task.AzureTask; import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager; import com.microsoft.azuretools.adauth.IDeviceLoginUI; -import com.microsoft.azuretools.authmanage.*; +import com.microsoft.azuretools.authmanage.AuthMethod; +import com.microsoft.azuretools.authmanage.AuthMethodManager; +import com.microsoft.azuretools.authmanage.CommonSettings; import com.microsoft.azuretools.authmanage.models.AuthMethodDetails; import com.microsoft.azuretools.sdkmanage.IdentityAzureManager; -import com.microsoft.azuretools.telemetrywrapper.*; +import com.microsoft.azuretools.telemetrywrapper.ErrorType; +import com.microsoft.azuretools.telemetrywrapper.EventUtil; +import com.microsoft.azuretools.telemetrywrapper.Operation; +import com.microsoft.azuretools.telemetrywrapper.TelemetryManager; import com.microsoft.intellij.secure.IdeaSecureStore; import com.microsoft.intellij.ui.components.AzureDialogWrapper; import org.apache.commons.collections4.CollectionUtils; @@ -43,17 +47,27 @@ import reactor.util.function.Tuple2; import rx.Single; -import javax.swing.*; -import java.awt.*; +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import java.awt.Component; import java.net.URI; import java.time.Duration; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; -import static com.microsoft.azuretools.telemetry.TelemetryConstants.*; +import static com.microsoft.azuretools.telemetry.TelemetryConstants.ACCOUNT; +import static com.microsoft.azuretools.telemetry.TelemetryConstants.AZURE_ENVIRONMENT; +import static com.microsoft.azuretools.telemetry.TelemetryConstants.SIGNIN; +import static com.microsoft.azuretools.telemetry.TelemetryConstants.SIGNIN_METHOD; public class SignInWindow extends AzureDialogWrapper { private static final Logger LOGGER = Logger.getInstance(SignInWindow.class); @@ -71,7 +85,6 @@ public class SignInWindow extends AzureDialogWrapper { private JLabel labelOAuthLogin; private AuthMethodDetails authMethodDetails; - private AuthMethodDetails authMethodDetailsResult; private String accountEmail; @@ -112,10 +125,6 @@ public SignInWindow(AuthMethodDetails authMethodDetails, Project project) { checkAccountAvailability(); } - public AuthMethodDetails getAuthMethodDetails() { - return authMethodDetailsResult; - } - @Nullable public static SignInWindow go(AuthMethodDetails authMethodDetails, Project project) { SignInWindow signInWindow = new SignInWindow(authMethodDetails, project); @@ -127,12 +136,6 @@ public static SignInWindow go(AuthMethodDetails authMethodDetails, Project proje return null; } - @Override - public void doCancelAction() { - authMethodDetailsResult = authMethodDetails; - super.doCancelAction(); - } - @Override public void doHelpAction() { final JXHyperlink helpLink = new JXHyperlink(); @@ -153,43 +156,55 @@ protected JComponent createCenterPanel() { } public Single login() { + AuthConfiguration auth = new AuthConfiguration(); + if (spRadioButton.isSelected()) { + final ServicePrincipalLoginDialog dialog = new ServicePrincipalLoginDialog(project); + if (dialog.showAndGet()) { + auth = dialog.getData(); + } + } else if (deviceLoginRadioButton.isSelected()) { + auth.setType(AuthType.DEVICE_CODE); + } else if (oauthLoginRadioButton.isSelected()) { + auth.setType(AuthType.OAUTH2); + } else if (azureCliRadioButton.isSelected()) { + auth.setType(AuthType.AZURE_CLI); + } + return loginAsync(auth); + } + + private Single loginAsync(AuthConfiguration auth) { final IAzureOperationTitle title = AzureOperationBundle.title("account.sign_in"); final AzureTask task = new AzureTask<>(null, title, true, () -> { final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); indicator.setIndeterminate(true); - return this.doLogin(indicator); + return doLogin(indicator, auth); }); return AzureTaskManager.getInstance().runInModalAsObservable(task).toSingle(); } - private @Nullable AuthMethodDetails doLogin(ProgressIndicator indicator) { - authMethodDetailsResult = new AuthMethodDetails(); - if (spRadioButton.isSelected()) { // automated - final Map properties = new HashMap<>(); - properties.put(AZURE_ENVIRONMENT, CommonSettings.getEnvironment().getName()); - properties.putAll(signInSPProp); - EventUtil.logEvent(EventType.info, ACCOUNT, SIGNIN, properties, null); - - UIUtil.invokeAndWaitIfNeeded(() -> call(this::doServicePrincipalLogin, "sp")); - } else if (deviceLoginRadioButton.isSelected()) { - authMethodDetailsResult = call(this::doDeviceLogin, "dc"); - } else if (azureCliRadioButton.isSelected()) { - authMethodDetailsResult = call(() -> checkCanceled(indicator, IdentityAzureManager.getInstance().signInAzureCli()), "az"); - } else if (oauthLoginRadioButton.isSelected()) { - authMethodDetailsResult = call(() -> checkCanceled(indicator, IdentityAzureManager.getInstance().signInOAuth()), "oauth"); + public AuthMethodDetails doLogin(ProgressIndicator indicator, AuthConfiguration auth) { + AuthMethodDetails authMethodDetailsResult = new AuthMethodDetails(); + if (AuthMethodManager.getInstance().isSignedIn()) { + doSignOut(); } - return authMethodDetailsResult; - } - - private AuthMethodDetails doServicePrincipalLogin() { - authMethodDetailsResult = new AuthMethodDetails(); - final ServicePrincipalLoginDialog dialog = new ServicePrincipalLoginDialog(project); - if (dialog.showAndGet()) { - AuthConfiguration data = dialog.getData(); - authMethodDetailsResult = doServicePrincipalLoginInternal(data); - if (StringUtils.isNotBlank(data.getKey())) { - secureStore.savePassword(StringUtils.joinWith("|", "account", data.getClient()), data.getKey()); - } + switch (auth.getType()) { + case SERVICE_PRINCIPAL: + authMethodDetailsResult = call(() -> checkCanceled(indicator, IdentityAzureManager.getInstance().signInServicePrincipal(auth)), "sp"); + if (StringUtils.isNotBlank(auth.getKey())) { + secureStore.savePassword(StringUtils.joinWith("|", "account", auth.getClient()), auth.getKey()); + } + break; + case DEVICE_CODE: + authMethodDetailsResult = call(this::doDeviceLogin, "dc"); + break; + case AZURE_CLI: + authMethodDetailsResult = call(() -> checkCanceled(indicator, IdentityAzureManager.getInstance().signInAzureCli()), "az"); + break; + case OAUTH2: + authMethodDetailsResult = call(() -> checkCanceled(indicator, IdentityAzureManager.getInstance().signInOAuth()), "oauth"); + break; + default: + break; } return authMethodDetailsResult; } @@ -264,27 +279,10 @@ private void disableAzureCliLogin() { azureCliRadioButton.setText("Azure CLI (Not logged in)"); } - private AuthMethodDetails doServicePrincipalLoginInternal(AuthConfiguration auth) { - try { - IdentityAzureManager authManager = IdentityAzureManager.getInstance(); - if (AuthMethodManager.getInstance().isSignedIn()) { - doSignOut(); - } - return authManager.signInServicePrincipal(auth).block(); - } catch (Exception ex) { - ex.printStackTrace(); - ErrorWindow.show(project, ex.getMessage(), SIGN_IN_ERROR); - } - return new AuthMethodDetails(); - } - @Nullable private synchronized AuthMethodDetails doDeviceLogin() { CompletableFuture deviceCodeLoginFuture = new CompletableFuture<>(); try { - if (AuthMethodManager.getInstance().isSignedIn()) { - doSignOut(); - } final IDeviceLoginUI deviceLoginUI = CommonSettings.getUiFactory().getDeviceLoginUI(); final AzureAccount az = com.microsoft.azure.toolkit.lib.Azure.az(AzureAccount.class); final Account account = az.loginAsync(AuthType.DEVICE_CODE, true).block();