@@ -42,6 +42,7 @@ public class ProjectConfigurationFactory { | |||
Settings projectSettings = new ChildSettings(globalSettings); | |||
addSettings(projectSettings, projectUuid); | |||
if (!projectUuid.equals(branchUuid)) { | |||
// TODO not supported? | |||
addSettings(projectSettings, branchUuid); | |||
} | |||
return new ConfigurationBridge(projectSettings); |
@@ -25,6 +25,7 @@ import org.sonar.api.config.Configuration; | |||
import org.sonar.api.config.internal.MapSettings; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; | |||
@@ -46,13 +47,13 @@ public class ProjectConfigurationFactoryTest { | |||
@Test | |||
public void return_project_settings() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("1").setValue("val1"), | |||
newComponentPropertyDto(project).setKey("2").setValue("val2"), | |||
newComponentPropertyDto(project).setKey("3").setValue("val3")); | |||
Configuration config = underTest.newProjectConfiguration(project.uuid(), project.uuid()); | |||
Configuration config = underTest.newProjectConfiguration(project.getUuid(), project.getUuid()); | |||
assertThat(config.get("1")).hasValue("val1"); | |||
assertThat(config.get("2")).hasValue("val2"); | |||
@@ -62,11 +63,11 @@ public class ProjectConfigurationFactoryTest { | |||
@Test | |||
public void project_settings_override_global_settings() { | |||
settings.setProperty("key", "value"); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("key").setValue("value2")); | |||
Configuration projectConfig = underTest.newProjectConfiguration(project.uuid(), project.uuid()); | |||
Configuration projectConfig = underTest.newProjectConfiguration(project.getUuid(), project.getUuid()); | |||
assertThat(projectConfig.get("key")).hasValue("value2"); | |||
} |
@@ -44,8 +44,10 @@ import org.sonar.db.audit.NoOpAuditPersister; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ProjectData; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.measure.LiveMeasureDto; | |||
import org.sonar.db.metric.MetricDto; | |||
import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import static org.apache.commons.lang.math.RandomUtils.nextInt; | |||
@@ -327,6 +329,60 @@ public class ProjectDaoIT { | |||
assertThat(projectUuids).containsExactlyInAnyOrder(project.projectUuid(), project2.projectUuid()); | |||
} | |||
@Test | |||
public void selectEntitiesByKeys_shouldReturnAllEntities() { | |||
ProjectData application = db.components().insertPrivateApplication(); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
PortfolioDto portfolio = db.components().insertPrivatePortfolioDto(); | |||
assertThat(projectDao.selectEntitiesByKeys(db.getSession(), List.of(application.projectKey(), project.projectKey(), portfolio.getKey(), "unknown"))) | |||
.extracting(EntityDto::getUuid) | |||
.containsOnly(application.projectUuid(), project.projectUuid(), portfolio.getUuid()); | |||
} | |||
@Test | |||
public void selectEntitiesByUuids_shouldReturnAllEntities() { | |||
ProjectData application = db.components().insertPrivateApplication(); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
PortfolioDto portfolio = db.components().insertPrivatePortfolioDto(); | |||
assertThat(projectDao.selectEntitiesByUuids(db.getSession(), List.of(application.projectUuid(), project.projectUuid(), portfolio.getUuid(), "unknown"))) | |||
.extracting(EntityDto::getKey) | |||
.containsOnly(application.projectKey(), project.projectKey(), portfolio.getKey()); | |||
} | |||
@Test | |||
public void selectEntityByUuid_shouldReturnAllEntities() { | |||
ProjectData application = db.components().insertPrivateApplication(); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
PortfolioDto portfolio = db.components().insertPrivatePortfolioDto(); | |||
assertThat(projectDao.selectEntityByUuid(db.getSession(), application.projectUuid()).get().getKey()).isEqualTo(application.projectKey()); | |||
assertThat(projectDao.selectEntityByUuid(db.getSession(), project.projectUuid()).get().getKey()).isEqualTo(project.projectKey()); | |||
assertThat(projectDao.selectEntityByUuid(db.getSession(), portfolio.getUuid()).get().getKey()).isEqualTo(portfolio.getKey()); | |||
} | |||
@Test | |||
public void selectEntityByUuid_whenNoMatch_shouldReturnEmpty() { | |||
assertThat(projectDao.selectEntityByUuid(db.getSession(), "unknown")).isEmpty(); | |||
} | |||
@Test | |||
public void selectEntityByKey_shouldReturnAllEntities() { | |||
ProjectData application = db.components().insertPrivateApplication(); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
PortfolioDto portfolio = db.components().insertPrivatePortfolioDto(); | |||
assertThat(projectDao.selectEntityByKey(db.getSession(), application.projectKey()).get().getUuid()).isEqualTo(application.projectUuid()); | |||
assertThat(projectDao.selectEntityByKey(db.getSession(), project.projectKey()).get().getUuid()).isEqualTo(project.projectUuid()); | |||
assertThat(projectDao.selectEntityByKey(db.getSession(), portfolio.getKey()).get().getUuid()).isEqualTo(portfolio.getUuid()); | |||
} | |||
@Test | |||
public void selectEntityByKey_whenNoMatch_shouldReturnEmpty() { | |||
assertThat(projectDao.selectEntityByKey(db.getSession(), "unknown")).isEmpty(); | |||
} | |||
private void insertDefaultQualityProfile(String language) { | |||
QProfileDto profile = db.qualityProfiles().insert(qp -> qp.setIsBuiltIn(true).setLanguage(language)); | |||
db.qualityProfiles().setAsDefault(profile); |
@@ -45,6 +45,7 @@ import org.sonar.db.EmailSubscriberDto; | |||
import org.sonar.db.audit.AuditPersister; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import static com.google.common.collect.ImmutableSet.of; | |||
@@ -88,52 +89,6 @@ public class PropertiesDaoIT { | |||
when(auditPersister.isTrackedProperty(anyString())).thenReturn(true); | |||
} | |||
@Test | |||
public void shouldFindUsersForNotification() { | |||
ComponentDto project1 = insertPrivateProject("uuid_45"); | |||
ComponentDto project2 = insertPrivateProject("uuid_56"); | |||
UserDto user1 = db.users().insertUser(u -> u.setLogin("user1")); | |||
UserDto user2 = db.users().insertUser(u -> u.setLogin("user2")); | |||
UserDto user3 = db.users().insertUser(u -> u.setLogin("user3")); | |||
insertProperty("notification.NewViolations.Email", "true", project1.uuid(), user2.getUuid(), user2.getLogin(), | |||
project1.getKey(), project1.name()); | |||
insertProperty("notification.NewViolations.Twitter", "true", null, user3.getUuid(), user3.getLogin(), | |||
null, null); | |||
insertProperty("notification.NewViolations.Twitter", "true", project2.uuid(), user1.getUuid(), user1.getLogin(), | |||
project2.getKey(), project2.name()); | |||
insertProperty("notification.NewViolations.Twitter", "true", project1.uuid(), user2.getUuid(), user2.getLogin(), | |||
project1.getKey(), project1.name()); | |||
insertProperty("notification.NewViolations.Twitter", "true", project2.uuid(), user3.getUuid(), user3.getLogin(), | |||
project2.getKey(), project2.name()); | |||
db.users().insertProjectPermissionOnUser(user2, UserRole.USER, project1); | |||
db.users().insertProjectPermissionOnUser(user3, UserRole.USER, project2); | |||
db.users().insertProjectPermissionOnUser(user1, UserRole.USER, project2); | |||
assertThat(underTest.findUsersForNotification("NewViolations", "Email", null)) | |||
.isEmpty(); | |||
assertThat(underTest.findUsersForNotification("NewViolations", "Email", "uuid_78")) | |||
.isEmpty(); | |||
assertThat(underTest.findUsersForNotification("NewViolations", "Email", project1.getKey())) | |||
.containsOnly(new Subscriber("user2", false)); | |||
assertThat(underTest.findUsersForNotification("NewViolations", "Email", project2.getKey())) | |||
.isEmpty(); | |||
assertThat(underTest.findUsersForNotification("NewViolations", "Twitter", null)) | |||
.containsOnly(new Subscriber("user3", true)); | |||
assertThat(underTest.findUsersForNotification("NewViolations", "Twitter", "uuid_78")) | |||
.containsOnly(new Subscriber("user3", true)); | |||
assertThat(underTest.findUsersForNotification("NewViolations", "Twitter", project1.getKey())) | |||
.containsOnly(new Subscriber("user2", false), new Subscriber("user3", true)); | |||
assertThat(underTest.findUsersForNotification("NewViolations", "Twitter", project2.getKey())) | |||
.containsOnly(new Subscriber("user1", false), new Subscriber("user3", true), new Subscriber("user3", false)); | |||
} | |||
@Test | |||
public void hasNotificationSubscribers() { | |||
UserDto user1 = db.users().insertUser(u -> u.setLogin("user1")); | |||
@@ -615,31 +570,31 @@ public class PropertiesDaoIT { | |||
@Test | |||
public void select_properties_by_keys_and_component_ids() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
ProjectDto project2 = db.components().insertPrivateProject().getProjectDto(); | |||
UserDto user = db.users().insertUser(); | |||
String key = "key"; | |||
String anotherKey = "anotherKey"; | |||
insertProperties(null, null, null, newGlobalPropertyDto().setKey(key)); | |||
insertProperties(null, project.getKey(), project.name(), newComponentPropertyDto(project).setKey(key)); | |||
insertProperties(null, project2.getKey(), project2.name(), newComponentPropertyDto(project2).setKey(key), | |||
insertProperties(null, project.getKey(), project.getName(), newComponentPropertyDto(project).setKey(key)); | |||
insertProperties(null, project2.getKey(), project2.getName(), newComponentPropertyDto(project2).setKey(key), | |||
newComponentPropertyDto(project2).setKey(anotherKey)); | |||
insertProperties(user.getLogin(), null, null, newUserPropertyDto(user).setKey(key)); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet(key), newHashSet(project.uuid()))) | |||
.extracting("key", "componentUuid").containsOnly(tuple(key, project.uuid())); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet(key), newHashSet(project.uuid(), project2.uuid()))) | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet(key), newHashSet(project.getUuid()))) | |||
.extracting("key", "componentUuid").containsOnly(tuple(key, project.getUuid())); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet(key), newHashSet(project.getUuid(), project2.getUuid()))) | |||
.extracting("key", "componentUuid").containsOnly( | |||
tuple(key, project.uuid()), | |||
tuple(key, project2.uuid())); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet(key, anotherKey), newHashSet(project.uuid(), project2.uuid()))) | |||
tuple(key, project.getUuid()), | |||
tuple(key, project2.getUuid())); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet(key, anotherKey), newHashSet(project.getUuid(), project2.getUuid()))) | |||
.extracting("key", "componentUuid").containsOnly( | |||
tuple(key, project.uuid()), | |||
tuple(key, project2.uuid()), | |||
tuple(anotherKey, project2.uuid())); | |||
tuple(key, project.getUuid()), | |||
tuple(key, project2.getUuid()), | |||
tuple(anotherKey, project2.getUuid())); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet("unknown"), newHashSet(project.uuid()))).isEmpty(); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet("unknown"), newHashSet(project.getUuid()))).isEmpty(); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet("key"), newHashSet("uuid123456789"))).isEmpty(); | |||
assertThat(underTest.selectPropertiesByKeysAndComponentUuids(session, newHashSet("unknown"), newHashSet("uuid123456789"))).isEmpty(); | |||
} |
@@ -64,6 +64,7 @@ import org.sonar.db.component.UuidWithBranchUuidDto; | |||
import org.sonar.db.component.ViewsSnapshotDto; | |||
import org.sonar.db.duplication.DuplicationMapper; | |||
import org.sonar.db.duplication.DuplicationUnitDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.es.EsQueueMapper; | |||
import org.sonar.db.event.EventComponentChangeMapper; | |||
import org.sonar.db.event.EventDto; | |||
@@ -195,6 +196,7 @@ public class MyBatis { | |||
confBuilder.loadAlias("CeTaskCharacteristic", CeTaskCharacteristicDto.class); | |||
confBuilder.loadAlias("Component", ComponentDto.class); | |||
confBuilder.loadAlias("DuplicationUnit", DuplicationUnitDto.class); | |||
confBuilder.loadAlias("Entity", EntityDto.class); | |||
confBuilder.loadAlias("Event", EventDto.class); | |||
confBuilder.loadAlias("ExternalGroup", ExternalGroupDto.class); | |||
confBuilder.loadAlias("FilePathWithHash", FilePathWithHashDto.class); |
@@ -0,0 +1,77 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 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.db.entity; | |||
import java.util.Objects; | |||
/** | |||
* Represents a project, an application, a portfolio or a sub-portfolio. | |||
* Entities are stored either in the projects or portfolios tables. | |||
*/ | |||
public class EntityDto { | |||
protected String kee; | |||
protected String uuid; | |||
protected String name; | |||
protected String qualifier; | |||
protected boolean isPrivate; | |||
public String getKey() { | |||
return kee; | |||
} | |||
public String getKee() { | |||
return kee; | |||
} | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
/** | |||
* Can be TRK, APP, VW or SVW | |||
*/ | |||
public String getQualifier() { | |||
return qualifier; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public boolean isPrivate() { | |||
return isPrivate; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (!(o instanceof EntityDto entityDto)) { | |||
return false; | |||
} | |||
return Objects.equals(uuid, entityDto.uuid); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(uuid); | |||
} | |||
} |
@@ -19,20 +19,17 @@ | |||
*/ | |||
package org.sonar.db.portfolio; | |||
import java.util.Objects; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.resources.Qualifiers; | |||
import org.sonar.db.entity.EntityDto; | |||
public class PortfolioDto { | |||
public class PortfolioDto extends EntityDto { | |||
public enum SelectionMode { | |||
NONE, MANUAL, REGEXP, REST, TAGS | |||
} | |||
private String uuid; | |||
private String kee; | |||
private String name; | |||
private String description; | |||
private boolean isPrivate = false; | |||
private String branchKey; | |||
private String rootUuid; | |||
@@ -79,6 +76,14 @@ public class PortfolioDto { | |||
this.branchKey = branchKey; | |||
} | |||
@Override | |||
public String getQualifier() { | |||
if (isRoot()) { | |||
return Qualifiers.VIEW; | |||
} | |||
return Qualifiers.SUBVIEW; | |||
} | |||
public String getSelectionMode() { | |||
return selectionMode; | |||
} | |||
@@ -121,26 +126,11 @@ public class PortfolioDto { | |||
return this; | |||
} | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
public PortfolioDto setUuid(String uuid) { | |||
this.uuid = uuid; | |||
return this; | |||
} | |||
/** | |||
* This is the getter used by MyBatis mapper. | |||
*/ | |||
public String getKee() { | |||
return kee; | |||
} | |||
public String getKey() { | |||
return getKee(); | |||
} | |||
/** | |||
* This is the setter used by MyBatis mapper. | |||
*/ | |||
@@ -153,19 +143,11 @@ public class PortfolioDto { | |||
return setKee(key); | |||
} | |||
public boolean isPrivate() { | |||
return isPrivate; | |||
} | |||
public PortfolioDto setPrivate(boolean aPrivate) { | |||
isPrivate = aPrivate; | |||
return this; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public PortfolioDto setName(String name) { | |||
this.name = name; | |||
return this; | |||
@@ -180,22 +162,4 @@ public class PortfolioDto { | |||
this.description = description; | |||
return this; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
PortfolioDto that = (PortfolioDto) o; | |||
return Objects.equals(uuid, that.uuid); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return uuid != null ? uuid.hashCode() : 0; | |||
} | |||
} |
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.db.project; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Optional; | |||
@@ -29,7 +30,9 @@ import org.sonar.db.Dao; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.audit.AuditPersister; | |||
import org.sonar.db.audit.model.ComponentNewValue; | |||
import org.sonar.db.entity.EntityDto; | |||
import static java.util.Collections.emptyList; | |||
import static org.sonar.db.DatabaseUtils.executeLargeInputs; | |||
public class ProjectDao implements Dao { | |||
@@ -70,14 +73,14 @@ public class ProjectDao implements Dao { | |||
public List<ProjectDto> selectProjectsByKeys(DbSession session, Set<String> keys) { | |||
if (keys.isEmpty()) { | |||
return Collections.emptyList(); | |||
return emptyList(); | |||
} | |||
return mapper(session).selectProjectsByKeys(keys); | |||
} | |||
public List<ProjectDto> selectApplicationsByKeys(DbSession session, Set<String> keys) { | |||
if (keys.isEmpty()) { | |||
return Collections.emptyList(); | |||
return emptyList(); | |||
} | |||
return executeLargeInputs(keys, partition -> mapper(session).selectApplicationsByKeys(partition)); | |||
@@ -101,7 +104,7 @@ public class ProjectDao implements Dao { | |||
public List<ProjectDto> selectByUuids(DbSession session, Set<String> uuids) { | |||
if (uuids.isEmpty()) { | |||
return Collections.emptyList(); | |||
return emptyList(); | |||
} | |||
return executeLargeInputs(uuids, partition -> mapper(session).selectByUuids(partition)); | |||
} | |||
@@ -143,4 +146,28 @@ public class ProjectDao implements Dao { | |||
public long getNclocSum(DbSession dbSession, @Nullable String projectUuidToExclude) { | |||
return Optional.ofNullable(mapper(dbSession).getNclocSum(projectUuidToExclude)).orElse(0L); | |||
} | |||
public Optional<EntityDto> selectEntityByUuid(DbSession dbSession, String uuid) { | |||
return Optional.ofNullable(mapper(dbSession).selectEntityByUuid(uuid)); | |||
} | |||
public List<EntityDto> selectEntitiesByUuids(DbSession dbSession, Collection<String> uuids) { | |||
if (uuids.isEmpty()) { | |||
return emptyList(); | |||
} | |||
return mapper(dbSession).selectEntitiesByUuids(uuids); | |||
} | |||
public Optional<EntityDto> selectEntityByKey(DbSession dbSession, String key) { | |||
return Optional.ofNullable(mapper(dbSession).selectEntityByKey(key)); | |||
} | |||
public List<EntityDto> selectEntitiesByKeys(DbSession dbSession, Collection<String> keys) { | |||
if (keys.isEmpty()) { | |||
return emptyList(); | |||
} | |||
return mapper(dbSession).selectEntitiesByKeys(keys); | |||
} | |||
} |
@@ -24,18 +24,14 @@ import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.db.entity.EntityDto; | |||
import static org.apache.commons.lang.StringUtils.trimToNull; | |||
import static org.sonar.db.component.DbTagsReader.readDbTags; | |||
public class ProjectDto { | |||
public class ProjectDto extends EntityDto { | |||
private static final String TAGS_SEPARATOR = ","; | |||
private String uuid; | |||
private String kee; | |||
private String qualifier; | |||
private String name; | |||
private String description; | |||
private boolean isPrivate = false; | |||
private String tags; | |||
private long createdAt; | |||
private long updatedAt; | |||
@@ -62,26 +58,11 @@ public class ProjectDto { | |||
return this; | |||
} | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
public ProjectDto setUuid(String uuid) { | |||
this.uuid = uuid; | |||
return this; | |||
} | |||
/** | |||
* This is the getter used by MyBatis mapper. | |||
*/ | |||
public String getKee() { | |||
return kee; | |||
} | |||
public String getKey() { | |||
return getKee(); | |||
} | |||
/** | |||
* This is the setter used by MyBatis mapper. | |||
*/ | |||
@@ -94,10 +75,6 @@ public class ProjectDto { | |||
return setKee(key); | |||
} | |||
public boolean isPrivate() { | |||
return isPrivate; | |||
} | |||
public ProjectDto setPrivate(boolean aPrivate) { | |||
isPrivate = aPrivate; | |||
return this; | |||
@@ -127,10 +104,6 @@ public class ProjectDto { | |||
return this; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public ProjectDto setName(String name) { | |||
this.name = name; | |||
return this; | |||
@@ -146,30 +119,8 @@ public class ProjectDto { | |||
return this; | |||
} | |||
public String getQualifier() { | |||
return qualifier; | |||
} | |||
public ProjectDto setQualifier(String qualifier) { | |||
this.qualifier = qualifier; | |||
return this; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
ProjectDto that = (ProjectDto) o; | |||
return Objects.equals(uuid, that.uuid); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return uuid != null ? uuid.hashCode() : 0; | |||
} | |||
} |
@@ -21,10 +21,13 @@ package org.sonar.db.project; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.ibatis.annotations.Param; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.entity.EntityDto; | |||
public interface ProjectMapper { | |||
@@ -72,4 +75,13 @@ public interface ProjectMapper { | |||
@CheckForNull | |||
Long getNclocSum(@Nullable @Param("projectUuidToExclude") String projectUuidToExclude); | |||
@CheckForNull | |||
EntityDto selectEntityByUuid(String uuid); | |||
List<EntityDto> selectEntitiesByUuids(@Param("uuids") Collection<String> uuids); | |||
@CheckForNull | |||
EntityDto selectEntityByKey(String key); | |||
List<EntityDto> selectEntitiesByKeys(@Param("keys") Collection<String> keys); | |||
} |
@@ -65,20 +65,6 @@ public class PropertiesDao implements Dao { | |||
this.auditPersister = auditPersister; | |||
} | |||
/** | |||
* Returns the logins of users who have subscribed to the given notification dispatcher with the given notification channel. | |||
* If a resource ID is passed, the search is made on users who have specifically subscribed for the given resource. | |||
* Note that {@link UserRole#USER} permission is not checked here, filter the results with | |||
* {@link org.sonar.db.permission.AuthorizationDao#keepAuthorizedLoginsOnProject} | |||
* | |||
* @return the list of Subscriber (maybe be empty - obviously) | |||
*/ | |||
public Set<Subscriber> findUsersForNotification(String notificationDispatcherKey, String notificationChannelKey, @Nullable String projectKey) { | |||
try (DbSession session = mybatis.openSession(false)) { | |||
return getMapper(session).findUsersForNotification(NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey, projectKey); | |||
} | |||
} | |||
public Set<EmailSubscriberDto> findEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey, | |||
@Nullable String projectKey) { | |||
return getMapper(dbSession).findEmailRecipientsForNotification(NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey, projectKey, null); | |||
@@ -171,6 +157,7 @@ public class PropertiesDao implements Dao { | |||
return getMapper(session).selectByKeyAndMatchingValue(key, value); | |||
} | |||
//TODO | |||
public List<PropertyDto> selectByKeyAndUserUuidAndComponentQualifier(DbSession session, String key, String userUuid, String qualifier) { | |||
return getMapper(session).selectByKeyAndUserUuidAndComponentQualifier(key, userUuid, qualifier); | |||
} |
@@ -27,8 +27,6 @@ import org.sonar.db.EmailSubscriberDto; | |||
public interface PropertiesMapper { | |||
Set<Subscriber> findUsersForNotification(@Param("notifKey") String notificationKey, @Nullable @Param("projectKey") String projectKey); | |||
Set<EmailSubscriberDto> findEmailRecipientsForNotification(@Param("notifKey") String notificationKey, @Nullable @Param("projectKey") String projectKey, | |||
@Nullable @Param("logins") List<String> logins); | |||
@@ -48,10 +46,6 @@ public interface PropertiesMapper { | |||
List<PropertyDto> selectByKeyAndMatchingValue(@Param("key") String key, @Param("value") String value); | |||
List<String> selectUuidsByUser(@Param("userUuid") String userUuid); | |||
List<String> selectIdsByMatchingLogin(@Param("login") String login, @Param("propertyKeys") List<String> propertyKeys); | |||
void insertAsEmpty(@Param("uuid") String uuid, @Param("key") String key, @Nullable @Param("userUuid") String userUuid, @Nullable @Param("componentUuid") String componentUuid, | |||
@Param("now") long now); | |||
@@ -65,8 +59,6 @@ public interface PropertiesMapper { | |||
int deleteProjectProperty(@Param("key") String key, @Param("componentUuid") String componentUuid); | |||
int deleteProjectProperties(@Param("key") String key, @Param("value") String value); | |||
int deleteGlobalProperty(@Param("key") String key); | |||
int deleteByQuery(@Param("query") PropertyQuery query); |
@@ -202,4 +202,64 @@ | |||
</if> | |||
</select> | |||
<sql id="entityProjectColumns"> | |||
p.uuid as uuid, p.kee as kee, p.name as name, p.private as isPrivate, p.qualifier as qualifier | |||
</sql> | |||
<sql id="entityPortfolioColumns"> | |||
p.uuid as uuid, p.kee as kee, p.name as name, p.private as isPrivate, | |||
case when p.parent_uuid is null then 'VW' else 'SVW' end as qualifier | |||
</sql> | |||
<select id="selectEntityByUuid" parameterType="string" resultType="Entity"> | |||
(select <include refid="entityProjectColumns"/> | |||
from projects p | |||
where p.uuid = #{uuid,jdbcType=VARCHAR}) | |||
UNION | |||
(select <include refid="entityPortfolioColumns"/> | |||
from portfolios p | |||
where p.uuid = #{uuid,jdbcType=VARCHAR}) | |||
</select> | |||
<select id="selectEntitiesByUuids" resultType="Entity"> | |||
(select <include refid="entityProjectColumns"/> | |||
from projects p | |||
where p.uuid in | |||
<foreach collection="uuids" open="(" close=")" item="uuid" separator=","> | |||
#{uuid,jdbcType=VARCHAR} | |||
</foreach>) | |||
UNION | |||
(select <include refid="entityPortfolioColumns"/> | |||
from portfolios p | |||
where p.uuid in | |||
<foreach collection="uuids" open="(" close=")" item="uuid" separator=","> | |||
#{uuid,jdbcType=VARCHAR} | |||
</foreach>) | |||
</select> | |||
<select id="selectEntityByKey" parameterType="string" resultType="Entity"> | |||
(select <include refid="entityProjectColumns"/> | |||
from projects p | |||
where p.kee = #{key,jdbcType=VARCHAR}) | |||
UNION | |||
(select <include refid="entityPortfolioColumns"/> | |||
from portfolios p | |||
where p.kee = #{key,jdbcType=VARCHAR}) | |||
</select> | |||
<select id="selectEntitiesByKeys" parameterType="string" resultType="Entity"> | |||
(select <include refid="entityProjectColumns"/> | |||
from projects p | |||
where p.kee in | |||
<foreach collection="keys" open="(" close=")" item="kee" separator=","> | |||
#{kee,jdbcType=VARCHAR} | |||
</foreach>) | |||
UNION | |||
(select <include refid="entityPortfolioColumns"/> | |||
from portfolios p | |||
where p.kee in | |||
<foreach collection="keys" open="(" close=")" item="kee" separator=","> | |||
#{kee,jdbcType=VARCHAR} | |||
</foreach>) </select> | |||
</mapper> |
@@ -3,35 +3,6 @@ | |||
<mapper namespace="org.sonar.db.property.PropertiesMapper"> | |||
<select id="findUsersForNotification" parameterType="map" resultType="org.sonar.db.property.Subscriber"> | |||
SELECT | |||
u.login as "login", | |||
${_true} as "global" | |||
FROM | |||
users u | |||
INNER JOIN properties p ON p.user_uuid = u.uuid | |||
WHERE | |||
p.prop_key = #{notifKey,jdbcType=VARCHAR} | |||
AND p.text_value = 'true' | |||
AND p.component_uuid IS NULL | |||
<if test="projectKey != null"> | |||
UNION | |||
SELECT | |||
u.login as "login", | |||
${_false} as "global" | |||
FROM | |||
users u | |||
INNER JOIN components c on c.kee = #{projectKey,jdbcType=VARCHAR} | |||
INNER JOIN properties p ON p.user_uuid = u.uuid | |||
WHERE | |||
p.prop_key = #{notifKey,jdbcType=VARCHAR} | |||
AND p.text_value = 'true' | |||
AND p.component_uuid = c.uuid | |||
</if> | |||
</select> | |||
<select id="findEmailRecipientsForNotification" parameterType="map" resultType="org.sonar.db.EmailSubscriberDto"> | |||
SELECT | |||
u.login as "login", | |||
@@ -59,13 +30,13 @@ | |||
u.email as "email" | |||
FROM | |||
users u | |||
INNER JOIN components c on | |||
c.kee = #{projectKey,jdbcType=VARCHAR} | |||
INNER JOIN projects proj on | |||
proj.kee = #{projectKey,jdbcType=VARCHAR} | |||
INNER JOIN properties p ON | |||
p.user_uuid = u.uuid | |||
and p.prop_key = #{notifKey,jdbcType=VARCHAR} | |||
and p.text_value = 'true' | |||
and p.component_uuid = c.uuid | |||
and p.component_uuid = proj.uuid | |||
WHERE | |||
u.email is not null | |||
<if test="logins != null"> | |||
@@ -189,24 +160,6 @@ | |||
</where> | |||
</select> | |||
<select id="selectUuidsByUser" parameterType="map" resultType="String"> | |||
select py.uuid | |||
from properties py | |||
where | |||
py.user_uuid=#{userUuid,jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectIdsByMatchingLogin" parameterType="String" resultType="String"> | |||
select py.uuid | |||
from properties py | |||
where | |||
py.text_value like #{login,jdbcType=VARCHAR} | |||
and py.prop_key in | |||
<foreach item="property" index="index" collection="propertyKeys" open="(" separator="," close=")"> | |||
#{property,jdbcType=VARCHAR} | |||
</foreach> | |||
</select> | |||
<select id="selectByKeyAndMatchingValue" parameterType="map" resultType="ScrapProperty"> | |||
select | |||
<include refid="columnsToScrapPropertyDto"/> | |||
@@ -313,15 +266,6 @@ | |||
and user_uuid is null | |||
</delete> | |||
<delete id="deleteProjectProperties" parameterType="map"> | |||
delete from properties | |||
where | |||
prop_key=#{key} | |||
and text_value = #{value} | |||
and component_uuid is not null | |||
and user_uuid is null | |||
</delete> | |||
<delete id="deleteGlobalProperty" parameterType="string"> | |||
delete from properties | |||
where |
@@ -24,6 +24,7 @@ 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.entity.EntityDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonar.db.property.PropertyQuery; | |||
@@ -38,29 +39,29 @@ public class FavoriteDbTester { | |||
this.dbSession = db.getSession(); | |||
} | |||
public void add(ComponentDto componentDto, String userUuid, String userLogin) { | |||
public void add(EntityDto entity, String userUuid, String userLogin) { | |||
dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto() | |||
.setKey(PROP_FAVORITE_KEY) | |||
.setUserUuid(userUuid) | |||
.setComponentUuid(componentDto.uuid()), | |||
userLogin, componentDto.getKey(), componentDto.name(), componentDto.qualifier()); | |||
.setComponentUuid(entity.getUuid()), | |||
userLogin, entity.getKey(), entity.getName(), entity.getQualifier()); | |||
dbSession.commit(); | |||
} | |||
public boolean hasFavorite(ComponentDto componentDto, String userUuid) { | |||
public boolean hasFavorite(EntityDto entity, String userUuid) { | |||
List<PropertyDto> result = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() | |||
.setKey(PROP_FAVORITE_KEY) | |||
.setComponentUuid(componentDto.uuid()) | |||
.setComponentUuid(entity.getUuid()) | |||
.setUserUuid(userUuid) | |||
.build(), dbSession); | |||
return !result.isEmpty(); | |||
} | |||
public boolean hasNoFavorite(ComponentDto componentDto) { | |||
public boolean hasNoFavorite(EntityDto entity) { | |||
List<PropertyDto> result = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() | |||
.setKey(PROP_FAVORITE_KEY) | |||
.setComponentUuid(componentDto.uuid()) | |||
.setComponentUuid(entity.getUuid()) | |||
.build(), dbSession); | |||
return result.isEmpty(); | |||
} |
@@ -28,7 +28,7 @@ import javax.annotation.Nullable; | |||
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.entity.EntityDto; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singletonList; | |||
@@ -75,15 +75,15 @@ public class PropertyDbTester { | |||
null, null, null, null); | |||
} | |||
public void insertPropertySet(String settingBaseKey, @Nullable ComponentDto componentDto, Map<String, String>... fieldValues) { | |||
public void insertPropertySet(String settingBaseKey, @Nullable EntityDto entity, Map<String, String>... fieldValues) { | |||
int index = 1; | |||
List<PropertyDto> propertyDtos = new ArrayList<>(); | |||
List<String> ids = new ArrayList<>(); | |||
for (Map<String, String> fieldValue : fieldValues) { | |||
for (Map.Entry<String, String> entry : fieldValue.entrySet()) { | |||
String key = settingBaseKey + "." + index + "." + entry.getKey(); | |||
if (componentDto != null) { | |||
propertyDtos.add(newComponentPropertyDto(componentDto).setKey(key).setValue(entry.getValue())); | |||
if (entity != null) { | |||
propertyDtos.add(newComponentPropertyDto(entity).setKey(key).setValue(entry.getValue())); | |||
} else { | |||
propertyDtos.add(newGlobalPropertyDto().setKey(key).setValue(entry.getValue())); | |||
} | |||
@@ -92,14 +92,14 @@ public class PropertyDbTester { | |||
index++; | |||
} | |||
String idsValue = Joiner.on(",").join(ids); | |||
if (componentDto != null) { | |||
propertyDtos.add(newComponentPropertyDto(componentDto).setKey(settingBaseKey).setValue(idsValue)); | |||
if (entity != null) { | |||
propertyDtos.add(newComponentPropertyDto(entity).setKey(settingBaseKey).setValue(idsValue)); | |||
} else { | |||
propertyDtos.add(newGlobalPropertyDto().setKey(settingBaseKey).setValue(idsValue)); | |||
} | |||
String componentKey = componentDto == null ? null : componentDto.getKey(); | |||
String componentName = componentDto == null ? null : componentDto.name(); | |||
String qualififer = componentDto == null ? null : componentDto.qualifier(); | |||
String componentKey = entity == null ? null : entity.getKey(); | |||
String componentName = entity == null ? null : entity.getName(); | |||
String qualififer = entity == null ? null : entity.getQualifier(); | |||
insertProperties(propertyDtos, null, componentKey, componentName, qualififer); | |||
} | |||
@@ -22,6 +22,7 @@ package org.sonar.db.property; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.math.RandomUtils; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.user.UserDto; | |||
import static com.google.common.base.Preconditions.checkNotNull; | |||
@@ -47,9 +48,9 @@ public class PropertyTesting { | |||
return newPropertyDto(key, value, component.uuid(), null); | |||
} | |||
public static PropertyDto newComponentPropertyDto(ComponentDto component) { | |||
checkNotNull(component.uuid()); | |||
return newPropertyDto(component.uuid(), null); | |||
public static PropertyDto newComponentPropertyDto(EntityDto entity) { | |||
checkNotNull(entity.getUuid()); | |||
return newPropertyDto(entity.getUuid(), null); | |||
} | |||
public static PropertyDto newUserPropertyDto(String key, String value, UserDto user) { |
@@ -26,6 +26,8 @@ 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.entity.EntityDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.property.PropertyQuery; | |||
import org.sonar.db.user.UserDto; | |||
@@ -44,7 +46,7 @@ public class FavoriteUpdaterIT { | |||
@Test | |||
public void put_favorite() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
UserDto user = db.users().insertUser(); | |||
assertNoFavorite(project, user); | |||
@@ -55,23 +57,23 @@ public class FavoriteUpdaterIT { | |||
@Test | |||
public void do_nothing_when_no_user() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
underTest.add(dbSession, project, null, null,true); | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() | |||
.setComponentUuid(project.uuid()) | |||
.setComponentUuid(project.getUuid()) | |||
.build(), dbSession)).isEmpty(); | |||
} | |||
@Test | |||
public void do_not_add_favorite_when_already_100_favorite_projects() { | |||
UserDto user = db.users().insertUser(); | |||
IntStream.rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getMainBranchComponent(), user.getUuid(), user.getName())); | |||
IntStream.rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getProjectDto(), user.getUuid(), user.getName())); | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() | |||
.setUserUuid(user.getUuid()) | |||
.build(), dbSession)).hasSize(100); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
underTest.add(dbSession, project, user.getUuid(), user.getLogin(), false); | |||
@@ -83,12 +85,12 @@ public class FavoriteUpdaterIT { | |||
@Test | |||
public void do_not_add_favorite_when_already_100_favorite_portfolios() { | |||
UserDto user = db.users().insertUser(); | |||
IntStream.rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getMainBranchComponent(), | |||
IntStream.rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getProjectDto(), | |||
user.getUuid(), user.getLogin())); | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() | |||
.setUserUuid(user.getUuid()) | |||
.build(), dbSession)).hasSize(100); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
underTest.add(dbSession, project, user.getUuid(), user.getLogin(), false); | |||
@@ -100,9 +102,9 @@ public class FavoriteUpdaterIT { | |||
@Test | |||
public void fail_when_more_than_100_projects_favorites() { | |||
UserDto user = db.users().insertUser(); | |||
IntStream.rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getMainBranchComponent(), | |||
IntStream.rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getProjectDto(), | |||
user.getUuid(), user.getLogin())); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
assertThatThrownBy(() -> underTest.add(dbSession, project, user.getUuid(), user.getLogin(), true)) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
@@ -111,27 +113,27 @@ public class FavoriteUpdaterIT { | |||
@Test | |||
public void fail_when_adding_existing_favorite() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
UserDto user = db.users().insertUser(); | |||
underTest.add(dbSession, project, user.getUuid(), user.getLogin(), true); | |||
assertFavorite(project, user); | |||
assertThatThrownBy(() -> underTest.add(dbSession, project, user.getUuid(), user.getLogin(), true)) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
.hasMessage(String.format("Component '%s' (uuid: %s) is already a favorite", project.getKey(), project.uuid())); | |||
.hasMessage(String.format("Component '%s' (uuid: %s) is already a favorite", project.getKey(), project.getUuid())); | |||
} | |||
private void assertFavorite(ComponentDto project, UserDto user) { | |||
private void assertFavorite(EntityDto entity, UserDto user) { | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() | |||
.setUserUuid(user.getUuid()) | |||
.setComponentUuid(project.uuid()) | |||
.setComponentUuid(entity.getUuid()) | |||
.build(), dbSession)).hasSize(1); | |||
} | |||
private void assertNoFavorite(ComponentDto project, UserDto user) { | |||
private void assertNoFavorite(EntityDto entity, UserDto user) { | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() | |||
.setUserUuid(user.getUuid()) | |||
.setComponentUuid(project.uuid()) | |||
.setComponentUuid(entity.getUuid()) | |||
.build(), dbSession)).isEmpty(); | |||
} | |||
} |
@@ -24,6 +24,7 @@ import javax.annotation.Nullable; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonar.db.property.PropertyQuery; | |||
@@ -41,7 +42,7 @@ public class FavoriteUpdater { | |||
/** | |||
* Set favorite to the logged in user. If no user, no action is done | |||
*/ | |||
public void add(DbSession dbSession, ComponentDto componentDto, @Nullable String userUuid, @Nullable String userLogin, boolean failIfTooManyFavorites) { | |||
public void add(DbSession dbSession, EntityDto entity, @Nullable String userUuid, @Nullable String userLogin, boolean failIfTooManyFavorites) { | |||
if (userUuid == null) { | |||
return; | |||
} | |||
@@ -49,21 +50,21 @@ public class FavoriteUpdater { | |||
List<PropertyDto> existingFavoriteOnComponent = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() | |||
.setKey(PROP_FAVORITE_KEY) | |||
.setUserUuid(userUuid) | |||
.setComponentUuid(componentDto.uuid()) | |||
.setComponentUuid(entity.getUuid()) | |||
.build(), dbSession); | |||
checkArgument(existingFavoriteOnComponent.isEmpty(), "Component '%s' (uuid: %s) is already a favorite", componentDto.getKey(), componentDto.uuid()); | |||
checkArgument(existingFavoriteOnComponent.isEmpty(), "Component '%s' (uuid: %s) is already a favorite", entity.getKey(), entity.getUuid()); | |||
List<PropertyDto> existingFavorites = dbClient.propertiesDao().selectByKeyAndUserUuidAndComponentQualifier(dbSession, PROP_FAVORITE_KEY, userUuid, componentDto.qualifier()); | |||
List<PropertyDto> existingFavorites = dbClient.propertiesDao().selectByKeyAndUserUuidAndComponentQualifier(dbSession, PROP_FAVORITE_KEY, userUuid, entity.getQualifier()); | |||
if (existingFavorites.size() >= 100) { | |||
checkArgument(!failIfTooManyFavorites, "You cannot have more than 100 favorites on components with qualifier '%s'", componentDto.qualifier()); | |||
checkArgument(!failIfTooManyFavorites, "You cannot have more than 100 favorites on components with qualifier '%s'", entity.getQualifier()); | |||
return; | |||
} | |||
dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto() | |||
.setKey(PROP_FAVORITE_KEY) | |||
.setComponentUuid(componentDto.uuid()) | |||
.setComponentUuid(entity.getUuid()) | |||
.setUserUuid(userUuid), | |||
userLogin, | |||
componentDto.getKey(), componentDto.name(), componentDto.qualifier()); | |||
entity.getKey(), entity.getName(), entity.getQualifier()); | |||
} | |||
/** |
@@ -113,69 +113,10 @@ public class DefaultNotificationManager implements NotificationManager { | |||
return dbClient.notificationQueueDao().count(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
@Override | |||
public Multimap<String, NotificationChannel> findSubscribedRecipientsForDispatcher(NotificationDispatcher dispatcher, | |||
String projectKey, SubscriberPermissionsOnProject subscriberPermissionsOnProject) { | |||
verifyProjectKey(projectKey); | |||
String dispatcherKey = dispatcher.getKey(); | |||
Set<SubscriberAndChannel> subscriberAndChannels = Arrays.stream(notificationChannels) | |||
.flatMap(notificationChannel -> toSubscriberAndChannels(dispatcherKey, projectKey, notificationChannel)) | |||
.collect(Collectors.toSet()); | |||
if (subscriberAndChannels.isEmpty()) { | |||
return ImmutableMultimap.of(); | |||
} | |||
ImmutableSetMultimap.Builder<String, NotificationChannel> builder = ImmutableSetMultimap.builder(); | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
Set<String> authorizedLogins = keepAuthorizedLogins(dbSession, projectKey, subscriberAndChannels, subscriberPermissionsOnProject); | |||
subscriberAndChannels.stream() | |||
.filter(subscriberAndChannel -> authorizedLogins.contains(subscriberAndChannel.subscriber().getLogin())) | |||
.forEach(subscriberAndChannel -> builder.put(subscriberAndChannel.subscriber().getLogin(), subscriberAndChannel.channel())); | |||
} | |||
return builder.build(); | |||
} | |||
private static void verifyProjectKey(String projectKey) { | |||
requireNonNull(projectKey, "projectKey is mandatory"); | |||
} | |||
private Stream<SubscriberAndChannel> toSubscriberAndChannels(String dispatcherKey, String projectKey, NotificationChannel notificationChannel) { | |||
Set<Subscriber> usersForNotification = dbClient.propertiesDao().findUsersForNotification(dispatcherKey, notificationChannel.getKey(), projectKey); | |||
return usersForNotification | |||
.stream() | |||
.map(login -> new SubscriberAndChannel(login, notificationChannel)); | |||
} | |||
private Set<String> keepAuthorizedLogins(DbSession dbSession, String projectKey, Set<SubscriberAndChannel> subscriberAndChannels, | |||
SubscriberPermissionsOnProject requiredPermissions) { | |||
if (requiredPermissions.getGlobalSubscribers().equals(requiredPermissions.getProjectSubscribers())) { | |||
return keepAuthorizedLogins(dbSession, projectKey, subscriberAndChannels, null, requiredPermissions.getGlobalSubscribers()); | |||
} else { | |||
return Stream | |||
.concat( | |||
keepAuthorizedLogins(dbSession, projectKey, subscriberAndChannels, true, requiredPermissions.getGlobalSubscribers()).stream(), | |||
keepAuthorizedLogins(dbSession, projectKey, subscriberAndChannels, false, requiredPermissions.getProjectSubscribers()).stream()) | |||
.collect(Collectors.toSet()); | |||
} | |||
} | |||
private Set<String> keepAuthorizedLogins(DbSession dbSession, String projectKey, Set<SubscriberAndChannel> subscriberAndChannels, | |||
@Nullable Boolean global, String permission) { | |||
Set<String> logins = subscriberAndChannels.stream() | |||
.filter(s -> global == null || s.subscriber().isGlobal() == global) | |||
.map(s -> s.subscriber().getLogin()) | |||
.collect(Collectors.toSet()); | |||
if (logins.isEmpty()) { | |||
return Collections.emptySet(); | |||
} | |||
return dbClient.authorizationDao().keepAuthorizedLoginsOnProject(dbSession, logins, projectKey, permission); | |||
} | |||
@Override | |||
public Set<EmailRecipient> findSubscribedEmailRecipients(String dispatcherKey, String projectKey, SubscriberPermissionsOnProject subscriberPermissionsOnProject) { | |||
verifyProjectKey(projectKey); | |||
@@ -244,23 +185,6 @@ public class DefaultNotificationManager implements NotificationManager { | |||
.filter(s -> authorizedLogins.contains(s.getLogin())); | |||
} | |||
private record SubscriberAndChannel(Subscriber subscriber, NotificationChannel channel) { | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
SubscriberAndChannel that = (SubscriberAndChannel) o; | |||
return Objects.equals(subscriber, that.subscriber) && | |||
Objects.equals(channel, that.channel); | |||
} | |||
} | |||
@VisibleForTesting | |||
protected List<NotificationChannel> getChannels() { | |||
return Arrays.asList(notificationChannels); |
@@ -44,23 +44,6 @@ public interface NotificationManager { | |||
*/ | |||
<T extends Notification> void scheduleForSending(T notification); | |||
/** | |||
* <p> | |||
* Returns the list of users who subscribed to the given dispatcher, along with the notification channels (email, twitter, ...) that they choose | |||
* for this dispatcher. | |||
* </p> | |||
* <p> | |||
* The resource ID can be null in case of notifications that have nothing to do with a specific project (like system notifications). | |||
* </p> | |||
* | |||
* @param dispatcher the dispatcher for which this list of users is requested | |||
* @param projectKey key of the project | |||
* @param subscriberPermissionsOnProject the required permission for global and project subscribers | |||
* @return the list of user login along with the subscribed channels | |||
*/ | |||
Multimap<String, NotificationChannel> findSubscribedRecipientsForDispatcher(NotificationDispatcher dispatcher, String projectKey, | |||
SubscriberPermissionsOnProject subscriberPermissionsOnProject); | |||
record EmailRecipient(String login, String email) { | |||
public EmailRecipient(String login, String email) { | |||
this.login = requireNonNull(login, "login can't be null"); |
@@ -142,125 +142,6 @@ public class DefaultNotificationManagerTest { | |||
verify(underTest, times(1)).logDeserializationIssue(); | |||
} | |||
@Test | |||
public void shouldFindNoRecipient() { | |||
assertThat(underTest.findSubscribedRecipientsForDispatcher(dispatcher, "uuid_45", new SubscriberPermissionsOnProject(UserRole.USER)).asMap().entrySet()) | |||
.isEmpty(); | |||
} | |||
@Test | |||
public void shouldFindSubscribedRecipientForGivenResource() { | |||
String projectKey = randomAlphabetic(6); | |||
String otherProjectKey = randomAlphabetic(7); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Email", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user1", false), new Subscriber("user3", false), new Subscriber("user3", true))); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", otherProjectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user2", false))); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user3", true))); | |||
when(propertiesDao.findUsersForNotification("NewAlerts", "Twitter", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user4", false))); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user1", "user3"), projectKey, "user")) | |||
.thenReturn(newHashSet("user1", "user3")); | |||
Multimap<String, NotificationChannel> multiMap = underTest.findSubscribedRecipientsForDispatcher(dispatcher, projectKey, | |||
ALL_MUST_HAVE_ROLE_USER); | |||
assertThat(multiMap.entries()).hasSize(3); | |||
Map<String, Collection<NotificationChannel>> map = multiMap.asMap(); | |||
assertThat(map.get("user1")).containsOnly(emailChannel); | |||
assertThat(map.get("user2")).isNull(); | |||
assertThat(map.get("user3")).containsOnly(emailChannel, twitterChannel); | |||
assertThat(map.get("user4")).isNull(); | |||
// code is optimized to perform only 1 SQL requests for all channels | |||
verify(authorizationDao, times(1)).keepAuthorizedLoginsOnProject(eq(dbSession), anySet(), anyString(), anyString()); | |||
} | |||
@Test | |||
public void should_apply_distinct_permission_filtering_global_or_project_subscribers() { | |||
String globalPermission = randomAlphanumeric(4); | |||
String projectPermission = randomAlphanumeric(5); | |||
String projectKey = randomAlphabetic(6); | |||
String otherProjectKey = randomAlphabetic(7); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Email", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user1", false), new Subscriber("user3", false), new Subscriber("user3", true))); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", otherProjectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user2", false))); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user3", true))); | |||
when(propertiesDao.findUsersForNotification("NewAlerts", "Twitter", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user4", false))); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user3", "user4"), projectKey, globalPermission)) | |||
.thenReturn(newHashSet("user3")); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user1", "user3"), projectKey, projectPermission)) | |||
.thenReturn(newHashSet("user1", "user3")); | |||
Multimap<String, NotificationChannel> multiMap = underTest.findSubscribedRecipientsForDispatcher(dispatcher, projectKey, | |||
new SubscriberPermissionsOnProject(globalPermission, projectPermission)); | |||
assertThat(multiMap.entries()).hasSize(3); | |||
Map<String, Collection<NotificationChannel>> map = multiMap.asMap(); | |||
assertThat(map.get("user1")).containsOnly(emailChannel); | |||
assertThat(map.get("user2")).isNull(); | |||
assertThat(map.get("user3")).containsOnly(emailChannel, twitterChannel); | |||
assertThat(map.get("user4")).isNull(); | |||
// code is optimized to perform only 2 SQL requests for all channels | |||
verify(authorizationDao, times(1)).keepAuthorizedLoginsOnProject(eq(dbSession), anySet(), anyString(), eq(globalPermission)); | |||
verify(authorizationDao, times(1)).keepAuthorizedLoginsOnProject(eq(dbSession), anySet(), anyString(), eq(projectPermission)); | |||
} | |||
@Test | |||
public void do_not_call_db_for_project_permission_filtering_if_there_is_no_project_subscriber() { | |||
String globalPermission = randomAlphanumeric(4); | |||
String projectPermission = randomAlphanumeric(5); | |||
String projectKey = randomAlphabetic(6); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Email", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user3", true))); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user3", true))); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user3"), projectKey, globalPermission)) | |||
.thenReturn(newHashSet("user3")); | |||
Multimap<String, NotificationChannel> multiMap = underTest.findSubscribedRecipientsForDispatcher(dispatcher, projectKey, | |||
new SubscriberPermissionsOnProject(globalPermission, projectPermission)); | |||
assertThat(multiMap.entries()).hasSize(2); | |||
Map<String, Collection<NotificationChannel>> map = multiMap.asMap(); | |||
assertThat(map.get("user3")).containsOnly(emailChannel, twitterChannel); | |||
verify(authorizationDao, times(1)).keepAuthorizedLoginsOnProject(eq(dbSession), anySet(), anyString(), eq(globalPermission)); | |||
verify(authorizationDao, times(0)).keepAuthorizedLoginsOnProject(eq(dbSession), anySet(), anyString(), eq(projectPermission)); | |||
} | |||
@Test | |||
public void do_not_call_db_for_project_permission_filtering_if_there_is_no_global_subscriber() { | |||
String globalPermission = randomAlphanumeric(4); | |||
String projectPermission = randomAlphanumeric(5); | |||
String projectKey = randomAlphabetic(6); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Email", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user3", false))); | |||
when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", projectKey)) | |||
.thenReturn(newHashSet(new Subscriber("user3", false))); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user3"), projectKey, projectPermission)) | |||
.thenReturn(newHashSet("user3")); | |||
Multimap<String, NotificationChannel> multiMap = underTest.findSubscribedRecipientsForDispatcher(dispatcher, projectKey, | |||
new SubscriberPermissionsOnProject(globalPermission, projectPermission)); | |||
assertThat(multiMap.entries()).hasSize(2); | |||
Map<String, Collection<NotificationChannel>> map = multiMap.asMap(); | |||
assertThat(map.get("user3")).containsOnly(emailChannel, twitterChannel); | |||
verify(authorizationDao, times(0)).keepAuthorizedLoginsOnProject(eq(dbSession), anySet(), anyString(), eq(globalPermission)); | |||
verify(authorizationDao, times(1)).keepAuthorizedLoginsOnProject(eq(dbSession), anySet(), anyString(), eq(projectPermission)); | |||
} | |||
@Test | |||
public void findSubscribedEmailRecipients_fails_with_NPE_if_projectKey_is_null() { | |||
String dispatcherKey = randomAlphabetic(12); |
@@ -28,6 +28,7 @@ import javax.annotation.Nullable; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
@@ -88,7 +89,6 @@ public abstract class AbstractUserSession implements UserSession { | |||
@Override | |||
public boolean hasComponentPermission(String permission, ComponentDto component) { | |||
Optional<String> projectUuid1 = componentUuidToProjectUuid(component.uuid()); | |||
return projectUuid1 | |||
@@ -101,6 +101,11 @@ public abstract class AbstractUserSession implements UserSession { | |||
return hasProjectUuidPermission(permission, project.getUuid()); | |||
} | |||
@Override | |||
public final boolean hasEntityPermission(String permission, EntityDto entity) { | |||
return hasProjectUuidPermission(permission, entity.getUuid()); | |||
} | |||
@Override | |||
public final boolean hasProjectPermission(String permission, String projectUuid) { | |||
return hasProjectUuidPermission(permission, projectUuid); | |||
@@ -148,6 +153,21 @@ public abstract class AbstractUserSession implements UserSession { | |||
return doKeepAuthorizedProjects(permission, projects); | |||
} | |||
@Override | |||
public <T extends EntityDto> List<T> keepAuthorizedEntities(String permission, Collection<T> projects) { | |||
return doKeepAuthorizedEntities(permission, projects); | |||
} | |||
/** | |||
* Naive implementation, to be overridden if needed | |||
*/ | |||
protected <T extends EntityDto> List<T> doKeepAuthorizedEntities(String permission, Collection<T> entities) { | |||
boolean allowPublicComponent = PUBLIC_PERMISSIONS.contains(permission); | |||
return entities.stream() | |||
.filter(c -> (allowPublicComponent && !c.isPrivate()) || hasProjectPermission(permission, c.getUuid())) | |||
.toList(); | |||
} | |||
/** | |||
* Naive implementation, to be overridden if needed | |||
*/ | |||
@@ -201,6 +221,15 @@ public abstract class AbstractUserSession implements UserSession { | |||
throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE); | |||
} | |||
@Override | |||
public UserSession checkEntityPermission(String projectPermission, EntityDto entity) { | |||
if (hasEntityPermission(projectPermission, entity)) { | |||
return this; | |||
} | |||
throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE); | |||
} | |||
@Override | |||
public UserSession checkChildProjectsPermission(String projectPermission, ComponentDto component) { | |||
if (!APP.equals(component.qualifier()) || hasChildProjectsPermission(projectPermission, component)) { |
@@ -41,6 +41,7 @@ import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTreeQuery; | |||
import org.sonar.db.component.ComponentTreeQuery.Strategy; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.GroupDto; | |||
@@ -195,6 +196,17 @@ public class ServerUserSession extends AbstractUserSession { | |||
.toList(); | |||
} | |||
@Override | |||
public <T extends EntityDto> List<T> keepAuthorizedEntities(String permission, Collection<T> projects) { | |||
Set<String> projectsUuids = projects.stream().map(EntityDto::getUuid).collect(Collectors.toSet()); | |||
// TODO | |||
Set<String> authorizedProjectsUuids = keepProjectsUuidsByPermission(permission, projectsUuids); | |||
return projects.stream() | |||
.filter(project -> authorizedProjectsUuids.contains(project.getUuid())) | |||
.toList(); | |||
} | |||
private Set<String> keepProjectsUuidsByPermission(String permission, Collection<String> projectsUuids) { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
String userUuid = userDto == null ? null : userDto.getUuid(); |
@@ -24,6 +24,7 @@ import java.util.List; | |||
import java.util.Optional; | |||
import javax.annotation.CheckForNull; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.GroupDto; | |||
@@ -128,6 +129,12 @@ public class ThreadLocalUserSession implements UserSession { | |||
return this; | |||
} | |||
@Override | |||
public UserSession checkEntityPermission(String projectPermission, EntityDto entity) { | |||
get().checkEntityPermission(projectPermission, entity); | |||
return this; | |||
} | |||
@Override | |||
public UserSession checkProjectPermission(String projectPermission, ProjectDto project) { | |||
get().checkProjectPermission(projectPermission, project); | |||
@@ -173,6 +180,11 @@ public class ThreadLocalUserSession implements UserSession { | |||
return get().hasComponentPermission(permission, component); | |||
} | |||
@Override | |||
public boolean hasEntityPermission(String permission, EntityDto entity) { | |||
return get().hasEntityPermission(permission, entity); | |||
} | |||
@Override | |||
public boolean hasProjectPermission(String permission, ProjectDto project) { | |||
return get().hasProjectPermission(permission, project); | |||
@@ -208,9 +220,13 @@ public class ThreadLocalUserSession implements UserSession { | |||
return get().keepAuthorizedComponents(permission, components); | |||
} | |||
@Override | |||
public <T extends EntityDto> List<T> keepAuthorizedEntities(String permission, Collection<T> entities) { | |||
return get().keepAuthorizedEntities(permission, entities); | |||
} | |||
@Override | |||
public List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects) { | |||
return get().keepAuthorizedProjects(permission, projects); | |||
} | |||
} |
@@ -25,7 +25,9 @@ import java.util.List; | |||
import java.util.Optional; | |||
import javax.annotation.CheckForNull; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.GroupDto; | |||
@@ -149,6 +151,8 @@ public interface UserSession { | |||
boolean hasProjectPermission(String permission, ProjectDto project); | |||
boolean hasEntityPermission(String permission, EntityDto entity); | |||
boolean hasProjectPermission(String permission, String projectUuid); | |||
boolean hasChildProjectsPermission(String permission, ComponentDto component); | |||
@@ -176,6 +180,8 @@ public interface UserSession { | |||
*/ | |||
List<ComponentDto> keepAuthorizedComponents(String permission, Collection<ComponentDto> components); | |||
<T extends EntityDto> List<T> keepAuthorizedEntities(String permission, Collection<T> components); | |||
List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects); | |||
/** | |||
@@ -190,6 +196,8 @@ public interface UserSession { | |||
*/ | |||
UserSession checkProjectPermission(String projectPermission, ProjectDto project); | |||
UserSession checkEntityPermission(String projectPermission, EntityDto entity); | |||
/** | |||
* Ensures that {@link #hasChildProjectsPermission(String, ComponentDto)} is {@code true} | |||
* otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. |
@@ -30,6 +30,7 @@ import org.junit.runner.Description; | |||
import org.junit.runners.model.Statement; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.project.ProjectDto; | |||
@@ -204,7 +205,7 @@ public class UserSessionRule implements TestRule, UserSession { | |||
return this; | |||
} | |||
public UserSession registerBranches(BranchDto ...branchDtos){ | |||
public UserSession registerBranches(BranchDto... branchDtos) { | |||
ensureAbstractMockUserSession().registerBranches(branchDtos); | |||
return this; | |||
} | |||
@@ -262,6 +263,11 @@ public class UserSessionRule implements TestRule, UserSession { | |||
return currentUserSession.hasProjectPermission(permission, project); | |||
} | |||
@Override | |||
public boolean hasEntityPermission(String permission, EntityDto entity) { | |||
return currentUserSession.hasProjectPermission(permission, entity.getUuid()); | |||
} | |||
@Override | |||
public boolean hasProjectPermission(String permission, String projectUuid) { | |||
return currentUserSession.hasProjectPermission(permission, projectUuid); | |||
@@ -292,6 +298,11 @@ public class UserSessionRule implements TestRule, UserSession { | |||
return currentUserSession.keepAuthorizedComponents(permission, components); | |||
} | |||
@Override | |||
public <T extends EntityDto> List<T> keepAuthorizedEntities(String permission, Collection<T> entities) { | |||
return currentUserSession.keepAuthorizedEntities(permission, entities); | |||
} | |||
@Override | |||
public List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects) { | |||
return currentUserSession.keepAuthorizedProjects(permission, projects); | |||
@@ -369,6 +380,12 @@ public class UserSessionRule implements TestRule, UserSession { | |||
return this; | |||
} | |||
@Override | |||
public UserSession checkEntityPermission(String projectPermission, EntityDto entity) { | |||
currentUserSession.checkEntityPermission(projectPermission, entity); | |||
return this; | |||
} | |||
@Override | |||
public UserSession checkProjectPermission(String projectPermission, ProjectDto project) { | |||
currentUserSession.checkProjectPermission(projectPermission, project); |
@@ -40,6 +40,7 @@ import org.sonar.db.DbTester; | |||
import org.sonar.db.ce.CeTaskTypes; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
@@ -91,11 +92,8 @@ public class ReportSubmitterIT { | |||
private final TestProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class); | |||
private final Configuration config = mock(Configuration.class); | |||
private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), mock(I18n.class), mock(System2.class), permissionTemplateService, | |||
new FavoriteUpdater(db.getDbClient()), projectIndexers, new SequenceUuidFactory(), defaultBranchNameResolver, true | |||
); | |||
new FavoriteUpdater(db.getDbClient()), projectIndexers, new SequenceUuidFactory(), defaultBranchNameResolver, true); | |||
private final BranchSupport ossEditionBranchSupport = new BranchSupport(null); | |||
private final ReportSubmitter underTest = new ReportSubmitter(queue, userSession, componentUpdater, permissionTemplateService, db.getDbClient(), ossEditionBranchSupport, | |||
@@ -146,7 +144,7 @@ public class ReportSubmitterIT { | |||
userSession.logIn(user).addProjectPermission(SCAN.getKey(), project); | |||
mockSuccessfulPrepareSubmitCall(); | |||
underTest.submit(project.getKey(), project.name(), emptyMap(), IOUtils.toInputStream("{binary}", StandardCharsets.UTF_8)); | |||
underTest.submit(project.getKey(), project.name(), emptyMap(), IOUtils.toInputStream("{binary}", UTF_8)); | |||
verifyReportIsPersisted(TASK_UUID); | |||
verifyNoInteractions(permissionTemplateService); | |||
@@ -165,7 +163,7 @@ public class ReportSubmitterIT { | |||
when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))).thenReturn(true); | |||
when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ComponentDto.class))).thenReturn(true); | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}")); | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8)); | |||
ComponentDto createdProject = db.getDbClient().componentDao().selectByKey(db.getSession(), PROJECT_KEY).get(); | |||
verifyReportIsPersisted(TASK_UUID); | |||
@@ -185,9 +183,9 @@ public class ReportSubmitterIT { | |||
when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))).thenReturn(true); | |||
when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ComponentDto.class))).thenReturn(true); | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}")); | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8)); | |||
ComponentDto createdProject = db.getDbClient().componentDao().selectByKey(db.getSession(), PROJECT_KEY).get(); | |||
ProjectDto createdProject = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).get(); | |||
assertThat(db.favorites().hasFavorite(createdProject, user.getUuid())).isTrue(); | |||
} | |||
@@ -203,14 +201,14 @@ public class ReportSubmitterIT { | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}")); | |||
ComponentDto createdProject = db.getDbClient().componentDao().selectByKey(db.getSession(), PROJECT_KEY).get(); | |||
ProjectDto createdProject = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).get(); | |||
assertThat(db.favorites().hasNoFavorite(createdProject)).isTrue(); | |||
} | |||
@Test | |||
public void do_no_add_favorite_when_already_100_favorite_projects_and_no_project_creator_permission_on_permission_template() { | |||
UserDto user = db.users().insertUser(); | |||
rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getMainBranchComponent(), user.getUuid(), user.getLogin())); | |||
rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getProjectDto(), user.getUuid(), user.getLogin())); | |||
userSession | |||
.logIn(user) | |||
.addPermission(GlobalPermission.SCAN) | |||
@@ -219,9 +217,9 @@ public class ReportSubmitterIT { | |||
when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))).thenReturn(true); | |||
when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ComponentDto.class))).thenReturn(true); | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}")); | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8)); | |||
ComponentDto createdProject = db.getDbClient().componentDao().selectByKey(db.getSession(), PROJECT_KEY).get(); | |||
ProjectDto createdProject = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).get(); | |||
assertThat(db.favorites().hasNoFavorite(createdProject)).isTrue(); | |||
} | |||
@@ -234,7 +232,7 @@ public class ReportSubmitterIT { | |||
when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))) | |||
.thenReturn(true); | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}")); | |||
underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8)); | |||
verify(queue).submit(any(CeTaskSubmit.class)); | |||
} | |||
@@ -245,7 +243,7 @@ public class ReportSubmitterIT { | |||
userSession.addPermission(SCAN); | |||
mockSuccessfulPrepareSubmitCall(); | |||
underTest.submit(project.getKey(), project.name(), emptyMap(), IOUtils.toInputStream("{binary}")); | |||
underTest.submit(project.getKey(), project.name(), emptyMap(), IOUtils.toInputStream("{binary}", UTF_8)); | |||
verify(queue).submit(any(CeTaskSubmit.class)); | |||
} | |||
@@ -256,7 +254,7 @@ public class ReportSubmitterIT { | |||
userSession.addProjectPermission(SCAN.getKey(), project); | |||
mockSuccessfulPrepareSubmitCall(); | |||
underTest.submit(project.getKey(), project.name(), emptyMap(), IOUtils.toInputStream("{binary}")); | |||
underTest.submit(project.getKey(), project.name(), emptyMap(), IOUtils.toInputStream("{binary}", UTF_8)); | |||
verify(queue).submit(any(CeTaskSubmit.class)); | |||
} |
@@ -33,6 +33,7 @@ import org.sonar.db.DbTester; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.BranchType; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
@@ -234,7 +235,7 @@ public class ComponentUpdaterIT { | |||
when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ComponentDto.class))) | |||
.thenReturn(true); | |||
ComponentDto dto = underTest.create(db.getSession(), project, userDto.getUuid(), userDto.getLogin()).mainBranchComponent(); | |||
ProjectDto dto = underTest.create(db.getSession(), project, userDto.getUuid(), userDto.getLogin()).projectDto(); | |||
assertThat(db.favorites().hasFavorite(dto, userDto.getUuid())).isTrue(); | |||
} | |||
@@ -242,7 +243,7 @@ public class ComponentUpdaterIT { | |||
@Test | |||
public void do_not_add_project_to_user_favorites_if_project_creator_is_defined_in_permission_template_and_already_100_favorites() { | |||
UserDto user = db.users().insertUser(); | |||
rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getMainBranchComponent(), user.getUuid(), user.getLogin())); | |||
rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getProjectDto(), user.getUuid(), user.getLogin())); | |||
NewComponent project = NewComponent.newComponentBuilder() | |||
.setKey(DEFAULT_PROJECT_KEY) | |||
.setName(DEFAULT_PROJECT_NAME) | |||
@@ -250,34 +251,34 @@ public class ComponentUpdaterIT { | |||
when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(eq(db.getSession()), any(ComponentDto.class))) | |||
.thenReturn(true); | |||
ComponentDto dto = underTest.create(db.getSession(), | |||
ProjectDto dto = underTest.create(db.getSession(), | |||
project, | |||
user.getUuid(), | |||
user.getLogin()).mainBranchComponent(); | |||
user.getLogin()).projectDto(); | |||
assertThat(db.favorites().hasFavorite(dto, user.getUuid())).isFalse(); | |||
} | |||
@Test | |||
public void does_not_add_project_to_favorite_when_anonymously_created() { | |||
ComponentDto project = underTest.create(db.getSession(), | |||
ProjectDto project = underTest.create(db.getSession(), | |||
NewComponent.newComponentBuilder() | |||
.setKey(DEFAULT_PROJECT_KEY) | |||
.setName(DEFAULT_PROJECT_NAME) | |||
.build(), | |||
null, null).mainBranchComponent(); | |||
null, null).projectDto(); | |||
assertThat(db.favorites().hasNoFavorite(project)).isTrue(); | |||
} | |||
@Test | |||
public void does_not_add_project_to_favorite_when_project_has_no_permission_on_template() { | |||
ComponentDto project = underTest.create(db.getSession(), | |||
ProjectDto project = underTest.create(db.getSession(), | |||
NewComponent.newComponentBuilder() | |||
.setKey(DEFAULT_PROJECT_KEY) | |||
.setName(DEFAULT_PROJECT_NAME) | |||
.build(), | |||
null, null).mainBranchComponent(); | |||
null, null).projectDto(); | |||
assertThat(db.favorites().hasNoFavorite(project)).isTrue(); | |||
} |
@@ -26,6 +26,7 @@ import org.sonar.api.server.ws.WebService; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.metric.MetricDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.component.TestComponentFinder; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
@@ -219,7 +220,7 @@ public class AppActionIT { | |||
@Test | |||
public void component_is_favorite() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
userSession.logIn("john").addProjectPermission(USER, project); | |||
db.favorites().add(project, userSession.getUuid(), userSession.getLogin()); | |||
@@ -34,7 +34,9 @@ import org.sonar.core.util.stream.MoreCollectors; | |||
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.component.ResourceTypesRule; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.component.index.ComponentIndex; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.es.EsTester; | |||
@@ -68,8 +70,6 @@ import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; | |||
import static org.sonar.api.resources.Qualifiers.VIEW; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; | |||
import static org.sonar.db.component.ComponentTesting.newPublicProjectDto; | |||
import static org.sonar.server.component.ws.SuggestionsAction.PARAM_MORE; | |||
import static org.sonar.server.component.ws.SuggestionsAction.PARAM_QUERY; | |||
import static org.sonar.server.component.ws.SuggestionsAction.PARAM_RECENTLY_BROWSED; | |||
@@ -132,8 +132,8 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void test_example_json_response() { | |||
ComponentDto project1 = db.components().insertPublicProject(p -> p.setKey("org.sonarsource:sonarqube").setName("SonarSource :: SonarQube")).getMainBranchComponent(); | |||
ComponentDto project2 = db.components().insertPublicProject(p -> p.setKey("org.sonarsource:sonarlint").setName("SonarSource :: SonarLint")).getMainBranchComponent(); | |||
ProjectDto project1 = db.components().insertPublicProject(p -> p.setKey("org.sonarsource:sonarqube").setName("SonarSource :: SonarQube")).getProjectDto(); | |||
ProjectDto project2 = db.components().insertPublicProject(p -> p.setKey("org.sonarsource:sonarlint").setName("SonarSource :: SonarLint")).getProjectDto(); | |||
componentIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project1); | |||
authorizationIndexerTester.allowOnlyAnyone(project2); | |||
@@ -150,7 +150,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_contain_recently_browsed() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
userSessionRule.addProjectPermission(USER, project); | |||
@@ -175,7 +175,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_contain_recently_browsed_public_project() { | |||
ComponentDto project = db.components().insertPublicProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPublicProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
@@ -199,7 +199,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_not_contain_recently_browsed_without_permission() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
@@ -215,7 +215,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_contain_favorites() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
doReturn(singletonList(project)).when(favoriteFinder).list(); | |||
componentIndexer.indexAll(); | |||
@@ -240,7 +240,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_not_contain_favorites_without_permission() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
doReturn(singletonList(project)).when(favoriteFinder).list(); | |||
componentIndexer.indexAll(); | |||
@@ -256,7 +256,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_contain_recently_browsed_favorites() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
doReturn(singletonList(project)).when(favoriteFinder).list(); | |||
componentIndexer.indexAll(); | |||
@@ -282,7 +282,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_not_contain_matches_that_are_neither_favorites_nor_recently_browsed() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
userSessionRule.addProjectPermission(USER, project); | |||
@@ -300,10 +300,10 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_order_results() { | |||
ComponentDto project1 = db.components().insertPrivateProject(p -> p.setName("Alpha")).getMainBranchComponent(); | |||
ComponentDto project2 = db.components().insertPrivateProject(p -> p.setName("Bravo")).getMainBranchComponent(); | |||
ComponentDto project3 = db.components().insertPrivateProject(p -> p.setName("Charlie")).getMainBranchComponent(); | |||
ComponentDto project4 = db.components().insertPrivateProject(p -> p.setName("Delta")).getMainBranchComponent(); | |||
ProjectDto project1 = db.components().insertPrivateProject(p -> p.setName("Alpha")).getProjectDto(); | |||
ProjectDto project2 = db.components().insertPrivateProject(p -> p.setName("Bravo")).getProjectDto(); | |||
ProjectDto project3 = db.components().insertPrivateProject(p -> p.setName("Charlie")).getProjectDto(); | |||
ProjectDto project4 = db.components().insertPrivateProject(p -> p.setName("Delta")).getProjectDto(); | |||
doReturn(asList(project4, project2)).when(favoriteFinder).list(); | |||
componentIndexer.indexAll(); | |||
@@ -314,7 +314,7 @@ public class SuggestionsActionIT { | |||
SuggestionsWsResponse response = ws.newRequest() | |||
.setMethod("POST") | |||
.setParam(PARAM_RECENTLY_BROWSED, Stream.of(project3, project1).map(ComponentDto::getKey).collect(joining(","))) | |||
.setParam(PARAM_RECENTLY_BROWSED, Stream.of(project3, project1).map(ProjectDto::getKey).collect(joining(","))) | |||
.executeProtobuf(SuggestionsWsResponse.class); | |||
// assert order of keys | |||
@@ -330,13 +330,13 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_return_empty_qualifiers() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
componentIndexer.indexOnAnalysis(project.branchUuid()); | |||
userSessionRule.addProjectPermission(USER, project); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
componentIndexer.indexOnAnalysis(project.getMainBranchDto().getUuid()); | |||
userSessionRule.addProjectPermission(USER, project.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
.setMethod("POST") | |||
.setParam(PARAM_RECENTLY_BROWSED, project.getKey()) | |||
.setParam(PARAM_RECENTLY_BROWSED, project.getProjectDto().getKey()) | |||
.executeProtobuf(SuggestionsWsResponse.class); | |||
assertThat(response.getResultsList()) | |||
@@ -348,13 +348,13 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_should_filter_allowed_qualifiers() { | |||
resourceTypes.setAllQualifiers(PROJECT, FILE, UNIT_TEST_FILE); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
componentIndexer.indexOnAnalysis(project.branchUuid()); | |||
userSessionRule.addProjectPermission(USER, project); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
componentIndexer.indexOnAnalysis(project.getMainBranchDto().getUuid()); | |||
userSessionRule.addProjectPermission(USER, project.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
.setMethod("POST") | |||
.setParam(PARAM_RECENTLY_BROWSED, project.getKey()) | |||
.setParam(PARAM_RECENTLY_BROWSED, project.getProjectDto().getKey()) | |||
.executeProtobuf(SuggestionsWsResponse.class); | |||
assertThat(response.getResultsList()) | |||
@@ -364,7 +364,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void exact_match_in_one_qualifier() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
@@ -389,12 +389,12 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void should_not_return_suggestion_on_non_existing_project() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
db.getDbClient().purgeDao().deleteProject(db.getSession(), project.uuid(), PROJECT, project.name(), project.getKey()); | |||
db.getDbClient().purgeDao().deleteProject(db.getSession(), project.getUuid(), PROJECT, project.getName(), project.getKey()); | |||
db.commit(); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -410,7 +410,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void must_not_search_if_no_valid_tokens_are_provided() { | |||
ComponentDto project = db.components().insertPrivateProject(p -> p.setName("SonarQube")).getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject(p -> p.setName("SonarQube")).getProjectDto(); | |||
componentIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
@@ -436,7 +436,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void should_warn_about_short_inputs_but_return_results_based_on_other_terms() { | |||
ComponentDto project = db.components().insertPrivateProject(p -> p.setName("SonarQube")).getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject(p -> p.setName("SonarQube")).getProjectDto(); | |||
componentIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
@@ -455,9 +455,9 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void should_contain_component_names() { | |||
ComponentDto project1 = db.components().insertPrivateProject(p -> p.setName("Project1")).getMainBranchComponent(); | |||
componentIndexer.indexOnAnalysis(project1.branchUuid()); | |||
authorizationIndexerTester.allowOnlyAnyone(project1); | |||
ProjectData project1 = db.components().insertPrivateProject(p -> p.setName("Project1")); | |||
componentIndexer.indexOnAnalysis(project1.getMainBranchDto().getUuid()); | |||
authorizationIndexerTester.allowOnlyAnyone(project1.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
.setMethod("POST") | |||
@@ -467,7 +467,7 @@ public class SuggestionsActionIT { | |||
assertThat(response.getResultsList()) | |||
.flatExtracting(Category::getItemsList) | |||
.extracting(Suggestion::getKey, Suggestion::getName) | |||
.containsExactlyInAnyOrder(tuple(project1.getKey(), project1.name())); | |||
.containsExactlyInAnyOrder(tuple(project1.getProjectDto().getKey(), project1.getProjectDto().getName())); | |||
} | |||
@Test | |||
@@ -492,13 +492,13 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void should_mark_favorite_items() { | |||
ComponentDto favouriteProject = db.components().insertPrivateProject(p -> p.setName("Project1")).getMainBranchComponent(); | |||
ComponentDto nonFavouriteProject = db.components().insertPublicProject(p -> p.setName("Project2")).getMainBranchComponent(); | |||
ProjectData favouriteProject = db.components().insertPrivateProject(p -> p.setName("Project1")); | |||
ProjectData nonFavouriteProject = db.components().insertPublicProject(p -> p.setName("Project2")); | |||
doReturn(singletonList(favouriteProject)).when(favoriteFinder).list(); | |||
componentIndexer.indexOnAnalysis(favouriteProject.branchUuid()); | |||
componentIndexer.indexOnAnalysis(nonFavouriteProject.branchUuid()); | |||
authorizationIndexerTester.allowOnlyAnyone(favouriteProject, nonFavouriteProject); | |||
doReturn(singletonList(favouriteProject.getProjectDto())).when(favoriteFinder).list(); | |||
componentIndexer.indexOnAnalysis(favouriteProject.getMainBranchDto().getUuid()); | |||
componentIndexer.indexOnAnalysis(nonFavouriteProject.getMainBranchDto().getUuid()); | |||
authorizationIndexerTester.allowOnlyAnyone(favouriteProject.getProjectDto(), nonFavouriteProject.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
.setMethod("POST") | |||
@@ -508,7 +508,7 @@ public class SuggestionsActionIT { | |||
assertThat(response.getResultsList()) | |||
.flatExtracting(Category::getItemsList) | |||
.extracting(Suggestion::getKey, Suggestion::getIsFavorite) | |||
.containsExactly(tuple(favouriteProject.getKey(), true), tuple(nonFavouriteProject.getKey(), false)); | |||
.containsExactly(tuple(favouriteProject.getProjectDto().getKey(), true), tuple(nonFavouriteProject.getProjectDto().getKey(), false)); | |||
} | |||
@Test | |||
@@ -553,7 +553,6 @@ public class SuggestionsActionIT { | |||
.containsExactlyInAnyOrder( | |||
tuple(SuggestionCategory.APP.getName(), false), | |||
tuple(SuggestionCategory.VIEW.getName(), false), | |||
tuple(SuggestionCategory.SUBVIEW.getName(), false), | |||
tuple(SuggestionCategory.PROJECT.getName(), false)); | |||
} | |||
@@ -677,8 +676,8 @@ public class SuggestionsActionIT { | |||
boolean useQuery) { | |||
String namePrefix = "MyProject"; | |||
List<ComponentDto> projects = range(0, numberOfProjects) | |||
.mapToObj(i -> db.components().insertPublicProject(p -> p.setName(namePrefix + i)).getMainBranchComponent()) | |||
List<ProjectDto> projects = range(0, numberOfProjects) | |||
.mapToObj(i -> db.components().insertPublicProject(p -> p.setName(namePrefix + i)).getProjectDto()) | |||
.collect(Collectors.toList()); | |||
componentIndexer.indexAll(); |
@@ -29,6 +29,7 @@ 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.project.ProjectDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonar.db.property.PropertyQuery; | |||
import org.sonar.db.user.UserDto; | |||
@@ -67,7 +68,7 @@ public class AddActionIT { | |||
@Test | |||
public void add_a_project() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
UserDto user = db.users().insertUser(); | |||
userSession.logIn(user).addProjectPermission(USER, project); | |||
@@ -82,7 +83,7 @@ public class AddActionIT { | |||
PropertyDto favorite = favorites.get(0); | |||
assertThat(favorite) | |||
.extracting(PropertyDto::getComponentUuid, PropertyDto::getUserUuid, PropertyDto::getKey) | |||
.containsOnly(project.uuid(), user.getUuid(), "favourite"); | |||
.containsOnly(project.getUuid(), user.getUuid(), "favourite"); | |||
} | |||
@Test | |||
@@ -104,24 +105,12 @@ public class AddActionIT { | |||
@Test | |||
public void fail_when_user_is_not_authenticated() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
assertThatThrownBy(() -> call(project.getKey())) | |||
.isInstanceOf(UnauthorizedException.class); | |||
} | |||
@Test | |||
public void fail_on_directory() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto directory = db.components().insertComponent(newDirectory(project, "dir")); | |||
UserDto user = db.users().insertUser(); | |||
userSession.logIn(user).addProjectPermission(USER, project); | |||
assertThatThrownBy(() -> call(directory.getKey())) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
.hasMessage("Only components with qualifiers TRK, VW, SVW, APP are supported"); | |||
} | |||
@Test | |||
public void fail_on_file() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
@@ -130,20 +119,8 @@ public class AddActionIT { | |||
userSession.logIn(user).addProjectPermission(USER, project); | |||
assertThatThrownBy(() -> call(file.getKey())) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
.hasMessage("Only components with qualifiers TRK, VW, SVW, APP are supported"); | |||
} | |||
@Test | |||
public void fail_on_unit_test_file() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto unitTestFile = db.components().insertComponent(newFileDto(project).setQualifier(UNIT_TEST_FILE)); | |||
UserDto user = db.users().insertUser(); | |||
userSession.logIn(user).addProjectPermission(USER, project); | |||
assertThatThrownBy(() -> call(unitTestFile.getKey())) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
.hasMessage("Only components with qualifiers TRK, VW, SVW, APP are supported"); | |||
.isInstanceOf(NotFoundException.class) | |||
.hasMessage("Entity with key '" + file.getKey() + "' not found"); | |||
} | |||
@Test |
@@ -26,7 +26,7 @@ import org.junit.Test; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.component.TestComponentFinder; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
@@ -37,13 +37,10 @@ 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.net.HttpURLConnection.HTTP_NO_CONTENT; | |||
import static java.util.Optional.ofNullable; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; | |||
import static org.sonar.server.favorite.ws.FavoritesWsParameters.PARAM_COMPONENT; | |||
public class RemoveActionIT { | |||
@@ -67,25 +64,22 @@ public class RemoveActionIT { | |||
@Test | |||
public void remove_a_favorite_project() { | |||
ComponentDto project = insertProjectAndPermissions(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
ProjectDto project = insertProjectAndPermissions(); | |||
db.favorites().add(project, user.getUuid(), user.getLogin()); | |||
db.favorites().add(file, user.getUuid(), user.getLogin()); | |||
TestResponse result = call(PROJECT_KEY); | |||
assertThat(result.getStatus()).isEqualTo(HTTP_NO_CONTENT); | |||
assertThat(db.favorites().hasFavorite(project, user.getUuid())).isFalse(); | |||
assertThat(db.favorites().hasFavorite(file, user.getUuid())).isTrue(); | |||
} | |||
@Test | |||
public void fail_if_not_already_a_favorite() { | |||
ComponentDto componentDto = insertProjectAndPermissions(); | |||
ProjectDto componentDto = insertProjectAndPermissions(); | |||
assertThatThrownBy(() -> call(PROJECT_KEY)) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
.hasMessage("Component '" + PROJECT_KEY + "' (uuid: "+componentDto.uuid()+") is not a favorite"); | |||
.hasMessage("Component '" + PROJECT_KEY + "' (uuid: " + componentDto.getUuid() + ") is not a favorite"); | |||
} | |||
@Test | |||
@@ -115,11 +109,11 @@ public class RemoveActionIT { | |||
assertThat(param.isRequired()).isTrue(); | |||
} | |||
private ComponentDto insertProject() { | |||
return db.components().insertPrivateProject(PROJECT_UUID, c -> c.setKey(PROJECT_KEY)).getMainBranchComponent(); | |||
private ProjectDto insertProject() { | |||
return db.components().insertPrivateProject(PROJECT_UUID, c -> c.setKey(PROJECT_KEY)).getProjectDto(); | |||
} | |||
private ComponentDto insertProjectAndPermissions() { | |||
private ProjectDto insertProjectAndPermissions() { | |||
userSession.logIn(user); | |||
return insertProject(); |
@@ -31,6 +31,7 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.sonar.server.favorite.FavoriteFinder; | |||
@@ -76,21 +77,18 @@ public class SearchActionIT { | |||
@Test | |||
public void return_favorites() { | |||
ComponentDto project = newPrivateProjectDto("P1").setKey("K1").setName("N1"); | |||
addComponent(project); | |||
addComponent(newFileDto(project).setKey("K11").setName("N11")); | |||
addComponent(newPrivateProjectDto("P2").setKey("K2").setName("N2")); | |||
addPermissionAndFavorite(db.components().insertPrivateProject("P1", c -> c.setKey("K1").setName("N1")).getProjectDto()); | |||
addPermissionAndFavorite(db.components().insertPrivateProject("P2", c -> c.setKey("K2").setName("N2")).getProjectDto()); | |||
SearchResponse result = call(); | |||
assertThat(result.getPaging()) | |||
.extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal) | |||
.containsExactly(1, 100, 3); | |||
.containsExactly(1, 100, 2); | |||
assertThat(result.getFavoritesList()) | |||
.extracting(Favorite::getKey, Favorite::getName, Favorite::getQualifier) | |||
.containsOnly( | |||
tuple("K1", "N1", PROJECT), | |||
tuple("K11", "N11", FILE), | |||
tuple("K2", "N2", PROJECT)); | |||
} | |||
@@ -104,8 +102,8 @@ public class SearchActionIT { | |||
@Test | |||
public void filter_authorized_components() { | |||
addComponent(ComponentTesting.newPrivateProjectDto().setKey("K1")); | |||
ComponentDto unauthorizedProject = db.components().insertComponent(ComponentTesting.newPrivateProjectDto()); | |||
addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setKey("K1")).getProjectDto()); | |||
ProjectDto unauthorizedProject = db.components().insertPrivateProject().getProjectDto(); | |||
db.favorites().add(unauthorizedProject, userUuid, userLogin); | |||
SearchResponse result = call(); | |||
@@ -117,8 +115,8 @@ public class SearchActionIT { | |||
@Test | |||
public void paginate_results() { | |||
IntStream.rangeClosed(1, 9) | |||
.forEach(i -> addComponent(ComponentTesting.newPrivateProjectDto().setKey("K" + i).setName("N" + i))); | |||
ComponentDto unauthorizedProject = db.components().insertComponent(ComponentTesting.newPrivateProjectDto()); | |||
.forEach(i -> addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setKey("K" + i).setName("N" + i)).getProjectDto())); | |||
ProjectDto unauthorizedProject = db.components().insertPrivateProject().getProjectDto(); | |||
db.favorites().add(unauthorizedProject, userUuid, userLogin); | |||
SearchResponse result = call(2, 3); | |||
@@ -127,14 +125,12 @@ public class SearchActionIT { | |||
assertThat(result.getFavoritesList()) | |||
.extracting(Favorite::getKey) | |||
.containsExactly("K4", "K5", "K6"); | |||
} | |||
@Test | |||
public void return_only_users_favorite() { | |||
addComponent(ComponentTesting.newPrivateProjectDto().setKey("K1")); | |||
ComponentDto otherUserFavorite = ComponentTesting.newPrivateProjectDto().setKey("K42"); | |||
db.components().insertComponent(otherUserFavorite); | |||
addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setKey("K1")).getProjectDto()); | |||
ProjectDto otherUserFavorite = db.components().insertPrivateProject(c -> c.setKey("K42")).getProjectDto(); | |||
db.favorites().add(otherUserFavorite, "42", userLogin); | |||
db.commit(); | |||
@@ -145,9 +141,9 @@ public class SearchActionIT { | |||
@Test | |||
public void favorites_ordered_by_name() { | |||
addComponent(ComponentTesting.newPrivateProjectDto().setName("N2")); | |||
addComponent(ComponentTesting.newPrivateProjectDto().setName("N3")); | |||
addComponent(ComponentTesting.newPrivateProjectDto().setName("N1")); | |||
addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setName("N2")).getProjectDto()); | |||
addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setName("N3")).getProjectDto()); | |||
addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setName("N1")).getProjectDto()); | |||
SearchResponse result = call(); | |||
@@ -157,9 +153,9 @@ public class SearchActionIT { | |||
@Test | |||
public void json_example() { | |||
addComponent(ComponentTesting.newPrivateProjectDto().setKey("K1").setName("Samba")); | |||
addComponent(ComponentTesting.newPrivateProjectDto().setKey("K2").setName("Apache HBase")); | |||
addComponent(ComponentTesting.newPrivateProjectDto().setKey("K3").setName("JDK9")); | |||
addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setKey("K1").setName("Samba")).getProjectDto()); | |||
addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setKey("K2").setName("Apache HBase")).getProjectDto()); | |||
addPermissionAndFavorite(db.components().insertPrivateProject(c -> c.setKey("K3").setName("JDK9")).getProjectDto()); | |||
String result = ws.newRequest().execute().getInput(); | |||
@@ -183,8 +179,7 @@ public class SearchActionIT { | |||
.isInstanceOf(UnauthorizedException.class); | |||
} | |||
private void addComponent(ComponentDto component) { | |||
db.components().insertComponent(component); | |||
private void addPermissionAndFavorite(ProjectDto component) { | |||
db.favorites().add(component, userUuid, userLogin); | |||
db.commit(); | |||
userSession.addProjectPermission(UserRole.USER, component); |
@@ -31,6 +31,7 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
@@ -199,7 +200,7 @@ public class CreateActionIT { | |||
.setParam("name", DEFAULT_PROJECT_NAME) | |||
.executeProtobuf(CreateWsResponse.class); | |||
ComponentDto project = db.getDbClient().componentDao().selectByKey(db.getSession(), DEFAULT_PROJECT_KEY).get(); | |||
ProjectDto project = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), DEFAULT_PROJECT_KEY).get(); | |||
assertThat(db.favorites().hasFavorite(project, user.getUuid())).isTrue(); | |||
} | |||
@@ -207,7 +208,7 @@ public class CreateActionIT { | |||
public void do_not_add_project_to_user_favorites_if_project_creator_is_defined_in_permission_template_and_already_100_favorites() { | |||
UserDto user = db.users().insertUser(); | |||
when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ComponentDto.class))).thenReturn(true); | |||
rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getMainBranchComponent(), user.getUuid(), user.getLogin())); | |||
rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getProjectDto(), user.getUuid(), user.getLogin())); | |||
userSession.logIn(user).addPermission(PROVISION_PROJECTS); | |||
ws.newRequest() | |||
@@ -215,7 +216,7 @@ public class CreateActionIT { | |||
.setParam("name", DEFAULT_PROJECT_NAME) | |||
.executeProtobuf(CreateWsResponse.class); | |||
ComponentDto project = db.getDbClient().componentDao().selectByKey(db.getSession(), DEFAULT_PROJECT_KEY).get(); | |||
ProjectDto project = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), DEFAULT_PROJECT_KEY).get(); | |||
assertThat(db.favorites().hasNoFavorite(project)).isTrue(); | |||
} | |||
@@ -21,6 +21,7 @@ package org.sonar.server.setting.ws; | |||
import java.util.Random; | |||
import javax.annotation.Nullable; | |||
import javax.sound.sampled.Port; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
@@ -34,6 +35,9 @@ 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.entity.EntityDto; | |||
import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.property.PropertyDbTester; | |||
import org.sonar.db.property.PropertyQuery; | |||
import org.sonar.db.user.UserDto; | |||
@@ -79,13 +83,13 @@ public class ResetActionIT { | |||
private final PropertyDefinitions definitions = new PropertyDefinitions(System2.INSTANCE); | |||
private final SettingsUpdater settingsUpdater = new SettingsUpdater(dbClient, definitions); | |||
private final SettingValidations settingValidations = new SettingValidations(definitions, dbClient, i18n); | |||
private ComponentDto project; | |||
private ProjectDto project; | |||
private final ResetAction underTest = new ResetAction(dbClient, componentFinder, settingsUpdater, userSession, definitions, settingValidations); | |||
private final WsActionTester ws = new WsActionTester(underTest); | |||
@Before | |||
public void setUp() { | |||
project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
project = db.components().insertPrivateProject().getProjectDto(); | |||
} | |||
@Test | |||
@@ -141,7 +145,7 @@ public class ResetActionIT { | |||
logInAsSystemAdministrator(); | |||
propertyDb.insertProperties(null, null, null, null, | |||
newGlobalPropertyDto().setKey("foo").setValue("one")); | |||
propertyDb.insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
propertyDb.insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("value")); | |||
executeRequestOnGlobalSetting("foo"); | |||
@@ -154,7 +158,7 @@ public class ResetActionIT { | |||
public void ignore_global_setting_when_removing_project_setting() { | |||
logInAsProjectAdmin(); | |||
propertyDb.insertProperties(null, null, null, null, newGlobalPropertyDto().setKey("foo").setValue("one")); | |||
propertyDb.insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
propertyDb.insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("value")); | |||
executeRequestOnProjectSetting("foo"); | |||
@@ -200,26 +204,6 @@ public class ResetActionIT { | |||
assertGlobalPropertyDoesNotExist("foo"); | |||
} | |||
@Test | |||
public void remove_setting_on_branch() { | |||
ComponentDto project = db.components().insertPublicProject().getMainBranchComponent(); | |||
String branchName = randomAlphanumeric(248); | |||
ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey(branchName)); | |||
definitions.addComponent(PropertyDefinition.builder("foo").onQualifiers(PROJECT).build()); | |||
propertyDb.insertProperties(null, branch.name(), null, null, newComponentPropertyDto(branch).setKey("foo").setValue("value")); | |||
userSession.logIn().addProjectPermission(ADMIN, project); | |||
userSession.addProjectBranchMapping(project.uuid(), branch); | |||
ws.newRequest() | |||
.setMediaType(MediaTypes.PROTOBUF) | |||
.setParam("keys", "foo") | |||
.setParam("component", branch.getKey()) | |||
.setParam("branch", branchName) | |||
.execute(); | |||
assertProjectPropertyDoesNotExist(branch, "foo"); | |||
} | |||
@Test | |||
public void empty_204_response() { | |||
logInAsSystemAdministrator(); | |||
@@ -256,9 +240,7 @@ public class ResetActionIT { | |||
userSession.logIn().addProjectPermission(USER, project); | |||
definitions.addComponent(PropertyDefinition.builder("foo").build()); | |||
assertThatThrownBy(() -> { | |||
executeRequestOnComponentSetting("foo", project); | |||
}) | |||
assertThatThrownBy(() -> executeRequestOnComponentSetting("foo", project)) | |||
.isInstanceOf(ForbiddenException.class) | |||
.hasMessage("Insufficient privileges"); | |||
} | |||
@@ -268,9 +250,7 @@ public class ResetActionIT { | |||
logInAsSystemAdministrator(); | |||
definitions.addComponent(PropertyDefinition.builder("foo").build()); | |||
assertThatThrownBy(() -> { | |||
executeRequestOnComponentSetting("foo", project); | |||
}) | |||
assertThatThrownBy(() -> executeRequestOnComponentSetting("foo", project)) | |||
.isInstanceOf(ForbiddenException.class) | |||
.hasMessage("Insufficient privileges"); | |||
} | |||
@@ -282,9 +262,7 @@ public class ResetActionIT { | |||
.onlyOnQualifiers(VIEW) | |||
.build()); | |||
assertThatThrownBy(() -> { | |||
executeRequestOnGlobalSetting("foo"); | |||
}) | |||
assertThatThrownBy(() -> executeRequestOnGlobalSetting("foo")) | |||
.isInstanceOf(BadRequestException.class) | |||
.hasMessage("Setting 'foo' cannot be global"); | |||
} | |||
@@ -297,9 +275,7 @@ public class ResetActionIT { | |||
.build()); | |||
i18n.put("qualifier." + PROJECT, "project"); | |||
assertThatThrownBy(() -> { | |||
executeRequestOnComponentSetting("foo", project); | |||
}) | |||
assertThatThrownBy(() -> executeRequestOnComponentSetting("foo", project)) | |||
.isInstanceOf(BadRequestException.class) | |||
.hasMessage("Setting 'foo' cannot be set on a project"); | |||
} | |||
@@ -311,115 +287,55 @@ public class ResetActionIT { | |||
definitions.addComponent(PropertyDefinition.builder("foo").build()); | |||
i18n.put("qualifier." + PROJECT, "project"); | |||
assertThatThrownBy(() -> { | |||
executeRequestOnComponentSetting("foo", project); | |||
}) | |||
assertThatThrownBy(() -> executeRequestOnComponentSetting("foo", project)) | |||
.isInstanceOf(BadRequestException.class) | |||
.hasMessage("Setting 'foo' cannot be set on a project"); | |||
} | |||
@Test | |||
public void succeed_for_property_without_definition_when_set_on_project_component() { | |||
ComponentDto project = randomPublicOrPrivateProject(); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(project, project); | |||
} | |||
@Test | |||
public void fail_for_property_without_definition_when_set_on_directory_component() { | |||
ComponentDto project = randomPublicOrPrivateProject(); | |||
ComponentDto directory = db.components().insertComponent(ComponentTesting.newDirectory(project, "A/B")); | |||
failForPropertyWithoutDefinitionOnUnsupportedComponent(project, directory); | |||
} | |||
@Test | |||
public void fail_for_property_without_definition_when_set_on_file_component() { | |||
ComponentDto project = randomPublicOrPrivateProject(); | |||
ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); | |||
failForPropertyWithoutDefinitionOnUnsupportedComponent(project, file); | |||
ProjectDto project = randomPublicOrPrivateProject(); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(project); | |||
} | |||
@Test | |||
public void succeed_for_property_without_definition_when_set_on_view_component() { | |||
ComponentDto view = db.components().insertPublicPortfolio(); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(view, view); | |||
} | |||
@Test | |||
public void succeed_for_property_without_definition_when_set_on_subview_component() { | |||
ComponentDto view = db.components().insertPublicPortfolio(); | |||
ComponentDto subview = db.components().insertComponent(ComponentTesting.newSubPortfolio(view)); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(view, subview); | |||
} | |||
@Test | |||
public void fail_for_property_without_definition_when_set_on_projectCopy_component() { | |||
ComponentDto view = db.components().insertPublicPortfolio(); | |||
ComponentDto projectCopy = db.components().insertComponent(ComponentTesting.newProjectCopy("a", db.components().insertPrivateProject().getMainBranchComponent(), view)); | |||
failForPropertyWithoutDefinitionOnUnsupportedComponent(view, projectCopy); | |||
PortfolioDto view = db.components().insertPublicPortfolioDto(); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(view); | |||
} | |||
@Test | |||
public void fail_when_component_not_found() { | |||
assertThatThrownBy(() -> { | |||
ws.newRequest() | |||
assertThatThrownBy(() -> ws.newRequest() | |||
.setParam("keys", "foo") | |||
.setParam("component", "unknown") | |||
.execute(); | |||
}) | |||
.execute()) | |||
.isInstanceOf(NotFoundException.class) | |||
.hasMessage("Component key 'unknown' not found"); | |||
} | |||
@Test | |||
public void fail_when_branch_not_found() { | |||
ComponentDto project = db.components().insertPublicProject().getMainBranchComponent(); | |||
logInAsProjectAdmin(project); | |||
ComponentDto branch = db.components().insertProjectBranch(project); | |||
String settingKey = "not_allowed_on_branch"; | |||
assertThatThrownBy(() -> { | |||
ws.newRequest() | |||
.setParam("keys", settingKey) | |||
.setParam("component", branch.getKey()) | |||
.setParam("branch", "unknown") | |||
.execute(); | |||
}) | |||
.isInstanceOf(NotFoundException.class) | |||
.hasMessage(format("Component '%s' on branch 'unknown' not found", branch.getKey())); | |||
} | |||
@Test | |||
public void fail_when_setting_key_is_defined_in_sonar_properties() { | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
logInAsProjectAdmin(project); | |||
String settingKey = ProcessProperties.Property.JDBC_URL.getKey(); | |||
assertThatThrownBy(() -> { | |||
ws.newRequest() | |||
assertThatThrownBy(() -> ws.newRequest() | |||
.setParam("keys", settingKey) | |||
.setParam("component", project.getKey()) | |||
.execute(); | |||
}) | |||
.execute()) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
.hasMessage(format("Setting '%s' can only be used in sonar.properties", settingKey)); | |||
} | |||
private void succeedForPropertyWithoutDefinitionAndValidComponent(ComponentDto root, ComponentDto module) { | |||
logInAsProjectAdmin(root); | |||
executeRequestOnComponentSetting("foo", module); | |||
private void succeedForPropertyWithoutDefinitionAndValidComponent(ProjectDto project) { | |||
logInAsProjectAdmin(project); | |||
executeRequestOnComponentSetting("foo", project); | |||
} | |||
private void failForPropertyWithoutDefinitionOnUnsupportedComponent(ComponentDto root, ComponentDto component) { | |||
i18n.put("qualifier." + component.qualifier(), "QualifierLabel"); | |||
logInAsProjectAdmin(root); | |||
assertThatThrownBy(() -> { | |||
executeRequestOnComponentSetting("foo", component); | |||
}) | |||
.isInstanceOf(BadRequestException.class) | |||
.hasMessage("Setting 'foo' cannot be set on a QualifierLabel"); | |||
private void succeedForPropertyWithoutDefinitionAndValidComponent(PortfolioDto project) { | |||
logInAsProjectAdmin(project); | |||
executeRequestOnComponentSetting("foo", project); | |||
} | |||
private void executeRequestOnGlobalSetting(String key) { | |||
@@ -430,8 +346,8 @@ public class ResetActionIT { | |||
executeRequest(key, project.getKey()); | |||
} | |||
private void executeRequestOnComponentSetting(String key, ComponentDto componentDto) { | |||
executeRequest(key, componentDto.getKey()); | |||
private void executeRequestOnComponentSetting(String key, EntityDto entity) { | |||
executeRequest(key, entity.getKey()); | |||
} | |||
private void executeRequest(String key, @Nullable String componentKey) { | |||
@@ -452,10 +368,14 @@ public class ResetActionIT { | |||
userSession.logIn().addProjectPermission(ADMIN, project); | |||
} | |||
private void logInAsProjectAdmin(ComponentDto root) { | |||
private void logInAsProjectAdmin(ProjectDto root) { | |||
userSession.logIn().addProjectPermission(ADMIN, root); | |||
} | |||
private void logInAsProjectAdmin(PortfolioDto root) { | |||
userSession.logIn().addPortfolioPermission(ADMIN, root); | |||
} | |||
private void assertGlobalPropertyDoesNotExist(String key) { | |||
assertThat(dbClient.propertiesDao().selectGlobalProperty(dbSession, key)).isNull(); | |||
} | |||
@@ -464,8 +384,8 @@ public class ResetActionIT { | |||
assertThat(dbClient.propertiesDao().selectGlobalProperty(dbSession, key)).isNotNull(); | |||
} | |||
private void assertProjectPropertyDoesNotExist(ComponentDto component, String key) { | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentUuid(component.uuid()).setKey(key).build(), dbSession)).isEmpty(); | |||
private void assertProjectPropertyDoesNotExist(EntityDto entity, String key) { | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentUuid(entity.getUuid()).setKey(key).build(), dbSession)).isEmpty(); | |||
} | |||
private void assertProjectPropertyDoesNotExist(String key) { | |||
@@ -473,7 +393,7 @@ public class ResetActionIT { | |||
} | |||
private void assertProjectPropertyExists(String key) { | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentUuid(project.uuid()).setKey(key).build(), dbSession)).isNotEmpty(); | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentUuid(project.getUuid()).setKey(key).build(), dbSession)).isNotEmpty(); | |||
} | |||
private void assertUserPropertyExists(String key, UserDto user) { | |||
@@ -484,8 +404,8 @@ public class ResetActionIT { | |||
dbSession)).isNotEmpty(); | |||
} | |||
private ComponentDto randomPublicOrPrivateProject() { | |||
return new Random().nextBoolean() ? db.components().insertPrivateProject().getMainBranchComponent() : db.components().insertPublicProject().getMainBranchComponent(); | |||
private ProjectDto randomPublicOrPrivateProject() { | |||
return new Random().nextBoolean() ? db.components().insertPrivateProject().getProjectDto() : db.components().insertPublicProject().getProjectDto(); | |||
} | |||
} |
@@ -836,7 +836,7 @@ public class SetActionIT { | |||
@Test | |||
public void succeed_for_property_without_definition_when_set_on_project_component() { | |||
ComponentDto project = randomPublicOrPrivateProject(); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(project, project); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(project); | |||
} | |||
@Test | |||
@@ -856,14 +856,14 @@ public class SetActionIT { | |||
@Test | |||
public void succeed_for_property_without_definition_when_set_on_view_component() { | |||
ComponentDto view = db.components().insertPrivatePortfolio(); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(view, view); | |||
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)); | |||
succeedForPropertyWithoutDefinitionAndValidComponent(view, subview); | |||
failForPropertyWithoutDefinitionOnUnsupportedComponent(view, subview); | |||
} | |||
@Test | |||
@@ -874,12 +874,12 @@ public class SetActionIT { | |||
failForPropertyWithoutDefinitionOnUnsupportedComponent(view, projectCopy); | |||
} | |||
private void succeedForPropertyWithoutDefinitionAndValidComponent(ComponentDto project, ComponentDto module) { | |||
private void succeedForPropertyWithoutDefinitionAndValidComponent(ComponentDto project) { | |||
logInAsProjectAdministrator(project); | |||
callForProjectSettingByKey("my.key", "My Value", module.getKey()); | |||
callForProjectSettingByKey("my.key", "My Value", project.getKey()); | |||
assertComponentSetting("my.key", "My Value", module.uuid()); | |||
assertComponentSetting("my.key", "My Value", project.uuid()); | |||
} | |||
private void failForPropertyWithoutDefinitionOnUnsupportedComponent(ComponentDto root, ComponentDto component) { |
@@ -33,6 +33,7 @@ import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.property.PropertyDbTester; | |||
import org.sonar.db.property.PropertyQuery; | |||
import org.sonar.db.user.UserDto; | |||
@@ -58,19 +59,19 @@ public class SettingsUpdaterIT { | |||
ComponentDbTester componentDb = new ComponentDbTester(db); | |||
PropertyDefinitions definitions = new PropertyDefinitions(System2.INSTANCE); | |||
ComponentDto project; | |||
ProjectDto project; | |||
SettingsUpdater underTest = new SettingsUpdater(dbClient, definitions); | |||
@Before | |||
public void setUp() { | |||
project = componentDb.insertComponent(ComponentTesting.newPrivateProjectDto()); | |||
project = componentDb.insertPrivateProject().getProjectDto(); | |||
} | |||
@Test | |||
public void delete_global_settings() { | |||
definitions.addComponent(PropertyDefinition.builder("foo").build()); | |||
propertyDb.insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
propertyDb.insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("value")); | |||
propertyDb.insertProperties(null, null, null, null, newGlobalPropertyDto().setKey("foo").setValue("one")); | |||
propertyDb.insertProperties(null, null, null, null, newGlobalPropertyDto().setKey("bar").setValue("two")); | |||
@@ -86,9 +87,9 @@ public class SettingsUpdaterIT { | |||
public void delete_component_settings() { | |||
definitions.addComponent(PropertyDefinition.builder("foo").build()); | |||
propertyDb.insertProperties(null, null, null, null, newGlobalPropertyDto().setKey("foo").setValue("value")); | |||
propertyDb.insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
propertyDb.insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("one")); | |||
propertyDb.insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
propertyDb.insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("bar").setValue("two")); | |||
underTest.deleteComponentSettings(dbSession, project, "foo", "bar"); | |||
@@ -150,7 +151,7 @@ public class SettingsUpdaterIT { | |||
PropertyFieldDefinition.build("key").name("Key").build(), | |||
PropertyFieldDefinition.build("size").name("Size").build())) | |||
.build()); | |||
propertyDb.insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
propertyDb.insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("1,2"), | |||
newComponentPropertyDto(project).setKey("foo.1.key").setValue("key1"), | |||
newComponentPropertyDto(project).setKey("foo.1.size").setValue("size1"), | |||
@@ -173,7 +174,7 @@ public class SettingsUpdaterIT { | |||
PropertyFieldDefinition.build("key").name("Key").build(), | |||
PropertyFieldDefinition.build("size").name("Size").build())) | |||
.build()); | |||
propertyDb.insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
propertyDb.insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("other").setValue("1,2"), | |||
newComponentPropertyDto(project).setKey("other.1.key").setValue("key1")); | |||
@@ -209,11 +210,11 @@ public class SettingsUpdaterIT { | |||
} | |||
private void assertProjectPropertyDoesNotExist(String key) { | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentUuid(project.uuid()).setKey(key).build(), dbSession)).isEmpty(); | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentUuid(project.getUuid()).setKey(key).build(), dbSession)).isEmpty(); | |||
} | |||
private void assertProjectPropertyExists(String key) { | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentUuid(project.uuid()).setKey(key).build(), dbSession)).isNotEmpty(); | |||
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentUuid(project.getUuid()).setKey(key).build(), dbSession)).isNotEmpty(); | |||
} | |||
private void assertUserPropertyExists(String key, UserDto user) { |
@@ -38,7 +38,10 @@ import org.sonar.api.web.UserRole; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ProjectData; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.process.ProcessProperties; | |||
import org.sonar.server.component.TestComponentFinder; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
@@ -80,11 +83,14 @@ public class ValuesActionIT { | |||
private final PropertyDefinitions definitions = new PropertyDefinitions(System2.INSTANCE); | |||
private final SettingsWsSupport support = new SettingsWsSupport(userSession); | |||
private final WsActionTester wsActionTester = new WsActionTester(new ValuesAction(dbClient, TestComponentFinder.from(db), userSession, definitions, support)); | |||
private ComponentDto project; | |||
private ProjectDto project; | |||
private ComponentDto rootComponent; | |||
@Before | |||
public void setUp() { | |||
project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ProjectData projectData = db.components().insertPrivateProject(); | |||
project = projectData.getProjectDto(); | |||
rootComponent = projectData.getMainBranchComponent(); | |||
} | |||
@Test | |||
@@ -240,7 +246,7 @@ public class ValuesActionIT { | |||
PropertyDefinition.builder("property").defaultValue("default").onQualifiers(PROJECT).build()); | |||
db.properties().insertProperties(null, null, null, | |||
null, newGlobalPropertyDto().setKey("property").setValue("one")); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
// The property is overriding global value | |||
newComponentPropertyDto(project).setKey("property").setValue("two")); | |||
@@ -259,7 +265,7 @@ public class ValuesActionIT { | |||
PropertyDefinition.builder("project").onQualifiers(PROJECT).build())); | |||
db.properties().insertProperties(null, null, null, | |||
null, newGlobalPropertyDto().setKey("global").setValue("one")); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("project").setValue("two")); | |||
ValuesWsResponse result = executeRequestForProjectProperties(); | |||
@@ -299,7 +305,7 @@ public class ValuesActionIT { | |||
@Test | |||
public void return_values_of_component_even_if_no_property_definition() { | |||
logInAsProjectUser(); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("property").setValue("foo")); | |||
ValuesWsResponse response = executeRequestForComponentProperties(project, "property"); | |||
@@ -334,31 +340,6 @@ public class ValuesActionIT { | |||
assertThat(result.getSettingsList()).isEmpty(); | |||
} | |||
@Test | |||
public void return_inherited_values_on_component() { | |||
logInAsProjectUser(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
definitions.addComponents(asList( | |||
PropertyDefinition.builder("defaultProperty").defaultValue("default").onQualifiers(PROJECT).build(), | |||
PropertyDefinition.builder("globalProperty").onQualifiers(PROJECT).build(), | |||
PropertyDefinition.builder("projectProperty").onQualifiers(PROJECT).build(), | |||
PropertyDefinition.builder("componentProperty").onQualifiers(PROJECT).build())); | |||
db.properties().insertProperties(null, null, null, null, | |||
newGlobalPropertyDto().setKey("globalProperty").setValue("global")); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
newComponentPropertyDto(project).setKey("projectProperty").setValue("project")); | |||
db.properties().insertProperties(null, file.getKey(), file.name(), file.qualifier(), | |||
newComponentPropertyDto(file).setKey("componentProperty").setValue("component")); | |||
ValuesWsResponse result = executeRequestForComponentProperties(file, "defaultProperty", "globalProperty", "projectProperty", "componentProperty"); | |||
assertThat(result.getSettingsList()).hasSize(4); | |||
assertSetting(result.getSettings(0), "defaultProperty", "default", true); | |||
assertSetting(result.getSettings(1), "globalProperty", "global", true); | |||
assertSetting(result.getSettings(2), "projectProperty", "project", true); | |||
assertSetting(result.getSettings(3), "componentProperty", "component", false); | |||
} | |||
@Test | |||
public void return_inherited_values_on_global_setting() { | |||
logIn(); | |||
@@ -375,83 +356,6 @@ public class ValuesActionIT { | |||
assertSetting(result.getSettings(1), "globalProperty", "global", false); | |||
} | |||
@Test | |||
public void return_parent_value() { | |||
logInAsProjectUser(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
definitions.addComponents(asList( | |||
PropertyDefinition.builder("foo").defaultValue("default").onQualifiers(PROJECT).build())); | |||
db.properties().insertProperties(null, null, null, null, | |||
newGlobalPropertyDto().setKey("foo").setValue("global")); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("project")); | |||
db.properties().insertProperties(null, file.getKey(), file.name(), file.qualifier(), | |||
newComponentPropertyDto(file).setKey("foo").setValue("file")); | |||
assertParentValue(executeRequestForComponentProperties(file, "foo").getSettings(0), "project"); | |||
assertParentValue(executeRequestForComponentProperties(project, "foo").getSettings(0), "global"); | |||
assertParentValue(executeRequestForGlobalProperties("foo").getSettings(0), "default"); | |||
} | |||
@Test | |||
public void return_parent_field_values() { | |||
logInAsProjectUser(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
definitions.addComponent(PropertyDefinition | |||
.builder("foo") | |||
.onQualifiers(PROJECT) | |||
.type(PropertyType.PROPERTY_SET) | |||
.fields(asList( | |||
PropertyFieldDefinition.build("key").name("Key").build(), | |||
PropertyFieldDefinition.build("size").name("Size").build())) | |||
.build()); | |||
db.properties().insertPropertySet("foo", null, ImmutableMap.of("key", "keyG1", "size", "sizeG1")); | |||
db.properties().insertPropertySet("foo", project, ImmutableMap.of("key", "keyP1", "size", "sizeP1")); | |||
db.properties().insertPropertySet("foo", file, ImmutableMap.of("key", "keyM1", "size", "sizeM1")); | |||
assertParentFieldValues(executeRequestForComponentProperties(file, "foo").getSettings(0), ImmutableMap.of("key", "keyP1", "size", "sizeP1")); | |||
assertParentFieldValues(executeRequestForComponentProperties(project, "foo").getSettings(0), ImmutableMap.of("key", "keyG1", "size", "sizeG1")); | |||
assertParentFieldValues(executeRequestForGlobalProperties("foo").getSettings(0)); | |||
} | |||
@Test | |||
public void return_no_parent_value() { | |||
logInAsProjectUser(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
definitions.addComponents(asList( | |||
PropertyDefinition.builder("simple").onQualifiers(PROJECT).build(), | |||
PropertyDefinition.builder("multi").multiValues(true).onQualifiers(PROJECT).build(), | |||
PropertyDefinition.builder("set") | |||
.type(PropertyType.PROPERTY_SET) | |||
.onQualifiers(PROJECT) | |||
.fields(asList( | |||
PropertyFieldDefinition.build("key").name("Key").build(), | |||
PropertyFieldDefinition.build("size").name("Size").build())) | |||
.build())); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
newComponentPropertyDto(project).setKey("simple").setValue("module"), | |||
newComponentPropertyDto(project).setKey("multi").setValue("module1,module2")); | |||
db.properties().insertPropertySet("set", project, ImmutableMap.of("key", "keyM1", "size", "sizeM1")); | |||
assertParentValue(executeRequestForComponentProperties(file, "simple").getSettings(0), null); | |||
assertParentValues(executeRequestForComponentProperties(file, "multi").getSettings(0)); | |||
assertParentFieldValues(executeRequestForComponentProperties(file, "set").getSettings(0)); | |||
} | |||
@Test | |||
public void return_parent_value_when_no_definition() { | |||
logInAsProjectUser(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
db.properties().insertProperties(null, null, null, null, | |||
newGlobalPropertyDto().setKey("foo").setValue("global")); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("project")); | |||
assertParentValue(executeRequestForComponentProperties(file, "foo").getSettings(0), "project"); | |||
assertParentValue(executeRequestForComponentProperties(project, "foo").getSettings(0), "global"); | |||
assertParentValue(executeRequestForGlobalProperties("foo").getSettings(0), null); | |||
} | |||
@Test | |||
public void return_value_of_deprecated_key() { | |||
logIn(); | |||
@@ -527,7 +431,7 @@ public class ValuesActionIT { | |||
PropertyDefinition.builder("secret.secured").onQualifiers(PROJECT).build())); | |||
db.properties().insertProperties(null, null, null, null, | |||
newGlobalPropertyDto().setKey("global.secret.secured").setValue("very secret")); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("one"), | |||
newComponentPropertyDto(project).setKey("secret.secured").setValue("password")); | |||
@@ -542,7 +446,7 @@ public class ValuesActionIT { | |||
userSession | |||
.addProjectPermission(USER, project) | |||
.addProjectPermission(SCAN.getKey(), project); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("not-defined.secured").setValue("123")); | |||
ValuesWsResponse result = executeRequestForProjectProperties("not-defined.secured"); | |||
@@ -575,7 +479,7 @@ public class ValuesActionIT { | |||
PropertyDefinition.builder("secret.secured").onQualifiers(PROJECT).build())); | |||
db.properties().insertProperties(null, null, null, null, | |||
newGlobalPropertyDto().setKey("global.secret.secured").setValue("very secret")); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("one"), | |||
newComponentPropertyDto(project).setKey("secret.secured").setValue("password")); | |||
@@ -590,7 +494,7 @@ public class ValuesActionIT { | |||
@Test | |||
public void return_secured_settings_even_if_not_defined_when_project_admin() { | |||
logInAsProjectAdmin(); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("not-defined.secured").setValue("123")); | |||
ValuesWsResponse result = executeRequestForProjectProperties("not-defined.secured"); | |||
@@ -676,7 +580,7 @@ public class ValuesActionIT { | |||
definitions.addComponents(asList( | |||
PropertyDefinition.builder("foo").onQualifiers(PROJECT).build(), | |||
PropertyDefinition.builder("secret.secured").onQualifiers(PROJECT).build())); | |||
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), | |||
db.properties().insertProperties(null, project.getKey(), project.getName(), project.getQualifier(), | |||
newComponentPropertyDto(project).setKey("foo").setValue("one"), | |||
newComponentPropertyDto(project).setKey("secret.secured").setValue("password")); | |||
@@ -847,8 +751,8 @@ public class ValuesActionIT { | |||
assertThat(response.getSetSecuredSettingsList()).contains("my.password.secured"); | |||
} | |||
private ValuesWsResponse executeRequestForComponentProperties(ComponentDto componentDto, String... keys) { | |||
return executeRequest(componentDto.getKey(), keys); | |||
private ValuesWsResponse executeRequestForComponentProperties(EntityDto entity, String... keys) { | |||
return executeRequest(entity.getKey(), keys); | |||
} | |||
private ValuesWsResponse executeRequestForProjectProperties(String... keys) { |
@@ -36,6 +36,7 @@ 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.entity.EntityDto; | |||
import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.portfolio.PortfolioDto.SelectionMode; | |||
import org.sonar.db.project.ProjectDto; | |||
@@ -236,14 +237,25 @@ public class ComponentUpdater { | |||
return branch; | |||
} | |||
// TODO this is wrong, should probably be done for the project and not for the component. Component has the uuid of the branch! | |||
private void handlePermissionTemplate(DbSession dbSession, ComponentDto componentDto, @Nullable String userUuid, @Nullable String userLogin) { | |||
permissionTemplateService.applyDefaultToNewComponent(dbSession, componentDto, userUuid); | |||
if (componentDto.qualifier().equals(PROJECT) | |||
&& permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(dbSession, componentDto)) { | |||
favoriteUpdater.add(dbSession, componentDto, userUuid, userLogin, false); | |||
favoriteUpdater.add(dbSession, toProject(componentDto), userUuid, userLogin, false); | |||
} | |||
} | |||
private static ProjectDto toProject(ComponentDto componentDto) { | |||
return new ProjectDto() | |||
.setUuid(componentDto.uuid()) | |||
.setKey(componentDto.getKey()) | |||
.setQualifier(componentDto.qualifier()) | |||
.setPrivate(componentDto.isPrivate()) | |||
.setName(componentDto.name()) | |||
.setDescription(componentDto.description()); | |||
} | |||
private String getQualifierToDisplay(String qualifier) { | |||
return i18n.message(Locale.getDefault(), "qualifier." + qualifier, "Project"); | |||
} |
@@ -26,14 +26,13 @@ import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.Comparator; | |||
import java.util.HashSet; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.Stream; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.resources.Qualifiers; | |||
import org.sonar.api.resources.ResourceType; | |||
@@ -47,6 +46,7 @@ import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.server.component.index.ComponentHit; | |||
import org.sonar.server.component.index.ComponentHitsPerQualifier; | |||
import org.sonar.server.component.index.ComponentIndex; | |||
@@ -170,41 +170,41 @@ public class SuggestionsAction implements ComponentsWsAction { | |||
* we are generating suggestions, by using (1) favorites and (2) recently browsed components (without searchin in Elasticsearch) | |||
*/ | |||
private SuggestionsWsResponse loadSuggestionsWithoutSearch(int skip, int limit, Set<String> recentlyBrowsedKeys, List<String> qualifiers) { | |||
List<ComponentDto> favoriteDtos = favoriteFinder.list(); | |||
if (favoriteDtos.isEmpty() && recentlyBrowsedKeys.isEmpty()) { | |||
List<EntityDto> favorites = favoriteFinder.list(); | |||
if (favorites.isEmpty() && recentlyBrowsedKeys.isEmpty()) { | |||
return newBuilder().build(); | |||
} | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
Set<ComponentDto> componentDtos = new HashSet<>(favoriteDtos); | |||
Set<EntityDto> entities = new HashSet<>(favorites); | |||
if (!recentlyBrowsedKeys.isEmpty()) { | |||
componentDtos.addAll(dbClient.componentDao().selectByKeys(dbSession, recentlyBrowsedKeys)); | |||
entities.addAll(dbClient.projectDao().selectEntitiesByKeys(dbSession, recentlyBrowsedKeys)); | |||
} | |||
List<ComponentDto> authorizedComponents = userSession.keepAuthorizedComponents(USER, componentDtos); | |||
ListMultimap<String, ComponentDto> componentsPerQualifier = authorizedComponents.stream() | |||
.collect(MoreCollectors.index(ComponentDto::qualifier)); | |||
if (componentsPerQualifier.isEmpty()) { | |||
List<EntityDto> authorizedEntities = userSession.keepAuthorizedEntities(USER, entities); | |||
ListMultimap<String, EntityDto> entityPerQualifier = authorizedEntities.stream() | |||
.collect(MoreCollectors.index(EntityDto::getQualifier)); | |||
if (entityPerQualifier.isEmpty()) { | |||
return newBuilder().build(); | |||
} | |||
Set<String> favoriteUuids = favoriteDtos.stream().map(ComponentDto::uuid).collect(MoreCollectors.toSet(favoriteDtos.size())); | |||
Comparator<ComponentDto> favoriteComparator = Comparator.comparing(c -> favoriteUuids.contains(c.uuid()) ? -1 : +1); | |||
Comparator<ComponentDto> comparator = favoriteComparator.thenComparing(ComponentDto::name); | |||
Set<String> favoriteUuids = favorites.stream().map(EntityDto::getUuid).collect(MoreCollectors.toSet(favorites.size())); | |||
Comparator<EntityDto> favoriteComparator = Comparator.comparing(c -> favoriteUuids.contains(c.getUuid()) ? -1 : +1); | |||
Comparator<EntityDto> comparator = favoriteComparator.thenComparing(EntityDto::getName); | |||
ComponentIndexResults componentsPerQualifiers = ComponentIndexResults.newBuilder().setQualifiers( | |||
qualifiers.stream().map(q -> { | |||
List<ComponentDto> componentsOfThisQualifier = componentsPerQualifier.get(q); | |||
List<EntityDto> componentsOfThisQualifier = entityPerQualifier.get(q); | |||
List<ComponentHit> hits = componentsOfThisQualifier | |||
.stream() | |||
.sorted(comparator) | |||
.skip(skip) | |||
.limit(limit) | |||
.map(ComponentDto::uuid) | |||
.map(EntityDto::getUuid) | |||
.map(ComponentHit::new) | |||
.collect(MoreCollectors.toList(limit)); | |||
int totalHits = componentsOfThisQualifier.size(); | |||
return new ComponentHitsPerQualifier(q, hits, totalHits); | |||
})).build(); | |||
return buildResponse(recentlyBrowsedKeys, favoriteUuids, componentsPerQualifiers, dbSession, authorizedComponents, skip + limit).build(); | |||
return buildResponse(recentlyBrowsedKeys, favoriteUuids, componentsPerQualifiers, authorizedEntities, skip + limit).build(); | |||
} | |||
} | |||
@@ -215,8 +215,8 @@ public class SuggestionsAction implements ComponentsWsAction { | |||
return queryBuilder.build(); | |||
} | |||
List<ComponentDto> favorites = favoriteFinder.list(); | |||
Set<String> favoriteKeys = favorites.stream().map(ComponentDto::getKey).collect(MoreCollectors.toSet(favorites.size())); | |||
List<EntityDto> favorites = favoriteFinder.list(); | |||
Set<String> favoriteKeys = favorites.stream().map(EntityDto::getKey).collect(MoreCollectors.toSet(favorites.size())); | |||
SuggestionQuery.Builder queryBuilder = SuggestionQuery.builder() | |||
.setQuery(query) | |||
.setRecentlyBrowsedKeys(recentlyBrowsedKeys) | |||
@@ -229,14 +229,14 @@ public class SuggestionsAction implements ComponentsWsAction { | |||
return newBuilder().build(); | |||
} | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
Set<String> componentUuids = componentsPerQualifiers.getQualifiers() | |||
Set<String> entityUuids = componentsPerQualifiers.getQualifiers() | |||
.map(ComponentHitsPerQualifier::getHits) | |||
.flatMap(Collection::stream) | |||
.map(ComponentHit::getUuid) | |||
.collect(toSet()); | |||
List<ComponentDto> componentDtos = dbClient.componentDao().selectByUuids(dbSession, componentUuids); | |||
Set<String> favoriteUuids = favorites.stream().map(ComponentDto::uuid).collect(MoreCollectors.toSet(favorites.size())); | |||
SuggestionsWsResponse.Builder searchWsResponse = buildResponse(recentlyBrowsedKeys, favoriteUuids, componentsPerQualifiers, dbSession, componentDtos, skip + limit); | |||
List<EntityDto> entities = dbClient.projectDao().selectEntitiesByUuids(dbSession, entityUuids); | |||
Set<String> favoriteUuids = favorites.stream().map(EntityDto::getUuid).collect(MoreCollectors.toSet(favorites.size())); | |||
SuggestionsWsResponse.Builder searchWsResponse = buildResponse(recentlyBrowsedKeys, favoriteUuids, componentsPerQualifiers, entities, skip + limit); | |||
getWarning(query).ifPresent(searchWsResponse::setWarning); | |||
return searchWsResponse.build(); | |||
} | |||
@@ -269,21 +269,11 @@ public class SuggestionsAction implements ComponentsWsAction { | |||
} | |||
private SuggestionsWsResponse.Builder buildResponse(Set<String> recentlyBrowsedKeys, Set<String> favoriteUuids, ComponentIndexResults componentsPerQualifiers, | |||
DbSession dbSession, List<ComponentDto> componentDtos, int coveredItems) { | |||
List<EntityDto> entities, int coveredItems) { | |||
Map<String, ComponentDto> componentsByUuids = componentDtos.stream() | |||
.collect(MoreCollectors.uniqueIndex(ComponentDto::uuid)); | |||
Map<String, ComponentDto> projectsByUuids = loadProjects(dbSession, componentsByUuids.values()); | |||
return toResponse(componentsPerQualifiers, recentlyBrowsedKeys, favoriteUuids, componentsByUuids, projectsByUuids, coveredItems); | |||
} | |||
private Map<String, ComponentDto> loadProjects(DbSession dbSession, Collection<ComponentDto> components) { | |||
Set<String> projectUuids = components.stream() | |||
.filter(c -> QUALIFIERS_FOR_WHICH_TO_RETURN_PROJECT.contains(c.qualifier())) | |||
.map(ComponentDto::branchUuid) | |||
.collect(MoreCollectors.toSet()); | |||
return dbClient.componentDao().selectByUuids(dbSession, projectUuids).stream() | |||
.collect(MoreCollectors.uniqueIndex(ComponentDto::uuid)); | |||
Map<String, EntityDto> entitiesByUuids = entities.stream() | |||
.collect(MoreCollectors.uniqueIndex(EntityDto::getUuid)); | |||
return toResponse(componentsPerQualifiers, recentlyBrowsedKeys, favoriteUuids, entitiesByUuids, coveredItems); | |||
} | |||
private ComponentIndexResults searchInIndex(SuggestionQuery suggestionQuery) { | |||
@@ -291,22 +281,22 @@ public class SuggestionsAction implements ComponentsWsAction { | |||
} | |||
private static SuggestionsWsResponse.Builder toResponse(ComponentIndexResults componentsPerQualifiers, Set<String> recentlyBrowsedKeys, Set<String> favoriteUuids, | |||
Map<String, ComponentDto> componentsByUuids, Map<String, ComponentDto> projectsByUuids, int coveredItems) { | |||
Map<String, EntityDto> entitiesByUuids, int coveredItems) { | |||
if (componentsPerQualifiers.isEmpty()) { | |||
return newBuilder(); | |||
} | |||
return newBuilder() | |||
.addAllResults(toCategories(componentsPerQualifiers, recentlyBrowsedKeys, favoriteUuids, componentsByUuids, projectsByUuids, coveredItems)) | |||
.addAllProjects(toProjects(projectsByUuids)); | |||
.addAllResults(toCategories(componentsPerQualifiers, recentlyBrowsedKeys, favoriteUuids, entitiesByUuids, coveredItems)); | |||
} | |||
private static List<Category> toCategories(ComponentIndexResults componentsPerQualifiers, Set<String> recentlyBrowsedKeys, Set<String> favoriteUuids, | |||
Map<String, ComponentDto> componentsByUuids, Map<String, ComponentDto> projectsByUuids, int coveredItems) { | |||
Map<String, EntityDto> entitiesByUuids, int coveredItems) { | |||
return componentsPerQualifiers.getQualifiers().map(qualifier -> { | |||
List<Suggestion> suggestions = qualifier.getHits().stream() | |||
.map(hit -> toSuggestion(hit, recentlyBrowsedKeys, favoriteUuids, componentsByUuids, projectsByUuids)) | |||
.filter(Objects::nonNull) | |||
.map(hit -> toSuggestion(hit, recentlyBrowsedKeys, favoriteUuids, entitiesByUuids)) | |||
.filter(Optional::isPresent) | |||
.map(Optional::get) | |||
.collect(toList()); | |||
return Category.newBuilder() | |||
@@ -321,33 +311,14 @@ public class SuggestionsAction implements ComponentsWsAction { | |||
* @return null when the component exists in Elasticsearch but not in database. That | |||
* occurs when failed indexing requests are been recovering. | |||
*/ | |||
@CheckForNull | |||
private static Suggestion toSuggestion(ComponentHit hit, Set<String> recentlyBrowsedKeys, Set<String> favoriteUuids, Map<String, ComponentDto> componentsByUuids, | |||
Map<String, ComponentDto> projectsByUuids) { | |||
ComponentDto result = componentsByUuids.get(hit.getUuid()); | |||
if (result == null | |||
// SONAR-11419 this has happened in production while code does not really allow it. An inconsistency in DB may be the cause. | |||
|| (QUALIFIERS_FOR_WHICH_TO_RETURN_PROJECT.contains(result.qualifier()) && projectsByUuids.get(result.branchUuid()) == null)) { | |||
return null; | |||
} | |||
Suggestion.Builder builder = Suggestion.newBuilder() | |||
.setKey(result.getKey()) | |||
.setName(result.name()) | |||
.setMatch(hit.getHighlightedText().orElse(HtmlEscapers.htmlEscaper().escape(result.name()))) | |||
.setIsRecentlyBrowsed(recentlyBrowsedKeys.contains(result.getKey())) | |||
.setIsFavorite(favoriteUuids.contains(result.uuid())); | |||
if (QUALIFIERS_FOR_WHICH_TO_RETURN_PROJECT.contains(result.qualifier())) { | |||
builder.setProject(projectsByUuids.get(result.branchUuid()).getKey()); | |||
} | |||
return builder.build(); | |||
} | |||
private static List<Project> toProjects(Map<String, ComponentDto> projectsByUuids) { | |||
return projectsByUuids.values().stream() | |||
.map(p -> Project.newBuilder() | |||
.setKey(p.getKey()) | |||
.setName(p.longName()) | |||
.build()) | |||
.toList(); | |||
private static Optional<Suggestion> toSuggestion(ComponentHit hit, Set<String> recentlyBrowsedKeys, Set<String> favoriteUuids, Map<String, EntityDto> entitiesByUuids) { | |||
return Optional.ofNullable(entitiesByUuids.get(hit.getUuid())) | |||
.map(result -> Suggestion.newBuilder() | |||
.setKey(result.getKey()) | |||
.setName(result.getName()) | |||
.setMatch(hit.getHighlightedText().orElse(HtmlEscapers.htmlEscaper().escape(result.getName()))) | |||
.setIsRecentlyBrowsed(recentlyBrowsedKeys.contains(result.getKey())) | |||
.setIsFavorite(favoriteUuids.contains(result.getUuid())) | |||
.build()); | |||
} | |||
} |
@@ -25,13 +25,12 @@ import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonar.db.property.PropertyQuery; | |||
import org.sonar.server.user.UserSession; | |||
import static java.util.Collections.emptyList; | |||
import static org.sonar.core.util.stream.MoreCollectors.toList; | |||
import static org.sonar.server.favorite.FavoriteUpdater.PROP_FAVORITE_KEY; | |||
public class FavoriteFinder { | |||
@@ -46,7 +45,7 @@ public class FavoriteFinder { | |||
/** | |||
* @return the list of favorite components of the authenticated user. Empty list if the user is not authenticated | |||
*/ | |||
public List<ComponentDto> list() { | |||
public List<EntityDto> list() { | |||
if (!userSession.isLoggedIn()) { | |||
return emptyList(); | |||
} | |||
@@ -58,9 +57,11 @@ public class FavoriteFinder { | |||
.build(); | |||
Set<String> componentUuids = dbClient.propertiesDao().selectByQuery(dbQuery, dbSession).stream().map(PropertyDto::getComponentUuid).collect(Collectors.toSet()); | |||
return dbClient.componentDao().selectByUuids(dbSession, componentUuids).stream() | |||
.sorted(Comparator.comparing(ComponentDto::name)) | |||
.collect(toList()); | |||
List<EntityDto> entities = dbClient.projectDao().selectEntitiesByUuids(dbSession, componentUuids); | |||
return entities.stream() | |||
.sorted(Comparator.comparing(EntityDto::getName)) | |||
.collect(Collectors.toList()); | |||
} | |||
} | |||
} |
@@ -28,7 +28,9 @@ import org.sonar.api.server.ws.WebService; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.favorite.FavoriteUpdater; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonar.server.ws.KeyExamples; | |||
@@ -92,14 +94,16 @@ public class AddAction implements FavoritesWsAction { | |||
private Consumer<Request> addFavorite() { | |||
return request -> { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
ComponentDto componentDto = componentFinder.getByKey(dbSession, request.mandatoryParam(PARAM_COMPONENT)); | |||
checkArgument(SUPPORTED_QUALIFIERS.contains(componentDto.qualifier()), "Only components with qualifiers %s are supported", SUPPORTED_QUALIFIERS_AS_STRING); | |||
EntityDto entity = dbClient.projectDao().selectEntityByKey(dbSession, request.mandatoryParam(PARAM_COMPONENT)) | |||
.orElseThrow(() -> new NotFoundException(format("Entity with key '%s' not found", request.mandatoryParam(PARAM_COMPONENT)))); | |||
checkArgument(SUPPORTED_QUALIFIERS.contains(entity.getQualifier()), "Only components with qualifiers %s are supported", SUPPORTED_QUALIFIERS_AS_STRING); | |||
userSession | |||
.checkLoggedIn() | |||
.checkComponentPermission(USER, componentDto); | |||
.checkEntityPermission(USER, entity); | |||
String userUuid = userSession.isLoggedIn() ? userSession.getUuid() : null; | |||
String userLogin = userSession.isLoggedIn() ? userSession.getLogin() : null; | |||
favoriteUpdater.add(dbSession, componentDto, userUuid, userLogin, true); | |||
favoriteUpdater.add(dbSession, entity, userUuid, userLogin, true); | |||
dbSession.commit(); | |||
} | |||
}; |
@@ -28,6 +28,7 @@ import org.sonar.api.utils.Paging; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.server.favorite.FavoriteFinder; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonarqube.ws.Common; | |||
@@ -78,25 +79,25 @@ public class SearchAction implements FavoritesWsAction { | |||
private SearchResults toSearchResults(SearchRequest request) { | |||
userSession.checkLoggedIn(); | |||
List<ComponentDto> authorizedFavorites = getAuthorizedFavorites(); | |||
List<EntityDto> authorizedFavorites = getAuthorizedFavorites(); | |||
Paging paging = Paging.forPageIndex(Integer.parseInt(request.getP())).withPageSize(Integer.parseInt(request.getPs())).andTotal(authorizedFavorites.size()); | |||
List<ComponentDto> displayedFavorites = authorizedFavorites.stream() | |||
List<EntityDto> displayedFavorites = authorizedFavorites.stream() | |||
.skip(paging.offset()) | |||
.limit(paging.pageSize()) | |||
.collect(MoreCollectors.toList()); | |||
return new SearchResults(paging, displayedFavorites); | |||
} | |||
private List<ComponentDto> getAuthorizedFavorites() { | |||
List<ComponentDto> componentDtos = favoriteFinder.list(); | |||
return userSession.keepAuthorizedComponents(UserRole.USER, componentDtos); | |||
private List<EntityDto> getAuthorizedFavorites() { | |||
List<EntityDto> entities = favoriteFinder.list(); | |||
return userSession.keepAuthorizedEntities(UserRole.USER, entities); | |||
} | |||
private static class SearchResults { | |||
private final List<ComponentDto> favorites; | |||
private final List<EntityDto> favorites; | |||
private final Paging paging; | |||
private SearchResults(Paging paging, List<ComponentDto> favorites) { | |||
private SearchResults(Paging paging, List<EntityDto> favorites) { | |||
this.paging = paging; | |||
this.favorites = favorites; | |||
} | |||
@@ -124,12 +125,12 @@ public class SearchAction implements FavoritesWsAction { | |||
.forEach(builder::addFavorites); | |||
} | |||
private static Favorite toWsFavorite(Favorite.Builder builder, ComponentDto componentDto) { | |||
private static Favorite toWsFavorite(Favorite.Builder builder, EntityDto componentDto) { | |||
builder | |||
.clear() | |||
.setKey(componentDto.getKey()); | |||
ofNullable(componentDto.name()).ifPresent(builder::setName); | |||
ofNullable(componentDto.qualifier()).ifPresent(builder::setQualifier); | |||
ofNullable(componentDto.getName()).ifPresent(builder::setName); | |||
ofNullable(componentDto.getQualifier()).ifPresent(builder::setQualifier); | |||
return builder.build(); | |||
} | |||
@@ -35,10 +35,13 @@ import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.setting.ws.SettingValidations.SettingData; | |||
import org.sonar.server.user.UserSession; | |||
import static java.lang.String.format; | |||
import static java.util.Collections.emptyList; | |||
import static org.sonar.server.setting.ws.SettingsWsParameters.PARAM_BRANCH; | |||
import static org.sonar.server.setting.ws.SettingsWsParameters.PARAM_COMPONENT; | |||
@@ -107,7 +110,7 @@ public class ResetAction implements SettingsWsAction { | |||
public void handle(Request request, Response response) throws Exception { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
ResetRequest resetRequest = toWsRequest(request); | |||
Optional<ComponentDto> component = getComponent(dbSession, resetRequest); | |||
Optional<EntityDto> component = getComponent(dbSession, resetRequest); | |||
checkPermissions(component); | |||
resetRequest.getKeys().forEach(key -> { | |||
SettingsWsSupport.validateKey(key); | |||
@@ -144,17 +147,20 @@ public class ResetAction implements SettingsWsAction { | |||
.setPullRequest(request.param(PARAM_PULL_REQUEST)); | |||
} | |||
private Optional<ComponentDto> getComponent(DbSession dbSession, ResetRequest request) { | |||
private Optional<EntityDto> getComponent(DbSession dbSession, ResetRequest request) { | |||
String componentKey = request.getComponent(); | |||
if (componentKey == null) { | |||
return Optional.empty(); | |||
} | |||
return Optional.of(componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, componentKey, request.getBranch(), request.getPullRequest())); | |||
// TODO this WS should support branches and PRs? | |||
return Optional.of(dbClient.projectDao().selectEntityByKey(dbSession, componentKey) | |||
.orElseThrow(() -> new NotFoundException(format("Component key '%s' not found", componentKey)))); | |||
} | |||
private void checkPermissions(Optional<ComponentDto> component) { | |||
private void checkPermissions(Optional<EntityDto> component) { | |||
if (component.isPresent()) { | |||
userSession.checkComponentPermission(UserRole.ADMIN, component.get()); | |||
userSession.checkEntityPermission(UserRole.ADMIN, component.get()); | |||
} else { | |||
userSession.checkIsSystemAdministrator(); | |||
} |
@@ -48,6 +48,7 @@ import org.sonar.api.web.UserRole; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonar.scanner.protocol.GsonHelper; | |||
import org.sonar.server.component.ComponentFinder; | |||
@@ -57,6 +58,7 @@ import org.sonar.server.setting.ws.SettingValidations.SettingData; | |||
import org.sonar.server.user.UserSession; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static java.lang.String.format; | |||
import static org.sonar.server.exceptions.BadRequestException.checkRequest; | |||
import static org.sonar.server.setting.ws.SettingsWsParameters.PARAM_COMPONENT; | |||
import static org.sonar.server.setting.ws.SettingsWsParameters.PARAM_FIELD_VALUES; | |||
@@ -103,9 +105,9 @@ public class SetAction implements SettingsWsAction { | |||
PARAM_VALUE, PARAM_VALUES) | |||
.setSince("6.1") | |||
.setChangelog( | |||
new Change("10.1", String.format("The use of module keys in parameter '%s' is removed", PARAM_COMPONENT)), | |||
new Change("10.1", format("The use of module keys in parameter '%s' is removed", PARAM_COMPONENT)), | |||
new Change("8.8", "Deprecated parameter 'componentKey' has been removed"), | |||
new Change("7.6", String.format("The use of module keys in parameter '%s' is deprecated", PARAM_COMPONENT)), | |||
new Change("7.6", format("The use of module keys in parameter '%s' is deprecated", PARAM_COMPONENT)), | |||
new Change("7.1", "The settings defined in conf/sonar.properties are read-only and can't be changed")) | |||
.setPost(true) | |||
.setHandler(this); | |||
@@ -144,10 +146,10 @@ public class SetAction implements SettingsWsAction { | |||
} | |||
private void doHandle(DbSession dbSession, SetRequest request) { | |||
Optional<ComponentDto> component = searchComponent(dbSession, request); | |||
String projectKey = component.isPresent() ? component.get().getKey() : null; | |||
String projectName = component.isPresent() ? component.get().name() : null; | |||
String qualifier = component.isPresent() ? component.get().qualifier() : null; | |||
Optional<EntityDto> component = searchComponent(dbSession, request); | |||
String projectKey = component.map(EntityDto::getKey).orElse(null); | |||
String projectName = component.map(EntityDto::getName).orElse(null); | |||
String qualifier = component.map(EntityDto::getQualifier).orElse(null); | |||
checkPermissions(component); | |||
PropertyDefinition definition = propertyDefinitions.get(request.getKey()); | |||
@@ -172,16 +174,16 @@ public class SetAction implements SettingsWsAction { | |||
} | |||
} | |||
private String doHandlePropertySet(DbSession dbSession, SetRequest request, @Nullable PropertyDefinition definition, Optional<ComponentDto> component) { | |||
private String doHandlePropertySet(DbSession dbSession, SetRequest request, @Nullable PropertyDefinition definition, Optional<EntityDto> component) { | |||
validatePropertySet(request, definition); | |||
int[] fieldIds = IntStream.rangeClosed(1, request.getFieldValues().size()).toArray(); | |||
String inlinedFieldKeys = IntStream.of(fieldIds).mapToObj(String::valueOf).collect(COMMA_JOINER); | |||
String key = persistedKey(request); | |||
String componentUuid = component.isPresent() ? component.get().uuid() : null; | |||
String componentUuid = component.isPresent() ? component.get().getUuid() : null; | |||
String componentKey = component.isPresent() ? component.get().getKey() : null; | |||
String componentName = component.isPresent() ? component.get().name() : null; | |||
String qualifier = component.isPresent() ? component.get().qualifier() : null; | |||
String componentName = component.isPresent() ? component.get().getName() : null; | |||
String qualifier = component.isPresent() ? component.get().getQualifier() : null; | |||
deleteSettings(dbSession, component, key); | |||
dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto().setKey(key).setValue(inlinedFieldKeys) | |||
@@ -197,7 +199,7 @@ public class SetAction implements SettingsWsAction { | |||
return inlinedFieldKeys; | |||
} | |||
private void deleteSettings(DbSession dbSession, Optional<ComponentDto> component, String key) { | |||
private void deleteSettings(DbSession dbSession, Optional<EntityDto> component, String key) { | |||
if (component.isPresent()) { | |||
settingsUpdater.deleteComponentSettings(dbSession, component.get(), key); | |||
} else { | |||
@@ -205,7 +207,7 @@ public class SetAction implements SettingsWsAction { | |||
} | |||
} | |||
private void commonChecks(SetRequest request, Optional<ComponentDto> component) { | |||
private void commonChecks(SetRequest request, Optional<EntityDto> component) { | |||
checkValueIsSet(request); | |||
String settingKey = request.getKey(); | |||
SettingData settingData = new SettingData(settingKey, valuesFromRequest(request), component.orElse(null)); | |||
@@ -284,9 +286,9 @@ public class SetAction implements SettingsWsAction { | |||
: request.getValue(); | |||
} | |||
private void checkPermissions(Optional<ComponentDto> component) { | |||
private void checkPermissions(Optional<EntityDto> component) { | |||
if (component.isPresent()) { | |||
userSession.checkComponentPermission(UserRole.ADMIN, component.get()); | |||
userSession.checkEntityPermission(UserRole.ADMIN, component.get()); | |||
} else { | |||
userSession.checkIsSystemAdministrator(); | |||
} | |||
@@ -311,19 +313,20 @@ public class SetAction implements SettingsWsAction { | |||
try { | |||
return gson.fromJson(json, type); | |||
} catch (JsonSyntaxException e) { | |||
throw BadRequestException.create(String.format("JSON '%s' does not respect expected format for setting '%s'. Ex: {\"field1\":\"value1\", \"field2\":\"value2\"}", json, key)); | |||
throw BadRequestException.create(format("JSON '%s' does not respect expected format for setting '%s'. Ex: {\"field1\":\"value1\", \"field2\":\"value2\"}", json, key)); | |||
} | |||
} | |||
private Optional<ComponentDto> searchComponent(DbSession dbSession, SetRequest request) { | |||
private Optional<EntityDto> searchComponent(DbSession dbSession, SetRequest request) { | |||
String componentKey = request.getComponent(); | |||
if (componentKey == null) { | |||
return Optional.empty(); | |||
} | |||
return Optional.of(componentFinder.getByKey(dbSession, componentKey)); | |||
return Optional.of(dbClient.projectDao().selectEntityByKey(dbSession, componentKey) | |||
.orElseThrow(() -> new IllegalArgumentException(format("Component '%s' not found", componentKey)))); | |||
} | |||
private PropertyDto toProperty(SetRequest request, Optional<ComponentDto> component) { | |||
private PropertyDto toProperty(SetRequest request, Optional<EntityDto> entity) { | |||
String key = persistedKey(request); | |||
String value = persistedValue(request); | |||
@@ -331,8 +334,8 @@ public class SetAction implements SettingsWsAction { | |||
.setKey(key) | |||
.setValue(value); | |||
if (component.isPresent()) { | |||
property.setComponentUuid(component.get().uuid()); | |||
if (entity.isPresent()) { | |||
property.setComponentUuid(entity.get().getUuid()); | |||
} | |||
return property; |
@@ -40,11 +40,10 @@ import org.sonar.api.PropertyType; | |||
import org.sonar.api.config.PropertyDefinition; | |||
import org.sonar.api.config.PropertyDefinitions; | |||
import org.sonar.api.resources.Qualifiers; | |||
import org.sonar.api.resources.Scopes; | |||
import org.sonar.core.i18n.I18n; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.metric.MetricDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
@@ -55,7 +54,7 @@ import static java.util.Objects.requireNonNull; | |||
import static org.sonar.server.exceptions.BadRequestException.checkRequest; | |||
public class SettingValidations { | |||
private static final Collection<String> SECURITY_JSON_PROPERTIES = asList( | |||
private static final Collection<String> SECURITY_JSON_PROPERTIES = List.of( | |||
"sonar.security.config.javasecurity", | |||
"sonar.security.config.phpsecurity", | |||
"sonar.security.config.pythonsecurity", | |||
@@ -76,32 +75,29 @@ public class SettingValidations { | |||
public Consumer<SettingData> scope() { | |||
return data -> { | |||
PropertyDefinition definition = definitions.get(data.key); | |||
checkRequest(data.component != null || definition == null || definition.global() || isGlobal(definition), | |||
checkRequest(data.entity != null || definition == null || definition.global() || isGlobal(definition), | |||
"Setting '%s' cannot be global", data.key); | |||
}; | |||
} | |||
public Consumer<SettingData> qualifier() { | |||
return data -> { | |||
String qualifier = data.component == null ? "" : data.component.qualifier(); | |||
String qualifier = data.entity == null ? "" : data.entity.getQualifier(); | |||
PropertyDefinition definition = definitions.get(data.key); | |||
checkRequest(checkComponentScopeAndQualifier(data, definition), | |||
checkRequest(checkComponentQualifier(data, definition), | |||
"Setting '%s' cannot be set on a %s", data.key, i18n.message(Locale.ENGLISH, "qualifier." + qualifier, null)); | |||
}; | |||
} | |||
private static boolean checkComponentScopeAndQualifier(SettingData data, @Nullable PropertyDefinition definition) { | |||
ComponentDto component = data.component; | |||
private static boolean checkComponentQualifier(SettingData data, @Nullable PropertyDefinition definition) { | |||
EntityDto component = data.entity; | |||
if (component == null) { | |||
return true; | |||
} | |||
if (!Scopes.PROJECT.equals(component.scope())) { | |||
return false; | |||
} | |||
if (definition == null) { | |||
return SUPPORTED_QUALIFIERS.contains(component.qualifier()); | |||
return SUPPORTED_QUALIFIERS.contains(component.getQualifier()); | |||
} | |||
return definition.qualifiers().contains(component.qualifier()); | |||
return definition.qualifiers().contains(component.getQualifier()); | |||
} | |||
public Consumer<SettingData> valueType() { | |||
@@ -116,12 +112,12 @@ public class SettingValidations { | |||
private final String key; | |||
private final List<String> values; | |||
@CheckForNull | |||
private final ComponentDto component; | |||
private final EntityDto entity; | |||
SettingData(String key, List<String> values, @Nullable ComponentDto component) { | |||
SettingData(String key, List<String> values, @Nullable EntityDto entity) { | |||
this.key = requireNonNull(key); | |||
this.values = requireNonNull(values); | |||
this.component = component; | |||
this.entity = entity; | |||
} | |||
} | |||
@@ -195,7 +191,6 @@ public class SettingValidations { | |||
SchemaLoader.load(jsonSchema).validate(jsonSubject); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -22,12 +22,14 @@ package org.sonar.server.setting.ws; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.PropertyType; | |||
import org.sonar.api.config.PropertyDefinition; | |||
import org.sonar.api.config.PropertyDefinitions; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
@@ -50,54 +52,54 @@ public class SettingsUpdater { | |||
public void deleteGlobalSettings(DbSession dbSession, List<String> settingKeys) { | |||
checkArgument(!settingKeys.isEmpty(), "At least one setting key is required"); | |||
settingKeys.forEach(key -> delete(dbSession, key, Optional.empty())); | |||
settingKeys.forEach(key -> delete(dbSession, key, null)); | |||
} | |||
public void deleteComponentSettings(DbSession dbSession, ComponentDto componentDto, String... settingKeys) { | |||
deleteComponentSettings(dbSession, componentDto, asList(settingKeys)); | |||
public void deleteComponentSettings(DbSession dbSession, EntityDto entity, String... settingKeys) { | |||
deleteComponentSettings(dbSession, entity, asList(settingKeys)); | |||
} | |||
public void deleteComponentSettings(DbSession dbSession, ComponentDto componentDto, List<String> settingKeys) { | |||
public void deleteComponentSettings(DbSession dbSession, EntityDto entity, List<String> settingKeys) { | |||
checkArgument(!settingKeys.isEmpty(), "At least one setting key is required"); | |||
for (String propertyKey : settingKeys) { | |||
delete(dbSession, propertyKey, Optional.of(componentDto)); | |||
delete(dbSession, propertyKey, entity); | |||
} | |||
} | |||
private void delete(DbSession dbSession, String settingKey, Optional<ComponentDto> componentDto) { | |||
private void delete(DbSession dbSession, String settingKey, @Nullable EntityDto entity) { | |||
PropertyDefinition definition = definitions.get(settingKey); | |||
if (definition == null || !definition.type().equals(PropertyType.PROPERTY_SET)) { | |||
deleteSetting(dbSession, settingKey, componentDto); | |||
deleteSetting(dbSession, settingKey, entity); | |||
} else { | |||
deletePropertySet(dbSession, settingKey, definition, componentDto); | |||
deletePropertySet(dbSession, settingKey, definition, entity); | |||
} | |||
} | |||
private void deleteSetting(DbSession dbSession, String settingKey, Optional<ComponentDto> componentDto) { | |||
if (componentDto.isPresent()) { | |||
dbClient.propertiesDao().deleteProjectProperty(dbSession, settingKey, componentDto.get().uuid(), componentDto.get().getKey(), | |||
componentDto.get().name(), componentDto.get().qualifier()); | |||
private void deleteSetting(DbSession dbSession, String settingKey, @Nullable EntityDto entity) { | |||
if (entity != null) { | |||
dbClient.propertiesDao().deleteProjectProperty(dbSession, settingKey, entity.getUuid(), entity.getKey(), | |||
entity.getName(), entity.getQualifier()); | |||
} else { | |||
dbClient.propertiesDao().deleteGlobalProperty(settingKey, dbSession); | |||
} | |||
} | |||
private void deletePropertySet(DbSession dbSession, String settingKey, PropertyDefinition definition, Optional<ComponentDto> componentDto) { | |||
Optional<PropertyDto> propertyDto = selectPropertyDto(dbSession, settingKey, componentDto); | |||
private void deletePropertySet(DbSession dbSession, String settingKey, PropertyDefinition definition, @Nullable EntityDto entity) { | |||
Optional<PropertyDto> propertyDto = selectPropertyDto(dbSession, settingKey, entity); | |||
if (!propertyDto.isPresent()) { | |||
// Setting doesn't exist, nothing to do | |||
return; | |||
} | |||
Set<String> settingSetKeys = extractPropertySetKeys(propertyDto.get(), definition); | |||
for (String key : settingSetKeys) { | |||
deleteSetting(dbSession, key, componentDto); | |||
deleteSetting(dbSession, key, entity); | |||
} | |||
deleteSetting(dbSession, settingKey, componentDto); | |||
deleteSetting(dbSession, settingKey, entity); | |||
} | |||
private Optional<PropertyDto> selectPropertyDto(DbSession dbSession, String settingKey, Optional<ComponentDto> componentDto) { | |||
if (componentDto.isPresent()) { | |||
return Optional.ofNullable(dbClient.propertiesDao().selectProjectProperty(dbSession, componentDto.get().uuid(), settingKey)); | |||
private Optional<PropertyDto> selectPropertyDto(DbSession dbSession, String settingKey, @Nullable EntityDto entity) { | |||
if (entity != null) { | |||
return Optional.ofNullable(dbClient.propertiesDao().selectProjectProperty(dbSession, entity.getUuid(), settingKey)); | |||
} else { | |||
return Optional.ofNullable(dbClient.propertiesDao().selectGlobalProperty(dbSession, settingKey)); | |||
} |