From a403ed93afa3982c3651799a00166a44a5b7872a Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 5 Feb 2018 11:58:56 +0100 Subject: [PATCH] SONAR-10290 Add ability to provide help message for identity providers --- .../user/ws/IdentityProvidersAction.java | 27 ++++++------ .../user/ws/identity_providers-example.json | 3 +- .../user/ws/IdentityProvidersActionTest.java | 42 +++++++++---------- .../api/server/authentication/Display.java | 20 +++++++++ .../server/authentication/DisplayTest.java | 28 +++++++++---- sonar-ws/src/main/protobuf/ws-users.proto | 1 + 6 files changed, 77 insertions(+), 44 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/IdentityProvidersAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/IdentityProvidersAction.java index 5cd92f7e038..e3762d5e88a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/IdentityProvidersAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/IdentityProvidersAction.java @@ -19,18 +19,18 @@ */ package org.sonar.server.user.ws; -import com.google.common.base.Function; -import com.google.common.collect.Lists; -import javax.annotation.Nonnull; +import java.util.function.Function; import org.sonar.api.server.authentication.Display; import org.sonar.api.server.authentication.IdentityProvider; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; +import org.sonar.core.util.stream.MoreCollectors; import org.sonar.server.authentication.IdentityProviderRepository; import org.sonarqube.ws.Users; import org.sonarqube.ws.Users.IdentityProvidersWsResponse; +import static org.sonar.core.util.Protobuf.setNullable; import static org.sonar.server.ws.WsUtils.writeProtobuf; public class IdentityProvidersAction implements UsersWsAction { @@ -57,24 +57,23 @@ public class IdentityProvidersAction implements UsersWsAction { private IdentityProvidersWsResponse buildResponse() { IdentityProvidersWsResponse.Builder response = IdentityProvidersWsResponse.newBuilder(); - response.addAllIdentityProviders(Lists.transform(identityProviderRepository.getAllEnabledAndSorted(), IdentityProviderToWsResponse.INSTANCE)); + response.addAllIdentityProviders(identityProviderRepository.getAllEnabledAndSorted() + .stream() + .map(toWsIdentityProvider()) + .collect(MoreCollectors.toList())); return response.build(); } - private enum IdentityProviderToWsResponse implements Function { - INSTANCE; - - @Override - public Users.IdentityProvider apply(@Nonnull IdentityProvider input) { + private static Function toWsIdentityProvider() { + return input -> { + Display display = input.getDisplay(); Users.IdentityProvider.Builder builder = Users.IdentityProvider.newBuilder() .setKey(input.getKey()) - .setName(input.getName()); - Display display = input.getDisplay(); - builder + .setName(input.getName()) .setIconPath(display.getIconPath()) .setBackgroundColor(display.getBackgroundColor()); - + setNullable(display.getHelpMessage(), builder::setHelpMessage); return builder.build(); - } + }; } } diff --git a/server/sonar-server/src/main/resources/org/sonar/server/user/ws/identity_providers-example.json b/server/sonar-server/src/main/resources/org/sonar/server/user/ws/identity_providers-example.json index 06cb4310c0a..e39ba1da119 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/user/ws/identity_providers-example.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/user/ws/identity_providers-example.json @@ -4,7 +4,8 @@ "key": "bitbucket", "name": "Bitbucket", "iconPath": "/static/authbitbucket/bitbucket.svg", - "backgroundColor": "#205081" + "backgroundColor": "#205081", + "helpMessage": "You need an existing account on bitbucket.com" }, { "key": "github", diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/IdentityProvidersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/IdentityProvidersActionTest.java index df6854267cf..0a6daada01a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/ws/IdentityProvidersActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/IdentityProvidersActionTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.user.ws; -import java.io.IOException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -34,30 +33,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.test.JsonAssert.assertJson; public class IdentityProvidersActionTest { - static IdentityProvider GITHUB = new TestIdentityProvider() - .setKey("github") - .setName("Github") - .setDisplay(Display.builder() - .setIconPath("/static/authgithub/github.svg") - .setBackgroundColor("#444444") - .build()) - .setEnabled(true); - - static IdentityProvider BITBUCKET = new TestIdentityProvider() - .setKey("bitbucket") - .setName("Bitbucket") - .setDisplay(Display.builder() - .setIconPath("/static/authbitbucket/bitbucket.svg") - .setBackgroundColor("#205081") - .build()) - .setEnabled(true); @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule public IdentityProviderRepositoryRule identityProviderRepository = new IdentityProviderRepositoryRule() .addIdentityProvider(GITHUB) - .addIdentityProvider(BITBUCKET); + .addIdentityProvider(BIT_BUCKET); WsActionTester ws = new WsActionTester(new IdentityProvidersAction(identityProviderRepository)); @@ -69,13 +51,31 @@ public class IdentityProvidersActionTest { } @Test - public void ws_properties() { + public void test_definition() { WebService.Action webService = ws.getDef(); assertThat(webService.key()).isEqualTo("identity_providers"); assertThat(webService.responseExampleAsString()).isNotEmpty(); assertThat(webService.since()).isEqualTo("5.5"); assertThat(webService.isInternal()).isTrue(); - } + + private static IdentityProvider GITHUB = new TestIdentityProvider() + .setKey("github") + .setName("Github") + .setDisplay(Display.builder() + .setIconPath("/static/authgithub/github.svg") + .setBackgroundColor("#444444") + .build()) + .setEnabled(true); + + private static IdentityProvider BIT_BUCKET = new TestIdentityProvider() + .setKey("bitbucket") + .setName("Bitbucket") + .setDisplay(Display.builder() + .setIconPath("/static/authbitbucket/bitbucket.svg") + .setBackgroundColor("#205081") + .setHelpMessage("You need an existing account on bitbucket.com") + .build()) + .setEnabled(true); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/Display.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/Display.java index 767e726526e..c25584db92b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/Display.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/Display.java @@ -19,6 +19,7 @@ */ package org.sonar.api.server.authentication; +import javax.annotation.CheckForNull; import javax.annotation.concurrent.Immutable; import static com.google.common.base.Preconditions.checkArgument; @@ -34,10 +35,12 @@ public final class Display { private final String iconPath; private final String backgroundColor; + private final String helpMessage; private Display(Builder builder) { this.iconPath = builder.iconPath; this.backgroundColor = builder.backgroundColor; + this.helpMessage = builder.helpMessage; } /** @@ -64,6 +67,14 @@ public final class Display { return backgroundColor; } + /** + * Optional help message to be displayed near the provider button. + */ + @CheckForNull + public String getHelpMessage() { + return helpMessage; + } + public static Builder builder() { return new Builder(); } @@ -72,6 +83,7 @@ public final class Display { private String iconPath; private String backgroundColor = "#236a97"; + private String helpMessage; private Builder() { } @@ -92,6 +104,14 @@ public final class Display { return this; } + /** + * @see Display#getHelpMessage() + */ + public Builder setHelpMessage(@CheckForNull String helpMessage) { + this.helpMessage = helpMessage; + return this; + } + public Display build() { checkArgument(isNotBlank(iconPath), "Icon path must not be blank"); validateBackgroundColor(); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/authentication/DisplayTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/authentication/DisplayTest.java index 0e1b832e5c4..963e571b45d 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/authentication/DisplayTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/authentication/DisplayTest.java @@ -31,7 +31,7 @@ public class DisplayTest { public ExpectedException thrown = ExpectedException.none(); @Test - public void create_display() throws Exception { + public void create_display() { Display display = Display.builder() .setIconPath("/static/authgithub/github.svg") .setBackgroundColor("#123456") @@ -39,10 +39,11 @@ public class DisplayTest { assertThat(display.getIconPath()).isEqualTo("/static/authgithub/github.svg"); assertThat(display.getBackgroundColor()).isEqualTo("#123456"); + assertThat(display.getHelpMessage()).isNull(); } @Test - public void create_display_with_default_background_color() throws Exception { + public void create_display_with_default_background_color() { Display display = Display.builder() .setIconPath("/static/authgithub/github.svg") .build(); @@ -50,8 +51,19 @@ public class DisplayTest { assertThat(display.getBackgroundColor()).isEqualTo("#236a97"); } + + @Test + public void create_display_with_help_message() { + Display display = Display.builder() + .setIconPath("/static/authgithub/github.svg") + .setHelpMessage("Help message") + .build(); + + assertThat(display.getHelpMessage()).isEqualTo("Help message"); + } + @Test - public void fail_when_icon_path_is_null() throws Exception { + public void fail_when_icon_path_is_null() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Icon path must not be blank"); @@ -62,7 +74,7 @@ public class DisplayTest { } @Test - public void fail_when_icon_path_is_blank() throws Exception { + public void fail_when_icon_path_is_blank() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Icon path must not be blank"); @@ -73,7 +85,7 @@ public class DisplayTest { } @Test - public void fail_when_background_color_is_null() throws Exception { + public void fail_when_background_color_is_null() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Background color must not be blank"); @@ -84,7 +96,7 @@ public class DisplayTest { } @Test - public void fail_when_background_color_is_blank() throws Exception { + public void fail_when_background_color_is_blank() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Background color must not be blank"); @@ -95,7 +107,7 @@ public class DisplayTest { } @Test - public void fail_when_background_color_has_wrong_size() throws Exception { + public void fail_when_background_color_has_wrong_size() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Background color must begin with a sharp followed by 6 characters"); @@ -106,7 +118,7 @@ public class DisplayTest { } @Test - public void fail_when_background_color_doesnt_begin_with_sharp() throws Exception { + public void fail_when_background_color_doesnt_begin_with_sharp() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Background color must begin with a sharp followed by 6 characters"); diff --git a/sonar-ws/src/main/protobuf/ws-users.proto b/sonar-ws/src/main/protobuf/ws-users.proto index d5bf59304d2..bcb9e798111 100644 --- a/sonar-ws/src/main/protobuf/ws-users.proto +++ b/sonar-ws/src/main/protobuf/ws-users.proto @@ -64,6 +64,7 @@ message IdentityProvider { optional string name = 2; optional string iconPath = 3; optional string backgroundColor = 4; + optional string helpMessage = 5; } message CreateWsResponse { -- 2.39.5