From f1a7b51a442031acc42867f0d1b9c5dcfc07b1fc Mon Sep 17 00:00:00 2001 From: Guillaume Jambet Date: Thu, 22 Feb 2018 11:00:45 +0100 Subject: [PATCH] SONAR-10426 Add homepage default when db is inconsistent --- .../main/java/org/sonar/db/user/UserDao.java | 8 +- .../java/org/sonar/db/user/UserMapper.java | 4 +- .../org/sonar/db/user/UserMapper.xml | 428 +++++++++--------- .../java/org/sonar/db/user/UserDaoTest.java | 16 + .../sonar/server/user/ws/CurrentAction.java | 109 +++-- .../sonar/server/user/ws/HomepageTypes.java | 4 +- .../server/user/ws/HomepageTypesImpl.java | 17 +- .../server/user/ws/CurrentActionTest.java | 100 +++- .../server/user/ws/SetHomepageActionTest.java | 45 +- 9 files changed, 437 insertions(+), 294 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java index c063482fc98..e58945b21aa 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java @@ -124,11 +124,15 @@ public class UserDao implements Dao { } public void cleanHomepage(DbSession dbSession, OrganizationDto organization) { - mapper(dbSession).clearHomepage("ORGANIZATION", organization.getUuid(), system2.now()); + mapper(dbSession).clearHomepages("ORGANIZATION", organization.getUuid(), system2.now()); } public void cleanHomepage(DbSession dbSession, ComponentDto project) { - mapper(dbSession).clearHomepage("PROJECT", project.uuid(), system2.now()); + mapper(dbSession).clearHomepages("PROJECT", project.uuid(), system2.now()); + } + + public void cleanHomepage(DbSession dbSession, UserDto user) { + mapper(dbSession).clearHomepage(user.getLogin(), system2.now()); } @CheckForNull diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java index 5d816dab951..fa80aba9ac8 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java @@ -70,5 +70,7 @@ public interface UserMapper { void deactivateUser(@Param("login") String login, @Param("now") long now); - void clearHomepage(@Param("homepageType") String type, @Param("homepageParameter") String value, @Param("now") long now); + void clearHomepages(@Param("homepageType") String type, @Param("homepageParameter") String value, @Param("now") long now); + + void clearHomepage(@Param("login") String login, @Param("now") long now); } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml index d7c568696e5..9b6f5c9f5ee 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml @@ -3,216 +3,226 @@ - - u.id as id, - u.login as login, - u.name as name, - u.email as email, - u.active as "active", - u.scm_accounts as "scmAccounts", - u.salt as "salt", - u.crypted_password as "cryptedPassword", - u.external_identity as "externalIdentity", - u.external_identity_provider as "externalIdentityProvider", - u.user_local as "local", - u.is_root as "root", - u.onboarded as "onboarded", - u.created_at as "createdAt", - u.updated_at as "updatedAt", - u.homepage_type as "homepageType", - u.homepage_parameter as "homepageParameter" - - - - - - - - - - - - - - - - - + SELECT + + FROM users u + WHERE u.login=#{login} + + + + + + + + + + + + + + + + + - - - - - - - update users set - active = ${_false}, - email = null, - scm_accounts = null, - external_identity = null, - external_identity_provider = null, - salt = null, - crypted_password = null, - updated_at = #{now, jdbcType=BIGINT} - where - login = #{login, jdbcType=VARCHAR} - - - - update users set - homepage_type = null, - homepage_parameter = null, - updated_at = #{now, jdbcType=BIGINT} - where - homepage_type = #{homepageType, jdbcType=VARCHAR} - and homepage_parameter = #{homepageParameter, jdbcType=VARCHAR} - - - - update users set - is_root = #{root, jdbcType=BOOLEAN}, - updated_at = #{now, jdbcType=BIGINT} - where - login = #{login, jdbcType=VARCHAR} - and active = ${_true} - - - - insert into users ( - login, - name, - email, - active, - scm_accounts, - external_identity, - external_identity_provider, - user_local, - salt, - crypted_password, - is_root, - onboarded, - created_at, - updated_at, - homepage_type, - homepage_parameter - ) values ( - #{user.login,jdbcType=VARCHAR}, - #{user.name,jdbcType=VARCHAR}, - #{user.email,jdbcType=VARCHAR}, - #{user.active,jdbcType=BOOLEAN}, - #{user.scmAccounts,jdbcType=VARCHAR}, - #{user.externalIdentity,jdbcType=VARCHAR}, - #{user.externalIdentityProvider,jdbcType=VARCHAR}, - #{user.local,jdbcType=BOOLEAN}, - #{user.salt,jdbcType=VARCHAR}, - #{user.cryptedPassword,jdbcType=VARCHAR}, - #{user.root,jdbcType=BOOLEAN}, - #{user.onboarded,jdbcType=BOOLEAN}, - #{now,jdbcType=BIGINT}, - #{now,jdbcType=BIGINT}, - #{user.homepageType,jdbcType=VARCHAR}, - #{user.homepageParameter,jdbcType=VARCHAR} - ) - - - - update users set - name = #{user.name, jdbcType=VARCHAR}, - email = #{user.email, jdbcType=VARCHAR}, - active = #{user.active, jdbcType=BOOLEAN}, - scm_accounts = #{user.scmAccounts, jdbcType=VARCHAR}, - external_identity = #{user.externalIdentity, jdbcType=VARCHAR}, - external_identity_provider = #{user.externalIdentityProvider, jdbcType=VARCHAR}, - user_local = #{user.local, jdbcType=BOOLEAN}, - onboarded = #{user.onboarded, jdbcType=BOOLEAN}, - salt = #{user.salt, jdbcType=VARCHAR}, - crypted_password = #{user.cryptedPassword, jdbcType=BIGINT}, - updated_at = #{now, jdbcType=BIGINT}, - homepage_type = #{user.homepageType, jdbcType=VARCHAR}, - homepage_parameter = #{user.homepageParameter, jdbcType=VARCHAR} - where - login = #{user.login, jdbcType=VARCHAR} - + + + + + + update users set + active = ${_false}, + email = null, + scm_accounts = null, + external_identity = null, + external_identity_provider = null, + salt = null, + crypted_password = null, + updated_at = #{now, jdbcType=BIGINT} + where + login = #{login, jdbcType=VARCHAR} + + + + update users set + homepage_type = null, + homepage_parameter = null, + updated_at = #{now, jdbcType=BIGINT} + where + homepage_type = #{homepageType, jdbcType=VARCHAR} + and homepage_parameter = #{homepageParameter, jdbcType=VARCHAR} + + + + update users set + homepage_type = null, + homepage_parameter = null, + updated_at = #{now, jdbcType=BIGINT} + where + login = #{login, jdbcType=VARCHAR} + + + + update users set + is_root = #{root, jdbcType=BOOLEAN}, + updated_at = #{now, jdbcType=BIGINT} + where + login = #{login, jdbcType=VARCHAR} + and active = ${_true} + + + + insert into users ( + login, + name, + email, + active, + scm_accounts, + external_identity, + external_identity_provider, + user_local, + salt, + crypted_password, + is_root, + onboarded, + created_at, + updated_at, + homepage_type, + homepage_parameter + ) values ( + #{user.login,jdbcType=VARCHAR}, + #{user.name,jdbcType=VARCHAR}, + #{user.email,jdbcType=VARCHAR}, + #{user.active,jdbcType=BOOLEAN}, + #{user.scmAccounts,jdbcType=VARCHAR}, + #{user.externalIdentity,jdbcType=VARCHAR}, + #{user.externalIdentityProvider,jdbcType=VARCHAR}, + #{user.local,jdbcType=BOOLEAN}, + #{user.salt,jdbcType=VARCHAR}, + #{user.cryptedPassword,jdbcType=VARCHAR}, + #{user.root,jdbcType=BOOLEAN}, + #{user.onboarded,jdbcType=BOOLEAN}, + #{now,jdbcType=BIGINT}, + #{now,jdbcType=BIGINT}, + #{user.homepageType,jdbcType=VARCHAR}, + #{user.homepageParameter,jdbcType=VARCHAR} + ) + + + + update users set + name = #{user.name, jdbcType=VARCHAR}, + email = #{user.email, jdbcType=VARCHAR}, + active = #{user.active, jdbcType=BOOLEAN}, + scm_accounts = #{user.scmAccounts, jdbcType=VARCHAR}, + external_identity = #{user.externalIdentity, jdbcType=VARCHAR}, + external_identity_provider = #{user.externalIdentityProvider, jdbcType=VARCHAR}, + user_local = #{user.local, jdbcType=BOOLEAN}, + onboarded = #{user.onboarded, jdbcType=BOOLEAN}, + salt = #{user.salt, jdbcType=VARCHAR}, + crypted_password = #{user.cryptedPassword, jdbcType=BIGINT}, + updated_at = #{now, jdbcType=BIGINT}, + homepage_type = #{user.homepageType, jdbcType=VARCHAR}, + homepage_parameter = #{user.homepageParameter, jdbcType=VARCHAR} + where + login = #{user.login, jdbcType=VARCHAR} + diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java index e4e219ec665..1286768f703 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java @@ -466,6 +466,22 @@ public class UserDaoTest { assertThat(untouchedUserReloaded.getHomepageParameter()).isEqualTo(untouchedUser.getHomepageParameter()); } + @Test + public void clean_user_homepage() { + + UserDto user = newUserDto().setHomepageType("RANDOM").setHomepageParameter("any-string"); + underTest.insert(session, user); + session.commit(); + + underTest.cleanHomepage(session,user); + + UserDto reloaded = underTest.selectUserById(session, user.getId()); + assertThat(reloaded.getUpdatedAt()).isEqualTo(NOW); + assertThat(reloaded.getHomepageType()).isNull(); + assertThat(reloaded.getHomepageParameter()).isNull(); + + } + @Test public void does_not_fail_to_deactivate_missing_user() { underTest.deactivateUser(session, UserTesting.newUserDto()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java index 3b7ad430f56..2df9909bcee 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java @@ -21,11 +21,12 @@ package org.sonar.server.user.ws; import java.util.Collection; import java.util.List; -import javax.annotation.Nullable; +import java.util.Optional; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService.NewController; +import org.sonar.core.platform.PluginRepository; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; @@ -39,9 +40,12 @@ import org.sonarqube.ws.Users.CurrentWsResponse; import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Strings.emptyToNull; -import static java.lang.String.format; import static java.util.Collections.singletonList; +import static java.util.Optional.empty; +import static java.util.Optional.of; +import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toList; +import static org.apache.commons.lang.StringUtils.EMPTY; import static org.sonar.core.util.Protobuf.setNullable; import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonarqube.ws.Users.CurrentWsResponse.Permissions; @@ -54,20 +58,23 @@ import static org.sonarqube.ws.client.user.UsersWsParameters.ACTION_CURRENT; public class CurrentAction implements UsersWsAction { + private static final String GOVERNANCE_PLUGIN_KEY = "governance"; + private final UserSession userSession; private final DbClient dbClient; private final DefaultOrganizationProvider defaultOrganizationProvider; private final AvatarResolver avatarResolver; private final HomepageTypes homepageTypes; - private static final String HOMEPAGE_PARAMETER_SHOULD_NOT_BE_NULL = "Homepage parameter should not be null"; + private final PluginRepository pluginRepository; public CurrentAction(UserSession userSession, DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider, - AvatarResolver avatarResolver, HomepageTypes homepageTypes) { + AvatarResolver avatarResolver, HomepageTypes homepageTypes, PluginRepository pluginRepository) { this.userSession = userSession; this.dbClient = dbClient; this.defaultOrganizationProvider = defaultOrganizationProvider; this.avatarResolver = avatarResolver; this.homepageTypes = homepageTypes; + this.pluginRepository = pluginRepository; } @Override @@ -129,42 +136,74 @@ public class CurrentAction implements UsersWsAction { } private CurrentWsResponse.Homepage buildHomepage(DbSession dbSession, UserDto user) { - String homepageType = user.getHomepageType(); - if (homepageType == null) { + if (noHomepageSet(user)) { return defaultHomepage(); } - CurrentWsResponse.Homepage.Builder homepage = CurrentWsResponse.Homepage.newBuilder() - .setType(CurrentWsResponse.HomepageType.valueOf(homepageType)); - setHomepageParameter(dbSession, homepageType, user.getHomepageParameter(), homepage); - return homepage.build(); + + return doBuildHomepage(dbSession, user).orElse(defaultHomepage()); + } + + private Optional doBuildHomepage(DbSession dbSession, UserDto user) { + + if (PROJECT.toString().equals(user.getHomepageType())) { + return projectHomepage(dbSession, user); + } + + if (APPLICATION.toString().equals(user.getHomepageType()) || PORTFOLIO.toString().equals(user.getHomepageType())) { + return applicationAndPortfolioHomepage(dbSession, user); + } + + if (ORGANIZATION.toString().equals(user.getHomepageType())) { + return organizationHomepage(dbSession, user); + } + + return of(CurrentWsResponse.Homepage.newBuilder() + .setType(CurrentWsResponse.HomepageType.valueOf(user.getHomepageType())) + .build()); } - private void setHomepageParameter(DbSession dbSession, String homepageType, @Nullable String homepageParameter, CurrentWsResponse.Homepage.Builder homepage) { - if (PROJECT.toString().equals(homepageType)) { - checkState(homepageParameter != null, HOMEPAGE_PARAMETER_SHOULD_NOT_BE_NULL); - ComponentDto component = dbClient.componentDao().selectByUuid(dbSession, homepageParameter) - .or(() -> { - throw new IllegalStateException(format("Unknown component '%s' for homepageParameter", homepageParameter)); - }); - homepage.setComponent(component.getKey()); - setNullable(component.getBranch(), homepage::setBranch); - return; + private Optional projectHomepage(DbSession dbSession, UserDto user) { + Optional projectOptional = ofNullable(dbClient.componentDao().selectByUuid(dbSession, of(user.getHomepageParameter()).orElse(EMPTY)).orNull()); + if (!projectOptional.isPresent()) { + cleanUserHomepageInDb(dbSession, user); + return empty(); } - if (APPLICATION.toString().equals(homepageType) || PORTFOLIO.toString().equals(homepageType)) { - checkState(homepageParameter != null, HOMEPAGE_PARAMETER_SHOULD_NOT_BE_NULL); - ComponentDto component = dbClient.componentDao().selectByUuid(dbSession, homepageParameter) - .or(() -> { - throw new IllegalStateException(format("Unknown component '%s' for homepageParameter", homepageParameter)); - }); - homepage.setComponent(component.getKey()); - return; + + CurrentWsResponse.Homepage.Builder homepage = CurrentWsResponse.Homepage.newBuilder() + .setType(CurrentWsResponse.HomepageType.valueOf(user.getHomepageType())) + .setComponent(projectOptional.get().getKey()); + setNullable(projectOptional.get().getBranch(), homepage::setBranch); + return of(homepage.build()); + } + + private Optional applicationAndPortfolioHomepage(DbSession dbSession, UserDto user) { + Optional componentOptional = ofNullable(dbClient.componentDao().selectByUuid(dbSession, of(user.getHomepageParameter()).orElse(EMPTY)).orNull()); + if (!componentOptional.isPresent() || !pluginRepository.hasPlugin(GOVERNANCE_PLUGIN_KEY)) { + cleanUserHomepageInDb(dbSession, user); + return empty(); } - if (ORGANIZATION.toString().equals(homepageType)) { - checkState(homepageParameter != null, HOMEPAGE_PARAMETER_SHOULD_NOT_BE_NULL); - OrganizationDto organization = dbClient.organizationDao().selectByUuid(dbSession, homepageParameter) - .orElseThrow(() -> new IllegalStateException(format("Unknown organization '%s' for homepageParameter", homepageParameter))); - homepage.setOrganization(organization.getKey()); + + return of(CurrentWsResponse.Homepage.newBuilder() + .setType(CurrentWsResponse.HomepageType.valueOf(user.getHomepageType())) + .setComponent(componentOptional.get().getKey()) + .build()); + } + + private Optional organizationHomepage(DbSession dbSession, UserDto user) { + Optional organizationOptional = dbClient.organizationDao().selectByUuid(dbSession, of(user.getHomepageParameter()).orElse(EMPTY)); + if (!organizationOptional.isPresent()) { + cleanUserHomepageInDb(dbSession, user); + return empty(); } + + return of(CurrentWsResponse.Homepage.newBuilder() + .setType(CurrentWsResponse.HomepageType.valueOf(user.getHomepageType())) + .setOrganization(organizationOptional.get().getKey()) + .build()); + } + + private void cleanUserHomepageInDb(DbSession dbSession, UserDto user) { + dbClient.userDao().cleanHomepage(dbSession, user); } private CurrentWsResponse.Homepage defaultHomepage() { @@ -173,4 +212,8 @@ public class CurrentAction implements UsersWsAction { .build(); } + private static boolean noHomepageSet(UserDto user) { + return user.getHomepageType() == null; + } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypes.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypes.java index be7f40ebc60..816555047f7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypes.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypes.java @@ -26,7 +26,7 @@ public interface HomepageTypes { enum Type { PROJECT, /** - * These types in only available on SonarQube + * These types are only available on SonarQube */ PROJECTS, ISSUES, PORTFOLIOS, PORTFOLIO, APPLICATION, /** @@ -34,7 +34,7 @@ public interface HomepageTypes { */ MY_PROJECTS, MY_ISSUES, /** - * This type in only available when organizations are enabled + * This type is only available when organizations are enabled */ ORGANIZATION } diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypesImpl.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypesImpl.java index 7dfc2527d59..d4ddeaa8318 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypesImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypesImpl.java @@ -50,7 +50,6 @@ public class HomepageTypesImpl implements HomepageTypes, Startable { private final DbClient dbClient; private List types; - private Type defaultType; public HomepageTypesImpl(Configuration configuration, OrganizationFlags organizationFlags, DbClient dbClient) { this.configuration = configuration; @@ -66,23 +65,29 @@ public class HomepageTypesImpl implements HomepageTypes, Startable { @Override public Type getDefaultType() { - checkState(types != null, "Homepage types have not been initialized yet"); - return defaultType; + return isOnSonarCloud() ? MY_PROJECTS : PROJECTS; } @Override public void start() { try (DbSession dbSession = dbClient.openSession(false)) { - boolean isOnSonarCloud = configuration.getBoolean(ProcessProperties.Property.SONARCLOUD_ENABLED.getKey()).orElse(false); - boolean isOrganizationEnabled = organizationFlags.isEnabled(dbSession); + boolean isOnSonarCloud = isOnSonarCloud(); + boolean isOrganizationEnabled = isOrganizationEnabled(dbSession); this.types = stream(values()) .filter(type -> (isOnSonarCloud && ON_SONARCLOUD.contains(type)) || (!isOnSonarCloud && ON_SONARQUBE.contains(type))) .filter(type -> isOrganizationEnabled || !(type.equals(ORGANIZATION))) .collect(toList()); - this.defaultType = isOnSonarCloud ? Type.MY_PROJECTS : PROJECTS; } } + private boolean isOrganizationEnabled(DbSession dbSession) { + return organizationFlags.isEnabled(dbSession); + } + + private Boolean isOnSonarCloud() { + return configuration.getBoolean(ProcessProperties.Property.SONARCLOUD_ENABLED.getKey()).orElse(false); + } + @Override public void stop() { // Nothing to do diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java index 7748ff91811..f148c030860 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java @@ -19,12 +19,13 @@ */ package org.sonar.server.user.ws; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.api.config.internal.MapSettings; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.System2; +import org.sonar.core.platform.PluginRepository; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; @@ -32,6 +33,7 @@ import org.sonar.db.user.UserDto; import org.sonar.server.issue.ws.AvatarResolverImpl; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider; +import org.sonar.server.organization.TestOrganizationFlags; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.Users.CurrentWsResponse; @@ -57,15 +59,14 @@ public class CurrentActionTest { private DbClient dbClient = db.getDbClient(); private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); - private HomepageTypes homepageTypes = mock(HomepageTypes.class); - private WsActionTester ws = new WsActionTester(new CurrentAction(userSessionRule, dbClient, defaultOrganizationProvider, new AvatarResolverImpl(), homepageTypes)); + private PluginRepository pluginRepository = mock(PluginRepository.class); + private MapSettings settings = new MapSettings(); + private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone(); + private HomepageTypesImpl homepageTypes = new HomepageTypesImpl(settings.asConfig(), organizationFlags, db.getDbClient()); - @Before - public void setUp() { - when(homepageTypes.getDefaultType()).thenReturn(HomepageTypes.Type.MY_PROJECTS); - ws = new WsActionTester(new CurrentAction(userSessionRule, dbClient, defaultOrganizationProvider, new AvatarResolverImpl(), homepageTypes)); - } + private WsActionTester ws = new WsActionTester( + new CurrentAction(userSessionRule, dbClient, defaultOrganizationProvider, new AvatarResolverImpl(), homepageTypes, pluginRepository)); @Test public void return_user_info() { @@ -180,6 +181,7 @@ public class CurrentActionTest { @Test public void return_homepage_when_set_to_a_portfolio() { + withGovernancePlugin(); ComponentDto portfolio = db.components().insertPrivatePortfolio(db.getDefaultOrganization()); UserDto user = db.users().insertUser(u -> u.setHomepageType("PORTFOLIO").setHomepageParameter(portfolio.uuid())); userSessionRule.logIn(user); @@ -193,6 +195,7 @@ public class CurrentActionTest { @Test public void return_homepage_when_set_to_an_application() { + withGovernancePlugin(); ComponentDto application = db.components().insertPrivateApplication(db.getDefaultOrganization()); UserDto user = db.users().insertUser(u -> u.setHomepageType("APPLICATION").setHomepageParameter(application.uuid())); userSessionRule.logIn(user); @@ -306,25 +309,90 @@ public class CurrentActionTest { } @Test - public void fail_with_ISE_when_user_homepage_project_does_not_exist_in_db() { + public void fallback_when_user_homepage_project_does_not_exist_in_db() { UserDto user = db.users().insertUser(u -> u.setHomepageType("PROJECT").setHomepageParameter("not-existing-project-uuid")); userSessionRule.logIn(user.getLogin()); - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Unknown component 'not-existing-project-uuid' for homepageParameter"); + CurrentWsResponse response = ws.newRequest().executeProtobuf(CurrentWsResponse.class); - call(); + assertThat(response.getHomepage()).isNotNull(); } @Test - public void fail_with_ISE_when_user_homepage_organization_does_not_exist_in_db() { + public void fallback_when_user_homepage_organization_does_not_exist_in_db() { UserDto user = db.users().insertUser(u -> u.setHomepageType("ORGANIZATION").setHomepageParameter("not-existing-organization-uuid")); userSessionRule.logIn(user.getLogin()); - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Unknown organization 'not-existing-organization-uuid' for homepageParameter"); + CurrentWsResponse response = ws.newRequest().executeProtobuf(CurrentWsResponse.class); - call(); + assertThat(response.getHomepage()).isNotNull(); + } + + @Test + public void fallback_when_user_homepage_portfolio_does_not_exist_in_db() { + withGovernancePlugin(); + UserDto user = db.users().insertUser(u -> u.setHomepageType("PORTFOLIO").setHomepageParameter("not-existing-portfolio-uuid")); + userSessionRule.logIn(user.getLogin()); + + CurrentWsResponse response = ws.newRequest().executeProtobuf(CurrentWsResponse.class); + + assertThat(response.getHomepage()).isNotNull(); + } + + @Test + public void fallback_when_user_homepage_application_does_not_exist_in_db() { + withGovernancePlugin(); + UserDto user = db.users().insertUser(u -> u.setHomepageType("APPLICATION").setHomepageParameter("not-existing-application-uuid")); + userSessionRule.logIn(user.getLogin()); + + CurrentWsResponse response = ws.newRequest().executeProtobuf(CurrentWsResponse.class); + + assertThat(response.getHomepage()).isNotNull(); + } + + @Test + public void fallback_when_user_homepage_application_and_governance_plugin_is_not_installed() { + withoutGovernancePlugin(); + ComponentDto application = db.components().insertPrivateApplication(db.getDefaultOrganization()); + UserDto user = db.users().insertUser(u -> u.setHomepageType("APPLICATION").setHomepageParameter(application.uuid())); + userSessionRule.logIn(user.getLogin()); + + CurrentWsResponse response = ws.newRequest().executeProtobuf(CurrentWsResponse.class); + + assertThat(response.getHomepage().getType().toString()).isEqualTo("PROJECTS"); + } + + @Test + public void fallback_to_PROJECTS_when_on_SonarQube() { + UserDto user = db.users().insertUser(u -> u.setHomepageType("PROJECT").setHomepageParameter("not-existing-project-uuid")); + userSessionRule.logIn(user.getLogin()); + + CurrentWsResponse response = ws.newRequest().executeProtobuf(CurrentWsResponse.class); + + assertThat(response.getHomepage().getType().toString()).isEqualTo("PROJECTS"); + } + + @Test + public void fallback_to_MY_PROJECTS_when_on_SonarCloud() { + onSonarCloud(); + UserDto user = db.users().insertUser(u -> u.setHomepageType("PROJECT").setHomepageParameter("not-existing-project-uuid")); + userSessionRule.logIn(user.getLogin()); + + CurrentWsResponse response = ws.newRequest().executeProtobuf(CurrentWsResponse.class); + + assertThat(response.getHomepage().getType().toString()).isEqualTo("MY_PROJECTS"); + } + + private void onSonarCloud() { + settings.setProperty("sonar.sonarcloud.enabled", true); + } + + private void withGovernancePlugin(){ + when(pluginRepository.hasPlugin("governance")).thenReturn(true); + } + + private void withoutGovernancePlugin(){ + when(pluginRepository.hasPlugin("governance")).thenReturn(false); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/SetHomepageActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/SetHomepageActionTest.java index 4d221650f45..92e8444c54b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/ws/SetHomepageActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/SetHomepageActionTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.user.ws; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -35,17 +34,8 @@ import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.TestResponse; import org.sonar.server.ws.WsActionTester; -import static java.util.Arrays.asList; import static org.apache.http.HttpStatus.SC_NO_CONTENT; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.server.user.ws.HomepageTypes.Type.ISSUES; -import static org.sonar.server.user.ws.HomepageTypes.Type.MY_ISSUES; -import static org.sonar.server.user.ws.HomepageTypes.Type.MY_PROJECTS; -import static org.sonar.server.user.ws.HomepageTypes.Type.ORGANIZATION; -import static org.sonar.server.user.ws.HomepageTypes.Type.PROJECT; -import static org.sonar.server.user.ws.HomepageTypes.Type.PROJECTS; import static org.sonar.server.user.ws.SetHomepageAction.PARAM_COMPONENT; import static org.sonar.server.user.ws.SetHomepageAction.PARAM_TYPE; @@ -61,15 +51,8 @@ public class SetHomepageActionTest { public ExpectedException expectedException = ExpectedException.none(); private DbClient dbClient = db.getDbClient(); - private HomepageTypes homepageTypes = mock(HomepageTypes.class); - private WsActionTester ws; - - @Before - public void setUp() { - when(homepageTypes.getTypes()).thenReturn(asList(PROJECT, ORGANIZATION, MY_ISSUES, MY_PROJECTS)); - ws = new WsActionTester(new SetHomepageAction(userSession, dbClient, TestComponentFinder.from(db))); - } + private WsActionTester ws = new WsActionTester(new SetHomepageAction(userSession, dbClient, TestComponentFinder.from(db))); @Test public void verify_definition() { @@ -163,7 +146,7 @@ public class SetHomepageActionTest { } @Test - public void set_sonarcloud_my_issues_homepage() { + public void set_SonarCloud_my_issues_homepage() { UserDto user = db.users().insertUser(); userSession.logIn(user); @@ -179,10 +162,7 @@ public class SetHomepageActionTest { } @Test - public void set_sonarqube_issues_homepage() { - - when(homepageTypes.getTypes()).thenReturn(asList(PROJECT, ORGANIZATION, ISSUES, PROJECTS)); - ws = new WsActionTester(new SetHomepageAction(userSession, dbClient, TestComponentFinder.from(db))); + public void set_SonarQube_issues_homepage() { UserDto user = db.users().insertUser(); userSession.logIn(user); @@ -199,7 +179,7 @@ public class SetHomepageActionTest { } @Test - public void set_sonarcloud_my_projects_homepage() { + public void set_SonarCloud_my_projects_homepage() { UserDto user = db.users().insertUser(); userSession.logIn(user); @@ -215,7 +195,7 @@ public class SetHomepageActionTest { } @Test - public void set_sonarqube_projects_homepage() { + public void set_SonarQube_projects_homepage() { UserDto user = db.users().insertUser(); userSession.logIn(user); @@ -327,6 +307,21 @@ public class SetHomepageActionTest { .execute(); } + @Test + public void fail_when_invalid_homepage_type() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + + expectedException.expect(IllegalArgumentException.class); + expectedException + .expectMessage("Value of parameter 'type' (PIPO) must be one of: [PROJECT, PROJECTS, ISSUES, PORTFOLIOS, PORTFOLIO, APPLICATION, MY_PROJECTS, MY_ISSUES, ORGANIZATION]"); + + ws.newRequest() + .setMethod("POST") + .setParam(PARAM_TYPE, "PIPO") + .execute(); + } + @Test public void fail_for_anonymous() { userSession.anonymous(); -- 2.39.5