12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265 |
- /*
- * SonarQube
- * Copyright (C) 2009-2024 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 com.google.gson.Gson;
- import com.tngtech.java.junit.dataprovider.DataProvider;
- import com.tngtech.java.junit.dataprovider.DataProviderRunner;
- import com.tngtech.java.junit.dataprovider.UseDataProvider;
- import java.net.HttpURLConnection;
- import java.util.List;
- import java.util.Map;
- import java.util.concurrent.ThreadLocalRandom;
- import javax.annotation.Nullable;
- import org.junit.Before;
- import org.junit.Rule;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.sonar.api.PropertyType;
- import org.sonar.api.config.PropertyDefinition;
- import org.sonar.api.config.PropertyDefinitions;
- import org.sonar.api.config.PropertyFieldDefinition;
- import org.sonar.api.resources.Qualifiers;
- import org.sonar.api.server.ws.WebService;
- import org.sonar.api.server.ws.WebService.Param;
- import org.sonar.api.utils.System2;
- import org.sonar.api.web.UserRole;
- import org.sonar.db.DbClient;
- import org.sonar.db.DbSession;
- import org.sonar.db.DbTester;
- import org.sonar.db.component.ComponentDto;
- import org.sonar.db.component.ComponentTesting;
- import org.sonar.db.component.ProjectData;
- import org.sonar.db.portfolio.PortfolioDto;
- import org.sonar.db.project.ProjectDto;
- import org.sonar.db.property.PropertyDbTester;
- import org.sonar.db.property.PropertyDto;
- import org.sonar.db.property.PropertyQuery;
- import org.sonar.process.ProcessProperties;
- import org.sonar.scanner.protocol.GsonHelper;
- import org.sonar.server.exceptions.BadRequestException;
- import org.sonar.server.exceptions.ForbiddenException;
- import org.sonar.server.exceptions.NotFoundException;
- import org.sonar.server.l18n.I18nRule;
- import org.sonar.server.setting.SettingsChangeNotifier;
- import org.sonar.server.tester.UserSessionRule;
- import org.sonar.server.ws.TestRequest;
- import org.sonar.server.ws.TestResponse;
- import org.sonar.server.ws.WsActionTester;
-
- import static java.lang.String.format;
- import static java.util.Collections.singletonList;
- import static org.assertj.core.api.Assertions.assertThat;
- import static org.assertj.core.api.Assertions.assertThatThrownBy;
- import static org.assertj.core.groups.Tuple.tuple;
- import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto;
- import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto;
- import static org.sonar.db.user.UserTesting.newUserDto;
-
- @RunWith(DataProviderRunner.class)
- public class SetActionIT {
-
- private static final Gson GSON = GsonHelper.create();
-
- @Rule
- public UserSessionRule userSession = UserSessionRule.standalone().logIn();
- @Rule
- public DbTester db = DbTester.create(System2.INSTANCE);
-
- private final PropertyDbTester propertyDb = new PropertyDbTester(db);
- private final DbClient dbClient = db.getDbClient();
- private final DbSession dbSession = db.getSession();
- private final I18nRule i18n = new I18nRule();
- private final PropertyDefinitions definitions = new PropertyDefinitions(System2.INSTANCE);
- private final FakeSettingsNotifier settingsChangeNotifier = new FakeSettingsNotifier(dbClient);
- private final SettingsUpdater settingsUpdater = new SettingsUpdater(dbClient, definitions);
- private final SettingValidations validations = new SettingValidations(definitions, dbClient, i18n);
- private final SetAction underTest = new SetAction(definitions, dbClient, userSession, settingsUpdater, settingsChangeNotifier, validations);
-
- private final WsActionTester ws = new WsActionTester(underTest);
-
- @Before
- public void setUp() {
- // by default test doesn't care about permissions
- userSession.logIn().setSystemAdministrator();
- }
-
- @DataProvider
- public static Object[][] securityJsonProperties() {
- return new Object[][] {
- {"sonar.security.config.javasecurity"},
- {"sonar.security.config.phpsecurity"},
- {"sonar.security.config.pythonsecurity"},
- {"sonar.security.config.roslyn.sonaranalyzer.security.cs"}
- };
- }
-
- @Test
- public void empty_204_response() {
- TestResponse result = ws.newRequest()
- .setParam("key", "my.key")
- .setParam("value", "my value")
- .execute();
-
- assertThat(result.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
- assertThat(result.getInput()).isEmpty();
- }
-
- @Test
- public void persist_new_global_setting() {
- callForGlobalSetting("my.key", "my,value");
-
- assertGlobalSetting("my.key", "my,value");
- assertThat(settingsChangeNotifier.wasCalled).isTrue();
- }
-
- @Test
- public void update_existing_global_setting() {
- propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my value"), null, null, null, null);
- assertGlobalSetting("my.key", "my value");
-
- callForGlobalSetting("my.key", "my new value");
-
- assertGlobalSetting("my.key", "my new value");
- assertThat(settingsChangeNotifier.wasCalled).isTrue();
- }
-
- @Test
- public void persist_new_project_setting() {
- propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my global value"), null, null, null, null);
- ProjectDto project = db.components().insertPrivateProject().getProjectDto();
- logInAsProjectAdministrator(project);
-
- callForProjectSettingByKey("my.key", "my project value", project.getKey());
-
- assertGlobalSetting("my.key", "my global value");
- assertComponentSetting("my.key", "my project value", project.getUuid());
- assertThat(settingsChangeNotifier.wasCalled).isFalse();
- }
-
- @Test
- public void persist_new_subportfolio_setting() {
- propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my global value"), null, null, null, null);
- ComponentDto portfolio = db.components().insertPrivatePortfolio();
- ComponentDto subportfolio = db.components().insertSubportfolio(portfolio);
- logInAsPortfolioAdministrator(db.components().getPortfolioDto(portfolio));
-
- callForProjectSettingByKey("my.key", "my project value", subportfolio.getKey());
-
- assertGlobalSetting("my.key", "my global value");
- assertComponentSetting("my.key", "my project value", subportfolio.uuid());
- assertThat(settingsChangeNotifier.wasCalled).isFalse();
- }
-
- @Test
- public void persist_project_property_with_project_admin_permission() {
- ProjectDto project = db.components().insertPrivateProject().getProjectDto();
- logInAsProjectAdministrator(project);
-
- callForProjectSettingByKey("my.key", "my value", project.getKey());
-
- assertComponentSetting("my.key", "my value", project.getUuid());
- }
-
- @Test
- public void update_existing_project_setting() {
- propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my global value"), null, null,
- null, null);
- ProjectDto project = db.components().insertPrivateProject().getProjectDto();
- propertyDb.insertProperty(newComponentPropertyDto("my.key", "my project value", project), project.getKey(),
- project.getName(), null, null);
- assertComponentSetting("my.key", "my project value", project.getUuid());
- logInAsProjectAdministrator(project);
-
- callForProjectSettingByKey("my.key", "my new project value", project.getKey());
-
- assertComponentSetting("my.key", "my new project value", project.getUuid());
- }
-
- @Test
- public void persist_several_multi_value_setting() {
- callForMultiValueGlobalSetting("my.key", List.of("first,Value", "second,Value", "third,Value"));
-
- String expectedValue = "first%2CValue,second%2CValue,third%2CValue";
- assertGlobalSetting("my.key", expectedValue);
- assertThat(settingsChangeNotifier.wasCalled).isTrue();
- }
-
- @Test
- public void persist_one_multi_value_setting() {
- callForMultiValueGlobalSetting("my.key", List.of("first,Value"));
-
- assertGlobalSetting("my.key", "first%2CValue");
- }
-
- @Test
- public void persist_property_set_setting() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("firstField")
- .name("First Field")
- .type(PropertyType.STRING)
- .build(),
- PropertyFieldDefinition.build("secondField")
- .name("Second Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
-
- callForGlobalPropertySet("my.key", List.of(
- GSON.toJson(Map.of("firstField", "firstValue", "secondField", "secondValue")),
- GSON.toJson(Map.of("firstField", "anotherFirstValue", "secondField", "anotherSecondValue")),
- GSON.toJson(Map.of("firstField", "yetFirstValue", "secondField", "yetSecondValue"))));
-
- assertThat(dbClient.propertiesDao().selectGlobalProperties(dbSession)).hasSize(7);
- assertGlobalSetting("my.key", "1,2,3");
- assertGlobalSetting("my.key.1.firstField", "firstValue");
- assertGlobalSetting("my.key.1.secondField", "secondValue");
- assertGlobalSetting("my.key.2.firstField", "anotherFirstValue");
- assertGlobalSetting("my.key.2.secondField", "anotherSecondValue");
- assertGlobalSetting("my.key.3.firstField", "yetFirstValue");
- assertGlobalSetting("my.key.3.secondField", "yetSecondValue");
- assertThat(settingsChangeNotifier.wasCalled).isTrue();
- }
-
- @Test
- public void update_property_set_setting() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("firstField")
- .name("First Field")
- .type(PropertyType.STRING)
- .build(),
- PropertyFieldDefinition.build("secondField")
- .name("Second Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
- propertyDb.insertProperties(null, null, null, null,
- newGlobalPropertyDto("my.key", "1,2,3,4"),
- newGlobalPropertyDto("my.key.1.firstField", "oldFirstValue"),
- newGlobalPropertyDto("my.key.1.secondField", "oldSecondValue"),
- newGlobalPropertyDto("my.key.2.firstField", "anotherOldFirstValue"),
- newGlobalPropertyDto("my.key.2.secondField", "anotherOldSecondValue"),
- newGlobalPropertyDto("my.key.3.firstField", "oldFirstValue"),
- newGlobalPropertyDto("my.key.3.secondField", "oldSecondValue"),
- newGlobalPropertyDto("my.key.4.firstField", "anotherOldFirstValue"),
- newGlobalPropertyDto("my.key.4.secondField", "anotherOldSecondValue"));
-
- callForGlobalPropertySet("my.key", List.of(
- GSON.toJson(Map.of("firstField", "firstValue", "secondField", "secondValue")),
- GSON.toJson(Map.of("firstField", "anotherFirstValue", "secondField", "anotherSecondValue")),
- GSON.toJson(Map.of("firstField", "yetFirstValue", "secondField", "yetSecondValue"))));
-
- assertThat(dbClient.propertiesDao().selectGlobalProperties(dbSession)).hasSize(7);
- assertGlobalSetting("my.key", "1,2,3");
- assertGlobalSetting("my.key.1.firstField", "firstValue");
- assertGlobalSetting("my.key.1.secondField", "secondValue");
- assertGlobalSetting("my.key.2.firstField", "anotherFirstValue");
- assertGlobalSetting("my.key.2.secondField", "anotherSecondValue");
- assertGlobalSetting("my.key.3.firstField", "yetFirstValue");
- assertGlobalSetting("my.key.3.secondField", "yetSecondValue");
- assertThat(settingsChangeNotifier.wasCalled).isTrue();
- }
-
- @Test
- public void update_property_set_on_component_setting() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .onQualifiers(Qualifiers.PROJECT)
- .fields(List.of(
- PropertyFieldDefinition.build("firstField")
- .name("First Field")
- .type(PropertyType.STRING)
- .build(),
- PropertyFieldDefinition.build("secondField")
- .name("Second Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
- ProjectDto project = db.components().insertPrivateProject().getProjectDto();
- propertyDb.insertProperties(null, null, null, null,
- newGlobalPropertyDto("my.key", "1"),
- newGlobalPropertyDto("my.key.1.firstField", "oldFirstValue"),
- newGlobalPropertyDto("my.key.1.secondField", "oldSecondValue"));
- propertyDb.insertProperties(null, project.getKey(), project.getName(), project.getQualifier(),
- newComponentPropertyDto("my.key", "1", project),
- newComponentPropertyDto("my.key.1.firstField", "componentFirstValue", project),
- newComponentPropertyDto("my.key.1.firstField", "componentSecondValue", project));
- logInAsProjectAdministrator(project);
-
- callForComponentPropertySet("my.key", List.of(
- GSON.toJson(Map.of("firstField", "firstValue", "secondField", "secondValue")),
- GSON.toJson(Map.of("firstField", "anotherFirstValue", "secondField", "anotherSecondValue"))),
- project.getKey());
-
- assertThat(dbClient.propertiesDao().selectGlobalProperties(dbSession)).hasSize(3);
- assertThat(dbClient.propertiesDao().selectEntityProperties(dbSession, project.getUuid())).hasSize(5);
- assertGlobalSetting("my.key", "1");
- assertGlobalSetting("my.key.1.firstField", "oldFirstValue");
- assertGlobalSetting("my.key.1.secondField", "oldSecondValue");
- String projectUuid = project.getUuid();
- assertComponentSetting("my.key", "1,2", projectUuid);
- assertComponentSetting("my.key.1.firstField", "firstValue", projectUuid);
- assertComponentSetting("my.key.1.secondField", "secondValue", projectUuid);
- assertComponentSetting("my.key.2.firstField", "anotherFirstValue", projectUuid);
- assertComponentSetting("my.key.2.secondField", "anotherSecondValue", projectUuid);
- assertThat(settingsChangeNotifier.wasCalled).isFalse();
- }
-
- @Test
- public void persist_multi_value_with_type_logIn() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.USER_LOGIN)
- .defaultValue("default")
- .multiValues(true)
- .build());
- db.users().insertUser(newUserDto().setLogin("login.1"));
- db.users().insertUser(newUserDto().setLogin("login.2"));
-
- callForMultiValueGlobalSetting("my.key", List.of("login.1", "login.2"));
-
- assertGlobalSetting("my.key", "login.1,login.2");
- }
-
- @Test
- public void user_setting_is_not_updated() {
- propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my user value").setUserUuid("42"), null, null,
- null, "user_login");
- propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my global value"), null, null, null, null);
-
- callForGlobalSetting("my.key", "my new global value");
-
- assertGlobalSetting("my.key", "my new global value");
- assertUserSetting("my.key", "my user value", "42");
- }
-
- @Test
- public void persist_global_property_with_deprecated_key() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .deprecatedKey("my.old.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.STRING)
- .defaultValue("default")
- .build());
-
- callForGlobalSetting("my.old.key", "My Value");
-
- assertGlobalSetting("my.key", "My Value");
- }
-
- @Test
- public void persist_JSON_property() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.JSON)
- .build());
-
- callForGlobalSetting("my.key", "{\"test\":\"value\"}");
-
- assertGlobalSetting("my.key", "{\"test\":\"value\"}");
- }
-
- @Test
- public void fail_if_JSON_invalid_for_JSON_property() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.JSON)
- .build());
-
- assertThatThrownBy(() -> callForGlobalSetting("my.key", "{\"test\":\"value\""))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessage("Provided JSON is invalid");
-
- assertThatThrownBy(() -> callForGlobalSetting("my.key", "{\"test\":\"value\",}"))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessage("Provided JSON is invalid");
-
- assertThatThrownBy(() -> callForGlobalSetting("my.key", "{\"test\":[\"value\",]}"))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessage("Provided JSON is invalid");
- }
-
- @Test
- @UseDataProvider("securityJsonProperties")
- public void successfully_validate_json_schema(String securityPropertyKey) {
- String security_custom_config = """
- {
- "S3649": {
- "sources": [
- {
- "methodId": "My\\\\Namespace\\\\ClassName\\\\ServerRequest::getQuery"
- }
- ],
- "sanitizers": [
- {
- "methodId": "str_replace", "args": [
- 0
- ]
- }
- ],
- "validators": [
- {
- "methodId": "is_valid", "args": [
- 1
- ]
- }
- ],
- "sinks": [
- {
- "methodId": "mysql_query",
- "args": [1]
- }
- ]
- }
- }""";
- definitions.addComponent(PropertyDefinition
- .builder(securityPropertyKey)
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.JSON)
- .build());
-
- callForGlobalSetting(securityPropertyKey, security_custom_config);
-
- assertGlobalSetting(securityPropertyKey, security_custom_config);
- }
-
- @Test
- @UseDataProvider("securityJsonProperties")
- public void fail_json_schema_validation_when_property_has_incorrect_type(String securityPropertyKey) {
- String security_custom_config = """
- {
- "S3649": {
- "sources": [
- {
- "methodId": "My\\\\Namespace\\\\ClassName\\\\ServerRequest::getQuery"
- }
- ],
- "sinks": [
- {
- "methodId": 12345,
- "args": [1]
- }
- ]
- }
- }""";
- definitions.addComponent(PropertyDefinition
- .builder(securityPropertyKey)
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.JSON)
- .build());
-
- assertThatThrownBy(() -> callForGlobalSetting(securityPropertyKey, security_custom_config))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("expected type: string, actual: integer at line 10, character 21, pointer: #/S3649/sinks/0/methodId");
- }
-
- @Test
- @UseDataProvider("securityJsonProperties")
- public void fail_json_schema_validation_when_sanitizers_have_no_args(String securityPropertyKey) {
- String security_custom_config = """
- {
- "S3649": {
- "sources": [
- {
- "methodId": "My\\\\Namespace\\\\ClassName\\\\ServerRequest::getQuery"
- }
- ],
- "sanitizers": [
- {
- "methodId": "SomeSanitizer"
- }
- ]
- }
- }""";
- definitions.addComponent(PropertyDefinition
- .builder(securityPropertyKey)
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.JSON)
- .build());
-
- assertThatThrownBy(() -> callForGlobalSetting(securityPropertyKey, security_custom_config))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("required properties are missing: args at line 9, character 8, pointer: #/S3649/sanitizers/0");
- }
-
- @Test
- @UseDataProvider("securityJsonProperties")
- public void fail_json_schema_validation_when_validators_have_empty_args_array(String securityPropertyKey) {
- String security_custom_config = """
- {
- "S3649": {
- "sources": [
- {
- "methodId": "My\\\\Namespace\\\\ClassName\\\\ServerRequest::getQuery"
- }
- ],
- "validators": [
- {
- "methodId": "SomeValidator",
- "args": []
- }
- ]
- }
- }""";
- definitions.addComponent(PropertyDefinition
- .builder(securityPropertyKey)
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.JSON)
- .build());
-
- assertThatThrownBy(() -> callForGlobalSetting(securityPropertyKey, security_custom_config))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("expected minimum items: 1, found only 0 at line 11, character 18, pointer: #/S3649/validators/0/args");
- }
-
- @Test
- @UseDataProvider("securityJsonProperties")
- public void fail_json_schema_validation_when_property_has_unknown_attribute(String securityPropertyKey) {
- String security_custom_config = """
- {
- "S3649": {
- "sources": [
- {
- "methodId": "My\\\\Namespace\\\\ClassName\\\\ServerRequest::getQuery"
- }
- ],
- "unknown": [
- {
- "methodId": 12345,
- "args": [1]
- }
- ]
- }
- }""";
- definitions.addComponent(PropertyDefinition
- .builder(securityPropertyKey)
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.JSON)
- .build());
-
- assertThatThrownBy(() -> callForGlobalSetting(securityPropertyKey, security_custom_config))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("false schema always fails at line 8, character 16, pointer: #/S3649/unknown");
- }
-
- @Test
- public void persist_global_setting_with_non_ascii_characters() {
- callForGlobalSetting("my.key", "fi±∞…");
-
- assertGlobalSetting("my.key", "fi±∞…");
- assertThat(settingsChangeNotifier.wasCalled).isTrue();
- }
-
- @Test
- public void fail_when_no_key() {
- assertThatThrownBy(() -> callForGlobalSetting(null, "my value"))
- .isInstanceOf(IllegalArgumentException.class);
- }
-
- @Test
- public void fail_when_empty_key_value() {
- assertThatThrownBy(() -> callForGlobalSetting(" ", "my value"))
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessage("The 'key' parameter is missing");
- }
-
- @Test
- public void fail_when_no_value() {
- assertThatThrownBy(() -> callForGlobalSetting("my.key", null))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Either 'value', 'values' or 'fieldValues' must be provided");
- }
-
- @Test
- public void fail_when_empty_value() {
- assertThatThrownBy(() -> callForGlobalSetting("my.key", ""))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("A non empty value must be provided");
- }
-
- @Test
- public void fail_when_one_empty_value_on_multi_value() {
- List<String> values = List.of("oneValue", " ", "anotherValue");
- assertThatThrownBy(() -> callForMultiValueGlobalSetting("my.key", values))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("A non empty value must be provided");
- }
-
- @Test
- public void throw_ForbiddenException_if_not_system_administrator() {
- userSession.logIn().setNonSystemAdministrator();
-
- assertThatThrownBy(() -> callForGlobalSetting("my.key", "my value"))
- .isInstanceOf(ForbiddenException.class)
- .hasMessage("Insufficient privileges");
- }
-
- @Test
- public void fail_when_data_and_type_do_not_match() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.INTEGER)
- .defaultValue("default")
- .build());
- i18n.put("property.error.notInteger", "Not an integer error message");
-
- assertThatThrownBy(() -> callForGlobalSetting("my.key", "My Value"))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Not an integer error message");
- }
-
- @Test
- public void fail_when_data_and_login_type_with_invalid_logIn() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.USER_LOGIN)
- .defaultValue("default")
- .multiValues(true)
- .build());
- db.users().insertUser(newUserDto().setLogin("login.1"));
- db.users().insertUser(newUserDto().setLogin("login.2").setActive(false));
-
- List<String> values = List.of("login.1", "login.2");
- assertThatThrownBy(() -> callForMultiValueGlobalSetting("my.key", values))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Error when validating login setting with key 'my.key' and values [login.1, login.2]. A value is not a valid login.");
- }
-
- @Test
- public void fail_when_data_and_type_do_not_match_with_unknown_error_key() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.INTEGER)
- .defaultValue("default")
- .build());
-
- List<String> values = List.of("My Value", "My Other Value");
- assertThatThrownBy(() -> callForMultiValueGlobalSetting("my.key", values))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Error when validating setting with key 'my.key' and value [My Value, My Other Value]");
- }
-
- @Test
- public void fail_when_global_with_property_only_on_projects() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.INTEGER)
- .defaultValue("default")
- .onlyOnQualifiers(Qualifiers.PROJECT)
- .build());
-
- assertThatThrownBy(() -> callForGlobalSetting("my.key", "42"))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Setting 'my.key' cannot be global");
- }
-
- @Test
- public void fail_when_view_property_when_on_projects_only() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.STRING)
- .defaultValue("default")
- .onQualifiers(Qualifiers.PROJECT)
- .build());
- ComponentDto view = db.components().insertPublicPortfolio();
- i18n.put("qualifier." + Qualifiers.VIEW, "View");
-
- assertThatThrownBy(() -> {
- logInAsPortfolioAdministrator(db.components().getPortfolioDto(view));
- callForProjectSettingByKey("my.key", "My Value", view.getKey());
- })
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Setting 'my.key' cannot be set on a View");
- }
-
- @Test
- public void fail_when_property_with_definition_when_component_qualifier_does_not_match() {
- PortfolioDto portfolio = db.components().insertPrivatePortfolioDto();
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.STRING)
- .defaultValue("default")
- .onQualifiers(Qualifiers.PROJECT)
- .build());
- i18n.put("qualifier." + portfolio.getQualifier(), "CptLabel");
- logInAsPortfolioAdministrator(portfolio);
-
- assertThatThrownBy(() -> callForProjectSettingByKey("my.key", "My Value", portfolio.getKey()))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Setting 'my.key' cannot be set on a CptLabel");
- }
-
- @Test
- public void succeed_for_property_without_definition_when_set_on_project_component() {
- ProjectDto project = randomPublicOrPrivateProject().getProjectDto();
- succeedForPropertyWithoutDefinitionAndValidComponent(project);
- }
-
- @Test
- public void fail_for_property_without_definition_when_set_on_directory_component() {
- ProjectData projectData = randomPublicOrPrivateProject();
- ComponentDto directory = db.components().insertComponent(ComponentTesting.newDirectory(projectData.getMainBranchComponent(), "A/B"));
- failForPropertyWithoutDefinitionOnUnsupportedComponent(projectData.getProjectDto(), directory);
- }
-
- @Test
- public void fail_for_property_without_definition_when_set_on_file_component() {
- ProjectData projectData = randomPublicOrPrivateProject();
- ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(projectData.getMainBranchComponent()));
- failForPropertyWithoutDefinitionOnUnsupportedComponent(projectData.getProjectDto(), file);
- }
-
- @Test
- public void succeed_for_property_without_definition_when_set_on_view_component() {
- PortfolioDto view = db.components().insertPrivatePortfolioDto();
- succeedForPropertyWithoutDefinitionAndValidComponent(view);
- }
-
- @Test
- public void succeed_for_property_without_definition_when_set_on_subview_component() {
- ComponentDto view = db.components().insertPrivatePortfolio();
- ComponentDto subview = db.components().insertComponent(ComponentTesting.newSubPortfolio(view));
- failForPropertyWithoutDefinitionOnUnsupportedComponent(db.components().getPortfolioDto(view), subview);
- }
-
- @Test
- public void fail_for_property_without_definition_when_set_on_projectCopy_component() {
- ComponentDto view = db.components().insertPrivatePortfolio();
- ComponentDto projectCopy = db.components().insertComponent(ComponentTesting.newProjectCopy("a", db.components().insertPrivateProject().getMainBranchComponent(), view));
-
- failForPropertyWithoutDefinitionOnUnsupportedComponent(db.components().getPortfolioDto(view), projectCopy);
- }
-
- private void succeedForPropertyWithoutDefinitionAndValidComponent(ProjectDto project) {
- logInAsProjectAdministrator(project);
-
- callForProjectSettingByKey("my.key", "My Value", project.getKey());
-
- assertComponentSetting("my.key", "My Value", project.getUuid());
- }
-
- private void succeedForPropertyWithoutDefinitionAndValidComponent(PortfolioDto portfolioDto) {
- logInAsPortfolioAdministrator(portfolioDto);
-
- callForProjectSettingByKey("my.key", "My Value", portfolioDto.getKey());
-
- assertComponentSetting("my.key", "My Value", portfolioDto.getUuid());
- }
-
- private void failForPropertyWithoutDefinitionOnUnsupportedComponent(ProjectDto project, ComponentDto component) {
- i18n.put("qualifier." + component.qualifier(), "QualifierLabel");
- logInAsProjectAdministrator(project);
-
- assertThatThrownBy(() -> callForProjectSettingByKey("my.key", "My Value", component.getKey()))
- .isInstanceOf(NotFoundException.class)
- .hasMessage(String.format("Component key '%s' not found", component.getKey()));
- }
-
- private void failForPropertyWithoutDefinitionOnUnsupportedComponent(PortfolioDto portfolio, ComponentDto component) {
- i18n.put("qualifier." + component.qualifier(), "QualifierLabel");
- logInAsPortfolioAdministrator(portfolio);
-
- assertThatThrownBy(() -> callForProjectSettingByKey("my.key", "My Value", component.getKey()))
- .isInstanceOf(NotFoundException.class)
- .hasMessage(String.format("Component key '%s' not found", component.getKey()));
- }
-
- @Test
- public void fail_when_single_and_multi_value_provided() {
- List<String> value = List.of("Another Value");
- assertThatThrownBy(() -> call("my.key", "My Value", value, null, null))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Either 'value', 'values' or 'fieldValues' must be provided");
- }
-
- @Test
- public void fail_when_multi_definition_and_single_value_provided() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .type(PropertyType.STRING)
- .multiValues(true)
- .build());
-
- assertThatThrownBy(() -> callForGlobalSetting("my.key", "My Value"))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Parameter 'value' must be used for single value setting. Parameter 'values' must be used for multi value setting.");
- }
-
- @Test
- public void fail_when_single_definition_and_multi_value_provided() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .type(PropertyType.STRING)
- .multiValues(false)
- .build());
-
- assertThatThrownBy(() -> callForMultiValueGlobalSetting("my.key", List.of("My Value")))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Parameter 'value' must be used for single value setting. Parameter 'values' must be used for multi value setting.");
- }
-
- @Test
- public void fail_when_empty_values_on_one_property_set() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("firstField")
- .name("First Field")
- .type(PropertyType.STRING)
- .build(),
- PropertyFieldDefinition.build("secondField")
- .name("Second Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
-
- assertThatThrownBy(() -> callForGlobalPropertySet("my.key", List.of(
- GSON.toJson(Map.of("firstField", "firstValue", "secondField", "secondValue")),
- GSON.toJson(Map.of("firstField", "", "secondField", "")),
- GSON.toJson(Map.of("firstField", "yetFirstValue", "secondField", "yetSecondValue")))))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("A non empty value must be provided");
- }
-
- @Test
- public void do_not_fail_when_only_one_empty_value_on_one_property_set() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("firstField")
- .name("First Field")
- .type(PropertyType.STRING)
- .build(),
- PropertyFieldDefinition.build("secondField")
- .name("Second Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
-
- callForGlobalPropertySet("my.key", List.of(
- GSON.toJson(Map.of("firstField", "firstValue", "secondField", "secondValue")),
- GSON.toJson(Map.of("firstField", "anotherFirstValue", "secondField", "")),
- GSON.toJson(Map.of("firstField", "yetFirstValue", "secondField", "yetSecondValue"))));
-
- assertGlobalSetting("my.key", "1,2,3");
- }
-
- @Test
- public void fail_when_property_set_setting_is_not_defined() {
- assertThatThrownBy(() -> callForGlobalPropertySet("my.key", singletonList("{\"field\":\"value\"}")))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Setting 'my.key' is undefined");
- }
-
- @Test
- public void fail_when_property_set_with_unknown_field() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("field")
- .name("Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
-
- List<String> values = List.of(GSON.toJson(Map.of("field", "value", "unknownField", "anotherValue")));
- assertThatThrownBy(() -> callForGlobalPropertySet("my.key", values))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Unknown field key 'unknownField' for setting 'my.key'");
- }
-
- @Test
- public void fail_when_property_set_has_field_with_incorrect_type() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("field")
- .name("Field")
- .type(PropertyType.INTEGER)
- .build()))
- .build());
-
- List<String> values = List.of(GSON.toJson(Map.of("field", "notAnInt")));
- assertThatThrownBy(() -> callForGlobalPropertySet("my.key", values))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Error when validating setting with key 'my.key'. Field 'field' has incorrect value 'notAnInt'.");
- }
-
- @Test
- public void fail_when_property_set_has_a_null_field_value() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("field")
- .name("Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
-
- List<String> values = List.of("{\"field\": null}");
- assertThatThrownBy(() -> callForGlobalPropertySet("my.key", values))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("A non empty value must be provided");
- }
-
- @Test
- public void fail_when_property_set_with_invalid_json() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("field")
- .name("Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
-
- List<String> values = List.of("incorrectJson:incorrectJson");
- assertThatThrownBy(() -> callForGlobalPropertySet("my.key", values))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("JSON 'incorrectJson:incorrectJson' does not respect expected format for setting 'my.key'. " +
- "Ex: {\"field1\":\"value1\", \"field2\":\"value2\"}");
- }
-
- @Test
- public void fail_when_property_set_with_json_of_the_wrong_format() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(
- PropertyFieldDefinition.build("field")
- .name("Field")
- .type(PropertyType.STRING)
- .build()))
- .build());
-
- List<String> values = List.of("[{\"field\":\"v1\"}, {\"field\":\"v2\"}]");
- assertThatThrownBy(() -> callForGlobalPropertySet("my.key", values))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("JSON '[{\"field\":\"v1\"}, {\"field\":\"v2\"}]' does not respect expected format for setting 'my.key'. " +
- "Ex: {\"field1\":\"value1\", \"field2\":\"value2\"}");
- }
-
- @Test
- public void fail_when_property_set_on_component_of_global_setting() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .category("cat")
- .subCategory("subCat")
- .type(PropertyType.PROPERTY_SET)
- .defaultValue("default")
- .fields(List.of(PropertyFieldDefinition.build("firstField").name("First Field").type(PropertyType.STRING).build()))
- .build());
- i18n.put("qualifier." + Qualifiers.PROJECT, "Project");
- ProjectDto project = db.components().insertPrivateProject().getProjectDto();
- logInAsProjectAdministrator(project);
-
- List<String> values = List.of(GSON.toJson(Map.of("firstField", "firstValue")));
- assertThatThrownBy(() -> callForComponentPropertySet("my.key", values, project.getKey()))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Setting 'my.key' cannot be set on a Project");
- }
-
- @Test
- public void fail_when_component_not_found() {
- TestRequest testRequest = ws.newRequest()
- .setParam("key", "foo")
- .setParam("value", "2")
- .setParam("component", "unknown");
- assertThatThrownBy(testRequest::execute)
- .isInstanceOf(NotFoundException.class)
- .hasMessage("Component key 'unknown' not found");
- }
-
- @Test
- public void fail_when_setting_key_is_defined_in_sonar_properties() {
- ProjectDto project = db.components().insertPrivateProject().getProjectDto();
- logInAsProjectAdministrator(project);
- String settingKey = ProcessProperties.Property.JDBC_URL.getKey();
-
- TestRequest testRequest = ws.newRequest()
- .setParam("key", settingKey)
- .setParam("value", "any value")
- .setParam("component", project.getKey());
- assertThatThrownBy(testRequest::execute)
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessage(format("Setting '%s' can only be used in sonar.properties", settingKey));
- }
-
- @Test
- public void definition() {
- WebService.Action definition = ws.getDef();
-
- assertThat(definition.key()).isEqualTo("set");
- assertThat(definition.isPost()).isTrue();
- assertThat(definition.isInternal()).isFalse();
- assertThat(definition.since()).isEqualTo("6.1");
- assertThat(definition.params()).extracting(Param::key)
- .containsOnly("key", "value", "values", "fieldValues", "component");
- }
-
- @Test
- public void call_whenEmailPropertyValid_shouldSucceed() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .type(PropertyType.EMAIL)
- .build());
-
- callForGlobalSetting("my.key", "test@sonarsource.com");
- assertGlobalSetting("my.key", "test@sonarsource.com");
- }
-
- @Test
- public void call_whenEmailPropertyInvalid_shouldFail() {
- definitions.addComponent(PropertyDefinition
- .builder("my.key")
- .name("foo")
- .description("desc")
- .type(PropertyType.EMAIL)
- .build());
- i18n.put("property.error.notEmail", "Not a valid email address");
-
- assertThatThrownBy(() -> callForGlobalSetting("my.key", "test1@sonarsource.com,test2@sonarsource.com"))
- .isInstanceOf(BadRequestException.class)
- .hasMessage("Not a valid email address");
- }
-
- private void assertGlobalSetting(String key, String value) {
- PropertyDto result = dbClient.propertiesDao().selectGlobalProperty(key);
-
- assertThat(result)
- .extracting(PropertyDto::getKey, PropertyDto::getValue, PropertyDto::getEntityUuid)
- .containsExactly(key, value, null);
- }
-
- private void assertUserSetting(String key, String value, String userUuid) {
- List<PropertyDto> result = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setKey(key).setUserUuid(userUuid).build(), dbSession);
-
- assertThat(result).hasSize(1)
- .extracting(PropertyDto::getKey, PropertyDto::getValue, PropertyDto::getUserUuid)
- .containsExactly(tuple(key, value, userUuid));
- }
-
- private void assertComponentSetting(String key, String value, String entityUuid) {
- PropertyDto result = dbClient.propertiesDao().selectProjectProperty(db.getSession(), entityUuid, key);
-
- assertThat(result)
- .isNotNull()
- .extracting(PropertyDto::getKey, PropertyDto::getValue, PropertyDto::getEntityUuid)
- .containsExactly(key, value, entityUuid);
- }
-
- private void callForGlobalSetting(@Nullable String key, @Nullable String value) {
- call(key, value, null, null, null);
- }
-
- private void callForMultiValueGlobalSetting(@Nullable String key, @Nullable List<String> values) {
- call(key, null, values, null, null);
- }
-
- private void callForGlobalPropertySet(@Nullable String key, @Nullable List<String> fieldValues) {
- call(key, null, null, fieldValues, null);
- }
-
- private void callForComponentPropertySet(@Nullable String key, @Nullable List<String> fieldValues, @Nullable String componentKey) {
- call(key, null, null, fieldValues, componentKey);
- }
-
- private void callForProjectSettingByKey(@Nullable String key, @Nullable String value, @Nullable String componentKey) {
- call(key, value, null, null, componentKey);
- }
-
- private void call(@Nullable String key, @Nullable String value, @Nullable List<String> values, @Nullable List<String> fieldValues, @Nullable String componentKey) {
- TestRequest request = ws.newRequest();
- if (key != null) {
- request.setParam("key", key);
- }
- if (value != null) {
- request.setParam("value", value);
- }
- if (values != null) {
- request.setMultiParam("values", values);
- }
- if (fieldValues != null) {
- request.setMultiParam("fieldValues", fieldValues);
- }
- if (componentKey != null) {
- request.setParam("component", componentKey);
- }
- request.execute();
- }
-
- private static class FakeSettingsNotifier extends SettingsChangeNotifier {
-
- private final DbClient dbClient;
- private boolean wasCalled = false;
-
- private FakeSettingsNotifier(DbClient dbClient) {
- this.dbClient = dbClient;
- }
-
- @Override
- public void onGlobalPropertyChange(String key, @Nullable String value) {
- wasCalled = true;
- PropertyDto property = dbClient.propertiesDao().selectGlobalProperty(key);
-
- assertThat(property.getValue()).isEqualTo(value);
- }
- }
-
- private void logInAsPortfolioAdministrator(PortfolioDto portfolio) {
- userSession.logIn().addPortfolioPermission(UserRole.ADMIN, portfolio);
- }
-
- private void logInAsProjectAdministrator(ProjectDto project) {
- userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
- }
-
- private ProjectData randomPublicOrPrivateProject() {
- return ThreadLocalRandom.current().nextBoolean() ? db.components().insertPrivateProject() : db.components().insertPublicProject();
- }
- }
|