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.

database.js 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.doSetup = void 0;
  4. const clc = require("colorette");
  5. const prompt_1 = require("../../prompt");
  6. const logger_1 = require("../../logger");
  7. const utils = require("../../utils");
  8. const fsutils = require("../../fsutils");
  9. const database_1 = require("../../management/database");
  10. const ora = require("ora");
  11. const ensureApiEnabled_1 = require("../../ensureApiEnabled");
  12. const getDefaultDatabaseInstance_1 = require("../../getDefaultDatabaseInstance");
  13. const error_1 = require("../../error");
  14. const apiv2_1 = require("../../apiv2");
  15. const DEFAULT_RULES = JSON.stringify({ rules: { ".read": "auth != null", ".write": "auth != null" } }, null, 2);
  16. async function getDBRules(instanceDetails) {
  17. if (!instanceDetails || !instanceDetails.name) {
  18. return DEFAULT_RULES;
  19. }
  20. const client = new apiv2_1.Client({ urlPrefix: instanceDetails.databaseUrl });
  21. const response = await client.request({
  22. method: "GET",
  23. path: "/.settings/rules.json",
  24. responseType: "stream",
  25. resolveOnHTTPError: true,
  26. });
  27. if (response.status !== 200) {
  28. throw new error_1.FirebaseError(`Failed to fetch current rules. Code: ${response.status}`);
  29. }
  30. return await response.response.text();
  31. }
  32. function writeDBRules(rules, logMessagePrefix, filename, config) {
  33. config.writeProjectFile(filename, rules);
  34. utils.logSuccess(`${logMessagePrefix} have been written to ${clc.bold(filename)}.`);
  35. logger_1.logger.info(`Future modifications to ${clc.bold(filename)} will update Realtime Database Security Rules when you run`);
  36. logger_1.logger.info(clc.bold("firebase deploy") + ".");
  37. }
  38. async function createDefaultDatabaseInstance(project) {
  39. const selectedLocation = await (0, prompt_1.promptOnce)({
  40. type: "list",
  41. message: "Please choose the location for your default Realtime Database instance:",
  42. choices: [
  43. { name: "us-central1", value: database_1.DatabaseLocation.US_CENTRAL1 },
  44. { name: "europe-west1", value: database_1.DatabaseLocation.EUROPE_WEST1 },
  45. { name: "asia-southeast1", value: database_1.DatabaseLocation.ASIA_SOUTHEAST1 },
  46. ],
  47. });
  48. let instanceName = `${project}-default-rtdb`;
  49. const checkOutput = await (0, database_1.checkInstanceNameAvailable)(project, instanceName, database_1.DatabaseInstanceType.DEFAULT_DATABASE, selectedLocation);
  50. if (!checkOutput.available) {
  51. if (!checkOutput.suggestedIds || checkOutput.suggestedIds.length === 0) {
  52. logger_1.logger.debug(`No instance names were suggested instead of conventional instance name: ${instanceName}`);
  53. throw new error_1.FirebaseError("Failed to create default RTDB instance");
  54. }
  55. instanceName = checkOutput.suggestedIds[0];
  56. logger_1.logger.info(`${clc.yellow("WARNING:")} your project ID has the legacy name format, so your default Realtime Database instance will be named differently: ${instanceName}`);
  57. }
  58. const spinner = ora(`Creating your default Realtime Database instance: ${instanceName}`).start();
  59. try {
  60. const createdInstance = await (0, database_1.createInstance)(project, instanceName, selectedLocation, database_1.DatabaseInstanceType.DEFAULT_DATABASE);
  61. spinner.succeed();
  62. return createdInstance;
  63. }
  64. catch (err) {
  65. spinner.fail();
  66. throw err;
  67. }
  68. }
  69. async function doSetup(setup, config) {
  70. setup.config = setup.config || {};
  71. let instanceDetails;
  72. if (setup.projectId) {
  73. await (0, ensureApiEnabled_1.ensure)(setup.projectId, "firebasedatabase.googleapis.com", "database", false);
  74. logger_1.logger.info();
  75. setup.instance =
  76. setup.instance || (await (0, getDefaultDatabaseInstance_1.getDefaultDatabaseInstance)({ project: setup.projectId }));
  77. if (setup.instance !== "") {
  78. instanceDetails = await (0, database_1.getDatabaseInstanceDetails)(setup.projectId, setup.instance);
  79. }
  80. else {
  81. const confirm = await (0, prompt_1.promptOnce)({
  82. type: "confirm",
  83. name: "confirm",
  84. default: true,
  85. message: "It seems like you haven’t initialized Realtime Database in your project yet. Do you want to set it up?",
  86. });
  87. if (confirm) {
  88. instanceDetails = await createDefaultDatabaseInstance(setup.projectId);
  89. }
  90. }
  91. }
  92. setup.config.database = setup.config.database || {};
  93. logger_1.logger.info();
  94. logger_1.logger.info("Firebase Realtime Database Security Rules allow you to define how your data should be");
  95. logger_1.logger.info("structured and when your data can be read from and written to.");
  96. logger_1.logger.info();
  97. await (0, prompt_1.prompt)(setup.config.database, [
  98. {
  99. type: "input",
  100. name: "rules",
  101. message: "What file should be used for Realtime Database Security Rules?",
  102. default: "database.rules.json",
  103. },
  104. ]);
  105. const filename = setup.config.database.rules;
  106. if (!filename) {
  107. throw new error_1.FirebaseError("Must specify location for Realtime Database rules file.");
  108. }
  109. let writeRules = true;
  110. if (fsutils.fileExistsSync(filename)) {
  111. const rulesDescription = instanceDetails
  112. ? `the Realtime Database Security Rules for ${clc.bold(instanceDetails.name)} from the Firebase console`
  113. : "default rules";
  114. const msg = `File ${clc.bold(filename)} already exists. Do you want to overwrite it with ${rulesDescription}?`;
  115. writeRules = await (0, prompt_1.promptOnce)({
  116. type: "confirm",
  117. message: msg,
  118. default: false,
  119. });
  120. }
  121. if (writeRules) {
  122. if (instanceDetails) {
  123. writeDBRules(await getDBRules(instanceDetails), `Database Rules for ${instanceDetails.name}`, filename, config);
  124. return;
  125. }
  126. writeDBRules(DEFAULT_RULES, "Default rules", filename, config);
  127. return;
  128. }
  129. logger_1.logger.info("Skipping overwrite of Realtime Database Security Rules.");
  130. logger_1.logger.info(`The security rules defined in ${clc.bold(filename)} will be published when you run ${clc.bold("firebase deploy")}.`);
  131. return;
  132. }
  133. exports.doSetup = doSetup;