Skip to content

Commit

Permalink
feat(UI): CycloneDX SBOM Importer & Package Portlet
Browse files Browse the repository at this point in the history
Signed-off-by: akapti <abdul.kapti@siemens-healhtineers.com>

feat(REST): REST endpoints for Package portlet
Signed-off-by: afsahsyeda <afsah.syeda@siemens-healhtineers.com>
  • Loading branch information
Abdul Kapti authored and akapti committed Jun 13, 2023
1 parent af7f8ca commit d73f31f
Show file tree
Hide file tree
Showing 117 changed files with 7,975 additions and 332 deletions.
8 changes: 8 additions & 0 deletions backend/src-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,13 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-core-java</artifactId>
</dependency>
<dependency>
<groupId>com.github.package-url</groupId>
<artifactId>packageurl-java</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ private void setShortSummaryFields(Release document, Release copy) {
copyField(document, copy, _Fields.RELEASE_DATE);
copyField(document, copy, _Fields.SOURCE_CODE_DOWNLOADURL);
copyField(document, copy, _Fields.BINARY_DOWNLOADURL);
copyField(document, copy, _Fields.PACKAGE_IDS);
}

private void setAdditionalFieldsForSummariesOtherThanShortAndDetailedExport(Release document, Release copy){
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.sw360.datahandler.thrift.attachments.CheckStatus;
import org.eclipse.sw360.datahandler.thrift.components.Component;
import org.eclipse.sw360.datahandler.thrift.components.Release;
import org.eclipse.sw360.datahandler.thrift.packages.Package;
import org.eclipse.sw360.datahandler.thrift.projects.Project;

import com.cloudant.client.api.CloudantClient;
Expand Down Expand Up @@ -101,6 +102,10 @@ protected void deleteAttachmentUsagesOfUnlinkedReleases(Source usedBy, Set<Strin
Project project = (Project) type;
project.setModifiedBy(userEmail);
project.setModifiedOn(SW360Utils.getCreatedOn());
} else if (type instanceof Package) {
Package pkg = (Package) type;
pkg.setModifiedBy(userEmail);
pkg.setModifiedOn(SW360Utils.getCreatedOn());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import org.eclipse.sw360.datahandler.thrift.components.*;
import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest;
import org.eclipse.sw360.datahandler.thrift.moderation.ModerationService;
import org.eclipse.sw360.datahandler.thrift.packages.Package;
import org.eclipse.sw360.datahandler.thrift.packages.PackageService;
import org.eclipse.sw360.datahandler.thrift.projects.Project;
import org.eclipse.sw360.datahandler.thrift.projects.ProjectService;
import org.eclipse.sw360.datahandler.thrift.users.RequestedAction;
Expand Down Expand Up @@ -72,6 +74,7 @@
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.*;

Expand Down Expand Up @@ -116,6 +119,7 @@ public class ComponentDatabaseHandler extends AttachmentAwareDatabaseHandler {
private final VendorRepository vendorRepository;
private final ProjectRepository projectRepository;
private final UserRepository userRepository;
private final PackageRepository packageRepository;
private DatabaseHandlerUtil dbHandlerUtil;

private final AttachmentConnector attachmentConnector;
Expand Down Expand Up @@ -150,6 +154,7 @@ public class ComponentDatabaseHandler extends AttachmentAwareDatabaseHandler {
ClearingInformation._Fields.REQUEST_ID, ClearingInformation._Fields.ADDITIONAL_REQUEST_INFO,
ClearingInformation._Fields.EXTERNAL_SUPPLIER_ID, ClearingInformation._Fields.EVALUATED,
ClearingInformation._Fields.PROC_START);

public ComponentDatabaseHandler(Supplier<CloudantClient> httpClient, String dbName, String attachmentDbName, ComponentModerator moderator, ReleaseModerator releaseModerator, ProjectModerator projectModerator) throws MalformedURLException {
super(httpClient, dbName, attachmentDbName);
DatabaseConnectorCloudant db = new DatabaseConnectorCloudant(httpClient, dbName);
Expand All @@ -160,6 +165,7 @@ public ComponentDatabaseHandler(Supplier<CloudantClient> httpClient, String dbNa
componentRepository = new ComponentRepository(db, releaseRepository, vendorRepository);
projectRepository = new ProjectRepository(db);
userRepository = new UserRepository(db);
packageRepository = new PackageRepository(db);

// Create the moderator
this.moderator = moderator;
Expand All @@ -185,6 +191,7 @@ public ComponentDatabaseHandler(Supplier<CloudantClient> httpClient, String dbNa
public ComponentDatabaseHandler(Supplier<CloudantClient> supplier, String dbName, String attachmentDbName) throws MalformedURLException {
this(supplier, dbName, attachmentDbName, new ComponentModerator(), new ReleaseModerator(), new ProjectModerator());
}

public ComponentDatabaseHandler(Supplier<CloudantClient> supplier, String dbName, String changelogsDbName, String attachmentDbName) throws MalformedURLException {
this(supplier, dbName, attachmentDbName, new ComponentModerator(), new ReleaseModerator(), new ProjectModerator());
DatabaseConnectorCloudant db = new DatabaseConnectorCloudant(supplier, changelogsDbName);
Expand Down Expand Up @@ -488,7 +495,7 @@ public AddDocumentRequestSummary addRelease(Release release, User user) throws S
if(isDuplicate(release)) {
final AddDocumentRequestSummary addDocumentRequestSummary = new AddDocumentRequestSummary()
.setRequestStatus(AddDocumentRequestStatus.DUPLICATE);
List<Release> duplicates = releaseRepository.searchByNameAndVersion(release.getName(), release.getVersion());
List<Release> duplicates = releaseRepository.searchByNameAndVersion(release.getName(), release.getVersion(), true);
if (duplicates.size() == 1) {
duplicates.stream()
.map(Release::getId)
Expand All @@ -497,7 +504,8 @@ public AddDocumentRequestSummary addRelease(Release release, User user) throws S
return addDocumentRequestSummary;
}

if (!isDependenciesExistsInRelease(release)) {
if (!isDependenciesExistsInRelease(release)
|| verifyLinkedPackages(Collections.emptySet(), CommonUtils.nullToEmptySet(release.getPackageIds()), "", user)) {
return new AddDocumentRequestSummary()
.setRequestStatus(AddDocumentRequestStatus.INVALID_INPUT);
}
Expand Down Expand Up @@ -542,7 +550,8 @@ public AddDocumentRequestSummary addRelease(Release release, User user) throws S
updateReleaseDependentFieldsForComponent(component, release);
updateModifiedFields(component, user.getEmail());
componentRepository.update(component);

// update linked packages
updateLinkedPackages(Collections.emptySet(), CommonUtils.nullToEmptySet(release.getPackageIds()), id, user);
sendMailNotificationsForNewRelease(release, user.getEmail());
dbHandlerUtil.addChangeLogs(release, null, user.getEmail(), Operation.CREATE, attachmentConnector,
Lists.newArrayList(), null, null);
Expand Down Expand Up @@ -573,7 +582,7 @@ private boolean isDuplicate(String releaseName, String releaseVersion) {
if (isNullEmptyOrWhitespace(releaseName)) {
return false;
}
List<Release> duplicates = releaseRepository.searchByNameAndVersion(releaseName, releaseVersion);
List<Release> duplicates = releaseRepository.searchByNameAndVersion(releaseName, releaseVersion, true);
return duplicates.size()>0;
}

Expand Down Expand Up @@ -734,6 +743,11 @@ private boolean isDependenciesExistsInRelease(Release release) {
String vendorId = release.getVendorId();
isValidDependentIds = DatabaseHandlerUtil.isAllIdInSetExists(Sets.newHashSet(vendorId), vendorRepository);
}

if (isValidDependentIds && release.isSetPackageIds()) {
Set<String> pacakgeIds = release.getPackageIds();
isValidDependentIds = DatabaseHandlerUtil.isAllIdInSetExists(pacakgeIds, packageRepository);
}
return isValidDependentIds;
}

Expand Down Expand Up @@ -1061,7 +1075,8 @@ public RequestStatus updateRelease(Release release, User user, Iterable<Release.
return RequestStatus.DUPLICATE_ATTACHMENT;
} else if (changeWouldResultInDuplicate(actual, release)) {
return RequestStatus.DUPLICATE;
} else if (!isDependenciesExistsInRelease(release)) {
} else if (!isDependenciesExistsInRelease(release)
|| verifyLinkedPackages(CommonUtils.nullToEmptySet(actual.getPackageIds()), CommonUtils.nullToEmptySet(release.getPackageIds()), release.getId(), user)) {
return RequestStatus.INVALID_INPUT;
} else {
DocumentPermissions<Release> permissions = makePermission(actual, user);
Expand Down Expand Up @@ -1107,6 +1122,8 @@ public RequestStatus updateRelease(Release release, User user, Iterable<Release.
// clean up attachments in database
attachmentConnector.deleteAttachmentDifference(nullToEmptySet(actual.getAttachments()),
nullToEmptySet(release.getAttachments()));
// update linked packages
updateLinkedPackages(CommonUtils.nullToEmptySet(actual.getPackageIds()), CommonUtils.nullToEmptySet(release.getPackageIds()), release.getId(), user);
sendMailNotificationsForReleaseUpdate(release, user.getEmail());
dbHandlerUtil.addChangeLogs(release, actual, user.getEmail(), Operation.UPDATE,
attachmentConnector, referenceDocLogList, null, null);
Expand Down Expand Up @@ -1320,7 +1337,7 @@ public RequestSummary updateReleasesDirectly(Set<Release> releases, User user) t
return RepositoryUtils.doBulk(prepareReleases(releases), user, releaseRepository);
}

public RequestStatus updateReleaseFromAdditionsAndDeletions(Release releaseAdditions, Release releaseDeletions, User user){
public RequestStatus updateReleaseFromAdditionsAndDeletions(Release releaseAdditions, Release releaseDeletions, User user) {

try {
Release release = getRelease(releaseAdditions.getId(), user);
Expand All @@ -1342,6 +1359,74 @@ public Component updateReleaseDependentFieldsForComponentId(String componentId,
return component;
}

/**
* return false if verification is successful
* return true if verification is failed
* verify existence of newly linked packageIds
* verify all newly linked packages are orphan packages
**/
private boolean verifyLinkedPackages(Set<String> currentPackageIds, Set<String> updatedPackageIds, String releaseId, User user) throws SW360Exception {
Set<String> addedPacakgeIds = Sets.difference(updatedPackageIds, currentPackageIds);
PackageService.Iface packageClient = new ThriftClients().makePackageClient();
if (CommonUtils.isNotEmpty(addedPacakgeIds)) {
try {
long addedCount = addedPacakgeIds.size();
List<Package> addedPackages = packageClient.getPackageByIds(addedPacakgeIds);
Predicate<Package> orphanReleaseFilter = pkg -> CommonUtils.isNullEmptyOrWhitespace(pkg.getReleaseId());
Predicate<Package> linkedReleaseFilter = pkg -> releaseId.equals(pkg.getReleaseId());
long orphanCount = addedPackages.stream().filter(orphanReleaseFilter).count();
long linkedCount = addedPackages.stream().filter(linkedReleaseFilter).count();
if (CommonUtils.isNotNullEmptyOrWhitespace(releaseId) && addedCount != orphanCount) {
return addedCount != linkedCount;
} else {
return addedCount != orphanCount;
}
} catch (TException e) {
log.error(String.format("An error occured while updating linked packages of release: %s", releaseId), e.getCause());
return true;
}
}
return false;
}

private void updateLinkedPackages(Set<String> currentPackageIds, Set<String> updatedPackageIds, String releaseId, User user) throws SW360Exception {
Set<String> removedPacakgeIds = Sets.difference(currentPackageIds, updatedPackageIds);
Set<String> addedPacakgeIds = Sets.difference(updatedPackageIds, currentPackageIds);
PackageService.Iface packageClient = new ThriftClients().makePackageClient();
try {
if (CommonUtils.isNotEmpty(removedPacakgeIds)) {
List<Package> removedPackages = packageRepository.get(removedPacakgeIds);
for (Package pkg : removedPackages) {
String relId = pkg.getReleaseId();
// update the package, if it contains linked release Id
if (CommonUtils.isNotNullEmptyOrWhitespace(relId) && releaseId.equals(relId)) {
pkg.unsetReleaseId();
RequestStatus status = packageClient.updatePackage(pkg, user);
log.info(String.format("Unlinked package <%s> from release <%s>, Unlinking status: <%s>", pkg.getId(), releaseId, status.name()));
}
}
}
if (CommonUtils.isNotEmpty(addedPacakgeIds)) {
List<Package> addedPackages = packageClient.getPackageByIds(addedPacakgeIds);
for (Package pkg : addedPackages) {
String relId = pkg.getReleaseId();
// update only orphan packages
if (CommonUtils.isNullEmptyOrWhitespace(relId)) {
pkg.setReleaseId(releaseId);
RequestStatus status = packageClient.updatePackage(pkg, user);
log.info(String.format("Linked package <%s> to release <%s>, Linking status: <%s>", pkg.getId(), releaseId, status.name()));
} else if (!relId.equals(releaseId)) {
log.warn(String.format("Linked-ReleasId <%s> in Package <%s>, and Linked-PackageId <%s> in Release <%s> association is incorrect",
relId, pkg.getId(), pkg.getId(), releaseId));
}
}
}
} catch (TException e) {
log.error(String.format("An error occured while updating linked packages of release: %s", releaseId), e.getCause());
throw new SW360Exception(e.getMessage());
}
}

public void recomputeReleaseDependentFields(Component component, String skipThisReleaseId) {
resetReleaseDependentFields(component);

Expand Down Expand Up @@ -1771,7 +1856,7 @@ public RequestStatus deleteRelease(String id, User user, boolean forceDelete) th
Release release = releaseRepository.get(id);
assertNotNull(release);

if (checkIfInUse(id)) return RequestStatus.IN_USE;
if (release.getPackageIdsSize() > 0 || checkIfInUse(id)) return RequestStatus.IN_USE;

if (makePermission(release, user).isActionAllowed(RequestedAction.DELETE) || forceDelete) {
Component componentBefore = componentRepository.get(release.getComponentId());
Expand Down Expand Up @@ -1968,6 +2053,11 @@ public List<Release> getReleases(Set<String> ids) {
return releaseRepository.makeSummary(SummaryType.SHORT, ids);
}

// return direct release from db, without making summary.
public List<Release> getReleasesWithoutSummary(Set<String> ids) {
return releaseRepository.get(ids);
}

public List<Release> getAccessibleReleases(Set<String> ids, User user) {
return getAccessibleReleaseList(releaseRepository.makeSummary(SummaryType.SHORT, ids), user);
}
Expand Down Expand Up @@ -2192,7 +2282,7 @@ public String getCyclicLinkedReleasePath(Release release, User user) throws TExc
}

public List<Component> searchComponentByNameForExport(String name, boolean caseSensitive) {
return componentRepository.searchByNameForExport(name, caseSensitive);
return componentRepository.searchComponentByName(name, caseSensitive);
}

public Set<Component> getUsingComponents(String releaseId) {
Expand Down
Loading

0 comments on commit d73f31f

Please sign in to comment.