@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.
@@ -14,7 +14,7 @@ jobs:
14
14
  with:
15
15
  node-version: 18
16
16
  - name: Cache Node.js modules
17
- uses: actions/cache@v2
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@v2
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 test coverage to Coveralls
51
- uses: coverallsapp/github-action@v1.1.2
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
- [![Build Status](https://travis-ci.com/opengovsg/formsg-javascript-sdk.svg?branch=master)](https://travis-ci.com/opengovsg/formsg-javascript-sdk)
4
3
  [![Coverage Status](https://coveralls.io/repos/github/opengovsg/formsg-javascript-sdk/badge.svg?branch=master)](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 `{}`.
@@ -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
- constructor();
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
- var encryptedSubmissionSecretKey = decryptParams.encryptedSubmissionSecretKey, rest = __rest(decryptParams, ["encryptedSubmissionSecretKey"]);
111
- var submissionSecretKey = (0, crypto_1.decryptContent)(formSecretKey, encryptedSubmissionSecretKey);
112
- if (submissionSecretKey === null)
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
- return _this.decryptFromSubmissionKey((0, tweetnacl_util_1.encodeBase64)(submissionSecretKey), rest);
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.13.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",