From efd1f332c460df57c23bd5fa6aa2f0d91b856163 Mon Sep 17 00:00:00 2001 From: Courtney Myers Date: Thu, 16 Jan 2025 15:00:59 -0500 Subject: [PATCH 1/2] Add env variables for snippets of text found within each Formio form's intro section and update Formio status API endpoints to look for substring within each form's schema before returning a status of true (ensures the correct Formio schema is applied to each form) --- app/server/.env.example | 9 ++++ app/server/app/config/formio.js | 37 +++++++++++++-- app/server/app/index.js | 9 ++++ app/server/app/routes/status.js | 83 ++++++++++++++++++++++++++------- 4 files changed, 119 insertions(+), 19 deletions(-) diff --git a/app/server/.env.example b/app/server/.env.example index 23ceb1d2..1e025a36 100644 --- a/app/server/.env.example +++ b/app/server/.env.example @@ -20,6 +20,15 @@ CSB_2023_CRF_OPEN=true CSB_2024_FRF_OPEN=true CSB_2024_PRF_OPEN=true CSB_2024_CRF_OPEN=true +FORMIO_2022_FRF_SUBSTRING= +FORMIO_2022_PRF_SUBSTRING= +FORMIO_2022_CRF_SUBSTRING= +FORMIO_2023_FRF_SUBSTRING= +FORMIO_2023_PRF_SUBSTRING= +FORMIO_2023_CRF_SUBSTRING= +FORMIO_2024_FRF_SUBSTRING= +FORMIO_2024_PRF_SUBSTRING= +FORMIO_2024_CRF_SUBSTRING= FORMIO_2022_FRF_PATH= FORMIO_2022_PRF_PATH= FORMIO_2022_CRF_PATH= diff --git a/app/server/app/config/formio.js b/app/server/app/config/formio.js index f3b3e00f..720169d6 100644 --- a/app/server/app/config/formio.js +++ b/app/server/app/config/formio.js @@ -15,9 +15,15 @@ const { CSB_2024_FRF_OPEN, CSB_2024_PRF_OPEN, CSB_2024_CRF_OPEN, - FORMIO_BASE_URL, - FORMIO_PROJECT_NAME, - FORMIO_API_KEY, + FORMIO_2022_FRF_SUBSTRING, + FORMIO_2022_PRF_SUBSTRING, + FORMIO_2022_CRF_SUBSTRING, + FORMIO_2023_FRF_SUBSTRING, + FORMIO_2023_PRF_SUBSTRING, + FORMIO_2023_CRF_SUBSTRING, + FORMIO_2024_FRF_SUBSTRING, + FORMIO_2024_PRF_SUBSTRING, + FORMIO_2024_CRF_SUBSTRING, FORMIO_2022_FRF_PATH, FORMIO_2022_PRF_PATH, FORMIO_2022_CRF_PATH, @@ -29,6 +35,9 @@ const { FORMIO_2024_PRF_PATH, FORMIO_2024_CRF_PATH, FORMIO_2024_CHANGE_PATH, + FORMIO_BASE_URL, + FORMIO_PROJECT_NAME, + FORMIO_API_KEY, } = process.env; const formioProjectUrl = `${FORMIO_BASE_URL}/${FORMIO_PROJECT_NAME}`; @@ -57,6 +66,27 @@ const formUrl = { }, }; +/** + * Stores intro text substring found within each form by rebate year. + */ +const formIntroSubstring = { + 2022: { + frf: FORMIO_2022_FRF_SUBSTRING, + prf: FORMIO_2022_PRF_SUBSTRING, + crf: FORMIO_2022_CRF_SUBSTRING, + }, + 2023: { + frf: FORMIO_2023_FRF_SUBSTRING, + prf: FORMIO_2023_PRF_SUBSTRING, + crf: FORMIO_2023_CRF_SUBSTRING, + }, + 2024: { + frf: FORMIO_2024_FRF_SUBSTRING, + prf: FORMIO_2024_PRF_SUBSTRING, + crf: FORMIO_2024_CRF_SUBSTRING, + }, +}; + /** * Stores whether the submission period is open for each form by rebate year. */ @@ -138,6 +168,7 @@ module.exports = { axiosFormio, formioProjectUrl, formUrl, + formIntroSubstring, submissionPeriodOpen, formioCSBMetadata, formioExampleMongoId, diff --git a/app/server/app/index.js b/app/server/app/index.js index 0ee2fce4..4e941af3 100644 --- a/app/server/app/index.js +++ b/app/server/app/index.js @@ -39,6 +39,15 @@ const requiredEnvironmentVariables = [ "CSB_2024_FRF_OPEN", "CSB_2024_PRF_OPEN", "CSB_2024_CRF_OPEN", + "FORMIO_2022_FRF_SUBSTRING", + "FORMIO_2022_PRF_SUBSTRING", + "FORMIO_2022_CRF_SUBSTRING", + "FORMIO_2023_FRF_SUBSTRING", + "FORMIO_2023_PRF_SUBSTRING", + // "FORMIO_2023_CRF_SUBSTRING", + "FORMIO_2024_FRF_SUBSTRING", + "FORMIO_2024_PRF_SUBSTRING", + // "FORMIO_2024_CRF_SUBSTRING", "FORMIO_2022_FRF_PATH", "FORMIO_2022_PRF_PATH", "FORMIO_2022_CRF_PATH", diff --git a/app/server/app/routes/status.js b/app/server/app/routes/status.js index 0aff0515..4f5a136e 100644 --- a/app/server/app/routes/status.js +++ b/app/server/app/routes/status.js @@ -1,14 +1,43 @@ const express = require("express"); // --- -const { axiosFormio, formUrl } = require("../config/formio"); +const { + axiosFormio, + formUrl, + formIntroSubstring, +} = require("../config/formio"); const { getSamEntities } = require("../utilities/bap"); /** - * Verify that schema has type of form and a title exists - * (confirming Formio returned a valid schema). + * Return the intro text from the "Welcome" section of a form. */ -function verifySchema(schema) { - return schema.type === "form" && !!schema.title; +function getFormIntroText(schema) { + const intro = schema.components.find((c) => c.title === "Welcome"); + if (!intro) return ""; + + const result = intro.components.reduce((string, component) => { + const { type, tag, content } = component; + const text = type === "htmlelement" && tag !== "style" && content; + if (text) + string += text + .replace(/"/g, "'") // convert double quotes to single quotes + .replace(/\r?\n/g, "") // remove new line characters + .replace(/\s\s+/g, " "); // remove double spaces + return string; + }, ""); + + return result; +} + +/** + * Verify the schema has a type of form, a title exists, and the form's intro + * text contains the correct value (confirming Formio returns the valid schema). + */ +function verifySchema({ schema, substring }) { + return ( + schema.type === "form" && + !!schema.title && + getFormIntroText(schema).includes(substring) + ); } const router = express.Router(); @@ -33,11 +62,13 @@ router.get("/bap/sam", (req, res) => { }); router.get("/formio/2022/frf", (req, res) => { + const substring = formIntroSubstring["2022"].frf; + axiosFormio(req) .get(formUrl["2022"].frf) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor @@ -46,11 +77,13 @@ router.get("/formio/2022/frf", (req, res) => { }); router.get("/formio/2022/prf", (req, res) => { + const substring = formIntroSubstring["2022"].prf; + axiosFormio(req) .get(formUrl["2022"].prf) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor @@ -59,11 +92,13 @@ router.get("/formio/2022/prf", (req, res) => { }); router.get("/formio/2022/crf", (req, res) => { + const substring = formIntroSubstring["2022"].crf; + axiosFormio(req) .get(formUrl["2022"].crf) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor @@ -72,11 +107,13 @@ router.get("/formio/2022/crf", (req, res) => { }); router.get("/formio/2023/frf", (req, res) => { + const substring = formIntroSubstring["2023"].frf; + axiosFormio(req) .get(formUrl["2023"].frf) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor @@ -85,11 +122,13 @@ router.get("/formio/2023/frf", (req, res) => { }); router.get("/formio/2023/prf", (req, res) => { + const substring = formIntroSubstring["2023"].prf; + axiosFormio(req) .get(formUrl["2023"].prf) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor @@ -98,11 +137,13 @@ router.get("/formio/2023/prf", (req, res) => { }); // router.get("/formio/2023/crf", (req, res) => { +// const substring = formIntroSubstring["2023"].crf; +// // axiosFormio(req) // .get(formUrl["2023"].crf) // .then((axiosRes) => axiosRes.data) // .then((schema) => { -// return res.json({ status: verifySchema(schema) }); +// return res.json({ status: verifySchema({ schema, substring }) }); // }) // .catch((_error) => { // // NOTE: error is logged in axiosFormio response interceptor @@ -111,11 +152,13 @@ router.get("/formio/2023/prf", (req, res) => { // }); router.get("/formio/2023/change", (req, res) => { + const substring = ""; + axiosFormio(req) .get(formUrl["2023"].change) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor @@ -124,11 +167,13 @@ router.get("/formio/2023/change", (req, res) => { }); router.get("/formio/2024/frf", (req, res) => { + const substring = formIntroSubstring["2024"].frf; + axiosFormio(req) .get(formUrl["2024"].frf) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor @@ -137,11 +182,13 @@ router.get("/formio/2024/frf", (req, res) => { }); router.get("/formio/2024/prf", (req, res) => { + const substring = formIntroSubstring["2024"].prf; + axiosFormio(req) .get(formUrl["2024"].prf) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor @@ -150,11 +197,13 @@ router.get("/formio/2024/prf", (req, res) => { }); // router.get("/formio/2024/crf", (req, res) => { +// const substring = formIntroSubstring["2024"].crf; +// // axiosFormio(req) // .get(formUrl["2024"].crf) // .then((axiosRes) => axiosRes.data) // .then((schema) => { -// return res.json({ status: verifySchema(schema) }); +// return res.json({ status: verifySchema({ schema, substring }) }); // }) // .catch((_error) => { // // NOTE: error is logged in axiosFormio response interceptor @@ -163,11 +212,13 @@ router.get("/formio/2024/prf", (req, res) => { // }); router.get("/formio/2024/change", (req, res) => { + const substring = ""; + axiosFormio(req) .get(formUrl["2024"].change) .then((axiosRes) => axiosRes.data) .then((schema) => { - return res.json({ status: verifySchema(schema) }); + return res.json({ status: verifySchema({ schema, substring }) }); }) .catch((_error) => { // NOTE: error is logged in axiosFormio response interceptor From 6ad186a1c2b7aca2d2d127fc063fdaebc58f3be2 Mon Sep 17 00:00:00 2001 From: Courtney Myers Date: Thu, 16 Jan 2025 15:23:58 -0500 Subject: [PATCH 2/2] Update dev and staging GitHub Actions to set new Formio form substring env variables --- .github/workflows/dev.yml | 18 ++++++++++++++++++ .github/workflows/staging.yml | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index ffe86f76..0a13122b 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -51,6 +51,15 @@ jobs: CSB_2024_FRF_OPEN: true CSB_2024_PRF_OPEN: true CSB_2024_CRF_OPEN: true + FORMIO_2022_FRF_SUBSTRING: ${{ secrets.FORMIO_2022_FRF_SUBSTRING }} + FORMIO_2022_PRF_SUBSTRING: ${{ secrets.FORMIO_2022_PRF_SUBSTRING }} + FORMIO_2022_CRF_SUBSTRING: ${{ secrets.FORMIO_2022_CRF_SUBSTRING }} + FORMIO_2023_FRF_SUBSTRING: ${{ secrets.FORMIO_2023_FRF_SUBSTRING }} + FORMIO_2023_PRF_SUBSTRING: ${{ secrets.FORMIO_2023_PRF_SUBSTRING }} + FORMIO_2023_CRF_SUBSTRING: ${{ secrets.FORMIO_2023_CRF_SUBSTRING }} + FORMIO_2024_FRF_SUBSTRING: ${{ secrets.FORMIO_2024_FRF_SUBSTRING }} + FORMIO_2024_PRF_SUBSTRING: ${{ secrets.FORMIO_2024_PRF_SUBSTRING }} + FORMIO_2024_CRF_SUBSTRING: ${{ secrets.FORMIO_2024_CRF_SUBSTRING }} FORMIO_2022_FRF_PATH: ${{ secrets.FORMIO_2022_FRF_PATH }} FORMIO_2022_PRF_PATH: ${{ secrets.FORMIO_2022_PRF_PATH }} FORMIO_2022_CRF_PATH: ${{ secrets.FORMIO_2022_CRF_PATH }} @@ -145,6 +154,15 @@ jobs: cf set-env $APP_NAME "CSB_2024_FRF_OPEN" "$CSB_2024_FRF_OPEN" > /dev/null cf set-env $APP_NAME "CSB_2024_PRF_OPEN" "$CSB_2024_PRF_OPEN" > /dev/null cf set-env $APP_NAME "CSB_2024_CRF_OPEN" "$CSB_2024_CRF_OPEN" > /dev/null + cf set-env $APP_NAME "FORMIO_2022_FRF_SUBSTRING" "$FORMIO_2022_FRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2022_PRF_SUBSTRING" "$FORMIO_2022_PRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2022_CRF_SUBSTRING" "$FORMIO_2022_CRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2023_FRF_SUBSTRING" "$FORMIO_2023_FRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2023_PRF_SUBSTRING" "$FORMIO_2023_PRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2023_CRF_SUBSTRING" "$FORMIO_2023_CRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2024_FRF_SUBSTRING" "$FORMIO_2024_FRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2024_PRF_SUBSTRING" "$FORMIO_2024_PRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2024_CRF_SUBSTRING" "$FORMIO_2024_CRF_SUBSTRING" > /dev/null cf set-env $APP_NAME "FORMIO_2022_FRF_PATH" "$FORMIO_2022_FRF_PATH" > /dev/null cf set-env $APP_NAME "FORMIO_2022_PRF_PATH" "$FORMIO_2022_PRF_PATH" > /dev/null cf set-env $APP_NAME "FORMIO_2022_CRF_PATH" "$FORMIO_2022_CRF_PATH" > /dev/null diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 97cf5fc2..6b712ac2 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -51,6 +51,15 @@ jobs: CSB_2024_FRF_OPEN: true CSB_2024_PRF_OPEN: true CSB_2024_CRF_OPEN: true + FORMIO_2022_FRF_SUBSTRING: ${{ secrets.FORMIO_2022_FRF_SUBSTRING }} + FORMIO_2022_PRF_SUBSTRING: ${{ secrets.FORMIO_2022_PRF_SUBSTRING }} + FORMIO_2022_CRF_SUBSTRING: ${{ secrets.FORMIO_2022_CRF_SUBSTRING }} + FORMIO_2023_FRF_SUBSTRING: ${{ secrets.FORMIO_2023_FRF_SUBSTRING }} + FORMIO_2023_PRF_SUBSTRING: ${{ secrets.FORMIO_2023_PRF_SUBSTRING }} + FORMIO_2023_CRF_SUBSTRING: ${{ secrets.FORMIO_2023_CRF_SUBSTRING }} + FORMIO_2024_FRF_SUBSTRING: ${{ secrets.FORMIO_2024_FRF_SUBSTRING }} + FORMIO_2024_PRF_SUBSTRING: ${{ secrets.FORMIO_2024_PRF_SUBSTRING }} + FORMIO_2024_CRF_SUBSTRING: ${{ secrets.FORMIO_2024_CRF_SUBSTRING }} FORMIO_2022_FRF_PATH: ${{ secrets.FORMIO_2022_FRF_PATH }} FORMIO_2022_PRF_PATH: ${{ secrets.FORMIO_2022_PRF_PATH }} FORMIO_2022_CRF_PATH: ${{ secrets.FORMIO_2022_CRF_PATH }} @@ -145,6 +154,15 @@ jobs: cf set-env $APP_NAME "CSB_2024_FRF_OPEN" "$CSB_2024_FRF_OPEN" > /dev/null cf set-env $APP_NAME "CSB_2024_PRF_OPEN" "$CSB_2024_PRF_OPEN" > /dev/null cf set-env $APP_NAME "CSB_2024_CRF_OPEN" "$CSB_2024_CRF_OPEN" > /dev/null + cf set-env $APP_NAME "FORMIO_2022_FRF_SUBSTRING" "$FORMIO_2022_FRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2022_PRF_SUBSTRING" "$FORMIO_2022_PRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2022_CRF_SUBSTRING" "$FORMIO_2022_CRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2023_FRF_SUBSTRING" "$FORMIO_2023_FRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2023_PRF_SUBSTRING" "$FORMIO_2023_PRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2023_CRF_SUBSTRING" "$FORMIO_2023_CRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2024_FRF_SUBSTRING" "$FORMIO_2024_FRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2024_PRF_SUBSTRING" "$FORMIO_2024_PRF_SUBSTRING" > /dev/null + cf set-env $APP_NAME "FORMIO_2024_CRF_SUBSTRING" "$FORMIO_2024_CRF_SUBSTRING" > /dev/null cf set-env $APP_NAME "FORMIO_2022_FRF_PATH" "$FORMIO_2022_FRF_PATH" > /dev/null cf set-env $APP_NAME "FORMIO_2022_PRF_PATH" "$FORMIO_2022_PRF_PATH" > /dev/null cf set-env $APP_NAME "FORMIO_2022_CRF_PATH" "$FORMIO_2022_CRF_PATH" > /dev/null