Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Changelog
All notable changes to this project will be documented in this file.

## [8.8.1](https://github.com/Backbase/stream-services/compare/8.8.0...8.8.1)
## [9.1.0](https://github.com/Backbase/stream-services/compare/9.0.0...9.1.0)
### Changed
- added partitioning to a batch permission update request
### Changed
- fix update data group items request to access-control (use externalDataItemIds instead of internal)

## [9.0.0](https://github.com/Backbase/stream-services/compare/8.8.0...9.0.0)
### Changed
- Upgraded to bb bom 2025.10.2

## [8.8.0](https://github.com/Backbase/stream-services/compare/8.7.0...8.8.0)
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>com.backbase.stream</groupId>
<artifactId>stream-services</artifactId>
<version>8.11.1</version>
<version>9.1.0</version>

<packaging>pom</packaging>
<name>Stream :: Services</name>
Expand Down
2 changes: 1 addition & 1 deletion stream-access-control/access-control-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.backbase.stream</groupId>
<artifactId>stream-access-control</artifactId>
<version>8.11.1</version>
<version>9.1.0</version>
</parent>

<artifactId>access-control-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.backbase.accesscontrol.permissioncheck.api.service.v1.PermissionCheckApi;
import com.backbase.accesscontrol.serviceagreement.api.service.v1.ServiceAgreementApi;
import com.backbase.accesscontrol.usercontext.api.service.v1.UserContextApi;
import com.backbase.dbs.arrangement.api.service.v3.ArrangementsApi;
import com.backbase.dbs.user.api.service.v2.IdentityManagementApi;
import com.backbase.dbs.user.api.service.v2.UserManagementApi;
import com.backbase.dbs.user.profile.api.service.v2.UserProfileManagementApi;
Expand Down Expand Up @@ -82,6 +83,7 @@ public CustomerAccessGroupService customerAccessGroupService(CustomerAccessGroup
@Bean
public AccessGroupService accessGroupService(
UserManagementApi usersApi,
ArrangementsApi arrangementsApi,
DeletionProperties configurationProperties,
BatchResponseUtils batchResponseUtils,
AccessControlConfigurationProperties accessControlConfigurationProperties,
Expand All @@ -95,7 +97,7 @@ public AccessGroupService accessGroupService(
AssignPermissionsApi assignPermissionsApi,
com.backbase.accesscontrol.assignpermissions.api.integration.v1.AssignPermissionsApi assignPermissionsIntegrationApi,
UserContextApi userContextApi) {
return new AccessGroupService(usersApi, batchResponseUtils, configurationProperties,
return new AccessGroupService(usersApi, arrangementsApi, batchResponseUtils, configurationProperties,
accessControlConfigurationProperties,
permissionCheckApi, dataGroupServiceApi, dataGroupIntegrationApi, functionGroupServiceApi,
functionGroupIntegrationApi,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
import com.backbase.accesscontrol.serviceagreement.api.service.v1.model.ServiceAgreementParticipants;
import com.backbase.accesscontrol.serviceagreement.api.service.v1.model.ServiceAgreementUpdateRequest;
import com.backbase.accesscontrol.usercontext.api.service.v1.UserContextApi;
import com.backbase.dbs.arrangement.api.service.v3.ArrangementsApi;
import com.backbase.dbs.arrangement.api.service.v3.model.ArrangementItem;
import com.backbase.dbs.arrangement.api.service.v3.model.ArrangementSearchesListResponse;
import com.backbase.dbs.arrangement.api.service.v3.model.ArrangementsSearchesPostRequest;
import com.backbase.dbs.user.api.service.v2.UserManagementApi;
import com.backbase.dbs.user.api.service.v2.model.GetUser;
import com.backbase.stream.configuration.AccessControlConfigurationProperties;
Expand Down Expand Up @@ -78,6 +82,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -126,6 +131,8 @@ public class AccessGroupService {
@NonNull
private final UserManagementApi usersApi;
@NonNull
private final ArrangementsApi arrangementsApiService;
@NonNull
private final BatchResponseUtils batchResponseUtils;
@NonNull
private final DeletionProperties deletionProperties;
Expand Down Expand Up @@ -195,7 +202,6 @@ public Mono<ServiceAgreement> getServiceAgreementByExternalId(String externalId)
}

/**
*
* @param streamTask
* @param serviceAgreement
* @return Service Agreement
Expand Down Expand Up @@ -971,65 +977,105 @@ public Mono<ProductGroupTask> setupProductGroups(ProductGroupTask streamTask) {
public Mono<BatchProductGroupTask> updateExistingDataGroupsBatch(BatchProductGroupTask task,
List<DataGroup> existingDataGroups, List<BaseProductGroup> productGroups) {
List<DataItemBatchUpdate> batchUpdateRequest = new ArrayList<>();
final Set<String> affectedArrangements = Stream.concat(
productGroups.stream().map(StreamUtils::getInternalProductIds).flatMap(List::stream),
productGroups.stream().map(BaseProductGroup::getCustomDataGroupItems).flatMap(List::stream)
.map(CustomDataGroupItem::getInternalId))
.collect(Collectors.toSet());
if (task.getIngestionMode().isDataGroupsReplaceEnabled()) {
final Map<String, String> affectedArrangementsInternalToExternalIds = Stream.concat(
productGroups.stream()
.flatMap(StreamUtils::getAllProducts)
.filter(Objects::nonNull)
.map(p -> new java.util.AbstractMap.SimpleEntry<>(p.getInternalId(), p.getExternalId())),
productGroups.stream()
.map(BaseProductGroup::getCustomDataGroupItems)
.filter(Objects::nonNull)
.flatMap(List::stream)
.map(i -> new java.util.AbstractMap.SimpleEntry<>(i.getInternalId(), i.getExternalId())))
.filter(e -> e.getKey() != null && e.getValue() != null)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a));

Mono<Map<String, String>> affectedArrangementsMono =
// if REPLACE mode, existing products (not sent in the request) also need to be added to the set of affected arrangements.
affectedArrangements.addAll(existingDataGroups.stream()
.map(DataGroup::getItems)
.flatMap(Set::stream)
.collect(Collectors.toSet())
);
}

existingDataGroups.forEach(dbsDataGroup -> {
// get group matching DBS one.
Optional<BaseProductGroup> pg = productGroups.stream()
.filter(it -> isEquals(it, dbsDataGroup))
.findFirst();
Set<String> arrangementsToAdd = new HashSet<>();
Set<String> arrangementsToRemove = new HashSet<>();
affectedArrangements.forEach(arrangement -> pg.ifPresent(p -> {
boolean shouldBeInGroup = StreamUtils.getInternalProductIds(pg.get()).contains(arrangement) ||
pg.get().getCustomDataGroupItems().stream().map(CustomDataGroupItem::getInternalId)
.anyMatch(arrangement::equals);
if (!dbsDataGroup.getItems().contains(arrangement) && shouldBeInGroup) {
// ADD.
log.debug("Arrangement item {} to be added to Data Group {}", arrangement, dbsDataGroup.getName());
arrangementsToAdd.add(arrangement);
task.getIngestionMode().isDataGroupsReplaceEnabled()
? Mono.defer(() -> {
Set<String> existingInternalIds = existingDataGroups.stream()
.map(DataGroup::getItems)
.filter(Objects::nonNull)
.flatMap(Set::stream)
.collect(Collectors.toSet());
if (existingInternalIds.isEmpty()) {
return Mono.just(affectedArrangementsInternalToExternalIds);
}
// Fetch external ids for existing arrangements (used to call access-control api to add/remove data group items).
return arrangementsApiService.postSearchArrangements(
new ArrangementsSearchesPostRequest()
.arrangementIds(existingInternalIds)
.size(existingInternalIds.size()))
.map(ArrangementSearchesListResponse::getArrangementElements)
.defaultIfEmpty(Collections.emptyList())
.map(items -> {
Map<String, String> merged = new HashMap<>(affectedArrangementsInternalToExternalIds);
items.forEach(item -> {
if (existingInternalIds.contains(item.getId())) {
merged.putIfAbsent(item.getId(), item.getExternalArrangementId());
}
});
return merged;
});
}
) : Mono.just(affectedArrangementsInternalToExternalIds);

return affectedArrangementsMono.flatMap(affectedArrangements -> {
existingDataGroups.forEach(dbsDataGroup -> {
// get group matching DBS one.
Optional<BaseProductGroup> pg = productGroups.stream()
.filter(it -> isEquals(it, dbsDataGroup))
.findFirst();
// it should be external data item ids (both add and remove)
Set<String> arrangementsToAdd = new HashSet<>();
Set<String> arrangementsToRemove = new HashSet<>();
affectedArrangements.forEach((internalId, externalId) -> {
boolean shouldBeInGroup =
StreamUtils.getInternalProductIds(pg.get()).contains(internalId) ||
pg.get().getCustomDataGroupItems().stream()
.map(CustomDataGroupItem::getInternalId)
.anyMatch(internalId::equals);
if (dbsDataGroup.getItems() != null && !dbsDataGroup.getItems().contains(internalId) && shouldBeInGroup) {
// ADD.
log.debug("Arrangement item {} with External Id {} to be added to Data Group {}",
internalId, externalId, dbsDataGroup.getName());
arrangementsToAdd.add(externalId);
}
if (dbsDataGroup.getItems().contains(internalId) && !shouldBeInGroup) {
// REMOVE.
log.debug("Arrangement item {} with External Id {} to be removed from Data Group {}",
internalId, externalId, dbsDataGroup.getName());
arrangementsToRemove.add(externalId);
}
});
if (!CollectionUtils.isEmpty(arrangementsToAdd)) {
batchUpdateRequest.add(new DataItemBatchUpdate()
.dataGroupIdentifier(new DataGroupNameIdentifier()
.name(dbsDataGroup.getName())
.dataGroupType(dbsDataGroup.getType())
.externalServiceAgreementId(task.getData().getServiceAgreement().getExternalId()))
.action(Action.ADD)
.dataItems(arrangementsToAdd)
);
}
if (dbsDataGroup.getItems().contains(arrangement) && !shouldBeInGroup) {
// remove.
log.debug("Arrangement item {} to be removed from Data Group {}", arrangement,
dbsDataGroup.getName());
arrangementsToRemove.add(arrangement);
if (!CollectionUtils.isEmpty(arrangementsToRemove)) {
batchUpdateRequest.add(new DataItemBatchUpdate()
.dataGroupIdentifier(new DataGroupNameIdentifier()
.name(dbsDataGroup.getName())
.dataGroupType(dbsDataGroup.getType())
.externalServiceAgreementId(task.getData().getServiceAgreement().getExternalId()))
.action(Action.REMOVE)
.dataItems(arrangementsToRemove)
);
}
}));
if (!CollectionUtils.isEmpty(arrangementsToAdd)) {
batchUpdateRequest.add(new DataItemBatchUpdate()
.dataGroupIdentifier(new DataGroupNameIdentifier()
.name(dbsDataGroup.getName())
.dataGroupType(dbsDataGroup.getType())
.externalServiceAgreementId(task.getData().getServiceAgreement().getExternalId()))
.action(Action.ADD)
.dataItems(arrangementsToAdd)
);
}
if (!CollectionUtils.isEmpty(arrangementsToRemove)) {
batchUpdateRequest.add(new DataItemBatchUpdate()
.dataGroupIdentifier(new DataGroupNameIdentifier()
.name(dbsDataGroup.getName())
.dataGroupType(dbsDataGroup.getType())
.externalServiceAgreementId(task.getData().getServiceAgreement().getExternalId()))
.action(Action.REMOVE)
.dataItems(arrangementsToRemove)
);
});
if (CollectionUtils.isEmpty(batchUpdateRequest)) {
log.debug("All Product Groups are up to date.");
task.info(ACCESS_GROUP, "update", "SUCCESS", prettyPrintProductGroupNames(task), null,
"All Product Groups are up to date.");
return Mono.just(task);
}
});
if (!CollectionUtils.isEmpty(batchUpdateRequest)) {
return updateDataGroupItems(batchUpdateRequest)
.doOnNext(response ->
task.info(ACCESS_GROUP, "update", response.getStatus().toString(), response.getResourceId(), null,
Expand All @@ -1045,12 +1091,7 @@ public Mono<BatchProductGroupTask> updateExistingDataGroupsBatch(BatchProductGro
})
.collectList()
.thenReturn(task);
} else {
log.debug("All Product Groups are up to date.");
task.info(ACCESS_GROUP, "update", "SUCCESS", prettyPrintProductGroupNames(task), null,
"All Product Groups are up to date.");
return Mono.just(task);
}
});
}

@NotNull
Expand Down
Loading