diff --git a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/AbstractSonarQubeConnectedModeTest.java b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/AbstractSonarQubeConnectedModeTest.java index 71064686b..7c0c88fa5 100644 --- a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/AbstractSonarQubeConnectedModeTest.java +++ b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/AbstractSonarQubeConnectedModeTest.java @@ -25,6 +25,7 @@ import com.sonar.orchestrator.locator.URLLocation; import java.io.File; import java.io.IOException; +import java.time.Instant; import java.util.Map; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; @@ -50,17 +51,26 @@ import org.sonarqube.ws.client.WsClientFactories; import org.sonarqube.ws.client.projects.CreateRequest; import org.sonarqube.ws.client.settings.SetRequest; +import org.sonarqube.ws.client.usertokens.GenerateRequest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; /** Every test class targeting SonarQube derives from here */ public abstract class AbstractSonarQubeConnectedModeTest extends AbstractSonarLintTest { + private static final String TIMESTAMP = Long.toString(Instant.now().toEpochMilli()); + private static final String TOKEN_NAME = "SLE-IT-" + TIMESTAMP; + protected static WsClient adminWsClient; + protected static String token; /** Should be used on @BeforeClass implementation for orchestrators to share the logic */ public static void prepare(OrchestratorRule orchestrator) { adminWsClient = newAdminWsClient(orchestrator.getServer()); + token = adminWsClient.userTokens() + .generate(new GenerateRequest().setName(TOKEN_NAME)) + .getToken(); + adminWsClient.settings().set(new SetRequest().setKey("sonar.forceAuthentication").setValue("true")); try { @@ -140,13 +150,10 @@ protected static void createConnectionAndBindProject(OrchestratorRule orchestrat serverUrlPage.setUrl(orchestrator.getServer().getUrl()); wizard.next(); - var authenticationModePage = new ServerConnectionWizard.AuthenticationModePage(wizard); - authenticationModePage.selectUsernamePasswordMode(); - wizard.next(); - + assertThat(wizard.isNextEnabled()).isFalse(); var authenticationPage = new ServerConnectionWizard.AuthenticationPage(wizard); - authenticationPage.setUsername(username); - authenticationPage.setPassword(password); + authenticationPage.setToken(token); + assertThat(wizard.isNextEnabled()).isTrue(); wizard.next(); // as login can take time, wait for the next page to appear diff --git a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/OpenInIdeTest.java b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/OpenInIdeTest.java index 42af3a56a..333534e46 100644 --- a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/OpenInIdeTest.java +++ b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/OpenInIdeTest.java @@ -150,13 +150,8 @@ public void test_open_in_ide_assist_manual_binding() throws IOException, Interru assertThat(serverUrlPage.getUrl()).isEqualTo(orchestrator.getServer().getUrl()); wizard.next(); - var authenticationModePage = new ServerConnectionWizard.AuthenticationModePage(wizard); - authenticationModePage.selectUsernamePasswordMode(); - wizard.next(); - var authenticationPage = new ServerConnectionWizard.AuthenticationPage(wizard); - authenticationPage.setUsername(Server.ADMIN_LOGIN); - authenticationPage.setPassword(Server.ADMIN_PASSWORD); + authenticationPage.setToken(token); wizard.next(); // as login can take time, wait for the next page to appear diff --git a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/SonarQubeConnectedModeTest.java b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/SonarQubeConnectedModeTest.java index 00e852d20..d2f34dc22 100644 --- a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/SonarQubeConnectedModeTest.java +++ b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/SonarQubeConnectedModeTest.java @@ -150,24 +150,15 @@ public void configureServerFromNewWizard() { assertThat(wizard.isNextEnabled()).isTrue(); wizard.next(); - var authenticationModePage = new ServerConnectionWizard.AuthenticationModePage(wizard); - authenticationModePage.selectUsernamePasswordMode(); - wizard.next(); - var authenticationPage = new ServerConnectionWizard.AuthenticationPage(wizard); assertThat(wizard.isNextEnabled()).isFalse(); - authenticationPage.setUsername(Server.ADMIN_LOGIN); - assertThat(wizard.isNextEnabled()).isFalse(); - authenticationPage.setPassword("wrong"); + authenticationPage.setToken("Goo"); assertThat(wizard.isNextEnabled()).isTrue(); - // until we change the ITs with the removal of the username / password authentication we check here once - assertThat(authenticationPage.getDeprecationMessage()).isEqualTo(authenticationPage.DEPRECATION_MESSAGE); - wizard.next(); new WaitUntil(new DialogMessageIsExpected(wizard, "Authentication failed")); - authenticationPage.setPassword(Server.ADMIN_PASSWORD); + authenticationPage.setToken(token); wizard.next(); // as login can take time, wait for the next page to appear diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/wizards/ServerConnectionWizard.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/wizards/ServerConnectionWizard.java index cf49a0f7c..3977f699f 100644 --- a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/wizards/ServerConnectionWizard.java +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/wizards/ServerConnectionWizard.java @@ -75,21 +75,7 @@ public String getUrl() { } } - public static class AuthenticationModePage extends WizardPage { - - public AuthenticationModePage(ReferencedComposite referencedComposite) { - super(referencedComposite); - } - - public void selectUsernamePasswordMode() { - new RadioButton(this, 1).click(); - } - } - public static class AuthenticationPage extends WizardPage { - public final String DEPRECATION_MESSAGE = "Authentication via username and password is deprecated and will " - + "be removed in the future. Please use a token instead."; - public AuthenticationPage(ReferencedComposite referencedComposite) { super(referencedComposite); } @@ -98,14 +84,6 @@ public void setToken(String token) { new DefaultText(this).setText(token); } - public void setUsername(String adminLogin) { - new DefaultText(this).setText(adminLogin); - } - - public void setPassword(String password) { - new DefaultText(this, 1).setText(password); - } - public String getDeprecationMessage() { return new DefaultLabel(this, 2).getText(); } diff --git a/org.sonarlint.eclipse.core/src/org/sonarlint/eclipse/core/internal/engine/connected/ConnectionManager.java b/org.sonarlint.eclipse.core/src/org/sonarlint/eclipse/core/internal/engine/connected/ConnectionManager.java index dda6f8174..57bd44d96 100644 --- a/org.sonarlint.eclipse.core/src/org/sonarlint/eclipse/core/internal/engine/connected/ConnectionManager.java +++ b/org.sonarlint.eclipse.core/src/org/sonarlint/eclipse/core/internal/engine/connected/ConnectionManager.java @@ -433,6 +433,10 @@ public static String getUsername(ConnectionFacade facade) throws StorageExceptio return getFromSecure(facade, USERNAME_ATTRIBUTE); } + /** + * @deprecated as only token authentication is supported from now on and this is saved in the username attribute! + */ + @Deprecated(since = "10.10", forRemoval = true) @Nullable public static String getPassword(ConnectionFacade facade) throws StorageException { return getFromSecure(facade, PASSWORD_ATTRIBUTE); diff --git a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/AbstractConnectionWizard.java b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/AbstractConnectionWizard.java index 890d68085..9d375566b 100644 --- a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/AbstractConnectionWizard.java +++ b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/AbstractConnectionWizard.java @@ -44,7 +44,6 @@ import org.sonarlint.eclipse.core.internal.utils.JobUtils; import org.sonarlint.eclipse.ui.internal.Messages; import org.sonarlint.eclipse.ui.internal.binding.BindingsView; -import org.sonarlint.eclipse.ui.internal.binding.wizard.connection.ServerConnectionModel.AuthMethod; import org.sonarlint.eclipse.ui.internal.binding.wizard.connection.ServerConnectionModel.ConnectionType; import org.sonarlint.eclipse.ui.internal.util.wizard.SonarLintWizardDialog; import org.sonarsource.sonarlint.core.rpc.protocol.backend.connection.common.TransientSonarCloudConnectionDto; @@ -193,7 +192,7 @@ protected Either modelToCredentialDto() { - return model.getAuthMethod() == AuthMethod.TOKEN + return model.getPassword() == null ? Either.forLeft(new TokenDto(model.getUsername())) : Either.forRight(new UsernamePasswordDto(model.getUsername(), model.getPassword())); } diff --git a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/AuthMethodWizardPage.java b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/AuthMethodWizardPage.java deleted file mode 100644 index e5ac9c469..000000000 --- a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/AuthMethodWizardPage.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SonarLint for Eclipse - * Copyright (C) 2015-2024 SonarSource SA - * sonarlint@sonarsource.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonarlint.eclipse.ui.internal.binding.wizard.connection; - -import org.eclipse.core.databinding.DataBindingContext; -import org.eclipse.core.databinding.observable.value.SelectObservableValue; -import org.eclipse.jface.databinding.wizard.WizardPageSupport; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.sonarlint.eclipse.ui.internal.SonarLintImages; -import org.sonarlint.eclipse.ui.internal.util.wizard.PojoPropertiesCompat; -import org.sonarlint.eclipse.ui.internal.util.wizard.WidgetPropertiesCompat; - -/** - * Choose between token and login/password authentication mode - */ -public class AuthMethodWizardPage extends WizardPage { - - private final ServerConnectionModel model; - - public AuthMethodWizardPage(ServerConnectionModel model) { - super("auth_method_page", "Choose authentication method", SonarLintImages.IMG_WIZBAN_NEW_CONNECTION); - this.model = model; - } - - @Override - public void createControl(Composite parent) { - - var radioButtonGroupContainer = new Composite(parent, SWT.NONE); - radioButtonGroupContainer.setLayout(new GridLayout()); - - var tokenButton = new Button(radioButtonGroupContainer, SWT.RADIO); - tokenButton.setText("Token"); - - var loginPasswordButton = new Button(radioButtonGroupContainer, SWT.RADIO); - loginPasswordButton.setText("Username + Password"); - - var sonarCloudSelection = WidgetPropertiesCompat.buttonSelection().observe(loginPasswordButton); - var onPremSelection = WidgetPropertiesCompat.buttonSelection().observe(tokenButton); - var selectObservable = new SelectObservableValue<>(ServerConnectionModel.AuthMethod.class); - selectObservable.addOption(ServerConnectionModel.AuthMethod.PASSWORD, sonarCloudSelection); - selectObservable.addOption(ServerConnectionModel.AuthMethod.TOKEN, onPremSelection); - var dataBindingContext = new DataBindingContext(); - dataBindingContext.bindValue(selectObservable, PojoPropertiesCompat.value(ServerConnectionModel.PROPERTY_AUTH_METHOD).observe(model)); - - WizardPageSupport.create(this, dataBindingContext); - - setControl(radioButtonGroupContainer); - } - -} diff --git a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/ServerConnectionModel.java b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/ServerConnectionModel.java index c1124b961..02856766d 100644 --- a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/ServerConnectionModel.java +++ b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/ServerConnectionModel.java @@ -55,19 +55,21 @@ public enum ConnectionType { SONARCLOUD, ONPREMISE } - public enum AuthMethod { - TOKEN, PASSWORD - } - private final boolean edit; private final boolean fromConnectionSuggestion; private ConnectionType connectionType = ConnectionType.SONARCLOUD; - private AuthMethod authMethod = AuthMethod.TOKEN; private String connectionId; private String serverUrl = SonarLintUtils.getSonarCloudUrl(); private String organization; private String username; + + /** + * @deprecated as only token authentication is supported from now on and this is saved in the username field! + */ + @Deprecated(since = "10.10", forRemoval = true) + @Nullable private String password; + private boolean notificationsSupported; private boolean notificationsDisabled; @@ -97,7 +99,6 @@ public ServerConnectionModel(ConnectionFacade connection) { SonarLintLogger.get().error(ERROR_READING_SECURE_STORAGE, e); MessageDialog.openError(Display.getCurrent().getActiveShell(), ERROR_READING_SECURE_STORAGE, "Unable to read password from secure storage: " + e.getMessage()); } - this.authMethod = StringUtils.isBlank(password) ? AuthMethod.TOKEN : AuthMethod.PASSWORD; } this.notificationsDisabled = connection.areNotificationsDisabled(); } @@ -122,22 +123,9 @@ public void setConnectionType(ConnectionType type) { setServerUrl(null); } else { setServerUrl(SonarLintUtils.getSonarCloudUrl()); - setAuthMethod(AuthMethod.TOKEN); } } - public AuthMethod getAuthMethod() { - return authMethod; - } - - public void setAuthMethod(AuthMethod authMethod) { - var old = this.authMethod; - this.authMethod = authMethod; - firePropertyChange(PROPERTY_AUTH_METHOD, old, this.authMethod); - setUsername(null); - setPassword(null); - } - public String getConnectionId() { return connectionId; } @@ -255,7 +243,7 @@ public boolean getNotificationsDisabled() { } public Either getTransientRpcCrendentials() { - if (authMethod == AuthMethod.TOKEN) { + if (password == null) { return Either.forLeft(new TokenDto(username)); } else { return Either.forRight(new UsernamePasswordDto(username, password)); diff --git a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/ServerConnectionWizard.java b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/ServerConnectionWizard.java index fd57b7429..194772e33 100644 --- a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/ServerConnectionWizard.java +++ b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/ServerConnectionWizard.java @@ -37,7 +37,6 @@ import org.sonarlint.eclipse.core.internal.engine.connected.ConnectionFacade; import org.sonarlint.eclipse.core.internal.utils.JobUtils; import org.sonarlint.eclipse.core.resource.ISonarLintProject; -import org.sonarlint.eclipse.ui.internal.binding.wizard.connection.ServerConnectionModel.AuthMethod; import org.sonarlint.eclipse.ui.internal.binding.wizard.connection.ServerConnectionModel.ConnectionType; import org.sonarlint.eclipse.ui.internal.binding.wizard.project.ProjectBindingWizard; import org.sonarlint.eclipse.ui.internal.util.wizard.SonarLintWizardDialog; @@ -48,8 +47,6 @@ public class ServerConnectionWizard extends AbstractConnectionWizard { private final ConnectionTypeWizardPage connectionTypeWizardPage; private final UrlWizardPage urlPage; - private final AuthMethodWizardPage authMethodPage; - private final UsernamePasswordWizardPage credentialsPage; private final OrganizationWizardPage orgPage; private final ConnectionIdWizardPage connectionIdPage; private final NotificationsWizardPage notifPage; @@ -63,8 +60,6 @@ private ServerConnectionWizard(String title, ServerConnectionModel model, Connec this.editedServer = editedServer; connectionTypeWizardPage = new ConnectionTypeWizardPage(model); urlPage = new UrlWizardPage(model); - authMethodPage = new AuthMethodWizardPage(model); - credentialsPage = new UsernamePasswordWizardPage(model); orgPage = new OrganizationWizardPage(model); connectionIdPage = new ConnectionIdWizardPage(model); notifPage = new NotificationsWizardPage(model); @@ -111,7 +106,12 @@ public static WizardDialog createDialog(Shell parent, ConnectionFacade connectio protected void actualHandlePageChanging(PageChangingEvent event) { var currentPage = (WizardPage) event.getCurrentPage(); var advance = getNextPage(currentPage) == event.getTargetPage(); - if (advance && !redirectedAfterNotificationCheck && (currentPage == credentialsPage || currentPage == tokenPage)) { + if (advance && !redirectedAfterNotificationCheck && currentPage == tokenPage) { + // When having a username/password based connection and editing it, there is only the option to switch to a token + // available. In this case, when a token was generated, we will remove the password and set the authentication + // method to "TOKEN" that is then used on the "AbstractConnectionWizard#testConnection(...)" already! + model.setPassword(null); + if (!testConnection(null)) { event.doit = false; return; @@ -155,8 +155,6 @@ protected void actualAddPages() { addPage(connectionIdPage); } addPage(urlPage); - addPage(authMethodPage); - addPage(credentialsPage); addPage(tokenPage); addPage(orgPage); addPage(notifPage); @@ -169,10 +167,7 @@ protected IWizardPage getActualNextPage(IWizardPage page) { return firstPageAfterConnectionType(); } if (page == urlPage) { - return authMethodPage; - } - if (page == authMethodPage) { - return model.getAuthMethod() == AuthMethod.PASSWORD ? credentialsPage : tokenPage; + return tokenPage; } // This comes from Connection suggestion, we don't need anything from here! @@ -180,7 +175,7 @@ protected IWizardPage getActualNextPage(IWizardPage page) { return null; } - if (page == credentialsPage || page == tokenPage) { + if (page == tokenPage) { if (model.getConnectionType() == ConnectionType.SONARCLOUD) { return orgPage; } else { diff --git a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/TokenWizardPage.java b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/TokenWizardPage.java index 0b93e2082..2c11df21f 100644 --- a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/TokenWizardPage.java +++ b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/TokenWizardPage.java @@ -114,7 +114,7 @@ private void createOpenSecurityPageButton(Composite container) { private void openTokenCreationPage() { try { - var job = new GenerateTokenJob(model.getServerUrl(), model.getConnectionType() == ConnectionType.SONARCLOUD); + var job = new GenerateTokenJob(model.getServerUrl()); getContainer().run(true, true, job); var response = job.getResponse(); var token = response.getToken(); @@ -138,19 +138,17 @@ private void handleReceivedToken(String token) { static final class GenerateTokenJob implements IRunnableWithProgress { private final String serverUrl; - private final boolean isSonarCloud; private HelpGenerateUserTokenResponse response; - public GenerateTokenJob(String serverUrl, boolean isSonarCloud) { + public GenerateTokenJob(String serverUrl) { this.serverUrl = serverUrl; - this.isSonarCloud = isSonarCloud; } @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Token generation", IProgressMonitor.UNKNOWN); try { - var params = new HelpGenerateUserTokenParams(serverUrl, isSonarCloud); + var params = new HelpGenerateUserTokenParams(serverUrl); var future = SonarLintBackendService.get().getBackend().getConnectionService().helpGenerateUserToken(params); this.response = JobUtils.waitForFutureInIRunnableWithProgress(monitor, future); } finally { diff --git a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/UsernamePasswordWizardPage.java b/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/UsernamePasswordWizardPage.java deleted file mode 100644 index 4bcd2f800..000000000 --- a/org.sonarlint.eclipse.ui/src/org/sonarlint/eclipse/ui/internal/binding/wizard/connection/UsernamePasswordWizardPage.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * SonarLint for Eclipse - * Copyright (C) 2015-2024 SonarSource SA - * sonarlint@sonarsource.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonarlint.eclipse.ui.internal.binding.wizard.connection; - -import org.eclipse.core.databinding.Binding; -import org.eclipse.core.databinding.DataBindingContext; -import org.eclipse.core.databinding.UpdateValueStrategy; -import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport; -import org.eclipse.jface.databinding.wizard.WizardPageSupport; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.sonarlint.eclipse.ui.internal.Messages; -import org.sonarlint.eclipse.ui.internal.SonarLintImages; -import org.sonarlint.eclipse.ui.internal.util.wizard.BeanPropertiesCompat; -import org.sonarlint.eclipse.ui.internal.util.wizard.WidgetPropertiesCompat; - -/** - * @deprecated SonarCloud only offers authentication via token, SonarQube should follow soon - */ -@Deprecated(since = "9.1", forRemoval = true) -public class UsernamePasswordWizardPage extends AbstractServerConnectionWizardPage { - public static final String DEPRECATION_MESSAGE = "Authentication via username and password is deprecated and will " - + "be removed in the future. Please use a token instead."; - - private Text connectionUsernameText; - private Text connectionPasswordText; - - private Binding usernameTextBinding; - - private Binding passwordTextBinding; - - public UsernamePasswordWizardPage(ServerConnectionModel model) { - super("server_credentials_page", "SonarQube Server User Credentials", model, 2); - } - - @SuppressWarnings("unchecked") - @Override - protected void doCreateControl(Composite container) { - createDeprecationLabel(container); - createUsernameOrTokenField(container); - createPasswordField(container); - - var dataBindingContext = new DataBindingContext(); - usernameTextBinding = dataBindingContext.bindValue( - WidgetPropertiesCompat.text(SWT.Modify).observe(connectionUsernameText), - BeanPropertiesCompat.value(ServerConnectionModel.class, ServerConnectionModel.PROPERTY_USERNAME) - .observe(model), - new UpdateValueStrategy().setBeforeSetValidator( - new MandatoryStringValidator("You must provide a login")), - null); - ControlDecorationSupport.create(usernameTextBinding, SWT.LEFT | SWT.TOP); - passwordTextBinding = dataBindingContext.bindValue( - WidgetPropertiesCompat.text(SWT.Modify).observe(connectionPasswordText), - BeanPropertiesCompat.value(ServerConnectionModel.class, ServerConnectionModel.PROPERTY_PASSWORD) - .observe(model), - new UpdateValueStrategy().setBeforeSetValidator( - new MandatoryStringValidator("You must provide a password")), - null); - ControlDecorationSupport.create(passwordTextBinding, SWT.LEFT | SWT.TOP); - - WizardPageSupport.create(this, dataBindingContext); - } - - private static void createDeprecationLabel(final Composite container) { - var deprecationContainer = new Composite(container, SWT.NONE); - deprecationContainer.setLayout(new GridLayout(3, false)); - deprecationContainer.setLayoutData(new GridData(SWT.LEFT, SWT.DOWN, true, false, Integer.MAX_VALUE, 1)); - - // icon on the left - new Label(deprecationContainer, SWT.NULL).setImage(SonarLintImages.IMG_SEVERITY_BLOCKER); - - var labelDeprecation = new Label(deprecationContainer, SWT.NULL); - labelDeprecation.setText(DEPRECATION_MESSAGE); - labelDeprecation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - labelDeprecation.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT)); - - // icon on the right - new Label(deprecationContainer, SWT.NULL).setImage(SonarLintImages.IMG_SEVERITY_BLOCKER); - } - - private void createPasswordField(final Composite container) { - var labelPassword = new Label(container, SWT.NULL); - labelPassword.setText(Messages.ServerLocationWizardPage_label_password); - connectionPasswordText = new Text(container, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD); - var gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalIndent = 10; - connectionPasswordText.setLayoutData(gd); - } - - private void createUsernameOrTokenField(final Composite container) { - var labelUsername = new Label(container, SWT.NULL); - labelUsername.setText("Username:"); - connectionUsernameText = new Text(container, SWT.BORDER | SWT.SINGLE); - var gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalIndent = 10; - connectionUsernameText.setLayoutData(gd); - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (visible) { - usernameTextBinding.validateTargetToModel(); - passwordTextBinding.validateTargetToModel(); - } - } - -}