UNPKG

supertokens-node

Version:
190 lines (189 loc) 9.49 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIInterface; const logger_1 = require("../../../logger"); const emailVerificationClaim_1 = require("../emailVerificationClaim"); const error_1 = __importDefault(require("../../session/error")); const utils_1 = require("../utils"); function getAPIInterface(stInstance) { return { verifyEmailPOST: async function ({ token, tenantId, session, options, userContext }) { const verifyTokenResponse = await options.recipeImplementation.verifyEmailUsingToken({ token, tenantId, attemptAccountLinking: true, userContext, }); if (verifyTokenResponse.status === "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR") { return verifyTokenResponse; } // status: "OK" let newSession = await stInstance .getRecipeInstanceOrThrow("emailverification") .updateSessionIfRequiredPostEmailVerification({ req: options.req, res: options.res, session, recipeUserIdWhoseEmailGotVerified: verifyTokenResponse.user.recipeUserId, userContext, }); return { status: "OK", user: verifyTokenResponse.user, newSession, }; }, isEmailVerifiedGET: async function ({ userContext, session, options }) { // In this API, we will check if the session's recipe user id's email is verified or not. const emailInfo = await stInstance .getRecipeInstanceOrThrow("emailverification") .getEmailForRecipeUserId(undefined, session.getRecipeUserId(userContext), userContext); if (emailInfo.status === "OK") { const isVerified = await options.recipeImplementation.isEmailVerified({ recipeUserId: session.getRecipeUserId(userContext), email: emailInfo.email, userContext, }); if (isVerified) { // here we do the same things we do for post email verification // cause email verification could happen in a different browser // whilst the first browser is polling this API - in this case, // we want to have the same effect to the session as if the // email was opened on the original browser itself. let newSession = await stInstance .getRecipeInstanceOrThrow("emailverification") .updateSessionIfRequiredPostEmailVerification({ req: options.req, res: options.res, session, recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), userContext, }); return { status: "OK", isVerified: true, newSession, }; } else { await session.setClaimValue(emailVerificationClaim_1.EmailVerificationClaim, false, userContext); return { status: "OK", isVerified: false, }; } } else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { // We consider people without email addresses as validated return { status: "OK", isVerified: true, }; } else { // this means that the user ID is not known to supertokens. This could // happen if the current session's user ID is not an auth user, // or if it belong to a recipe user ID that got deleted. Either way, // we logout the user. throw new error_1.default({ type: error_1.default.UNAUTHORISED, message: "Unknown User ID provided", }); } }, generateEmailVerifyTokenPOST: async function ({ options, userContext, session }) { // In this API, we generate the email verification token for session's recipe user ID. const tenantId = session.getTenantId(); const emailInfo = await stInstance .getRecipeInstanceOrThrow("emailverification") .getEmailForRecipeUserId(undefined, session.getRecipeUserId(userContext), userContext); if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { (0, logger_1.logDebugMessage)(`Email verification email not sent to user ${session .getRecipeUserId(userContext) .getAsString()} because it doesn't have an email address.`); // this can happen if the user ID was found, but it has no email. In this // case, we treat it as a success case. let newSession = await stInstance .getRecipeInstanceOrThrow("emailverification") .updateSessionIfRequiredPostEmailVerification({ req: options.req, res: options.res, session, recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), userContext, }); return { status: "EMAIL_ALREADY_VERIFIED_ERROR", newSession, }; } else if (emailInfo.status === "OK") { let response = await options.recipeImplementation.createEmailVerificationToken({ recipeUserId: session.getRecipeUserId(userContext), email: emailInfo.email, tenantId, userContext, }); // In case the email is already verified, we do the same thing // as what happens in the verifyEmailPOST API post email verification (cause maybe the session is outdated). if (response.status === "EMAIL_ALREADY_VERIFIED_ERROR") { (0, logger_1.logDebugMessage)(`Email verification email not sent to user ${session .getRecipeUserId(userContext) .getAsString()} because it is already verified.`); let newSession = await stInstance .getRecipeInstanceOrThrow("emailverification") .updateSessionIfRequiredPostEmailVerification({ req: options.req, res: options.res, session, recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), userContext, }); return { status: "EMAIL_ALREADY_VERIFIED_ERROR", newSession, }; } if ((await session.getClaimValue(emailVerificationClaim_1.EmailVerificationClaim)) !== false) { // this can happen if the email was unverified in another browser // and this session is still outdated - and the user has not // called the get email verification API yet. await session.fetchAndSetClaim(emailVerificationClaim_1.EmailVerificationClaim, userContext); } let emailVerifyLink = (0, utils_1.getEmailVerifyLink)({ appInfo: options.appInfo, token: response.token, tenantId, request: options.req, userContext, }); (0, logger_1.logDebugMessage)(`Sending email verification email to ${emailInfo}`); await options.emailDelivery.ingredientInterfaceImpl.sendEmail({ type: "EMAIL_VERIFICATION", user: { id: session.getUserId(), recipeUserId: session.getRecipeUserId(userContext), email: emailInfo.email, }, emailVerifyLink, tenantId, userContext, }); return { status: "OK", }; } else { // this means that the user ID is not known to supertokens. This could // happen if the current session's user ID is not an auth user, // or if it belong to a recipe user ID that got deleted. Either way, // we logout the user. (0, logger_1.logDebugMessage)("generateEmailVerifyTokenPOST: Returning UNAUTHORISED because the user id provided is unknown"); throw new error_1.default({ type: error_1.default.UNAUTHORISED, message: "Unknown User ID provided" }); } }, }; }