import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
import org.sonar.core.metric.db.MetricDto;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.metric.ws.MetricJsonWriter;
+import org.sonar.server.user.UserSession;
import static com.google.common.base.Preconditions.checkArgument;
public static final String PARAM_PROJECT_KEY = "projectKey";
private final DbClient dbClient;
+ private final UserSession userSession;
- public MetricsAction(DbClient dbClient) {
+ public MetricsAction(DbClient dbClient, UserSession userSession) {
this.dbClient = dbClient;
+ this.userSession = userSession;
}
@Override
.setHandler(this)
.setResponseExample(Resources.getResource(getClass(), "example-metrics.json"))
.setDescription("List all custom metrics for which no custom measure already exists on a given project.<br /> " +
- "The project id or project key must be provided.");
+ "The project id or project key must be provided.<br />" +
+ "Requires 'Administer System' permission or 'Administer' permission on the project.");
action.createParam(PARAM_PROJECT_ID)
.setDescription("Project id")
@Override
public void handle(Request request, Response response) throws Exception {
DbSession dbSession = dbClient.openSession(false);
+
try {
- List<MetricDto> metrics = searchMetrics(dbSession, request);
+ ComponentDto project = searchProject(dbSession, request);
+ checkPermissions(project);
+ List<MetricDto> metrics = searchMetrics(dbSession, project);
- JsonWriter json = response.newJsonWriter();
- json.beginObject();
- MetricJsonWriter.write(json, metrics, MetricJsonWriter.ALL_FIELDS);
- json.endObject();
- json.close();
+ writeResponse(response.newJsonWriter(), metrics);
} finally {
MyBatis.closeQuietly(dbSession);
}
}
- private List<MetricDto> searchMetrics(DbSession dbSession, Request request) {
- String projectUuidParam = request.param(PARAM_PROJECT_ID);
- String projectKeyParam = request.param(PARAM_PROJECT_KEY);
- String projectUuid;
+ private void writeResponse(JsonWriter json, List<MetricDto> metrics) {
+ json.beginObject();
+ MetricJsonWriter.write(json, metrics, MetricJsonWriter.ALL_FIELDS);
+ json.endObject();
+ json.close();
+ }
+
+ private List<MetricDto> searchMetrics(DbSession dbSession, ComponentDto project) {
+ return dbClient.metricDao().selectAvailableCustomMetricsByComponentUuid(dbSession, project.uuid());
+ }
+
+ private ComponentDto searchProject(DbSession dbSession, Request request) {
+ String projectUuid = request.param(PARAM_PROJECT_ID);
+ String projectKey = request.param(PARAM_PROJECT_KEY);
+ checkArgument(projectUuid != null ^ projectKey != null, "The project key or the project id must be provided, not both.");
+
+ if (projectUuid != null) {
+ ComponentDto project = dbClient.componentDao().selectNullableByUuid(dbSession, projectUuid);
+ if (project == null) {
+ throw new NotFoundException(String.format("Project id '%s' not found", projectUuid));
+ }
- checkArgument(projectUuidParam != null ^ projectKeyParam != null, "The project uuid or the project key must be provided, not both.");
+ return project;
+ }
+
+ ComponentDto project = dbClient.componentDao().selectNullableByKey(dbSession, projectKey);
+ if (project == null) {
+ throw new NotFoundException(String.format("Project key '%s' not found", projectKey));
+ }
+
+ return project;
+ }
- if (projectUuidParam == null) {
- projectUuid = dbClient.componentDao().selectByKey(dbSession, projectKeyParam).uuid();
- } else {
- projectUuid = projectUuidParam;
+ private void checkPermissions(ComponentDto component) {
+ if (userSession.hasGlobalPermission(GlobalPermissions.SYSTEM_ADMIN)) {
+ return;
}
- return dbClient.metricDao().selectAvailableCustomMetricsByComponentUuid(dbSession, projectUuid);
+ userSession.checkLoggedIn().checkProjectUuidPermission(UserRole.ADMIN, component.projectUuid());
}
}
import org.junit.rules.ExpectedException;
import org.sonar.api.config.Settings;
import org.sonar.api.measures.Metric;
+import org.sonar.api.web.UserRole;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.measure.custom.db.CustomMeasureDto;
import org.sonar.core.metric.db.MetricDto;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
import org.sonar.server.component.ComponentTesting;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.measure.custom.persistence.CustomMeasureDao;
import org.sonar.server.metric.persistence.MetricDao;
+import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.user.index.UserDoc;
import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.ws.WsTester;
@Rule
public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
@ClassRule
public static EsTester es = new EsTester().addDefinitions(new UserIndexDefinition(new Settings()));
@ClassRule
DbClient dbClient;
DbSession dbSession;
WsTester ws;
+ ComponentDto defaultProject;
@BeforeClass
public static void setUpClass() throws Exception {
dbClient = new DbClient(db.database(), db.myBatis(), new MetricDao(), new ComponentDao(), new CustomMeasureDao());
dbSession = dbClient.openSession(false);
db.truncateTables();
- ws = new WsTester(new CustomMeasuresWs(new MetricsAction(dbClient)));
+ ws = new WsTester(new CustomMeasuresWs(new MetricsAction(dbClient, userSession)));
+ userSession.login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+ defaultProject = insertDefaultProject();
}
@After
public void list_metrics_where_no_existing_custom_measure() throws Exception {
MetricDto metric = insertCustomMetric("metric-key-1");
insertCustomMetric("metric-key-2");
- ComponentDto project = insertDefaultProject();
insertProject("project-uuid-2", "project-key-2");
CustomMeasureDto customMeasure = newCustomMeasureDto()
- .setComponentUuid(project.uuid())
+ .setComponentUuid(defaultProject.uuid())
.setMetricId(metric.getId());
dbClient.customMeasureDao().insert(dbSession, customMeasure);
dbSession.commit();
public void list_metrics_based_on_project_key() throws Exception {
MetricDto metric = insertCustomMetric("metric-key-1");
insertCustomMetric("metric-key-2");
- ComponentDto project = insertDefaultProject();
insertProject("project-uuid-2", "project-key-2");
CustomMeasureDto customMeasure = newCustomMeasureDto()
- .setComponentUuid(project.uuid())
+ .setComponentUuid(defaultProject.uuid())
.setMetricId(metric.getId());
dbClient.customMeasureDao().insert(dbSession, customMeasure);
dbSession.commit();
.doesNotContain("metric-key-1");
}
+ @Test
+ public void list_metrics_as_a_project_admin() throws Exception {
+ insertCustomMetric("metric-key-1");
+ userSession.login("login").addProjectUuidPermissions(UserRole.ADMIN, defaultProject.uuid());
+
+ String response = newRequest().outputAsString();
+
+ assertThat(response).contains("metric-key-1");
+ }
+
@Test
public void response_with_correct_formatting() throws Exception {
dbClient.metricDao().insert(dbSession, newCustomMetric("custom-key-1")
ws.newGetRequest(ENDPOINT, ACTION).execute();
}
+ @Test
+ public void fail_if_insufficient_privilege() throws Exception {
+ expectedException.expect(ForbiddenException.class);
+ userSession.login("login");
+
+ insertCustomMetric("metric-key-1");
+
+ newRequest();
+ }
+
private WsTester.Result newRequest() throws Exception {
return ws.newGetRequest(ENDPOINT, ACTION)
.setParam(MetricsAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)