From 7b2fd68f3bdece8186a134f6bbfc88fdd0d2c507 Mon Sep 17 00:00:00 2001 From: Patrick Hobusch Date: Thu, 21 Mar 2024 16:53:20 +0800 Subject: [PATCH] WIP --- pom.xml | 8 +- .../model/util/AuthenticationIdpBeanUtil.java | 169 ++++++++++++++++++ .../model/util/AuthenticationSsoBeanUtil.java | 46 +++++ .../jira/rest/AuthenticationResourceImpl.java | 23 +++ .../service/AuthenticationServiceImpl.java | 105 +++++++++++ .../util/AuthenticationIdpBeanUtilTest.java | 61 +++++++ .../service/AuthenticationServiceTest.java | 124 +++++++++++++ 7 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtil.java create mode 100644 src/main/java/de/aservo/confapi/jira/model/util/AuthenticationSsoBeanUtil.java create mode 100644 src/main/java/de/aservo/confapi/jira/rest/AuthenticationResourceImpl.java create mode 100644 src/main/java/de/aservo/confapi/jira/service/AuthenticationServiceImpl.java create mode 100644 src/test/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtilTest.java create mode 100644 src/test/java/de/aservo/confapi/jira/service/AuthenticationServiceTest.java diff --git a/pom.xml b/pom.xml index 43064c3..50a2186 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ 4.0.0 confapi-jira-plugin - 0.0.7-SNAPSHOT + 0.1.0-SNAPSHOT atlassian-plugin ConfAPI for Jira @@ -221,6 +221,12 @@ provided + + com.atlassian.plugins.authentication + atlassian-authentication-plugin + provided + + com.atlassian.plugin atlassian-spring-scanner-annotation diff --git a/src/main/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtil.java b/src/main/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtil.java new file mode 100644 index 0000000..ebcd3e6 --- /dev/null +++ b/src/main/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtil.java @@ -0,0 +1,169 @@ +package de.aservo.confapi.jira.model.util; + +import com.atlassian.plugins.authentication.api.config.IdpConfig; +import com.atlassian.plugins.authentication.api.config.SsoType; +import com.atlassian.plugins.authentication.api.config.oidc.OidcConfig; +import com.atlassian.plugins.authentication.api.config.saml.SamlConfig; +import de.aservo.confapi.commons.exception.BadRequestException; +import de.aservo.confapi.commons.exception.InternalServerErrorException; +import de.aservo.confapi.commons.model.AbstractAuthenticationIdpBean; +import de.aservo.confapi.commons.model.AuthenticationIdpOidcBean; +import de.aservo.confapi.commons.model.AuthenticationIdpSamlBean; + +public class AuthenticationIdpBeanUtil { + + public static IdpConfig toIdpConfig( + final AbstractAuthenticationIdpBean authenticationIdpBean) { + + return toIdpConfig(authenticationIdpBean, null); + } + + public static IdpConfig toIdpConfig( + final AbstractAuthenticationIdpBean authenticationIdpBean, + final IdpConfig existingIdpConfig) { + + if (authenticationIdpBean instanceof AuthenticationIdpOidcBean) { + return toOidcConfig((AuthenticationIdpOidcBean) authenticationIdpBean, existingIdpConfig); + } + + throw new BadRequestException("IDP types other than OIDC are not (yet) supported"); + } + + private static OidcConfig toOidcConfig( + final AuthenticationIdpOidcBean authenticationIdpOidcBean, + final IdpConfig existingIdpConfig) { + + final OidcConfig.Builder oidcConfigBuilder; + + if (existingIdpConfig == null) { + oidcConfigBuilder = OidcConfig.builder(); + } else { + verifyIdAndType(authenticationIdpOidcBean, existingIdpConfig, OidcConfig.class); + oidcConfigBuilder = OidcConfig.builder((OidcConfig) existingIdpConfig); + } + + if (authenticationIdpOidcBean.getId() != null) { + oidcConfigBuilder.setId(authenticationIdpOidcBean.getId()); + } + if (authenticationIdpOidcBean.getName() != null) { + oidcConfigBuilder.setName(authenticationIdpOidcBean.getName()); + } + if (authenticationIdpOidcBean.getEnabled() != null) { + oidcConfigBuilder.setEnabled(authenticationIdpOidcBean.getEnabled()); + } + if (authenticationIdpOidcBean.getUrl() != null) { + oidcConfigBuilder.setIssuer(authenticationIdpOidcBean.getUrl()); + } + if (authenticationIdpOidcBean.getEnableRememberMe() != null) { + oidcConfigBuilder.setEnableRememberMe(authenticationIdpOidcBean.getEnableRememberMe()); + } + if (authenticationIdpOidcBean.getButtonText() != null) { + oidcConfigBuilder.setButtonText(authenticationIdpOidcBean.getButtonText()); + } + if (authenticationIdpOidcBean.getClientId() != null) { + oidcConfigBuilder.setClientId(authenticationIdpOidcBean.getClientId()); + } + if (authenticationIdpOidcBean.getClientSecret() != null) { + oidcConfigBuilder.setClientSecret(authenticationIdpOidcBean.getClientSecret()); + } + if (authenticationIdpOidcBean.getUsernameClaim() != null) { + oidcConfigBuilder.setUsernameClaim(authenticationIdpOidcBean.getUsernameClaim()); + } + if (authenticationIdpOidcBean.getAdditionalScopes() != null) { + oidcConfigBuilder.setAdditionalScopes(authenticationIdpOidcBean.getAdditionalScopes()); + } + if (authenticationIdpOidcBean.getDiscoveryEnabled() != null) { + oidcConfigBuilder.setDiscoveryEnabled(authenticationIdpOidcBean.getDiscoveryEnabled()); + } + if (authenticationIdpOidcBean.getAuthorizationEndpoint() != null) { + oidcConfigBuilder.setAuthorizationEndpoint(authenticationIdpOidcBean.getAuthorizationEndpoint()); + } + if (authenticationIdpOidcBean.getTokenEndpoint() != null) { + oidcConfigBuilder.setTokenEndpoint(authenticationIdpOidcBean.getTokenEndpoint()); + } + if (authenticationIdpOidcBean.getUserInfoEndpoint() != null) { + oidcConfigBuilder.setUserInfoEndpoint(authenticationIdpOidcBean.getUserInfoEndpoint()); + } + + return oidcConfigBuilder.build(); + } + + public static AbstractAuthenticationIdpBean toAuthenticationIdpBean( + final IdpConfig idpConfig) { + + if (idpConfig.getSsoType().equals(SsoType.OIDC)) { + return toAuthenticationIdpOidcBean(idpConfig); + } else if (idpConfig.getSsoType().equals(SsoType.SAML)) { + return toAuthenticationIdpSamlBean(idpConfig); + } + + throw new UnsupportedOperationException("The IDP type cannot be NONE"); + } + + private static AuthenticationIdpOidcBean toAuthenticationIdpOidcBean( + final IdpConfig idpConfig) { + + if (!(idpConfig instanceof OidcConfig)) { + throw new InternalServerErrorException("The class of the IDP config is not OIDC"); + } + + final OidcConfig oidcConfig = (OidcConfig) idpConfig; + + final AuthenticationIdpOidcBean authenticationIdpOidcBean = new AuthenticationIdpOidcBean(); + authenticationIdpOidcBean.setId(oidcConfig.getId()); + authenticationIdpOidcBean.setName(oidcConfig.getName()); + authenticationIdpOidcBean.setEnabled(oidcConfig.isEnabled()); + authenticationIdpOidcBean.setUrl(oidcConfig.getIssuer()); + authenticationIdpOidcBean.setEnableRememberMe(oidcConfig.isEnableRememberMe()); + authenticationIdpOidcBean.setButtonText(oidcConfig.getButtonText()); + authenticationIdpOidcBean.setClientId(oidcConfig.getClientId()); + authenticationIdpOidcBean.setUsernameClaim(oidcConfig.getUsernameClaim()); + authenticationIdpOidcBean.setAdditionalScopes(oidcConfig.getAdditionalScopes()); + authenticationIdpOidcBean.setDiscoveryEnabled(oidcConfig.isDiscoveryEnabled()); + authenticationIdpOidcBean.setAuthorizationEndpoint(oidcConfig.getAuthorizationEndpoint()); + authenticationIdpOidcBean.setTokenEndpoint(oidcConfig.getTokenEndpoint()); + authenticationIdpOidcBean.setUserInfoEndpoint(oidcConfig.getUserInfoEndpoint()); + + return authenticationIdpOidcBean; + } + + private static AuthenticationIdpSamlBean toAuthenticationIdpSamlBean( + final IdpConfig idpConfig) { + + if (!(idpConfig instanceof SamlConfig)) { + throw new InternalServerErrorException("The class of the IDP config is not SAML"); + } + + final SamlConfig samlConfig = (SamlConfig) idpConfig; + + final AuthenticationIdpSamlBean authenticationIdpSamlBean = new AuthenticationIdpSamlBean(); + authenticationIdpSamlBean.setId(samlConfig.getId()); + authenticationIdpSamlBean.setName(samlConfig.getName()); + authenticationIdpSamlBean.setEnabled(samlConfig.isEnabled()); + authenticationIdpSamlBean.setUrl(samlConfig.getIssuer()); + authenticationIdpSamlBean.setEnableRememberMe(samlConfig.isEnableRememberMe()); + authenticationIdpSamlBean.setButtonText(samlConfig.getButtonText()); + // is it wanted to return the certificate here? + authenticationIdpSamlBean.setUsernameAttribute(samlConfig.getUsernameAttribute()); + + return authenticationIdpSamlBean; + } + + private static void verifyIdAndType( + final AbstractAuthenticationIdpBean authenticationIdpBean, + final IdpConfig existingIdpConfig, + final Class clazz) { + + if (authenticationIdpBean.getId() != null && !authenticationIdpBean.getId().equals(existingIdpConfig.getId())) { + throw new BadRequestException("An ID has been passed but it does not match the ID of the existing IDP with the same name"); + } + + if (!clazz.isAssignableFrom(existingIdpConfig.getClass())) { + throw new BadRequestException("The existing IDP config with the same name is not of type OIDC"); + } + } + + private AuthenticationIdpBeanUtil() { + } + +} diff --git a/src/main/java/de/aservo/confapi/jira/model/util/AuthenticationSsoBeanUtil.java b/src/main/java/de/aservo/confapi/jira/model/util/AuthenticationSsoBeanUtil.java new file mode 100644 index 0000000..cb54324 --- /dev/null +++ b/src/main/java/de/aservo/confapi/jira/model/util/AuthenticationSsoBeanUtil.java @@ -0,0 +1,46 @@ +package de.aservo.confapi.jira.model.util; + +import com.atlassian.plugins.authentication.api.config.ImmutableSsoConfig; +import com.atlassian.plugins.authentication.api.config.SsoConfig; +import de.aservo.confapi.commons.model.AuthenticationSsoBean; + +public class AuthenticationSsoBeanUtil { + + public static SsoConfig toSsoConfig( + final AuthenticationSsoBean authenticationSsoBean) { + + return toSsoConfig(authenticationSsoBean, null); + } + + public static SsoConfig toSsoConfig( + final AuthenticationSsoBean authenticationSsoBean, + final SsoConfig existingSsoConfig) { + + final ImmutableSsoConfig.Builder ssoConfigBuilder; + + if (existingSsoConfig != null) { + ssoConfigBuilder = ImmutableSsoConfig.toBuilder(existingSsoConfig); + } else { + ssoConfigBuilder = ImmutableSsoConfig.builder(); + } + + if (authenticationSsoBean.getShowOnLogin() != null) { + ssoConfigBuilder.setShowLoginForm(authenticationSsoBean.getShowOnLogin()); + } + + return ssoConfigBuilder.build(); + } + + public static AuthenticationSsoBean toAuthenticationSsoBean( + final SsoConfig ssoConfig) { + + final AuthenticationSsoBean authenticationSsoBean = new AuthenticationSsoBean(); + authenticationSsoBean.setShowOnLogin(ssoConfig.getShowLoginForm()); + + return authenticationSsoBean; + } + + private AuthenticationSsoBeanUtil() { + } + +} diff --git a/src/main/java/de/aservo/confapi/jira/rest/AuthenticationResourceImpl.java b/src/main/java/de/aservo/confapi/jira/rest/AuthenticationResourceImpl.java new file mode 100644 index 0000000..b53f48f --- /dev/null +++ b/src/main/java/de/aservo/confapi/jira/rest/AuthenticationResourceImpl.java @@ -0,0 +1,23 @@ +package de.aservo.confapi.jira.rest; + +import com.sun.jersey.spi.container.ResourceFilters; +import de.aservo.confapi.commons.constants.ConfAPI; +import de.aservo.confapi.commons.rest.AbstractAuthenticationResourceImpl; +import de.aservo.confapi.commons.service.api.AuthenticationService; +import de.aservo.confapi.jira.filter.SysadminOnlyResourceFilter; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import javax.ws.rs.Path; + +@Path(ConfAPI.AUTHENTICATION) +@ResourceFilters(SysadminOnlyResourceFilter.class) +@Component +public class AuthenticationResourceImpl extends AbstractAuthenticationResourceImpl { + + @Inject + public AuthenticationResourceImpl(AuthenticationService authenticationService) { + super(authenticationService); + } + +} diff --git a/src/main/java/de/aservo/confapi/jira/service/AuthenticationServiceImpl.java b/src/main/java/de/aservo/confapi/jira/service/AuthenticationServiceImpl.java new file mode 100644 index 0000000..e5c8650 --- /dev/null +++ b/src/main/java/de/aservo/confapi/jira/service/AuthenticationServiceImpl.java @@ -0,0 +1,105 @@ +package de.aservo.confapi.jira.service; + +import com.atlassian.plugin.spring.scanner.annotation.export.ExportAsService; +import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; +import com.atlassian.plugins.authentication.api.config.IdpConfig; +import com.atlassian.plugins.authentication.api.config.IdpConfigService; +import com.atlassian.plugins.authentication.api.config.SsoConfig; +import com.atlassian.plugins.authentication.api.config.SsoConfigService; +import de.aservo.confapi.commons.exception.BadRequestException; +import de.aservo.confapi.commons.model.AbstractAuthenticationIdpBean; +import de.aservo.confapi.commons.model.AuthenticationIdpsBean; +import de.aservo.confapi.commons.model.AuthenticationSsoBean; +import de.aservo.confapi.commons.service.api.AuthenticationService; +import de.aservo.confapi.jira.model.util.AuthenticationIdpBeanUtil; +import de.aservo.confapi.jira.model.util.AuthenticationSsoBeanUtil; +import org.springframework.stereotype.Component; + +import java.util.Comparator; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Component +@ExportAsService(AuthenticationService.class) +public class AuthenticationServiceImpl implements AuthenticationService { + + @ComponentImport + private final IdpConfigService idpConfigService; + + @ComponentImport + private final SsoConfigService ssoConfigService; + + public AuthenticationServiceImpl( + final IdpConfigService idpConfigService, + final SsoConfigService ssoConfigService) { + + this.idpConfigService = idpConfigService; + this.ssoConfigService = ssoConfigService; + } + + @Override + public AuthenticationIdpsBean getAuthenticationIdps() { + return new AuthenticationIdpsBean(idpConfigService.getIdpConfigs().stream() + .map(AuthenticationIdpBeanUtil::toAuthenticationIdpBean) + .sorted(authenticationIdpBeanComparator) + .collect(Collectors.toList())); + } + + @Override + public AuthenticationIdpsBean setAuthenticationIdps( + final AuthenticationIdpsBean authenticationIdpsBean) { + + return new AuthenticationIdpsBean(authenticationIdpsBean.getAuthenticationIdpBeans().stream() + .map(this::setAuthenticationIdp) + .sorted(authenticationIdpBeanComparator) + .collect(Collectors.toList())); + } + + public AbstractAuthenticationIdpBean setAuthenticationIdp( + final AbstractAuthenticationIdpBean authenticationIdpBean) { + + if (authenticationIdpBean.getName() == null || authenticationIdpBean.getName().trim().isEmpty()) { + throw new BadRequestException("The name cannot be empty"); + } + + final IdpConfig existingIdpConfig = findIdpConfigByName(authenticationIdpBean.getName()); + + if (existingIdpConfig == null) { + final IdpConfig idpConfig = AuthenticationIdpBeanUtil.toIdpConfig(authenticationIdpBean); + final IdpConfig addedIdpConfig = idpConfigService.addIdpConfig(idpConfig); + return AuthenticationIdpBeanUtil.toAuthenticationIdpBean(addedIdpConfig); + } + + final IdpConfig idpConfig = AuthenticationIdpBeanUtil.toIdpConfig(authenticationIdpBean, existingIdpConfig); + final IdpConfig updatedIdpConfig = idpConfigService.updateIdpConfig(idpConfig); + return AuthenticationIdpBeanUtil.toAuthenticationIdpBean(updatedIdpConfig); + } + + @Override + public AuthenticationSsoBean getAuthenticationSso() { + return AuthenticationSsoBeanUtil.toAuthenticationSsoBean(ssoConfigService.getSsoConfig()); + } + + @Override + public AuthenticationSsoBean setAuthenticationSso(AuthenticationSsoBean authenticationSsoBean) { + final SsoConfig existingSsoConfig = ssoConfigService.getSsoConfig(); + final SsoConfig ssoConfig = AuthenticationSsoBeanUtil.toSsoConfig(authenticationSsoBean, existingSsoConfig); + return AuthenticationSsoBeanUtil.toAuthenticationSsoBean(ssoConfigService.updateSsoConfig(ssoConfig)); + } + + IdpConfig findIdpConfigByName( + final String name) { + + final Map idpConfigsByName = idpConfigService.getIdpConfigs().stream().collect(Collectors.toMap( + IdpConfig::getName, Function.identity(), (existing, replacement) -> { + throw new IllegalStateException("Duplicate name key found: " + existing.getName()); + } + )); + + return idpConfigsByName.get(name); + } + + static Comparator authenticationIdpBeanComparator = (a1, a2) -> a1.getName().compareToIgnoreCase(a2.getName()); + +} diff --git a/src/test/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtilTest.java b/src/test/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtilTest.java new file mode 100644 index 0000000..5452a16 --- /dev/null +++ b/src/test/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtilTest.java @@ -0,0 +1,61 @@ +package de.aservo.confapi.jira.model.util; + +import com.atlassian.plugins.authentication.api.config.IdpConfig; +import com.atlassian.plugins.authentication.api.config.SsoType; +import com.atlassian.plugins.authentication.api.config.oidc.OidcConfig; +import com.atlassian.plugins.authentication.api.config.saml.SamlConfig; +import de.aservo.confapi.commons.exception.BadRequestException; +import de.aservo.confapi.commons.model.AbstractAuthenticationIdpBean; +import de.aservo.confapi.commons.model.AuthenticationIdpOidcBean; +import de.aservo.confapi.commons.model.AuthenticationIdpSamlBean; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MockitoExtension.class) +class AuthenticationIdpBeanUtilTest { + + @Test + void testToIdpConfigOidc() { + final AuthenticationIdpOidcBean authenticationIdpOidcBean = AuthenticationIdpOidcBean.EXAMPLE_1; + final IdpConfig idpConfig = AuthenticationIdpBeanUtil.toIdpConfig(authenticationIdpOidcBean); + assertEquals(SsoType.OIDC, idpConfig.getSsoType()); + } + + @Test + void testToIdpConfigOidcExistingIdDoesNotMatch() { + final AuthenticationIdpOidcBean authenticationIdpOidcBean = AuthenticationIdpOidcBean.EXAMPLE_1; + final IdpConfig existingIdpConfig = OidcConfig.builder().setId(authenticationIdpOidcBean.getId() + 1).build(); + + assertThrows(BadRequestException.class, () -> { + AuthenticationIdpBeanUtil.toIdpConfig(authenticationIdpOidcBean, existingIdpConfig); + }); + } + + @Test + void testToIdpConfigOidcExistingTypeDoesNotMatch() { + final AuthenticationIdpOidcBean authenticationIdpOidcBean = AuthenticationIdpOidcBean.EXAMPLE_1; + final IdpConfig existingIdpConfig = SamlConfig.builder().build(); + + assertThrows(BadRequestException.class, () -> { + AuthenticationIdpBeanUtil.toIdpConfig(authenticationIdpOidcBean, existingIdpConfig); + }); + } + + @Test + void testToAuthenticationIdpBeanOidcType() { + final IdpConfig idpConfig = OidcConfig.builder().setName("oidc").build(); + final AbstractAuthenticationIdpBean authenticationIdpBean = AuthenticationIdpBeanUtil.toAuthenticationIdpBean(idpConfig); + assertTrue(authenticationIdpBean.getClass().isAssignableFrom(AuthenticationIdpOidcBean.class)); + } + + @Test + void testToAuthenticationIdpBeanSamlType() { + final IdpConfig idpConfig = SamlConfig.builder().setName("saml").build(); + final AbstractAuthenticationIdpBean authenticationIdpBean = AuthenticationIdpBeanUtil.toAuthenticationIdpBean(idpConfig); + assertTrue(authenticationIdpBean.getClass().isAssignableFrom(AuthenticationIdpSamlBean.class)); + } + +} diff --git a/src/test/java/de/aservo/confapi/jira/service/AuthenticationServiceTest.java b/src/test/java/de/aservo/confapi/jira/service/AuthenticationServiceTest.java new file mode 100644 index 0000000..b66fcee --- /dev/null +++ b/src/test/java/de/aservo/confapi/jira/service/AuthenticationServiceTest.java @@ -0,0 +1,124 @@ +package de.aservo.confapi.jira.service; + +import com.atlassian.plugins.authentication.api.config.*; +import com.atlassian.plugins.authentication.api.config.oidc.OidcConfig; +import com.atlassian.plugins.authentication.api.config.saml.SamlConfig; +import de.aservo.confapi.commons.exception.BadRequestException; +import de.aservo.confapi.commons.model.AbstractAuthenticationIdpBean; +import de.aservo.confapi.commons.model.AuthenticationIdpOidcBean; +import de.aservo.confapi.commons.model.AuthenticationIdpsBean; +import de.aservo.confapi.commons.model.AuthenticationSsoBean; +import de.aservo.confapi.jira.model.util.AuthenticationIdpBeanUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class AuthenticationServiceTest { + + @Mock + private IdpConfigService idpConfigService; + + @Mock + private SsoConfigService ssoConfigService; + + private AuthenticationServiceImpl authenticationService; + + @BeforeEach + public void setup() { + authenticationService = new AuthenticationServiceImpl(idpConfigService, ssoConfigService); + } + + @Test + void testGetAuthenticationIdps() { + final OidcConfig oidcConfig = OidcConfig.builder().setName("oidc").build(); + final SamlConfig samlConfig = SamlConfig.builder().setName("saml").build(); + doReturn(Arrays.asList(oidcConfig, samlConfig)).when(idpConfigService).getIdpConfigs(); + + final AuthenticationIdpsBean authenticationIdpsBean = authenticationService.getAuthenticationIdps(); + final List names = authenticationIdpsBean.getAuthenticationIdpBeans().stream() + .map(AbstractAuthenticationIdpBean::getName) + .collect(Collectors.toList()); + assertTrue(names.contains(oidcConfig.getName())); + assertTrue(names.contains(samlConfig.getName())); + } + + @Test + void testSetAuthenticationIdpsWithCreate() { + final AuthenticationIdpOidcBean authenticationIdpOidcBean = AuthenticationIdpOidcBean.EXAMPLE_1; + final AuthenticationIdpsBean authenticationIdpsBean = new AuthenticationIdpsBean(Collections.singletonList(authenticationIdpOidcBean)); + doAnswer(invocation -> invocation.getArgument(0)).when(idpConfigService).addIdpConfig(any()); + + final AuthenticationIdpsBean resultAuthenticationIdpsBean = authenticationService.setAuthenticationIdps(authenticationIdpsBean); + verify(idpConfigService, times(1)).addIdpConfig(any()); + assertEquals(authenticationIdpOidcBean.getId(), resultAuthenticationIdpsBean.getAuthenticationIdpBeans().iterator().next().getId()); + assertEquals(authenticationIdpOidcBean.getName(), resultAuthenticationIdpsBean.getAuthenticationIdpBeans().iterator().next().getName()); + } + + @Test + void testSetAuthenticationIdpsWithUpdate() { + final AuthenticationIdpOidcBean authenticationIdpOidcBean = AuthenticationIdpOidcBean.EXAMPLE_1; + final AuthenticationIdpsBean authenticationIdpsBean = new AuthenticationIdpsBean(Collections.singletonList(authenticationIdpOidcBean)); + final IdpConfig idpConfig = AuthenticationIdpBeanUtil.toIdpConfig(authenticationIdpOidcBean); + doReturn(Collections.singletonList(idpConfig)).when(idpConfigService).getIdpConfigs(); + doAnswer(invocation -> invocation.getArgument(0)).when(idpConfigService).updateIdpConfig(any()); + + final AuthenticationIdpsBean resultAuthenticationIdpsBean = authenticationService.setAuthenticationIdps(authenticationIdpsBean); + verify(idpConfigService, times(1)).updateIdpConfig(any()); + assertEquals(authenticationIdpOidcBean.getId(), resultAuthenticationIdpsBean.getAuthenticationIdpBeans().iterator().next().getId()); + assertEquals(authenticationIdpOidcBean.getName(), resultAuthenticationIdpsBean.getAuthenticationIdpBeans().iterator().next().getName()); + } + + @Test + void testSetAuthenticationIdpsNameNull() { + final AuthenticationIdpOidcBean authenticationIdpOidcBean = new AuthenticationIdpOidcBean(); + final AuthenticationIdpsBean authenticationIdpsBean = new AuthenticationIdpsBean(Collections.singletonList(authenticationIdpOidcBean)); + + assertThrows(BadRequestException.class, () -> { + authenticationService.setAuthenticationIdps(authenticationIdpsBean); + }); + } + + @Test + void testSetAuthenticationIdpsNameEmpty() { + final AuthenticationIdpOidcBean authenticationIdpOidcBean = new AuthenticationIdpOidcBean(); + authenticationIdpOidcBean.setName(""); + final AuthenticationIdpsBean authenticationIdpsBean = new AuthenticationIdpsBean(Collections.singletonList(authenticationIdpOidcBean)); + + assertThrows(BadRequestException.class, () -> { + authenticationService.setAuthenticationIdps(authenticationIdpsBean); + }); + } + + @Test + void testGetAuthenticationSso() { + final SsoConfig ssoConfig = ImmutableSsoConfig.builder().setShowLoginForm(true).build(); + doReturn(ssoConfig).when(ssoConfigService).getSsoConfig(); + + final AuthenticationSsoBean authenticationSsoBean = authenticationService.getAuthenticationSso(); + assertEquals(ssoConfig.getShowLoginForm(), authenticationSsoBean.getShowOnLogin()); + } + + @Test + void testSetAuthenticationSso() { + final AuthenticationSsoBean authenticationSsoBean = AuthenticationSsoBean.EXAMPLE_1; + final SsoConfig ssoConfig = ImmutableSsoConfig.builder().setShowLoginForm(authenticationSsoBean.getShowOnLogin()).build(); + doReturn(ssoConfig).when(ssoConfigService).updateSsoConfig(ssoConfig); + + final AuthenticationSsoBean resultAuthenticationSsoBean = authenticationService.setAuthenticationSso(authenticationSsoBean); + verify(ssoConfigService, times(1)).updateSsoConfig(ssoConfig); + assertEquals(authenticationSsoBean.getShowOnLogin(), resultAuthenticationSsoBean.getShowOnLogin()); + } + +}