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.

index.js 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.AuthEmulator = exports.SingleProjectMode = void 0;
  4. const fs = require("fs");
  5. const path = require("path");
  6. const http = require("http");
  7. const utils = require("../../utils");
  8. const constants_1 = require("../constants");
  9. const emulatorLogger_1 = require("../emulatorLogger");
  10. const types_1 = require("../types");
  11. const server_1 = require("./server");
  12. const error_1 = require("../../error");
  13. const track_1 = require("../../track");
  14. var SingleProjectMode;
  15. (function (SingleProjectMode) {
  16. SingleProjectMode[SingleProjectMode["NO_WARNING"] = 0] = "NO_WARNING";
  17. SingleProjectMode[SingleProjectMode["WARNING"] = 1] = "WARNING";
  18. SingleProjectMode[SingleProjectMode["ERROR"] = 2] = "ERROR";
  19. })(SingleProjectMode = exports.SingleProjectMode || (exports.SingleProjectMode = {}));
  20. class AuthEmulator {
  21. constructor(args) {
  22. this.args = args;
  23. }
  24. async start() {
  25. const { host, port } = this.getInfo();
  26. const app = await (0, server_1.createApp)(this.args.projectId, this.args.singleProjectMode);
  27. const server = app.listen(port, host);
  28. this.destroyServer = utils.createDestroyer(server);
  29. }
  30. async connect() {
  31. }
  32. stop() {
  33. return this.destroyServer ? this.destroyServer() : Promise.resolve();
  34. }
  35. getInfo() {
  36. const host = this.args.host || constants_1.Constants.getDefaultHost();
  37. const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.AUTH);
  38. return {
  39. name: this.getName(),
  40. host,
  41. port,
  42. };
  43. }
  44. getName() {
  45. return types_1.Emulators.AUTH;
  46. }
  47. async importData(authExportDir, projectId, options) {
  48. void (0, track_1.trackEmulator)("emulator_import", {
  49. initiated_by: options.initiatedBy,
  50. emulator_name: types_1.Emulators.AUTH,
  51. });
  52. const logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.AUTH);
  53. const { host, port } = this.getInfo();
  54. const configPath = path.join(authExportDir, "config.json");
  55. const configStat = await stat(configPath);
  56. if (configStat === null || configStat === void 0 ? void 0 : configStat.isFile()) {
  57. logger.logLabeled("BULLET", "auth", `Importing config from ${configPath}`);
  58. await importFromFile({
  59. method: "PATCH",
  60. host: utils.connectableHostname(host),
  61. port,
  62. path: `/emulator/v1/projects/${projectId}/config`,
  63. headers: {
  64. Authorization: "Bearer owner",
  65. "Content-Type": "application/json",
  66. },
  67. }, configPath);
  68. }
  69. else {
  70. logger.logLabeled("WARN", "auth", `Skipped importing config because ${configPath} does not exist.`);
  71. }
  72. const accountsPath = path.join(authExportDir, "accounts.json");
  73. const accountsStat = await stat(accountsPath);
  74. if (accountsStat === null || accountsStat === void 0 ? void 0 : accountsStat.isFile()) {
  75. logger.logLabeled("BULLET", "auth", `Importing accounts from ${accountsPath}`);
  76. await importFromFile({
  77. method: "POST",
  78. host: utils.connectableHostname(host),
  79. port,
  80. path: `/identitytoolkit.googleapis.com/v1/projects/${projectId}/accounts:batchCreate`,
  81. headers: {
  82. Authorization: "Bearer owner",
  83. "Content-Type": "application/json",
  84. },
  85. }, accountsPath, { ignoreErrors: ["MISSING_USER_ACCOUNT"] });
  86. }
  87. else {
  88. logger.logLabeled("WARN", "auth", `Skipped importing accounts because ${accountsPath} does not exist.`);
  89. }
  90. }
  91. }
  92. exports.AuthEmulator = AuthEmulator;
  93. function stat(path) {
  94. return new Promise((resolve, reject) => fs.stat(path, (err, stats) => {
  95. if (err) {
  96. if (err.code === "ENOENT") {
  97. return resolve(undefined);
  98. }
  99. return reject(err);
  100. }
  101. else {
  102. return resolve(stats);
  103. }
  104. }));
  105. }
  106. function importFromFile(reqOptions, path, options = {}) {
  107. const readStream = fs.createReadStream(path);
  108. return new Promise((resolve, reject) => {
  109. const req = http.request(reqOptions, (response) => {
  110. if (response.statusCode === 200) {
  111. resolve();
  112. }
  113. else {
  114. let data = "";
  115. response
  116. .on("data", (d) => {
  117. data += d.toString();
  118. })
  119. .on("error", reject)
  120. .on("end", () => {
  121. const ignoreErrors = options === null || options === void 0 ? void 0 : options.ignoreErrors;
  122. if (ignoreErrors === null || ignoreErrors === void 0 ? void 0 : ignoreErrors.length) {
  123. let message;
  124. try {
  125. message = JSON.parse(data).error.message;
  126. }
  127. catch (_a) {
  128. message = undefined;
  129. }
  130. if (message && ignoreErrors.includes(message)) {
  131. return resolve();
  132. }
  133. }
  134. return reject(new error_1.FirebaseError(`Received HTTP status code: ${response.statusCode}\n${data}`));
  135. });
  136. }
  137. });
  138. req.on("error", reject);
  139. readStream.pipe(req, { end: true });
  140. }).catch((e) => {
  141. throw new error_1.FirebaseError(`Error during Auth Emulator import: ${e.message}`, {
  142. original: e,
  143. exit: 1,
  144. });
  145. });
  146. }