*/
package org.sonar.server.authentication;
-import com.google.common.collect.ImmutableSet;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
package org.sonar.server.badge.ws;
import javax.annotation.Nullable;
+import org.sonar.api.config.Configuration;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbClient;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.NotFoundException;
+import static org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_DEFAULT_VALUE;
+import static org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY;
import static org.sonar.db.component.BranchType.BRANCH;
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
private final ComponentFinder componentFinder;
private final DbClient dbClient;
+ private final Configuration config;
- public ProjectBadgesSupport(ComponentFinder componentFinder, DbClient dbClient) {
+ public ProjectBadgesSupport(ComponentFinder componentFinder, DbClient dbClient, Configuration config) {
this.componentFinder = componentFinder;
this.dbClient = dbClient;
+ this.config = config;
}
void addProjectAndBranchParams(WebService.NewAction action) {
} catch (NotFoundException e) {
throw new NotFoundException(PROJECT_HAS_NOT_BEEN_FOUND);
}
- String token = request.param(PARAM_TOKEN);
- if (projectDto.isPrivate() && !isTokenValid(dbSession, projectDto, token)) {
+ boolean tokenInvalid = !isTokenValid(dbSession, projectDto, request.param(PARAM_TOKEN));
+ boolean forceAuthEnabled = config.getBoolean(CORE_FORCE_AUTHENTICATION_PROPERTY).orElse(CORE_FORCE_AUTHENTICATION_DEFAULT_VALUE);
+ if ((projectDto.isPrivate() || forceAuthEnabled) && tokenInvalid) {
throw new NotFoundException(PROJECT_HAS_NOT_BEEN_FOUND);
}
}
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Configuration;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric.Level;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.metric.MetricDto;
+import org.sonar.db.project.ProjectDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.badge.ws.SvgGenerator.Color;
import org.sonar.server.component.ComponentFinder;
@Rule
public DbTester db = DbTester.create();
- private MapSettings mapSettings = new MapSettings().setProperty("sonar.sonarcloud.enabled", false);
+ private final MapSettings mapSettings = new MapSettings().setProperty("sonar.sonarcloud.enabled", false);
+ private final Configuration config = mapSettings.asConfig();
- private WsActionTester ws = new WsActionTester(
+ private final WsActionTester ws = new WsActionTester(
new MeasureAction(
db.getDbClient(),
- new ProjectBadgesSupport(new ComponentFinder(db.getDbClient(), null), db.getDbClient()),
+ new ProjectBadgesSupport(new ComponentFinder(db.getDbClient(), null), db.getDbClient(), config),
new SvgGenerator(mapSettings.asConfig())));
+ @Before
+ public void before(){
+ mapSettings.setProperty(CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY, false);
+ }
+
@Test
public void int_measure() {
ComponentDto project = db.components().insertPublicProject();
}
@Test
- public void return_error_on_private_project() throws ParseException {
+ public void return_error_on_private_project_without_token() throws ParseException {
ComponentDto project = db.components().insertPrivateProject();
UserDto user = db.users().insertUser();
userSession.logIn(user).addProjectPermission(USER, project);
checkError(response, "Project has not been found");
}
+ @DataProvider
+ public static Object[][] publicProject_forceAuth_accessGranted(){
+ return new Object[][] {
+ // public project, force auth : works depending on token's validity
+ {true, true, true, true},
+ {true, true, false, false},
+
+ // public project, no force auth : access always granted
+ {true, false, true, true},
+ {true, false, false, true},
+
+ // private project, regardless of force auth, access granted depending on token's validity:
+ {false, true, true, true},
+ {false, true, false, false},
+ {false, false, true, true},
+ {false, false, false, false},
+ };
+ }
+
+ @Test
+ @UseDataProvider("publicProject_forceAuth_accessGranted")
+ public void badge_accessible_on_private_project_with_token(boolean publicProject, boolean forceAuth,
+ boolean validToken, boolean accessGranted) throws ParseException {
+ ComponentDto projectAsComponent = publicProject ? db.components().insertPublicProject() : db.components().insertPrivateProject();
+ userSession.registerComponents(projectAsComponent);
+ MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name()));
+
+ db.measures().insertLiveMeasure(projectAsComponent, metric, m -> m.setValue(10_000d));
+ ProjectDto project = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), projectAsComponent.getKey())
+ .orElseThrow(() -> new IllegalStateException("project not found"));
+
+ String token = db.getDbClient().projectBadgeTokenDao()
+ .insert(db.getSession(), UuidFactoryFast.getInstance().create(), project, "user-uuid", "user-login")
+ .getToken();
+ db.commit();
+
+ mapSettings.setProperty(CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY, forceAuth);
+
+ TestResponse response = ws.newRequest()
+ .setParam("project", projectAsComponent.getKey())
+ .setParam("metric", metric.getKey())
+ .setParam("token", validToken ? token : "invalid-token")
+ .execute();
+
+ if(accessGranted){
+ checkSvg(response, "bugs", "10k", DEFAULT);
+ }else{
+ checkError(response, "Project has not been found");
+ }
+ }
+
@Test
public void return_error_on_provisioned_project() throws ParseException {
ComponentDto project = db.components().insertPublicProject();
*/
package org.sonar.server.badge.ws;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Configuration;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.measures.Metric.Level;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
+import org.sonar.db.project.ProjectDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.tester.UserSessionRule;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.db.component.BranchType.BRANCH;
+@RunWith(DataProviderRunner.class)
public class QualityGateActionTest {
@Rule
@Rule
public DbTester db = DbTester.create();
- private final MapSettings mapSettings = new MapSettings().setProperty("sonar.sonarcloud.enabled", false);
+ private final MapSettings mapSettings = new MapSettings().setProperty("sonar.sonarcloud.enabled", false).setProperty(CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY, false);
+ private final Configuration config = mapSettings.asConfig();
- private WsActionTester ws = new WsActionTester(
+ private final WsActionTester ws = new WsActionTester(
new QualityGateAction(db.getDbClient(),
- new ProjectBadgesSupport(new ComponentFinder(db.getDbClient(), null), db.getDbClient()),
+ new ProjectBadgesSupport(new ComponentFinder(db.getDbClient(), null), db.getDbClient(), config),
new SvgGenerator(mapSettings.asConfig())));
+
+ @Before
+ public void before(){
+ mapSettings.setProperty(CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY, false);
+ }
+
@Test
public void quality_gate_passed() {
ComponentDto project = db.components().insertPublicProject();
checkResponse(response, ERROR);
}
+
+ @DataProvider
+ public static Object[][] publicProject_forceAuth_validToken_accessGranted(){
+ return new Object[][] {
+ // public project, force auth : access granted depending on token's validity
+ {true, true, true, true},
+ {true, true, false, false},
+
+ // public project, no force auth : access always granted
+ {true, false, true, true},
+ {true, false, false, true},
+
+ // private project, regardless of force auth, access granted depending on token's validity:
+ {false, true, true, true},
+ {false, true, false, false},
+ {false, false, true, true},
+ {false, false, false, false},
+ };
+ }
+
+ @Test
+ @UseDataProvider("publicProject_forceAuth_validToken_accessGranted")
+ public void badge_accessible_on_private_project_with_token(boolean publicProject, boolean forceAuth,
+ boolean validToken, boolean accessGranted) throws ParseException {
+ ComponentDto projectAsComponent = publicProject ? db.components().insertPublicProject() : db.components().insertPrivateProject();
+ userSession.registerComponents(projectAsComponent);
+ MetricDto metric = createQualityGateMetric();
+
+ db.measures().insertLiveMeasure(projectAsComponent, metric, m -> m.setData(OK.name()));
+ ProjectDto project = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), projectAsComponent.getKey())
+ .orElseThrow(() -> new IllegalStateException("project not found"));
+
+ String token = db.getDbClient().projectBadgeTokenDao()
+ .insert(db.getSession(), UuidFactoryFast.getInstance().create(), project, "user-uuid", "user-login")
+ .getToken();
+ db.commit();
+
+ mapSettings.setProperty(CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY, forceAuth);
+
+ TestResponse response = ws.newRequest()
+ .setParam("project", projectAsComponent.getKey())
+ .setParam("token", validToken ? token : "invalid-token")
+ .execute();
+
+ if(accessGranted){
+ checkResponse(response, OK);
+ }else{
+ checkError(response, "Project has not been found");
+ }
+
+ }
+
@Test
public void etag_should_be_different_if_quality_gate_is_different() {
ComponentDto project = db.components().insertPublicProject();