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