aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2019-08-05 16:04:11 -0500
committerSonarTech <sonartech@sonarsource.com>2019-09-24 20:21:12 +0200
commitd2bba782392ad2390d790b15c8eddb24f37acd1e (patch)
treea1fc476f5cc1164e77f1c5872cd0304c94fae977
parent09a0e34e0e4f22bb848a7339d6fe0153ac1ae97b (diff)
downloadsonarqube-d2bba782392ad2390d790b15c8eddb24f37acd1e.tar.gz
sonarqube-d2bba782392ad2390d790b15c8eddb24f37acd1e.zip
SONAR-12366 Create WS to read/write New Code Periods
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java5
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/newcodeperiod/NewCodePeriodDaoTest.java38
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/CreateNewCodePeriodTableTest.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/setting/ws/GetNewCodePeriodAction.java63
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/setting/ws/ShowNewCodePeriodAction.java175
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/setting/ws/UpdateNewCodePeriodAction.java (renamed from server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetNewCodePeriodAction.java)25
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/setting/ws/ShowNewCodePeriodActionTest.java247
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/setting/ws/UpdateNewCodePeriodActionTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetNewCodePeriodActionTest.java)89
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SettingsWsModule.java4
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/ws/SettingsWsModuleTest.java2
-rw-r--r--sonar-ws/src/main/protobuf/ws-settings.proto15
11 files changed, 504 insertions, 161 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java
index 6ef05723cff..4ffc6cd4dd6 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java
@@ -64,11 +64,6 @@ public class NewCodePeriodDao implements Dao {
}
}
- public void update(DbSession dbSession, NewCodePeriodDto dto) {
- requireNonNull(dto.getType(), "Type of NewCodePeriod must be specified.");
- mapper(dbSession).update(dto.setUpdatedAt(system2.now()));
- }
-
public Optional<NewCodePeriodDto> selectByProject(DbSession dbSession, String projectUuid) {
requireNonNull(projectUuid, "Project uuid must be specified.");
return Optional.ofNullable(mapper(dbSession).selectByProject(projectUuid));
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/newcodeperiod/NewCodePeriodDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/newcodeperiod/NewCodePeriodDaoTest.java
index 14f2fe68bf9..f9d675c9e30 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/newcodeperiod/NewCodePeriodDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/newcodeperiod/NewCodePeriodDaoTest.java
@@ -69,36 +69,6 @@ public class NewCodePeriodDaoTest {
}
@Test
- public void update_new_code_period() {
- when(uuidFactory.create()).thenReturn("uuid-1");
-
- NewCodePeriodDto dto = db.newCodePeriods().insert(new NewCodePeriodDto()
- .setProjectUuid("proj-uuid")
- .setBranchUuid("branch-uuid")
- .setType(NewCodePeriodType.NUMBER_OF_DAYS)
- .setValue("5"));
-
- underTest.update(dbSession, new NewCodePeriodDto()
- .setUuid(dto.getUuid())
- .setType(NewCodePeriodType.SPECIFIC_ANALYSIS)
- .setValue("analysis-uuid"));
-
- Optional<NewCodePeriodDto> resultOpt = underTest.selectByUuid(dbSession, "uuid-1");
-
- assertThat(resultOpt).isNotNull();
- assertThat(resultOpt).isNotEmpty();
-
- NewCodePeriodDto result = resultOpt.get();
- assertThat(result.getUuid()).isEqualTo("uuid-1");
- assertThat(result.getProjectUuid()).isEqualTo("proj-uuid");
- assertThat(result.getBranchUuid()).isEqualTo("branch-uuid");
- assertThat(result.getType()).isEqualTo(NewCodePeriodType.SPECIFIC_ANALYSIS);
- assertThat(result.getValue()).isEqualTo("analysis-uuid");
- assertThat(result.getCreatedAt()).isNotEqualTo(0);
- assertThat(result.getUpdatedAt()).isNotEqualTo(0);
- }
-
- @Test
public void insert_with_upsert() {
when(uuidFactory.create()).thenReturn("uuid-1");
@@ -135,6 +105,8 @@ public class NewCodePeriodDaoTest {
underTest.upsert(dbSession, new NewCodePeriodDto()
.setType(NewCodePeriodType.SPECIFIC_ANALYSIS)
+ .setProjectUuid("proj-uuid")
+ .setBranchUuid("branch-uuid")
.setValue("analysis-uuid"));
Optional<NewCodePeriodDto> resultOpt = underTest.selectByUuid(dbSession, "uuid-1");
@@ -167,7 +139,7 @@ public class NewCodePeriodDaoTest {
assertThat(resultOpt).isNotEmpty();
NewCodePeriodDto result = resultOpt.get();
- assertThat(result.getUuid()).isEqualTo("uuid-1");
+ assertThat(result.getUuid()).isEqualTo("1");
assertThat(result.getProjectUuid()).isEqualTo("proj-uuid");
assertThat(result.getBranchUuid()).isEqualTo("branch-uuid");
assertThat(result.getType()).isEqualTo(NewCodePeriodType.NUMBER_OF_DAYS);
@@ -191,7 +163,7 @@ public class NewCodePeriodDaoTest {
assertThat(resultOpt).isNotEmpty();
NewCodePeriodDto result = resultOpt.get();
- assertThat(result.getUuid()).isEqualTo("uuid-1");
+ assertThat(result.getUuid()).isEqualTo("1");
assertThat(result.getProjectUuid()).isEqualTo("proj-uuid");
assertThat(result.getBranchUuid()).isNull();
assertThat(result.getType()).isEqualTo(NewCodePeriodType.NUMBER_OF_DAYS);
@@ -211,7 +183,7 @@ public class NewCodePeriodDaoTest {
.setValue("30"));
NewCodePeriodDto result = underTest.selectGlobal(dbSession);
- assertThat(result.getUuid()).isEqualTo("uuid-1");
+ assertThat(result.getUuid()).isEqualTo("1");
assertThat(result.getProjectUuid()).isNull();
assertThat(result.getBranchUuid()).isNull();
assertThat(result.getType()).isEqualTo(NewCodePeriodType.NUMBER_OF_DAYS);
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/CreateNewCodePeriodTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/CreateNewCodePeriodTableTest.java
index 06a3664429d..dfee7c48dea 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/CreateNewCodePeriodTableTest.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/CreateNewCodePeriodTableTest.java
@@ -50,7 +50,7 @@ public class CreateNewCodePeriodTableTest {
dbTester.assertColumnDefinition(TABLE_NAME, "project_uuid", VARCHAR, 40, true);
dbTester.assertColumnDefinition(TABLE_NAME, "branch_uuid", VARCHAR, 40, true);
dbTester.assertColumnDefinition(TABLE_NAME, "type", VARCHAR, 30, false);
- dbTester.assertColumnDefinition(TABLE_NAME, "value", VARCHAR, 40, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "value", VARCHAR, 40, true);
dbTester.assertColumnDefinition(TABLE_NAME, "updated_at", BIGINT, 20, false);
dbTester.assertColumnDefinition(TABLE_NAME, "created_at", BIGINT, 20, false);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/GetNewCodePeriodAction.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/GetNewCodePeriodAction.java
deleted file mode 100644
index 47d00ddd82a..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/GetNewCodePeriodAction.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info 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.setting.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.newcodeperiod.NewCodePeriodDao;
-import org.sonar.server.user.UserSession;
-
-public class GetNewCodePeriodAction implements SettingsWsAction {
- private final DbClient dbClient;
- private final UserSession userSession;
- private final NewCodePeriodDao newCodePeriodDao;
-
- public GetNewCodePeriodAction(DbClient dbClient, UserSession userSession, NewCodePeriodDao newCodePeriodDao) {
- this.dbClient = dbClient;
- this.userSession = userSession;
- this.newCodePeriodDao = newCodePeriodDao;
- }
-
- @Override
- public void define(WebService.NewController context) {
- context.createAction("get_new_code_period")
- .setDescription("Updates the setting for the New Code Period.<br>" +
- "Requires one of the following permissions: " +
- "<ul>" +
- "<li>'Administer System'</li>" +
- "<li>'Administer' rights on the specified component</li>" +
- "</ul>")
- .setSince("8.0")
- .setResponseExample(getClass().getResource("generate_secret_key-example.json"))
- .setHandler(this);
- }
-
- @Override
- public void handle(Request request, Response response) throws Exception {
- userSession.checkIsSystemAdministrator();
- try (DbSession dbSession = dbClient.openSession(false)) {
- // TODO should it fall back branch->project->global?
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ShowNewCodePeriodAction.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ShowNewCodePeriodAction.java
new file mode 100644
index 00000000000..2c033bae81b
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ShowNewCodePeriodAction.java
@@ -0,0 +1,175 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.setting.ws;
+
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.BranchType;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.newcodeperiod.NewCodePeriodDao;
+import org.sonar.db.newcodeperiod.NewCodePeriodDto;
+import org.sonar.db.newcodeperiod.NewCodePeriodType;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.Settings;
+import org.sonarqube.ws.Settings.ShowNewCodePeriodResponse;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+import static org.sonar.server.component.ComponentFinder.ParamNames.PROJECT_ID_AND_KEY;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+
+public class ShowNewCodePeriodAction implements SettingsWsAction {
+ private static final String PARAM_BRANCH = "branch";
+ private static final String PARAM_PROJECT = "project";
+
+ private final DbClient dbClient;
+ private final UserSession userSession;
+ private final ComponentFinder componentFinder;
+ private final NewCodePeriodDao newCodePeriodDao;
+
+ public ShowNewCodePeriodAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, NewCodePeriodDao newCodePeriodDao) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ this.componentFinder = componentFinder;
+ this.newCodePeriodDao = newCodePeriodDao;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction("show_new_code_period")
+ .setDescription("Shows a setting for the New Code Period.<br>" +
+ "Requires one of the following permissions: " +
+ "<ul>" +
+ "<li>'Administer System'</li>" +
+ "<li>'Administer' rights on the specified component</li>" +
+ "</ul>")
+ .setSince("8.0")
+ .setResponseExample(getClass().getResource("generate_secret_key-example.json"))
+ .setHandler(this);
+
+ action.createParam(PARAM_PROJECT)
+ .setDescription("Project key");
+ action.createParam(PARAM_BRANCH)
+ .setDescription("Branch key");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ String projectStr = request.getParam(PARAM_PROJECT).emptyAsNull().or(() -> null);
+ String branchStr = request.getParam(PARAM_BRANCH).emptyAsNull().or(() -> null);
+
+ if (projectStr == null && branchStr != null) {
+ throw new IllegalArgumentException("If branch key is specified, project key needs to be specified too");
+ }
+
+ try (DbSession dbSession = dbClient.openSession(false)) {
+
+ ComponentDto projectBranch = null;
+ String projectUuid = null;
+ String branchUuid = null;
+
+ if (projectStr != null) {
+ projectBranch = getProject(dbSession, projectStr, branchStr);
+ userSession.checkComponentPermission(UserRole.ADMIN, projectBranch);
+ if (branchStr != null) {
+ branchUuid = projectBranch.uuid();
+ }
+ // depending whether it's the main branch or not
+ projectUuid = projectBranch.getMainBranchProjectUuid() != null ? projectBranch.getMainBranchProjectUuid() : projectBranch.uuid();
+ }
+
+ ShowNewCodePeriodResponse.Builder builder = get(dbSession, projectUuid, branchUuid, false);
+
+ if (projectStr != null) {
+ builder.setProjectKey(projectStr);
+ }
+ if (branchStr != null) {
+ builder.setBranchKey(branchStr);
+ }
+ writeProtobuf(builder.build(), request, response);
+ }
+ }
+
+ private ShowNewCodePeriodResponse.Builder get(DbSession dbSession, @Nullable String projectUuid, @Nullable String branchUuid, boolean inherited) {
+ if (projectUuid == null) {
+ return build(newCodePeriodDao.selectGlobal(dbSession), inherited);
+ }
+ if (branchUuid == null) {
+ Optional<NewCodePeriodDto> dto = newCodePeriodDao.selectByProject(dbSession, projectUuid);
+ return dto.map(d -> build(d, inherited))
+ .orElseGet(() -> get(dbSession, null, null, true));
+ }
+
+ Optional<NewCodePeriodDto> dto = newCodePeriodDao.selectByBranch(dbSession, projectUuid, branchUuid);
+ return dto.map(d -> build(d, inherited))
+ .orElseGet(() -> get(dbSession, projectUuid, null, true));
+ }
+
+ private ShowNewCodePeriodResponse.Builder build(NewCodePeriodDto dto, boolean inherited) {
+ ShowNewCodePeriodResponse.Builder builder = ShowNewCodePeriodResponse.newBuilder()
+ .setType(convertType(dto.getType()))
+ .setInherited(inherited);
+
+ if (dto.getValue() != null) {
+ builder.setValue(dto.getValue());
+ }
+ return builder;
+ }
+
+ private Settings.NewCodePeriodType convertType(NewCodePeriodType type) {
+ switch (type) {
+ case NUMBER_OF_DAYS:
+ return Settings.NewCodePeriodType.NUMBER_OF_DAYS;
+ case DATE:
+ return Settings.NewCodePeriodType.DATE;
+ case PREVIOUS_VERSION:
+ return Settings.NewCodePeriodType.PREVIOUS_VERSION;
+ case SPECIFIC_ANALYSIS:
+ return Settings.NewCodePeriodType.SPECIFIC_ANALYSIS;
+ default:
+ throw new IllegalStateException("Unexpected type: " + type);
+ }
+ }
+
+ private ComponentDto getProject(DbSession dbSession, String projectKey, @Nullable String branchKey) {
+ if (branchKey == null) {
+ return componentFinder.getByUuidOrKey(dbSession, null, projectKey, PROJECT_ID_AND_KEY);
+ }
+ ComponentDto project = componentFinder.getByKeyAndBranch(dbSession, projectKey, branchKey);
+
+ BranchDto branchDto = dbClient.branchDao().selectByUuid(dbSession, project.uuid())
+ .orElseThrow(() -> new NotFoundException(format("Branch '%s' is not found", branchKey)));
+
+ checkArgument(branchDto.getBranchType() == BranchType.LONG,
+ "Not a long-living branch: '%s'", branchKey);
+
+ return project;
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetNewCodePeriodAction.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/UpdateNewCodePeriodAction.java
index bc8259c6fef..d3126956172 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetNewCodePeriodAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/UpdateNewCodePeriodAction.java
@@ -50,9 +50,9 @@ import static org.sonar.db.newcodeperiod.NewCodePeriodType.PREVIOUS_VERSION;
import static org.sonar.db.newcodeperiod.NewCodePeriodType.SPECIFIC_ANALYSIS;
import static org.sonar.server.component.ComponentFinder.ParamNames.PROJECT_ID_AND_KEY;
-public class SetNewCodePeriodAction implements SettingsWsAction {
- private static final String PARAM_BRANCH = "branchKey";
- private static final String PARAM_PROJECT = "projectKey";
+public class UpdateNewCodePeriodAction implements SettingsWsAction {
+ private static final String PARAM_BRANCH = "branch";
+ private static final String PARAM_PROJECT = "project";
private static final String PARAM_TYPE = "type";
private static final String PARAM_VALUE = "value";
private static final Set<NewCodePeriodType> OVERALL_TYPES = ImmutableSet.of(PREVIOUS_VERSION, NUMBER_OF_DAYS);
@@ -64,7 +64,7 @@ public class SetNewCodePeriodAction implements SettingsWsAction {
private final ComponentFinder componentFinder;
private final NewCodePeriodDao newCodePeriodDao;
- public SetNewCodePeriodAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, NewCodePeriodDao newCodePeriodDao) {
+ public UpdateNewCodePeriodAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, NewCodePeriodDao newCodePeriodDao) {
this.dbClient = dbClient;
this.userSession = userSession;
this.componentFinder = componentFinder;
@@ -73,15 +73,14 @@ public class SetNewCodePeriodAction implements SettingsWsAction {
@Override
public void define(WebService.NewController context) {
- WebService.NewAction action = context.createAction("set_new_code_period")
+ WebService.NewAction action = context.createAction("update_new_code_period")
.setDescription("Updates the setting for the New Code Period.<br>" +
"Requires one of the following permissions: " +
"<ul>" +
- "<li>'Administer System'</li>" +
- "<li>'Administer' rights on the specified component</li>" +
+ "<li>'Administer System' to change the global setting</li>" +
+ "<li>'Administer' rights for a specified component</li>" +
"</ul>")
.setSince("8.0")
- .setResponseExample(getClass().getResource("generate_secret_key-example.json"))
.setHandler(this);
action.createParam(PARAM_PROJECT)
@@ -116,15 +115,19 @@ public class SetNewCodePeriodAction implements SettingsWsAction {
if (projectStr != null) {
projectBranch = getProject(dbSession, projectStr, branchStr);
userSession.checkComponentPermission(UserRole.ADMIN, projectBranch);
- dto.setProjectUuid(projectBranch.projectUuid());
+ if (branchStr != null) {
+ dto.setBranchUuid(projectBranch.uuid());
+ }
+ // depending whether it's the main branch or not
+ dto.setProjectUuid(projectBranch.getMainBranchProjectUuid() != null ? projectBranch.getMainBranchProjectUuid() : projectBranch.uuid());
} else {
userSession.checkIsSystemAdministrator();
}
setValue(dbSession, dto, type, projectBranch, branchStr, valueStr);
- // TODO upsert?
- newCodePeriodDao.insert(dbSession, dto);
+ newCodePeriodDao.upsert(dbSession, dto);
+ dbSession.commit();
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ShowNewCodePeriodActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ShowNewCodePeriodActionTest.java
new file mode 100644
index 00000000000..de1b36af126
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ShowNewCodePeriodActionTest.java
@@ -0,0 +1,247 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.setting.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchType;
+import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.newcodeperiod.NewCodePeriodDao;
+import org.sonar.db.newcodeperiod.NewCodePeriodDbTester;
+import org.sonar.db.newcodeperiod.NewCodePeriodDto;
+import org.sonar.db.newcodeperiod.NewCodePeriodType;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.component.TestComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.Settings;
+import org.sonarqube.ws.Settings.ShowNewCodePeriodResponse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ShowNewCodePeriodActionTest {
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ private ComponentDbTester componentDb = new ComponentDbTester(db);
+ private DbClient dbClient = db.getDbClient();
+ private DbSession dbSession = db.getSession();
+ private ComponentFinder componentFinder = TestComponentFinder.from(db);
+ private NewCodePeriodDao dao = new NewCodePeriodDao(System2.INSTANCE, UuidFactoryFast.getInstance());
+ private NewCodePeriodDbTester tester = new NewCodePeriodDbTester(db);
+ private ShowNewCodePeriodAction underTest = new ShowNewCodePeriodAction(dbClient, userSession, componentFinder, dao);
+ private WsActionTester ws = new WsActionTester(underTest);
+
+ @Test
+ public void test_definition() {
+ WebService.Action definition = ws.getDef();
+
+ assertThat(definition.key()).isEqualTo("show_new_code_period");
+ assertThat(definition.isInternal()).isFalse();
+ assertThat(definition.since()).isEqualTo("8.0");
+ assertThat(definition.isPost()).isFalse();
+
+ assertThat(definition.params()).extracting(WebService.Param::key).containsOnly("project", "branch");
+ assertThat(definition.param("project").isRequired()).isFalse();
+ assertThat(definition.param("branch").isRequired()).isFalse();
+ }
+
+ @Test
+ public void throw_IAE_if_branch_is_specified_without_project() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("If branch key is specified, project key needs to be specified too");
+
+ ws.newRequest()
+ .setParam("branch", "branch")
+ .execute();
+ }
+
+ @Test
+ public void throw_NFE_if_project_not_found() {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Component key 'unknown' not found");
+
+ ws.newRequest()
+ .setParam("project", "unknown")
+ .execute();
+ }
+
+ @Test
+ public void throw_NFE_if_branch_not_found() {
+ ComponentDto project = componentDb.insertMainBranch();
+ logInAsProjectAdministrator(project);
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Component '" + project.getKey() + "' on branch 'unknown' not found");
+
+ ws.newRequest()
+ .setParam("project", project.getKey())
+ .setParam("branch", "unknown")
+ .execute();
+ }
+
+ @Test
+ public void throw_IAE_if_branch_is_a_SLB() {
+ ComponentDto project = componentDb.insertMainBranch();
+ ComponentDto branch = componentDb.insertProjectBranch(project, b -> b.setKey("branch").setBranchType(BranchType.SHORT));
+ logInAsProjectAdministrator(project);
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Not a long-living branch: 'branch'");
+
+ ws.newRequest()
+ .setParam("project", project.getKey())
+ .setParam("branch", "branch")
+ .execute();
+ }
+
+ @Test
+ public void throw_NFE_if_no_project_permission() {
+ ComponentDto project = componentDb.insertMainBranch();
+ expectedException.expect(ForbiddenException.class);
+ expectedException.expectMessage("Insufficient privileges");
+
+ ws.newRequest()
+ .setParam("project", project.getKey())
+ .execute();
+ }
+
+ @Test
+ public void show_global_setting() {
+ tester.insert(new NewCodePeriodDto().setType(NewCodePeriodType.PREVIOUS_VERSION));
+
+ ShowNewCodePeriodResponse response = ws.newRequest()
+ .executeProtobuf(ShowNewCodePeriodResponse.class);
+
+ assertResponse(response, "", "", Settings.NewCodePeriodType.PREVIOUS_VERSION, "", false);
+ }
+
+ @Test
+ public void show_project_setting() {
+ ComponentDto project = componentDb.insertMainBranch();
+ logInAsProjectAdministrator(project);
+
+ tester.insert(new NewCodePeriodDto()
+ .setProjectUuid(project.uuid())
+ .setType(NewCodePeriodType.NUMBER_OF_DAYS)
+ .setValue("4"));
+
+ ShowNewCodePeriodResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .executeProtobuf(ShowNewCodePeriodResponse.class);
+
+ assertResponse(response, project.getKey(), "", Settings.NewCodePeriodType.NUMBER_OF_DAYS, "4", false);
+ }
+
+ @Test
+ public void show_branch_setting() {
+ ComponentDto project = componentDb.insertMainBranch();
+ logInAsProjectAdministrator(project);
+
+ ComponentDto branch = componentDb.insertProjectBranch(project, b -> b.setKey("branch"));
+
+ tester.insert(new NewCodePeriodDto()
+ .setProjectUuid(project.uuid())
+ .setBranchUuid(branch.uuid())
+ .setType(NewCodePeriodType.DATE)
+ .setValue("2018-04-05"));
+
+ ShowNewCodePeriodResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .setParam("branch", "branch")
+ .executeProtobuf(ShowNewCodePeriodResponse.class);
+
+ assertResponse(response, project.getKey(), "branch", Settings.NewCodePeriodType.DATE, "2018-04-05", false);
+ }
+
+ @Test
+ public void show_inherited_project_setting() {
+ ComponentDto project = componentDb.insertMainBranch();
+ logInAsProjectAdministrator(project);
+ tester.insert(new NewCodePeriodDto().setType(NewCodePeriodType.PREVIOUS_VERSION));
+
+ ShowNewCodePeriodResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .executeProtobuf(ShowNewCodePeriodResponse.class);
+
+ assertResponse(response, project.getKey(), "", Settings.NewCodePeriodType.PREVIOUS_VERSION, "", true);
+ }
+
+ @Test
+ public void show_inherited_branch_setting_from_project() {
+ ComponentDto project = componentDb.insertMainBranch();
+ logInAsProjectAdministrator(project);
+
+ ComponentDto branch = componentDb.insertProjectBranch(project, b -> b.setKey("branch"));
+
+ tester.insert(new NewCodePeriodDto()
+ .setProjectUuid(project.uuid())
+ .setType(NewCodePeriodType.DATE)
+ .setValue("2018-04-05"));
+
+ ShowNewCodePeriodResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .setParam("branch", "branch")
+ .executeProtobuf(ShowNewCodePeriodResponse.class);
+
+ assertResponse(response, project.getKey(), "branch", Settings.NewCodePeriodType.DATE, "2018-04-05", true);
+ }
+
+ @Test
+ public void show_inherited_branch_setting_from_global() {
+ ComponentDto project = componentDb.insertMainBranch();
+ logInAsProjectAdministrator(project);
+ ComponentDto branch = componentDb.insertProjectBranch(project, b -> b.setKey("branch"));
+ tester.insert(new NewCodePeriodDto().setType(NewCodePeriodType.NUMBER_OF_DAYS).setValue("3"));
+
+ ShowNewCodePeriodResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .setParam("branch", "branch")
+ .executeProtobuf(ShowNewCodePeriodResponse.class);
+
+ assertResponse(response, project.getKey(), "branch", Settings.NewCodePeriodType.NUMBER_OF_DAYS, "3", true);
+ }
+
+ private void assertResponse(ShowNewCodePeriodResponse response, String projectKey, String branchKey, Settings.NewCodePeriodType type, String value, boolean inherited) {
+ assertThat(response.getBranchKey()).isEqualTo(branchKey);
+ assertThat(response.getProjectKey()).isEqualTo(projectKey);
+ assertThat(response.getInherited()).isEqualTo(inherited);
+ assertThat(response.getValue()).isEqualTo(value);
+ assertThat(response.getType()).isEqualTo(type);
+ }
+
+ private void logInAsProjectAdministrator(ComponentDto project) {
+ userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
+ }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetNewCodePeriodActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/UpdateNewCodePeriodActionTest.java
index d0d5c9400a0..740bf44d85d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetNewCodePeriodActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/UpdateNewCodePeriodActionTest.java
@@ -26,6 +26,7 @@ import org.junit.rules.ExpectedException;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
+import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
@@ -45,7 +46,7 @@ import org.sonar.server.ws.WsActionTester;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
-public class SetNewCodePeriodActionTest {
+public class UpdateNewCodePeriodActionTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
@@ -57,28 +58,25 @@ public class SetNewCodePeriodActionTest {
private DbClient dbClient = db.getDbClient();
private DbSession dbSession = db.getSession();
private ComponentFinder componentFinder = TestComponentFinder.from(db);
- private NewCodePeriodDao dao = new NewCodePeriodDao(System2.INSTANCE);
- private DbTester dbTester = DbTester.create();
+ private NewCodePeriodDao dao = new NewCodePeriodDao(System2.INSTANCE, UuidFactoryFast.getInstance());
- private SetNewCodePeriodAction underTest = new SetNewCodePeriodAction(dbClient, userSession, componentFinder, dao);
+ private UpdateNewCodePeriodAction underTest = new UpdateNewCodePeriodAction(dbClient, userSession, componentFinder, dao);
private WsActionTester ws = new WsActionTester(underTest);
@Test
public void test_definition() {
WebService.Action definition = ws.getDef();
- assertThat(definition.key()).isEqualTo("set_new_code_period");
+ assertThat(definition.key()).isEqualTo("update_new_code_period");
assertThat(definition.isInternal()).isFalse();
- //assertThat(definition.responseExampleAsString()).isNotEmpty();
assertThat(definition.since()).isEqualTo("8.0");
assertThat(definition.isPost()).isFalse();
- assertThat(definition.params()).extracting(WebService.Param::key).containsOnly("value", "type", "projectKey", "branchKey");
+ assertThat(definition.params()).extracting(WebService.Param::key).containsOnly("value", "type", "project", "branch");
assertThat(definition.param("value").isRequired()).isFalse();
assertThat(definition.param("type").isRequired()).isTrue();
- assertThat(definition.param("projectKey").isRequired()).isFalse();
- assertThat(definition.param("branchKey").isRequired()).isFalse();
-
+ assertThat(definition.param("project").isRequired()).isFalse();
+ assertThat(definition.param("branch").isRequired()).isFalse();
}
// validation of type
@@ -104,7 +102,7 @@ public class SetNewCodePeriodActionTest {
@Test
public void throw_IAE_if_type_is_invalid_for_global() {
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Invalid type 'DATE'. Overall setting can only be set with types: [PREVIOUS_VERSION, DAYS]");
+ expectedException.expectMessage("Invalid type 'DATE'. Overall setting can only be set with types: [PREVIOUS_VERSION, NUMBER_OF_DAYS]");
ws.newRequest()
.setParam("type", "date")
@@ -117,10 +115,10 @@ public class SetNewCodePeriodActionTest {
logInAsProjectAdministrator(project);
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Invalid type 'ANALYSIS'. Projects can only be set with types: [DATE, PREVIOUS_VERSION, DAYS]");
+ expectedException.expectMessage("Invalid type 'SPECIFIC_ANALYSIS'. Projects can only be set with types: [DATE, PREVIOUS_VERSION, NUMBER_OF_DAYS]");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "specific_analysis")
.execute();
}
@@ -134,7 +132,7 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("New Code Period type 'DATE' requires a value");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "date")
.execute();
}
@@ -144,11 +142,11 @@ public class SetNewCodePeriodActionTest {
ComponentDto project = componentDb.insertMainBranch();
logInAsProjectAdministrator(project);
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("New Code Period type 'DAYS' requires a value");
+ expectedException.expectMessage("New Code Period type 'NUMBER_OF_DAYS' requires a value");
ws.newRequest()
- .setParam("projectKey", project.getKey())
- .setParam("branchKey", "master")
+ .setParam("project", project.getKey())
+ .setParam("branch", "master")
.setParam("type", "number_of_days")
.execute();
}
@@ -158,12 +156,12 @@ public class SetNewCodePeriodActionTest {
ComponentDto project = componentDb.insertMainBranch();
logInAsProjectAdministrator(project);
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("New Code Period type 'ANALYSIS' requires a value");
+ expectedException.expectMessage("New Code Period type 'SPECIFIC_ANALYSIS' requires a value");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "specific_analysis")
- .setParam("branchKey", "master")
+ .setParam("branch", "master")
.execute();
}
@@ -175,9 +173,9 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("Failed to parse date: unknown");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "date")
- .setParam("branchKey", "master")
+ .setParam("branch", "master")
.setParam("value", "unknown")
.execute();
}
@@ -190,9 +188,9 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("Failed to parse number of days: unknown");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "number_of_days")
- .setParam("branchKey", "master")
+ .setParam("branch", "master")
.setParam("value", "unknown")
.execute();
}
@@ -205,9 +203,9 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("Analysis 'unknown' is not found");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "specific_analysis")
- .setParam("branchKey", "master")
+ .setParam("branch", "master")
.setParam("value", "unknown")
.execute();
}
@@ -225,9 +223,9 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("Analysis '" + analysisBranch.getUuid() + "' does not belong to branch 'master' of project '" + project.getKey() + "'");
ws.newRequest()
- .setParam("projectKey", project.getKey())
- .setParam("type", "analysis")
- .setParam("branchKey", "master")
+ .setParam("project", project.getKey())
+ .setParam("type", "specific_analysis")
+ .setParam("branch", "master")
.setParam("value", analysisBranch.getUuid())
.execute();
}
@@ -239,7 +237,7 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("If branch key is specified, project key needs to be specified too");
ws.newRequest()
- .setParam("branchKey", "branch")
+ .setParam("branch", "branch")
.execute();
}
@@ -250,7 +248,7 @@ public class SetNewCodePeriodActionTest {
ws.newRequest()
.setParam("type", "previous_version")
- .setParam("projectKey", "unknown")
+ .setParam("project", "unknown")
.execute();
}
@@ -262,9 +260,9 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("Component '" + project.getKey() + "' on branch 'unknown' not found");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "previous_version")
- .setParam("branchKey", "unknown")
+ .setParam("branch", "unknown")
.execute();
}
@@ -277,9 +275,9 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("Not a long-living branch: 'branch'");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "previous_version")
- .setParam("branchKey", "branch")
+ .setParam("branch", "branch")
.execute();
}
@@ -291,7 +289,7 @@ public class SetNewCodePeriodActionTest {
expectedException.expectMessage("Insufficient privileges");
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "previous_version")
.execute();
}
@@ -322,11 +320,11 @@ public class SetNewCodePeriodActionTest {
ComponentDto project = componentDb.insertMainBranch();
logInAsProjectAdministrator(project);
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "number_of_days")
.setParam("value", "5")
.execute();
- assertTableContainsOnly(project.getKey(), null, NewCodePeriodType.NUMBER_OF_DAYS, "5");
+ assertTableContainsOnly(project.uuid(), null, NewCodePeriodType.NUMBER_OF_DAYS, "5");
}
@@ -341,20 +339,19 @@ public class SetNewCodePeriodActionTest {
logInAsProjectAdministrator(project);
ws.newRequest()
- .setParam("projectKey", project.getKey())
+ .setParam("project", project.getKey())
.setParam("type", "specific_analysis")
- .setParam("branchKey", "branch")
+ .setParam("branch", "branch")
.setParam("value", analysisBranch.getUuid())
.execute();
- assertTableContainsOnly(project.getKey(), "branch", NewCodePeriodType.SPECIFIC_ANALYSIS, analysisBranch.getUuid());
-
+ assertTableContainsOnly(project.uuid(), branch.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, analysisBranch.getUuid());
}
- private void assertTableContainsOnly(@Nullable String projectKey, @Nullable String branchKey, NewCodePeriodType type, @Nullable String value) {
- dbTester.countRowsOfTable(dbSession, "new_code_period");
- assertThat(dbTester.selectFirst(dbSession, "select projectKey, branchKey, type, value from new_code_period"))
- .containsOnly(entry("projectKey", projectKey), entry("branchKey", branchKey), entry("type", type), entry("value", value));
+ private void assertTableContainsOnly(@Nullable String projectUuid, @Nullable String branchUuid, NewCodePeriodType type, @Nullable String value) {
+ assertThat(db.countRowsOfTable(dbSession, "new_code_periods")).isEqualTo(1);
+ assertThat(db.selectFirst(dbSession, "select project_uuid, branch_uuid, type, value from new_code_periods"))
+ .containsOnly(entry("PROJECT_UUID", projectUuid), entry("BRANCH_UUID", branchUuid), entry("TYPE", type.name()), entry("VALUE", value));
}
private void logInAsProjectAdministrator(ComponentDto project) {
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SettingsWsModule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SettingsWsModule.java
index 61371ee1e3d..7b21556d6bb 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SettingsWsModule.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SettingsWsModule.java
@@ -35,6 +35,8 @@ public class SettingsWsModule extends Module {
GenerateSecretKeyAction.class,
CheckSecretKeyAction.class,
SettingsUpdater.class,
- SettingValidations.class);
+ SettingValidations.class,
+ ShowNewCodePeriodAction.class,
+ UpdateNewCodePeriodAction.class);
}
}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/ws/SettingsWsModuleTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/ws/SettingsWsModuleTest.java
index b3dd8904a60..a13ca7fe359 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/ws/SettingsWsModuleTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/ws/SettingsWsModuleTest.java
@@ -29,6 +29,6 @@ public class SettingsWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new SettingsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(11 + 2);
+ assertThat(container.size()).isEqualTo(13 + 2);
}
}
diff --git a/sonar-ws/src/main/protobuf/ws-settings.proto b/sonar-ws/src/main/protobuf/ws-settings.proto
index db185b54446..180e7d4c463 100644
--- a/sonar-ws/src/main/protobuf/ws-settings.proto
+++ b/sonar-ws/src/main/protobuf/ws-settings.proto
@@ -44,6 +44,21 @@ message CheckSecretKeyWsResponse {
bool secretKeyAvailable = 1;
}
+message ShowNewCodePeriodResponse {
+ string projectKey = 1;
+ string branchKey = 2;
+ NewCodePeriodType type = 3;
+ string value = 4;
+ bool inherited = 5;
+}
+
+enum NewCodePeriodType {
+ PREVIOUS_VERSION = 0;
+ NUMBER_OF_DAYS = 1;
+ DATE = 2;
+ SPECIFIC_ANALYSIS = 3;
+}
+
message Definition {
string key = 1;
oneof nameOneOf {string name = 2;}