From 0ce9cb99f90b25835de7ccb12752ae97409c9d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Lengyel?= Date: Mon, 16 Oct 2023 11:50:01 +0200 Subject: [PATCH] fix: fix tenant filtering in getUsers (#719) * fix: fix tenant filtering in getUsers * chore: update build/pkg lock --- CHANGELOG.md | 6 + .../accountlinking/recipeImplementation.js | 6 +- lib/build/recipe/accountlinking/types.d.ts | 1 + lib/build/version.d.ts | 2 +- lib/build/version.js | 2 +- .../accountlinking/recipeImplementation.ts | 4 +- lib/ts/recipe/accountlinking/types.ts | 1 + lib/ts/version.ts | 2 +- package-lock.json | 4 +- package.json | 2 +- test/accountlinking/helperFunctions.test.js | 126 ++++++++++++++++++ 11 files changed, 147 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d63aa9698..6515e0b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) +## [16.3.2] - 2023-10-16 + +### Fixes + +- `getUsersNewestFirst` and `getUsersOldestFirst` will now properly filter users by tenantId. + ## [16.3.1] - 2023-10-12 ### Fixes diff --git a/lib/build/recipe/accountlinking/recipeImplementation.js b/lib/build/recipe/accountlinking/recipeImplementation.js index 03043931b..16c7fb2f8 100644 --- a/lib/build/recipe/accountlinking/recipeImplementation.js +++ b/lib/build/recipe/accountlinking/recipeImplementation.js @@ -23,13 +23,15 @@ const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const user_1 = require("../../user"); function getRecipeImplementation(querier, config, recipeInstance) { return { - getUsers: async function ({ timeJoinedOrder, limit, paginationToken, includeRecipeIds, query }) { + getUsers: async function ({ tenantId, timeJoinedOrder, limit, paginationToken, includeRecipeIds, query }) { let includeRecipeIdsStr = undefined; if (includeRecipeIds !== undefined) { includeRecipeIdsStr = includeRecipeIds.join(","); } let response = await querier.sendGetRequest( - new normalisedURLPath_1.default("/users"), + new normalisedURLPath_1.default( + `${tenantId !== null && tenantId !== void 0 ? tenantId : "public"}/users` + ), Object.assign( { includeRecipeIds: includeRecipeIdsStr, diff --git a/lib/build/recipe/accountlinking/types.d.ts b/lib/build/recipe/accountlinking/types.d.ts index ee66ae675..804682e69 100644 --- a/lib/build/recipe/accountlinking/types.d.ts +++ b/lib/build/recipe/accountlinking/types.d.ts @@ -54,6 +54,7 @@ export declare type TypeNormalisedInput = { }; export declare type RecipeInterface = { getUsers: (input: { + tenantId: string; timeJoinedOrder: "ASC" | "DESC"; limit?: number; paginationToken?: string; diff --git a/lib/build/version.d.ts b/lib/build/version.d.ts index 0526ec868..b5080728e 100644 --- a/lib/build/version.d.ts +++ b/lib/build/version.d.ts @@ -1,4 +1,4 @@ // @ts-nocheck -export declare const version = "16.3.1"; +export declare const version = "16.3.2"; export declare const cdiSupported: string[]; export declare const dashboardVersion = "0.8"; diff --git a/lib/build/version.js b/lib/build/version.js index 4e4eeb4aa..91d42690d 100644 --- a/lib/build/version.js +++ b/lib/build/version.js @@ -15,7 +15,7 @@ exports.dashboardVersion = exports.cdiSupported = exports.version = void 0; * License for the specific language governing permissions and limitations * under the License. */ -exports.version = "16.3.1"; +exports.version = "16.3.2"; exports.cdiSupported = ["4.0"]; // Note: The actual script import for dashboard uses v{DASHBOARD_VERSION} exports.dashboardVersion = "0.8"; diff --git a/lib/ts/recipe/accountlinking/recipeImplementation.ts b/lib/ts/recipe/accountlinking/recipeImplementation.ts index 75cdefb25..4c8655921 100644 --- a/lib/ts/recipe/accountlinking/recipeImplementation.ts +++ b/lib/ts/recipe/accountlinking/recipeImplementation.ts @@ -30,12 +30,14 @@ export default function getRecipeImplementation( getUsers: async function ( this: RecipeInterface, { + tenantId, timeJoinedOrder, limit, paginationToken, includeRecipeIds, query, }: { + tenantId: string; timeJoinedOrder: "ASC" | "DESC"; limit?: number; paginationToken?: string; @@ -50,7 +52,7 @@ export default function getRecipeImplementation( if (includeRecipeIds !== undefined) { includeRecipeIdsStr = includeRecipeIds.join(","); } - let response = await querier.sendGetRequest(new NormalisedURLPath("/users"), { + let response = await querier.sendGetRequest(new NormalisedURLPath(`${tenantId ?? "public"}/users`), { includeRecipeIds: includeRecipeIdsStr, timeJoinedOrder: timeJoinedOrder, limit: limit, diff --git a/lib/ts/recipe/accountlinking/types.ts b/lib/ts/recipe/accountlinking/types.ts index e52d83cb7..65d15f44f 100644 --- a/lib/ts/recipe/accountlinking/types.ts +++ b/lib/ts/recipe/accountlinking/types.ts @@ -67,6 +67,7 @@ export type TypeNormalisedInput = { export type RecipeInterface = { getUsers: (input: { + tenantId: string; timeJoinedOrder: "ASC" | "DESC"; limit?: number; paginationToken?: string; diff --git a/lib/ts/version.ts b/lib/ts/version.ts index 9f01964aa..d27b134ca 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 = "16.3.1"; +export const version = "16.3.2"; export const cdiSupported = ["4.0"]; diff --git a/package-lock.json b/package-lock.json index dbc13d373..b256f9f86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "supertokens-node", - "version": "16.3.1", + "version": "16.3.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "supertokens-node", - "version": "16.2.1", + "version": "16.3.2", "license": "Apache-2.0", "dependencies": { "content-type": "^1.0.5", diff --git a/package.json b/package.json index 19f3dafbf..96446f114 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "supertokens-node", - "version": "16.3.1", + "version": "16.3.2", "description": "NodeJS driver for SuperTokens core", "main": "index.js", "scripts": { diff --git a/test/accountlinking/helperFunctions.test.js b/test/accountlinking/helperFunctions.test.js index e01417138..c44c0726b 100644 --- a/test/accountlinking/helperFunctions.test.js +++ b/test/accountlinking/helperFunctions.test.js @@ -29,6 +29,7 @@ let { ProcessState, PROCESS_STATE } = require("../../lib/build/processState"); let EmailPassword = require("../../recipe/emailpassword"); let EmailVerification = require("../../recipe/emailverification"); let ThirdParty = require("../../recipe/thirdparty"); +let Multitenancy = require("../../recipe/multitenancy"); let AccountLinking = require("../../recipe/accountlinking"); let AccountLinkingRecipe = require("../../lib/build/recipe/accountlinking/recipe").default; @@ -1137,6 +1138,70 @@ describe(`accountlinkingTests: ${printPath("[test/accountlinking/helperFunctions }); describe("listUsersByAccountInfo tests", function () { + it("listUsersByAccountInfo filters by tenantId", async function () { + const connectionURI = await startSTWithMultitenancyAndAccountLinking(); + + supertokens.init({ + supertokens: { + connectionURI, + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Multitenancy.init(), + EmailPassword.init(), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + { + config: { + thirdPartyId: "google", + clients: [ + { + clientId: "", + clientSecret: "", + }, + ], + }, + }, + ], + }, + }), + Session.init(), + ], + }); + await Multitenancy.createOrUpdateTenant("tenant1", { + thirdPartyEnabled: true, + emailPasswordEnabled: true, + }); + + const { user: pubUser } = await EmailPassword.signUp("public", "test@example.com", "password123"); + + const { user: t1User } = await ThirdParty.manuallyCreateOrUpdateUser( + "tenant1", + "google", + "abc", + "test@example.com", + false + ); + + let t1UserList = await supertokens.listUsersByAccountInfo("tenant1", { + email: "test@example.com", + }); + + assert.strictEqual(t1UserList.length, 1); + assert.strictEqual(t1UserList[0].id, t1User.id); + + let pubUserList = await supertokens.listUsersByAccountInfo("public", { + email: "test@example.com", + }); + assert.strictEqual(pubUserList.length, 1); + assert.strictEqual(pubUserList[0].id, pubUser.id); + }); + it("listUsersByAccountInfo does and properly", async function () { const connectionURI = await startSTWithMultitenancyAndAccountLinking(); @@ -1242,6 +1307,67 @@ describe(`accountlinkingTests: ${printPath("[test/accountlinking/helperFunctions }); }); + describe("getUsers tests", function () { + it("getUsers filters by tenantId", async function () { + const connectionURI = await startSTWithMultitenancyAndAccountLinking(); + + supertokens.init({ + supertokens: { + connectionURI, + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Multitenancy.init(), + EmailPassword.init(), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + { + config: { + thirdPartyId: "google", + clients: [ + { + clientId: "", + clientSecret: "", + }, + ], + }, + }, + ], + }, + }), + Session.init(), + ], + }); + await Multitenancy.createOrUpdateTenant("tenant1", { + thirdPartyEnabled: true, + emailPasswordEnabled: true, + }); + + const { user: pubUser } = await EmailPassword.signUp("public", "test@example.com", "password123"); + + const { user: t1User } = await ThirdParty.manuallyCreateOrUpdateUser( + "tenant1", + "google", + "abc", + "test@example.com", + false + ); + + let { users: t1UserList } = await supertokens.getUsersNewestFirst({ tenantId: "tenant1" }); + assert.strictEqual(t1UserList.length, 1); + assert.strictEqual(t1UserList[0].id, t1User.id); + + let { users: pubUserList } = await supertokens.getUsersNewestFirst({ tenantId: "public" }); + assert.strictEqual(pubUserList.length, 1); + assert.strictEqual(pubUserList[0].id, pubUser.id); + }); + }); + describe("isEmailChangeAllowed tests", function () { it("isEmailChangeAllowed returns false if checking for email which belongs to other primary and if email password user is not a primary user or is not linked, and account linking is enabled and email verification is required", async function () { const connectionURI = await startSTWithMultitenancyAndAccountLinking();