CE-1772 - update fileDownload adornment type to be able to specify a process name or custom code-ref, to run along with downloading a field's file.

This commit is contained in:
2024-12-17 11:40:11 -06:00
parent 96761b7162
commit c5f41a8042
7 changed files with 371 additions and 11 deletions

View File

@ -29,8 +29,11 @@ import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
import com.kingsrook.qqq.backend.core.logging.QCollectingLogger;
@ -39,12 +42,19 @@ import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReferenceLambda;
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.modules.backend.implementations.mock.MockBackendModule;
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
import com.kingsrook.qqq.middleware.javalin.misc.DownloadFileSupplementalAction;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import org.apache.logging.log4j.Level;
@ -282,6 +292,69 @@ class QJavalinImplementationTest extends QJavalinTestBase
/*******************************************************************************
** test downloading from a URL field
**
*******************************************************************************/
@Test
public void test_dataDownloadRecordFieldUrl()
{
try
{
TestDownloadFileSupplementalAction.callCount = 0;
Unirest.config().followRedirects(false);
////////////////////////////////////////////////////////////////////////////////////////////////////////
// first request - has no custom code - should just give us back a redirect to the value in the field //
////////////////////////////////////////////////////////////////////////////////////////////////////////
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/1/licenseScanPdfUrl/License-1.pdf").asString();
assertEquals(302, response.getStatus());
assertThat(response.getHeaders().get("location").get(0)).contains("https://");
////////////////////////////////////////////////////
// set a code-reference on the download adornment //
////////////////////////////////////////////////////
Optional<FieldAdornment> fileDownloadAdornment = QJavalinImplementation.getQInstance().getTable(TestUtils.TABLE_NAME_PERSON)
.getField("licenseScanPdfUrl")
.getAdornment(AdornmentType.FILE_DOWNLOAD);
fileDownloadAdornment.get().withValue(AdornmentType.FileDownloadValues.SUPPLEMENTAL_CODE_REFERENCE, new QCodeReference(TestDownloadFileSupplementalAction.class));
/////////////////////////////////////////
// request again - assert the code ran //
/////////////////////////////////////////
assertEquals(0, TestDownloadFileSupplementalAction.callCount);
response = Unirest.get(BASE_URL + "/data/person/1/licenseScanPdfUrl/License-1.pdf").asString();
assertEquals(302, response.getStatus());
assertThat(response.getHeaders().get("location").get(0)).contains("https://");
assertEquals(1, TestDownloadFileSupplementalAction.callCount);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// set adornment to run process (note, leaving the code-ref - this demonstrates that process "trumps" if both exist) //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
AtomicInteger processRunCount = new AtomicInteger(0);
QJavalinImplementation.getQInstance().addProcess(new QProcessMetaData().withName("testDownloadProcess").withStep(
new QBackendStepMetaData().withName("execute").withCode(new QCodeReferenceLambda<BackendStep>((input, output) -> processRunCount.incrementAndGet()))
));
fileDownloadAdornment.get().withValue(AdornmentType.FileDownloadValues.SUPPLEMENTAL_PROCESS_NAME, "testDownloadProcess");
/////////////////////////////////////////
// request again - assert the code ran //
/////////////////////////////////////////
response = Unirest.get(BASE_URL + "/data/person/1/licenseScanPdfUrl/License-1.pdf").asString();
assertEquals(302, response.getStatus());
assertThat(response.getHeaders().get("location").get(0)).contains("https://");
assertEquals(1, TestDownloadFileSupplementalAction.callCount);
assertEquals(1, processRunCount.get());
}
finally
{
Unirest.config().reset();
}
}
/*******************************************************************************
** test a table get (single record) for an id that isn't found
**
@ -1395,4 +1468,19 @@ class QJavalinImplementationTest extends QJavalinTestBase
}
}
/***************************************************************************
**
***************************************************************************/
public static class TestDownloadFileSupplementalAction implements DownloadFileSupplementalAction
{
static int callCount = 0;
@Override
public void run(DownloadFileSupplementalActionInput input, DownloadFileSupplementalActionOutput output) throws QException
{
callCount++;
}
}
}

View File

@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.javalin;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
@ -316,6 +317,8 @@ public class TestUtils
.withField(new QFieldMetaData("testScriptId", QFieldType.INTEGER).withBackendName("test_script_id"))
.withField(new QFieldMetaData("photo", QFieldType.BLOB).withBackendName("photo"))
.withField(new QFieldMetaData("photoFileName", QFieldType.STRING).withBackendName("photo_file_name"))
.withField(new QFieldMetaData("licenseScanPdfUrl", QFieldType.STRING).withBackendName("license_scan_pdf_url"))
.withAssociation(new Association().withName("pets").withJoinName("personJoinPet").withAssociatedTableName(TABLE_NAME_PET))
.withAssociatedScript(new AssociatedScript()
.withFieldName("testScriptId")
@ -331,6 +334,11 @@ public class TestUtils
.withValue(AdornmentType.FileDownloadValues.DEFAULT_MIME_TYPE, "image")
.withValue(AdornmentType.FileDownloadValues.FILE_NAME_FIELD, "photoFileName"));
qTableMetaData.getField("licenseScanPdfUrl")
.withFieldAdornment(new FieldAdornment(AdornmentType.FILE_DOWNLOAD)
.withValue(AdornmentType.FileDownloadValues.FILE_NAME_FORMAT, "License-%s.pdf")
.withValue(AdornmentType.FileDownloadValues.FILE_NAME_FORMAT_FIELDS, new ArrayList<>(List.of("id"))));
return (qTableMetaData);
}

View File

@ -33,10 +33,11 @@ CREATE TABLE person
partner_person_id INT,
test_script_id INT,
photo BLOB,
photo_file_name VARCHAR(50)
photo_file_name VARCHAR(50),
license_scan_pdf_url VARCHAR(250)
);
INSERT INTO person (id, first_name, last_name, birth_date, email, partner_person_id, photo, photo_file_name) VALUES (1, 'Darin', 'Kelkhoff', '1980-05-31', 'darin.kelkhoff@gmail.com', 6, '12345', 'darin-photo.png');
INSERT INTO person (id, first_name, last_name, birth_date, email, partner_person_id, photo, photo_file_name, license_scan_pdf_url) VALUES (1, 'Darin', 'Kelkhoff', '1980-05-31', 'darin.kelkhoff@gmail.com', 6, '12345', 'darin-photo.png', 'https://somedomain/somepath.pdf');
INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (2, 'James', 'Maes', '1980-05-15', 'jmaes@mmltholdings.com');
INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (3, 'Tim', 'Chamberlain', '1976-05-28', 'tchamberlain@mmltholdings.com');
INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (4, 'Tyler', 'Samples', '1990-01-01', 'tsamples@mmltholdings.com');