Commit bb64c6c5 authored by Anastasios Poimenidis's avatar Anastasios Poimenidis
Browse files

fix: ensure keycloak credentials are not stored during Organization persistence

parent 5a4aecf9
Loading
Loading
Loading
Loading
Loading
+0 −17
Original line number Diff line number Diff line
@@ -6,8 +6,6 @@ import org.etsi.osl.hypo.api.tmf.agreement.schema.Agreement;
import org.etsi.osl.hypo.api.tmf.agreement.schema.AgreementSpecification;
import org.etsi.osl.hypo.api.tmf.alarm.schema.Alarm;
import org.etsi.osl.hypo.api.tmf.geographic.site.schema.GeographicSite;
import org.etsi.osl.hypo.api.tmf.party.individual.schema.Individual;
import org.etsi.osl.hypo.api.tmf.party.organization.schema.Organization;
import org.etsi.osl.hypo.api.tmf.party.partnership.management.schema.Partnership;
import org.etsi.osl.hypo.api.tmf.party.partnership.management.schema.PartnershipSpecification;
import org.etsi.osl.hypo.api.tmf.party.role.management.schema.PartyRole;
@@ -51,21 +49,6 @@ import org.mapstruct.SubclassExhaustiveStrategy;
        subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION)
public interface UpdateMapper {

    @Mapping(target = "entityId", ignore = true)
    @Mapping(target = "organizationParentRelationship.entityId", ignore = true)
    @Mapping(target = "taxExemptionCertificate.attachment.entityId", ignore = true)
    @Mapping(target = "contactMedium.mediumCharacteristic.entityId", ignore = true)
    @Mapping(target = "organizationParentRelationship.organization.entityId", ignore = true)
    @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    Organization updateOrganization(
            Organization newOrganization, @MappingTarget Organization oldOrganization);

    @Mapping(target = "entityId", ignore = true)
    @Mapping(target = "taxExemptionCertificate.attachment.entityId", ignore = true)
    @Mapping(target = "contactMedium.mediumCharacteristic.entityId", ignore = true)
    @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    Individual updateIndividual(Individual newIndividual, @MappingTarget Individual oldIndividual);

    @Mapping(target = "entityId", ignore = true)
    @Mapping(target = "orderItem.entityId", ignore = true)
    @Mapping(target = "orderItem.appointment.entityId", ignore = true)
+21 −2
Original line number Diff line number Diff line
package org.etsi.osl.hypo.api.tmf.party.api;
package org.etsi.osl.hypo.api.tmf.party.api.mapper;

import org.etsi.osl.hypo.api.tmf.common.schema.RelatedPartyEntity;
import org.etsi.osl.hypo.api.tmf.party.individual.schema.Individual;
@@ -7,6 +7,7 @@ import org.mapstruct.BeanMapping;
import org.mapstruct.InjectionStrategy;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.ReportingPolicy;
import org.mapstruct.SubclassExhaustiveStrategy;
@@ -15,7 +16,25 @@ import org.mapstruct.SubclassExhaustiveStrategy;
        componentModel = "cdi",
        injectionStrategy = InjectionStrategy.CONSTRUCTOR,
        subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION)
public interface RelatedPartyMapper {
public interface OrganizationMapper {

    @Mapping(target = "entityId", ignore = true)
    @Mapping(target = "organizationParentRelationship.entityId", ignore = true)
    @Mapping(target = "taxExemptionCertificate.attachment.entityId", ignore = true)
    @Mapping(target = "contactMedium.mediumCharacteristic.entityId", ignore = true)
    @Mapping(target = "organizationParentRelationship.organization.entityId", ignore = true)
    @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    Organization updateOrganization(
            Organization newOrganization, @MappingTarget Organization oldOrganization);

    @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    Organization cloneOrganization(Organization organization);

    @Mapping(target = "entityId", ignore = true)
    @Mapping(target = "taxExemptionCertificate.attachment.entityId", ignore = true)
    @Mapping(target = "contactMedium.mediumCharacteristic.entityId", ignore = true)
    @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    Individual updateIndividual(Individual newIndividual, @MappingTarget Individual oldIndividual);

    @Mapping(target = "entityId", ignore = true)
    @BeanMapping(
+7 −14
Original line number Diff line number Diff line
package org.etsi.osl.hypo.api.tmf.party.api.services;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.etsi.osl.hypo.api.tmf.common.api.mapper.UpdateMapper;
import org.etsi.osl.hypo.api.tmf.common.api.services.RelatedPartyService;
import org.etsi.osl.hypo.api.tmf.common.api.services.UtilService;
import org.etsi.osl.hypo.api.tmf.common.exception.DuplicateKeyException;
import org.etsi.osl.hypo.api.tmf.common.exception.ServiceNotFoundException;
import org.etsi.osl.hypo.api.tmf.common.schema.RelatedPartyEntity;
import org.etsi.osl.hypo.api.tmf.party.api.RelatedPartyMapper;
import org.etsi.osl.hypo.api.tmf.party.api.kafka.outgoing.producer.RegistryProducer;
import org.etsi.osl.hypo.api.tmf.party.api.mapper.OrganizationMapper;
import org.etsi.osl.hypo.api.tmf.party.api.repository.IndividualRepository;
import org.etsi.osl.hypo.api.tmf.party.individual.schema.Individual;
import org.jboss.logging.Logger;
@@ -22,26 +20,20 @@ import org.jboss.logging.Logger;
public class IndividualService {
    private final IndividualRepository individualRepository;

    private final UpdateMapper updateMapper;
    private final RelatedPartyMapper relatedPartyMapper;

    private final OrganizationMapper organizationMapper;
    private final RelatedPartyService relatedPartyService;

    private final RegistryProducer registryProducer;

    private static final Logger logger = Logger.getLogger(IndividualService.class);
    private static final String INDIVIDUAL_WITH_ID = "Individual with id ";

    @Inject
    public IndividualService(
            IndividualRepository individualRepository,
            UpdateMapper updateMapper,
            RelatedPartyMapper relatedPartyMapper,
            OrganizationMapper organizationMapper,
            RelatedPartyService relatedPartyService,
            RegistryProducer registryProducer) {
        this.individualRepository = individualRepository;
        this.updateMapper = updateMapper;
        this.relatedPartyMapper = relatedPartyMapper;
        this.organizationMapper = organizationMapper;
        this.relatedPartyService = relatedPartyService;
        this.registryProducer = registryProducer;
    }
@@ -113,7 +105,7 @@ public class IndividualService {
        }
        individualRepository.persist(individual);

        RelatedPartyEntity relatedPartyEntity = relatedPartyMapper.individualToRelatedParty(individual);
        RelatedPartyEntity relatedPartyEntity = organizationMapper.individualToRelatedParty(individual);
        relatedPartyService.findOrCreateRelatedPartyEntity(relatedPartyEntity);

        return individual;
@@ -122,7 +114,8 @@ public class IndividualService {
    @Transactional
    public Individual updateIndividual(String id, Individual newIndividual) {
        Individual oldIndividual = getById(id);
        Individual updatedIndividual = updateMapper.updateIndividual(newIndividual, oldIndividual);
        Individual updatedIndividual =
                organizationMapper.updateIndividual(newIndividual, oldIndividual);
        individualRepository.persist(updatedIndividual);
        return oldIndividual;
    }
+16 −19
Original line number Diff line number Diff line
@@ -6,7 +6,6 @@ import static org.etsi.osl.hypo.api.tmf.common.constants.OssConstants.PEERED_ORG

import io.opentelemetry.instrumentation.annotations.WithSpan;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import java.util.HashMap;
import java.util.HashSet;
@@ -21,7 +20,6 @@ import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.etsi.osl.hypo.api.tmf.common.api.mapper.UpdateMapper;
import org.etsi.osl.hypo.api.tmf.common.api.services.RelatedPartyService;
import org.etsi.osl.hypo.api.tmf.common.api.services.UtilService;
import org.etsi.osl.hypo.api.tmf.common.exception.DuplicateKeyException;
@@ -29,9 +27,9 @@ import org.etsi.osl.hypo.api.tmf.common.exception.ServiceNotFoundException;
import org.etsi.osl.hypo.api.tmf.common.model.BaseEntity;
import org.etsi.osl.hypo.api.tmf.common.schema.RelatedPartyEntity;
import org.etsi.osl.hypo.api.tmf.common.schema.ValueEntity;
import org.etsi.osl.hypo.api.tmf.party.api.RelatedPartyMapper;
import org.etsi.osl.hypo.api.tmf.party.api.kafka.outgoing.model.OrganizationAuthCredentials;
import org.etsi.osl.hypo.api.tmf.party.api.kafka.outgoing.producer.RegistryProducer;
import org.etsi.osl.hypo.api.tmf.party.api.mapper.OrganizationMapper;
import org.etsi.osl.hypo.api.tmf.party.api.repository.OrganizationRepository;
import org.etsi.osl.hypo.api.tmf.party.organization.schema.Characteristic;
import org.etsi.osl.hypo.api.tmf.party.organization.schema.Organization;
@@ -44,25 +42,20 @@ public class OrganizationService {
    private final OrganizationRepository organizationRepository;
    private final RelatedPartyService relatedPartyService;
    private final RegistryProducer registryProducer;

    private final RelatedPartyMapper relatedPartyMapper;
    private final UpdateMapper updateMapper;
    private final OrganizationMapper organizationMapper;

    private static final Logger logger = Logger.getLogger(OrganizationService.class);
    private static final String ORGANIZATION_WITH_ID = "Organization with id ";

    @Inject
    public OrganizationService(
            OrganizationRepository organizationRepository,
            RelatedPartyService relatedPartyService,
            RegistryProducer registryProducer,
            RelatedPartyMapper relatedPartyMapper,
            UpdateMapper updateMapper) {
            OrganizationMapper organizationMapper) {
        this.organizationRepository = organizationRepository;
        this.relatedPartyService = relatedPartyService;
        this.registryProducer = registryProducer;
        this.relatedPartyMapper = relatedPartyMapper;
        this.updateMapper = updateMapper;
        this.organizationMapper = organizationMapper;
    }

    @Transactional
@@ -155,19 +148,19 @@ public class OrganizationService {

            // remove sensitive characteristics
            // they will be stored in Vault
            storeOrganizationCredentials(organization);
            Organization organizationResponse = storeOrganizationCredentials(organization);

            // send KAFKA message to Registry API to store the organization Auth Credentials
            if (StringUtils.isNotBlank(authHeader)) {
                this.sendCredentialsToRegistry(organization, authHeader);
                this.sendCredentialsToRegistry(organizationResponse, authHeader);
            }

            // create a related party entity for references
            RelatedPartyEntity relatedPartyEntity =
                    relatedPartyMapper.organizationToRelatedParty(organization);
                    organizationMapper.organizationToRelatedParty(organization);
            relatedPartyService.findOrCreateRelatedPartyEntity(relatedPartyEntity);

            return organization;
            return organizationResponse;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
@@ -178,7 +171,7 @@ public class OrganizationService {
    public Organization updateOrganization(String id, Organization newOrganization) {
        Organization oldOrganization = getById(id);
        Organization updatedOrganization =
                updateMapper.updateOrganization(newOrganization, oldOrganization);
                organizationMapper.updateOrganization(newOrganization, oldOrganization);
        organizationRepository.persist(updatedOrganization);
        return updatedOrganization;
    }
@@ -387,7 +380,7 @@ public class OrganizationService {
        }
    }

    private void storeOrganizationCredentials(Organization organization) {
    private Organization storeOrganizationCredentials(Organization organization) {
        Set<String> organizationCredentialsCharacteristicsNames =
                Set.of(EXTERNAL_TMF_API_USERNAME, EXTERNAL_TMF_API_PASSWORD);

@@ -395,7 +388,7 @@ public class OrganizationService {

        if (CollectionUtils.isEmpty(partyCharacteristic)) {
            organizationRepository.persist(organization);
            return;
            return organizationMapper.cloneOrganization(organization);
        }

        // obtain characteristics for keycloak
@@ -412,8 +405,12 @@ public class OrganizationService {
        // store in db
        organizationRepository.persist(organization);

        Organization clonedOrganization = organizationMapper.cloneOrganization(organization);

        // add back characteristics for POST response
        organization.getPartyCharacteristic().addAll(partyCharacteristicsCredentials);
        clonedOrganization.getPartyCharacteristic().addAll(partyCharacteristicsCredentials);

        return clonedOrganization;
    }

    private void sendDeleteCredentialsMessageToRegistry(String organizationId, String authHeader) {
+3 −4
Original line number Diff line number Diff line
@@ -27,9 +27,9 @@ import java.util.List;
import java.util.Optional;
import java.util.Random;
import net.joshka.junit.json.params.JsonFileSource;
import org.etsi.osl.hypo.api.tmf.common.api.mapper.UpdateMapper;
import org.etsi.osl.hypo.api.tmf.common.api.services.RelatedPartyService;
import org.etsi.osl.hypo.api.tmf.common.schema.RelatedPartyEntity;
import org.etsi.osl.hypo.api.tmf.party.api.mapper.OrganizationMapper;
import org.etsi.osl.hypo.api.tmf.party.api.rest.IndividualResource;
import org.etsi.osl.hypo.api.tmf.party.api.services.IndividualService;
import org.etsi.osl.hypo.api.tmf.party.individual.schema.Individual;
@@ -46,10 +46,9 @@ class IndividualResourceTest {
    @TestHTTPResource()
    URL individualPartyManagement;

    @Inject UpdateMapper updateMapper;

    static ObjectMapper objectMapper;

    @Inject OrganizationMapper organizationMapper;
    @Inject IndividualService individualService;
    @Inject RelatedPartyService relatedPartyService;

@@ -135,7 +134,7 @@ class IndividualResourceTest {
                        .extract()
                        .as(Individual.class);

        updateMapper.updateIndividual(expectedResponse, individual);
        organizationMapper.updateIndividual(expectedResponse, individual);

        Individual actualResponse =
                given()
Loading