3 * Copyright (C) 2009-2017 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.platform.db.migration.version.v63;
22 import java.sql.SQLException;
23 import java.util.HashMap;
25 import org.sonar.api.utils.log.Loggers;
26 import org.sonar.db.Database;
27 import org.sonar.server.platform.db.migration.step.DataChange;
29 import static com.google.common.base.MoreObjects.firstNonNull;
30 import static com.google.common.base.Preconditions.checkState;
33 * Populate the columns DEFAULT_PERM_TEMPLATE, DEFAULT_PERM_TEMPLATE_PROJECT and DEFAULT_PERM_TEMPLATE_VIEW of table
34 * ORGANIZATIONS, for the default organization exclusively, from the properties holding the default permissions template
35 * uuids. These properties are then deleted.
38 * This migration ensures it can run but failing if:
40 * <li>there is more than one organizations (because we can't populate the column for those extra organizations)</li>
41 * <li>the global default permission template can't be found (because an organization must have at least this default template)</li>
45 public class PopulateDefaultPermTemplateColumnsOfOrganizations extends DataChange {
46 private static final String DEFAULT_TEMPLATE_PROPERTY = "sonar.permission.template.default";
47 private static final String DEFAULT_PROJECT_TEMPLATE_PROPERTY = "sonar.permission.template.TRK.default";
48 private static final String DEFAULT_VIEW_TEMPLATE_PROPERTY = "sonar.permission.template.VW.default";
49 private static final String DEFAULT_DEV_TEMPLATE_PROPERTY = "sonar.permission.template.DEV.default";
51 private final DefaultOrganizationUuidProvider defaultOrganizationUuid;
53 public PopulateDefaultPermTemplateColumnsOfOrganizations(Database db, DefaultOrganizationUuidProvider defaultOrganizationUuid) {
55 this.defaultOrganizationUuid = defaultOrganizationUuid;
59 protected void execute(Context context) throws SQLException {
60 String defaultOrganizationUuid = this.defaultOrganizationUuid.getAndCheck(context);
61 ensureOnlyDefaultOrganizationExists(context, defaultOrganizationUuid);
63 Map<String, String> defaultTemplateProperties = retrieveDefaultTemplateProperties(context);
65 String globalDefaultTemplate = defaultTemplateProperties.get(DEFAULT_TEMPLATE_PROPERTY);
66 if (globalDefaultTemplate == null || globalDefaultTemplate.isEmpty()) {
67 // DB has just been created, default template of default organization will be populated by a startup task
70 String projectDefaultTemplate = firstNonNull(defaultTemplateProperties.get(DEFAULT_PROJECT_TEMPLATE_PROPERTY), globalDefaultTemplate);
71 String viewDefaultTemplate = defaultTemplateProperties.get(DEFAULT_VIEW_TEMPLATE_PROPERTY);
73 Loggers.get(PopulateDefaultPermTemplateColumnsOfOrganizations.class)
74 .debug("Setting default templates on default organization '{}': project='{}', view='{}'",
75 defaultOrganizationUuid, projectDefaultTemplate, viewDefaultTemplate);
77 context.prepareUpsert("update organizations set" +
78 " default_perm_template_project=?," +
79 " default_perm_template_view=?" +
82 .setString(1, projectDefaultTemplate)
83 .setString(2, viewDefaultTemplate)
84 .setString(3, defaultOrganizationUuid)
89 context.prepareUpsert("delete from properties where prop_key in (?,?,?,?)")
90 .setString(1, DEFAULT_TEMPLATE_PROPERTY)
91 .setString(2, DEFAULT_PROJECT_TEMPLATE_PROPERTY)
92 .setString(3, DEFAULT_VIEW_TEMPLATE_PROPERTY)
93 .setString(4, DEFAULT_DEV_TEMPLATE_PROPERTY)
98 private static void ensureOnlyDefaultOrganizationExists(Context context, String defaultOrganizationUuid) throws SQLException {
99 Integer otherOrganizationCount = context.prepareSelect("select count(*) from organizations where uuid <> ?")
100 .setString(1, defaultOrganizationUuid)
101 .get(row -> row.getInt(1));
102 checkState(otherOrganizationCount == 0,
103 "Can not migrate DB if more than one organization exists. Remove all organizations but the default one which uuid is '%s'",
104 defaultOrganizationUuid);
107 private static Map<String, String> retrieveDefaultTemplateProperties(Context context) throws SQLException {
108 Map<String, String> templates = new HashMap<>(3);
109 context.prepareSelect("select prop_key,is_empty,text_value from properties where prop_key in (?,?,?)")
110 .setString(1, DEFAULT_TEMPLATE_PROPERTY)
111 .setString(2, DEFAULT_PROJECT_TEMPLATE_PROPERTY)
112 .setString(3, DEFAULT_VIEW_TEMPLATE_PROPERTY)
114 String key = row.getString(1);
115 boolean isEmpty = row.getBoolean(2);
116 String textValue = row.getString(3);
118 templates.put(key, textValue);