@opengovsg/formsg-sdk 7.4.1 → 7.5.0
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/dist/cjs/adapt-v3-to-v4.d.ts +7 -1
- package/dist/cjs/adapt-v3-to-v4.js +12 -6
- package/dist/cjs/crypto-v3.d.ts +2 -1
- package/dist/cjs/crypto-v3.js +29 -3
- package/dist/esm/adapt-v3-to-v4.d.ts +7 -1
- package/dist/esm/adapt-v3-to-v4.js +10 -6
- package/dist/esm/crypto-v3.d.ts +2 -1
- package/dist/esm/crypto-v3.js +30 -4
- package/package.json +1 -1
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { FormFieldsV3 } from './types';
|
|
2
|
-
import { AdaptV3ToV4Options, FieldResponsesV4 } from './types-v4';
|
|
2
|
+
import { AdaptV3ToV4Options, FieldResponsesV4, FormFieldMeta } from './types-v4';
|
|
3
|
+
/**
|
|
4
|
+
* Derives question text from form field metadata, prefixing MyInfo fields.
|
|
5
|
+
* Shared between V3→V4 adaptation and the V4 question backfill in
|
|
6
|
+
* CryptoV3.decryptToV4 so the two stay consistent.
|
|
7
|
+
*/
|
|
8
|
+
export declare const deriveQuestionFromMeta: (meta?: FormFieldMeta) => string;
|
|
3
9
|
/**
|
|
4
10
|
* Converts V3 decrypted responses to V4 normalized shape.
|
|
5
11
|
*
|
|
@@ -11,6 +11,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
11
11
|
return __assign.apply(this, arguments);
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.deriveQuestionFromMeta = void 0;
|
|
14
15
|
exports.adaptV3ToV4 = adaptV3ToV4;
|
|
15
16
|
var constants_v4_1 = require("./constants-v4");
|
|
16
17
|
var crypto_1 = require("./util/crypto");
|
|
@@ -81,6 +82,13 @@ var convertSignatureAnswer = function (answer) {
|
|
|
81
82
|
type: 'draw',
|
|
82
83
|
};
|
|
83
84
|
};
|
|
85
|
+
/**
|
|
86
|
+
* Derives question text from form field metadata, prefixing MyInfo fields.
|
|
87
|
+
* Shared between V3→V4 adaptation and the V4 question backfill in
|
|
88
|
+
* CryptoV3.decryptToV4 so the two stay consistent.
|
|
89
|
+
*/
|
|
90
|
+
var deriveQuestionFromMeta = function (meta) { var _a, _b; return (meta === null || meta === void 0 ? void 0 : meta.myInfo) ? "[Myinfo] ".concat((_a = meta.question) !== null && _a !== void 0 ? _a : '') : ((_b = meta === null || meta === void 0 ? void 0 : meta.question) !== null && _b !== void 0 ? _b : ''); };
|
|
91
|
+
exports.deriveQuestionFromMeta = deriveQuestionFromMeta;
|
|
84
92
|
// since v3 answer types when decrypted in sdk are not well-typed, we do best-effort conversion based on field type
|
|
85
93
|
var convertAnswer = function (fieldType, answer) {
|
|
86
94
|
if (constants_v4_1.GENERIC_STRING_FIELD_TYPES.has(fieldType)) {
|
|
@@ -119,20 +127,18 @@ var convertAnswer = function (fieldType, answer) {
|
|
|
119
127
|
* @returns V4 responses record
|
|
120
128
|
*/
|
|
121
129
|
function adaptV3ToV4(v3Responses, options) {
|
|
122
|
-
var _a, _b
|
|
130
|
+
var _a, _b;
|
|
123
131
|
if (options === void 0) { options = {}; }
|
|
124
132
|
var provenance = (_a = options.provenance) !== null && _a !== void 0 ? _a : {
|
|
125
133
|
submittedAt: new Date().toISOString(),
|
|
126
134
|
};
|
|
127
135
|
var formFields = (_b = options.formFields) !== null && _b !== void 0 ? _b : {};
|
|
128
136
|
var v4Responses = {};
|
|
129
|
-
for (var _i = 0,
|
|
130
|
-
var
|
|
137
|
+
for (var _i = 0, _c = Object.entries(v3Responses); _i < _c.length; _i++) {
|
|
138
|
+
var _d = _c[_i], fieldId = _d[0], field = _d[1];
|
|
131
139
|
var meta = formFields[fieldId];
|
|
132
140
|
var myInfo = meta === null || meta === void 0 ? void 0 : meta.myInfo;
|
|
133
|
-
var question =
|
|
134
|
-
? "[Myinfo] ".concat((_c = meta === null || meta === void 0 ? void 0 : meta.question) !== null && _c !== void 0 ? _c : '')
|
|
135
|
-
: ((_d = meta === null || meta === void 0 ? void 0 : meta.question) !== null && _d !== void 0 ? _d : '');
|
|
141
|
+
var question = (0, exports.deriveQuestionFromMeta)(meta);
|
|
136
142
|
v4Responses[fieldId] = __assign({ fieldType: field.fieldType, question: question, answer: convertAnswer(field.fieldType, field.answer), provenance: provenance }, (myInfo && { myInfo: myInfo }));
|
|
137
143
|
}
|
|
138
144
|
return v4Responses;
|
package/dist/cjs/crypto-v3.d.ts
CHANGED
|
@@ -40,7 +40,8 @@ export default class CryptoV3 extends CryptoBase {
|
|
|
40
40
|
decrypt: (formSecretKey: string, decryptParams: DecryptParamsV3) => DecryptedContentV3 | null;
|
|
41
41
|
/**
|
|
42
42
|
* Decrypts an encrypted submission and returns it in V4 format.
|
|
43
|
-
* If the decrypted data is already in V4 format, it is returned
|
|
43
|
+
* If the decrypted data is already in V4 format, it is returned with any
|
|
44
|
+
* missing question text backfilled from the provided formFields metadata.
|
|
44
45
|
* If the decrypted data is in V3 format, it is adapted to V4 using the provided formFields metadata.
|
|
45
46
|
* @param formSecretKey The base-64 encoded form secret key for decrypting the submission.
|
|
46
47
|
* @param decryptParams The params containing encrypted content, encrypted submission key and information.
|
package/dist/cjs/crypto-v3.js
CHANGED
|
@@ -58,6 +58,30 @@ function isFieldResponsesV4(responses) {
|
|
|
58
58
|
var first = entries[0];
|
|
59
59
|
return typeof first.provenance === 'object' && first.provenance !== null;
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Backfills question text (and myInfo metadata) on V4 responses stored
|
|
63
|
+
* without them, in place. V4 blobs written from wire bodies lack question
|
|
64
|
+
* text: the receiver shim adapts V3 bodies without the form definition in
|
|
65
|
+
* scope, and thin V4 wire bodies omit `question` entirely (the server strips
|
|
66
|
+
* it). Enrich empty questions from the form definition at read time instead.
|
|
67
|
+
* Responses that already carry a question are left untouched.
|
|
68
|
+
*/
|
|
69
|
+
function backfillMissingQuestions(responses, formFields) {
|
|
70
|
+
for (var _i = 0, _a = Object.entries(responses); _i < _a.length; _i++) {
|
|
71
|
+
var _b = _a[_i], fieldId = _b[0], response = _b[1];
|
|
72
|
+
if (response.question)
|
|
73
|
+
continue;
|
|
74
|
+
// Tolerate an omitted formFields map from untyped (JS) callers
|
|
75
|
+
var meta = formFields === null || formFields === void 0 ? void 0 : formFields[fieldId];
|
|
76
|
+
if (!meta)
|
|
77
|
+
continue;
|
|
78
|
+
response.question = (0, adapt_v3_to_v4_1.deriveQuestionFromMeta)(meta);
|
|
79
|
+
if (meta.myInfo && !response.myInfo) {
|
|
80
|
+
response.myInfo = meta.myInfo;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return responses;
|
|
84
|
+
}
|
|
61
85
|
var CryptoV3 = /** @class */ (function (_super) {
|
|
62
86
|
__extends(CryptoV3, _super);
|
|
63
87
|
function CryptoV3(_a) {
|
|
@@ -167,7 +191,8 @@ var CryptoV3 = /** @class */ (function (_super) {
|
|
|
167
191
|
};
|
|
168
192
|
/**
|
|
169
193
|
* Decrypts an encrypted submission and returns it in V4 format.
|
|
170
|
-
* If the decrypted data is already in V4 format, it is returned
|
|
194
|
+
* If the decrypted data is already in V4 format, it is returned with any
|
|
195
|
+
* missing question text backfilled from the provided formFields metadata.
|
|
171
196
|
* If the decrypted data is in V3 format, it is adapted to V4 using the provided formFields metadata.
|
|
172
197
|
* @param formSecretKey The base-64 encoded form secret key for decrypting the submission.
|
|
173
198
|
* @param decryptParams The params containing encrypted content, encrypted submission key and information.
|
|
@@ -179,9 +204,10 @@ var CryptoV3 = /** @class */ (function (_super) {
|
|
|
179
204
|
var decrypted = _this.decrypt(formSecretKey, decryptParams);
|
|
180
205
|
if (!decrypted)
|
|
181
206
|
return null;
|
|
182
|
-
// If the decrypted responses are already in V4 format, return
|
|
207
|
+
// If the decrypted responses are already in V4 format, return them with
|
|
208
|
+
// any missing question text backfilled from the form definition.
|
|
183
209
|
var responses = isFieldResponsesV4(decrypted.responses)
|
|
184
|
-
? decrypted.responses
|
|
210
|
+
? backfillMissingQuestions(decrypted.responses, formFields)
|
|
185
211
|
: (0, adapt_v3_to_v4_1.adaptV3ToV4)(decrypted.responses, { formFields: formFields });
|
|
186
212
|
return {
|
|
187
213
|
submissionSecretKey: decrypted.submissionSecretKey,
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { FormFieldsV3 } from './types';
|
|
2
|
-
import { AdaptV3ToV4Options, FieldResponsesV4 } from './types-v4';
|
|
2
|
+
import { AdaptV3ToV4Options, FieldResponsesV4, FormFieldMeta } from './types-v4';
|
|
3
|
+
/**
|
|
4
|
+
* Derives question text from form field metadata, prefixing MyInfo fields.
|
|
5
|
+
* Shared between V3→V4 adaptation and the V4 question backfill in
|
|
6
|
+
* CryptoV3.decryptToV4 so the two stay consistent.
|
|
7
|
+
*/
|
|
8
|
+
export declare const deriveQuestionFromMeta: (meta?: FormFieldMeta) => string;
|
|
3
9
|
/**
|
|
4
10
|
* Converts V3 decrypted responses to V4 normalized shape.
|
|
5
11
|
*
|
|
@@ -78,6 +78,12 @@ var convertSignatureAnswer = function (answer) {
|
|
|
78
78
|
type: 'draw',
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Derives question text from form field metadata, prefixing MyInfo fields.
|
|
83
|
+
* Shared between V3→V4 adaptation and the V4 question backfill in
|
|
84
|
+
* CryptoV3.decryptToV4 so the two stay consistent.
|
|
85
|
+
*/
|
|
86
|
+
export var deriveQuestionFromMeta = function (meta) { var _a, _b; return (meta === null || meta === void 0 ? void 0 : meta.myInfo) ? "[Myinfo] ".concat((_a = meta.question) !== null && _a !== void 0 ? _a : '') : ((_b = meta === null || meta === void 0 ? void 0 : meta.question) !== null && _b !== void 0 ? _b : ''); };
|
|
81
87
|
// since v3 answer types when decrypted in sdk are not well-typed, we do best-effort conversion based on field type
|
|
82
88
|
var convertAnswer = function (fieldType, answer) {
|
|
83
89
|
if (GENERIC_STRING_FIELD_TYPES.has(fieldType)) {
|
|
@@ -116,20 +122,18 @@ var convertAnswer = function (fieldType, answer) {
|
|
|
116
122
|
* @returns V4 responses record
|
|
117
123
|
*/
|
|
118
124
|
export function adaptV3ToV4(v3Responses, options) {
|
|
119
|
-
var _a, _b
|
|
125
|
+
var _a, _b;
|
|
120
126
|
if (options === void 0) { options = {}; }
|
|
121
127
|
var provenance = (_a = options.provenance) !== null && _a !== void 0 ? _a : {
|
|
122
128
|
submittedAt: new Date().toISOString(),
|
|
123
129
|
};
|
|
124
130
|
var formFields = (_b = options.formFields) !== null && _b !== void 0 ? _b : {};
|
|
125
131
|
var v4Responses = {};
|
|
126
|
-
for (var _i = 0,
|
|
127
|
-
var
|
|
132
|
+
for (var _i = 0, _c = Object.entries(v3Responses); _i < _c.length; _i++) {
|
|
133
|
+
var _d = _c[_i], fieldId = _d[0], field = _d[1];
|
|
128
134
|
var meta = formFields[fieldId];
|
|
129
135
|
var myInfo = meta === null || meta === void 0 ? void 0 : meta.myInfo;
|
|
130
|
-
var question =
|
|
131
|
-
? "[Myinfo] ".concat((_c = meta === null || meta === void 0 ? void 0 : meta.question) !== null && _c !== void 0 ? _c : '')
|
|
132
|
-
: ((_d = meta === null || meta === void 0 ? void 0 : meta.question) !== null && _d !== void 0 ? _d : '');
|
|
136
|
+
var question = deriveQuestionFromMeta(meta);
|
|
133
137
|
v4Responses[fieldId] = __assign({ fieldType: field.fieldType, question: question, answer: convertAnswer(field.fieldType, field.answer), provenance: provenance }, (myInfo && { myInfo: myInfo }));
|
|
134
138
|
}
|
|
135
139
|
return v4Responses;
|
package/dist/esm/crypto-v3.d.ts
CHANGED
|
@@ -40,7 +40,8 @@ export default class CryptoV3 extends CryptoBase {
|
|
|
40
40
|
decrypt: (formSecretKey: string, decryptParams: DecryptParamsV3) => DecryptedContentV3 | null;
|
|
41
41
|
/**
|
|
42
42
|
* Decrypts an encrypted submission and returns it in V4 format.
|
|
43
|
-
* If the decrypted data is already in V4 format, it is returned
|
|
43
|
+
* If the decrypted data is already in V4 format, it is returned with any
|
|
44
|
+
* missing question text backfilled from the provided formFields metadata.
|
|
44
45
|
* If the decrypted data is in V3 format, it is adapted to V4 using the provided formFields metadata.
|
|
45
46
|
* @param formSecretKey The base-64 encoded form secret key for decrypting the submission.
|
|
46
47
|
* @param decryptParams The params containing encrypted content, encrypted submission key and information.
|
package/dist/esm/crypto-v3.js
CHANGED
|
@@ -38,7 +38,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
38
38
|
import { decodeBase64, decodeUTF8, encodeBase64, encodeUTF8, } from 'tweetnacl-util';
|
|
39
39
|
import { decryptContent, encryptMessage, generateKeypair, verifySignedMessage, } from './util/crypto';
|
|
40
40
|
import { determineIsFormFieldsV3 } from './util/validate';
|
|
41
|
-
import { adaptV3ToV4 } from './adapt-v3-to-v4';
|
|
41
|
+
import { adaptV3ToV4, deriveQuestionFromMeta } from './adapt-v3-to-v4';
|
|
42
42
|
import CryptoBase from './crypto-base';
|
|
43
43
|
import { MissingPublicKeyError } from './errors';
|
|
44
44
|
/**
|
|
@@ -52,6 +52,30 @@ export function isFieldResponsesV4(responses) {
|
|
|
52
52
|
var first = entries[0];
|
|
53
53
|
return typeof first.provenance === 'object' && first.provenance !== null;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Backfills question text (and myInfo metadata) on V4 responses stored
|
|
57
|
+
* without them, in place. V4 blobs written from wire bodies lack question
|
|
58
|
+
* text: the receiver shim adapts V3 bodies without the form definition in
|
|
59
|
+
* scope, and thin V4 wire bodies omit `question` entirely (the server strips
|
|
60
|
+
* it). Enrich empty questions from the form definition at read time instead.
|
|
61
|
+
* Responses that already carry a question are left untouched.
|
|
62
|
+
*/
|
|
63
|
+
function backfillMissingQuestions(responses, formFields) {
|
|
64
|
+
for (var _i = 0, _a = Object.entries(responses); _i < _a.length; _i++) {
|
|
65
|
+
var _b = _a[_i], fieldId = _b[0], response = _b[1];
|
|
66
|
+
if (response.question)
|
|
67
|
+
continue;
|
|
68
|
+
// Tolerate an omitted formFields map from untyped (JS) callers
|
|
69
|
+
var meta = formFields === null || formFields === void 0 ? void 0 : formFields[fieldId];
|
|
70
|
+
if (!meta)
|
|
71
|
+
continue;
|
|
72
|
+
response.question = deriveQuestionFromMeta(meta);
|
|
73
|
+
if (meta.myInfo && !response.myInfo) {
|
|
74
|
+
response.myInfo = meta.myInfo;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return responses;
|
|
78
|
+
}
|
|
55
79
|
var CryptoV3 = /** @class */ (function (_super) {
|
|
56
80
|
__extends(CryptoV3, _super);
|
|
57
81
|
function CryptoV3(_a) {
|
|
@@ -161,7 +185,8 @@ var CryptoV3 = /** @class */ (function (_super) {
|
|
|
161
185
|
};
|
|
162
186
|
/**
|
|
163
187
|
* Decrypts an encrypted submission and returns it in V4 format.
|
|
164
|
-
* If the decrypted data is already in V4 format, it is returned
|
|
188
|
+
* If the decrypted data is already in V4 format, it is returned with any
|
|
189
|
+
* missing question text backfilled from the provided formFields metadata.
|
|
165
190
|
* If the decrypted data is in V3 format, it is adapted to V4 using the provided formFields metadata.
|
|
166
191
|
* @param formSecretKey The base-64 encoded form secret key for decrypting the submission.
|
|
167
192
|
* @param decryptParams The params containing encrypted content, encrypted submission key and information.
|
|
@@ -173,9 +198,10 @@ var CryptoV3 = /** @class */ (function (_super) {
|
|
|
173
198
|
var decrypted = _this.decrypt(formSecretKey, decryptParams);
|
|
174
199
|
if (!decrypted)
|
|
175
200
|
return null;
|
|
176
|
-
// If the decrypted responses are already in V4 format, return
|
|
201
|
+
// If the decrypted responses are already in V4 format, return them with
|
|
202
|
+
// any missing question text backfilled from the form definition.
|
|
177
203
|
var responses = isFieldResponsesV4(decrypted.responses)
|
|
178
|
-
? decrypted.responses
|
|
204
|
+
? backfillMissingQuestions(decrypted.responses, formFields)
|
|
179
205
|
: adaptV3ToV4(decrypted.responses, { formFields: formFields });
|
|
180
206
|
return {
|
|
181
207
|
submissionSecretKey: decrypted.submissionSecretKey,
|