From 63677011405b121c301e944184f2f54d6491ac89 Mon Sep 17 00:00:00 2001 From: Victor Andrade <0vetor0@gmail.com> Date: Sun, 16 Feb 2025 20:50:30 -0300 Subject: [PATCH 1/9] feat: add signInFeature type and validation for form fields --- lib/build/recipe/emailpassword/types.d.ts | 4 ++ lib/build/recipe/emailpassword/utils.js | 62 ++++++++++++++++----- lib/ts/recipe/emailpassword/types.ts | 5 ++ lib/ts/recipe/emailpassword/utils.ts | 64 +++++++++++++++++----- test/emailpassword/signinFeature.test.js | 67 +++++++++++++++++++++++ 5 files changed, 174 insertions(+), 28 deletions(-) diff --git a/lib/build/recipe/emailpassword/types.d.ts b/lib/build/recipe/emailpassword/types.d.ts index fa3eb14088..cbf775a02e 100644 --- a/lib/build/recipe/emailpassword/types.d.ts +++ b/lib/build/recipe/emailpassword/types.d.ts @@ -36,6 +36,9 @@ export declare type TypeFormField = { export declare type TypeInputSignUp = { formFields?: TypeInputFormField[]; }; +export declare type TypeInputSignIn = { + formFields?: TypeInputFormField[]; +}; export declare type NormalisedFormField = { id: string; validate: (value: any, tenantId: string, userContext: UserContext) => Promise; @@ -53,6 +56,7 @@ export declare type TypeNormalisedInputResetPasswordUsingTokenFeature = { }; export declare type TypeInput = { signUpFeature?: TypeInputSignUp; + signInFeature?: TypeInputSignIn; emailDelivery?: EmailDeliveryTypeInput; override?: { functions?: ( diff --git a/lib/build/recipe/emailpassword/utils.js b/lib/build/recipe/emailpassword/utils.js index 18014af694..9950e3810c 100644 --- a/lib/build/recipe/emailpassword/utils.js +++ b/lib/build/recipe/emailpassword/utils.js @@ -28,7 +28,11 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { appInfo, config === undefined ? undefined : config.signUpFeature ); - let signInFeature = validateAndNormaliseSignInConfig(recipeInstance, appInfo, signUpFeature); + let signInFeature = validateAndNormaliseSignInConfig( + recipeInstance, + appInfo, + config === undefined ? undefined : config.signInFeature + ); let resetPasswordUsingTokenFeature = validateAndNormaliseResetPasswordUsingTokenConfig(signUpFeature); let override = Object.assign( { @@ -99,22 +103,50 @@ function validateAndNormaliseResetPasswordUsingTokenConfig(signUpConfig) { }; } function normaliseSignInFormFields(formFields) { - return formFields - .filter( - (filter) => - filter.id === constants_1.FORM_FIELD_EMAIL_ID || filter.id === constants_1.FORM_FIELD_PASSWORD_ID - ) - .map((field) => { - return { - id: field.id, - // see issue: https://github.com/supertokens/supertokens-node/issues/36 - validate: field.id === constants_1.FORM_FIELD_EMAIL_ID ? field.validate : defaultValidator, - optional: false, - }; + let normalisedFormFields = []; + if (formFields !== undefined) { + formFields.forEach((field) => { + if (field.id === constants_1.FORM_FIELD_PASSWORD_ID) { + normalisedFormFields.push({ + id: field.id, + validate: field.validate === undefined ? defaultPasswordValidator : field.validate, + optional: false, + }); + } else if (field.id === constants_1.FORM_FIELD_EMAIL_ID) { + normalisedFormFields.push({ + id: field.id, + validate: field.validate === undefined ? defaultEmailValidator : field.validate, + optional: false, + }); + } else { + normalisedFormFields.push({ + id: field.id, + validate: field.validate === undefined ? defaultValidator : field.validate, + optional: field.optional === undefined ? false : field.optional, + }); + } + }); + } + if (normalisedFormFields.filter((field) => field.id === constants_1.FORM_FIELD_PASSWORD_ID).length === 0) { + // no password field give by user + normalisedFormFields.push({ + id: constants_1.FORM_FIELD_PASSWORD_ID, + validate: defaultPasswordValidator, + optional: false, + }); + } + if (normalisedFormFields.filter((field) => field.id === constants_1.FORM_FIELD_EMAIL_ID).length === 0) { + // no email field give by user + normalisedFormFields.push({ + id: constants_1.FORM_FIELD_EMAIL_ID, + validate: defaultEmailValidator, + optional: false, }); + } + return normalisedFormFields; } -function validateAndNormaliseSignInConfig(_, __, signUpConfig) { - let formFields = normaliseSignInFormFields(signUpConfig.formFields); +function validateAndNormaliseSignInConfig(_, __, config) { + let formFields = normaliseSignInFormFields(config === undefined ? undefined : config.formFields); return { formFields, }; diff --git a/lib/ts/recipe/emailpassword/types.ts b/lib/ts/recipe/emailpassword/types.ts index 0fdfbe088f..a1e650bad8 100644 --- a/lib/ts/recipe/emailpassword/types.ts +++ b/lib/ts/recipe/emailpassword/types.ts @@ -52,6 +52,10 @@ export type TypeInputSignUp = { formFields?: TypeInputFormField[]; }; +export type TypeInputSignIn = { + formFields?: TypeInputFormField[]; +}; + export type NormalisedFormField = { id: string; validate: (value: any, tenantId: string, userContext: UserContext) => Promise; @@ -73,6 +77,7 @@ export type TypeNormalisedInputResetPasswordUsingTokenFeature = { export type TypeInput = { signUpFeature?: TypeInputSignUp; + signInFeature?: TypeInputSignIn; emailDelivery?: EmailDeliveryTypeInput; override?: { functions?: ( diff --git a/lib/ts/recipe/emailpassword/utils.ts b/lib/ts/recipe/emailpassword/utils.ts index f6ce4316de..b58cf25bfa 100644 --- a/lib/ts/recipe/emailpassword/utils.ts +++ b/lib/ts/recipe/emailpassword/utils.ts @@ -23,6 +23,7 @@ import { TypeNormalisedInputResetPasswordUsingTokenFeature, NormalisedFormField, TypeInputFormField, + TypeInputSignIn, } from "./types"; import { NormalisedAppinfo, UserContext } from "../../types"; import { FORM_FIELD_EMAIL_ID, FORM_FIELD_PASSWORD_ID } from "./constants"; @@ -41,7 +42,11 @@ export function validateAndNormaliseUserInput( config === undefined ? undefined : config.signUpFeature ); - let signInFeature = validateAndNormaliseSignInConfig(recipeInstance, appInfo, signUpFeature); + let signInFeature = validateAndNormaliseSignInConfig( + recipeInstance, + appInfo, + config === undefined ? undefined : config.signInFeature + ); let resetPasswordUsingTokenFeature = validateAndNormaliseResetPasswordUsingTokenConfig(signUpFeature); @@ -114,25 +119,58 @@ function validateAndNormaliseResetPasswordUsingTokenConfig( }; } -function normaliseSignInFormFields(formFields: NormalisedFormField[]) { - return formFields - .filter((filter) => filter.id === FORM_FIELD_EMAIL_ID || filter.id === FORM_FIELD_PASSWORD_ID) - .map((field) => { - return { - id: field.id, - // see issue: https://github.com/supertokens/supertokens-node/issues/36 - validate: field.id === FORM_FIELD_EMAIL_ID ? field.validate : defaultValidator, - optional: false, - }; +function normaliseSignInFormFields(formFields?: TypeInputFormField[]) { + let normalisedFormFields: NormalisedFormField[] = []; + if (formFields !== undefined) { + formFields.forEach((field) => { + if (field.id === FORM_FIELD_PASSWORD_ID) { + normalisedFormFields.push({ + id: field.id, + validate: field.validate === undefined ? defaultPasswordValidator : field.validate, + optional: false, + }); + } else if (field.id === FORM_FIELD_EMAIL_ID) { + normalisedFormFields.push({ + id: field.id, + validate: field.validate === undefined ? defaultEmailValidator : field.validate, + optional: false, + }); + } else { + normalisedFormFields.push({ + id: field.id, + validate: field.validate === undefined ? defaultValidator : field.validate, + optional: field.optional === undefined ? false : field.optional, + }); + } }); + } + if (normalisedFormFields.filter((field) => field.id === FORM_FIELD_PASSWORD_ID).length === 0) { + // no password field give by user + normalisedFormFields.push({ + id: FORM_FIELD_PASSWORD_ID, + validate: defaultPasswordValidator, + optional: false, + }); + } + if (normalisedFormFields.filter((field) => field.id === FORM_FIELD_EMAIL_ID).length === 0) { + // no email field give by user + normalisedFormFields.push({ + id: FORM_FIELD_EMAIL_ID, + validate: defaultEmailValidator, + optional: false, + }); + } + return normalisedFormFields; } function validateAndNormaliseSignInConfig( _: Recipe, __: NormalisedAppinfo, - signUpConfig: TypeNormalisedInputSignUp + config?: TypeInputSignIn ): TypeNormalisedInputSignIn { - let formFields: NormalisedFormField[] = normaliseSignInFormFields(signUpConfig.formFields); + let formFields: NormalisedFormField[] = normaliseSignInFormFields( + config === undefined ? undefined : config.formFields + ); return { formFields, diff --git a/test/emailpassword/signinFeature.test.js b/test/emailpassword/signinFeature.test.js index 15f95f7d6b..780c5bf6d3 100644 --- a/test/emailpassword/signinFeature.test.js +++ b/test/emailpassword/signinFeature.test.js @@ -1887,4 +1887,71 @@ describe(`signinFeature: ${printPath("[test/emailpassword/signinFeature.test.js] ); assert(invalidEmailResponse.status === "WRONG_CREDENTIALS_ERROR"); }); + + // test case where more than the configured form fields are passed. + it("test bad case when too many formFields are passed", async function () { + const connectionURI = await startST(); + STExpress.init({ + supertokens: { + connectionURI, + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + EmailPassword.init({ + signInFeature: { + formFields: [ + { + id: "testField", + }, + ], + }, + }), + Session.init({ getTokenTransferMethod: () => "cookie" }), + ], + }); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + let response = await new Promise((resolve) => + request(app) + .post("/auth/signin") + .send({ + formFields: [ + { + id: "password", + value: "validpass123", + }, + { + id: "email", + value: "random@gmail.com", + }, + { + id: "testField", + value: "some value", + }, + { + id: "extraField", + value: "some value", + }, + ], + }) + .expect(400) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(JSON.parse(res.text)); + } + }) + ); + + assert(response.message == "Are you sending too many formFields?"); + }); }); From 87226401972832bac0ef39f56e2584184fda4bb3 Mon Sep 17 00:00:00 2001 From: Victor Andrade <0vetor0@gmail.com> Date: Sun, 16 Feb 2025 21:10:05 -0300 Subject: [PATCH 2/9] chore: bump version to 21.1.1 and update changelog for signInFeature type and validation --- CHANGELOG.md | 4 ++++ lib/ts/version.ts | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02dc79092c..e510d5cbce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +## [21.1.1] - 2024-11-19 + +- Adds signInFeature type and validation for form fields in EmailPassword Recipe. + ## [21.1.0] - 2024-11-19 - Adds `getCookieNameForTokenType` config option to allow customizing the cookie name for a token type. diff --git a/lib/ts/version.ts b/lib/ts/version.ts index 7c52a9640d..a437c0b300 100644 --- a/lib/ts/version.ts +++ b/lib/ts/version.ts @@ -12,7 +12,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -export const version = "21.1.0"; +export const version = "21.1.1"; export const cdiSupported = ["5.2"]; diff --git a/package-lock.json b/package-lock.json index bc0641fa81..25d9e8627b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "supertokens-node", - "version": "21.1.0", + "version": "21.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "supertokens-node", - "version": "21.1.0", + "version": "21.1.1", "license": "Apache-2.0", "dependencies": { "buffer": "^6.0.3", diff --git a/package.json b/package.json index 06454f21cf..ba55a2a64a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "supertokens-node", - "version": "21.1.0", + "version": "21.1.1", "description": "NodeJS driver for SuperTokens core", "main": "index.js", "scripts": { From 5bd1f307d439aa7a53e78f5abde9844f753e4387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Gon=C3=A7alves=20de=20Andrade?= <0vetor0@gmail.com> Date: Sun, 25 May 2025 15:31:21 -0300 Subject: [PATCH 3/9] Update lib/ts/recipe/emailpassword/utils.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mihály Lengyel --- lib/ts/recipe/emailpassword/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ts/recipe/emailpassword/utils.ts b/lib/ts/recipe/emailpassword/utils.ts index b58cf25bfa..326263fc29 100644 --- a/lib/ts/recipe/emailpassword/utils.ts +++ b/lib/ts/recipe/emailpassword/utils.ts @@ -126,7 +126,7 @@ function normaliseSignInFormFields(formFields?: TypeInputFormField[]) { if (field.id === FORM_FIELD_PASSWORD_ID) { normalisedFormFields.push({ id: field.id, - validate: field.validate === undefined ? defaultPasswordValidator : field.validate, + validate: field.validate === undefined ? defaultValidator : field.validate, optional: false, }); } else if (field.id === FORM_FIELD_EMAIL_ID) { From 24e650223d503bec42c30a2abbd11dec434a9fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Gon=C3=A7alves=20de=20Andrade?= <0vetor0@gmail.com> Date: Sun, 25 May 2025 15:31:50 -0300 Subject: [PATCH 4/9] Update lib/ts/recipe/emailpassword/utils.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mihály Lengyel --- lib/ts/recipe/emailpassword/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ts/recipe/emailpassword/utils.ts b/lib/ts/recipe/emailpassword/utils.ts index 326263fc29..ccf1862a79 100644 --- a/lib/ts/recipe/emailpassword/utils.ts +++ b/lib/ts/recipe/emailpassword/utils.ts @@ -152,7 +152,7 @@ function normaliseSignInFormFields(formFields?: TypeInputFormField[]) { optional: false, }); } - if (normalisedFormFields.filter((field) => field.id === FORM_FIELD_EMAIL_ID).length === 0) { + if (!normalisedFormFields.some((field) => field.id === FORM_FIELD_EMAIL_ID)) { // no email field give by user normalisedFormFields.push({ id: FORM_FIELD_EMAIL_ID, From 6addbe74577afa7f9d40d357de20babec20e4a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Gon=C3=A7alves=20de=20Andrade?= <0vetor0@gmail.com> Date: Sun, 25 May 2025 15:36:05 -0300 Subject: [PATCH 5/9] Update package.json Minor version instead of patch version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ba55a2a64a..735a154d0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "supertokens-node", - "version": "21.1.1", + "version": "21.2.0", "description": "NodeJS driver for SuperTokens core", "main": "index.js", "scripts": { From caa3b5d8c610fabe3f9c9198194e60bbb82c1882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Gon=C3=A7alves=20de=20Andrade?= <0vetor0@gmail.com> Date: Sun, 25 May 2025 15:36:51 -0300 Subject: [PATCH 6/9] Update lib/ts/recipe/emailpassword/utils.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimize array validation Co-authored-by: Mihály Lengyel --- lib/ts/recipe/emailpassword/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ts/recipe/emailpassword/utils.ts b/lib/ts/recipe/emailpassword/utils.ts index ccf1862a79..0ff61bf341 100644 --- a/lib/ts/recipe/emailpassword/utils.ts +++ b/lib/ts/recipe/emailpassword/utils.ts @@ -144,7 +144,7 @@ function normaliseSignInFormFields(formFields?: TypeInputFormField[]) { } }); } - if (normalisedFormFields.filter((field) => field.id === FORM_FIELD_PASSWORD_ID).length === 0) { + if (!normalisedFormFields.some((field) => field.id === FORM_FIELD_PASSWORD_ID)) { // no password field give by user normalisedFormFields.push({ id: FORM_FIELD_PASSWORD_ID, From c491dca1ff1398fcdbcb48dd550a3c4b37777672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Gon=C3=A7alves=20de=20Andrade?= <0vetor0@gmail.com> Date: Sun, 25 May 2025 15:38:20 -0300 Subject: [PATCH 7/9] Update lib/ts/recipe/emailpassword/utils.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mihály Lengyel --- lib/ts/recipe/emailpassword/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ts/recipe/emailpassword/utils.ts b/lib/ts/recipe/emailpassword/utils.ts index 0ff61bf341..2d0f4ec73f 100644 --- a/lib/ts/recipe/emailpassword/utils.ts +++ b/lib/ts/recipe/emailpassword/utils.ts @@ -148,7 +148,7 @@ function normaliseSignInFormFields(formFields?: TypeInputFormField[]) { // no password field give by user normalisedFormFields.push({ id: FORM_FIELD_PASSWORD_ID, - validate: defaultPasswordValidator, + validate: defaultValidator, optional: false, }); } From 1d45f4dd65b32bb2de6973c6948f4bfa05c32341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Gon=C3=A7alves=20de=20Andrade?= <0vetor0@gmail.com> Date: Sun, 25 May 2025 15:38:59 -0300 Subject: [PATCH 8/9] Update version.ts --- lib/ts/version.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ts/version.ts b/lib/ts/version.ts index a437c0b300..a613472d21 100644 --- a/lib/ts/version.ts +++ b/lib/ts/version.ts @@ -12,7 +12,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -export const version = "21.1.1"; +export const version = "21.2.0"; export const cdiSupported = ["5.2"]; From 44129ed553196690acf9f99180d1e5eb16eea580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Gon=C3=A7alves=20de=20Andrade?= <0vetor0@gmail.com> Date: Sun, 25 May 2025 15:41:49 -0300 Subject: [PATCH 9/9] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e510d5cbce..b676142133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] -## [21.1.1] - 2024-11-19 +## [21.2.0] - 2024-11-19 - Adds signInFeature type and validation for form fields in EmailPassword Recipe.