Skip to content
Snippets Groups Projects
Commit d76d8e05 authored by OZGCloud's avatar OZGCloud
Browse files

Merge pull request 'OZG-6858-Zugriffsberechtigung' (#35) from...

Merge pull request 'OZG-6858-Zugriffsberechtigung' (#35) from OZG-6858-Zugriffsberechtigung into master

Reviewed-on: https://git.ozg-sh.de/ozgcloud-app/nachrichten-manager/pulls/35


Reviewed-by: default avatarOZGCloud <ozgcloud@mgm-tp.com>
parents 84ab6055 7f5b95c3
No related branches found
No related tags found
No related merge requests found
Showing
with 166 additions and 9 deletions
......@@ -15,8 +15,12 @@ public class NachrichtenManagerConfiguration {
public static final String OZG_CLOUD_COMMAND_SERVICE_NAME = "nachrichten_OzgCloudCommandService";
public static final String NACHRICHTEN_VORGANG_SERVICE = "nachrichten_vorgangService";
public static final String NACHRICHTEN_VORGANG_REMOTE_SERVICE = "nachrichten_vorgangRemoteService";
@GrpcClient("command-manager")
public static final String GRPC_VORGANG_MANAGER_NAME = "vorgang-manager";
public static final String GRPC_COMMAND_MANAGER_NAME = "command-manager";
@GrpcClient(GRPC_COMMAND_MANAGER_NAME)
private CommandServiceGrpc.CommandServiceBlockingStub commandServiceStub;
@Bean(OZG_CLOUD_COMMAND_SERVICE_NAME)
......
......@@ -33,11 +33,14 @@ import java.util.stream.Stream;
import jakarta.annotation.PostConstruct;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.opensaml.saml.saml2.core.Response;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import de.ozgcloud.apilib.common.datatypes.GenericId;
import de.ozgcloud.apilib.common.errorhandling.NotFoundException;
import de.ozgcloud.nachrichten.NachrichtenManagerConfiguration;
import de.ozgcloud.nachrichten.NachrichtenManagerProperties;
import de.ozgcloud.nachrichten.common.vorgang.Vorgang;
......@@ -136,6 +139,7 @@ public class AntragraumService {
public String sendRueckfrageAnswer(String samlToken, String rueckfrageId, PostfachNachricht nachricht) {
verifyToken(samlToken);
verifyPostfachId(samlToken, nachricht);
return postfachNachrichtService.persistAnswer(rueckfrageId, nachricht);
}
......@@ -153,7 +157,11 @@ public class AntragraumService {
public PostfachNachricht getRueckfrage(String samlToken, String id) {
verifyToken(samlToken);
return nachrichtMapper.fromMapToPostfachMail(postfachNachrichtService.getById(id));
var nachricht = nachrichtMapper.fromMapToPostfachMail(postfachNachrichtService.getById(id));
verifyPostfachId(samlToken, nachricht);
return nachricht;
}
void verifyToken(String token) {
......@@ -163,6 +171,15 @@ public class AntragraumService {
}
}
void verifyPostfachId(String samlToken, PostfachNachricht nachricht) {
var vorgang = vorgangService.getVorgang(nachricht.getVorgangId());
if (!StringUtils.equals(vorgang.getPostfachId(), getPostfachId(samlToken))) {
LOG.info("PostfachId in token is not matching postfachId in vorgang.");
throw new NotFoundException(GenericId.from(nachricht.getId()), "PostfachNachricht");
}
}
public boolean isAccessible(String samlToken, String trustLevel) {
return getTrustLevel(samlToken).getIntValue() >= TrustLevel.fromString(trustLevel).getIntValue();
}
......
package de.ozgcloud.nachrichten.common.vorgang;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress;
import de.ozgcloud.vorgang.vorgang.GrpcVorgangHead;
import de.ozgcloud.vorgang.vorgang.GrpcVorgangWithEingang;
@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN)
interface NachrichtenVorgangMapper {
@Mapping(target = "trustLevel", source = "vorgangWithEingang.header.serviceKonto.trustLevel")
@Mapping(target = "postfachId", expression = "java(getPostfachId(vorgangWithEingang.getHeader()))")
Vorgang fromVorgangWithEingang(GrpcVorgangWithEingang vorgangWithEingang);
}
default String getPostfachId(GrpcVorgangHead head) {
return head.getServiceKonto().getPostfachAddressesList().stream()
.map(this::getPostfachId).findFirst()
.orElse(StringUtils.EMPTY);
}
default String getPostfachId(GrpcPostfachAddress address) {
return address.getIdentifier().getPropertyList().stream()
.filter(prop -> Vorgang.POSTFACH_ID_FIELD.equals(prop.getName()))
.map(prop -> prop.getValue(0))
.findFirst()
.orElse(StringUtils.EMPTY);
}
}
\ No newline at end of file
......@@ -7,9 +7,12 @@ import lombok.Getter;
@Builder
public class Vorgang {
public static final String POSTFACH_ID_FIELD = "postfachId";
private String id;
private String name;
private String nummer;
private String trustLevel;
private String postfachId;
}
\ No newline at end of file
......@@ -31,6 +31,7 @@ import java.util.stream.StreamSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.ozgcloud.nachrichten.NachrichtenManagerConfiguration;
import de.ozgcloud.nachrichten.common.grpc.NachrichtenCallContextAttachingInterceptor;
import de.ozgcloud.nachrichten.postfach.FindVorgangIterator;
import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangRequest;
......@@ -38,10 +39,10 @@ import de.ozgcloud.vorgang.vorgang.GrpcVorgangHeader;
import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
import net.devh.boot.grpc.client.inject.GrpcClient;
@Service("findVorgangRemoteService")
@Service(NachrichtenManagerConfiguration.NACHRICHTEN_VORGANG_REMOTE_SERVICE)
class VorgangRemoteService {
@GrpcClient("vorgang-manager")
@GrpcClient(NachrichtenManagerConfiguration.GRPC_VORGANG_MANAGER_NAME)
private VorgangServiceBlockingStub vorgangServiceStub;
@Autowired
......
......@@ -12,7 +12,7 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class VorgangService {
@Qualifier("findVorgangRemoteService")
@Qualifier(NachrichtenManagerConfiguration.NACHRICHTEN_VORGANG_REMOTE_SERVICE)
private final VorgangRemoteService remoteService;
public Stream<String> findVorgangIds(String servicekontoType, String postfachId) {
......
package de.ozgcloud.nachrichten.antragraum;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
......@@ -20,7 +21,9 @@ import org.mockito.Mock;
import org.mockito.Spy;
import org.opensaml.saml.saml2.core.Response;
import de.ozgcloud.apilib.common.errorhandling.NotFoundException;
import de.ozgcloud.nachrichten.NachrichtenManagerProperties;
import de.ozgcloud.nachrichten.common.vorgang.GrpcPostfachAddressTestFactory;
import de.ozgcloud.nachrichten.common.vorgang.GrpcServiceKontoTestFactory;
import de.ozgcloud.nachrichten.common.vorgang.Vorgang;
import de.ozgcloud.nachrichten.common.vorgang.VorgangService;
......@@ -29,6 +32,7 @@ import de.ozgcloud.nachrichten.postfach.PersistPostfachNachrichtService;
import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
import de.ozgcloud.nachrichten.postfach.PostfachNachrichtMapper;
import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
class AntragraumServiceTest {
......@@ -301,6 +305,7 @@ class AntragraumServiceTest {
@BeforeEach
void mock() {
doNothing().when(service).verifyToken(any());
doNothing().when(service).verifyPostfachId(any(), any());
}
@Test
......@@ -316,6 +321,13 @@ class AntragraumServiceTest {
verify(postfachNachrichtService).persistAnswer(RUECKFRAGE_ID, NACHRICHT);
}
@Test
void shouldVerifyPostfachId() {
service.sendRueckfrageAnswer(SAML_TOKEN, RUECKFRAGE_ID, NACHRICHT);
verify(service).verifyPostfachId(SAML_TOKEN, NACHRICHT);
}
}
@Nested
......@@ -390,6 +402,7 @@ class AntragraumServiceTest {
when(nachrichtMapper.fromMapToPostfachMail(any())).thenReturn(nachricht);
doNothing().when(service).verifyToken(any());
doNothing().when(service).verifyPostfachId(any(), any());
}
@Test
......@@ -420,11 +433,66 @@ class AntragraumServiceTest {
assertThat(rueckfrage).isEqualTo(nachricht);
}
@Test
void shouldCallVerifyPostfachId() {
getRueckfrage();
verify(service).verifyPostfachId(samlToken, nachricht);
}
private PostfachNachricht getRueckfrage() {
return service.getRueckfrage(samlToken, RueckfrageHeadTestFactory.ID);
}
}
@DisplayName("Verify postfachId")
@Nested
class TestVerifyPostfachId {
private static final String SAML_TOKEN = "TOKEN";
private static final PostfachNachricht POSTFACH_NACHRICHT = PostfachNachrichtTestFactory.create();
@BeforeEach
void mock() {
when(vorgangService.getVorgang(any())).thenReturn(VorgangTestFactory.create());
}
@Test
void shouldCallVorgangService() {
doReturn(GrpcPostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE).when(service).getPostfachId(any());
service.verifyPostfachId(SAML_TOKEN, POSTFACH_NACHRICHT);
verify(vorgangService).getVorgang(MessageTestFactory.VORGANG_ID);
}
@Test
void shouldGetPostfachIdFromToken() {
doReturn(GrpcPostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE).when(service).getPostfachId(any());
service.verifyPostfachId(SAML_TOKEN, POSTFACH_NACHRICHT);
verify(service).getPostfachId(SAML_TOKEN);
}
@Test
void shouldThrowExceptionOnMismatchPostfachId() {
doReturn("not-matching-postfach-id").when(service).getPostfachId(any());
assertThatThrownBy(() -> service.verifyPostfachId(SAML_TOKEN, POSTFACH_NACHRICHT))
.isInstanceOf(NotFoundException.class)
.hasMessageContaining("PostfachNachricht")
.hasMessageContaining(PostfachNachrichtTestFactory.ID);
}
@Test
void shouldNotThrowExceptionOnMatchingPostfachId() {
doReturn(GrpcPostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE).when(service).getPostfachId(any());
assertDoesNotThrow(() -> service.verifyPostfachId(SAML_TOKEN, POSTFACH_NACHRICHT));
}
}
@DisplayName("Is accessible")
@Nested
class TestIsAccessible {
......
package de.ozgcloud.nachrichten.common.vorgang;
import java.util.UUID;
import de.ozgcloud.vorgang.common.GrpcObject;
import de.ozgcloud.vorgang.common.GrpcProperty;
import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress;
public class GrpcPostfachAddressTestFactory {
public static final String IDENTIFIER_POSTFACH_ID_FIELD = "postfachId";
public static final String STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE = UUID.randomUUID().toString();
public static GrpcPostfachAddress create() {
return createBuilder().build();
}
public static GrpcPostfachAddress.Builder createBuilder() {
return GrpcPostfachAddress.newBuilder()
.setIdentifier(createStringBasedIdentifier());
}
private static GrpcObject createStringBasedIdentifier() {
return GrpcObject.newBuilder()
.addProperty(GrpcProperty.newBuilder()
.setName(IDENTIFIER_POSTFACH_ID_FIELD)
.addValue(STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE)
.build())
.build();
}
}
......@@ -14,6 +14,7 @@ public class GrpcServiceKontoTestFactory {
public static GrpcServiceKonto.Builder createBuilder() {
return GrpcServiceKonto.newBuilder()
.setTrustLevel(TRUST_LEVEL);
.setTrustLevel(TRUST_LEVEL)
.addPostfachAddresses(GrpcPostfachAddressTestFactory.create());
}
}
}
\ No newline at end of file
......@@ -21,5 +21,18 @@ class NachrichtenVorgangMapperTest {
assertThat(vorgang).usingRecursiveComparison().isEqualTo(VorgangTestFactory.create());
}
@Test
void shouldProceedIfPostfachAddressesAreMissing() {
var ohnePostfachId = GrpcVorgangWithEingangTestFactory.createBuilder().setHeader(
GrpcVorgangHeadTestFactory.createBuilder()
.setServiceKonto(GrpcServiceKontoTestFactory.createBuilder().clearPostfachAddresses().build())
.build())
.build();
var vorgang = mapper.fromVorgangWithEingang(ohnePostfachId);
assertThat(vorgang).isNotNull();
}
}
}
......@@ -19,6 +19,7 @@ public class VorgangTestFactory {
.id(ID)
.name(NAME)
.nummer(NUMMER)
.trustLevel(GrpcServiceKontoTestFactory.TRUST_LEVEL);
.trustLevel(GrpcServiceKontoTestFactory.TRUST_LEVEL)
.postfachId(GrpcPostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment