private String key;
private Long value;
+ public KeyLongValue() {
+ // for MyBatis
+ }
+
+ public KeyLongValue(String key, Long value) {
+ this.key = key;
+ this.value = value;
+ }
+
public String getKey() {
return key;
}
*/
package org.sonar.db.component;
+import java.util.Date;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Stream;
private final Set<String> componentUuids;
private final Set<String> componentKeys;
private final Long analyzedBefore;
+ private final Long analyzedAfter;
+ private final Date createdAfter;
private final boolean onProvisionedOnly;
private ComponentQuery(Builder builder) {
this.componentKeys = builder.componentKeys;
this.isPrivate = builder.isPrivate;
this.analyzedBefore = builder.analyzedBefore;
+ this.analyzedAfter = builder.analyzedAfter;
+ this.createdAfter = builder.createdAfter;
this.onProvisionedOnly = builder.onProvisionedOnly;
}
return analyzedBefore;
}
+ @CheckForNull
+ public Long getAnalyzedAfter() {
+ return analyzedAfter;
+ }
+
+ @CheckForNull
+ public Date getCreatedAfter() {
+ return createdAfter;
+ }
+
public boolean isOnProvisionedOnly() {
return onProvisionedOnly;
}
private Set<String> componentUuids;
private Set<String> componentKeys;
private Long analyzedBefore;
+ private Long analyzedAfter;
+ private Date createdAfter;
private boolean onProvisionedOnly = false;
public Builder setNameOrKeyQuery(@Nullable String nameOrKeyQuery) {
return this;
}
+ /**
+ * Filter on date of last analysis. On projects, all branches and pull requests are taken into
+ * account. For example the analysis of a short-lived branch is included in the filter
+ * even if the main branch has never been analyzed.
+ */
+ public Builder setAnalyzedAfter(@Nullable Long l) {
+ this.analyzedAfter = l;
+ return this;
+ }
+
+ public Builder setCreatedAfter(@Nullable Date l) {
+ this.createdAfter = l;
+ return this;
+ }
+
public Builder setOnProvisionedOnly(boolean onProvisionedOnly) {
this.onProvisionedOnly = onProvisionedOnly;
return this;
import org.sonar.api.utils.System2;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
+import org.sonar.db.KeyLongValue;
import org.sonar.db.Pagination;
import org.sonar.db.qualitygate.QGateWithOrgDto;
import org.sonar.db.user.GroupDto;
return getMapper(dbSession).countByQuery(organizationQuery);
}
+ public List<KeyLongValue> countTeamsByMembers(DbSession dbSession) {
+ return getMapper(dbSession).countTeamsByMembers();
+ }
+
+ public List<KeyLongValue> countTeamsByProjects(DbSession dbSession) {
+ return getMapper(dbSession).countTeamsByProjects();
+ }
+
public List<OrganizationDto> selectByQuery(DbSession dbSession, OrganizationQuery organizationQuery, Pagination pagination) {
requireNonNull(organizationQuery, "organizationQuery can't be null");
return getMapper(dbSession).selectByQuery(organizationQuery, pagination);
import java.util.List;
import javax.annotation.CheckForNull;
import org.apache.ibatis.annotations.Param;
+import org.sonar.db.KeyLongValue;
import org.sonar.db.Pagination;
public interface OrganizationMapper {
int countByQuery(@Param("query") OrganizationQuery organizationQuery);
+ List<KeyLongValue> countTeamsByMembers();
+
+ List<KeyLongValue> countTeamsByProjects();
+
List<OrganizationDto> selectByQuery(@Param("query") OrganizationQuery organizationQuery,
@Param("pagination") Pagination pagination);
import static org.sonar.core.util.stream.MoreCollectors.toSet;
public class OrganizationQuery {
- private static final OrganizationQuery NO_QUERY = newOrganizationQueryBuilder().build();
+ private static final OrganizationQuery NO_FILTER = newOrganizationQueryBuilder().build();
private final Set<String> keys;
private final Integer userId;
+ private final boolean onlyTeam;
+ private final boolean onlyPersonal;
+ private final boolean withAnalyses;
private OrganizationQuery(Builder builder) {
this.keys = builder.keys;
this.userId = builder.member;
+ this.onlyPersonal = builder.onlyPersonal;
+ this.onlyTeam = builder.onlyTeam;
+ if (this.onlyPersonal && this.onlyTeam) {
+ throw new IllegalArgumentException("Only one of onlyPersonal and onlyTeam can be true");
+ }
+ this.withAnalyses = builder.withAnalyses;
}
@CheckForNull
return userId;
}
+ public boolean isOnlyTeam() {
+ return onlyTeam;
+ }
+
+ public boolean isOnlyPersonal() {
+ return onlyPersonal;
+ }
+
+ public boolean isWithAnalyses() {
+ return withAnalyses;
+ }
+
public static OrganizationQuery returnAll() {
- return NO_QUERY;
+ return NO_FILTER;
}
public static Builder newOrganizationQueryBuilder() {
public static class Builder {
private Set<String> keys;
+ @Nullable
private Integer member;
+ private boolean onlyTeam = false;
+ private boolean onlyPersonal = false;
+ private boolean withAnalyses = false;
private Builder() {
// use static factory method
return this;
}
+ public Builder setOnlyTeam() {
+ this.onlyTeam = true;
+ return this;
+ }
+
+ public Builder setOnlyPersonal() {
+ this.onlyPersonal = true;
+ return this;
+ }
+
+ public Builder setWithAnalyses() {
+ this.withAnalyses = true;
+ return this;
+ }
+
public OrganizationQuery build() {
return new OrganizationQuery(this);
}
import org.sonar.core.util.UuidFactory;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
+import org.sonar.db.KeyLongValue;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
return mapper(dbSession).countRootUsersButLogin(login);
}
+ /**
+ * Includes deactivated users
+ */
+ public long countTotalUsers(DbSession dbSession) {
+ return mapper(dbSession).countTotalUsers();
+ }
+
+ public long countTeamUsers(DbSession dbSession) {
+ return mapper(dbSession).countTeamUsers();
+ }
+
+ public long countPersonalUsers(DbSession dbSession) {
+ return mapper(dbSession).countPersonalUsers();
+ }
+
+ public long countPersonalUsersWithZeroProjects(DbSession dbSession) {
+ return mapper(dbSession).countPersonalUsersWithZeroProjects();
+ }
+
+ public long countNewUsersSince(DbSession dbSession, long since) {
+ return mapper(dbSession).countNewUsersSince(since);
+ }
+
+ public long countActiveUsers(DbSession dbSession) {
+ return mapper(dbSession).countActiveUsers();
+ }
+
+ public List<KeyLongValue> countUsersByIdentityProviders(DbSession dbSession) {
+ return mapper(dbSession).countUsersByIdentityProviders();
+ }
+
public UserDto insert(DbSession session, UserDto dto) {
long now = system2.now();
mapper(session).insert(dto.setUuid(uuidFactory.create()).setCreatedAt(now).setUpdatedAt(now));
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.ResultHandler;
import org.sonar.api.user.UserQuery;
+import org.sonar.db.KeyLongValue;
public interface UserMapper {
*/
long countRootUsersButLogin(@Param("login") String login);
+ long countTotalUsers();
+
+ long countTeamUsers();
+
+ long countPersonalUsers();
+
+ long countPersonalUsersWithZeroProjects();
+
+ long countNewUsersSince(@Param("since") long since);
+
+ long countActiveUsers();
+
+ List<KeyLongValue> countUsersByIdentityProviders();
+
void insert(@Param("user") UserDto userDto);
void update(@Param("user") UserDto userDto);
where pb.project_uuid = p.uuid
)
</if>
+ <if test="query.analyzedAfter != null">
+ and (
+ exists(
+ -- branches of projects
+ select 1 from snapshots s
+ inner join project_branches pb on s.component_uuid = pb.uuid
+ where pb.project_uuid = p.uuid
+ and s.status='P'
+ and s.islast = ${_true}
+ and s.created_at >= #{query.analyzedAfter,jdbcType=BIGINT}
+ )
+ or exists (
+ -- applications, portfolios
+ select 1 from snapshots s
+ where s.component_uuid = p.uuid
+ and s.status='P'
+ and s.islast = ${_true}
+ and s.created_at >= #{query.analyzedAfter,jdbcType=BIGINT}
+ )
+ )
+ </if>
+ <if test="query.createdAfter != null">
+ and p.created_at >= #{query.createdAfter,jdbcType=TIMESTAMP}
+ </if>
</sql>
<select id="selectDescendants" resultType="Component">
#{key, jdbcType=VARCHAR}
</foreach>
</if>
+ <if test="query.onlyTeam">
+ and not exists(
+ select 1
+ from users u
+ where u.organization_uuid = org.uuid
+ and u.active = ${_true}
+ )
+ </if>
+ <if test="query.onlyPersonal">
+ and exists(
+ select 1
+ from users u
+ where u.organization_uuid = org.uuid
+ and u.active = ${_true}
+ )
+ </if>
+ <if test="query.withAnalyses">
+ and exists(
+ select 1
+ from snapshots s
+ inner join projects p on p.uuid = s.component_uuid
+ where p.organization_uuid = org.uuid
+ and p.enabled = ${_true}
+ and s.islast = ${_true}
+ )
+ </if>
</where>
</sql>
+ <select id="countTeamsByMembers" resultType="org.sonar.db.KeyLongValue">
+ select range as "key", count(1) as "value"
+ from (
+ select case
+ when nb = 0 then '0'
+ when nb = 1 then '1'
+ when nb >= 2 and nb <= 4 then '2-4'
+ when nb >= 5 and nb <= 9 then '5-9'
+ when nb >= 10 and nb <= 24 then '10-24'
+ else '25+'
+ end as range
+ from (
+ select o.uuid, count(om.user_id) as nb
+ from organizations o
+ left join organization_members om on om.organization_uuid = o.uuid
+ where not exists(
+ select 1
+ from users u
+ where u.organization_uuid = o.uuid
+ and u.active = ${_true}
+ )
+ group by o.uuid
+ ) alias1
+ ) alias2
+ group by range
+ </select>
+
+ <select id="countTeamsByProjects" resultType="org.sonar.db.KeyLongValue">
+ select range as "key", count(1) as "value"
+ from (
+ select case
+ when nb = 0 then '0'
+ when nb = 1 then '1'
+ when nb >= 2 and nb <= 4 then '2-4'
+ when nb >= 5 and nb <= 9 then '5-9'
+ when nb >= 10 and nb <= 24 then '10-24'
+ else '25+'
+ end as range
+ from (
+ select o.uuid, count(p.uuid) as nb
+ from organizations o
+ left join projects p on p.organization_uuid = o.uuid
+ where not exists(
+ select 1
+ from users u
+ where u.organization_uuid = o.uuid
+ and u.active = ${_true}
+ )
+ group by o.uuid
+ ) alias1
+ ) alias2
+ group by range
+ </select>
+
<select id="selectByPermission" parameterType="map" resultType="Organization">
select
<include refid="selectColumns"/>
and u.login <> #{login}
</select>
+ <select id="countTotalUsers" resultType="long">
+ select count(1) from users
+ </select>
+
+ <select id="countTeamUsers" resultType="long">
+ select count(1)
+ from users
+ where active = ${_true}
+ and exists (
+ select 1
+ from organization_members om
+ where om.user_id = users.id
+ and (users.organization_uuid is null or om.organization_uuid != users.organization_uuid)
+ )
+ </select>
+
+ <select id="countPersonalUsers" resultType="long">
+ select count(1)
+ from users
+ where active = ${_true}
+ and organization_uuid is not null
+ and not exists (
+ select 1
+ from organization_members om
+ where om.user_id = users.id
+ and om.organization_uuid != users.organization_uuid
+ )
+ </select>
+
+ <select id="countPersonalUsersWithZeroProjects" resultType="long">
+ select count(1)
+ from users
+ where active = ${_true}
+ and organization_uuid is not null
+ and not exists (
+ select 1
+ from organization_members om
+ where om.user_id = users.id
+ and om.organization_uuid != users.organization_uuid
+ )
+ and not exists (
+ select 1
+ from projects p
+ where p.organization_uuid = users.organization_uuid
+ )
+ </select>
+
+ <select id="countNewUsersSince" parameterType="long" resultType="long">
+ select count(1)
+ from users
+ where created_at > #{since,jdbcType=BIGINT}
+ </select>
+
+ <select id="countActiveUsers" resultType="long">
+ select count(1)
+ from users
+ where active = ${_true}
+ </select>
+
+ <select id="countUsersByIdentityProviders" resultType="org.sonar.db.KeyLongValue">
+ select external_identity_provider as "key", count(1) as "value"
+ from users
+ where active = ${_true}
+ group by external_identity_provider
+ </select>
+
<update id="deactivateUser" parameterType="map">
update users set
active = ${_false},
import static org.assertj.core.api.Assertions.tuple;
import static org.assertj.guava.api.Assertions.assertThat;
import static org.sonar.api.resources.Qualifiers.APP;
+import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.api.utils.DateUtils.parseDate;
+import static org.sonar.db.component.ComponentTesting.newBranchDto;
import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.db.component.ComponentTreeQuery.Strategy.CHILDREN;
import static org.sonar.db.component.ComponentTreeQuery.Strategy.LEAVES;
-import static org.sonar.db.component.SnapshotTesting.newAnalysis;
@RunWith(DataProviderRunner.class)
public class ComponentDaoTest {
@DataProvider
public static Object[][] oneOrMoreProjects() {
- return new Object[][] {
+ return new Object[][]{
{1},
{1 + new Random().nextInt(10)}
};
@DataProvider
public static Object[][] portfolioOrApplicationRootViewQualifier() {
- return new Object[][] {
+ return new Object[][]{
{Qualifiers.VIEW},
{Qualifiers.APP},
};
.setEnabled(false));
SnapshotDto analyzedPortfolio = db.components().insertProjectAndSnapshot(ComponentTesting.newView(organization));
- Supplier<ComponentQuery.Builder> query = () -> ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT).setOnProvisionedOnly(true);
+ Supplier<ComponentQuery.Builder> query = () -> ComponentQuery.builder().setQualifiers(PROJECT).setOnProvisionedOnly(true);
assertThat(underTest.selectByQuery(dbSession, organization.getUuid(), query.get().build(), 0, 10))
.extracting(ComponentDto::uuid)
.containsOnly(provisionedProject.uuid());
// filter on qualifiers
assertThat(underTest.selectByQuery(dbSession, organization.getUuid(), query.get().setQualifiers("XXX").build(), 0, 10)).isEmpty();
- assertThat(underTest.selectByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(Qualifiers.PROJECT, "XXX").build(), 0, 10))
+ assertThat(underTest.selectByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(PROJECT, "XXX").build(), 0, 10))
.extracting(ComponentDto::uuid)
.containsOnly(provisionedProject.uuid());
- assertThat(underTest.selectByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW).build(), 0, 10))
+ assertThat(underTest.selectByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(PROJECT, Qualifiers.VIEW).build(), 0, 10))
.extracting(ComponentDto::uuid)
.containsOnly(provisionedProject.uuid(), provisionedPortfolio.uuid());
@Test
public void selectByQuery_onProvisionedOnly_filters_projects_with_analysis_on_branch() {
Supplier<ComponentQuery.Builder> query = () -> ComponentQuery.builder()
- .setQualifiers(Qualifiers.PROJECT)
+ .setQualifiers(PROJECT)
.setOnProvisionedOnly(true);
// the project does not have any analysis
db.components().insertProjectAndSnapshot(ComponentTesting.newView(organization));
Supplier<ComponentQuery.Builder> query = () -> ComponentQuery.builder().setOnProvisionedOnly(true);
- assertThat(underTest.countByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(Qualifiers.PROJECT).build())).isEqualTo(1);
+ assertThat(underTest.countByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(PROJECT).build())).isEqualTo(1);
assertThat(underTest.countByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(Qualifiers.VIEW).build())).isEqualTo(0);
- assertThat(underTest.countByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW).build())).isEqualTo(1);
+ assertThat(underTest.countByQuery(dbSession, organization.getUuid(), query.get().setQualifiers(PROJECT, Qualifiers.VIEW).build())).isEqualTo(1);
}
@Test
public void countByQuery_throws_IAE_if_too_many_component_ids() {
Set<Long> ids = LongStream.range(0L, 1_010L).boxed().collect(toSet());
ComponentQuery.Builder query = ComponentQuery.builder()
- .setQualifiers(Qualifiers.PROJECT)
+ .setQualifiers(PROJECT)
.setComponentIds(ids);
assertThatCountByQueryThrowsIAE(query, "Too many component ids in query");
public void countByQuery_throws_IAE_if_too_many_component_keys() {
Set<String> keys = IntStream.range(0, 1_010).mapToObj(String::valueOf).collect(toSet());
ComponentQuery.Builder query = ComponentQuery.builder()
- .setQualifiers(Qualifiers.PROJECT)
+ .setQualifiers(PROJECT)
.setComponentKeys(keys);
assertThatCountByQueryThrowsIAE(query, "Too many component keys in query");
public void countByQuery_throws_IAE_if_too_many_component_uuids() {
Set<String> uuids = IntStream.range(0, 1_010).mapToObj(String::valueOf).collect(toSet());
ComponentQuery.Builder query = ComponentQuery.builder()
- .setQualifiers(Qualifiers.PROJECT)
+ .setQualifiers(PROJECT)
.setComponentUuids(uuids);
assertThatCountByQueryThrowsIAE(query, "Too many component UUIDs in query");
public void selectByQuery_throws_IAE_if_too_many_component_ids() {
Set<Long> ids = LongStream.range(0L, 1_010L).boxed().collect(toSet());
ComponentQuery.Builder query = ComponentQuery.builder()
- .setQualifiers(Qualifiers.PROJECT)
+ .setQualifiers(PROJECT)
.setComponentIds(ids);
assertThatSelectByQueryThrowsIAE(query, "Too many component ids in query");
public void selectByQuery_throws_IAE_if_too_many_component_keys() {
Set<String> keys = IntStream.range(0, 1_010).mapToObj(String::valueOf).collect(toSet());
ComponentQuery.Builder query = ComponentQuery.builder()
- .setQualifiers(Qualifiers.PROJECT)
+ .setQualifiers(PROJECT)
.setComponentKeys(keys);
assertThatSelectByQueryThrowsIAE(query, "Too many component keys in query");
public void selectByQuery_throws_IAE_if_too_many_component_uuids() {
Set<String> uuids = IntStream.range(0, 1_010).mapToObj(String::valueOf).collect(toSet());
ComponentQuery.Builder query = ComponentQuery.builder()
- .setQualifiers(Qualifiers.PROJECT)
+ .setQualifiers(PROJECT)
.setComponentUuids(uuids);
assertThatSelectByQueryThrowsIAE(query, "Too many component UUIDs in query");
db.components().insertProjectAndSnapshot(newPrivateProjectDto(organizationDto).setName("project-" + i));
}
- ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("oJect").setQualifiers(Qualifiers.PROJECT).build();
+ ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("oJect").setQualifiers(PROJECT).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 1, 3);
int count = underTest.countByQuery(dbSession, query);
public void selectByQuery_name_with_special_characters() {
db.components().insertProjectAndSnapshot(newPrivateProjectDto(db.getDefaultOrganization()).setName("project-\\_%/-name"));
- ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("-\\_%/-").setQualifiers(Qualifiers.PROJECT).build();
+ ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("-\\_%/-").setQualifiers(PROJECT).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
assertThat(result).hasSize(1);
db.components().insertProjectAndSnapshot(newPrivateProjectDto(db.organizations().insert()).setDbKey("project-_%-key"));
db.components().insertProjectAndSnapshot(newPrivateProjectDto(db.organizations().insert()).setDbKey("project-key-that-does-not-match"));
- ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("project-_%-key").setQualifiers(Qualifiers.PROJECT).build();
+ ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("project-_%-key").setQualifiers(PROJECT).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
assertThat(result).hasSize(1);
ComponentQuery query = ComponentQuery.builder()
.setNameOrKeyQuery("JECT-K")
.setPartialMatchOnKey(true)
- .setQualifiers(Qualifiers.PROJECT).build();
+ .setQualifiers(PROJECT).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
assertThat(result).hasSize(1);
db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization()).setDbKey("java-project-key").setLanguage("java"));
db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization()).setDbKey("cpp-project-key").setLanguage("cpp"));
- ComponentQuery query = ComponentQuery.builder().setLanguage("java").setQualifiers(Qualifiers.PROJECT).build();
+ ComponentQuery query = ComponentQuery.builder().setLanguage("java").setQualifiers(PROJECT).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
assertThat(result).hasSize(1);
}
@Test
- public void selectByQuery_filter_on_last_analysis_date() {
+ public void selectByQuery_filter_last_analysis_date() {
long aLongTimeAgo = 1_000_000_000L;
long recentTime = 3_000_000_000L;
- ComponentDto oldProject = db.components().insertPublicProject();
- db.getDbClient().snapshotDao().insert(dbSession, newAnalysis(oldProject).setCreatedAt(aLongTimeAgo));
- ComponentDto recentProject = db.components().insertPublicProject();
- db.getDbClient().snapshotDao().insert(dbSession, newAnalysis(recentProject).setCreatedAt(recentTime));
- db.getDbClient().snapshotDao().insert(dbSession, newAnalysis(recentProject).setCreatedAt(aLongTimeAgo).setLast(false));
- ComponentQuery.Builder query = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT);
-
- assertThat(underTest.selectByQuery(dbSession, query.setAnalyzedBefore(recentTime).build(), 0, 10)).extracting(ComponentDto::getKey)
- .containsExactlyInAnyOrder(oldProject.getKey());
- assertThat(underTest.selectByQuery(dbSession, query.setAnalyzedBefore(aLongTimeAgo).build(), 0, 10)).extracting(ComponentDto::getKey)
+ ComponentDto oldProject = db.components().insertPrivateProject();
+ db.components().insertSnapshot(oldProject, s -> s.setCreatedAt(aLongTimeAgo));
+ ComponentDto recentProject = db.components().insertPrivateProject();
+ db.components().insertSnapshot(recentProject, s -> s.setCreatedAt(recentTime).setLast(true));
+ db.components().insertSnapshot(recentProject, s -> s.setCreatedAt(aLongTimeAgo).setLast(false));
+
+ // before date
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedBefore(recentTime), 0, 10))
+ .containsExactlyInAnyOrder(oldProject.uuid());
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedBefore(aLongTimeAgo), 0, 10))
.isEmpty();
- assertThat(underTest.selectByQuery(dbSession, query.setAnalyzedBefore(recentTime + 1_000L).build(), 0, 10)).extracting(ComponentDto::getKey)
- .containsExactlyInAnyOrder(oldProject.getKey(), recentProject.getKey());
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedBefore(recentTime + 1_000L), 0, 10))
+ .containsExactlyInAnyOrder(oldProject.uuid(), recentProject.uuid());
+
+ // after date
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedAfter(recentTime - 1_000L), 0, 10))
+ .containsExactlyInAnyOrder(recentProject.uuid());
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedAfter(recentTime + 1_000L), 0, 10))
+ .isEmpty();
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedAfter(aLongTimeAgo), 0, 10))
+ .containsExactlyInAnyOrder(oldProject.uuid(), recentProject.uuid());
+ }
+
+ @Test
+ public void selectByQuery_filter_last_analysis_date_on_non_main_branches() {
+ long aLongTimeAgo = 1_000_000_000L;
+ long recentTime = 3_000_000_000L;
+ // project with only a non-main and old analyzed branch
+ ComponentDto oldProject = db.components().insertMainBranch();
+ ComponentDto oldProjectBranch = db.components().insertProjectBranch(oldProject, newBranchDto(oldProject).setBranchType(BranchType.SHORT));
+ db.components().insertSnapshot(oldProjectBranch, s -> s.setLast(true).setCreatedAt(aLongTimeAgo));
+
+ // project with only a old main branch and a recent non-main branch
+ ComponentDto recentProject = db.components().insertMainBranch();
+ ComponentDto recentProjectBranch = db.components().insertProjectBranch(recentProject, newBranchDto(recentProject).setBranchType(BranchType.SHORT));
+ db.components().insertSnapshot(recentProjectBranch, s -> s.setCreatedAt(recentTime).setLast(true));
+ db.components().insertSnapshot(recentProjectBranch, s -> s.setCreatedAt(aLongTimeAgo).setLast(false));
+
+ // after date
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedAfter(recentTime - 1_000L), 0, 10))
+ .containsExactlyInAnyOrder(recentProject.uuid());
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedAfter(recentTime + 1_000L), 0, 10))
+ .isEmpty();
+ assertThat(selectProjectUuidsByQuery(q -> q.setAnalyzedAfter(aLongTimeAgo), 0, 10))
+ .containsExactlyInAnyOrder(oldProject.uuid(), recentProject.uuid());
+ }
+
+ @Test
+ public void selectByQuery_filter_created_at() {
+ ComponentDto project1 = db.components().insertPrivateProject(p -> p.setCreatedAt(parseDate("2018-02-01")));
+ ComponentDto project2 = db.components().insertPrivateProject(p -> p.setCreatedAt(parseDate("2018-06-01")));
+
+ assertThat(selectProjectUuidsByQuery(q -> q.setCreatedAfter(parseDate("2017-12-01")), 0, 10))
+ .containsExactlyInAnyOrder(project1.uuid(), project2.uuid());
+ assertThat(selectProjectUuidsByQuery(q -> q.setCreatedAfter(parseDate("2018-02-20")), 0, 10))
+ .containsExactlyInAnyOrder(project2.uuid());
+ assertThat(selectProjectUuidsByQuery(q -> q.setCreatedAfter(parseDate("2019-01-01")), 0, 10))
+ .isEmpty();
+ }
+
+ private List<String> selectProjectUuidsByQuery(Consumer<ComponentQuery.Builder> query, int offset, int limit) {
+ ComponentQuery.Builder builder = ComponentQuery.builder().setQualifiers(PROJECT);
+ query.accept(builder);
+ return underTest.selectByQuery(dbSession, builder.build(), offset, limit)
+ .stream()
+ .map(ComponentDto::uuid)
+ .collect(Collectors.toList());
}
@Test
db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization()).setDbKey("private-key"));
db.components().insertComponent(ComponentTesting.newPublicProjectDto(db.getDefaultOrganization()).setDbKey("public-key"));
- ComponentQuery privateProjectsQuery = ComponentQuery.builder().setPrivate(true).setQualifiers(Qualifiers.PROJECT).build();
- ComponentQuery publicProjectsQuery = ComponentQuery.builder().setPrivate(false).setQualifiers(Qualifiers.PROJECT).build();
- ComponentQuery allProjectsQuery = ComponentQuery.builder().setPrivate(null).setQualifiers(Qualifiers.PROJECT).build();
+ ComponentQuery privateProjectsQuery = ComponentQuery.builder().setPrivate(true).setQualifiers(PROJECT).build();
+ ComponentQuery publicProjectsQuery = ComponentQuery.builder().setPrivate(false).setQualifiers(PROJECT).build();
+ ComponentQuery allProjectsQuery = ComponentQuery.builder().setPrivate(null).setQualifiers(PROJECT).build();
assertThat(underTest.selectByQuery(dbSession, privateProjectsQuery, 0, 10)).extracting(ComponentDto::getDbKey).containsExactly("private-key");
assertThat(underTest.selectByQuery(dbSession, publicProjectsQuery, 0, 10)).extracting(ComponentDto::getDbKey).containsExactly("public-key");
@Test
public void selectByQuery_on_empty_list_of_component_id() {
db.components().insertPrivateProject();
- ComponentQuery dbQuery = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT).setComponentIds(emptySet()).build();
+ ComponentQuery dbQuery = ComponentQuery.builder().setQualifiers(PROJECT).setComponentIds(emptySet()).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, dbQuery, 0, 10);
int count = underTest.countByQuery(dbSession, dbQuery);
ComponentDto jdk8 = db.components().insertComponent(newPrivateProjectDto(organizationDto));
ComponentDto cLang = db.components().insertComponent(newPrivateProjectDto(organizationDto));
- ComponentQuery query = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT)
+ ComponentQuery query = ComponentQuery.builder().setQualifiers(PROJECT)
.setComponentIds(newHashSet(sonarqube.getId(), jdk8.getId())).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
@Test
public void selectByQuery_on_empty_list_of_component_key() {
db.components().insertPrivateProject();
- ComponentQuery dbQuery = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT).setComponentKeys(emptySet()).build();
+ ComponentQuery dbQuery = ComponentQuery.builder().setQualifiers(PROJECT).setComponentKeys(emptySet()).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, dbQuery, 0, 10);
int count = underTest.countByQuery(dbSession, dbQuery);
ComponentDto sonarqube = db.components().insertComponent(newPrivateProjectDto(organizationDto));
ComponentDto jdk8 = db.components().insertComponent(newPrivateProjectDto(organizationDto));
ComponentDto cLang = db.components().insertComponent(newPrivateProjectDto(organizationDto));
- ComponentQuery query = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT)
+ ComponentQuery query = ComponentQuery.builder().setQualifiers(PROJECT)
.setComponentKeys(newHashSet(sonarqube.getDbKey(), jdk8.getDbKey())).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
@Test
public void selectByQuery_on_empty_list_of_component_uuids() {
db.components().insertPrivateProject();
- ComponentQuery dbQuery = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT).setComponentUuids(emptySet()).build();
+ ComponentQuery dbQuery = ComponentQuery.builder().setQualifiers(PROJECT).setComponentUuids(emptySet()).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, dbQuery, 0, 10);
int count = underTest.countByQuery(dbSession, dbQuery);
ComponentDto sonarqube = db.components().insertComponent(newPrivateProjectDto(organizationDto));
ComponentDto jdk8 = db.components().insertComponent(newPrivateProjectDto(organizationDto));
ComponentDto cLang = db.components().insertComponent(newPrivateProjectDto(organizationDto));
- ComponentQuery query = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT)
+ ComponentQuery query = ComponentQuery.builder().setQualifiers(PROJECT)
.setComponentUuids(newHashSet(sonarqube.uuid(), jdk8.uuid())).build();
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
import java.util.Map;
import java.util.Optional;
import java.util.Random;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.apache.ibatis.exceptions.PersistenceException;
+import org.assertj.core.groups.Tuple;
import org.assertj.core.util.Lists;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.KeyLongValue;
+import org.sonar.db.Pagination;
+import org.sonar.db.component.ComponentDto;
import org.sonar.db.dialect.Dialect;
import org.sonar.db.dialect.Oracle;
import org.sonar.db.qualitygate.QGateWithOrgDto;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.Pagination.forPage;
+import static org.sonar.db.organization.OrganizationQuery.Builder;
import static org.sonar.db.organization.OrganizationQuery.newOrganizationQueryBuilder;
import static org.sonar.db.organization.OrganizationQuery.returnAll;
import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
db.organizations().addMember(organization, user);
db.organizations().addMember(anotherOrganization, user);
- List<OrganizationDto> result = underTest.selectByQuery(dbSession, OrganizationQuery.newOrganizationQueryBuilder().setMember(user.getId()).build(), forPage(1).andSize(100));
+ List<OrganizationDto> result = underTest.selectByQuery(dbSession, newOrganizationQueryBuilder().setMember(user.getId()).build(), forPage(1).andSize(100));
assertThat(result).extracting(OrganizationDto::getUuid)
.containsExactlyInAnyOrder(organization.getUuid(), anotherOrganization.getUuid())
db.organizations().addMember(anotherOrganization, user);
db.organizations().addMember(organizationWithoutKeyProvided, user);
- List<OrganizationDto> result = underTest.selectByQuery(dbSession, OrganizationQuery.newOrganizationQueryBuilder()
+ List<OrganizationDto> result = underTest.selectByQuery(dbSession, newOrganizationQueryBuilder()
.setKeys(Arrays.asList(organization.getKey(), anotherOrganization.getKey(), organizationWithoutMember.getKey()))
.setMember(user.getId()).build(), forPage(1).andSize(100));
.doesNotContain(organizationWithoutKeyProvided.getUuid(), organizationWithoutMember.getUuid());
}
+ @Test
+ public void selectByQuery_filter_on_type() {
+ OrganizationDto personalOrg1 = db.organizations().insert();
+ db.users().insertUser(u -> u.setOrganizationUuid(personalOrg1.getUuid()));
+ OrganizationDto personalOrg2 = db.organizations().insert();
+ db.users().insertUser(u -> u.setOrganizationUuid(personalOrg2.getUuid()));
+ OrganizationDto teamOrg1 = db.organizations().insert();
+
+ assertThat(selectUuidsByQuery(q -> q.setOnlyPersonal(), forPage(1).andSize(100)))
+ .containsExactlyInAnyOrder(personalOrg1.getUuid(), personalOrg2.getUuid());
+ assertThat(selectUuidsByQuery(q -> q.setOnlyTeam(), forPage(1).andSize(100)))
+ .containsExactlyInAnyOrder(teamOrg1.getUuid());
+ }
+
+ @Test
+ public void selectByQuery_filter_on_withAnalyses() {
+ assertThat(selectUuidsByQuery(q -> q.setWithAnalyses(), forPage(1).andSize(100)))
+ .isEmpty();
+
+ // has projects and analyses
+ OrganizationDto orgWithAnalyses = db.organizations().insert();
+ ComponentDto analyzedProject = db.components().insertPrivateProject(orgWithAnalyses);
+ db.components().insertSnapshot(analyzedProject, s -> s.setLast(true));
+ // has projects but no analyses
+ OrganizationDto orgWithProjects = db.organizations().insert();
+ db.components().insertPrivateProject(orgWithProjects);
+ db.components().insertPrivateProject(orgWithProjects, p -> p.setEnabled(false));
+ // has no projects
+ db.organizations().insert();
+ // has only disabled projects
+ OrganizationDto orgWithOnlyDisabledProjects = db.organizations().insert();
+ db.components().insertPrivateProject(orgWithOnlyDisabledProjects, p -> p.setEnabled(false));
+
+ assertThat(selectUuidsByQuery(q -> q.setWithAnalyses(), forPage(1).andSize(100)))
+ .containsExactlyInAnyOrder(orgWithAnalyses.getUuid());
+ }
+
+ private List<String> selectUuidsByQuery(Consumer<Builder> query, Pagination pagination) {
+ Builder builder = newOrganizationQueryBuilder();
+ query.accept(builder);
+ return underTest.selectByQuery(dbSession, builder.build(), pagination).stream()
+ .map(OrganizationDto::getUuid)
+ .collect(Collectors.toList());
+ }
+
@Test
public void getDefaultTemplates_returns_empty_when_table_is_empty() {
assertThat(underTest.getDefaultTemplates(dbSession, ORGANIZATION_DTO_1.getUuid())).isEmpty();
.containsOnlyOnce(organization.getUuid());
}
+ @Test
+ public void countTeamsByMembers() {
+ assertThat(underTest.countTeamsByMembers(dbSession)).isEmpty();
+
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ UserDto user3 = db.users().insertUser();
+ OrganizationDto org1 = db.organizations().insert();
+ db.organizations().addMember(org1, user1, user2, user3);
+ OrganizationDto org2 = db.organizations().insert();
+ db.organizations().addMember(org2, user1);
+ OrganizationDto org3 = db.organizations().insert();
+ db.organizations().addMember(org3, user1, user2, user3);
+
+ assertThat(underTest.countTeamsByMembers(dbSession))
+ .extracting(KeyLongValue::getKey, KeyLongValue::getValue)
+ .containsExactlyInAnyOrder(Tuple.tuple("1", 1L), Tuple.tuple("2-4", 2L));
+
+ }
+
+ @Test
+ public void countTeamsByProjects() {
+ assertThat(underTest.countTeamsByProjects(dbSession)).isEmpty();
+
+ OrganizationDto org1 = db.organizations().insert();
+ db.components().insertPrivateProject(org1);
+ OrganizationDto org2 = db.organizations().insert();
+ db.components().insertPrivateProject(org2);
+ db.components().insertPrivateProject(org2);
+ OrganizationDto org3 = db.organizations().insert();
+ db.components().insertPrivateProject(org3);
+ db.components().insertPrivateProject(org3);
+ db.components().insertPrivateProject(org3);
+
+ assertThat(underTest.countTeamsByProjects(dbSession))
+ .extracting(KeyLongValue::getKey, KeyLongValue::getValue)
+ .containsExactlyInAnyOrder(Tuple.tuple("1", 1L), Tuple.tuple("2-4", 2L));
+
+ }
+
private void expectDtoCanNotBeNull() {
expectedException.expect(NullPointerException.class);
expectedException.expectMessage("OrganizationDto can't be null");
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.KeyLongValue;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
assertThat(underTest.countRootUsersButLogin(session, rootLogin)).isEqualTo(2);
}
+ @Test
+ public void countTotalUsers() {
+ assertThat(underTest.countTotalUsers(session)).isEqualTo(0);
+
+ db.users().insertUser(u -> u.setActive(false));
+ db.users().insertUser(u -> u.setActive(true));
+
+ assertThat(underTest.countTotalUsers(session)).isEqualTo(2);
+ }
+
+ @Test
+ public void countTeamUsers() {
+ assertThat(underTest.countTeamUsers(session)).isEqualTo(0);
+
+ // user 1: with only personal organization
+ OrganizationDto user1Org = db.organizations().insert();
+ insertNonRootUser(newUserDto().setOrganizationUuid(user1Org.getUuid()));
+ assertThat(underTest.countTeamUsers(session)).isEqualTo(0);
+
+ // user 2: with no organizations at all
+ insertNonRootUser(newUserDto().setOrganizationUuid(null));
+ assertThat(underTest.countTeamUsers(session)).isEqualTo(0);
+
+ // user 3: with personal and team organizations
+ OrganizationDto user3Org = db.organizations().insert();
+ OrganizationDto teamOrg = db.organizations().insert();
+ UserDto user3 = insertNonRootUser(newUserDto().setOrganizationUuid(user3Org.getUuid()));
+ db.organizations().addMember(teamOrg, user3);
+ assertThat(underTest.countTeamUsers(session)).isEqualTo(1);
+ }
+
+ @Test
+ public void countPersonalUsers() {
+ assertThat(underTest.countPersonalUsers(session)).isEqualTo(0);
+
+ // user 1: with only personal organization
+ OrganizationDto user1Org = db.organizations().insert();
+ insertNonRootUser(newUserDto().setOrganizationUuid(user1Org.getUuid()));
+ assertThat(underTest.countPersonalUsers(session)).isEqualTo(1);
+
+ // user 2: with no organizations at all
+ insertNonRootUser(newUserDto().setOrganizationUuid(null));
+ assertThat(underTest.countPersonalUsers(session)).isEqualTo(1);
+
+ // user 3: with personal and team organizations
+ OrganizationDto user3Org = db.organizations().insert();
+ OrganizationDto teamOrg = db.organizations().insert();
+ UserDto user3 = insertNonRootUser(newUserDto().setOrganizationUuid(user3Org.getUuid()));
+ db.organizations().addMember(teamOrg, user3);
+ assertThat(underTest.countPersonalUsers(session)).isEqualTo(1);
+
+ // user 4: excluded because deactivated
+ OrganizationDto user4Org = db.organizations().insert();
+ insertNonRootUser(newUserDto().setOrganizationUuid(user4Org.getUuid()).setActive(false));
+ assertThat(underTest.countPersonalUsers(session)).isEqualTo(1);
+ }
+
+ @Test
+ public void countNewUsersSince() {
+ assertThat(underTest.countNewUsersSince(session, 400L)).isEqualTo(0);
+
+ when(system2.now()).thenReturn(100L);
+ insertNonRootUser(newUserDto());
+ when(system2.now()).thenReturn(200L);
+ insertNonRootUser(newUserDto());
+ when(system2.now()).thenReturn(300L);
+ insertNonRootUser(newUserDto());
+
+ assertThat(underTest.countNewUsersSince(session, 50L)).isEqualTo(3);
+ assertThat(underTest.countNewUsersSince(session, 190L)).isEqualTo(2);
+ assertThat(underTest.countNewUsersSince(session, 400L)).isEqualTo(0);
+ }
+
+ @Test
+ public void countUsersByIdentityProviders() {
+ assertThat(underTest.countUsersByIdentityProviders(session)).isEmpty();
+
+ db.users().insertUser(u -> u.setActive(true).setExternalIdentityProvider("bitbucket"));
+ db.users().insertUser(u -> u.setActive(true).setExternalIdentityProvider("github"));
+ db.users().insertUser(u -> u.setActive(true).setExternalIdentityProvider("github"));
+ // this used is excluded because deactivated
+ db.users().insertUser(u -> u.setActive(false).setExternalIdentityProvider("github"));
+
+ assertThat(underTest.countUsersByIdentityProviders(session))
+ .extracting(KeyLongValue::getKey, KeyLongValue::getValue)
+ .containsExactlyInAnyOrder(tuple("bitbucket", 1L), tuple("github", 2L));
+ }
+
private UserDto insertInactiveRootUser(UserDto dto) {
insertRootUser(dto);
dto.setActive(false);