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
42 changes: 29 additions & 13 deletions openaev-api/src/main/java/io/openaev/rest/domain/DomainService.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import io.openaev.rest.domain.enums.PresetDomain;
import io.openaev.rest.domain.form.DomainBaseInput;
import io.openaev.rest.exception.ElementNotFoundException;
import io.openaev.rest.injector_contract.form.InjectorContractDomainDTO;
import io.openaev.utils.FilterUtilsJpa;
import jakarta.transaction.Transactional;
import java.time.Instant;
Expand All @@ -31,7 +32,6 @@
public class DomainService {

private static final String DOMAIN_ID_NOT_FOUND_MSG = "Domain not found with id";
private static final String DOMAIN_NAME_NOT_FOUND_MSG = "Domain not found with name";

private final DomainRepository domainRepository;

Expand All @@ -45,16 +45,6 @@ public List<Domain> searchDomains() {
return fromIterable(domainRepository.findAll());
}

private Optional<Domain> findByName(final String name) {
return Optional.ofNullable(
domainRepository
.findByName(name)
.orElseThrow(
() ->
new ElementNotFoundException(
(String.format("%s: %s", DOMAIN_NAME_NOT_FOUND_MSG, name)))));
}

public Optional<Domain> findOptionalById(final String domainId) {
return domainRepository.findById(domainId);
}
Expand Down Expand Up @@ -82,15 +72,41 @@ public Domain upsert(final Domain domainToUpsert) {
return this.upsert(domainToUpsert.getName(), domainToUpsert.getColor());
}

/**
* Saves a collection of contract entities in the database. If an entity already exists (searched
* by name) in the database, it is retrieved instead of saved (no modification). If the entity is
* not found, it is created.
*
* @param domains set of domain entities to save or retrieve.
* @return set of saved or retrieved domains
*/
@Transactional
public Set<Domain> upsertDomainEntities(Set<Domain> domains) {
return this.upserts(
Optional.ofNullable(domains)
.map(
collection ->
collection.stream().map(InjectorContractDomainDTO::fromDomain).collect(toSet()))
.orElse(null));
}

/**
* Saves a collection of contract DTOs in the database. If an entity already exists (searched by
* name) in the database, it is retrieved instead of saved (no modification). If the entity is not
* found, it is created.
*
* @param domains set of domain DTOs to save or retrieve.
* @return set of saved or retrieved domains
*/
@Transactional
public Set<Domain> upserts(Set<Domain> domains) {
public Set<Domain> upserts(Set<InjectorContractDomainDTO> domains) {
if (domains == null || domains.isEmpty()) {
return new HashSet<>();
}

Map<String, Domain> existing =
domainRepository
.findByNameIn(domains.stream().map(Domain::getName).collect(toSet()))
.findByNameIn(domains.stream().map(InjectorContractDomainDTO::getName).collect(toSet()))
.stream()
.collect(toMap(Domain::getName, Function.identity()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@
import io.openaev.rest.attack_pattern.service.AttackPatternService;
import io.openaev.rest.domain.DomainService;
import io.openaev.rest.exception.ElementNotFoundException;
import io.openaev.rest.injector_contract.form.InjectorContractAddInput;
import io.openaev.rest.injector_contract.form.InjectorContractInput;
import io.openaev.rest.injector_contract.form.InjectorContractUpdateInput;
import io.openaev.rest.injector_contract.form.InjectorContractUpdateMappingInput;
import io.openaev.rest.injector_contract.form.*;
import io.openaev.rest.injector_contract.output.InjectorContractBaseOutput;
import io.openaev.rest.injector_contract.output.InjectorContractDomainCountOutput;
import io.openaev.rest.injector_contract.output.InjectorContractFullOutput;
Expand Down Expand Up @@ -322,8 +319,8 @@ private void applyBuiltinContractData(
}

if (!isPayloads) {
Set<Domain> currentDomains = this.domainService.upserts(target.getDomains());
Set<Domain> domainsToAdd = this.domainService.upserts(source.getDomains());
Set<Domain> currentDomains = this.domainService.upsertDomainEntities(target.getDomains());
Set<Domain> domainsToAdd = this.domainService.upsertDomainEntities(target.getDomains());
target.setDomains(this.domainService.mergeDomains(currentDomains, domainsToAdd));
}
setupImportAvailable(target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static io.openaev.config.AppConfig.MANDATORY_MESSAGE;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openaev.database.model.Domain;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.ArrayList;
Expand Down Expand Up @@ -58,5 +57,5 @@ public class InjectorContractAddInput {

@NotNull(message = MANDATORY_MESSAGE)
@JsonProperty("contract_domains")
private Set<Domain> domains;
private Set<InjectorContractDomainDTO> domains;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.openaev.rest.injector_contract.form;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openaev.database.model.Domain;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class InjectorContractDomainDTO {
@JsonProperty("domain_id")
@NotBlank
private String id;

@JsonProperty("domain_name")
@NotBlank
private String name;

@JsonProperty("domain_color")
@NotBlank
private String color;

public static InjectorContractDomainDTO fromDomain(Domain domain) {
InjectorContractDomainDTO dto = new InjectorContractDomainDTO();
dto.setId(domain.getId());
dto.setName(domain.getName());
dto.setColor(domain.getColor());
return dto;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static io.openaev.config.AppConfig.MANDATORY_MESSAGE;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openaev.database.model.Domain;
import io.openaev.database.model.Endpoint.PLATFORM_TYPE;
import jakarta.validation.constraints.NotBlank;
import java.util.*;
Expand Down Expand Up @@ -38,5 +37,5 @@ public class InjectorContractInput {
private PLATFORM_TYPE[] platforms = new PLATFORM_TYPE[0];

@JsonProperty("contract_domains")
private Set<Domain> domains = new HashSet<>();
private Set<InjectorContractDomainDTO> domains = new HashSet<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static io.openaev.config.AppConfig.MANDATORY_MESSAGE;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openaev.database.model.Domain;
import jakarta.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -41,5 +40,5 @@ public class InjectorContractUpdateInput {
private String[] platforms = new String[0];

@JsonProperty("contract_domains")
private Set<Domain> domains;
private Set<InjectorContractDomainDTO> domains;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openaev.database.model.*;
import io.openaev.rest.injector_contract.form.InjectorContractDomainDTO;
import io.openaev.rest.payload.output_parser.OutputParserInput;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
Expand Down Expand Up @@ -107,5 +108,5 @@ public class PayloadUpsertInput {
@NotNull(message = MANDATORY_MESSAGE)
@JsonProperty("payload_domains")
@Schema(description = "Update list of domains")
private Set<Domain> domains = new HashSet<>();
private Set<InjectorContractDomainDTO> domains = new HashSet<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ private void setInjectorContractPropertyBasedOnPayload(
injectorContract.setPayload(payload);
injectorContract.setPlatforms(payload.getPlatforms());
injectorContract.setDomains(
domainService.upserts(new HashSet<>(Set.of(PresetDomain.TOCLASSIFY))));
domainService.upsertDomainEntities(new HashSet<>(Set.of(PresetDomain.TOCLASSIFY))));
injectorContract.setAttackPatterns(
fromIterable(
attackPatternRepository.findAllById(
Expand Down Expand Up @@ -365,7 +365,7 @@ private DnsResolution createDynamicDnsResolutionPayload() {
});

dynamicDnsResolutionPayload.setDomains(
domainService.upserts(
domainService.upsertDomainEntities(
Set.of(PresetDomain.ENDPOINT, PresetDomain.NETWORK, PresetDomain.URL_FILTERING)));

dynamicDnsResolutionPayload.setTags(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ public Payload updatePayloadFromUpsert(
payload.setCollector(collector);
}

final Set<Domain> existingDomains = this.domainService.upserts(payload.getDomains());
final Set<Domain> existingDomains =
this.domainService.upsertDomainEntities(payload.getDomains());
final Set<Domain> domainsToAdd = this.domainService.upserts(input.getDomains());
payload.setDomains(this.domainService.mergeDomains(existingDomains, domainsToAdd));
payload.setAttackPatterns(attackPatterns);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,8 @@ public Injector updateExistingExternalInjector(
}

if (!payloads) {
Set<Domain> currentDomains = this.domainService.upserts(contract.getDomains());
Set<Domain> currentDomains =
this.domainService.upsertDomainEntities(contract.getDomains());
Set<Domain> domainsToAdd = this.domainService.upserts(current.get().getDomains());
contract.setDomains(
this.domainService.mergeDomains(currentDomains, domainsToAdd));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
import io.openaev.database.model.Domain;
import io.openaev.rest.domain.DomainService;
import io.openaev.rest.domain.enums.PresetDomain;
import io.openaev.utils.fixtures.ColourFixture;
import io.openaev.utils.fixtures.DomainFixture;
import io.openaev.utils.fixtures.composers.DomainComposer;
import jakarta.transaction.Transactional;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -19,14 +23,68 @@
public class DomainServiceTest extends IntegrationTest {

@Autowired private DomainService domainService;
@Autowired private DomainComposer domainComposer;

@Test
@DisplayName("Upsert with null parameter should not fail")
@DisplayName("Upsert DTOs with null parameter should not fail")
void upsertWithNullShouldNotFail() {
Set<Domain> domains = this.domainService.upserts(null);
assertTrue(domains.isEmpty());
}

@Test
@DisplayName("Upsert entities with null parameter should not fail")
void upsertEntitiesWithNullShouldNotFail() {
Set<Domain> domains = this.domainService.upsertDomainEntities(null);
assertTrue(domains.isEmpty());
}

@Test
@DisplayName("Upsert entities with set partially existing")
void upsertEntitiesWithSetPartiallyExisting() {
Set<Domain> domains = new HashSet<>();
for (int i = 0; i < 3; i++) {
domains.add(domainComposer.forDomain(DomainFixture.getRandomDomain()).persist().get());
}
for (int i = 0; i < 3; i++) {
// don't persist those
domains.add(DomainFixture.getRandomDomain());
}

Set<Domain> upserted = this.domainService.upsertDomainEntities(domains);

assertThat(upserted).hasSameElementsAs(domains);
}

@Test
@DisplayName("Upsert existing entities prevents changing colour")
void upsertExistingEntitiesPreventsCHangingColour() {
Map<String, Domain> domains = new HashMap<>();
for (int i = 0; i < 3; i++) {
Domain d = DomainFixture.getRandomDomain();
domains.put(d.getName(), domainComposer.forDomain(d).persist().get());
}

Set<Domain> modified =
domains.values().stream()
.map(
domain ->
DomainFixture.getDomainWithNameAndColour(
domain.getName(), ColourFixture.getRandomRgbString()))
.collect(Collectors.toSet());

Set<Domain> upserted = this.domainService.upsertDomainEntities(modified);

assertThat(upserted)
.hasSameElementsAs(domains.values())
.satisfies(
set ->
set.forEach(
domain ->
assertThat(domain.getColor())
.isEqualTo(domains.get(domain.getName()).getColor())));
}

@Test
@DisplayName("Set should be merged")
void setShouldBeMerged() {
Expand Down
Loading
Loading