diff --git a/lib/build/recipe/dashboard/api/analytics.d.ts b/lib/build/recipe/dashboard/api/analytics.d.ts index 8e0b0a4cf..80f1121b8 100644 --- a/lib/build/recipe/dashboard/api/analytics.d.ts +++ b/lib/build/recipe/dashboard/api/analytics.d.ts @@ -3,4 +3,4 @@ import { APIInterface, APIOptions } from "../types"; export declare type Response = { status: "OK"; }; -export default function analyticsPost(_: APIInterface, options: APIOptions, __: any): Promise; +export default function analyticsPost(_: APIInterface, ___: string, options: APIOptions, __: any): Promise; diff --git a/lib/build/recipe/dashboard/api/analytics.js b/lib/build/recipe/dashboard/api/analytics.js index 879fa9ce8..4e0f91cec 100644 --- a/lib/build/recipe/dashboard/api/analytics.js +++ b/lib/build/recipe/dashboard/api/analytics.js @@ -56,7 +56,7 @@ const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath" const version_1 = require("../../../version"); const error_1 = __importDefault(require("../../../error")); const axios_1 = __importDefault(require("axios")); -function analyticsPost(_, options, __) { +function analyticsPost(_, ___, options, __) { return __awaiter(this, void 0, void 0, function* () { // If telemetry is disabled, dont send any event if (!supertokens_1.default.getInstanceOrThrowError().telemetryEnabled) { diff --git a/lib/build/recipe/dashboard/api/apiKeyProtector.d.ts b/lib/build/recipe/dashboard/api/apiKeyProtector.d.ts index 8304c3960..357ebeb82 100644 --- a/lib/build/recipe/dashboard/api/apiKeyProtector.d.ts +++ b/lib/build/recipe/dashboard/api/apiKeyProtector.d.ts @@ -2,6 +2,7 @@ import { APIFunction, APIInterface, APIOptions } from "../types"; export default function apiKeyProtector( apiImplementation: APIInterface, + tenantId: string, options: APIOptions, apiFunction: APIFunction, userContext: any diff --git a/lib/build/recipe/dashboard/api/apiKeyProtector.js b/lib/build/recipe/dashboard/api/apiKeyProtector.js index 33becbebf..be572cf54 100644 --- a/lib/build/recipe/dashboard/api/apiKeyProtector.js +++ b/lib/build/recipe/dashboard/api/apiKeyProtector.js @@ -32,7 +32,7 @@ var __awaiter = }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../utils"); -function apiKeyProtector(apiImplementation, options, apiFunction, userContext) { +function apiKeyProtector(apiImplementation, tenantId, options, apiFunction, userContext) { return __awaiter(this, void 0, void 0, function* () { const shouldAllowAccess = yield options.recipeImplementation.shouldAllowAccess({ req: options.req, @@ -43,7 +43,7 @@ function apiKeyProtector(apiImplementation, options, apiFunction, userContext) { utils_1.sendUnauthorisedAccess(options.res); return true; } - const response = yield apiFunction(apiImplementation, options, userContext); + const response = yield apiFunction(apiImplementation, tenantId, options, userContext); options.res.sendJSONResponse(response); return true; }); diff --git a/lib/build/recipe/dashboard/api/listTenants.d.ts b/lib/build/recipe/dashboard/api/listTenants.d.ts new file mode 100644 index 000000000..6633e6532 --- /dev/null +++ b/lib/build/recipe/dashboard/api/listTenants.d.ts @@ -0,0 +1,23 @@ +// @ts-nocheck +import { APIInterface, APIOptions } from "../types"; +import { ProviderConfig } from "../../thirdparty/types"; +export declare type Response = { + status: "OK"; + tenants: { + tenantId: string; + emailPassword: { + enabled: boolean; + }; + passwordless: { + enabled: boolean; + }; + thirdParty: { + enabled: boolean; + providers: ProviderConfig[]; + }; + coreConfig: { + [key: string]: any; + }; + }[]; +}; +export default function listTenants(_: APIInterface, __: string, ___: APIOptions, userContext: any): Promise; diff --git a/lib/build/recipe/dashboard/api/listTenants.js b/lib/build/recipe/dashboard/api/listTenants.js new file mode 100644 index 000000000..7cad0b06b --- /dev/null +++ b/lib/build/recipe/dashboard/api/listTenants.js @@ -0,0 +1,46 @@ +"use strict"; +var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; +Object.defineProperty(exports, "__esModule", { value: true }); +const multitenancy_1 = __importDefault(require("../../multitenancy")); +function listTenants(_, __, ___, userContext) { + return __awaiter(this, void 0, void 0, function* () { + let tenantsRes = yield multitenancy_1.default.listAllTenants(userContext); + return tenantsRes; + }); +} +exports.default = listTenants; diff --git a/lib/build/recipe/dashboard/api/search/tagsGet.d.ts b/lib/build/recipe/dashboard/api/search/tagsGet.d.ts index 89d1f2c12..537d69be1 100644 --- a/lib/build/recipe/dashboard/api/search/tagsGet.d.ts +++ b/lib/build/recipe/dashboard/api/search/tagsGet.d.ts @@ -4,5 +4,10 @@ declare type TagsResponse = { status: "OK"; tags: string[]; }; -export declare const getSearchTags: (_: APIInterface, options: APIOptions, __: any) => Promise; +export declare const getSearchTags: ( + _: APIInterface, + ___: string, + options: APIOptions, + __: any +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/search/tagsGet.js b/lib/build/recipe/dashboard/api/search/tagsGet.js index 8c5a6e0e1..4a25b9dcc 100644 --- a/lib/build/recipe/dashboard/api/search/tagsGet.js +++ b/lib/build/recipe/dashboard/api/search/tagsGet.js @@ -53,7 +53,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.getSearchTags = void 0; const querier_1 = require("../../../../querier"); const normalisedURLPath_1 = __importDefault(require("../../../../normalisedURLPath")); -const getSearchTags = (_, options, __) => +const getSearchTags = (_, ___, options, __) => __awaiter(void 0, void 0, void 0, function* () { let querier = querier_1.Querier.getNewInstanceOrThrowError(options.recipeId); let tagsResponse = yield querier.sendGetRequest(new normalisedURLPath_1.default("/user/search/tags"), {}); diff --git a/lib/build/recipe/dashboard/api/signOut.d.ts b/lib/build/recipe/dashboard/api/signOut.d.ts index 94abfb8cf..860f728b6 100644 --- a/lib/build/recipe/dashboard/api/signOut.d.ts +++ b/lib/build/recipe/dashboard/api/signOut.d.ts @@ -1,3 +1,3 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../types"; -export default function signOut(_: APIInterface, options: APIOptions, __: any): Promise; +export default function signOut(_: APIInterface, ___: string, options: APIOptions, __: any): Promise; diff --git a/lib/build/recipe/dashboard/api/signOut.js b/lib/build/recipe/dashboard/api/signOut.js index 0f4be075d..acc67eeff 100644 --- a/lib/build/recipe/dashboard/api/signOut.js +++ b/lib/build/recipe/dashboard/api/signOut.js @@ -53,7 +53,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../../../utils"); const querier_1 = require("../../../querier"); const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath")); -function signOut(_, options, __) { +function signOut(_, ___, options, __) { var _a; return __awaiter(this, void 0, void 0, function* () { if (options.config.authMode === "api-key") { diff --git a/lib/build/recipe/dashboard/api/userdetails/userDelete.d.ts b/lib/build/recipe/dashboard/api/userdetails/userDelete.d.ts index 0087f4fd2..5ff53a862 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userDelete.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userDelete.d.ts @@ -3,5 +3,5 @@ import { APIInterface, APIOptions } from "../../types"; declare type Response = { status: "OK"; }; -export declare const userDelete: (_: APIInterface, options: APIOptions, __: any) => Promise; +export declare const userDelete: (_: APIInterface, ___: string, options: APIOptions, __: any) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userDelete.js b/lib/build/recipe/dashboard/api/userdetails/userDelete.js index af86137b1..6596186fd 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userDelete.js +++ b/lib/build/recipe/dashboard/api/userdetails/userDelete.js @@ -39,7 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.userDelete = void 0; const supertokens_1 = __importDefault(require("../../../../supertokens")); const error_1 = __importDefault(require("../../../../error")); -const userDelete = (_, options, __) => +const userDelete = (_, ___, options, __) => __awaiter(void 0, void 0, void 0, function* () { const userId = options.req.getKeyValueFromQuery("userId"); if (userId === undefined) { diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyGet.js b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyGet.js index 41d2785bf..958a0231e 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyGet.js @@ -40,7 +40,7 @@ exports.userEmailverifyGet = void 0; const error_1 = __importDefault(require("../../../../error")); const recipe_1 = __importDefault(require("../../../emailverification/recipe")); const emailverification_1 = __importDefault(require("../../../emailverification")); -const userEmailverifyGet = (_, options, userContext) => +const userEmailverifyGet = (_, ___, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const req = options.req; const userId = req.getKeyValueFromQuery("userId"); diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.d.ts index e70fb753b..5f2b605d5 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.d.ts @@ -3,5 +3,10 @@ import { APIInterface, APIOptions } from "../../types"; declare type Response = { status: "OK"; }; -export declare const userEmailVerifyPut: (_: APIInterface, options: APIOptions, userContext: any) => Promise; +export declare const userEmailVerifyPut: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: any +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.js b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.js index 62be6057b..16691d233 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.js @@ -39,7 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.userEmailVerifyPut = void 0; const error_1 = __importDefault(require("../../../../error")); const emailverification_1 = __importDefault(require("../../../emailverification")); -const userEmailVerifyPut = (_, options, userContext) => +const userEmailVerifyPut = (_, tenantId, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const requestBody = yield options.req.getJSONBody(); const userId = requestBody.userId; @@ -60,6 +60,7 @@ const userEmailVerifyPut = (_, options, userContext) => const tokenResponse = yield emailverification_1.default.createEmailVerificationToken( userId, undefined, + tenantId, userContext ); if (tokenResponse.status === "EMAIL_ALREADY_VERIFIED_ERROR") { @@ -69,6 +70,7 @@ const userEmailVerifyPut = (_, options, userContext) => } const verifyResponse = yield emailverification_1.default.verifyEmailUsingToken( tokenResponse.token, + tenantId, userContext ); if (verifyResponse.status === "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR") { diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.d.ts b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.d.ts index c7e416918..68039149d 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.d.ts @@ -5,6 +5,7 @@ declare type Response = { }; export declare const userEmailVerifyTokenPost: ( _: APIInterface, + tenantId: string, options: APIOptions, userContext: any ) => Promise; diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.js b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.js index f19c6b1f5..2eae6be79 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.js +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.js @@ -41,7 +41,7 @@ const error_1 = __importDefault(require("../../../../error")); const emailverification_1 = __importDefault(require("../../../emailverification")); const recipe_1 = __importDefault(require("../../../emailverification/recipe")); const utils_1 = require("../../../emailverification/utils"); -const userEmailVerifyTokenPost = (_, options, userContext) => +const userEmailVerifyTokenPost = (_, tenantId, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const requestBody = yield options.req.getJSONBody(); const userId = requestBody.userId; @@ -58,6 +58,7 @@ const userEmailVerifyTokenPost = (_, options, userContext) => let emailVerificationToken = yield emailverification_1.default.createEmailVerificationToken( userId, undefined, + tenantId, userContext ); if (emailVerificationToken.status === "EMAIL_ALREADY_VERIFIED_ERROR") { @@ -65,7 +66,6 @@ const userEmailVerifyTokenPost = (_, options, userContext) => status: "EMAIL_ALREADY_VERIFIED_ERROR", }; } - const tenantId = ""; let emailVerifyLink = utils_1.getEmailVerifyLink({ appInfo: options.appInfo, token: emailVerificationToken.token, diff --git a/lib/build/recipe/dashboard/api/userdetails/userGet.js b/lib/build/recipe/dashboard/api/userdetails/userGet.js index e3edc28a0..67b237620 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userGet.js @@ -41,7 +41,7 @@ const error_1 = __importDefault(require("../../../../error")); const utils_1 = require("../../utils"); const recipe_1 = __importDefault(require("../../../usermetadata/recipe")); const usermetadata_1 = __importDefault(require("../../../usermetadata")); -const userGet = (_, options, userContext) => +const userGet = (_, ___, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const userId = options.req.getKeyValueFromQuery("userId"); const recipeId = options.req.getKeyValueFromQuery("recipeId"); diff --git a/lib/build/recipe/dashboard/api/userdetails/userMetadataGet.js b/lib/build/recipe/dashboard/api/userdetails/userMetadataGet.js index 4876cc22c..04f9dcb1f 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userMetadataGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userMetadataGet.js @@ -40,7 +40,7 @@ exports.userMetaDataGet = void 0; const error_1 = __importDefault(require("../../../../error")); const recipe_1 = __importDefault(require("../../../usermetadata/recipe")); const usermetadata_1 = __importDefault(require("../../../usermetadata")); -const userMetaDataGet = (_, options, userContext) => +const userMetaDataGet = (_, ___, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const userId = options.req.getKeyValueFromQuery("userId"); if (userId === undefined) { diff --git a/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.d.ts index f1eee84b6..0fa8dac6b 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.d.ts @@ -3,5 +3,10 @@ import { APIInterface, APIOptions } from "../../types"; declare type Response = { status: "OK"; }; -export declare const userMetadataPut: (_: APIInterface, options: APIOptions, userContext: any) => Promise; +export declare const userMetadataPut: ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: any +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.js b/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.js index 01b465789..db731489a 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.js @@ -40,7 +40,7 @@ exports.userMetadataPut = void 0; const recipe_1 = __importDefault(require("../../../usermetadata/recipe")); const usermetadata_1 = __importDefault(require("../../../usermetadata")); const error_1 = __importDefault(require("../../../../error")); -const userMetadataPut = (_, options, userContext) => +const userMetadataPut = (_, ___, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const requestBody = yield options.req.getJSONBody(); const userId = requestBody.userId; diff --git a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.d.ts index 4885b9e0c..f2cbf6abd 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.d.ts @@ -8,5 +8,10 @@ declare type Response = status: "INVALID_PASSWORD_ERROR"; error: string; }; -export declare const userPasswordPut: (_: APIInterface, options: APIOptions, userContext: any) => Promise; +export declare const userPasswordPut: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: any +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js index 2e7033748..d4fed4a91 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js @@ -43,7 +43,7 @@ const emailpassword_1 = __importDefault(require("../../../emailpassword")); const recipe_2 = __importDefault(require("../../../thirdpartyemailpassword/recipe")); const thirdpartyemailpassword_1 = __importDefault(require("../../../thirdpartyemailpassword")); const constants_1 = require("../../../emailpassword/constants"); -const userPasswordPut = (_, options, userContext) => +const userPasswordPut = (_, tenantId, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const requestBody = yield options.req.getJSONBody(); const userId = requestBody.userId; @@ -86,7 +86,11 @@ const userPasswordPut = (_, options, userContext) => error: passwordValidationError, }; } - const passwordResetToken = yield emailpassword_1.default.createResetPasswordToken(userId, userContext); + const passwordResetToken = yield emailpassword_1.default.createResetPasswordToken( + userId, + tenantId, + userContext + ); if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") { // Techincally it can but its an edge case so we assume that it wont throw new Error("Should never come here"); @@ -94,6 +98,7 @@ const userPasswordPut = (_, options, userContext) => const passwordResetResponse = yield emailpassword_1.default.resetPasswordUsingToken( passwordResetToken.token, newPassword, + tenantId, userContext ); if (passwordResetResponse.status === "RESET_PASSWORD_INVALID_TOKEN_ERROR") { @@ -115,6 +120,7 @@ const userPasswordPut = (_, options, userContext) => } const passwordResetToken = yield thirdpartyemailpassword_1.default.createResetPasswordToken( userId, + tenantId, userContext ); if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") { @@ -124,6 +130,7 @@ const userPasswordPut = (_, options, userContext) => const passwordResetResponse = yield thirdpartyemailpassword_1.default.resetPasswordUsingToken( passwordResetToken.token, newPassword, + tenantId, userContext ); if (passwordResetResponse.status === "RESET_PASSWORD_INVALID_TOKEN_ERROR") { diff --git a/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts index 51c5edb2a..08684b279 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts @@ -18,5 +18,10 @@ declare type Response = status: "INVALID_PHONE_ERROR"; error: string; }; -export declare const userPut: (_: APIInterface, options: APIOptions, userContext: any) => Promise; +export declare const userPut: ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: any +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userPut.js b/lib/build/recipe/dashboard/api/userdetails/userPut.js index cc6f06a33..cb628ea4d 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userPut.js @@ -278,7 +278,7 @@ const updatePhoneForRecipeId = (recipeId, userId, phone, userContext) => */ throw new Error("Should never come here"); }); -const userPut = (_, options, userContext) => +const userPut = (_, ___, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const requestBody = yield options.req.getJSONBody(); const userId = requestBody.userId; diff --git a/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js b/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js index 2d2e16e9e..b49fb12ff 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js @@ -39,7 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.userSessionsGet = void 0; const error_1 = __importDefault(require("../../../../error")); const session_1 = __importDefault(require("../../../session")); -const userSessionsGet = (_, options, userContext) => +const userSessionsGet = (_, ___, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const userId = options.req.getKeyValueFromQuery("userId"); if (userId === undefined) { @@ -48,7 +48,7 @@ const userSessionsGet = (_, options, userContext) => type: error_1.default.BAD_INPUT_ERROR, }); } - const response = yield session_1.default.getAllSessionHandlesForUser(userId, userContext); + const response = yield session_1.default.getAllSessionHandlesForUser(userId, undefined, userContext); let sessions = []; let sessionInfoPromises = []; for (let i = 0; i < response.length; i++) { diff --git a/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.d.ts b/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.d.ts index 47aaa7d37..cc1b697dc 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.d.ts @@ -3,5 +3,10 @@ import { APIInterface, APIOptions } from "../../types"; declare type Response = { status: "OK"; }; -export declare const userSessionsPost: (_: APIInterface, options: APIOptions, userContext: any) => Promise; +export declare const userSessionsPost: ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: any +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.js b/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.js index 4a069cdaa..449bc9fd6 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.js +++ b/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.js @@ -39,7 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.userSessionsPost = void 0; const error_1 = __importDefault(require("../../../../error")); const session_1 = __importDefault(require("../../../session")); -const userSessionsPost = (_, options, userContext) => +const userSessionsPost = (_, ___, options, userContext) => __awaiter(void 0, void 0, void 0, function* () { const requestBody = yield options.req.getJSONBody(); const sessionHandles = requestBody.sessionHandles; diff --git a/lib/build/recipe/dashboard/api/usersCountGet.d.ts b/lib/build/recipe/dashboard/api/usersCountGet.d.ts index ee85bd142..78b011594 100644 --- a/lib/build/recipe/dashboard/api/usersCountGet.d.ts +++ b/lib/build/recipe/dashboard/api/usersCountGet.d.ts @@ -4,4 +4,4 @@ export declare type Response = { status: "OK"; count: number; }; -export default function usersCountGet(_: APIInterface, __: APIOptions, ___: any): Promise; +export default function usersCountGet(_: APIInterface, tenantId: string, __: APIOptions, ___: any): Promise; diff --git a/lib/build/recipe/dashboard/api/usersCountGet.js b/lib/build/recipe/dashboard/api/usersCountGet.js index 35163c0d7..4c032bb59 100644 --- a/lib/build/recipe/dashboard/api/usersCountGet.js +++ b/lib/build/recipe/dashboard/api/usersCountGet.js @@ -51,9 +51,9 @@ var __importDefault = }; Object.defineProperty(exports, "__esModule", { value: true }); const supertokens_1 = __importDefault(require("../../../supertokens")); -function usersCountGet(_, __, ___) { +function usersCountGet(_, tenantId, __, ___) { return __awaiter(this, void 0, void 0, function* () { - const count = yield supertokens_1.default.getInstanceOrThrowError().getUserCount(); + const count = yield supertokens_1.default.getInstanceOrThrowError().getUserCount(undefined, tenantId); return { status: "OK", count, diff --git a/lib/build/recipe/dashboard/api/usersGet.d.ts b/lib/build/recipe/dashboard/api/usersGet.d.ts index 1b35c5447..379b01c5f 100644 --- a/lib/build/recipe/dashboard/api/usersGet.d.ts +++ b/lib/build/recipe/dashboard/api/usersGet.d.ts @@ -10,6 +10,7 @@ export declare type Response = { timeJoined: number; firstName?: string; lastName?: string; + tenantIds: string[]; } & ( | { email: string; @@ -28,7 +29,12 @@ export declare type Response = { ); }[]; }; -export default function usersGet(_: APIInterface, options: APIOptions, userContext: any): Promise; +export default function usersGet( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: any +): Promise; export declare function getSearchParamsFromURL( path: string ): { diff --git a/lib/build/recipe/dashboard/api/usersGet.js b/lib/build/recipe/dashboard/api/usersGet.js index eb7b3876d..1f2e91b1c 100644 --- a/lib/build/recipe/dashboard/api/usersGet.js +++ b/lib/build/recipe/dashboard/api/usersGet.js @@ -41,7 +41,7 @@ const error_1 = __importDefault(require("../../../error")); const supertokens_1 = __importDefault(require("../../../supertokens")); const recipe_1 = __importDefault(require("../../usermetadata/recipe")); const usermetadata_1 = __importDefault(require("../../usermetadata")); -function usersGet(_, options, userContext) { +function usersGet(_, tenantId, options, userContext) { return __awaiter(this, void 0, void 0, function* () { const req = options.req; const limit = options.req.getKeyValueFromQuery("limit"); @@ -68,6 +68,7 @@ function usersGet(_, options, userContext) { timeJoinedOrder: timeJoinedOrder, limit: parseInt(limit), paginationToken, + tenantId, }); // If the UserMetaData recipe has been initialised, fetch first and last name try { diff --git a/lib/build/recipe/dashboard/constants.d.ts b/lib/build/recipe/dashboard/constants.d.ts index 7b0c33787..0ef826f56 100644 --- a/lib/build/recipe/dashboard/constants.d.ts +++ b/lib/build/recipe/dashboard/constants.d.ts @@ -13,3 +13,4 @@ export declare const USER_PASSWORD_API = "/api/user/password"; export declare const USER_EMAIL_VERIFY_TOKEN_API = "/api/user/email/verify/token"; export declare const SEARCH_TAGS_API = "/api/search/tags"; export declare const DASHBOARD_ANALYTICS_API = "/api/analytics"; +export declare const TENANTS_LIST_API = "/api/tenants/list"; diff --git a/lib/build/recipe/dashboard/constants.js b/lib/build/recipe/dashboard/constants.js index 9cf1620dc..ea41c846b 100644 --- a/lib/build/recipe/dashboard/constants.js +++ b/lib/build/recipe/dashboard/constants.js @@ -14,7 +14,7 @@ * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -exports.DASHBOARD_ANALYTICS_API = exports.SEARCH_TAGS_API = exports.USER_EMAIL_VERIFY_TOKEN_API = exports.USER_PASSWORD_API = exports.USER_SESSIONS_API = exports.USER_METADATA_API = exports.USER_EMAIL_VERIFY_API = exports.USER_API = exports.USERS_COUNT_API = exports.USERS_LIST_GET_API = exports.VALIDATE_KEY_API = exports.SIGN_OUT_API = exports.SIGN_IN_API = exports.DASHBOARD_API = void 0; +exports.TENANTS_LIST_API = exports.DASHBOARD_ANALYTICS_API = exports.SEARCH_TAGS_API = exports.USER_EMAIL_VERIFY_TOKEN_API = exports.USER_PASSWORD_API = exports.USER_SESSIONS_API = exports.USER_METADATA_API = exports.USER_EMAIL_VERIFY_API = exports.USER_API = exports.USERS_COUNT_API = exports.USERS_LIST_GET_API = exports.VALIDATE_KEY_API = exports.SIGN_OUT_API = exports.SIGN_IN_API = exports.DASHBOARD_API = void 0; exports.DASHBOARD_API = "/dashboard"; exports.SIGN_IN_API = "/api/signin"; exports.SIGN_OUT_API = "/api/signout"; @@ -29,3 +29,4 @@ exports.USER_PASSWORD_API = "/api/user/password"; exports.USER_EMAIL_VERIFY_TOKEN_API = "/api/user/email/verify/token"; exports.SEARCH_TAGS_API = "/api/search/tags"; exports.DASHBOARD_ANALYTICS_API = "/api/analytics"; +exports.TENANTS_LIST_API = "/api/tenants/list"; diff --git a/lib/build/recipe/dashboard/recipe.d.ts b/lib/build/recipe/dashboard/recipe.d.ts index 8c88a841d..88d94f3c1 100644 --- a/lib/build/recipe/dashboard/recipe.d.ts +++ b/lib/build/recipe/dashboard/recipe.d.ts @@ -19,7 +19,7 @@ export default class Recipe extends RecipeModule { getAPIsHandled: () => APIHandled[]; handleAPIRequest: ( id: string, - _: string | undefined, + tenantId: string, req: BaseRequest, res: BaseResponse, __: NormalisedURLPath, diff --git a/lib/build/recipe/dashboard/recipe.js b/lib/build/recipe/dashboard/recipe.js index 69493087d..6b6b0aa08 100644 --- a/lib/build/recipe/dashboard/recipe.js +++ b/lib/build/recipe/dashboard/recipe.js @@ -80,6 +80,7 @@ const tagsGet_1 = require("./api/search/tagsGet"); const analytics_1 = __importDefault(require("./api/analytics")); const constants_2 = require("../multitenancy/constants"); const recipe_1 = __importDefault(require("../../recipe/multitenancy/recipe")); +const listTenants_1 = __importDefault(require("./api/listTenants")); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { super(recipeId, appInfo); @@ -251,15 +252,7 @@ class Recipe extends recipeModule_1.default { }, ]; }; - this.handleAPIRequest = ( - id, - _, // TODO tenantId - req, - res, - __, - ___, - userContext - ) => + this.handleAPIRequest = (id, tenantId, req, res, __, ___, userContext) => __awaiter(this, void 0, void 0, function* () { let options = { config: this.config, @@ -327,12 +320,14 @@ class Recipe extends recipeModule_1.default { apiFunction = signOut_1.default; } else if (id === constants_1.DASHBOARD_ANALYTICS_API && req.getMethod() === "post") { apiFunction = analytics_1.default; + } else if (id === constants_1.TENANTS_LIST_API) { + apiFunction = listTenants_1.default; } // If the id doesnt match any APIs return false if (apiFunction === undefined) { return false; } - return yield apiKeyProtector_1.default(this.apiImpl, options, apiFunction, userContext); + return yield apiKeyProtector_1.default(this.apiImpl, tenantId, options, apiFunction, userContext); }); this.handleError = (err, _, __) => __awaiter(this, void 0, void 0, function* () { diff --git a/lib/build/recipe/dashboard/types.d.ts b/lib/build/recipe/dashboard/types.d.ts index 5547dd146..1cc924e7f 100644 --- a/lib/build/recipe/dashboard/types.d.ts +++ b/lib/build/recipe/dashboard/types.d.ts @@ -41,6 +41,7 @@ export declare type APIInterface = { }; export declare type APIFunction = ( apiImplementation: APIInterface, + tenantId: string, options: APIOptions, userContext: any ) => Promise; @@ -51,6 +52,7 @@ declare type CommonUserInformation = { timeJoined: number; firstName: string; lastName: string; + tenantIds: string[]; }; export declare type EmailPasswordUser = CommonUserInformation & { email: string; diff --git a/lib/build/recipe/multitenancy/index.d.ts b/lib/build/recipe/multitenancy/index.d.ts index b170566a6..ff639cb9e 100644 --- a/lib/build/recipe/multitenancy/index.d.ts +++ b/lib/build/recipe/multitenancy/index.d.ts @@ -51,7 +51,22 @@ export default class Wrapper { userContext?: any ): Promise<{ status: "OK"; - tenants: string[]; + tenants: { + tenantId: string; + emailPassword: { + enabled: boolean; + }; + passwordless: { + enabled: boolean; + }; + thirdParty: { + enabled: boolean; + providers: ProviderConfig[]; + }; + coreConfig: { + [key: string]: any; + }; + }[]; }>; static createOrUpdateThirdPartyConfig( tenantId: string | undefined, diff --git a/lib/build/recipe/multitenancy/types.d.ts b/lib/build/recipe/multitenancy/types.d.ts index 45b124472..444f3c2a8 100644 --- a/lib/build/recipe/multitenancy/types.d.ts +++ b/lib/build/recipe/multitenancy/types.d.ts @@ -86,7 +86,22 @@ export declare type RecipeInterface = { userContext: any; }) => Promise<{ status: "OK"; - tenants: string[]; + tenants: { + tenantId: string; + emailPassword: { + enabled: boolean; + }; + passwordless: { + enabled: boolean; + }; + thirdParty: { + enabled: boolean; + providers: ProviderConfig[]; + }; + coreConfig: { + [key: string]: any; + }; + }[]; }>; createOrUpdateThirdPartyConfig: (input: { tenantId?: string; diff --git a/lib/build/supertokens.d.ts b/lib/build/supertokens.d.ts index cde5f888b..34b77cadf 100644 --- a/lib/build/supertokens.d.ts +++ b/lib/build/supertokens.d.ts @@ -27,13 +27,14 @@ export default class SuperTokens { userContext: any ) => Promise; getAllCORSHeaders: () => string[]; - getUserCount: (includeRecipeIds?: string[] | undefined) => Promise; + getUserCount: (includeRecipeIds?: string[] | undefined, tenantId?: string | undefined) => Promise; getUsers: (input: { timeJoinedOrder: "ASC" | "DESC"; limit?: number; paginationToken?: string; includeRecipeIds?: string[]; query?: object; + tenantId?: string; }) => Promise<{ users: { recipeId: string; diff --git a/lib/build/supertokens.js b/lib/build/supertokens.js index 6dd5340f6..104c7895a 100644 --- a/lib/build/supertokens.js +++ b/lib/build/supertokens.js @@ -59,6 +59,7 @@ const error_1 = __importDefault(require("./error")); const logger_1 = require("./logger"); const postSuperTokensInitCallbacks_1 = require("./postSuperTokensInitCallbacks"); const recipe_1 = __importDefault(require("./recipe/multitenancy/recipe")); +const constants_2 = require("./recipe/multitenancy/constants"); class SuperTokens { constructor(config) { var _a, _b; @@ -78,7 +79,7 @@ class SuperTokens { }); return Array.from(headerSet); }; - this.getUserCount = (includeRecipeIds) => + this.getUserCount = (includeRecipeIds, tenantId) => __awaiter(this, void 0, void 0, function* () { let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); let apiVersion = yield querier.getAPIVersion(); @@ -91,9 +92,15 @@ class SuperTokens { if (includeRecipeIds !== undefined) { includeRecipeIdsStr = includeRecipeIds.join(","); } - let response = yield querier.sendGetRequest(new normalisedURLPath_1.default("/users/count"), { - includeRecipeIds: includeRecipeIdsStr, - }); + let response = yield querier.sendGetRequest( + new normalisedURLPath_1.default( + `${tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId}/users/count` + ), + { + includeRecipeIds: includeRecipeIdsStr, + includeAllTenants: tenantId === undefined, + } + ); return Number(response.count); }); this.getUsers = (input) => @@ -109,8 +116,11 @@ class SuperTokens { if (input.includeRecipeIds !== undefined) { includeRecipeIdsStr = input.includeRecipeIds.join(","); } + if (input.tenantId === undefined) { + input.tenantId = constants_2.DEFAULT_TENANT_ID; + } let response = yield querier.sendGetRequest( - new normalisedURLPath_1.default("/users"), + new normalisedURLPath_1.default(`/${input.tenantId}/users`), Object.assign(Object.assign({}, input.query), { includeRecipeIds: includeRecipeIdsStr, timeJoinedOrder: input.timeJoinedOrder, @@ -120,7 +130,7 @@ class SuperTokens { ); const users = response.users; return { - users: users.map(utils_1.updateTenantId), + users, nextPaginationToken: response.nextPaginationToken, }; }); diff --git a/lib/build/utils.d.ts b/lib/build/utils.d.ts index 878d88268..5a95076cb 100644 --- a/lib/build/utils.d.ts +++ b/lib/build/utils.d.ts @@ -14,12 +14,5 @@ export declare function frontendHasInterceptor(req: BaseRequest): boolean; export declare function humaniseMilliseconds(ms: number): string; export declare function makeDefaultUserContextFromAPI(request: BaseRequest): any; export declare function setRequestInUserContextIfNotDefined(userContext: any | undefined, request: BaseRequest): any; -export declare function updateTenantId(user: { - recipeId: string; - user: any; -}): { - recipeId: string; - user: any; -}; export declare function getTopLevelDomainForSameSiteResolution(url: string): string; export declare function getFromObjectCaseInsensitive(key: string, object: Record): T | undefined; diff --git a/lib/build/utils.js b/lib/build/utils.js index 3c34a1370..119069d47 100644 --- a/lib/build/utils.js +++ b/lib/build/utils.js @@ -41,7 +41,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getFromObjectCaseInsensitive = exports.getTopLevelDomainForSameSiteResolution = exports.updateTenantId = exports.setRequestInUserContextIfNotDefined = exports.makeDefaultUserContextFromAPI = exports.humaniseMilliseconds = exports.frontendHasInterceptor = exports.getRidFromHeader = exports.isAnIpAddress = exports.send200Response = exports.sendNon200Response = exports.sendNon200ResponseWithMessage = exports.normaliseHttpMethod = exports.normaliseInputAppInfoOrThrowError = exports.maxVersion = exports.getLargestVersionFromIntersection = void 0; +exports.getFromObjectCaseInsensitive = exports.getTopLevelDomainForSameSiteResolution = exports.setRequestInUserContextIfNotDefined = exports.makeDefaultUserContextFromAPI = exports.humaniseMilliseconds = exports.frontendHasInterceptor = exports.getRidFromHeader = exports.isAnIpAddress = exports.send200Response = exports.sendNon200Response = exports.sendNon200ResponseWithMessage = exports.normaliseHttpMethod = exports.normaliseInputAppInfoOrThrowError = exports.maxVersion = exports.getLargestVersionFromIntersection = void 0; const psl = __importStar(require("psl")); const normalisedURLDomain_1 = __importDefault(require("./normalisedURLDomain")); const normalisedURLPath_1 = __importDefault(require("./normalisedURLPath")); @@ -189,15 +189,6 @@ function setRequestInUserContextIfNotDefined(userContext, request) { return userContext; } exports.setRequestInUserContextIfNotDefined = setRequestInUserContextIfNotDefined; -function updateTenantId(user) { - if (user.user.thirdParty !== undefined && user.user.thirdParty.userId.includes("|")) { - return Object.assign(Object.assign({}, user), { - user: Object.assign(Object.assign({}, user.user), { tenantId: user.user.thirdParty.userId.split("|")[1] }), - }); - } - return user; -} -exports.updateTenantId = updateTenantId; function getTopLevelDomainForSameSiteResolution(url) { let urlObj = new URL(url); let hostname = urlObj.hostname; diff --git a/lib/ts/recipe/dashboard/api/analytics.ts b/lib/ts/recipe/dashboard/api/analytics.ts index ac1c64b0d..a5b17a478 100644 --- a/lib/ts/recipe/dashboard/api/analytics.ts +++ b/lib/ts/recipe/dashboard/api/analytics.ts @@ -25,7 +25,12 @@ export type Response = { status: "OK"; }; -export default async function analyticsPost(_: APIInterface, options: APIOptions, __: any): Promise { +export default async function analyticsPost( + _: APIInterface, + ___: string, + options: APIOptions, + __: any +): Promise { // If telemetry is disabled, dont send any event if (!SuperTokens.getInstanceOrThrowError().telemetryEnabled) { return { diff --git a/lib/ts/recipe/dashboard/api/apiKeyProtector.ts b/lib/ts/recipe/dashboard/api/apiKeyProtector.ts index 521282b0c..ad6edc541 100644 --- a/lib/ts/recipe/dashboard/api/apiKeyProtector.ts +++ b/lib/ts/recipe/dashboard/api/apiKeyProtector.ts @@ -17,6 +17,7 @@ import { sendUnauthorisedAccess } from "../utils"; export default async function apiKeyProtector( apiImplementation: APIInterface, + tenantId: string, options: APIOptions, apiFunction: APIFunction, userContext: any @@ -32,7 +33,7 @@ export default async function apiKeyProtector( return true; } - const response = await apiFunction(apiImplementation, options, userContext); + const response = await apiFunction(apiImplementation, tenantId, options, userContext); options.res.sendJSONResponse(response); return true; } diff --git a/lib/ts/recipe/dashboard/api/listTenants.ts b/lib/ts/recipe/dashboard/api/listTenants.ts new file mode 100644 index 000000000..c0ac1549b --- /dev/null +++ b/lib/ts/recipe/dashboard/api/listTenants.ts @@ -0,0 +1,45 @@ +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +import { APIInterface, APIOptions } from "../types"; +import Multitenancy from "../../multitenancy"; +import { ProviderConfig } from "../../thirdparty/types"; + +export type Response = { + status: "OK"; + tenants: { + tenantId: string; + emailPassword: { + enabled: boolean; + }; + passwordless: { + enabled: boolean; + }; + thirdParty: { + enabled: boolean; + providers: ProviderConfig[]; + }; + coreConfig: { [key: string]: any }; + }[]; +}; + +export default async function listTenants( + _: APIInterface, + __: string, + ___: APIOptions, + userContext: any +): Promise { + let tenantsRes = await Multitenancy.listAllTenants(userContext); + return tenantsRes; +} diff --git a/lib/ts/recipe/dashboard/api/search/tagsGet.ts b/lib/ts/recipe/dashboard/api/search/tagsGet.ts index 616e8c7b0..c16f48012 100644 --- a/lib/ts/recipe/dashboard/api/search/tagsGet.ts +++ b/lib/ts/recipe/dashboard/api/search/tagsGet.ts @@ -19,7 +19,12 @@ import NormalisedURLPath from "../../../../normalisedURLPath"; type TagsResponse = { status: "OK"; tags: string[] }; -export const getSearchTags = async (_: APIInterface, options: APIOptions, __: any): Promise => { +export const getSearchTags = async ( + _: APIInterface, + ___: string, + options: APIOptions, + __: any +): Promise => { let querier = Querier.getNewInstanceOrThrowError(options.recipeId); let tagsResponse = await querier.sendGetRequest(new NormalisedURLPath("/user/search/tags"), {}); return tagsResponse; diff --git a/lib/ts/recipe/dashboard/api/signOut.ts b/lib/ts/recipe/dashboard/api/signOut.ts index 8c5a1d42c..b6e92ec87 100644 --- a/lib/ts/recipe/dashboard/api/signOut.ts +++ b/lib/ts/recipe/dashboard/api/signOut.ts @@ -18,7 +18,7 @@ import { send200Response } from "../../../utils"; import { Querier } from "../../../querier"; import NormalisedURLPath from "../../../normalisedURLPath"; -export default async function signOut(_: APIInterface, options: APIOptions, __: any): Promise { +export default async function signOut(_: APIInterface, ___: string, options: APIOptions, __: any): Promise { if (options.config.authMode === "api-key") { send200Response(options.res, { status: "OK" }); } else { diff --git a/lib/ts/recipe/dashboard/api/userdetails/userDelete.ts b/lib/ts/recipe/dashboard/api/userdetails/userDelete.ts index b478fb748..65de7236c 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userDelete.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userDelete.ts @@ -6,7 +6,7 @@ type Response = { status: "OK"; }; -export const userDelete = async (_: APIInterface, options: APIOptions, __: any): Promise => { +export const userDelete = async (_: APIInterface, ___: string, options: APIOptions, __: any): Promise => { const userId = options.req.getKeyValueFromQuery("userId"); if (userId === undefined) { diff --git a/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyGet.ts b/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyGet.ts index 6e643a834..67ff5ff05 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyGet.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyGet.ts @@ -14,6 +14,7 @@ type Response = export const userEmailverifyGet: APIFunction = async ( _: APIInterface, + ___: string, options: APIOptions, userContext: any ): Promise => { diff --git a/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyPut.ts b/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyPut.ts index f04ee4b4d..fed4238b9 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyPut.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyPut.ts @@ -6,7 +6,12 @@ type Response = { status: "OK"; }; -export const userEmailVerifyPut = async (_: APIInterface, options: APIOptions, userContext: any): Promise => { +export const userEmailVerifyPut = async ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: any +): Promise => { const requestBody = await options.req.getJSONBody(); const userId = requestBody.userId; const verified = requestBody.verified; @@ -26,7 +31,12 @@ export const userEmailVerifyPut = async (_: APIInterface, options: APIOptions, u } if (verified) { - const tokenResponse = await EmailVerification.createEmailVerificationToken(userId, undefined, userContext); + const tokenResponse = await EmailVerification.createEmailVerificationToken( + userId, + undefined, + tenantId, + userContext + ); if (tokenResponse.status === "EMAIL_ALREADY_VERIFIED_ERROR") { return { @@ -34,7 +44,11 @@ export const userEmailVerifyPut = async (_: APIInterface, options: APIOptions, u }; } - const verifyResponse = await EmailVerification.verifyEmailUsingToken(tokenResponse.token, userContext); + const verifyResponse = await EmailVerification.verifyEmailUsingToken( + tokenResponse.token, + tenantId, + userContext + ); if (verifyResponse.status === "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR") { // This should never happen because we consume the token immediately after creating it diff --git a/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.ts b/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.ts index 3977b03e6..3e2f7227d 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.ts @@ -10,6 +10,7 @@ type Response = { export const userEmailVerifyTokenPost = async ( _: APIInterface, + tenantId: string, options: APIOptions, userContext: any ): Promise => { @@ -29,7 +30,12 @@ export const userEmailVerifyTokenPost = async ( throw new Error("Should never come here"); } - let emailVerificationToken = await EmailVerification.createEmailVerificationToken(userId, undefined, userContext); + let emailVerificationToken = await EmailVerification.createEmailVerificationToken( + userId, + undefined, + tenantId, + userContext + ); if (emailVerificationToken.status === "EMAIL_ALREADY_VERIFIED_ERROR") { return { @@ -37,7 +43,6 @@ export const userEmailVerifyTokenPost = async ( }; } - const tenantId = ""; let emailVerifyLink = getEmailVerifyLink({ appInfo: options.appInfo, token: emailVerificationToken.token, diff --git a/lib/ts/recipe/dashboard/api/userdetails/userGet.ts b/lib/ts/recipe/dashboard/api/userdetails/userGet.ts index 3eb8a7268..98065350c 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userGet.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userGet.ts @@ -36,6 +36,7 @@ type Response = export const userGet: APIFunction = async ( _: APIInterface, + ___: string, options: APIOptions, userContext: any ): Promise => { diff --git a/lib/ts/recipe/dashboard/api/userdetails/userMetadataGet.ts b/lib/ts/recipe/dashboard/api/userdetails/userMetadataGet.ts index 733373ed7..4dd1016c7 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userMetadataGet.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userMetadataGet.ts @@ -14,6 +14,7 @@ type Response = export const userMetaDataGet: APIFunction = async ( _: APIInterface, + ___: string, options: APIOptions, userContext: any ): Promise => { diff --git a/lib/ts/recipe/dashboard/api/userdetails/userMetadataPut.ts b/lib/ts/recipe/dashboard/api/userdetails/userMetadataPut.ts index 0853959b0..43c232ffe 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userMetadataPut.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userMetadataPut.ts @@ -7,7 +7,12 @@ type Response = { status: "OK"; }; -export const userMetadataPut = async (_: APIInterface, options: APIOptions, userContext: any): Promise => { +export const userMetadataPut = async ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: any +): Promise => { const requestBody = await options.req.getJSONBody(); const userId = requestBody.userId; const data = requestBody.data; diff --git a/lib/ts/recipe/dashboard/api/userdetails/userPasswordPut.ts b/lib/ts/recipe/dashboard/api/userdetails/userPasswordPut.ts index 6f670bfc2..f4023aef5 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userPasswordPut.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userPasswordPut.ts @@ -15,7 +15,12 @@ type Response = error: string; }; -export const userPasswordPut = async (_: APIInterface, options: APIOptions, userContext: any): Promise => { +export const userPasswordPut = async ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: any +): Promise => { const requestBody = await options.req.getJSONBody(); const userId = requestBody.userId; const newPassword = requestBody.newPassword; @@ -67,7 +72,7 @@ export const userPasswordPut = async (_: APIInterface, options: APIOptions, user }; } - const passwordResetToken = await EmailPassword.createResetPasswordToken(userId, userContext); + const passwordResetToken = await EmailPassword.createResetPasswordToken(userId, tenantId, userContext); if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") { // Techincally it can but its an edge case so we assume that it wont @@ -77,6 +82,7 @@ export const userPasswordPut = async (_: APIInterface, options: APIOptions, user const passwordResetResponse = await EmailPassword.resetPasswordUsingToken( passwordResetToken.token, newPassword, + tenantId, userContext ); @@ -102,7 +108,7 @@ export const userPasswordPut = async (_: APIInterface, options: APIOptions, user }; } - const passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(userId, userContext); + const passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(userId, tenantId, userContext); if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") { // Techincally it can but its an edge case so we assume that it wont @@ -112,6 +118,7 @@ export const userPasswordPut = async (_: APIInterface, options: APIOptions, user const passwordResetResponse = await ThirdPartyEmailPassword.resetPasswordUsingToken( passwordResetToken.token, newPassword, + tenantId, userContext ); diff --git a/lib/ts/recipe/dashboard/api/userdetails/userPut.ts b/lib/ts/recipe/dashboard/api/userdetails/userPut.ts index 01887a4d5..aa16f4980 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userPut.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userPut.ts @@ -345,7 +345,12 @@ const updatePhoneForRecipeId = async ( throw new Error("Should never come here"); }; -export const userPut = async (_: APIInterface, options: APIOptions, userContext: any): Promise => { +export const userPut = async ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: any +): Promise => { const requestBody = await options.req.getJSONBody(); const userId = requestBody.userId; const recipeId = requestBody.recipeId; diff --git a/lib/ts/recipe/dashboard/api/userdetails/userSessionsGet.ts b/lib/ts/recipe/dashboard/api/userdetails/userSessionsGet.ts index 818c4918f..fa1fcff9f 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userSessionsGet.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userSessionsGet.ts @@ -18,6 +18,7 @@ type Response = { export const userSessionsGet: APIFunction = async ( _: APIInterface, + ___: string, options: APIOptions, userContext: any ): Promise => { @@ -30,7 +31,7 @@ export const userSessionsGet: APIFunction = async ( }); } - const response = await Session.getAllSessionHandlesForUser(userId, userContext); + const response = await Session.getAllSessionHandlesForUser(userId, undefined, userContext); let sessions: SessionType[] = []; let sessionInfoPromises: Promise[] = []; diff --git a/lib/ts/recipe/dashboard/api/userdetails/userSessionsPost.ts b/lib/ts/recipe/dashboard/api/userdetails/userSessionsPost.ts index 928baa4c4..d7b142d2e 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userSessionsPost.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userSessionsPost.ts @@ -6,7 +6,12 @@ type Response = { status: "OK"; }; -export const userSessionsPost = async (_: APIInterface, options: APIOptions, userContext: any): Promise => { +export const userSessionsPost = async ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: any +): Promise => { const requestBody = await options.req.getJSONBody(); const sessionHandles = requestBody.sessionHandles; diff --git a/lib/ts/recipe/dashboard/api/usersCountGet.ts b/lib/ts/recipe/dashboard/api/usersCountGet.ts index 8b15ef88d..5d3b30105 100644 --- a/lib/ts/recipe/dashboard/api/usersCountGet.ts +++ b/lib/ts/recipe/dashboard/api/usersCountGet.ts @@ -21,8 +21,13 @@ export type Response = { count: number; }; -export default async function usersCountGet(_: APIInterface, __: APIOptions, ___: any): Promise { - const count = await SuperTokens.getInstanceOrThrowError().getUserCount(); +export default async function usersCountGet( + _: APIInterface, + tenantId: string, + __: APIOptions, + ___: any +): Promise { + const count = await SuperTokens.getInstanceOrThrowError().getUserCount(undefined, tenantId); return { status: "OK", diff --git a/lib/ts/recipe/dashboard/api/usersGet.ts b/lib/ts/recipe/dashboard/api/usersGet.ts index 62274845b..3142c2327 100644 --- a/lib/ts/recipe/dashboard/api/usersGet.ts +++ b/lib/ts/recipe/dashboard/api/usersGet.ts @@ -28,6 +28,7 @@ export type Response = { timeJoined: number; firstName?: string; lastName?: string; + tenantIds: string[]; } & ( | { email: string; @@ -47,7 +48,12 @@ export type Response = { }[]; }; -export default async function usersGet(_: APIInterface, options: APIOptions, userContext: any): Promise { +export default async function usersGet( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: any +): Promise { const req = options.req; const limit = options.req.getKeyValueFromQuery("limit"); @@ -78,6 +84,7 @@ export default async function usersGet(_: APIInterface, options: APIOptions, use timeJoinedOrder: timeJoinedOrder, limit: parseInt(limit), paginationToken, + tenantId, }); // If the UserMetaData recipe has been initialised, fetch first and last name diff --git a/lib/ts/recipe/dashboard/constants.ts b/lib/ts/recipe/dashboard/constants.ts index 3a148e376..60df0c66b 100644 --- a/lib/ts/recipe/dashboard/constants.ts +++ b/lib/ts/recipe/dashboard/constants.ts @@ -27,3 +27,4 @@ export const USER_PASSWORD_API = "/api/user/password"; export const USER_EMAIL_VERIFY_TOKEN_API = "/api/user/email/verify/token"; export const SEARCH_TAGS_API = "/api/search/tags"; export const DASHBOARD_ANALYTICS_API = "/api/analytics"; +export const TENANTS_LIST_API = "/api/tenants/list"; diff --git a/lib/ts/recipe/dashboard/recipe.ts b/lib/ts/recipe/dashboard/recipe.ts index 0cde61a9e..dbaeee3f4 100644 --- a/lib/ts/recipe/dashboard/recipe.ts +++ b/lib/ts/recipe/dashboard/recipe.ts @@ -26,6 +26,7 @@ import { SEARCH_TAGS_API, SIGN_IN_API, SIGN_OUT_API, + TENANTS_LIST_API, USERS_COUNT_API, USERS_LIST_GET_API, USER_API, @@ -61,6 +62,7 @@ import { getSearchTags } from "./api/search/tagsGet"; import analyticsPost from "./api/analytics"; import { DEFAULT_TENANT_ID } from "../multitenancy/constants"; import MultitenancyRecipe from "../../recipe/multitenancy/recipe"; +import listTenants from "./api/listTenants"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -249,7 +251,7 @@ export default class Recipe extends RecipeModule { handleAPIRequest = async ( id: string, - _: string | undefined, // TODO tenantId + tenantId: string, req: BaseRequest, res: BaseResponse, __: NormalisedURLPath, @@ -332,6 +334,8 @@ export default class Recipe extends RecipeModule { apiFunction = signOut; } else if (id === DASHBOARD_ANALYTICS_API && req.getMethod() === "post") { apiFunction = analyticsPost; + } else if (id === TENANTS_LIST_API) { + apiFunction = listTenants; } // If the id doesnt match any APIs return false @@ -339,7 +343,7 @@ export default class Recipe extends RecipeModule { return false; } - return await apiKeyProtector(this.apiImpl, options, apiFunction, userContext); + return await apiKeyProtector(this.apiImpl, tenantId, options, apiFunction, userContext); }; handleError = async (err: error, _: BaseRequest, __: BaseResponse): Promise => { diff --git a/lib/ts/recipe/dashboard/types.ts b/lib/ts/recipe/dashboard/types.ts index 66ccd0a00..7c0f5339d 100644 --- a/lib/ts/recipe/dashboard/types.ts +++ b/lib/ts/recipe/dashboard/types.ts @@ -59,7 +59,12 @@ export type APIInterface = { dashboardGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise); }; -export type APIFunction = (apiImplementation: APIInterface, options: APIOptions, userContext: any) => Promise; +export type APIFunction = ( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: any +) => Promise; export type RecipeIdForUser = "emailpassword" | "thirdparty" | "passwordless"; @@ -70,6 +75,7 @@ type CommonUserInformation = { timeJoined: number; firstName: string; lastName: string; + tenantIds: string[]; }; export type EmailPasswordUser = CommonUserInformation & { diff --git a/lib/ts/recipe/multitenancy/index.ts b/lib/ts/recipe/multitenancy/index.ts index 86e9414e5..2a30bda96 100644 --- a/lib/ts/recipe/multitenancy/index.ts +++ b/lib/ts/recipe/multitenancy/index.ts @@ -85,7 +85,20 @@ export default class Wrapper { userContext?: any ): Promise<{ status: "OK"; - tenants: string[]; + tenants: { + tenantId: string; + emailPassword: { + enabled: boolean; + }; + passwordless: { + enabled: boolean; + }; + thirdParty: { + enabled: boolean; + providers: ProviderConfig[]; + }; + coreConfig: { [key: string]: any }; + }[]; }> { const recipeInstance = Recipe.getInstanceOrThrowError(); return recipeInstance.recipeInterfaceImpl.listAllTenants({ diff --git a/lib/ts/recipe/multitenancy/types.ts b/lib/ts/recipe/multitenancy/types.ts index cddf1498e..ca624bafe 100644 --- a/lib/ts/recipe/multitenancy/types.ts +++ b/lib/ts/recipe/multitenancy/types.ts @@ -107,7 +107,20 @@ export type RecipeInterface = { userContext: any; }) => Promise<{ status: "OK"; - tenants: string[]; + tenants: { + tenantId: string; + emailPassword: { + enabled: boolean; + }; + passwordless: { + enabled: boolean; + }; + thirdParty: { + enabled: boolean; + providers: ProviderConfig[]; + }; + coreConfig: { [key: string]: any }; + }[]; }>; // Third party provider management diff --git a/lib/ts/supertokens.ts b/lib/ts/supertokens.ts index ff57a8c35..39a34597e 100644 --- a/lib/ts/supertokens.ts +++ b/lib/ts/supertokens.ts @@ -19,7 +19,6 @@ import { maxVersion, normaliseHttpMethod, sendNon200ResponseWithMessage, - updateTenantId, getRidFromHeader, } from "./utils"; import { Querier } from "./querier"; @@ -33,6 +32,7 @@ import STError from "./error"; import { logDebugMessage } from "./logger"; import { PostSuperTokensInitCallbacks } from "./postSuperTokensInitCallbacks"; import MultitenancyRecipe from "./recipe/multitenancy/recipe"; +import { DEFAULT_TENANT_ID } from "./recipe/multitenancy/constants"; export default class SuperTokens { private static instance: SuperTokens | undefined; @@ -146,7 +146,7 @@ export default class SuperTokens { return Array.from(headerSet); }; - getUserCount = async (includeRecipeIds?: string[]): Promise => { + getUserCount = async (includeRecipeIds?: string[], tenantId?: string): Promise => { let querier = Querier.getNewInstanceOrThrowError(undefined); let apiVersion = await querier.getAPIVersion(); if (maxVersion(apiVersion, "2.7") === "2.7") { @@ -158,9 +158,14 @@ export default class SuperTokens { if (includeRecipeIds !== undefined) { includeRecipeIdsStr = includeRecipeIds.join(","); } - let response = await querier.sendGetRequest(new NormalisedURLPath("/users/count"), { - includeRecipeIds: includeRecipeIdsStr, - }); + + let response = await querier.sendGetRequest( + new NormalisedURLPath(`${tenantId === undefined ? DEFAULT_TENANT_ID : tenantId}/users/count`), + { + includeRecipeIds: includeRecipeIdsStr, + includeAllTenants: tenantId === undefined, + } + ); return Number(response.count); }; @@ -170,6 +175,7 @@ export default class SuperTokens { paginationToken?: string; includeRecipeIds?: string[]; query?: object; + tenantId?: string; }): Promise<{ users: { recipeId: string; user: any }[]; nextPaginationToken?: string; @@ -185,7 +191,10 @@ export default class SuperTokens { if (input.includeRecipeIds !== undefined) { includeRecipeIdsStr = input.includeRecipeIds.join(","); } - let response = await querier.sendGetRequest(new NormalisedURLPath("/users"), { + if (input.tenantId === undefined) { + input.tenantId = DEFAULT_TENANT_ID; + } + let response = await querier.sendGetRequest(new NormalisedURLPath(`/${input.tenantId}/users`), { ...input.query, includeRecipeIds: includeRecipeIdsStr, timeJoinedOrder: input.timeJoinedOrder, @@ -195,7 +204,7 @@ export default class SuperTokens { const users: { recipeId: string; user: any }[] = response.users; return { - users: users.map(updateTenantId), + users, nextPaginationToken: response.nextPaginationToken, }; }; diff --git a/lib/ts/utils.ts b/lib/ts/utils.ts index 7605f1408..6f67fded7 100644 --- a/lib/ts/utils.ts +++ b/lib/ts/utils.ts @@ -155,19 +155,6 @@ export function setRequestInUserContextIfNotDefined(userContext: any | undefined return userContext; } -export function updateTenantId(user: { recipeId: string; user: any }): { recipeId: string; user: any } { - if (user.user.thirdParty !== undefined && user.user.thirdParty.userId.includes("|")) { - return { - ...user, - user: { - ...user.user, - tenantId: user.user.thirdParty.userId.split("|")[1], - }, - }; - } - return user; -} - export function getTopLevelDomainForSameSiteResolution(url: string): string { let urlObj = new URL(url); let hostname = urlObj.hostname;