@opengovsg/formsg-sdk 0.13.0 → 0.15.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/.github/workflows/ci.yml +4 -4
- package/CHANGELOG.md +21 -0
- package/README.md +4 -1
- package/dist/crypto-v3.d.ts +5 -1
- package/dist/crypto-v3.js +45 -6
- package/dist/index.js +1 -1
- package/dist/types.d.ts +3 -1
- package/package.json +1 -2
package/.github/workflows/ci.yml
CHANGED
|
@@ -14,7 +14,7 @@ jobs:
|
|
|
14
14
|
with:
|
|
15
15
|
node-version: 18
|
|
16
16
|
- name: Cache Node.js modules
|
|
17
|
-
uses: actions/cache@
|
|
17
|
+
uses: actions/cache@v4
|
|
18
18
|
with:
|
|
19
19
|
# npm cache files are stored in `~/.npm` on Linux/macOS
|
|
20
20
|
path: ~/.npm
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
with:
|
|
36
36
|
node-version: 18
|
|
37
37
|
- name: Cache Node.js modules
|
|
38
|
-
uses: actions/cache@
|
|
38
|
+
uses: actions/cache@v4
|
|
39
39
|
with:
|
|
40
40
|
# npm cache files are stored in `~/.npm` on Linux/macOS
|
|
41
41
|
path: ~/.npm
|
|
@@ -47,7 +47,7 @@ jobs:
|
|
|
47
47
|
- run: npm run test-ci
|
|
48
48
|
env:
|
|
49
49
|
NODE_OPTIONS: '--max-old-space-size=8192'
|
|
50
|
-
- name: Submit
|
|
51
|
-
uses: coverallsapp/github-action@
|
|
50
|
+
- name: Submit coverage to Coveralls
|
|
51
|
+
uses: coverallsapp/github-action@v2
|
|
52
52
|
with:
|
|
53
53
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,29 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v0.15.0](https://github.com/opengovsg/formsg-javascript-sdk/compare/v0.15.0...v0.14.0)
|
|
8
|
+
|
|
9
|
+
- feat: add verified content to v3 [`#121`](https://github.com/opengovsg/formsg-javascript-sdk/pull/121)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
#### [v0.14.0](https://github.com/opengovsg/formsg-javascript-sdk/compare/v0.13.0...v0.14.0)
|
|
13
|
+
|
|
14
|
+
- chore: remove build status from README.md [`#120`](https://github.com/opengovsg/formsg-javascript-sdk/pull/120)
|
|
15
|
+
|
|
16
|
+
> 6 August 2025
|
|
17
|
+
|
|
18
|
+
- feat: add signature to supported form fields [`#118`](https://github.com/opengovsg/formsg-javascript-sdk/pull/118)
|
|
19
|
+
- fix: upgrade actions/cache [`#115`](https://github.com/opengovsg/formsg-javascript-sdk/pull/115)
|
|
20
|
+
- Release v0.13.0 [`#114`](https://github.com/opengovsg/formsg-javascript-sdk/pull/114)
|
|
21
|
+
- updated readme with address answerArray [`#112`](https://github.com/opengovsg/formsg-javascript-sdk/pull/112)
|
|
22
|
+
- build(deps-dev): bump braces from 3.0.2 to 3.0.3 [`#109`](https://github.com/opengovsg/formsg-javascript-sdk/pull/109)
|
|
23
|
+
- build(deps): bump follow-redirects from 1.15.4 to 1.15.6 [`#107`](https://github.com/opengovsg/formsg-javascript-sdk/pull/107)
|
|
24
|
+
- add signature to supported form fields [`31db628`](https://github.com/opengovsg/formsg-javascript-sdk/commit/31db628ce44e009b5c19f8c9910bd997d77df586)
|
|
25
|
+
|
|
7
26
|
#### [v0.13.0](https://github.com/opengovsg/formsg-javascript-sdk/compare/v0.12.0...v0.13.0)
|
|
8
27
|
|
|
28
|
+
> 15 January 2025
|
|
29
|
+
|
|
9
30
|
- add address to field type [`#111`](https://github.com/opengovsg/formsg-javascript-sdk/pull/111)
|
|
10
31
|
|
|
11
32
|
#### [v0.12.0](https://github.com/opengovsg/formsg-javascript-sdk/compare/v0.12.0-alpha.1...v0.12.0)
|
package/README.md
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
_Please note that this is an SDK for webhooks integration, and_ **_not_** _the FormSG system._
|
|
2
2
|
|
|
3
|
-
[](https://travis-ci.com/opengovsg/formsg-javascript-sdk)
|
|
4
3
|
[](https://coveralls.io/github/opengovsg/formsg-javascript-sdk?branch=master)
|
|
5
4
|
|
|
6
5
|
# FormSG Javascript SDK
|
|
@@ -181,6 +180,10 @@ Attachments are end-to-end encrypted in the same way as normal form submissions,
|
|
|
181
180
|
|
|
182
181
|
_Warning:_ We do not have the ability to scan any attachments for malicious content (e.g. spyware or viruses), so careful handling is needed.
|
|
183
182
|
|
|
183
|
+
### Processing Local address fields
|
|
184
|
+
|
|
185
|
+
Address Field is a compound field with 6 inputs in the answerArray. It will always follow the ordinance of [`blockNumber`, `streetName`, `buildingName`, `levelNumber`, `unitNumber`, `postalCode`]
|
|
186
|
+
|
|
184
187
|
### Format of Payment Content
|
|
185
188
|
|
|
186
189
|
These fields will be available if the submission is a payment submission, otherwise, the value will be an empty `{}`.
|
package/dist/crypto-v3.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import CryptoBase from './crypto-base';
|
|
2
2
|
import { DecryptedContentV3, DecryptParams, DecryptParamsV3, EncryptedContentV3 } from './types';
|
|
3
3
|
export default class CryptoV3 extends CryptoBase {
|
|
4
|
-
|
|
4
|
+
signingPublicKey?: string;
|
|
5
|
+
constructor({ signingPublicKey }?: {
|
|
6
|
+
signingPublicKey?: string;
|
|
7
|
+
});
|
|
5
8
|
/**
|
|
6
9
|
* Encrypt input with a unique keypair for each submission.
|
|
7
10
|
* @param msg The message to encrypt, will be stringified.
|
|
@@ -26,6 +29,7 @@ export default class CryptoV3 extends CryptoBase {
|
|
|
26
29
|
* @param decryptParams.encryptedSubmissionSecretKey The encrypted submission secret key encoded with base-64.
|
|
27
30
|
* @param decryptParams.version The version of the payload. Used to determine the decryption process to decrypt the content with.
|
|
28
31
|
* @returns The decrypted content if successful. Else, null will be returned.
|
|
32
|
+
* @throws {MissingPublicKeyError} if a public key is not provided when instantiating this class and is needed for verifying signed content.
|
|
29
33
|
*/
|
|
30
34
|
decrypt: (formSecretKey: string, decryptParams: DecryptParamsV3) => DecryptedContentV3 | null;
|
|
31
35
|
/**
|
package/dist/crypto-v3.js
CHANGED
|
@@ -44,9 +44,11 @@ var tweetnacl_util_1 = require("tweetnacl-util");
|
|
|
44
44
|
var crypto_1 = require("./util/crypto");
|
|
45
45
|
var validate_1 = require("./util/validate");
|
|
46
46
|
var crypto_base_1 = __importDefault(require("./crypto-base"));
|
|
47
|
+
var errors_1 = require("./errors");
|
|
47
48
|
var CryptoV3 = /** @class */ (function (_super) {
|
|
48
49
|
__extends(CryptoV3, _super);
|
|
49
|
-
function CryptoV3() {
|
|
50
|
+
function CryptoV3(_a) {
|
|
51
|
+
var _b = _a === void 0 ? {} : _a, signingPublicKey = _b.signingPublicKey;
|
|
50
52
|
var _this = _super.call(this) || this;
|
|
51
53
|
/**
|
|
52
54
|
* Encrypt input with a unique keypair for each submission.
|
|
@@ -76,7 +78,7 @@ var CryptoV3 = /** @class */ (function (_super) {
|
|
|
76
78
|
*/
|
|
77
79
|
_this.decryptFromSubmissionKey = function (submissionSecretKey, decryptParams) {
|
|
78
80
|
try {
|
|
79
|
-
var encryptedContent = decryptParams.encryptedContent;
|
|
81
|
+
var encryptedContent = decryptParams.encryptedContent, verifiedContent = decryptParams.verifiedContent;
|
|
80
82
|
// Do not return the transformed object in `_decrypt` function as a signed
|
|
81
83
|
// object is not encoded in UTF8 and is encoded in Base-64 instead.
|
|
82
84
|
var decryptedContent = (0, crypto_1.decryptContent)(submissionSecretKey, encryptedContent);
|
|
@@ -91,9 +93,35 @@ var CryptoV3 = /** @class */ (function (_super) {
|
|
|
91
93
|
submissionSecretKey: submissionSecretKey,
|
|
92
94
|
responses: decryptedObject,
|
|
93
95
|
};
|
|
96
|
+
/**
|
|
97
|
+
* Note on verifiedContent decryption for cryptoV3:
|
|
98
|
+
* Although decryption is supported, verifiedContent encryption is not supported
|
|
99
|
+
* in cryptoV3 encrypt.
|
|
100
|
+
* This is to keep the encryption of verifiedContent and encryptedContent similar to storage mode - where
|
|
101
|
+
* verifiedContent and encryptedContent are defined and encrypted separately.
|
|
102
|
+
*/
|
|
103
|
+
// decrypt verifiedContent if it exists
|
|
104
|
+
if (verifiedContent) {
|
|
105
|
+
if (!_this.signingPublicKey) {
|
|
106
|
+
throw new errors_1.MissingPublicKeyError('Public signing key must be provided when instantiating the Crypto class in order to verify verified content');
|
|
107
|
+
}
|
|
108
|
+
var decryptedVerifiedContent = (0, crypto_1.decryptContent)(submissionSecretKey, verifiedContent);
|
|
109
|
+
if (!decryptedVerifiedContent) {
|
|
110
|
+
// Returns null if decrypting verified content failed.
|
|
111
|
+
throw new Error('Failed to decrypt verified content');
|
|
112
|
+
}
|
|
113
|
+
var decryptedVerifiedObject = (0, crypto_1.verifySignedMessage)(decryptedVerifiedContent, _this.signingPublicKey);
|
|
114
|
+
returnedObject.verified = decryptedVerifiedObject;
|
|
115
|
+
}
|
|
94
116
|
return returnedObject;
|
|
95
117
|
}
|
|
96
118
|
catch (err) {
|
|
119
|
+
// Should only throw if MissingPublicKeyError.
|
|
120
|
+
// This library should be able to be used to encrypt and decrypt content
|
|
121
|
+
// if the content does not contain verified fields.
|
|
122
|
+
if (err instanceof errors_1.MissingPublicKeyError) {
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
97
125
|
return null;
|
|
98
126
|
}
|
|
99
127
|
};
|
|
@@ -105,13 +133,23 @@ var CryptoV3 = /** @class */ (function (_super) {
|
|
|
105
133
|
* @param decryptParams.encryptedSubmissionSecretKey The encrypted submission secret key encoded with base-64.
|
|
106
134
|
* @param decryptParams.version The version of the payload. Used to determine the decryption process to decrypt the content with.
|
|
107
135
|
* @returns The decrypted content if successful. Else, null will be returned.
|
|
136
|
+
* @throws {MissingPublicKeyError} if a public key is not provided when instantiating this class and is needed for verifying signed content.
|
|
108
137
|
*/
|
|
109
138
|
_this.decrypt = function (formSecretKey, decryptParams) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
139
|
+
try {
|
|
140
|
+
var encryptedSubmissionSecretKey = decryptParams.encryptedSubmissionSecretKey, rest = __rest(decryptParams, ["encryptedSubmissionSecretKey"]);
|
|
141
|
+
var submissionSecretKey = (0, crypto_1.decryptContent)(formSecretKey, encryptedSubmissionSecretKey);
|
|
142
|
+
if (submissionSecretKey === null)
|
|
143
|
+
return null;
|
|
144
|
+
return _this.decryptFromSubmissionKey((0, tweetnacl_util_1.encodeBase64)(submissionSecretKey), rest);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
if (err instanceof errors_1.MissingPublicKeyError) {
|
|
148
|
+
// rethrow to let the caller decide how to handle missing signing key
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
113
151
|
return null;
|
|
114
|
-
|
|
152
|
+
}
|
|
115
153
|
};
|
|
116
154
|
/**
|
|
117
155
|
* Returns true if a pair of public & secret keys are associated with each other
|
|
@@ -127,6 +165,7 @@ var CryptoV3 = /** @class */ (function (_super) {
|
|
|
127
165
|
return (testResponse.toString() ===
|
|
128
166
|
((_a = _this.decrypt(secretKey, __assign(__assign({}, cipherResponse), { version: internalValidationVersion }))) === null || _a === void 0 ? void 0 : _a.responses.toString()));
|
|
129
167
|
};
|
|
168
|
+
_this.signingPublicKey = signingPublicKey;
|
|
130
169
|
return _this;
|
|
131
170
|
}
|
|
132
171
|
return CryptoV3;
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ module.exports = function (config) {
|
|
|
25
25
|
secretKey: webhookSecretKey,
|
|
26
26
|
}),
|
|
27
27
|
crypto: new crypto_1.default({ signingPublicKey: signingPublicKey }),
|
|
28
|
-
cryptoV3: new crypto_v3_1.default(),
|
|
28
|
+
cryptoV3: new crypto_v3_1.default({ signingPublicKey: signingPublicKey }),
|
|
29
29
|
verification: new verification_1.default({
|
|
30
30
|
publicKey: verificationPublicKey,
|
|
31
31
|
secretKey: verificationOptions === null || verificationOptions === void 0 ? void 0 : verificationOptions.secretKey,
|
package/dist/types.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type PackageInitParams = {
|
|
|
6
6
|
/** Initializes public key used for verifying and decrypting in this package. If not given, will default to "production". */
|
|
7
7
|
mode?: PackageMode;
|
|
8
8
|
};
|
|
9
|
-
export type FieldType = 'section' | 'radiobutton' | 'dropdown' | 'checkbox' | 'nric' | 'email' | 'table' | 'number' | 'rating' | 'yes_no' | 'decimal' | 'textfield' | 'textarea' | 'attachment' | 'date' | 'mobile' | 'homeno' | 'statement' | 'image' | 'country_region' | 'uen' | 'children' | 'address';
|
|
9
|
+
export type FieldType = 'section' | 'radiobutton' | 'dropdown' | 'checkbox' | 'nric' | 'email' | 'table' | 'number' | 'rating' | 'yes_no' | 'decimal' | 'textfield' | 'textarea' | 'attachment' | 'date' | 'mobile' | 'homeno' | 'statement' | 'image' | 'country_region' | 'uen' | 'children' | 'address' | 'signature';
|
|
10
10
|
export type FormField = {
|
|
11
11
|
_id: string;
|
|
12
12
|
question: string;
|
|
@@ -41,6 +41,7 @@ export interface DecryptParams {
|
|
|
41
41
|
export interface DecryptParamsV3 {
|
|
42
42
|
encryptedContent: EncryptedContent;
|
|
43
43
|
encryptedSubmissionSecretKey: EncryptedContent;
|
|
44
|
+
verifiedContent?: EncryptedContent;
|
|
44
45
|
version: number;
|
|
45
46
|
}
|
|
46
47
|
export type DecryptedContent = {
|
|
@@ -50,6 +51,7 @@ export type DecryptedContent = {
|
|
|
50
51
|
export type DecryptedContentV3 = {
|
|
51
52
|
submissionSecretKey: string;
|
|
52
53
|
responses: FormFieldsV3;
|
|
54
|
+
verified?: Record<string, any>;
|
|
53
55
|
};
|
|
54
56
|
export type DecryptedFile = {
|
|
55
57
|
filename: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengovsg/formsg-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/opengovsg/formsg-javascript-sdk.git"
|
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
"@types/node": "^18.18.9",
|
|
37
37
|
"@typescript-eslint/eslint-plugin": "^4.25.0",
|
|
38
38
|
"auto-changelog": "^2.4.0",
|
|
39
|
-
"coveralls": "^3.1.1",
|
|
40
39
|
"eslint-config-prettier": "^8.3.0",
|
|
41
40
|
"eslint-plugin-import": "^2.23.3",
|
|
42
41
|
"eslint-plugin-jest": "^24.3.6",
|