diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-01-24 17:00:41 +0100 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-01-27 16:55:16 +0100 |
commit | c04694a7b2db32cdf9cc8aaf872bc90ffbf9c95d (patch) | |
tree | 4e664a012a17f019c12b309d9d9763f609db2146 /sonar-db | |
parent | a670d389488e9e451aa03413b37495e6d4f93e95 (diff) | |
download | sonarqube-c04694a7b2db32cdf9cc8aaf872bc90ffbf9c95d.tar.gz sonarqube-c04694a7b2db32cdf9cc8aaf872bc90ffbf9c95d.zip |
SONAR-8690 add support for default templates to OrganizationDao
Diffstat (limited to 'sonar-db')
6 files changed, 328 insertions, 15 deletions
diff --git a/sonar-db/src/main/java/org/sonar/db/organization/DefaultTemplates.java b/sonar-db/src/main/java/org/sonar/db/organization/DefaultTemplates.java new file mode 100644 index 00000000000..6a7b4ef288c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/organization/DefaultTemplates.java @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.db.organization; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +import static java.util.Objects.requireNonNull; + +public class DefaultTemplates { + private String project; + private String view; + + @CheckForNull + public String getProject() { + return project; + } + + public DefaultTemplates setProject(String project) { + requireNonNull(project, "project default template can't be null"); + this.project = project; + return this; + } + + @CheckForNull + public String getView() { + return view; + } + + public DefaultTemplates setView(@Nullable String view) { + this.view = view; + return this; + } + + @Override + public String toString() { + return "DefaultTemplates{" + + "project='" + project + '\'' + + ", view='" + view + '\'' + + '}'; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java index 2705c8355e4..17ee6afe7a8 100644 --- a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java +++ b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java @@ -52,7 +52,7 @@ public class OrganizationDao implements Dao { } public Optional<OrganizationDto> selectByUuid(DbSession dbSession, String uuid) { - requireNonNull(uuid, "uuid can't be null"); + checkUuid(uuid); return Optional.ofNullable(getMapper(dbSession).selectByUuid(uuid)); } @@ -61,6 +61,32 @@ public class OrganizationDao implements Dao { return Optional.ofNullable(getMapper(dbSession).selectByKey(key)); } + public List<OrganizationDto> selectByUuids(DbSession dbSession, Set<String> organizationUuids) { + if (organizationUuids.size() == 1) { + return Collections.singletonList(getMapper(dbSession).selectByUuid(organizationUuids.iterator().next())); + } + return executeLargeInputs(organizationUuids, getMapper(dbSession)::selectByUuids); + } + + /** + * Retrieve the default template of the specified organization if: + * <ol> + * <li>the specified organization exists</li> + * <li>the project default permission template is defined</li> + * </ol> + */ + public Optional<DefaultTemplates> getDefaultTemplates(DbSession dbSession, String organizationUuid) { + checkUuid(organizationUuid); + return Optional.ofNullable(getMapper(dbSession).selectDefaultTemplatesByUuid(organizationUuid)); + } + + public void setDefaultTemplates(DbSession dbSession, String uuid, DefaultTemplates defaultTemplates) { + checkUuid(uuid); + checkDefaultTemplates(defaultTemplates); + long now = system2.now(); + getMapper(dbSession).updateDefaultTemplates(uuid, defaultTemplates, now); + } + public int update(DbSession dbSession, OrganizationDto organization) { checkDto(organization); organization.setUpdatedAt(system2.now()); @@ -83,10 +109,12 @@ public class OrganizationDao implements Dao { return dbSession.getMapper(OrganizationMapper.class); } - public List<OrganizationDto> selectByUuids(DbSession dbSession, Set<String> organizationUuids) { - if (organizationUuids.size() == 1) { - return Collections.singletonList(getMapper(dbSession).selectByUuid(organizationUuids.iterator().next())); - } - return executeLargeInputs(organizationUuids, getMapper(dbSession)::selectByUuids); + private static void checkUuid(String uuid) { + requireNonNull(uuid, "uuid can't be null"); + } + + private static void checkDefaultTemplates(DefaultTemplates defaultTemplates) { + requireNonNull(defaultTemplates, "defaultTemplates can't be null"); + requireNonNull(defaultTemplates.getProject(), "defaultTemplates.project can't be null"); } } diff --git a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java index 8a2b9b3c1fb..94a35be76be 100644 --- a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java @@ -37,6 +37,8 @@ public interface OrganizationMapper { List<OrganizationDto> selectByUuids(@Param("uuids") List<String> uuids); + DefaultTemplates selectDefaultTemplatesByUuid(@Param("uuid") String uuid); + /** * Update the organization with UUID specified by {@link OrganizationDto#getUuid()}. * <p> @@ -46,6 +48,9 @@ public interface OrganizationMapper { */ int update(@Param("organization") OrganizationDto organization); + void updateDefaultTemplates(@Param("organizationUuid") String organizationUuid, + @Param("defaultTemplates") DefaultTemplates defaultTemplates, @Param("now") long now); + int deleteByUuid(@Param("uuid") String uuid); int deleteByKey(@Param("key") String key); diff --git a/sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml b/sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml index c7ab1ea8461..15de61bfaaa 100644 --- a/sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml @@ -12,6 +12,11 @@ org.created_at as "createdAt", org.updated_at as "updatedAt" </sql> + + <sql id="defaultTemplatesColumns"> + org.default_perm_template_project as "project", + org.default_perm_template_view as "view" + </sql> <select id="selectByUuid" resultType="Organization"> select @@ -21,6 +26,15 @@ org.uuid = #{uuid, jdbcType=VARCHAR} </select> + <select id="selectDefaultTemplatesByUuid" resultType="org.sonar.db.organization.DefaultTemplates"> + select + <include refid="defaultTemplatesColumns"/> + from organizations org + where + org.uuid = #{uuid, jdbcType=VARCHAR} + and org.default_perm_template_project is not null + </select> + <select id="selectByKey" resultType="Organization"> select <include refid="selectColumns"/> @@ -119,7 +133,17 @@ avatar_url = #{organization.avatarUrl, jdbcType=VARCHAR}, updated_at = #{organization.updatedAt, jdbcType=BIGINT} where - uuid = #{organization.uuid} + uuid = #{organization.uuid, jdbcType=VARCHAR} + </update> + + <update id="updateDefaultTemplates"> + update organizations + set + default_perm_template_project = #{defaultTemplates.project, jdbcType=VARCHAR}, + default_perm_template_view = #{defaultTemplates.view, jdbcType=VARCHAR}, + updated_at = #{now, jdbcType=BIGINT} + where + uuid = #{organizationUuid, jdbcType=VARCHAR} </update> <delete id="deleteByUuid"> diff --git a/sonar-db/src/test/java/org/sonar/db/organization/DefaultTemplatesTest.java b/sonar-db/src/test/java/org/sonar/db/organization/DefaultTemplatesTest.java new file mode 100644 index 00000000000..bc1edd302be --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/organization/DefaultTemplatesTest.java @@ -0,0 +1,55 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.db.organization; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DefaultTemplatesTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private DefaultTemplates underTest = new DefaultTemplates(); + + @Test + public void setProject_throws_NPE_if_argument_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("project default template can't be null"); + + underTest.setProject(null); + } + + @Test + public void setView_accepts_null() { + underTest.setView(null); + } + + @Test + public void check_toString() { + assertThat(underTest.toString()).isEqualTo("DefaultTemplates{project='null', view='null'}"); + underTest + .setProject("a project") + .setView("a view"); + assertThat(underTest.toString()).isEqualTo("DefaultTemplates{project='a project', view='a view'}"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java b/sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java index 88a51f6e658..b4b3f2c9ae5 100644 --- a/sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java @@ -19,6 +19,9 @@ */ package org.sonar.db.organization; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -26,6 +29,7 @@ import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.Random; +import javax.annotation.Nullable; import org.apache.ibatis.exceptions.PersistenceException; import org.assertj.core.util.Lists; import org.junit.Rule; @@ -109,6 +113,9 @@ public class OrganizationDaoTest { assertThat(row.get("avatarUrl")).isEqualTo(ORGANIZATION_DTO_1.getAvatarUrl()); assertThat(row.get("createdAt")).isEqualTo(ORGANIZATION_DTO_1.getCreatedAt()); assertThat(row.get("updatedAt")).isEqualTo(ORGANIZATION_DTO_1.getUpdatedAt()); + assertThat(row.get("defaultTemplate")).isNull(); + assertThat(row.get("projectDefaultTemplate")).isNull(); + assertThat(row.get("viewDefaultTemplate")).isNull(); } @Test @@ -125,6 +132,9 @@ public class OrganizationDaoTest { assertThat(row.get("avatarUrl")).isNull(); assertThat(row.get("createdAt")).isEqualTo(SOME_DATE); assertThat(row.get("updatedAt")).isEqualTo(SOME_DATE); + assertThat(row.get("defaultTemplate")).isNull(); + assertThat(row.get("projectDefaultTemplate")).isNull(); + assertThat(row.get("viewDefaultTemplate")).isNull(); } @Test @@ -435,8 +445,89 @@ public class OrganizationDaoTest { .containsExactly("uuid1", "uuid3"); } - private static OrganizationQuery newQueryWithKeys(String... keys) { - return newOrganizationQueryBuilder().setKeys(Arrays.asList(keys)).build(); + @Test + public void getDefaultTemplates_returns_empty_when_table_is_empty() { + assertThat(underTest.getDefaultTemplates(dbSession, ORGANIZATION_DTO_1.getUuid())).isEmpty(); + } + + @Test + public void getDefaultTemplates_returns_empty_when_row_exists_but_all_default_templates_columns_are_null() { + insertOrganization(ORGANIZATION_DTO_1); + + assertThat(underTest.getDefaultTemplates(dbSession, ORGANIZATION_DTO_1.getUuid())).isEmpty(); + } + + @Test + public void getDefaultTemplates_returns_data_when_project_default_templates_column_is_not_null() { + insertOrganization(ORGANIZATION_DTO_1); + underTest.setDefaultTemplates(dbSession, ORGANIZATION_DTO_1.getUuid(), new DefaultTemplates().setProject("foo")); + + verifyGetDefaultTemplates(ORGANIZATION_DTO_1, "foo", null); + } + + @Test + public void getDefaultTemplates_returns_data_when_project_and_view_default_template_column_are_not_null() { + insertOrganization(ORGANIZATION_DTO_1); + setDefaultTemplate(ORGANIZATION_DTO_1, "foo", "bar"); + + verifyGetDefaultTemplates(ORGANIZATION_DTO_1, "foo", "bar"); + } + + @Test + public void getDefaultTemplates_returns_empty_when_only_view_default_template_column_is_not_null() { + dirtyInsertWithDefaultTemplate("uuid1", null, "bar"); + + assertThat(underTest.getDefaultTemplates(dbSession, "uuid1")) + .isEmpty(); + } + + @Test + public void getDefaultTemplates_returns_empty_when_project_and_view_default_template_column_are_not_null() { + insertOrganization(ORGANIZATION_DTO_1); + + assertThat(underTest.getDefaultTemplates(dbSession, ORGANIZATION_DTO_1.getUuid())) + .isEmpty(); + } + + @Test + public void getDefaultTemplates_is_case_sensitive() { + insertOrganization(ORGANIZATION_DTO_1); + underTest.setDefaultTemplates(dbSession, ORGANIZATION_DTO_1.getUuid(), new DefaultTemplates().setProject("foo").setView("bar")); + + assertThat(underTest.getDefaultTemplates(dbSession, ORGANIZATION_DTO_1.getUuid().toUpperCase(Locale.ENGLISH))) + .isEmpty(); + } + + @Test + public void setDefaultTemplates_throws_NPE_when_uuid_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("uuid can't be null"); + + underTest.setDefaultTemplates(dbSession, null, new DefaultTemplates().setProject("p")); + } + + @Test + public void setDefaultTemplates_throws_NPE_when_defaultTemplate_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("defaultTemplates can't be null"); + + underTest.setDefaultTemplates(dbSession, "uuid", null); + } + + @Test + public void setDefaultTemplates_throws_NPE_when_defaultTemplate_project_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("defaultTemplates.project can't be null"); + + underTest.setDefaultTemplates(dbSession, "uuid", new DefaultTemplates()); + } + + @Test + public void setDefaultTemplates_throws_NPE_when_defaultTemplate_project_is_null_and_view_is_not() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("defaultTemplates.project can't be null"); + + underTest.setDefaultTemplates(dbSession, "uuid", new DefaultTemplates().setView("foo")); } @Test @@ -603,6 +694,47 @@ public class OrganizationDaoTest { dbSession.commit(); } + private void dirtyInsertWithDefaultTemplate(String organizationUuid, @Nullable String project, @Nullable String view) { + try (Connection connection = dbTester.database().getDataSource().getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement( + "insert into organizations" + + " (" + + " uuid," + + " kee," + + " name," + + " default_perm_template_project," + + " default_perm_template_view," + + " created_at," + + " updated_at" + + " )" + + " values" + + " (" + + " ?," + + " ?," + + " ?," + + " ?," + + " ?," + + " ?," + + " ?" + + " )")) { + preparedStatement.setString(1, organizationUuid); + preparedStatement.setString(2, organizationUuid); + preparedStatement.setString(3, organizationUuid); + preparedStatement.setString(4, project); + preparedStatement.setString(5, view); + preparedStatement.setLong(6, 1000L); + preparedStatement.setLong(7, 2000L); + preparedStatement.execute(); + } catch (SQLException e) { + throw new RuntimeException("dirty insert failed", e); + } + } + + private void setDefaultTemplate(OrganizationDto organizationDto1, @Nullable String project, @Nullable String view) { + underTest.setDefaultTemplates(dbSession, organizationDto1.getUuid(), new DefaultTemplates().setProject(project).setView(view)); + dbSession.commit(); + } + private void verifyOrganization1(Optional<OrganizationDto> optional) { assertThat(optional).isNotEmpty(); verifyOrganization1(optional.get()); @@ -619,11 +751,6 @@ public class OrganizationDaoTest { assertThat(dto.getUpdatedAt()).isEqualTo(ORGANIZATION_DTO_1.getUpdatedAt()); } - private void verifyOrganization(Optional<OrganizationDto> optional, OrganizationDto expected) { - assertThat(optional).isNotEmpty(); - verifyOrganization(optional.get(), expected); - } - private void verifyOrganization(OrganizationDto dto, OrganizationDto expected) { assertThat(dto.getUuid()).isEqualTo(expected.getUuid()); assertThat(dto.getKey()).isEqualTo(expected.getKey()); @@ -638,7 +765,9 @@ public class OrganizationDaoTest { private Map<String, Object> selectSingleRow() { List<Map<String, Object>> rows = dbTester.select("select" + " uuid as \"uuid\", kee as \"key\", name as \"name\", description as \"description\", url as \"url\", avatar_url as \"avatarUrl\"," + - " created_at as \"createdAt\", updated_at as \"updatedAt\"" + + " created_at as \"createdAt\", updated_at as \"updatedAt\"," + + " default_perm_template_project as \"projectDefaultPermTemplate\"," + + " default_perm_template_view as \"viewDefaultPermTemplate\"" + " from organizations"); assertThat(rows).hasSize(1); return rows.get(0); @@ -653,4 +782,17 @@ public class OrganizationDaoTest { .setUrl(organizationDto.getUrl()) .setAvatarUrl(organizationDto.getAvatarUrl()); } + + private static OrganizationQuery newQueryWithKeys(String... keys) { + return newOrganizationQueryBuilder().setKeys(Arrays.asList(keys)).build(); + } + + private void verifyGetDefaultTemplates(OrganizationDto organizationDto, + @Nullable String expectedProject, @Nullable String expectedView) { + Optional<DefaultTemplates> optional = underTest.getDefaultTemplates(dbSession, organizationDto.getUuid()); + assertThat(optional).isNotEmpty(); + DefaultTemplates defaultTemplates = optional.get(); + assertThat(defaultTemplates.getProject()).isEqualTo(expectedProject); + assertThat(defaultTemplates.getView()).isEqualTo(expectedView); + } } |