Browse Source

SONAR-10426 Add homepage default when db is inconsistent

tags/7.5
Guillaume Jambet 6 years ago
parent
commit
f1a7b51a44

+ 6
- 2
server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java View File

@@ -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

+ 3
- 1
server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java View File

@@ -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);
}

+ 219
- 209
server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml View File

@@ -3,216 +3,226 @@

<mapper namespace="org.sonar.db.user.UserMapper">

<sql id="userColumns">
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"
</sql>

<select id="selectByLogin" parameterType="String" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.login=#{login}
</select>

<select id="selectNullableByScmAccountOrLoginOrEmail" parameterType="map" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE
u.login=#{scmAccount}
OR u.email=#{scmAccount}
OR u.scm_accounts like #{likeScmAccount}
</select>

<select id="selectUser" parameterType="int" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.id=#{id}
</select>

<select id="selectUserByLogin" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.login=#{id} AND u.active=${_true}
</select>

<select id="selectByLogins" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.login in
<foreach collection="list" open="(" close=")" item="login" separator=",">
#{login}
</foreach>
</select>

<select id="scrollAll" resultType="User" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
select <include refid="userColumns"/>
from users u
</select>

<select id="selectByIds" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</select>

<select id="selectUsers" parameterType="map" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
<where>
<if test="logins != null and logins.size() > 0">
u.login IN
<foreach item="login" index="index" collection="logins" open="(" separator="," close=")">
#{login}
<sql id="userColumns">
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"
</sql>

<select id="selectByLogin" parameterType="String" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.login=#{login}
</select>

<select id="selectNullableByScmAccountOrLoginOrEmail" parameterType="map" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE
u.login=#{scmAccount}
OR u.email=#{scmAccount}
OR u.scm_accounts like #{likeScmAccount}
</select>

<select id="selectUser" parameterType="int" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.id=#{id}
</select>

<select id="selectUserByLogin" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.login=#{id} AND u.active=${_true}
</select>

<select id="selectByLogins" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.login in
<foreach collection="list" open="(" close=")" item="login" separator=",">
#{login}
</foreach>
</if>
<if test="includeDeactivated==false">
</select>

<select id="scrollAll" resultType="User" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
select
<include refid="userColumns"/>
from users u
</select>

<select id="selectByIds" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE u.id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</select>

<select id="selectUsers" parameterType="map" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
<where>
<if test="logins != null and logins.size() > 0">
u.login IN
<foreach item="login" index="index" collection="logins" open="(" separator="," close=")">
#{login}
</foreach>
</if>
<if test="includeDeactivated==false">
AND u.active=${_true}
</if>
<if test="searchText != null">
AND (u.login LIKE #{searchTextSql} ESCAPE '/' OR u.name LIKE #{searchTextSql} ESCAPE '/')
</if>
<if test="mustBeRoot != null and mustBeRoot==true">
AND u.is_root = ${_true}
</if>
<if test="mustBeRoot != null and mustBeRoot==false">
AND u.is_root = ${_false}
</if>
</where>
ORDER BY u.name
</select>

<select id="selectByEmail" parameterType="String" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE lower(u.email)=#{email, jdbcType=VARCHAR}
AND u.active=${_true}
</if>
<if test="searchText != null">
AND (u.login LIKE #{searchTextSql} ESCAPE '/' OR u.name LIKE #{searchTextSql} ESCAPE '/')
</if>
<if test="mustBeRoot != null and mustBeRoot==true">
AND u.is_root = ${_true}
</if>
<if test="mustBeRoot != null and mustBeRoot==false">
AND u.is_root = ${_false}
</if>
</where>
ORDER BY u.name
</select>

<select id="selectByEmail" parameterType="String" resultType="User">
SELECT
<include refid="userColumns"/>
FROM users u
WHERE lower(u.email)=#{email, jdbcType=VARCHAR}
AND u.active=${_true}
</select>

<select id="countRootUsersButLogin" parameterType="String" resultType="long">
select
count(1)
from
users u
where
u.active = ${_true}
and u.is_root = ${_true}
and u.login &lt;&gt; #{login}
</select>

<update id="deactivateUser" parameterType="map">
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>

<update id="clearHomepage" parameterType="map">
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>

<update id="setRoot">
update users set
is_root = #{root, jdbcType=BOOLEAN},
updated_at = #{now, jdbcType=BIGINT}
where
login = #{login, jdbcType=VARCHAR}
and active = ${_true}
</update>

<insert id="insert" parameterType="map" keyColumn="id" useGeneratedKeys="true" keyProperty="user.id">
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}
)
</insert>

<update id="update" parameterType="map">
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>
</select>

<select id="countRootUsersButLogin" parameterType="String" resultType="long">
select
count(1)
from
users u
where
u.active = ${_true}
and u.is_root = ${_true}
and u.login &lt;&gt; #{login}
</select>

<update id="deactivateUser" parameterType="map">
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>

<update id="clearHomepages" parameterType="map">
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>

<update id="clearHomepage" parameterType="map">
update users set
homepage_type = null,
homepage_parameter = null,
updated_at = #{now, jdbcType=BIGINT}
where
login = #{login, jdbcType=VARCHAR}
</update>

<update id="setRoot">
update users set
is_root = #{root, jdbcType=BOOLEAN},
updated_at = #{now, jdbcType=BIGINT}
where
login = #{login, jdbcType=VARCHAR}
and active = ${_true}
</update>

<insert id="insert" parameterType="map" keyColumn="id" useGeneratedKeys="true" keyProperty="user.id">
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}
)
</insert>

<update id="update" parameterType="map">
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>

</mapper>

+ 16
- 0
server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java View File

@@ -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());

+ 76
- 33
server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java View File

@@ -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<CurrentWsResponse.Homepage> 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<CurrentWsResponse.Homepage> projectHomepage(DbSession dbSession, UserDto user) {
Optional<ComponentDto> 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<CurrentWsResponse.Homepage> applicationAndPortfolioHomepage(DbSession dbSession, UserDto user) {
Optional<ComponentDto> 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<CurrentWsResponse.Homepage> organizationHomepage(DbSession dbSession, UserDto user) {
Optional<OrganizationDto> 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;
}

}

+ 2
- 2
server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypes.java View File

@@ -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
}

+ 11
- 6
server/sonar-server/src/main/java/org/sonar/server/user/ws/HomepageTypesImpl.java View File

@@ -50,7 +50,6 @@ public class HomepageTypesImpl implements HomepageTypes, Startable {
private final DbClient dbClient;

private List<Type> 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

+ 84
- 16
server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java View File

@@ -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);
}

}

+ 20
- 25
server/sonar-server/src/test/java/org/sonar/server/user/ws/SetHomepageActionTest.java View File

@@ -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();

Loading…
Cancel
Save