Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ public InjectResultOverviewOutput relaunch(String id) {
Inject duplicatedInject = findAndDuplicateInject(id);
this.throwIfInjectNotLaunchable(duplicatedInject);
Inject savedInject = saveInjectAndStatusAsQueuing(duplicatedInject);
deleteForRelaunch(id);
deleteForRelaunch(id, savedInject.getId());
return injectMapper.toInjectResultOverviewOutput(savedInject);
}

Expand All @@ -416,9 +416,9 @@ public void delete(String id) {
}

@Transactional
public void deleteForRelaunch(String id) {
injectDocumentRepository.deleteDocumentsFromInject(id);
injectRepository.deleteByIdNative(id);
public void deleteForRelaunch(String oldId, String newId) {
injectDocumentRepository.updateInjectId(newId, oldId);
injectRepository.deleteByIdNative(oldId);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class AtomicTestingService {
private final InjectSearchService injectSearchService;
private final InjectService injectService;
private final GrantService grantService;
private final InjectDocumentRepository injectDocumentRepository;

// -- CRUD --

Expand Down Expand Up @@ -119,35 +120,38 @@ public InjectResultOverviewOutput createOrUpdate(AtomicTestingInput input, Strin
injectToSave.setAssetGroups(
fromIterable(this.assetGroupRepository.findAllById(input.getAssetGroups())));

List<String> previousDocumentIds =
injectToSave.getDocuments().stream()
.map(InjectDocument::getDocument)
.map(Document::getId)
.toList();
injectToSave.getDocuments().clear();

Inject finalInjectToSave = injectToSave;
List<InjectDocument> injectDocuments =
input.getDocuments().stream()
.map(
i -> {
if (!previousDocumentIds.contains(i.getDocumentId())) {
InjectDocument injectDocument = new InjectDocument();
injectDocument.setInject(finalInjectToSave);
injectDocument.setDocument(
documentRepository.findById(i.getDocumentId()).orElseThrow());
injectDocument.setAttached(i.isAttached());
return injectDocument;
}
return null;
})
.filter(Objects::nonNull)
.toList();
injectToSave.getDocuments().addAll(injectDocuments);
input
.getDocuments()
.forEach(
i -> {
InjectDocumentId injectDocumentId = new InjectDocumentId();
injectDocumentId.setInjectId(finalInjectToSave.getId());
injectDocumentId.setDocumentId(i.getDocumentId());
InjectDocument injectDocument =
injectDocumentRepository.findById(injectDocumentId).orElse(new InjectDocument());
if (injectDocument.getInject() == null) {
injectDocument.setCompositeId(injectDocumentId);
injectDocument.setInject(finalInjectToSave);
injectDocument.setDocument(
documentRepository.findById(i.getDocumentId()).orElseThrow());
}
injectDocument.setAttached(i.isAttached());
finalInjectToSave
.getDocuments()
.add(
injectId == null
? injectDocument
: injectDocumentRepository.save(injectDocument));
});

if (injectId == null) {
actionMetricCollector.addAtomicTestingCreatedCount();
}
Inject inject = injectRepository.save(injectToSave);
return injectMapper.toInjectResultOverviewOutput(inject);
injectToSave = injectRepository.save(injectToSave);
return injectMapper.toInjectResultOverviewOutput(injectToSave);
}

private ObjectNode setExpectations(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.openaev.rest;

import static io.openaev.injectors.email.EmailContract.EMAIL_DEFAULT;
import static io.openaev.utils.JsonUtils.asJsonString;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
Expand All @@ -13,6 +13,7 @@
import com.jayway.jsonpath.JsonPath;
import io.openaev.IntegrationTest;
import io.openaev.database.model.*;
import io.openaev.database.repository.DocumentRepository;
import io.openaev.database.repository.InjectRepository;
import io.openaev.database.repository.InjectStatusRepository;
import io.openaev.database.repository.InjectorContractRepository;
Expand All @@ -39,6 +40,7 @@ public class AtomicTestingApiTest extends IntegrationTest {
static Inject INJECT_WITHOUT_STATUS;
static InjectStatus INJECT_STATUS;
static InjectorContract INJECTOR_CONTRACT;
static Document DOCUMENT;

@Autowired private AgentComposer agentComposer;
@Autowired private EndpointComposer endpointComposer;
Expand All @@ -51,6 +53,7 @@ public class AtomicTestingApiTest extends IntegrationTest {
@Autowired private InjectRepository injectRepository;
@Autowired private InjectorContractRepository injectorContractRepository;
@Autowired private InjectStatusRepository injectStatusRepository;
@Autowired private DocumentRepository documentRepository;
@Autowired private EntityManager entityManager;
@Autowired private ObjectMapper mapper;

Expand All @@ -65,6 +68,8 @@ void before() {
InjectStatus injectStatus = InjectStatusFixture.createPendingInjectStatus();
injectStatus.setInject(injectWithPayload);
INJECT_STATUS = injectStatusRepository.save(injectStatus);

DOCUMENT = documentRepository.save(DocumentFixture.getDocumentJpeg());
}

private InjectComposer.Composer getAtomicTestingWrapper(
Expand Down Expand Up @@ -137,6 +142,57 @@ void findAnAtomicTestingWithStatusAndCommandLines() throws Exception {
mapper.readTree(expectedExpectationsJson), mapper.readTree(actualExpectationsJson));
}

@Test
@DisplayName("Create and upadte an atomic testing")
@WithMockUser(isAdmin = true)
void createAndUpdateAnAtomicTesting() throws Exception {
String response =
mvc.perform(
post(ATOMIC_TESTINGS_URI)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(
asJsonString(InjectFixture.createAtomicTesting("test", DOCUMENT.getId()))))
.andExpect(status().is2xxSuccessful())
.andReturn()
.getResponse()
.getContentAsString();
assertNotNull(response);
String newInjectId = JsonPath.read(response, "$.inject_id");
response =
mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + newInjectId).accept(MediaType.APPLICATION_JSON))
.andExpect(status().is2xxSuccessful())
.andReturn()
.getResponse()
.getContentAsString();
assertEquals(newInjectId, JsonPath.read(response, "$.inject_id"));
assertEquals("test", JsonPath.read(response, "$.inject_title"));
List<String> documentIds = JsonPath.read(response, "$.injects_documents");
assertEquals(1, documentIds.size());

response =
mvc.perform(
put(ATOMIC_TESTINGS_URI + "/" + newInjectId)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(InjectFixture.createAtomicTesting("test2", null))))
.andExpect(status().is2xxSuccessful())
.andReturn()
.getResponse()
.getContentAsString();
assertNotNull(response);
response =
mvc.perform(get(ATOMIC_TESTINGS_URI + "/" + newInjectId).accept(MediaType.APPLICATION_JSON))
.andExpect(status().is2xxSuccessful())
.andReturn()
.getResponse()
.getContentAsString();
assertEquals(newInjectId, JsonPath.read(response, "$.inject_id"));
assertEquals("test2", JsonPath.read(response, "$.inject_title"));
documentIds = JsonPath.read(response, "$.injects_documents");
assertEquals(0, documentIds.size());
}

@Test
@DisplayName("Duplicate and delete an atomic testing")
@WithMockUser(isAdmin = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package io.openaev.utils.fixtures;

import static io.openaev.database.model.InjectorContract.CONTRACT_ELEMENT_CONTENT_KEY_EXPECTATIONS;
import static io.openaev.injectors.email.EmailContract.EMAIL_DEFAULT;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.openaev.database.model.*;
import io.openaev.injectors.challenge.model.ChallengeContent;
import io.openaev.rest.atomic_testing.form.AtomicTestingInput;
import io.openaev.rest.inject.form.InjectDocumentInput;
import java.util.List;
import java.util.Map;
import java.util.UUID;
Expand All @@ -17,12 +20,31 @@ public class InjectFixture {
public static final String INJECT_EMAIL_NAME = "Test email inject";
public static final String INJECT_CHALLENGE_NAME = "Test challenge inject";

public static AtomicTestingInput createAtomicTesting(String title, String documentId) {
AtomicTestingInput input = new AtomicTestingInput();
input.setInjectorContract(EMAIL_DEFAULT);
input.setContent(injectContent());
input.setTitle(title);
input.setAllTeams(false);
if (documentId != null) {
InjectDocumentInput documentInput = new InjectDocumentInput();
documentInput.setDocumentId(documentId);
documentInput.setAttached(true);
input.setDocuments(List.of(documentInput));
}
return input;
}

public static Inject createInject(InjectorContract injectorContract, String title) {
Inject inject = createInjectWithTitle(title);
inject.setInjectorContract(injectorContract);
inject.setEnabled(true);
inject.setDependsDuration(0L);
inject.setContent(injectContent());
return inject;
}

private static ObjectNode injectContent() {
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode injectContent = objectMapper.createObjectNode();
injectContent.set(
Expand All @@ -31,9 +53,7 @@ public static Inject createInject(InjectorContract injectorContract, String titl
List.of(
ExpectationFixture.createExpectation(InjectExpectation.EXPECTATION_TYPE.MANUAL)),
ArrayNode.class));
inject.setContent(injectContent);

return inject;
return injectContent;
}

public static Inject createTechnicalInject(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const InjectDocumentsList = ({ readOnly, hasAttachments }: Props) => {
useEffect(() => {
const test = (injectDocuments || [])
.map(d => ({
...d,
...documentsMap[d.document_id],
document_attached: d.document_attached,
}))
Expand Down Expand Up @@ -92,8 +93,29 @@ const InjectDocumentsList = ({ readOnly, hasAttachments }: Props) => {
document_attached: boolean;
}[]) => {
const docIds = injectDocuments.map(d => d.document_id);
const newDocs = documents.filter(d => !docIds.includes(d.document_id));
appendInjectDocuments(newDocs);
const selectedIds = documents.map(d => d.document_id);

// Add only documents that are not already present
const newDocs = documents
.filter(d => !docIds.includes(d.document_id))
.map(d => ({
document_id: d.document_id,
document_attached: hasAttachments,
}));

if (newDocs.length > 0) {
appendInjectDocuments(newDocs);
}

// Remove documents that are currently stored but no longer selected
const idsToRemove = docIds.filter(id => !selectedIds.includes(id));

idsToRemove.forEach((id) => {
const index = injectDocuments.findIndex(d => d.document_id === id);
if (index !== -1) {
removeInjectDocuments(index);
}
});
};

return (
Expand Down
24 changes: 16 additions & 8 deletions openaev-front/src/components/fields/FileTransferDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,18 @@ const FileTransferDialog: FunctionComponent<Props> = ({
const { documents }: { documents: [RawDocument] } = useHelper((helper: DocumentHelper & UserHelper) => ({ documents: helper.getDocuments() }));

useEffect(() => {
if (initialDocumentIds.length > 0) {
setSelectedDocuments(documents.filter((document) => {
const docId = document.document_id;
return docId && initialDocumentIds.includes(docId);
}));
}
// If initial data hasn't arrived yet, do nothing
if (initialDocumentIds.length === 0) return;

// If we already have selected documents, don't override user changes
if (selectedDocuments.length > 0) return;

// Initialize selectedDocuments from initialDocumentIds (only once)
setSelectedDocuments(
documents.filter(
doc => doc.document_id && initialDocumentIds.includes(doc.document_id),
),
);
}, [initialDocumentIds]);

const handleSearchDocuments = (value?: string) => {
Expand Down Expand Up @@ -137,9 +143,11 @@ const FileTransferDialog: FunctionComponent<Props> = ({
return tags.length === 0 || tags.every(tag => document.document_tags?.includes(tag.id));
};

const selectedIds = selectedDocuments.map(d => d.document_id);

const filteredDocuments = documents.filter((document) => {
const isInitialValue = document.document_id && initialDocumentIds?.includes(document.document_id);
return !isInitialValue
const isSelected = document.document_id && selectedIds.includes(document.document_id);
return !isSelected
&& filterByExtensions(document)
&& filterByKeyword(document)
&& filterByTag(document);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,10 @@ void addInjectDoc(
@Param("injectId") String injectId,
@Param("documentId") String docId,
@Param("documentAttached") boolean docAttached);

@Modifying
@Query(
value = "UPDATE injects_documents SET inject_id = :injectId where inject_id = :oldInjectId",
nativeQuery = true)
void updateInjectId(@Param("injectId") String injectId, @Param("oldInjectId") String oldInjectId);
}
Loading