No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

state.js 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.decodeRefreshToken = exports.encodeRefreshToken = exports.BlockingFunctionEvents = exports.TenantProjectState = exports.AgentProjectState = exports.ProjectState = exports.SIGNIN_METHOD_EMAIL_LINK = exports.PROVIDER_GAME_CENTER = exports.PROVIDER_CUSTOM = exports.PROVIDER_ANONYMOUS = exports.PROVIDER_PHONE = exports.PROVIDER_PASSWORD = void 0;
  4. const utils_1 = require("./utils");
  5. const cloudFunctions_1 = require("./cloudFunctions");
  6. const errors_1 = require("./errors");
  7. exports.PROVIDER_PASSWORD = "password";
  8. exports.PROVIDER_PHONE = "phone";
  9. exports.PROVIDER_ANONYMOUS = "anonymous";
  10. exports.PROVIDER_CUSTOM = "custom";
  11. exports.PROVIDER_GAME_CENTER = "gc.apple.com";
  12. exports.SIGNIN_METHOD_EMAIL_LINK = "emailLink";
  13. class ProjectState {
  14. constructor(projectId) {
  15. this.projectId = projectId;
  16. this.users = new Map();
  17. this.localIdForEmail = new Map();
  18. this.localIdForInitialEmail = new Map();
  19. this.localIdForPhoneNumber = new Map();
  20. this.localIdsForProviderEmail = new Map();
  21. this.userIdForProviderRawId = new Map();
  22. this.oobs = new Map();
  23. this.verificationCodes = new Map();
  24. this.temporaryProofs = new Map();
  25. this.pendingLocalIds = new Set();
  26. }
  27. get projectNumber() {
  28. return "12345";
  29. }
  30. generateLocalId() {
  31. for (let i = 0; i < 10; i++) {
  32. const localId = (0, utils_1.randomId)(28);
  33. if (!this.users.has(localId) && !this.pendingLocalIds.has(localId)) {
  34. this.pendingLocalIds.add(localId);
  35. return localId;
  36. }
  37. }
  38. throw new Error("Cannot generate a random unique localId after 10 tries.");
  39. }
  40. createUserWithLocalId(localId, props) {
  41. if (this.users.has(localId)) {
  42. return undefined;
  43. }
  44. this.users.set(localId, {
  45. localId,
  46. });
  47. this.pendingLocalIds.delete(localId);
  48. const user = this.updateUserByLocalId(localId, props, {
  49. upsertProviders: props.providerUserInfo,
  50. });
  51. this.authCloudFunction.dispatch("create", user);
  52. return user;
  53. }
  54. overwriteUserWithLocalId(localId, props) {
  55. const userInfoBefore = this.users.get(localId);
  56. if (userInfoBefore) {
  57. this.removeUserFromIndex(userInfoBefore);
  58. }
  59. const timestamp = new Date();
  60. this.users.set(localId, {
  61. localId,
  62. createdAt: props.createdAt || timestamp.getTime().toString(),
  63. lastLoginAt: timestamp.getTime().toString(),
  64. });
  65. const user = this.updateUserByLocalId(localId, props, {
  66. upsertProviders: props.providerUserInfo,
  67. });
  68. return user;
  69. }
  70. deleteUser(user) {
  71. this.users.delete(user.localId);
  72. this.removeUserFromIndex(user);
  73. this.authCloudFunction.dispatch("delete", user);
  74. }
  75. updateUserByLocalId(localId, fields, options = {}) {
  76. var _a, _b;
  77. const upsertProviders = (_a = options.upsertProviders) !== null && _a !== void 0 ? _a : [];
  78. const deleteProviders = (_b = options.deleteProviders) !== null && _b !== void 0 ? _b : [];
  79. const user = this.users.get(localId);
  80. if (!user) {
  81. throw new Error(`Internal assertion error: trying to update nonexistent user: ${localId}`);
  82. }
  83. const oldEmail = user.email;
  84. const oldPhoneNumber = user.phoneNumber;
  85. for (const field of Object.keys(fields)) {
  86. (0, utils_1.mirrorFieldTo)(user, field, fields);
  87. }
  88. if (oldEmail && oldEmail !== user.email) {
  89. this.localIdForEmail.delete(oldEmail);
  90. }
  91. if (user.email) {
  92. this.localIdForEmail.set(user.email, user.localId);
  93. }
  94. if (user.email && (user.passwordHash || user.emailLinkSignin)) {
  95. upsertProviders.push({
  96. providerId: exports.PROVIDER_PASSWORD,
  97. email: user.email,
  98. federatedId: user.email,
  99. rawId: user.email,
  100. displayName: user.displayName,
  101. photoUrl: user.photoUrl,
  102. });
  103. }
  104. else {
  105. deleteProviders.push(exports.PROVIDER_PASSWORD);
  106. }
  107. if (user.initialEmail) {
  108. this.localIdForInitialEmail.set(user.initialEmail, user.localId);
  109. }
  110. if (oldPhoneNumber && oldPhoneNumber !== user.phoneNumber) {
  111. this.localIdForPhoneNumber.delete(oldPhoneNumber);
  112. }
  113. if (user.phoneNumber) {
  114. this.localIdForPhoneNumber.set(user.phoneNumber, user.localId);
  115. upsertProviders.push({
  116. providerId: exports.PROVIDER_PHONE,
  117. phoneNumber: user.phoneNumber,
  118. rawId: user.phoneNumber,
  119. });
  120. }
  121. else {
  122. deleteProviders.push(exports.PROVIDER_PHONE);
  123. }
  124. if (user.mfaInfo) {
  125. this.validateMfaEnrollments(user.mfaInfo);
  126. }
  127. return this.updateUserProviderInfo(user, upsertProviders, deleteProviders);
  128. }
  129. validateMfaEnrollments(enrollments) {
  130. const phoneNumbers = new Set();
  131. const enrollmentIds = new Set();
  132. for (const enrollment of enrollments) {
  133. (0, errors_1.assert)(enrollment.phoneInfo && (0, utils_1.isValidPhoneNumber)(enrollment.phoneInfo), "INVALID_MFA_PHONE_NUMBER : Invalid format.");
  134. (0, errors_1.assert)(enrollment.mfaEnrollmentId, "INVALID_MFA_ENROLLMENT_ID : mfaEnrollmentId must be defined.");
  135. (0, errors_1.assert)(!enrollmentIds.has(enrollment.mfaEnrollmentId), "DUPLICATE_MFA_ENROLLMENT_ID");
  136. (0, errors_1.assert)(!phoneNumbers.has(enrollment.phoneInfo), "INTERNAL_ERROR : MFA Enrollment Phone Numbers must be unique.");
  137. phoneNumbers.add(enrollment.phoneInfo);
  138. enrollmentIds.add(enrollment.mfaEnrollmentId);
  139. }
  140. return enrollments;
  141. }
  142. updateUserProviderInfo(user, upsertProviders, deleteProviders) {
  143. var _a, _b;
  144. const oldProviderEmails = getProviderEmailsForUser(user);
  145. if (user.providerUserInfo) {
  146. const updatedProviderUserInfo = [];
  147. for (const info of user.providerUserInfo) {
  148. if (deleteProviders.includes(info.providerId)) {
  149. (_a = this.userIdForProviderRawId.get(info.providerId)) === null || _a === void 0 ? void 0 : _a.delete(info.rawId);
  150. }
  151. else {
  152. updatedProviderUserInfo.push(info);
  153. }
  154. }
  155. user.providerUserInfo = updatedProviderUserInfo;
  156. }
  157. if (upsertProviders.length) {
  158. user.providerUserInfo = (_b = user.providerUserInfo) !== null && _b !== void 0 ? _b : [];
  159. for (const upsert of upsertProviders) {
  160. const providerId = upsert.providerId;
  161. let users = this.userIdForProviderRawId.get(providerId);
  162. if (!users) {
  163. users = new Map();
  164. this.userIdForProviderRawId.set(providerId, users);
  165. }
  166. users.set(upsert.rawId, user.localId);
  167. const index = user.providerUserInfo.findIndex((info) => info.providerId === upsert.providerId);
  168. if (index < 0) {
  169. user.providerUserInfo.push(upsert);
  170. }
  171. else {
  172. user.providerUserInfo[index] = upsert;
  173. }
  174. }
  175. }
  176. for (const email of getProviderEmailsForUser(user)) {
  177. oldProviderEmails.delete(email);
  178. let localIds = this.localIdsForProviderEmail.get(email);
  179. if (!localIds) {
  180. localIds = new Set();
  181. this.localIdsForProviderEmail.set(email, localIds);
  182. }
  183. localIds.add(user.localId);
  184. }
  185. for (const oldEmail of oldProviderEmails) {
  186. this.removeProviderEmailForUser(oldEmail, user.localId);
  187. }
  188. return user;
  189. }
  190. getUserByEmail(email) {
  191. const localId = this.localIdForEmail.get(email);
  192. if (!localId) {
  193. return undefined;
  194. }
  195. return this.getUserByLocalIdAssertingExists(localId);
  196. }
  197. getUserByInitialEmail(initialEmail) {
  198. const localId = this.localIdForInitialEmail.get(initialEmail);
  199. if (!localId) {
  200. return undefined;
  201. }
  202. return this.getUserByLocalIdAssertingExists(localId);
  203. }
  204. getUserByLocalIdAssertingExists(localId) {
  205. const userInfo = this.getUserByLocalId(localId);
  206. if (!userInfo) {
  207. throw new Error(`Internal state invariant broken: no user with ID: ${localId}`);
  208. }
  209. return userInfo;
  210. }
  211. getUsersByEmailOrProviderEmail(email) {
  212. var _a;
  213. const users = [];
  214. const seenLocalIds = new Set();
  215. const localId = this.localIdForEmail.get(email);
  216. if (localId) {
  217. users.push(this.getUserByLocalIdAssertingExists(localId));
  218. seenLocalIds.add(localId);
  219. }
  220. for (const localId of (_a = this.localIdsForProviderEmail.get(email)) !== null && _a !== void 0 ? _a : []) {
  221. if (!seenLocalIds.has(localId)) {
  222. users.push(this.getUserByLocalIdAssertingExists(localId));
  223. seenLocalIds.add(localId);
  224. }
  225. }
  226. return users;
  227. }
  228. getUserByPhoneNumber(phoneNumber) {
  229. const localId = this.localIdForPhoneNumber.get(phoneNumber);
  230. if (!localId) {
  231. return undefined;
  232. }
  233. return this.getUserByLocalIdAssertingExists(localId);
  234. }
  235. removeProviderEmailForUser(email, localId) {
  236. const localIds = this.localIdsForProviderEmail.get(email);
  237. if (!localIds) {
  238. return;
  239. }
  240. localIds.delete(localId);
  241. if (localIds.size === 0) {
  242. this.localIdsForProviderEmail.delete(email);
  243. }
  244. }
  245. getUserByProviderRawId(provider, rawId) {
  246. var _a;
  247. const localId = (_a = this.userIdForProviderRawId.get(provider)) === null || _a === void 0 ? void 0 : _a.get(rawId);
  248. if (!localId) {
  249. return undefined;
  250. }
  251. return this.getUserByLocalIdAssertingExists(localId);
  252. }
  253. listProviderInfosByProviderId(provider) {
  254. var _a;
  255. const users = this.userIdForProviderRawId.get(provider);
  256. if (!users) {
  257. return [];
  258. }
  259. const infos = [];
  260. for (const localId of users.values()) {
  261. const user = this.getUserByLocalIdAssertingExists(localId);
  262. const info = (_a = user.providerUserInfo) === null || _a === void 0 ? void 0 : _a.find((info) => info.providerId === provider);
  263. if (!info) {
  264. throw new Error(`Internal assertion error: User ${localId} does not have providerInfo ${provider}.`);
  265. }
  266. infos.push(info);
  267. }
  268. return infos;
  269. }
  270. getUserByLocalId(localId) {
  271. return this.users.get(localId);
  272. }
  273. createRefreshTokenFor(userInfo, provider, { extraClaims = {}, secondFactor, } = {}) {
  274. const localId = userInfo.localId;
  275. const refreshTokenRecord = {
  276. _AuthEmulatorRefreshToken: "DO NOT MODIFY",
  277. localId,
  278. provider,
  279. extraClaims,
  280. projectId: this.projectId,
  281. secondFactor,
  282. tenantId: userInfo.tenantId,
  283. };
  284. const refreshToken = encodeRefreshToken(refreshTokenRecord);
  285. return refreshToken;
  286. }
  287. validateRefreshToken(refreshToken) {
  288. const record = decodeRefreshToken(refreshToken);
  289. (0, errors_1.assert)(record.projectId === this.projectId, "INVALID_REFRESH_TOKEN");
  290. if (this instanceof TenantProjectState) {
  291. (0, errors_1.assert)(record.tenantId === this.tenantId, "TENANT_ID_MISMATCH");
  292. }
  293. const user = this.getUserByLocalId(record.localId);
  294. (0, errors_1.assert)(user, "INVALID_REFRESH_TOKEN");
  295. return {
  296. user,
  297. provider: record.provider,
  298. extraClaims: record.extraClaims,
  299. secondFactor: record.secondFactor,
  300. };
  301. }
  302. createOob(email, requestType, generateLink) {
  303. const oobCode = (0, utils_1.randomBase64UrlStr)(54);
  304. const oobLink = generateLink(oobCode);
  305. const oob = {
  306. email,
  307. requestType,
  308. oobCode,
  309. oobLink,
  310. };
  311. this.oobs.set(oobCode, oob);
  312. return oob;
  313. }
  314. validateOobCode(oobCode) {
  315. return this.oobs.get(oobCode);
  316. }
  317. deleteOobCode(oobCode) {
  318. return this.oobs.delete(oobCode);
  319. }
  320. listOobCodes() {
  321. return this.oobs.values();
  322. }
  323. createVerificationCode(phoneNumber) {
  324. const sessionInfo = (0, utils_1.randomBase64UrlStr)(226);
  325. const verification = {
  326. code: (0, utils_1.randomDigits)(6),
  327. phoneNumber,
  328. sessionInfo,
  329. };
  330. this.verificationCodes.set(sessionInfo, verification);
  331. return verification;
  332. }
  333. getVerificationCodeBySessionInfo(sessionInfo) {
  334. return this.verificationCodes.get(sessionInfo);
  335. }
  336. deleteVerificationCodeBySessionInfo(sessionInfo) {
  337. return this.verificationCodes.delete(sessionInfo);
  338. }
  339. listVerificationCodes() {
  340. return this.verificationCodes.values();
  341. }
  342. deleteAllAccounts() {
  343. this.users.clear();
  344. this.localIdForEmail.clear();
  345. this.localIdForPhoneNumber.clear();
  346. this.localIdsForProviderEmail.clear();
  347. this.userIdForProviderRawId.clear();
  348. }
  349. getUserCount() {
  350. return this.users.size;
  351. }
  352. queryUsers(filter, options) {
  353. const users = [];
  354. for (const user of this.users.values()) {
  355. if (!options.startToken || user.localId > options.startToken) {
  356. filter;
  357. users.push(user);
  358. }
  359. }
  360. users.sort((a, b) => {
  361. if (options.sortByField === "localId") {
  362. if (a.localId < b.localId) {
  363. return -1;
  364. }
  365. else if (a.localId > b.localId) {
  366. return 1;
  367. }
  368. }
  369. return 0;
  370. });
  371. return options.order === "DESC" ? users.reverse() : users;
  372. }
  373. createTemporaryProof(phoneNumber) {
  374. const record = {
  375. phoneNumber,
  376. temporaryProof: (0, utils_1.randomBase64UrlStr)(119),
  377. temporaryProofExpiresIn: "3600",
  378. };
  379. this.temporaryProofs.set(record.temporaryProof, record);
  380. return record;
  381. }
  382. validateTemporaryProof(temporaryProof, phoneNumber) {
  383. const record = this.temporaryProofs.get(temporaryProof);
  384. if (!record || record.phoneNumber !== phoneNumber) {
  385. return undefined;
  386. }
  387. return record;
  388. }
  389. removeUserFromIndex(user) {
  390. var _a, _b;
  391. if (user.email) {
  392. this.localIdForEmail.delete(user.email);
  393. }
  394. if (user.initialEmail) {
  395. this.localIdForInitialEmail.delete(user.initialEmail);
  396. }
  397. if (user.phoneNumber) {
  398. this.localIdForPhoneNumber.delete(user.phoneNumber);
  399. }
  400. for (const info of (_a = user.providerUserInfo) !== null && _a !== void 0 ? _a : []) {
  401. (_b = this.userIdForProviderRawId.get(info.providerId)) === null || _b === void 0 ? void 0 : _b.delete(info.rawId);
  402. if (info.email) {
  403. this.removeProviderEmailForUser(info.email, user.localId);
  404. }
  405. }
  406. }
  407. }
  408. exports.ProjectState = ProjectState;
  409. class AgentProjectState extends ProjectState {
  410. constructor(projectId) {
  411. super(projectId);
  412. this.tenantProjectForTenantId = new Map();
  413. this._authCloudFunction = new cloudFunctions_1.AuthCloudFunction(this.projectId);
  414. this._config = {
  415. signIn: { allowDuplicateEmails: false },
  416. blockingFunctions: {},
  417. };
  418. }
  419. get authCloudFunction() {
  420. return this._authCloudFunction;
  421. }
  422. get oneAccountPerEmail() {
  423. return !this._config.signIn.allowDuplicateEmails;
  424. }
  425. set oneAccountPerEmail(oneAccountPerEmail) {
  426. this._config.signIn.allowDuplicateEmails = !oneAccountPerEmail;
  427. }
  428. get allowPasswordSignup() {
  429. return true;
  430. }
  431. get disableAuth() {
  432. return false;
  433. }
  434. get mfaConfig() {
  435. return { state: "ENABLED", enabledProviders: ["PHONE_SMS"] };
  436. }
  437. get enableAnonymousUser() {
  438. return true;
  439. }
  440. get enableEmailLinkSignin() {
  441. return true;
  442. }
  443. get config() {
  444. return this._config;
  445. }
  446. get blockingFunctionsConfig() {
  447. return this._config.blockingFunctions;
  448. }
  449. set blockingFunctionsConfig(blockingFunctions) {
  450. this._config.blockingFunctions = blockingFunctions;
  451. }
  452. shouldForwardCredentialToBlockingFunction(type) {
  453. var _a, _b, _c, _d, _e, _f;
  454. switch (type) {
  455. case "accessToken":
  456. return (_b = (_a = this._config.blockingFunctions.forwardInboundCredentials) === null || _a === void 0 ? void 0 : _a.accessToken) !== null && _b !== void 0 ? _b : false;
  457. case "idToken":
  458. return (_d = (_c = this._config.blockingFunctions.forwardInboundCredentials) === null || _c === void 0 ? void 0 : _c.idToken) !== null && _d !== void 0 ? _d : false;
  459. case "refreshToken":
  460. return (_f = (_e = this._config.blockingFunctions.forwardInboundCredentials) === null || _e === void 0 ? void 0 : _e.refreshToken) !== null && _f !== void 0 ? _f : false;
  461. }
  462. }
  463. getBlockingFunctionUri(event) {
  464. const triggers = this.blockingFunctionsConfig.triggers;
  465. if (triggers) {
  466. return Object.prototype.hasOwnProperty.call(triggers, event)
  467. ? triggers[event].functionUri
  468. : undefined;
  469. }
  470. return undefined;
  471. }
  472. updateConfig(update, updateMask) {
  473. var _a, _b, _c;
  474. if (!updateMask) {
  475. this.oneAccountPerEmail = (_b = !((_a = update.signIn) === null || _a === void 0 ? void 0 : _a.allowDuplicateEmails)) !== null && _b !== void 0 ? _b : true;
  476. this.blockingFunctionsConfig = (_c = update.blockingFunctions) !== null && _c !== void 0 ? _c : {};
  477. return this.config;
  478. }
  479. return applyMask(updateMask, this.config, update);
  480. }
  481. getTenantProject(tenantId) {
  482. if (!this.tenantProjectForTenantId.has(tenantId)) {
  483. this.createTenantWithTenantId(tenantId, {
  484. tenantId,
  485. allowPasswordSignup: true,
  486. disableAuth: false,
  487. mfaConfig: {
  488. state: "ENABLED",
  489. enabledProviders: ["PHONE_SMS"],
  490. },
  491. enableAnonymousUser: true,
  492. enableEmailLinkSignin: true,
  493. });
  494. }
  495. return this.tenantProjectForTenantId.get(tenantId);
  496. }
  497. listTenants(startToken) {
  498. const tenantProjects = [];
  499. for (const tenantProject of this.tenantProjectForTenantId.values()) {
  500. if (!startToken || tenantProject.tenantId > startToken) {
  501. tenantProjects.push(tenantProject);
  502. }
  503. }
  504. tenantProjects.sort((a, b) => {
  505. if (a.tenantId < b.tenantId) {
  506. return -1;
  507. }
  508. else if (a.tenantId > b.tenantId) {
  509. return 1;
  510. }
  511. return 0;
  512. });
  513. return tenantProjects.map((tenantProject) => tenantProject.tenantConfig);
  514. }
  515. createTenant(tenant) {
  516. for (let i = 0; i < 10; i++) {
  517. const tenantId = (0, utils_1.randomId)(28);
  518. const createdTenant = this.createTenantWithTenantId(tenantId, tenant);
  519. if (createdTenant) {
  520. return createdTenant;
  521. }
  522. }
  523. throw new Error("Could not generate a random unique tenantId after 10 tries");
  524. }
  525. createTenantWithTenantId(tenantId, tenant) {
  526. if (this.tenantProjectForTenantId.has(tenantId)) {
  527. return undefined;
  528. }
  529. tenant.name = `projects/${this.projectId}/tenants/${tenantId}`;
  530. tenant.tenantId = tenantId;
  531. this.tenantProjectForTenantId.set(tenantId, new TenantProjectState(this.projectId, tenantId, tenant, this));
  532. return tenant;
  533. }
  534. deleteTenant(tenantId) {
  535. this.tenantProjectForTenantId.delete(tenantId);
  536. }
  537. }
  538. exports.AgentProjectState = AgentProjectState;
  539. class TenantProjectState extends ProjectState {
  540. constructor(projectId, tenantId, _tenantConfig, parentProject) {
  541. super(projectId);
  542. this.tenantId = tenantId;
  543. this._tenantConfig = _tenantConfig;
  544. this.parentProject = parentProject;
  545. }
  546. get oneAccountPerEmail() {
  547. return this.parentProject.oneAccountPerEmail;
  548. }
  549. get authCloudFunction() {
  550. return this.parentProject.authCloudFunction;
  551. }
  552. get tenantConfig() {
  553. return this._tenantConfig;
  554. }
  555. get allowPasswordSignup() {
  556. return this._tenantConfig.allowPasswordSignup;
  557. }
  558. get disableAuth() {
  559. return this._tenantConfig.disableAuth;
  560. }
  561. get mfaConfig() {
  562. return this._tenantConfig.mfaConfig;
  563. }
  564. get enableAnonymousUser() {
  565. return this._tenantConfig.enableAnonymousUser;
  566. }
  567. get enableEmailLinkSignin() {
  568. return this._tenantConfig.enableEmailLinkSignin;
  569. }
  570. shouldForwardCredentialToBlockingFunction(type) {
  571. return this.parentProject.shouldForwardCredentialToBlockingFunction(type);
  572. }
  573. getBlockingFunctionUri(event) {
  574. return this.parentProject.getBlockingFunctionUri(event);
  575. }
  576. delete() {
  577. this.parentProject.deleteTenant(this.tenantId);
  578. }
  579. updateTenant(update, updateMask) {
  580. var _a, _b, _c, _d, _e;
  581. if (!updateMask) {
  582. const mfaConfig = (_a = update.mfaConfig) !== null && _a !== void 0 ? _a : {};
  583. if (!("state" in mfaConfig)) {
  584. mfaConfig.state = "DISABLED";
  585. }
  586. if (!("enabledProviders" in mfaConfig)) {
  587. mfaConfig.enabledProviders = [];
  588. }
  589. this._tenantConfig = {
  590. tenantId: this.tenantId,
  591. name: this.tenantConfig.name,
  592. allowPasswordSignup: (_b = update.allowPasswordSignup) !== null && _b !== void 0 ? _b : false,
  593. disableAuth: (_c = update.disableAuth) !== null && _c !== void 0 ? _c : false,
  594. mfaConfig: mfaConfig,
  595. enableAnonymousUser: (_d = update.enableAnonymousUser) !== null && _d !== void 0 ? _d : false,
  596. enableEmailLinkSignin: (_e = update.enableEmailLinkSignin) !== null && _e !== void 0 ? _e : false,
  597. displayName: update.displayName,
  598. };
  599. return this.tenantConfig;
  600. }
  601. return applyMask(updateMask, this.tenantConfig, update);
  602. }
  603. }
  604. exports.TenantProjectState = TenantProjectState;
  605. var BlockingFunctionEvents;
  606. (function (BlockingFunctionEvents) {
  607. BlockingFunctionEvents["BEFORE_CREATE"] = "beforeCreate";
  608. BlockingFunctionEvents["BEFORE_SIGN_IN"] = "beforeSignIn";
  609. })(BlockingFunctionEvents = exports.BlockingFunctionEvents || (exports.BlockingFunctionEvents = {}));
  610. function encodeRefreshToken(refreshTokenRecord) {
  611. return Buffer.from(JSON.stringify(refreshTokenRecord), "utf8").toString("base64");
  612. }
  613. exports.encodeRefreshToken = encodeRefreshToken;
  614. function decodeRefreshToken(refreshTokenString) {
  615. let refreshTokenRecord;
  616. try {
  617. const json = Buffer.from(refreshTokenString, "base64").toString("utf8");
  618. refreshTokenRecord = JSON.parse(json);
  619. }
  620. catch (_a) {
  621. throw new errors_1.BadRequestError("INVALID_REFRESH_TOKEN");
  622. }
  623. (0, errors_1.assert)(refreshTokenRecord._AuthEmulatorRefreshToken, "INVALID_REFRESH_TOKEN");
  624. return refreshTokenRecord;
  625. }
  626. exports.decodeRefreshToken = decodeRefreshToken;
  627. function getProviderEmailsForUser(user) {
  628. var _a;
  629. const emails = new Set();
  630. (_a = user.providerUserInfo) === null || _a === void 0 ? void 0 : _a.forEach(({ email }) => {
  631. if (email) {
  632. emails.add(email);
  633. }
  634. });
  635. return emails;
  636. }
  637. function applyMask(updateMask, dest, update) {
  638. const paths = updateMask.split(",");
  639. for (const path of paths) {
  640. const fields = path.split(".");
  641. let updateField = update;
  642. let existingField = dest;
  643. let field;
  644. for (let i = 0; i < fields.length - 1; i++) {
  645. field = fields[i];
  646. if (updateField[field] == null) {
  647. console.warn(`Unable to find field '${field}' in update '${updateField}`);
  648. break;
  649. }
  650. if (Array.isArray(updateField[field]) || Object(updateField[field]) !== updateField[field]) {
  651. console.warn(`Field '${field}' is singular and cannot have sub-fields`);
  652. break;
  653. }
  654. if (!existingField[field]) {
  655. existingField[field] = {};
  656. }
  657. updateField = updateField[field];
  658. existingField = existingField[field];
  659. }
  660. field = fields[fields.length - 1];
  661. if (updateField[field] == null) {
  662. console.warn(`Unable to find field '${field}' in update '${JSON.stringify(updateField)}`);
  663. continue;
  664. }
  665. existingField[field] = updateField[field];
  666. }
  667. return dest;
  668. }