Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(notifications): 622 - Admin / User should not be able to edit… #1159

Merged
merged 7 commits into from
Apr 11, 2024
4 changes: 2 additions & 2 deletions frontend/src/app/modules/core/user/role.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ export class RoleService {

}

public isAtLeastSupervisor(): boolean {
public isSupervisor(): boolean {
return this.hasAccess('supervisor');
}

public isAtLeastUser(): boolean {
public isUser(): boolean {
return this.hasAccess('user');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class ErrorPageComponent {
});

// if user has no sufficient permissions to use this app
if (!roleService.isAtLeastUser() && !roleService.isAdmin()) {
if (!roleService.isUser() && !roleService.isAdmin()) {
this.actionUrl = '';
this.actionLabel = '';
this.showSignOutButton = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class NotificationActionHelperService {
}

public isAtLeastSupervisor(): boolean {
return this.roleService.isAtLeastSupervisor();
return this.roleService.isSupervisor();
}

public showApproveButton({ status, isFromSender } = {} as Notification): boolean {
Expand Down Expand Up @@ -62,9 +62,9 @@ export class NotificationActionHelperService {

public isAuthorizedForButton(action: NotificationAction): boolean {
if (action === NotificationAction.APPROVE || action === NotificationAction.CLOSE) {
return this.roleService.isAtLeastSupervisor();
return this.roleService.isSupervisor();
} else {
return this.roleService.isAtLeastUser();
return this.roleService.isUser();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,3 @@ export class NotificationMenuActionsAssembler {
];
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export class TableComponent {
icon: 'edit',
action: (data: Record<string, unknown>) => this.editClicked.emit(data),
condition: data => this.isEditable(data),
isAuthorized: this.roleService.isSupervisor(),
};

const menuActionsConfig = menuActions ? [ viewDetailsMenuAction, editDetailsMenuAction, ...menuActions ] : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export class NotificationService {

public editNotification(notificationId: string, title: string, receiverBpn: string, severity: string, targetDate: string, description: string, affectedPartIds: string[]): Observable<void> {
const requestUrl = this.notificationUrl();
const body = { title, receiverBpn: receiverBpn, severity, targetDate, description, affectedPartIds: affectedPartIds };
const body = { title: title === "" ? null: title, receiverBpn: receiverBpn, severity, targetDate, description, affectedPartIds: affectedPartIds };
return this.apiService.put<void>(`${ requestUrl }/${ notificationId }/edit`, body);
}

Expand Down
14 changes: 7 additions & 7 deletions frontend/src/assets/locales/de/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,24 +211,24 @@
"bpnLabel": "BPN",
"bpnDescription": "Bitte geben Sie die Empfänger BPN an.",
"restoreItem": "Zuletzt gelöschtes Produkt wiederherstellen?",
"titleDescription": "Wählen Sie einen kurzen Titel",
"titleDescription": "Wählen Sie einen kurzen Titel.",
"titleLabel": "Titel",
"typeDescription": "Typ des Qualitätsthemas",
"typeDescription": "Typ des Qualitätsthemas.",
"typeLabel": "Type",
"textAreaLabel": "Beschreibung",
"targetDateLabel": "Rückmeldedatum",
"cancel": "ABBRUCH",
"submit": "ZUR WARTESCHLANGE HINZUFÜGEN",
"severity": "Gefahrenstufe",
"severityDescription": "Wählen Sie die Gefahrenstufe für das vorliegende Problem",
"severityDescription": "Wählen Sie die Gefahrenstufe für das vorliegende Problem.",
"serverError": "Serverfehler:",
"remove": "Auswahl entfernen",
"add": "Auswahl hinzufügen",
"modifyNotAllowed": "Erfordert mindestens eine Selektion innerhalb der Tabelle",
"textAreaDescription": "",
"saveNotAllowed": "Erfordert eine valide Eingabe im Formular",
"saveSuccess": "Qualitätsthema wurde erfolgreich aktualisiert",
"saveError": "Bei der Aktualisierung des Qualitätsthemas ist ein Fehler aufgetreten"
"textAreaDescription": "Beschreiben Sie das Problem.",
"saveNotAllowed": "Erfordert eine valide Eingabe im Formular.",
"saveSuccess": "Qualitätsthema wurde erfolgreich aktualisiert.",
"saveError": "Bei der Aktualisierung des Qualitätsthemas ist ein Fehler aufgetreten."
},
"editNotification": {
"saveButton": "Speichern",
Expand Down
32 changes: 16 additions & 16 deletions frontend/src/assets/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
},
"pageTitle": {
"dashboard": "Dashboard",
"parts": "My Parts",
"otherParts": "Other Parts",
"parts": "My parts",
"otherParts": "Other parts",
"about": "About Catena-X Open-Source Traceability",
"relations": "Part Relations",
"relations": "Part relations",
"admin": "Administration Catena-X",
"alerts": "Quality Topics"
"alerts": "Quality topics"
},
"layout": {
"nav": {
Expand Down Expand Up @@ -200,18 +200,18 @@

},
"requestNotification": {
"investigation": "Quality Investigation",
"alert": "Quality Alert",
"header": "Create Notification",
"editNotificationHeader": "Edit Notification",
"investigation": "Quality investigation",
"alert": "Quality alert",
"header": "Create notification",
"editNotificationHeader": "Edit notification",
"affectedParts": "Affected parts",
"unAffectedParts": "Available parts",
"partDescription": "You selected the following parts:",
"targetDateDescription": "Please specify the deadline by which you expect a response.",
"titleLabel": "Title",
"titleDescription": "Specify a short title",
"titleDescription": "Specify a short title.",
"targetDateLabel": "Deadline",
"typeDescription": "Type of Quality Topic",
"typeDescription": "Type of quality topic.",
"typeLabel": "Type",
"bpnLabel": "BPN",
"bpnDescription": "Please specify the receiver BPN.",
Expand All @@ -220,15 +220,15 @@
"cancel": "CANCEL",
"submit": "ADD TO QUEUE",
"severity": "Severity",
"severityDescription": "Select the severity for the problem at hand",
"severityDescription": "Select the severity for the problem at hand.",
"serverError": "Server error:",
"remove": "Remove selection",
"add": "Add selection",
"modifyNotAllowed": "Requires atleast one selection in the parts table",
"textAreaDescription": "",
"saveNotAllowed": "Requires valid form input",
"saveSuccess": "Quality topic was updated successfully",
"saveError": "An error occurred while updating the quality topic"
"modifyNotAllowed": "Requires at least one selection in the parts table.",
"textAreaDescription": "Describe the quality issue.",
"saveNotAllowed": "Requires valid form input.",
"saveSuccess": "Quality topic was updated successfully.",
"saveError": "An error occurred while updating the quality topic."
},
"editNotification": {
"saveButton": "Save",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@

package org.eclipse.tractusx.traceability.bpn.domain.model;

public record BpnEdcMapping(String bpn, String url) {

public String getBpn() {
return bpn;
}

public String getUrl() {
return url;
}
public record BpnEdcMapping(String bpn, String url, String manufacturerName) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

import java.util.List;
import java.util.Map;
import java.util.Optional;

public interface BpnRepository {

Expand All @@ -43,4 +42,6 @@ public interface BpnRepository {

void updateManufacturers(Map<String, String> bpns);

List<BpnEdcMapping> findAllByIdIn(List<String> bpns);

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@
import org.eclipse.tractusx.traceability.bpn.domain.model.BpnNotFoundException;
import org.eclipse.tractusx.traceability.bpn.domain.service.BpnRepository;
import org.eclipse.tractusx.traceability.bpn.infrastructure.model.BpnEntity;

import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Optional;

@Slf4j
@Component
Expand Down Expand Up @@ -89,6 +87,11 @@ public void updateManufacturers(Map<String, String> bpns) {
}
}

@Override
public List<BpnEdcMapping> findAllByIdIn(List<String> bpns) {
return this.toDTOList(repository.findAllById(bpns));
}

@Override
public List<BpnEdcMapping> saveAll(List<BpnMappingRequest> bpnEdcMappings) {
List<BpnEntity> bpnEdcMappingEntities = bpnEdcMappings.stream().map(this::toEntity).toList();
Expand All @@ -98,10 +101,15 @@ public List<BpnEdcMapping> saveAll(List<BpnMappingRequest> bpnEdcMappings) {
private BpnEdcMapping toDTO(BpnEntity entity) {
return new BpnEdcMapping(
entity.getManufacturerId(),
entity.getUrl()
entity.getUrl(),
entity.getManufacturerName()
);
}

private List<BpnEdcMapping> toDTOList(List<BpnEntity> bpnEntities) {
return bpnEntities.stream().map(this::toDTO).toList();
}

private BpnEntity toEntity(BpnMappingRequest bpnEdcMappings) {
return BpnEntity.builder()
.manufacturerId(bpnEdcMappings.bpn())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.tractusx.traceability.assets.domain.base.model.AssetBase;
import org.eclipse.tractusx.traceability.bpn.domain.model.BpnEdcMapping;
import org.eclipse.tractusx.traceability.common.model.BPN;
import org.eclipse.tractusx.traceability.notification.domain.notification.exception.InvestigationIllegalUpdate;
import org.eclipse.tractusx.traceability.notification.domain.notification.exception.InvestigationStatusTransitionNotAllowed;
Expand Down Expand Up @@ -75,15 +76,15 @@ public static Notification startNotification(String title, Instant createDate, B
.build();
}

public void clearNotifications(){
public void clearNotifications() {
notifications = new ArrayList<>();
}
public void createInitialNotifications(List<AssetBase> affectedParts, BPN applicationBPN, EditNotification editNotification) {

public void createInitialNotifications(List<AssetBase> affectedParts, BPN applicationBPN, EditNotification editNotification, List<BpnEdcMapping> bpnEdcMappings) {

if (editNotification.getReceiverBpn() != null) {
Map.Entry<String, List<AssetBase>> receiverAssetsMap = new AbstractMap.SimpleEntry<>(editNotification.getReceiverBpn(), affectedParts);

Optional<String> sentToName = bpnEdcMappings.stream().filter(bpnEdcMapping -> bpnEdcMapping.bpn().equals(editNotification.getReceiverBpn())).findFirst().map(BpnEdcMapping::manufacturerName);
NotificationMessage notificationMessage = NotificationMessage.create(
applicationBPN,
editNotification.getReceiverBpn(),
Expand All @@ -93,7 +94,7 @@ public void createInitialNotifications(List<AssetBase> affectedParts, BPN applic
this.notificationType,
receiverAssetsMap,
applicationBPN.value(),
editNotification.getReceiverBpn());
sentToName.orElse(null));

this.addNotificationMessage(notificationMessage);

Expand All @@ -104,17 +105,18 @@ public void createInitialNotifications(List<AssetBase> affectedParts, BPN applic
.entrySet()
.stream()
.map(receiverAssetsMapEntry -> {
String receiver = receiverAssetsMapEntry.getKey();
String sentToBPN = receiverAssetsMapEntry.getKey();
Optional<String> sentToName = bpnEdcMappings.stream().filter(bpnEdcMapping -> bpnEdcMapping.bpn().equals(sentToBPN)).findFirst().map(BpnEdcMapping::manufacturerName);
return NotificationMessage.create(
applicationBPN,
receiver,
sentToBPN,
editNotification.getDescription(),
editNotification.getTargetDate(),
editNotification.getSeverity(),
this.notificationType,
receiverAssetsMapEntry,
applicationBPN.value(),
editNotification.getReceiverBpn());
sentToName.orElse(null));
})
.forEach(this::addNotificationMessage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import lombok.extern.slf4j.Slf4j;
import org.eclipse.tractusx.traceability.assets.domain.asbuilt.repository.AssetAsBuiltRepository;
import org.eclipse.tractusx.traceability.assets.domain.base.model.AssetBase;
import org.eclipse.tractusx.traceability.bpn.domain.model.BpnEdcMapping;
import org.eclipse.tractusx.traceability.bpn.domain.service.BpnRepository;
import org.eclipse.tractusx.traceability.common.model.BPN;
import org.eclipse.tractusx.traceability.common.model.PageResult;
import org.eclipse.tractusx.traceability.common.model.SearchCriteria;
Expand Down Expand Up @@ -53,6 +55,7 @@ public abstract class AbstractNotificationService implements NotificationService
private final TraceabilityProperties traceabilityProperties;
private final NotificationPublisherService notificationPublisherService;
private final AssetAsBuiltRepository assetAsBuiltRepository;
private final BpnRepository bpnRepository;

private static final List<String> SUPPORTED_ENUM_FIELDS = List.of("status", "side", "messages_severity", "type");

Expand Down Expand Up @@ -109,12 +112,14 @@ public void updateStatusTransition(Long notificationId, NotificationStatus notif
public void editNotification(EditNotification editNotification) {
Notification notification = loadOrNotFoundException(new NotificationId(editNotification.getId()));
List<AssetBase> affectedParts = assetAsBuiltRepository.getAssetsById(editNotification.getAffectedPartIds());
List<BpnEdcMapping> bpnMappings = bpnRepository.findAllByIdIn(affectedParts.stream().map(AssetBase::getManufacturerId).toList());

List<String> oldMessageIds =
notification.getNotifications().stream().map(NotificationMessage::getId).toList();

getNotificationRepository().deleteByIdIn(oldMessageIds);
notification.clearNotifications();
notification.createInitialNotifications(affectedParts, traceabilityProperties.getBpn(), editNotification);
notification.createInitialNotifications(affectedParts, traceabilityProperties.getBpn(), editNotification, bpnMappings);
if (editNotification.getReceiverBpn() != null) {
notification.setBpn(BPN.of(editNotification.getReceiverBpn()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,23 @@
package org.eclipse.tractusx.traceability.notification.domain.notification.service;

import org.eclipse.tractusx.traceability.assets.domain.asbuilt.repository.AssetAsBuiltRepository;
import org.eclipse.tractusx.traceability.bpn.domain.service.BpnRepository;
import org.eclipse.tractusx.traceability.common.properties.TraceabilityProperties;
import org.eclipse.tractusx.traceability.notification.domain.notification.exception.NotificationNotFoundException;
import org.eclipse.tractusx.traceability.notification.domain.notification.repository.NotificationRepository;
import org.eclipse.tractusx.traceability.notification.domain.base.service.AbstractNotificationService;
import org.eclipse.tractusx.traceability.notification.domain.base.service.NotificationPublisherService;
import org.eclipse.tractusx.traceability.notification.domain.notification.exception.NotificationNotFoundException;
import org.eclipse.tractusx.traceability.notification.domain.notification.repository.NotificationRepository;
import org.springframework.stereotype.Service;

@Service("notificationServiceImpl")
public class NotificationServiceImpl extends AbstractNotificationService {


private final NotificationRepository notificationRepository;


public NotificationServiceImpl(TraceabilityProperties traceabilityProperties,
NotificationRepository alertRepository,
NotificationPublisherService notificationPublisherService,
AssetAsBuiltRepository assetAsBuiltRepository) {
super(traceabilityProperties, notificationPublisherService, assetAsBuiltRepository);
AssetAsBuiltRepository assetAsBuiltRepository, BpnRepository bpnRepository) {
super(traceabilityProperties, notificationPublisherService, assetAsBuiltRepository, bpnRepository);
this.notificationRepository = alertRepository;

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

import org.eclipse.tractusx.traceability.bpn.domain.model.BpnEdcMapping;
import org.eclipse.tractusx.traceability.bpn.domain.service.BpnRepository;
import org.eclipse.tractusx.traceability.common.properties.EdcProperties;
import org.eclipse.tractusx.traceability.discovery.domain.model.Discovery;
import org.eclipse.tractusx.traceability.discovery.domain.repository.DiscoveryRepository;
import org.eclipse.tractusx.traceability.common.properties.EdcProperties;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
Expand Down Expand Up @@ -56,7 +56,7 @@ void testGetDiscoveryByBPNSuccessfulBoth() {

// given
Discovery discoveryByService = Discovery.builder().receiverUrls(List.of("receiver2.de")).senderUrl("sender2.de").build();
BpnEdcMapping bpnEdcMapping = new BpnEdcMapping("bpn", "receiver.de");
BpnEdcMapping bpnEdcMapping = new BpnEdcMapping("bpn", "receiver.de", "name");
when(bpnRepository.existsWhereUrlNotNull(any())).thenReturn(true);
when(bpnRepository.findByIdOrThrowNotFoundException(any())).thenReturn(bpnEdcMapping);
when(discoveryRepository.retrieveDiscoveryByFinderAndEdcDiscoveryService(any())).thenReturn(Optional.of(discoveryByService));
Expand All @@ -72,7 +72,7 @@ void testGetDiscoveryByBPNSuccessfulBoth() {
void givenTrailingUrl_whenTestGetDiscoveryByBPN_thenSuccessfulBoth() {
// given
Discovery discoveryByService = Discovery.builder().receiverUrls(List.of("receiver2.de/")).senderUrl("sender2.de").build();
BpnEdcMapping bpnEdcMapping = new BpnEdcMapping("bpn", "receiver.de");
BpnEdcMapping bpnEdcMapping = new BpnEdcMapping("bpn", "receiver.de", "name");
when(bpnRepository.existsWhereUrlNotNull(any())).thenReturn(true);
when(bpnRepository.findByIdOrThrowNotFoundException(any())).thenReturn(bpnEdcMapping);
when(discoveryRepository.retrieveDiscoveryByFinderAndEdcDiscoveryService(any())).thenReturn(Optional.of(discoveryByService));
Expand Down