@gov-cy/govcy-express-services 1.6.2 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gov-cy/govcy-express-services",
3
- "version": "1.6.2",
3
+ "version": "1.6.3",
4
4
  "description": "An Express-based system that dynamically renders services using @gov-cy/govcy-frontend-renderer and posts data to a submission API.",
5
5
  "author": "DMRID - DSF Team",
6
6
  "license": "MIT",
@@ -181,4 +181,16 @@ export function cyLoginPolicy(req, res, next) {
181
181
  next
182
182
  );
183
183
  }
184
- /************************************************************************/
184
+ /************************************************************************/
185
+
186
+ export function getUniqueIdentifier(req) {
187
+ // https://dev.azure.com/cyprus-gov-cds/Documentation/_wiki/wikis/Documentation/82/Available-Scopes-and-Claims
188
+ const user = req?.session?.user || {};
189
+
190
+ const id =
191
+ user.unique_identifier ??
192
+ user.legal_unique_identifier ??
193
+ "";
194
+
195
+ return String(id);
196
+ }
@@ -184,7 +184,7 @@ export function govcyReviewPostHandler() {
184
184
  const submissionData = prepareSubmissionData(req, siteId, service);
185
185
 
186
186
  // Prepare submission data for API
187
- const submissionDataAPI = prepareSubmissionDataAPI(submissionData, service);
187
+ const submissionDataAPI = prepareSubmissionDataAPI(submissionData, service, req);
188
188
 
189
189
  logger.debug("Prepared submission data for API:", submissionDataAPI);
190
190
 
@@ -437,10 +437,13 @@ export const staticResources = {
437
437
  {
438
438
  check: "valid",
439
439
  params: {
440
- checkValue: "noSpecialChars",
440
+ checkValue: "nameCY",
441
441
  message: {
442
- el: "Το όνομα σας πρέπει να αποτελείται μόνο από γράμματα, αριθμούς και ορισμένους άλλους χαρακτήρες",
443
- en: "Your name must consist only of letters, numbers and some other characters",
442
+ // el: "Το όνομά σας μπορεί να περιέχει μόνο γράμματα, κενά, παύλες (-), αποστρόφους (’ ‘ ʼ) και τελείες (.)",
443
+ // en: "Your name can only include letters, spaces, hyphens (-), apostrophes (’ ‘ ʼ) and dots (.)",
444
+ // tr: ""
445
+ el: "Το όνομά σας μπορεί να περιέχει μόνο γράμματα, κενά, παύλες (-), αποστρόφους (’ ‘ ʼ) και τελείες (.)",
446
+ en: "Your name can only include letters, spaces, hyphens (-), curly apostrophes (’ ‘ ʼ) and dots (.)",
444
447
  tr: ""
445
448
  }
446
449
  }
@@ -8,6 +8,7 @@ import { getServiceConfigData, getPageConfigData } from "./govcyLoadConfigData.m
8
8
  import { getMultipleThingsEmptyFormData } from "./govcyFormHandling.mjs";
9
9
  import { logger } from "./govcyLogger.mjs";
10
10
  import { createUmdManualPageTemplate } from "../middleware/govcyUpdateMyDetails.mjs"
11
+ import { getUniqueIdentifier } from "../middleware/cyLoginAuth.mjs"
11
12
  import nunjucks from "nunjucks";
12
13
 
13
14
  /**
@@ -101,14 +102,14 @@ export function prepareSubmissionData(req, siteId, service) {
101
102
  // radios conditional elements
102
103
  if (el.element === "radios") {
103
104
  for (const radioItem of el.params.items || []) {
104
-
105
+
105
106
  const isSelected = radioItem.value === value; // 🔸 to decide to populate only selected
106
-
107
+
107
108
  for (const condEl of radioItem.conditionalElements || []) {
108
109
  if (!ALLOWED_FORM_ELEMENTS.includes(condEl.element)) continue;
109
110
  const condId = condEl.params?.id || condEl.params?.name;
110
111
  if (!condId) continue;
111
-
112
+
112
113
  // 🔸only populate if selected, otherwise empty string
113
114
  let condValue = isSelected
114
115
  ? getValue(condEl, pageUrl, req, siteId, idx)
@@ -268,9 +269,10 @@ export function prepareSubmissionData(req, siteId, service) {
268
269
  *
269
270
  * @param {object} data data prepared by `prepareSubmissionData`\
270
271
  * @param {object} service service config data
272
+ * @param {object} req request object
271
273
  * @returns {object} The API-ready submission data object with all fields as strings
272
274
  */
273
- export function prepareSubmissionDataAPI(data, service) {
275
+ export function prepareSubmissionDataAPI(data, service, req) {
274
276
 
275
277
  //deep copy data to avoid mutating the original
276
278
  let dataObj = JSON.parse(JSON.stringify(data));
@@ -290,12 +292,20 @@ export function prepareSubmissionDataAPI(data, service) {
290
292
  let pageEmptyData = getMultipleThingsEmptyFormData(page);
291
293
  //replace the dataObj.submissionData[key] with the empty data
292
294
  dataObj.submissionData[key] = [pageEmptyData];
293
-
295
+
294
296
  } catch (error) {
295
297
  logger.error('Error getting pageConfigData:', key);
296
298
  }
297
299
  }
298
300
  }
301
+ // get the Unique Identifier of the user
302
+ const uniqueIdentifier = getUniqueIdentifier(req);
303
+
304
+ // Insert unique identifier as the first item in the array
305
+ dataObj.submissionData = {
306
+ cylogin_unique_identifier: uniqueIdentifier,
307
+ ...(dataObj.submissionData || {})
308
+ };
299
309
  }
300
310
 
301
311
  return {
@@ -936,7 +946,7 @@ export function generateSubmitEmail(service, submissionData, submissionId, req)
936
946
  // Custom page
937
947
  // ==========================================================
938
948
  // 🆕 Check for custom pages that should appear after this one
939
- for (const [customKey, customPage] of customPageEntries) {
949
+ for (const [customKey, customPage] of customPageEntries) {
940
950
  const insertAfter = customPage.insertAfterPageUrl;
941
951
  if (insertAfter && insertAfter === pageUrl && Array.isArray(customPage.email)) {
942
952
  pagesInBody.push(customPage.pageUrl); // Track custom page key for later
@@ -952,7 +962,7 @@ export function generateSubmitEmail(service, submissionData, submissionId, req)
952
962
  body.push(...customPage.email);
953
963
  }
954
964
  }
955
-
965
+
956
966
  // ==========================================================
957
967
  }
958
968
 
@@ -29,7 +29,8 @@ function validateValue(value, rules) {
29
29
  alphaNum: (val) => /^[A-Za-zΑ-Ωα-ω\u0370-\u03ff\u1f00-\u1fff0-9\s]+$/.test(val),
30
30
  noSpecialChars: (val) => /^([0-9]|[A-Z]|[a-z]|[α-ω]|[Α-Ω]|[,]|[.]|[-]|[(]|[)]|[?]|[!]|[;]|[:]|[\n]|[\r]|[ _]|[\u0370-\u03ff\u1f00-\u1fff])+$/.test(val),
31
31
  noSpecialCharsEl: (val) => /^([0-9]|[α-ω]|[Α-Ω]|[,]|[.]|[-]|[(]|[)]|[?]|[!]|[;]|[:]|[\n]|[\r]|[ _]|[\u0370-\u03ff\u1f00-\u1fff])+$/.test(val),
32
- name: (val) => /^[A-Za-zΑ-Ωα-ω\u0370-\u03ff\u1f00-\u1fff\s'-]+$/.test(val),
32
+ name: (val) => /^[\p{L}\p{M}\s’‘ʼ.-]+$/u.test(val),
33
+ nameCY: (val) => /^[A-Za-zΑ-Ωα-ωΆ-Ώά-ώΪΫϊΐϋΰÇĞİIŞÖÜçğışöü\s.’‘ʼ-]*$/u.test(val),
33
34
  tel: (val) => /^(?:\+|00)?[\d\s\-()]{8,20}$/.test(val.replace(/[\s\-()]/g, '')),
34
35
  mobile: (val) => /^(?:\+|00)?[\d\s\-()]{8,20}$/.test(val.replace(/[\s\-()]/g, '')),
35
36
  // telCY: (val) => /^(?:\+|00)?357[-\s]?(2|9)\d{7}$/.test(val.replace(/[\s\-()]/g, '')),