From 8a0b54de6a665cd26ba35c8e696bf6d66765a531 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Vilain Date: Tue, 16 Jul 2013 17:06:26 +0200 Subject: [PATCH] SONAR-4464 Exclude default permissions properties from the backup / restore operations --- .../configuration/PropertiesBackup.java | 34 ++++-- .../configuration/PropertiesBackupTest.java | 100 +++++++++++++++--- 2 files changed, 113 insertions(+), 21 deletions(-) diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/PropertiesBackup.java b/sonar-server/src/main/java/org/sonar/server/configuration/PropertiesBackup.java index f85e96cc682..85eedeeb50e 100644 --- a/sonar-server/src/main/java/org/sonar/server/configuration/PropertiesBackup.java +++ b/sonar-server/src/main/java/org/sonar/server/configuration/PropertiesBackup.java @@ -33,6 +33,8 @@ import java.util.Map; public class PropertiesBackup implements Backupable { + private static final String PERMISSION_PROPERTIES_PREFIX = "sonar.permission.template"; + private final PersistentSettings persistentSettings; public PropertiesBackup(PersistentSettings persistentSettings) { @@ -43,8 +45,7 @@ public class PropertiesBackup implements Backupable { List xmlProperties = Lists.newArrayList(); for (PropertyDto property : persistentSettings.getGlobalProperties()) { - // "sonar.core.id" must never be restored, it is unique for a server and it created once at the 1rst server startup - if (!CoreProperties.SERVER_ID.equals(property.getKey())) { + if (shouldBeExported(property.getKey())) { xmlProperties.add(new Property(property.getKey(), property.getValue())); } } @@ -54,19 +55,20 @@ public class PropertiesBackup implements Backupable { public void importXml(SonarConfig sonarConfig) { LoggerFactory.getLogger(getClass()).info("Restore properties"); - // "sonar.core.id" property should not be cleared, because it is the unique key used to identify the server - // and it is used by the batch to verify that it connects to the same DB as the remote server (see SONAR-3126). - String serverId = persistentSettings.getString(CoreProperties.SERVER_ID); - String serverStartTime = persistentSettings.getString(CoreProperties.SERVER_STARTTIME); - Map properties = Maps.newHashMap(); + if (sonarConfig.getProperties() != null && !sonarConfig.getProperties().isEmpty()) { for (Property xmlProperty : sonarConfig.getProperties()) { properties.put(xmlProperty.getKey(), xmlProperty.getValue()); } } - properties.put(CoreProperties.SERVER_ID, serverId); - properties.put(CoreProperties.SERVER_STARTTIME, serverStartTime); + + for (PropertyDto property : persistentSettings.getGlobalProperties()) { + if (shouldNotBeErased(property.getKey())) { + properties.put(property.getKey(), property.getValue()); + } + } + persistentSettings.deleteProperties(); persistentSettings.saveProperties(properties); } @@ -74,4 +76,18 @@ public class PropertiesBackup implements Backupable { public void configure(XStream xStream) { xStream.alias("property", Property.class); } + + private boolean shouldBeExported(String propertyKey) { + // "sonar.core.id" must never be restored, it is unique for a server and it created once at the 1rst server startup + // default permissions properties should not be exported as they reference permission_templates entries in the DB + return !CoreProperties.SERVER_ID.equals(propertyKey) && !propertyKey.startsWith(PERMISSION_PROPERTIES_PREFIX); + } + + private boolean shouldNotBeErased(String propertyKey) { + // "sonar.core.id" property should not be cleared, because it is the unique key used to identify the server + // and it is used by the batch to verify that it connects to the same DB as the remote server (see SONAR-3126). + // default permissions properties should not be erased as they reference permission_templates entries in the DB + return CoreProperties.SERVER_ID.equals(propertyKey) || CoreProperties.SERVER_STARTTIME.equals(propertyKey) + || propertyKey.startsWith(PERMISSION_PROPERTIES_PREFIX); + } } diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/PropertiesBackupTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/PropertiesBackupTest.java index 0807e3fe6c2..39c408126be 100644 --- a/sonar-server/src/test/java/org/sonar/server/configuration/PropertiesBackupTest.java +++ b/sonar-server/src/test/java/org/sonar/server/configuration/PropertiesBackupTest.java @@ -19,27 +19,26 @@ */ package org.sonar.server.configuration; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; -import org.hamcrest.collection.IsMapContaining; +import org.hamcrest.Description; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentMatcher; import org.sonar.api.CoreProperties; import org.sonar.api.database.configuration.Property; import org.sonar.core.properties.PropertyDto; -import org.sonar.jpa.test.AbstractDbUnitTestCase; import org.sonar.server.platform.PersistentSettings; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; -public class PropertiesBackupTest extends AbstractDbUnitTestCase { +public class PropertiesBackupTest { private PersistentSettings persistentSettings; private PropertiesBackup backup; @@ -52,7 +51,8 @@ public class PropertiesBackupTest extends AbstractDbUnitTestCase { @Test public void shouldExportProperties() { - when(persistentSettings.getGlobalProperties()).thenReturn(Lists.newArrayList(new PropertyDto().setKey("key1").setValue("value1"), new PropertyDto().setKey("key2").setValue("value2"))); + when(persistentSettings.getGlobalProperties()) + .thenReturn(Lists.newArrayList(new PropertyDto().setKey("key1").setValue("value1"), new PropertyDto().setKey("key2").setValue("value2"))); SonarConfig config = new SonarConfig(); backup.exportXml(config); @@ -62,7 +62,8 @@ public class PropertiesBackupTest extends AbstractDbUnitTestCase { @Test public void shouldNotExportServerId() { - when(persistentSettings.getGlobalProperties()).thenReturn(Lists.newArrayList(new PropertyDto().setKey(CoreProperties.SERVER_ID).setValue("111"), new PropertyDto().setKey("key").setValue("value"))); + when(persistentSettings.getGlobalProperties()) + .thenReturn(Lists.newArrayList(new PropertyDto().setKey(CoreProperties.SERVER_ID).setValue("111"), new PropertyDto().setKey("key").setValue("value"))); SonarConfig config = new SonarConfig(); backup.exportXml(config); @@ -77,19 +78,94 @@ public class PropertiesBackupTest extends AbstractDbUnitTestCase { backup.importXml(config); - verify(persistentSettings).saveProperties(argThat(IsMapContaining.hasEntry("key1", "value1"))); + Map expectedProperties = new HashMap(); + expectedProperties.put("key1", "value1"); + verify(persistentSettings).saveProperties(argThat(IsMap.containing(expectedProperties))); } @Test public void shouldNotImportServerId() { // initial server id - when(persistentSettings.getString(CoreProperties.SERVER_ID)).thenReturn("111"); + when(persistentSettings.getGlobalProperties()).thenReturn(Lists.newArrayList( + new PropertyDto().setKey(CoreProperties.SERVER_ID).setValue("111"))); Collection newProperties = Arrays.asList(new Property(CoreProperties.SERVER_ID, "999")); SonarConfig config = new SonarConfig(); config.setProperties(newProperties); backup.importXml(config); - verify(persistentSettings).saveProperties(argThat(IsMapContaining.hasEntry(CoreProperties.SERVER_ID, "111"))); + Map expectedProperties = new HashMap(); + expectedProperties.put(CoreProperties.SERVER_ID, "111"); + verify(persistentSettings).saveProperties(argThat(IsMap.containing(expectedProperties))); + } + + @Test + public void shouldNotImportPermissionProperties() throws Exception { + when(persistentSettings.getGlobalProperties()).thenReturn(Lists.newArrayList( + new PropertyDto().setKey("sonar.permission.template.default").setValue("default_template"), + new PropertyDto().setKey("sonar.permission.template.TRK.default").setValue("default_template_for_projects"), + new PropertyDto().setKey("erasable_key").setValue("erasable_value"))); + + Collection newProperties = Arrays.asList( + new Property("sonar.permission.template.default", "another_default"), + new Property("key_to_import", "value_to_import"), + new Property("erasable_key", "new_value")); + SonarConfig config = new SonarConfig(); + config.setProperties(newProperties); + backup.importXml(config); + + Map expectedProperties = new HashMap(); + expectedProperties.put("key_to_import", "value_to_import"); + expectedProperties.put("erasable_key", "new_value"); + expectedProperties.put("sonar.permission.template.default", "default_template"); + expectedProperties.put("sonar.permission.template.TRK.default", "default_template_for_projects"); + verify(persistentSettings).saveProperties(argThat(IsMap.containing(expectedProperties))); + } + + @Test + public void shouldNotExportPermissionProperties() throws Exception { + when(persistentSettings.getGlobalProperties()).thenReturn(Lists.newArrayList( + new PropertyDto().setKey("sonar.permission.template.default").setValue("default_template"), + new PropertyDto().setKey("sonar.permission.template.TRK.default").setValue("default_template_for_projects"), + new PropertyDto().setKey("key").setValue("value"))); + + SonarConfig config = new SonarConfig(); + backup.exportXml(config); + + assertThat(config.getProperties()).containsOnly(new Property("key", "value")); + } + + private static class IsMap extends ArgumentMatcher> { + + private final Map referenceMap; + + private IsMap(Map referenceMap) { + this.referenceMap = referenceMap; + } + + static IsMap containing(Map keyValuePairs) { + return new IsMap(keyValuePairs); + } + + @Override + public boolean matches(Object argument) { + if(argument != null && argument instanceof Map) { + Map argAsMap = (Map) argument; + for (String key : argAsMap.keySet()) { + if(!referenceMap.containsKey(key) || !referenceMap.get(key).equals(argAsMap.get(key))) { + return false; + } + } + return true; + } + return false; + } + + @Override + public void describeTo(Description description) { + if(referenceMap != null) { + description.appendText(referenceMap.toString()); + } + } } } -- 2.39.5