]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8690 add support for default templates to OrganizationDao
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 24 Jan 2017 16:00:41 +0000 (17:00 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 27 Jan 2017 15:55:16 +0000 (16:55 +0100)
sonar-db/src/main/java/org/sonar/db/organization/DefaultTemplates.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java
sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java
sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml
sonar-db/src/test/java/org/sonar/db/organization/DefaultTemplatesTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java

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 (file)
index 0000000..6a7b4ef
--- /dev/null
@@ -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 + '\'' +
+      '}';
+  }
+}
index 2705c8355e4d6a7230fb9653b91cf5b8ff046137..17ee6afe7a8391ab18eb339e93b5ad83f3012b9a 100644 (file)
@@ -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");
   }
 }
index 8a2b9b3c1fb1e756f3cfbd8837e5538247b758d3..94a35be76be54a1f98df5abcd9097b93966a0fdc 100644 (file)
@@ -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);
index c7ab1ea8461c27731305401c9318c57a93261aa6..15de61bfaaa82500f1b1cc416ade4c061ac0e39b 100644 (file)
     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
       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"/>
       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 (file)
index 0000000..bc1edd3
--- /dev/null
@@ -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'}");
+  }
+}
index 88a51f6e658e842ae99044e82610a5a17ef680a1..b4b3f2c9ae5f325b97643cf6058b92c85694d43a 100644 (file)
@@ -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);
+  }
 }