]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6732 ensure properties in DB are never altered from CE
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 18 Mar 2016 16:53:30 +0000 (17:53 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 21 Mar 2016 15:44:06 +0000 (16:44 +0100)
server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
server/sonar-ce/src/main/java/org/sonar/ce/db/CeDbClient.java [new file with mode: 0644]
server/sonar-ce/src/main/java/org/sonar/ce/db/ReadOnlyPropertiesDao.java [new file with mode: 0644]
server/sonar-ce/src/main/java/org/sonar/ce/db/package-info.java [new file with mode: 0644]
server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
server/sonar-ce/src/test/java/org/sonar/ce/db/CeDbClientTest.java [new file with mode: 0644]
server/sonar-ce/src/test/java/org/sonar/ce/db/ReadOnlyPropertiesDaoTest.java [new file with mode: 0644]

index ef74282206f768e4cdae85aa028589eeacbcc2ca..7354d63978cd5169196e5bb66da0212642471904 100644 (file)
@@ -35,6 +35,8 @@ import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
 import org.sonar.api.utils.Durations;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.UriReader;
+import org.sonar.ce.db.CeDbClient;
+import org.sonar.ce.db.ReadOnlyPropertiesDao;
 import org.sonar.ce.es.EsIndexerEnabler;
 import org.sonar.ce.property.CePropertyDefinitions;
 import org.sonar.ce.settings.ComputeEngineSettings;
@@ -54,7 +56,6 @@ import org.sonar.core.user.DeprecatedUserFinder;
 import org.sonar.core.util.UuidFactoryImpl;
 import org.sonar.db.DaoModule;
 import org.sonar.db.DatabaseChecker;
-import org.sonar.db.DbClient;
 import org.sonar.db.DefaultDatabase;
 import org.sonar.db.permission.PermissionRepository;
 import org.sonar.db.purge.PurgeProfiler;
@@ -159,8 +160,10 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
     CeUserSession.class,
 
     // DB
-    DbClient.class,
     DaoModule.class,
+    // DbClient.class, replaced by CeDbClient to use ReadOnlyPropertiesDao instead of PropertiesDao
+    ReadOnlyPropertiesDao.class,
+    CeDbClient.class,
     // MigrationStepModule.class, DB maintenance, responsibility of Web Server
 
     // Elasticsearch
@@ -174,9 +177,11 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
     IssueIndex.class,
 
     // Classes kept for backward compatibility of plugins/libs (like sonar-license) that are directly calling classes from the core
-    org.sonar.core.properties.PropertiesDao.class
+    // org.sonar.core.properties.PropertiesDao.class, replaced by ReadOnlyPropertiesDao (declared above) which is a ReadOnly implementation
   };
   private static final Object[] LEVEL_2_COMPONENTS = new Object[] {
+    // add ReadOnlyPropertiesDao at level2 again so that it shadows PropertiesDao
+    ReadOnlyPropertiesDao.class,
     DefaultServerUpgradeStatus.class,
     // no DatabaseMigrator.class, responsibility of Web Server
 
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/db/CeDbClient.java b/server/sonar-ce/src/main/java/org/sonar/ce/db/CeDbClient.java
new file mode 100644 (file)
index 0000000..6cf67f8
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.ce.db;
+
+import java.util.Map;
+import org.sonar.db.Dao;
+import org.sonar.db.Database;
+import org.sonar.db.DbClient;
+import org.sonar.db.MyBatis;
+import org.sonar.db.property.PropertiesDao;
+
+public class CeDbClient extends DbClient {
+  private ReadOnlyPropertiesDao readOnlyPropertiesDao;
+
+  public CeDbClient(Database database, MyBatis myBatis, Dao... daos) {
+    super(database, myBatis, daos);
+  }
+
+  @Override
+  protected void doOnLoad(Map<Class, Dao> daoByClass) {
+    this.readOnlyPropertiesDao = getDao(daoByClass, ReadOnlyPropertiesDao.class);
+  }
+
+  @Override
+  public PropertiesDao propertiesDao() {
+    return this.readOnlyPropertiesDao;
+  }
+}
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/db/ReadOnlyPropertiesDao.java b/server/sonar-ce/src/main/java/org/sonar/ce/db/ReadOnlyPropertiesDao.java
new file mode 100644 (file)
index 0000000..373ae90
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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.ce.db;
+
+import java.util.Map;
+import org.sonar.core.properties.PropertiesDao;
+import org.sonar.db.DbSession;
+import org.sonar.db.MyBatis;
+import org.sonar.db.property.PropertyDto;
+
+/**
+ * Compute Engine specific override of {@link PropertiesDao} and {@link org.sonar.db.property.PropertiesDao} which
+ * implements no write method (ie. insert/update/delete) because updating the Properties is the Web Server responsibility
+ * alone.
+ * <p>
+ * This ugly trick is required because licensed plugin bundle {@link com.sonarsource.license.api.internal.ServerLicenseVerifierImpl}
+ * which update license properties by calling {@link PropertiesDao} directly and this can not be disabled.
+ * </p>
+ */
+public class ReadOnlyPropertiesDao extends PropertiesDao {
+  public ReadOnlyPropertiesDao(MyBatis mybatis) {
+    super(mybatis);
+  }
+
+  @Override
+  public void insertProperty(DbSession session, PropertyDto property) {
+    // do nothing
+  }
+
+  @Override
+  public void insertProperty(PropertyDto property) {
+    // do nothing
+  }
+
+  @Override
+  public void deleteProjectProperty(String key, Long projectId) {
+    // do nothing
+  }
+
+  @Override
+  public void deleteProjectProperty(String key, Long projectId, DbSession session) {
+    // do nothing
+  }
+
+  @Override
+  public void deleteProjectProperties(String key, String value, DbSession session) {
+    // do nothing
+  }
+
+  @Override
+  public void deleteProjectProperties(String key, String value) {
+    // do nothing
+  }
+
+  @Override
+  public void deleteGlobalProperties() {
+    // do nothing
+  }
+
+  @Override
+  public void deleteGlobalProperty(String key, DbSession session) {
+    // do nothing
+  }
+
+  @Override
+  public void deleteGlobalProperty(String key) {
+    // do nothing
+  }
+
+  @Override
+  public void deleteAllProperties(String key) {
+    // do nothing
+  }
+
+  @Override
+  public void insertGlobalProperties(Map<String, String> properties) {
+    // do nothing
+  }
+
+  @Override
+  public void renamePropertyKey(String oldKey, String newKey) {
+    // do nothing
+  }
+
+  @Override
+  public void updateProperties(String key, String oldValue, String newValue) {
+    // do nothing
+  }
+
+  @Override
+  public void updateProperties(String key, String oldValue, String newValue, DbSession session) {
+    // do nothing
+  }
+
+  @Override
+  public void setProperty(org.sonar.core.properties.PropertyDto property) {
+    // do nothing
+  }
+
+}
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/db/package-info.java b/server/sonar-ce/src/main/java/org/sonar/ce/db/package-info.java
new file mode 100644 (file)
index 0000000..74cebb0
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.ce.db;
+
+import javax.annotation.ParametersAreNonnullByDefault;
index b0075cd66777f7c77c711b835aaf2034cf8b5b60..6e9e5dbc6798901cbb1b1a206e5c2418d0416e63 100644 (file)
@@ -89,7 +89,7 @@ public class ComputeEngineContainerImplTest {
       );
     assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize(
       CONTAINER_ITSELF
-      + 10 // level 2
+      + 11 // level 2
       );
     assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize(
       COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/db/CeDbClientTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/db/CeDbClientTest.java
new file mode 100644 (file)
index 0000000..883247a
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.ce.db;
+
+import org.junit.Test;
+import org.sonar.db.Dao;
+import org.sonar.db.Database;
+import org.sonar.db.DbClient;
+import org.sonar.db.MyBatis;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class CeDbClientTest {
+  private Database database = mock(Database.class);
+  private MyBatis myBatis = mock(MyBatis.class);
+  private ReadOnlyPropertiesDao readOnlyPropertiesDao = new ReadOnlyPropertiesDao(myBatis);
+
+  private DbClient underTest = new CeDbClient(database, myBatis, (Dao) readOnlyPropertiesDao);
+
+  @Test
+  public void getPropertiesDao_returns_ReadOnlyPropertiesDao() {
+    assertThat(underTest.propertiesDao()).isSameAs(readOnlyPropertiesDao);
+  }
+}
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/db/ReadOnlyPropertiesDaoTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/db/ReadOnlyPropertiesDaoTest.java
new file mode 100644 (file)
index 0000000..bcb0549
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * 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.ce.db;
+
+import org.junit.Test;
+import org.sonar.db.DbSession;
+import org.sonar.db.MyBatis;
+import org.sonar.db.property.PropertyDto;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+public class ReadOnlyPropertiesDaoTest {
+  private MyBatis myBatis = mock(MyBatis.class);
+  private DbSession dbSession = mock(DbSession.class);
+  private PropertyDto propertyDto = mock(PropertyDto.class);
+  private org.sonar.core.properties.PropertyDto oldPropertyDto = mock(org.sonar.core.properties.PropertyDto.class);
+  private ReadOnlyPropertiesDao underTest = new ReadOnlyPropertiesDao(myBatis);
+
+  @Test
+  public void insertProperty() {
+    underTest.insertProperty(dbSession, propertyDto);
+
+    assertNoInteraction();
+  }
+
+  @Test
+  public void insertProperty1() {
+    underTest.insertProperty(propertyDto);
+
+    assertNoInteraction();
+  }
+
+  @Test
+  public void deleteProjectProperty() {
+    underTest.deleteProjectProperty(null, null);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void deleteProjectProperty1() {
+    underTest.deleteProjectProperty(null, null, dbSession);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void deleteProjectProperties() {
+    underTest.deleteProjectProperties(null, null);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void deleteProjectProperties1() {
+    underTest.deleteProjectProperties(null, null, dbSession);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void deleteGlobalProperties() {
+    underTest.deleteGlobalProperties();
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void deleteGlobalProperty() {
+    underTest.deleteGlobalProperty(null);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void deleteGlobalProperty1() {
+    underTest.deleteGlobalProperty(null, dbSession);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void deleteAllProperties() {
+    underTest.deleteAllProperties(null);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void insertGlobalProperties() {
+    underTest.insertGlobalProperties(null);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void renamePropertyKey() {
+    underTest.renamePropertyKey(null, null);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void updateProperties() {
+    underTest.updateProperties(null, null, null);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void updateProperties1() {
+    underTest.updateProperties(null, null, null, dbSession);
+
+    assertNoInteraction();
+
+  }
+
+  @Test
+  public void setProperty() {
+    underTest.setProperty(oldPropertyDto);
+
+    assertNoInteraction();
+
+  }
+
+  private void assertNoInteraction() {
+    verifyNoMoreInteractions(myBatis, dbSession, propertyDto);
+  }
+}