]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8690 populate DEFAULT_PERM_TEMPLATE_* columns from PROPERTIES
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 24 Jan 2017 15:49:11 +0000 (16:49 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 27 Jan 2017 15:55:16 +0000 (16:55 +0100)
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v63/DbVersion63.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v63/DefaultOrganizationUuid.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v63/DefaultOrganizationUuidImpl.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizations.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v63/DbVersion63Test.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizationsTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v63/TestDefaultOrganizationUuid.java
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizationsTest/properties_and_organizations.sql [new file with mode: 0644]
sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql

index e42a5685b7e94e87dd355ad58a090c567cfcd1b9..9aae9b502f753e586bc7b551e78ce430573a1ac0 100644 (file)
@@ -40,6 +40,7 @@ public class DbVersion63 implements DbVersion {
       .add(1505, "Make PROJECTS.ORGANIZATION_UUID not nullable", MakeOrganizationUuidOfProjectsNotNullable.class)
       .add(1506, "Add index on PROJECTS.ORGANIZATION_UUID", AddIndexOnOrganizationUuidOfProjects.class)
       .add(1507, "Drop table RESOURCE_INDEX", DropTableResourceIndex.class)
-      .add(1508, "Add columns ORGANIZATIONS.DEFAULT_PERM_TEMPLATE_*", AddDefaultPermTemplateColumnsToOrganizations.class);
+      .add(1508, "Add columns ORGANIZATIONS.DEFAULT_PERM_TEMPLATE_*", AddDefaultPermTemplateColumnsToOrganizations.class)
+      .add(1509, "Populate columns ORGANIZATIONS.DEFAULT_PERM_TEMPLATE_*", PopulateDefaultPermTemplateColumnsOfOrganizations.class);
   }
 }
index 5ac0cf1b29c2a0d29d076a6b51a3cab20caed2c1..21bf3714503fda6e7562c83e64d397f1e3ed35ad 100644 (file)
@@ -24,7 +24,18 @@ import org.sonar.server.platform.db.migration.step.DataChange;
 
 public interface DefaultOrganizationUuid {
   /**
+   * Retrieves the uuid of the default organization from table INTERNAL_PROPERTIES.
+   *
    * @throws IllegalStateException if uuid of the default organization can't be retrieved
    */
   String get(DataChange.Context context) throws SQLException;
+
+  /**
+   * Retrieves the uuid of the default organization from table INTERNAL_PROPERTIES and ensure the specified organization
+   * exists in table ORGANIZATIONS.
+   *
+   * @throws IllegalStateException if uuid of the default organization can't be retrieved
+   * @throws IllegalStateException if the default organization does not exist
+   */
+  String getAndCheck(DataChange.Context context) throws SQLException;
 }
index 2342db0346347e2ebcfb5ae923226e43cb807632..46382e125e86a75b7c235e62a9fdbd304d3d27ba 100644 (file)
@@ -26,8 +26,8 @@ import org.sonar.server.platform.db.migration.step.Select;
 import static com.google.common.base.Preconditions.checkState;
 
 /**
- * Component which can be injected in steps which provides access to the UUID of the default organization, read directly
- * from the BD.
+ * Component which can be injected in steps which provides access to the UUID of the default organization, it reads
+ * directly from the BD.
  */
 public class DefaultOrganizationUuidImpl implements DefaultOrganizationUuid {
 
@@ -41,4 +41,15 @@ public class DefaultOrganizationUuidImpl implements DefaultOrganizationUuid {
     checkState(uuid != null, "Default organization uuid is missing");
     return uuid;
   }
+
+  @Override
+  public String getAndCheck(DataChange.Context context) throws SQLException {
+    String organizationUuid = get(context);
+    Select select = context.prepareSelect("select uuid from organizations where uuid=?")
+      .setString(1, organizationUuid);
+    checkState(select.get(row -> row.getString(1)) != null,
+      "Default organization with uuid '%s' does not exist in table ORGANIZATIONS",
+      organizationUuid);
+    return organizationUuid;
+  }
 }
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizations.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizations.java
new file mode 100644 (file)
index 0000000..a5c4094
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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.server.platform.db.migration.version.v63;
+
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static com.google.common.base.MoreObjects.firstNonNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Populate the columns DEFAULT_PERM_TEMPLATE, DEFAULT_PERM_TEMPLATE_PROJECT and DEFAULT_PERM_TEMPLATE_VIEW of table
+ * ORGANIZATIONS, for the default organization exclusively, from the properties holding the default permissions template
+ * uuids. These properties are then deleted.
+ *
+ * <p>
+ * This migration ensures it can run but failing if:
+ * <ul>
+ *   <li>there is more than one organizations (because we can't populate the column for those extra organizations)</li>
+ *   <li>the global default permission template can't be found (because an organization must have at least this default template)</li>
+ * </ul>
+ * </p>
+ */
+public class PopulateDefaultPermTemplateColumnsOfOrganizations extends DataChange {
+  private static final String DEFAULT_TEMPLATE_PROPERTY = "sonar.permission.template.default";
+  private static final String DEFAULT_PROJECT_TEMPLATE_PROPERTY = "sonar.permission.template.TRK.default";
+  private static final String DEFAULT_VIEW_TEMPLATE_PROPERTY = "sonar.permission.template.VW.default";
+  private static final String DEFAULT_DEV_TEMPLATE_PROPERTY = "sonar.permission.template.DEV.default";
+
+  private final DefaultOrganizationUuid defaultOrganizationUuid;
+
+  public PopulateDefaultPermTemplateColumnsOfOrganizations(Database db, DefaultOrganizationUuid defaultOrganizationUuid) {
+    super(db);
+    this.defaultOrganizationUuid = defaultOrganizationUuid;
+  }
+
+  @Override
+  protected void execute(Context context) throws SQLException {
+    String defaultOrganizationUuid = this.defaultOrganizationUuid.getAndCheck(context);
+    ensureOnlyDefaultOrganizationExists(context, defaultOrganizationUuid);
+
+    Map<String, String> defaultTemplateProperties = retrieveDefaultTemplateProperties(context);
+
+    String globalDefaultTemplate = defaultTemplateProperties.get(DEFAULT_TEMPLATE_PROPERTY);
+    if (globalDefaultTemplate == null || globalDefaultTemplate.isEmpty()) {
+      // DB has just been created, default template of default organization will be populated by a startup task
+      return;
+    }
+    String projectDefaultTemplate = firstNonNull(defaultTemplateProperties.get(DEFAULT_PROJECT_TEMPLATE_PROPERTY), globalDefaultTemplate);
+    String viewDefaultTemplate = defaultTemplateProperties.get(DEFAULT_VIEW_TEMPLATE_PROPERTY);
+
+    Loggers.get(PopulateDefaultPermTemplateColumnsOfOrganizations.class)
+      .debug("Setting default templates on default organization '{}': project='{}', view='{}'",
+        defaultOrganizationUuid, projectDefaultTemplate, viewDefaultTemplate);
+
+    context.prepareUpsert("update organizations set" +
+      " default_perm_template_project=?," +
+      " default_perm_template_view=?" +
+      " where" +
+      " uuid=?")
+      .setString(1, projectDefaultTemplate)
+      .setString(2, viewDefaultTemplate)
+      .setString(3, defaultOrganizationUuid)
+      .execute()
+      .commit();
+
+    // delete properties
+    context.prepareUpsert("delete from properties where prop_key in (?,?,?,?)")
+      .setString(1, DEFAULT_TEMPLATE_PROPERTY)
+      .setString(2, DEFAULT_PROJECT_TEMPLATE_PROPERTY)
+      .setString(3, DEFAULT_VIEW_TEMPLATE_PROPERTY)
+      .setString(4, DEFAULT_DEV_TEMPLATE_PROPERTY)
+      .execute()
+      .commit();
+  }
+
+  private static void ensureOnlyDefaultOrganizationExists(Context context, String defaultOrganizationUuid) throws SQLException {
+    Integer otherOrganizationCount = context.prepareSelect("select count(*) from organizations where uuid <> ?")
+      .setString(1, defaultOrganizationUuid)
+      .get(row -> row.getInt(1));
+    checkState(otherOrganizationCount == 0,
+      "Can not migrate DB if more than one organization exists. Remove all organizations but the default one which uuid is '%s'",
+      defaultOrganizationUuid);
+  }
+
+  private static Map<String, String> retrieveDefaultTemplateProperties(Context context) throws SQLException {
+    Map<String, String> templates = new HashMap<>(3);
+    context.prepareSelect("select prop_key,is_empty,text_value from properties where prop_key in (?,?,?)")
+      .setString(1, DEFAULT_TEMPLATE_PROPERTY)
+      .setString(2, DEFAULT_PROJECT_TEMPLATE_PROPERTY)
+      .setString(3, DEFAULT_VIEW_TEMPLATE_PROPERTY)
+      .scroll(row -> {
+        String key = row.getString(1);
+        boolean isEmpty = row.getBoolean(2);
+        String textValue = row.getString(3);
+        if (!isEmpty) {
+          templates.put(key, textValue);
+        }
+      });
+    return templates;
+  }
+}
index 87ed043ecef00e881125eb6208ef0a1609af99bc..3512ef01c85800a3f5cee897cb512a09f4adf450 100644 (file)
@@ -41,7 +41,7 @@ public class DbVersion63Test {
 
   @Test
   public void verify_migration_count() {
-    verifyMigrationCount(underTest, 9);
+    verifyMigrationCount(underTest, 10);
   }
 
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizationsTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizationsTest.java
new file mode 100644 (file)
index 0000000..cca219f
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * 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.server.platform.db.migration.version.v63;
+
+import java.sql.SQLException;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PopulateDefaultPermTemplateColumnsOfOrganizationsTest {
+  private static final String DEFAULT_TEMPLATE_PROPERTY = "sonar.permission.template.default";
+  private static final String DEFAULT_PROJECT_TEMPLATE_PROPERTY = "sonar.permission.template.TRK.default";
+  private static final String DEFAULT_VIEW_TEMPLATE_PROPERTY = "sonar.permission.template.VW.default";
+  private static final String DEFAULT_DEV_TEMPLATE_PROPERTY = "sonar.permission.template.DEV.default";
+  private static final String DEFAULT_ORGANIZATION_UUID = "def org uuid";
+
+  @Rule
+  public DbTester dbTester = DbTester.createForSchema(System2.INSTANCE, PopulateDefaultPermTemplateColumnsOfOrganizationsTest.class, "properties_and_organizations.sql");
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private PopulateDefaultPermTemplateColumnsOfOrganizations underTest = new PopulateDefaultPermTemplateColumnsOfOrganizations(dbTester.database(),
+    new DefaultOrganizationUuidImpl());
+
+  @Test
+  public void fails_with_ISE_when_no_default_organization_is_set() throws SQLException {
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Default organization uuid is missing");
+
+    underTest.execute();
+  }
+
+  @Test
+  public void fails_with_ISE_when_default_organization_does_not_exist_in_table_ORGANIZATIONS() throws SQLException {
+    insertDefaultOrganizationUuid("blabla");
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Default organization with uuid 'blabla' does not exist in table ORGANIZATIONS");
+
+    underTest.execute();
+  }
+
+  @Test
+  public void fails_with_ISE_when_more_than_one_organization_exist() throws SQLException {
+    setupDefaultOrganization();
+
+    insertOrganization("other orga uuid");
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Can not migrate DB if more than one organization exists. " +
+      "Remove all organizations but the default one which uuid is '" + DEFAULT_ORGANIZATION_UUID + "'");
+
+    underTest.execute();
+  }
+
+  @Test
+  public void do_nothing_if_global_default_template_property_does_not_exist() throws SQLException {
+    setupDefaultOrganization();
+
+    underTest.execute();
+
+    verifyTemplateColumns(null, null);
+    verifyPropertiesDoNotExist();
+  }
+
+  @Test
+  public void execute_sets_project_perm_template_when_global_default_template_is_defined_in_property() throws SQLException {
+    setupDefaultOrganization();
+    insertProperty(DEFAULT_TEMPLATE_PROPERTY, "foo");
+
+    underTest.execute();
+
+    verifyTemplateColumns("foo", null);
+    verifyPropertiesDoNotExist();
+  }
+
+  @Test
+  public void execute_sets_project_perm_template_from_project_default_template_property_over_global_property() throws SQLException {
+    setupDefaultOrganization();
+    insertProperty(DEFAULT_TEMPLATE_PROPERTY, "foo");
+    insertProperty(DEFAULT_PROJECT_TEMPLATE_PROPERTY, "bar");
+
+    underTest.execute();
+
+    verifyTemplateColumns("bar", null);
+    verifyPropertiesDoNotExist();
+  }
+
+  @Test
+  public void execute_sets_project_perm_template_from_global_property_and_view_perm_template_from_view_property() throws SQLException {
+    setupDefaultOrganization();
+    insertProperty(DEFAULT_TEMPLATE_PROPERTY, "foo");
+    insertProperty(DEFAULT_VIEW_TEMPLATE_PROPERTY, "bar");
+
+    underTest.execute();
+
+    verifyTemplateColumns("foo", "bar");
+    verifyPropertiesDoNotExist();
+  }
+
+  @Test
+  public void execute_sets_project_from_project_property_and_view_from_view_property_when_all_properties_are_defined() throws SQLException {
+    setupDefaultOrganization();
+    insertProperty(DEFAULT_TEMPLATE_PROPERTY, "foo");
+    insertProperty(DEFAULT_PROJECT_TEMPLATE_PROPERTY, "bar");
+    insertProperty(DEFAULT_VIEW_TEMPLATE_PROPERTY, "doh");
+
+    underTest.execute();
+
+    verifyTemplateColumns("bar", "doh");
+    verifyPropertiesDoNotExist();
+  }
+
+  @Test
+  public void execute_deletes_dev_property_when_it_is_defined() throws SQLException {
+    setupDefaultOrganization();
+    insertProperty(DEFAULT_TEMPLATE_PROPERTY, "foo");
+    insertProperty(DEFAULT_DEV_TEMPLATE_PROPERTY, "bar");
+
+    underTest.execute();
+
+    verifyPropertiesDoNotExist();
+  }
+
+  private void verifyTemplateColumns(@Nullable String project, @Nullable String view) {
+    Map<String, Object> row = dbTester.selectFirst("select " +
+      " default_perm_template_project as \"projectDefaultPermTemplate\"," +
+      " default_perm_template_view as \"viewDefaultPermTemplate\"" +
+      " from organizations where uuid='" + DEFAULT_ORGANIZATION_UUID + "'");
+    assertThat(row.get("projectDefaultPermTemplate")).isEqualTo(project);
+    assertThat(row.get("viewDefaultPermTemplate")).isEqualTo(view);
+  }
+
+  private void verifyPropertiesDoNotExist() {
+    verifyPropertyDoesNotExist(DEFAULT_TEMPLATE_PROPERTY);
+    verifyPropertyDoesNotExist(DEFAULT_PROJECT_TEMPLATE_PROPERTY);
+    verifyPropertyDoesNotExist(DEFAULT_VIEW_TEMPLATE_PROPERTY);
+    verifyPropertyDoesNotExist(DEFAULT_DEV_TEMPLATE_PROPERTY);
+  }
+
+  private void verifyPropertyDoesNotExist(String globalPermissionTemplateDefault) {
+    assertThat(dbTester.countSql("select count(*) as \"cnt\" from PROPERTIES where prop_key='" + globalPermissionTemplateDefault + "'"))
+      .isEqualTo(0);
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    setupDefaultOrganization();
+    insertProperty(DEFAULT_TEMPLATE_PROPERTY, "foo");
+
+    underTest.execute();
+
+    underTest.execute();
+  }
+
+  private void setupDefaultOrganization() {
+    insertDefaultOrganizationUuid(DEFAULT_ORGANIZATION_UUID);
+    insertOrganization(DEFAULT_ORGANIZATION_UUID);
+  }
+
+  private void insertOrganization(String uuid) {
+    dbTester.executeInsert(
+      "ORGANIZATIONS",
+      "UUID", uuid,
+      "KEE", uuid,
+      "NAME", uuid,
+      "CREATED_AT", "1000",
+      "UPDATED_AT", "1000");
+  }
+
+  private void insertDefaultOrganizationUuid(String defaultOrganizationUuid) {
+    dbTester.executeInsert(
+      "INTERNAL_PROPERTIES",
+      "KEE", "organization.default",
+      "IS_EMPTY", "false",
+      "TEXT_VALUE", defaultOrganizationUuid);
+  }
+
+  private void insertProperty(String key, @Nullable String value) {
+    dbTester.executeInsert(
+      "PROPERTIES",
+      "PROP_KEY", key,
+      "IS_EMPTY", String.valueOf(value == null),
+      "TEXT_VALUE", value);
+  }
+}
index ba1b6e1f0924874ecf215c0a47f5a61145a5e948..1f3116a0e39a7cee6521f8b856ecac3f49a7b0a4 100644 (file)
@@ -24,6 +24,9 @@ import org.sonar.server.platform.db.migration.step.DataChange;
 
 import static java.util.Objects.requireNonNull;
 
+/**
+ * Implementation of {@link DefaultOrganizationUuid} which never fails and returns the specified organization uuid.
+ */
 public class TestDefaultOrganizationUuid implements DefaultOrganizationUuid {
   private final String organizationUuid;
 
@@ -35,4 +38,9 @@ public class TestDefaultOrganizationUuid implements DefaultOrganizationUuid {
   public String get(DataChange.Context context) throws SQLException {
     return organizationUuid;
   }
+
+  @Override
+  public String getAndCheck(DataChange.Context context) throws SQLException {
+    return organizationUuid;
+  }
 }
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizationsTest/properties_and_organizations.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v63/PopulateDefaultPermTemplateColumnsOfOrganizationsTest/properties_and_organizations.sql
new file mode 100644 (file)
index 0000000..056ce7c
--- /dev/null
@@ -0,0 +1,36 @@
+CREATE TABLE "ORGANIZATIONS" (
+  "UUID" VARCHAR(40) NOT NULL PRIMARY KEY,
+  "KEE" VARCHAR(32) NOT NULL,
+  "NAME" VARCHAR(64) NOT NULL,
+  "DESCRIPTION" VARCHAR(256),
+  "URL" VARCHAR(256),
+  "AVATAR_URL" VARCHAR(256),
+  "DEFAULT_PERM_TEMPLATE" VARCHAR(40),
+  "DEFAULT_PERM_TEMPLATE_PROJECT" VARCHAR(40),
+  "DEFAULT_PERM_TEMPLATE_VIEW" VARCHAR(40),
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL
+);
+CREATE UNIQUE INDEX "PK_ORGANIZATIONS" ON "ORGANIZATIONS" ("UUID");
+CREATE UNIQUE INDEX "ORGANIZATION_KEY" ON "ORGANIZATIONS" ("KEE");
+
+CREATE TABLE "PROPERTIES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PROP_KEY" VARCHAR(512) NOT NULL,
+  "RESOURCE_ID" INTEGER,
+  "USER_ID" INTEGER,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB(2147483647),
+  "CREATED_AT" BIGINT
+);
+CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
+
+CREATE TABLE "INTERNAL_PROPERTIES" (
+  "KEE" VARCHAR(50) NOT NULL PRIMARY KEY,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB,
+  "CREATED_AT" BIGINT
+);
+CREATE UNIQUE INDEX "UNIQ_INTERNAL_PROPERTIES" ON "INTERNAL_PROPERTIES" ("KEE");
index e9f211edb22d9d4b5bf2f8c25a2097d6c4c0dffa..26c5cd9909f2912f0b94bcab4777599c3c99660c 100644 (file)
@@ -522,6 +522,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1505');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1506');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1507');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1508');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1509');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, EXTERNAL_IDENTITY, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, IS_ROOT, CREATED_AT, UPDATED_AT) VALUES (1, 'admin', 'Administrator', '', 'admin', 'sonarqube', true, 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', true, '1418215735482', '1418215735482');
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;