firebase-tools 10.4.2 → 10.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bin/firebase.js +1 -1
- package/lib/commands/emulators-start.js +6 -1
- package/lib/commands/ext-dev-emulators-start.js +5 -1
- package/lib/emulator/auth/operations.js +21 -20
- package/lib/emulator/auth/state.js +79 -43
- package/lib/emulator/commandUtils.js +72 -2
- package/lib/emulator/controller.js +9 -0
- package/lib/emulator/downloadableEmulators.js +13 -6
- package/lib/emulator/shared/request.js +19 -0
- package/lib/emulator/storage/apis/firebase.js +20 -28
- package/lib/emulator/storage/apis/gcloud.js +69 -57
- package/lib/emulator/storage/files.js +42 -49
- package/lib/emulator/storage/index.js +14 -2
- package/lib/emulator/storage/rules/utils.js +11 -3
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/lib/emulator/storage/list.js +0 -18
package/lib/bin/firebase.js
CHANGED
|
@@ -20,7 +20,7 @@ marked.setOptions({
|
|
|
20
20
|
renderer: new TerminalRenderer(),
|
|
21
21
|
});
|
|
22
22
|
const updateMessage = `Update available ${clc.xterm(240)("{currentVersion}")} → ${clc.green("{latestVersion}")}\n` +
|
|
23
|
-
`To update to the latest version using npm, run
|
|
23
|
+
`To update to the latest version using npm, run\n${clc.cyan("npm install -g firebase-tools")}\n` +
|
|
24
24
|
`For other CLI management options, visit the ${marked("[CLI documentation](https://firebase.google.com/docs/cli#update-cli)")}`;
|
|
25
25
|
updateNotifier.notify({ defer: true, isGlobal: true, message: updateMessage });
|
|
26
26
|
const client = require("..");
|
|
@@ -8,6 +8,7 @@ const registry_1 = require("../emulator/registry");
|
|
|
8
8
|
const types_1 = require("../emulator/types");
|
|
9
9
|
const clc = require("cli-color");
|
|
10
10
|
const constants_1 = require("../emulator/constants");
|
|
11
|
+
const utils_1 = require("../utils");
|
|
11
12
|
const Table = require("cli-table");
|
|
12
13
|
function stylizeLink(url) {
|
|
13
14
|
return clc.underline(clc.bold(url));
|
|
@@ -22,8 +23,9 @@ module.exports = new command_1.Command("emulators:start")
|
|
|
22
23
|
.option(commandUtils.FLAG_EXPORT_ON_EXIT, commandUtils.DESC_EXPORT_ON_EXIT)
|
|
23
24
|
.action(async (options) => {
|
|
24
25
|
const killSignalPromise = commandUtils.shutdownWhenKilled(options);
|
|
26
|
+
let deprecationNotices;
|
|
25
27
|
try {
|
|
26
|
-
await controller.startAll(options);
|
|
28
|
+
({ deprecationNotices } = await controller.startAll(options));
|
|
27
29
|
}
|
|
28
30
|
catch (e) {
|
|
29
31
|
await controller.cleanShutdown();
|
|
@@ -85,5 +87,8 @@ ${clc.blackBright(" Other reserved ports:")} ${reservedPortsString}
|
|
|
85
87
|
|
|
86
88
|
Issues? Report them at ${stylizeLink("https://github.com/firebase/firebase-tools/issues")} and attach the *-debug.log files.
|
|
87
89
|
`);
|
|
90
|
+
for (const notice of deprecationNotices) {
|
|
91
|
+
(0, utils_1.logLabeledWarning)("emulators", notice, "warn");
|
|
92
|
+
}
|
|
88
93
|
await killSignalPromise;
|
|
89
94
|
});
|
|
@@ -19,9 +19,10 @@ module.exports = new command_1.Command("ext:dev:emulators:start")
|
|
|
19
19
|
.action(async (options) => {
|
|
20
20
|
const killSignalPromise = commandUtils.shutdownWhenKilled(options);
|
|
21
21
|
const emulatorOptions = await optionsHelper.buildOptions(options);
|
|
22
|
+
let deprecationNotices;
|
|
22
23
|
try {
|
|
23
24
|
commandUtils.beforeEmulatorCommand(emulatorOptions);
|
|
24
|
-
await controller.startAll(emulatorOptions);
|
|
25
|
+
({ deprecationNotices } = await controller.startAll(emulatorOptions));
|
|
25
26
|
}
|
|
26
27
|
catch (e) {
|
|
27
28
|
await controller.cleanShutdown();
|
|
@@ -31,5 +32,8 @@ module.exports = new command_1.Command("ext:dev:emulators:start")
|
|
|
31
32
|
throw e;
|
|
32
33
|
}
|
|
33
34
|
utils.logSuccess("All emulators ready, it is now safe to connect.");
|
|
35
|
+
for (const notice of deprecationNotices) {
|
|
36
|
+
utils.logLabeledWarning("emulators", notice, "warn");
|
|
37
|
+
}
|
|
34
38
|
await killSignalPromise;
|
|
35
39
|
});
|
|
@@ -39,6 +39,7 @@ exports.authOperations = {
|
|
|
39
39
|
projects: {
|
|
40
40
|
createSessionCookie,
|
|
41
41
|
queryAccounts,
|
|
42
|
+
updateConfig,
|
|
42
43
|
accounts: {
|
|
43
44
|
_: signUp,
|
|
44
45
|
delete: deleteAccount,
|
|
@@ -1236,28 +1237,17 @@ function getEmulatorProjectConfig(state) {
|
|
|
1236
1237
|
usageMode: state.usageMode,
|
|
1237
1238
|
};
|
|
1238
1239
|
}
|
|
1239
|
-
function updateEmulatorProjectConfig(state, reqBody) {
|
|
1240
|
+
function updateEmulatorProjectConfig(state, reqBody, ctx) {
|
|
1240
1241
|
var _a;
|
|
1241
|
-
const
|
|
1242
|
-
if (allowDuplicateEmails != null) {
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
if (usageMode != null) {
|
|
1248
|
-
(0, errors_1.assert)(state instanceof state_1.AgentProjectState, "((Only top level projects can set usageMode.))");
|
|
1249
|
-
switch (usageMode) {
|
|
1250
|
-
case "PASSTHROUGH":
|
|
1251
|
-
(0, errors_1.assert)(state.getUserCount() === 0, "Users are present, unable to set passthrough mode");
|
|
1252
|
-
state.usageMode = state_1.UsageMode.PASSTHROUGH;
|
|
1253
|
-
break;
|
|
1254
|
-
case "DEFAULT":
|
|
1255
|
-
state.usageMode = state_1.UsageMode.DEFAULT;
|
|
1256
|
-
break;
|
|
1257
|
-
default:
|
|
1258
|
-
throw new errors_1.BadRequestError("Invalid usage mode provided");
|
|
1259
|
-
}
|
|
1242
|
+
const updateMask = [];
|
|
1243
|
+
if (((_a = reqBody.signIn) === null || _a === void 0 ? void 0 : _a.allowDuplicateEmails) != null) {
|
|
1244
|
+
updateMask.push("signIn.allowDuplicateEmails");
|
|
1245
|
+
}
|
|
1246
|
+
if (reqBody.usageMode) {
|
|
1247
|
+
updateMask.push("usageMode");
|
|
1260
1248
|
}
|
|
1249
|
+
ctx.params.query.updateMask = updateMask.join();
|
|
1250
|
+
updateConfig(state, reqBody, ctx);
|
|
1261
1251
|
return getEmulatorProjectConfig(state);
|
|
1262
1252
|
}
|
|
1263
1253
|
function listOobCodesInProject(state) {
|
|
@@ -1390,6 +1380,17 @@ function mfaSignInFinalize(state, reqBody) {
|
|
|
1390
1380
|
refreshToken,
|
|
1391
1381
|
};
|
|
1392
1382
|
}
|
|
1383
|
+
function updateConfig(state, reqBody, ctx) {
|
|
1384
|
+
var _a;
|
|
1385
|
+
(0, errors_1.assert)(state instanceof state_1.AgentProjectState, "((Can only update top-level configurations on agent projects.))");
|
|
1386
|
+
for (const event in (_a = reqBody.blockingFunctions) === null || _a === void 0 ? void 0 : _a.triggers) {
|
|
1387
|
+
if (Object.prototype.hasOwnProperty.call(reqBody.blockingFunctions.triggers, event)) {
|
|
1388
|
+
(0, errors_1.assert)(Object.values(state_1.BlockingFunctionEvents).includes(event), "INVALID_BLOCKING_FUNCTION: ((Event type is invalid.))");
|
|
1389
|
+
(0, errors_1.assert)((0, utils_1.parseAbsoluteUri)(reqBody.blockingFunctions.triggers[event].functionUri), "INVALID_BLOCKING_FUNCTION: ((Expected an absolute URI with valid scheme and host.))");
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
return state.updateConfig(reqBody, ctx.params.query.updateMask);
|
|
1393
|
+
}
|
|
1393
1394
|
function coercePrimitiveToString(value) {
|
|
1394
1395
|
switch (typeof value) {
|
|
1395
1396
|
case "string":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UsageMode = 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;
|
|
3
|
+
exports.BlockingFunctionEvents = exports.UsageMode = 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
4
|
const utils_1 = require("./utils");
|
|
5
5
|
const cloudFunctions_1 = require("./cloudFunctions");
|
|
6
6
|
const errors_1 = require("./errors");
|
|
@@ -422,25 +422,28 @@ exports.ProjectState = ProjectState;
|
|
|
422
422
|
class AgentProjectState extends ProjectState {
|
|
423
423
|
constructor(projectId) {
|
|
424
424
|
super(projectId);
|
|
425
|
-
this._oneAccountPerEmail = true;
|
|
426
|
-
this._usageMode = UsageMode.DEFAULT;
|
|
427
425
|
this.tenantProjectForTenantId = new Map();
|
|
428
426
|
this._authCloudFunction = new cloudFunctions_1.AuthCloudFunction(this.projectId);
|
|
427
|
+
this._config = {
|
|
428
|
+
signIn: { allowDuplicateEmails: false },
|
|
429
|
+
usageMode: UsageMode.DEFAULT,
|
|
430
|
+
blockingFunctions: {},
|
|
431
|
+
};
|
|
429
432
|
}
|
|
430
433
|
get authCloudFunction() {
|
|
431
434
|
return this._authCloudFunction;
|
|
432
435
|
}
|
|
433
436
|
get oneAccountPerEmail() {
|
|
434
|
-
return this.
|
|
437
|
+
return !this._config.signIn.allowDuplicateEmails;
|
|
435
438
|
}
|
|
436
439
|
set oneAccountPerEmail(oneAccountPerEmail) {
|
|
437
|
-
this.
|
|
440
|
+
this._config.signIn.allowDuplicateEmails = !oneAccountPerEmail;
|
|
438
441
|
}
|
|
439
442
|
get usageMode() {
|
|
440
|
-
return this.
|
|
443
|
+
return this._config.usageMode;
|
|
441
444
|
}
|
|
442
445
|
set usageMode(usageMode) {
|
|
443
|
-
this.
|
|
446
|
+
this._config.usageMode = usageMode;
|
|
444
447
|
}
|
|
445
448
|
get allowPasswordSignup() {
|
|
446
449
|
return true;
|
|
@@ -457,6 +460,31 @@ class AgentProjectState extends ProjectState {
|
|
|
457
460
|
get enableEmailLinkSignin() {
|
|
458
461
|
return true;
|
|
459
462
|
}
|
|
463
|
+
get config() {
|
|
464
|
+
return this._config;
|
|
465
|
+
}
|
|
466
|
+
get blockingFunctionsConfig() {
|
|
467
|
+
return this._config.blockingFunctions;
|
|
468
|
+
}
|
|
469
|
+
set blockingFunctionsConfig(blockingFunctions) {
|
|
470
|
+
this._config.blockingFunctions = blockingFunctions;
|
|
471
|
+
}
|
|
472
|
+
updateConfig(update, updateMask) {
|
|
473
|
+
var _a, _b, _c, _d;
|
|
474
|
+
if (update.usageMode) {
|
|
475
|
+
(0, errors_1.assert)(update.usageMode !== UsageMode.USAGE_MODE_UNSPECIFIED, "INVALID_USAGE_MODE: ((Invalid usage mode provided.))");
|
|
476
|
+
if (update.usageMode === UsageMode.PASSTHROUGH) {
|
|
477
|
+
(0, errors_1.assert)(this.getUserCount() === 0, "USERS_STILL_EXIST: ((Users are present, unable to set passthrough mode.))");
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
if (!updateMask) {
|
|
481
|
+
this.oneAccountPerEmail = (_b = !((_a = update.signIn) === null || _a === void 0 ? void 0 : _a.allowDuplicateEmails)) !== null && _b !== void 0 ? _b : true;
|
|
482
|
+
this.blockingFunctionsConfig = (_c = update.blockingFunctions) !== null && _c !== void 0 ? _c : {};
|
|
483
|
+
this.usageMode = (_d = update.usageMode) !== null && _d !== void 0 ? _d : UsageMode.DEFAULT;
|
|
484
|
+
return this.config;
|
|
485
|
+
}
|
|
486
|
+
return applyMask(updateMask, this.config, update);
|
|
487
|
+
}
|
|
460
488
|
getTenantProject(tenantId) {
|
|
461
489
|
if (!this.tenantProjectForTenantId.has(tenantId)) {
|
|
462
490
|
this.createTenantWithTenantId(tenantId, {
|
|
@@ -574,40 +602,21 @@ class TenantProjectState extends ProjectState {
|
|
|
574
602
|
};
|
|
575
603
|
return this.tenantConfig;
|
|
576
604
|
}
|
|
577
|
-
|
|
578
|
-
for (const path of paths) {
|
|
579
|
-
const fields = path.split(".");
|
|
580
|
-
let updateField = update;
|
|
581
|
-
let existingField = this._tenantConfig;
|
|
582
|
-
let field;
|
|
583
|
-
for (let i = 0; i < fields.length - 1; i++) {
|
|
584
|
-
field = fields[i];
|
|
585
|
-
if (updateField[field] == null) {
|
|
586
|
-
console.warn(`Unable to find field '${field}' in update '${updateField}`);
|
|
587
|
-
break;
|
|
588
|
-
}
|
|
589
|
-
if (Array.isArray(updateField[field]) ||
|
|
590
|
-
Object(updateField[field]) !== updateField[field]) {
|
|
591
|
-
console.warn(`Field '${field}' is singular and cannot have sub-fields`);
|
|
592
|
-
break;
|
|
593
|
-
}
|
|
594
|
-
if (!existingField[field]) {
|
|
595
|
-
existingField[field] = {};
|
|
596
|
-
}
|
|
597
|
-
updateField = updateField[field];
|
|
598
|
-
existingField = existingField[field];
|
|
599
|
-
}
|
|
600
|
-
field = fields[fields.length - 1];
|
|
601
|
-
if (updateField[field] == null) {
|
|
602
|
-
console.warn(`Unable to find field '${field}' in update '${JSON.stringify(updateField)}`);
|
|
603
|
-
continue;
|
|
604
|
-
}
|
|
605
|
-
existingField[field] = updateField[field];
|
|
606
|
-
}
|
|
607
|
-
return this.tenantConfig;
|
|
605
|
+
return applyMask(updateMask, this.tenantConfig, update);
|
|
608
606
|
}
|
|
609
607
|
}
|
|
610
608
|
exports.TenantProjectState = TenantProjectState;
|
|
609
|
+
var UsageMode;
|
|
610
|
+
(function (UsageMode) {
|
|
611
|
+
UsageMode["USAGE_MODE_UNSPECIFIED"] = "USAGE_MODE_UNSPECIFIED";
|
|
612
|
+
UsageMode["DEFAULT"] = "DEFAULT";
|
|
613
|
+
UsageMode["PASSTHROUGH"] = "PASSTHROUGH";
|
|
614
|
+
})(UsageMode = exports.UsageMode || (exports.UsageMode = {}));
|
|
615
|
+
var BlockingFunctionEvents;
|
|
616
|
+
(function (BlockingFunctionEvents) {
|
|
617
|
+
BlockingFunctionEvents["BEFORE_CREATE"] = "beforeCreate";
|
|
618
|
+
BlockingFunctionEvents["BEFORE_SIGN_IN"] = "beforeSignIn";
|
|
619
|
+
})(BlockingFunctionEvents = exports.BlockingFunctionEvents || (exports.BlockingFunctionEvents = {}));
|
|
611
620
|
function getProviderEmailsForUser(user) {
|
|
612
621
|
var _a;
|
|
613
622
|
const emails = new Set();
|
|
@@ -618,8 +627,35 @@ function getProviderEmailsForUser(user) {
|
|
|
618
627
|
});
|
|
619
628
|
return emails;
|
|
620
629
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
630
|
+
function applyMask(updateMask, dest, update) {
|
|
631
|
+
const paths = updateMask.split(",");
|
|
632
|
+
for (const path of paths) {
|
|
633
|
+
const fields = path.split(".");
|
|
634
|
+
let updateField = update;
|
|
635
|
+
let existingField = dest;
|
|
636
|
+
let field;
|
|
637
|
+
for (let i = 0; i < fields.length - 1; i++) {
|
|
638
|
+
field = fields[i];
|
|
639
|
+
if (updateField[field] == null) {
|
|
640
|
+
console.warn(`Unable to find field '${field}' in update '${updateField}`);
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
if (Array.isArray(updateField[field]) || Object(updateField[field]) !== updateField[field]) {
|
|
644
|
+
console.warn(`Field '${field}' is singular and cannot have sub-fields`);
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
if (!existingField[field]) {
|
|
648
|
+
existingField[field] = {};
|
|
649
|
+
}
|
|
650
|
+
updateField = updateField[field];
|
|
651
|
+
existingField = existingField[field];
|
|
652
|
+
}
|
|
653
|
+
field = fields[fields.length - 1];
|
|
654
|
+
if (updateField[field] == null) {
|
|
655
|
+
console.warn(`Unable to find field '${field}' in update '${JSON.stringify(updateField)}`);
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
existingField[field] = updateField[field];
|
|
659
|
+
}
|
|
660
|
+
return dest;
|
|
661
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.emulatorExec = exports.shutdownWhenKilled = exports.setExportOnExitOptions = exports.parseInspectionPort = exports.beforeEmulatorCommand = exports.warnEmulatorNotSupported = exports.printNoticeIfEmulated = exports.DESC_TEST_PARAMS = exports.FLAG_TEST_PARAMS = exports.DESC_TEST_CONFIG = exports.FLAG_TEST_CONFIG = exports.DESC_UI = exports.FLAG_UI = exports.EXPORT_ON_EXIT_CWD_DANGER = exports.EXPORT_ON_EXIT_USAGE_ERROR = exports.DESC_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT_NAME = exports.DESC_IMPORT = exports.FLAG_IMPORT = exports.DESC_INSPECT_FUNCTIONS = exports.FLAG_INSPECT_FUNCTIONS = exports.DESC_ONLY = exports.FLAG_ONLY = void 0;
|
|
3
|
+
exports.JAVA_DEPRECATION_WARNING = exports.checkJavaSupported = exports.emulatorExec = exports.shutdownWhenKilled = exports.setExportOnExitOptions = exports.parseInspectionPort = exports.beforeEmulatorCommand = exports.warnEmulatorNotSupported = exports.printNoticeIfEmulated = exports.DESC_TEST_PARAMS = exports.FLAG_TEST_PARAMS = exports.DESC_TEST_CONFIG = exports.FLAG_TEST_CONFIG = exports.DESC_UI = exports.FLAG_UI = exports.EXPORT_ON_EXIT_CWD_DANGER = exports.EXPORT_ON_EXIT_USAGE_ERROR = exports.DESC_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT_NAME = exports.DESC_IMPORT = exports.FLAG_IMPORT = exports.DESC_INSPECT_FUNCTIONS = exports.FLAG_INSPECT_FUNCTIONS = exports.DESC_ONLY = exports.FLAG_ONLY = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
5
|
const childProcess = require("child_process");
|
|
6
6
|
const controller = require("../emulator/controller");
|
|
@@ -287,15 +287,19 @@ async function emulatorExec(script, options) {
|
|
|
287
287
|
extraEnv.GCLOUD_PROJECT = projectId;
|
|
288
288
|
}
|
|
289
289
|
let exitCode = 0;
|
|
290
|
+
let deprecationNotices;
|
|
290
291
|
try {
|
|
291
292
|
const showUI = !!options.ui;
|
|
292
|
-
await controller.startAll(options, showUI);
|
|
293
|
+
({ deprecationNotices } = await controller.startAll(options, showUI));
|
|
293
294
|
exitCode = await runScript(script, extraEnv);
|
|
294
295
|
await (0, controller_1.onExit)(options);
|
|
295
296
|
}
|
|
296
297
|
finally {
|
|
297
298
|
await controller.cleanShutdown();
|
|
298
299
|
}
|
|
300
|
+
for (const notice of deprecationNotices) {
|
|
301
|
+
utils.logLabeledWarning("emulators", notice, "warn");
|
|
302
|
+
}
|
|
299
303
|
if (exitCode !== 0) {
|
|
300
304
|
throw new error_1.FirebaseError(`Script "${clc.bold(script)}" exited with code ${exitCode}`, {
|
|
301
305
|
exit: exitCode,
|
|
@@ -303,3 +307,69 @@ async function emulatorExec(script, options) {
|
|
|
303
307
|
}
|
|
304
308
|
}
|
|
305
309
|
exports.emulatorExec = emulatorExec;
|
|
310
|
+
const JAVA_VERSION_REGEX = /version "([1-9][0-9]*)/;
|
|
311
|
+
const MIN_SUPPORTED_JAVA_MAJOR_VERSION = 11;
|
|
312
|
+
const JAVA_HINT = "Please make sure Java is installed and on your system PATH.";
|
|
313
|
+
async function checkJavaSupported() {
|
|
314
|
+
return new Promise((resolve, reject) => {
|
|
315
|
+
var _a, _b;
|
|
316
|
+
let child;
|
|
317
|
+
try {
|
|
318
|
+
child = childProcess.spawn("java", ["-Duser.language=en", "-Dfile.encoding=UTF-8", "-version"], {
|
|
319
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
catch (err) {
|
|
323
|
+
return reject(new error_1.FirebaseError(`Could not spawn \`java -version\`. ${JAVA_HINT}`, { original: err }));
|
|
324
|
+
}
|
|
325
|
+
let output = "";
|
|
326
|
+
let error = "";
|
|
327
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (data) => {
|
|
328
|
+
const str = data.toString("utf8");
|
|
329
|
+
logger_1.logger.debug(str);
|
|
330
|
+
output += str;
|
|
331
|
+
});
|
|
332
|
+
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (data) => {
|
|
333
|
+
const str = data.toString("utf8");
|
|
334
|
+
logger_1.logger.debug(str);
|
|
335
|
+
error += str;
|
|
336
|
+
});
|
|
337
|
+
child.once("error", (err) => {
|
|
338
|
+
reject(new error_1.FirebaseError(`Could not spawn \`java -version\`. ${JAVA_HINT}`, { original: err }));
|
|
339
|
+
});
|
|
340
|
+
child.once("exit", (code, signal) => {
|
|
341
|
+
if (signal) {
|
|
342
|
+
reject(new error_1.FirebaseError(`Process \`java -version\` was killed by signal ${signal}.`));
|
|
343
|
+
}
|
|
344
|
+
else if (code && code !== 0) {
|
|
345
|
+
reject(new error_1.FirebaseError(`Process \`java -version\` has exited with code ${code}. ${JAVA_HINT}\n` +
|
|
346
|
+
`-----Original stdout-----\n${output}` +
|
|
347
|
+
`-----Original stderr-----\n${error}`));
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
resolve(`${output}\n${error}`);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}).then((output) => {
|
|
354
|
+
const match = output.match(JAVA_VERSION_REGEX);
|
|
355
|
+
if (match) {
|
|
356
|
+
const version = match[1];
|
|
357
|
+
const versionInt = parseInt(version, 10);
|
|
358
|
+
if (!versionInt) {
|
|
359
|
+
utils.logLabeledWarning("emulators", `Failed to parse Java version. Got "${match[0]}".`, "warn");
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
logger_1.logger.debug(`Parsed Java major version: ${versionInt}`);
|
|
363
|
+
return versionInt >= MIN_SUPPORTED_JAVA_MAJOR_VERSION;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
logger_1.logger.debug("java -version outputs:", output);
|
|
368
|
+
logger_1.logger.warn(`Failed to parse Java version.`);
|
|
369
|
+
}
|
|
370
|
+
return false;
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
exports.checkJavaSupported = checkJavaSupported;
|
|
374
|
+
exports.JAVA_DEPRECATION_WARNING = "Support for Java version <= 10 will be dropped soon in firebase-tools@11. " +
|
|
375
|
+
"Please upgrade to Java version 11 or above to continue using the emulators.";
|
|
@@ -39,6 +39,7 @@ const auth_2 = require("../auth");
|
|
|
39
39
|
const extensionsEmulator_1 = require("./extensionsEmulator");
|
|
40
40
|
const previews_1 = require("../previews");
|
|
41
41
|
const projectConfig_1 = require("../functions/projectConfig");
|
|
42
|
+
const downloadableEmulators_1 = require("./downloadableEmulators");
|
|
42
43
|
const START_LOGGING_EMULATOR = utils.envOverride("START_LOGGING_EMULATOR", "false", (val) => val === "true");
|
|
43
44
|
async function getAndCheckAddress(emulator, options) {
|
|
44
45
|
var _a, _b, _c, _d;
|
|
@@ -216,6 +217,13 @@ async function startAll(options, showUI = true) {
|
|
|
216
217
|
if (targets.length === 0) {
|
|
217
218
|
throw new error_1.FirebaseError(`No emulators to start, run ${clc.bold("firebase init emulators")} to get started.`);
|
|
218
219
|
}
|
|
220
|
+
const deprecationNotices = [];
|
|
221
|
+
if (targets.some(downloadableEmulators_1.requiresJava)) {
|
|
222
|
+
if (!(await commandUtils.checkJavaSupported())) {
|
|
223
|
+
utils.logLabeledWarning("emulators", commandUtils_1.JAVA_DEPRECATION_WARNING, "warn");
|
|
224
|
+
deprecationNotices.push(commandUtils_1.JAVA_DEPRECATION_WARNING);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
219
227
|
const hubLogger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.HUB);
|
|
220
228
|
hubLogger.logLabeled("BULLET", "emulators", `Starting emulators: ${targets.join(", ")}`);
|
|
221
229
|
const projectId = (0, projectUtils_1.getProjectId)(options) || "";
|
|
@@ -479,6 +487,7 @@ async function startAll(options, showUI = true) {
|
|
|
479
487
|
await instance.connect();
|
|
480
488
|
}
|
|
481
489
|
}
|
|
490
|
+
return { deprecationNotices };
|
|
482
491
|
}
|
|
483
492
|
exports.startAll = startAll;
|
|
484
493
|
async function exportEmulatorData(exportPath, options) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.start = exports.downloadIfNecessary = exports.stop = exports.getPID = exports.get = exports.getDownloadDetails = exports.handleEmulatorProcessError = exports._getCommand = exports.getLogFileName = exports.DownloadDetails = void 0;
|
|
3
|
+
exports.start = exports.downloadIfNecessary = exports.stop = exports.getPID = exports.get = exports.getDownloadDetails = exports.requiresJava = exports.handleEmulatorProcessError = exports._getCommand = exports.getLogFileName = exports.DownloadDetails = void 0;
|
|
4
4
|
const types_1 = require("./types");
|
|
5
5
|
const constants_1 = require("./constants");
|
|
6
6
|
const error_1 = require("../error");
|
|
@@ -29,13 +29,13 @@ exports.DownloadDetails = {
|
|
|
29
29
|
},
|
|
30
30
|
},
|
|
31
31
|
firestore: {
|
|
32
|
-
downloadPath: path.join(CACHE_DIR, "cloud-firestore-emulator-v1.
|
|
33
|
-
version: "1.
|
|
32
|
+
downloadPath: path.join(CACHE_DIR, "cloud-firestore-emulator-v1.14.1.jar"),
|
|
33
|
+
version: "1.14.1",
|
|
34
34
|
opts: {
|
|
35
35
|
cacheDir: CACHE_DIR,
|
|
36
|
-
remoteUrl: "https://storage.googleapis.com/firebase-preview-drop/emulator/cloud-firestore-emulator-v1.
|
|
37
|
-
expectedSize:
|
|
38
|
-
expectedChecksum: "
|
|
36
|
+
remoteUrl: "https://storage.googleapis.com/firebase-preview-drop/emulator/cloud-firestore-emulator-v1.14.1.jar",
|
|
37
|
+
expectedSize: 60416634,
|
|
38
|
+
expectedChecksum: "33cffe8065d4250816f257eb19245932",
|
|
39
39
|
namePrefix: "cloud-firestore-emulator",
|
|
40
40
|
},
|
|
41
41
|
},
|
|
@@ -236,6 +236,13 @@ async function handleEmulatorProcessError(emulator, err) {
|
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
exports.handleEmulatorProcessError = handleEmulatorProcessError;
|
|
239
|
+
function requiresJava(emulator) {
|
|
240
|
+
if (emulator in Commands) {
|
|
241
|
+
return Commands[emulator].binary === "java";
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
exports.requiresJava = requiresJava;
|
|
239
246
|
async function _runBinary(emulator, command, extraEnv) {
|
|
240
247
|
return new Promise((resolve) => {
|
|
241
248
|
var _a, _b;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reqBodyToBuffer = void 0;
|
|
4
|
+
async function reqBodyToBuffer(req) {
|
|
5
|
+
if (req.body instanceof Buffer) {
|
|
6
|
+
return Buffer.from(req.body);
|
|
7
|
+
}
|
|
8
|
+
const bufs = [];
|
|
9
|
+
req.on("data", (data) => {
|
|
10
|
+
bufs.push(data);
|
|
11
|
+
});
|
|
12
|
+
await new Promise((resolve) => {
|
|
13
|
+
req.on("end", () => {
|
|
14
|
+
resolve();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
return Buffer.concat(bufs);
|
|
18
|
+
}
|
|
19
|
+
exports.reqBodyToBuffer = reqBodyToBuffer;
|
|
@@ -10,6 +10,7 @@ const registry_1 = require("../../registry");
|
|
|
10
10
|
const multipart_1 = require("../multipart");
|
|
11
11
|
const errors_1 = require("../errors");
|
|
12
12
|
const upload_1 = require("../upload");
|
|
13
|
+
const request_1 = require("../../shared/request");
|
|
13
14
|
function createFirebaseEndpoints(emulator) {
|
|
14
15
|
const firebaseStorageAPI = (0, express_1.Router)();
|
|
15
16
|
const { storageLayer, uploadService } = emulator;
|
|
@@ -71,7 +72,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
71
72
|
let metadata;
|
|
72
73
|
let data;
|
|
73
74
|
try {
|
|
74
|
-
({ metadata, data } = await storageLayer.
|
|
75
|
+
({ metadata, data } = await storageLayer.getObject({
|
|
75
76
|
bucketId: req.params.bucketId,
|
|
76
77
|
decodedObjectId: decodeURIComponent(req.params.objectId),
|
|
77
78
|
authorization: req.header("authorization"),
|
|
@@ -117,11 +118,11 @@ function createFirebaseEndpoints(emulator) {
|
|
|
117
118
|
return res.json(new metadata_1.OutgoingFirebaseMetadata(metadata));
|
|
118
119
|
});
|
|
119
120
|
firebaseStorageAPI.get("/b/:bucketId/o", async (req, res) => {
|
|
120
|
-
var _a, _b;
|
|
121
|
+
var _a, _b, _c, _d, _e;
|
|
121
122
|
const maxResults = (_a = req.query.maxResults) === null || _a === void 0 ? void 0 : _a.toString();
|
|
122
|
-
let
|
|
123
|
+
let listResponse;
|
|
123
124
|
try {
|
|
124
|
-
|
|
125
|
+
listResponse = await storageLayer.listObjects({
|
|
125
126
|
bucketId: req.params.bucketId,
|
|
126
127
|
prefix: req.query.prefix ? req.query.prefix.toString() : "",
|
|
127
128
|
delimiter: req.query.delimiter ? req.query.delimiter.toString() : "",
|
|
@@ -141,23 +142,14 @@ function createFirebaseEndpoints(emulator) {
|
|
|
141
142
|
}
|
|
142
143
|
throw err;
|
|
143
144
|
}
|
|
144
|
-
return res.json(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const bufs = [];
|
|
151
|
-
req.on("data", (data) => {
|
|
152
|
-
bufs.push(data);
|
|
145
|
+
return res.status(200).json({
|
|
146
|
+
nextPageToken: listResponse.nextPageToken,
|
|
147
|
+
prefixes: (_c = listResponse.prefixes) !== null && _c !== void 0 ? _c : [],
|
|
148
|
+
items: (_e = (_d = listResponse.items) === null || _d === void 0 ? void 0 : _d.map((item) => {
|
|
149
|
+
return { name: item.name, bucket: item.bucket };
|
|
150
|
+
})) !== null && _e !== void 0 ? _e : [],
|
|
153
151
|
});
|
|
154
|
-
|
|
155
|
-
req.on("end", () => {
|
|
156
|
-
resolve();
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
return Buffer.concat(bufs);
|
|
160
|
-
};
|
|
152
|
+
});
|
|
161
153
|
const handleUpload = async (req, res) => {
|
|
162
154
|
if (!req.query.name) {
|
|
163
155
|
res.sendStatus(400);
|
|
@@ -174,7 +166,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
174
166
|
let metadataRaw;
|
|
175
167
|
let dataRaw;
|
|
176
168
|
try {
|
|
177
|
-
({ metadataRaw, dataRaw } = (0, multipart_1.parseObjectUploadMultipartRequest)(contentTypeHeader, await reqBodyToBuffer(req)));
|
|
169
|
+
({ metadataRaw, dataRaw } = (0, multipart_1.parseObjectUploadMultipartRequest)(contentTypeHeader, await (0, request_1.reqBodyToBuffer)(req)));
|
|
178
170
|
}
|
|
179
171
|
catch (err) {
|
|
180
172
|
if (err instanceof Error) {
|
|
@@ -196,7 +188,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
196
188
|
});
|
|
197
189
|
let metadata;
|
|
198
190
|
try {
|
|
199
|
-
metadata = await storageLayer.
|
|
191
|
+
metadata = await storageLayer.uploadObject(upload);
|
|
200
192
|
}
|
|
201
193
|
catch (err) {
|
|
202
194
|
if (err instanceof errors_1.ForbiddenError) {
|
|
@@ -268,7 +260,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
268
260
|
if (uploadCommand.includes("upload")) {
|
|
269
261
|
let upload;
|
|
270
262
|
try {
|
|
271
|
-
upload = uploadService.continueResumableUpload(uploadId, await reqBodyToBuffer(req));
|
|
263
|
+
upload = uploadService.continueResumableUpload(uploadId, await (0, request_1.reqBodyToBuffer)(req));
|
|
272
264
|
}
|
|
273
265
|
catch (err) {
|
|
274
266
|
if (err instanceof errors_1.NotFoundError) {
|
|
@@ -301,7 +293,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
301
293
|
}
|
|
302
294
|
let metadata;
|
|
303
295
|
try {
|
|
304
|
-
metadata = await storageLayer.
|
|
296
|
+
metadata = await storageLayer.uploadObject(upload);
|
|
305
297
|
}
|
|
306
298
|
catch (err) {
|
|
307
299
|
if (err instanceof errors_1.ForbiddenError) {
|
|
@@ -333,7 +325,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
333
325
|
return res.sendStatus(400);
|
|
334
326
|
}
|
|
335
327
|
try {
|
|
336
|
-
metadata = storageLayer.
|
|
328
|
+
metadata = storageLayer.createDownloadToken({
|
|
337
329
|
bucketId,
|
|
338
330
|
decodedObjectId,
|
|
339
331
|
authorization,
|
|
@@ -356,7 +348,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
356
348
|
}
|
|
357
349
|
else {
|
|
358
350
|
try {
|
|
359
|
-
metadata = storageLayer.
|
|
351
|
+
metadata = storageLayer.deleteDownloadToken({
|
|
360
352
|
bucketId,
|
|
361
353
|
decodedObjectId,
|
|
362
354
|
token: (_b = (_a = req.query["delete_token"]) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : "",
|
|
@@ -390,7 +382,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
390
382
|
const handleMetadataUpdate = async (req, res) => {
|
|
391
383
|
let metadata;
|
|
392
384
|
try {
|
|
393
|
-
metadata = await storageLayer.
|
|
385
|
+
metadata = await storageLayer.updateObjectMetadata({
|
|
394
386
|
bucketId: req.params.bucketId,
|
|
395
387
|
decodedObjectId: decodeURIComponent(req.params.objectId),
|
|
396
388
|
metadata: req.body,
|
|
@@ -427,7 +419,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
427
419
|
firebaseStorageAPI.post("/b/:bucketId/o/:objectId?", handleObjectPostRequest);
|
|
428
420
|
firebaseStorageAPI.delete("/b/:bucketId/o/:objectId", async (req, res) => {
|
|
429
421
|
try {
|
|
430
|
-
await storageLayer.
|
|
422
|
+
await storageLayer.deleteObject({
|
|
431
423
|
bucketId: req.params.bucketId,
|
|
432
424
|
decodedObjectId: decodeURIComponent(req.params.objectId),
|
|
433
425
|
authorization: req.header("authorization"),
|
|
@@ -11,33 +11,34 @@ const crc_1 = require("../crc");
|
|
|
11
11
|
const multipart_1 = require("../multipart");
|
|
12
12
|
const upload_1 = require("../upload");
|
|
13
13
|
const errors_1 = require("../errors");
|
|
14
|
+
const request_1 = require("../../shared/request");
|
|
14
15
|
function createCloudEndpoints(emulator) {
|
|
15
16
|
const gcloudStorageAPI = (0, express_1.Router)();
|
|
16
|
-
const {
|
|
17
|
+
const { adminStorageLayer, uploadService } = emulator;
|
|
17
18
|
gcloudStorageAPI.use(/.*\/b\/(.+?)\/.*/, (req, res, next) => {
|
|
18
|
-
|
|
19
|
+
adminStorageLayer.createBucket(req.params[0]);
|
|
19
20
|
next();
|
|
20
21
|
});
|
|
21
22
|
gcloudStorageAPI.get("/b", async (req, res) => {
|
|
22
23
|
res.json({
|
|
23
24
|
kind: "storage#buckets",
|
|
24
|
-
items: await
|
|
25
|
+
items: await adminStorageLayer.listBuckets(),
|
|
25
26
|
});
|
|
26
27
|
});
|
|
27
28
|
gcloudStorageAPI.get(["/b/:bucketId/o/:objectId", "/download/storage/v1/b/:bucketId/o/:objectId"], async (req, res) => {
|
|
28
29
|
let getObjectResponse;
|
|
29
30
|
try {
|
|
30
|
-
getObjectResponse = await
|
|
31
|
+
getObjectResponse = await adminStorageLayer.getObject({
|
|
31
32
|
bucketId: req.params.bucketId,
|
|
32
33
|
decodedObjectId: req.params.objectId,
|
|
33
|
-
}
|
|
34
|
+
});
|
|
34
35
|
}
|
|
35
36
|
catch (err) {
|
|
36
37
|
if (err instanceof errors_1.NotFoundError) {
|
|
37
38
|
return sendObjectNotFound(req, res);
|
|
38
39
|
}
|
|
39
40
|
if (err instanceof errors_1.ForbiddenError) {
|
|
40
|
-
|
|
41
|
+
return res.sendStatus(403);
|
|
41
42
|
}
|
|
42
43
|
throw err;
|
|
43
44
|
}
|
|
@@ -49,67 +50,67 @@ function createCloudEndpoints(emulator) {
|
|
|
49
50
|
gcloudStorageAPI.patch("/b/:bucketId/o/:objectId", async (req, res) => {
|
|
50
51
|
let updatedMetadata;
|
|
51
52
|
try {
|
|
52
|
-
updatedMetadata = await
|
|
53
|
+
updatedMetadata = await adminStorageLayer.updateObjectMetadata({
|
|
53
54
|
bucketId: req.params.bucketId,
|
|
54
55
|
decodedObjectId: req.params.objectId,
|
|
55
56
|
metadata: req.body,
|
|
56
|
-
}
|
|
57
|
+
});
|
|
57
58
|
}
|
|
58
59
|
catch (err) {
|
|
59
60
|
if (err instanceof errors_1.NotFoundError) {
|
|
60
61
|
return sendObjectNotFound(req, res);
|
|
61
62
|
}
|
|
62
63
|
if (err instanceof errors_1.ForbiddenError) {
|
|
63
|
-
|
|
64
|
+
return res.sendStatus(403);
|
|
64
65
|
}
|
|
65
66
|
throw err;
|
|
66
67
|
}
|
|
67
68
|
return res.json(new metadata_1.CloudStorageObjectMetadata(updatedMetadata));
|
|
68
69
|
});
|
|
69
|
-
gcloudStorageAPI.get("/b/:bucketId/o", (req, res) => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
gcloudStorageAPI.get("/b/:bucketId/o", async (req, res) => {
|
|
71
|
+
var _a;
|
|
72
|
+
let listResponse;
|
|
73
|
+
try {
|
|
74
|
+
listResponse = await adminStorageLayer.listObjects({
|
|
75
|
+
bucketId: req.params.bucketId,
|
|
76
|
+
prefix: req.query.prefix ? req.query.prefix.toString() : "",
|
|
77
|
+
delimiter: req.query.delimiter ? req.query.delimiter.toString() : "",
|
|
78
|
+
pageToken: req.query.pageToken ? req.query.pageToken.toString() : undefined,
|
|
79
|
+
maxResults: req.query.maxResults ? +req.query.maxResults.toString() : undefined,
|
|
80
|
+
authorization: req.header("authorization"),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
if (err instanceof errors_1.ForbiddenError) {
|
|
85
|
+
return res.sendStatus(403);
|
|
86
|
+
}
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
return res.status(200).json({
|
|
90
|
+
kind: "#storage/objects",
|
|
91
|
+
nextPageToken: listResponse.nextPageToken,
|
|
92
|
+
prefixes: listResponse.prefixes,
|
|
93
|
+
items: (_a = listResponse.items) === null || _a === void 0 ? void 0 : _a.map((item) => new metadata_1.CloudStorageObjectMetadata(item)),
|
|
94
|
+
});
|
|
79
95
|
});
|
|
80
96
|
gcloudStorageAPI.delete("/b/:bucketId/o/:objectId", async (req, res) => {
|
|
81
97
|
try {
|
|
82
|
-
await
|
|
98
|
+
await adminStorageLayer.deleteObject({
|
|
83
99
|
bucketId: req.params.bucketId,
|
|
84
100
|
decodedObjectId: req.params.objectId,
|
|
85
|
-
}
|
|
101
|
+
});
|
|
86
102
|
}
|
|
87
103
|
catch (err) {
|
|
88
104
|
if (err instanceof errors_1.NotFoundError) {
|
|
89
105
|
return sendObjectNotFound(req, res);
|
|
90
106
|
}
|
|
91
107
|
if (err instanceof errors_1.ForbiddenError) {
|
|
92
|
-
|
|
108
|
+
return res.sendStatus(403);
|
|
93
109
|
}
|
|
94
110
|
throw err;
|
|
95
111
|
}
|
|
96
112
|
return res.sendStatus(204);
|
|
97
113
|
});
|
|
98
|
-
const reqBodyToBuffer = async (req) => {
|
|
99
|
-
if (req.body instanceof Buffer) {
|
|
100
|
-
return Buffer.from(req.body);
|
|
101
|
-
}
|
|
102
|
-
const bufs = [];
|
|
103
|
-
req.on("data", (data) => {
|
|
104
|
-
bufs.push(data);
|
|
105
|
-
});
|
|
106
|
-
await new Promise((resolve) => {
|
|
107
|
-
req.on("end", () => {
|
|
108
|
-
resolve();
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
return Buffer.concat(bufs);
|
|
112
|
-
};
|
|
113
114
|
gcloudStorageAPI.put("/upload/storage/v1/b/:bucketId/o", async (req, res) => {
|
|
114
115
|
if (!req.query.upload_id) {
|
|
115
116
|
res.sendStatus(400);
|
|
@@ -118,7 +119,7 @@ function createCloudEndpoints(emulator) {
|
|
|
118
119
|
const uploadId = req.query.upload_id.toString();
|
|
119
120
|
let upload;
|
|
120
121
|
try {
|
|
121
|
-
uploadService.continueResumableUpload(uploadId, await reqBodyToBuffer(req));
|
|
122
|
+
uploadService.continueResumableUpload(uploadId, await (0, request_1.reqBodyToBuffer)(req));
|
|
122
123
|
upload = uploadService.finalizeResumableUpload(uploadId);
|
|
123
124
|
}
|
|
124
125
|
catch (err) {
|
|
@@ -132,11 +133,11 @@ function createCloudEndpoints(emulator) {
|
|
|
132
133
|
}
|
|
133
134
|
let metadata;
|
|
134
135
|
try {
|
|
135
|
-
metadata = await
|
|
136
|
+
metadata = await adminStorageLayer.uploadObject(upload);
|
|
136
137
|
}
|
|
137
138
|
catch (err) {
|
|
138
139
|
if (err instanceof errors_1.ForbiddenError) {
|
|
139
|
-
|
|
140
|
+
return res.sendStatus(403);
|
|
140
141
|
}
|
|
141
142
|
throw err;
|
|
142
143
|
}
|
|
@@ -147,17 +148,17 @@ function createCloudEndpoints(emulator) {
|
|
|
147
148
|
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.STORAGE).log("WARN_ONCE", "Cloud Storage ACLs are not supported in the Storage Emulator. All related methods will succeed, but have no effect.");
|
|
148
149
|
let getObjectResponse;
|
|
149
150
|
try {
|
|
150
|
-
getObjectResponse = await
|
|
151
|
+
getObjectResponse = await adminStorageLayer.getObject({
|
|
151
152
|
bucketId: req.params.bucketId,
|
|
152
153
|
decodedObjectId: req.params.objectId,
|
|
153
|
-
}
|
|
154
|
+
});
|
|
154
155
|
}
|
|
155
156
|
catch (err) {
|
|
156
157
|
if (err instanceof errors_1.NotFoundError) {
|
|
157
158
|
return sendObjectNotFound(req, res);
|
|
158
159
|
}
|
|
159
160
|
if (err instanceof errors_1.ForbiddenError) {
|
|
160
|
-
|
|
161
|
+
return res.sendStatus(403);
|
|
161
162
|
}
|
|
162
163
|
throw err;
|
|
163
164
|
}
|
|
@@ -206,7 +207,7 @@ function createCloudEndpoints(emulator) {
|
|
|
206
207
|
let metadataRaw;
|
|
207
208
|
let dataRaw;
|
|
208
209
|
try {
|
|
209
|
-
({ metadataRaw, dataRaw } = (0, multipart_1.parseObjectUploadMultipartRequest)(contentTypeHeader, await reqBodyToBuffer(req)));
|
|
210
|
+
({ metadataRaw, dataRaw } = (0, multipart_1.parseObjectUploadMultipartRequest)(contentTypeHeader, await (0, request_1.reqBodyToBuffer)(req)));
|
|
210
211
|
}
|
|
211
212
|
catch (err) {
|
|
212
213
|
return res.status(400).json({
|
|
@@ -225,11 +226,11 @@ function createCloudEndpoints(emulator) {
|
|
|
225
226
|
});
|
|
226
227
|
let metadata;
|
|
227
228
|
try {
|
|
228
|
-
metadata = await
|
|
229
|
+
metadata = await adminStorageLayer.uploadObject(upload);
|
|
229
230
|
}
|
|
230
231
|
catch (err) {
|
|
231
232
|
if (err instanceof errors_1.ForbiddenError) {
|
|
232
|
-
|
|
233
|
+
return res.sendStatus(403);
|
|
233
234
|
}
|
|
234
235
|
throw err;
|
|
235
236
|
}
|
|
@@ -238,34 +239,45 @@ function createCloudEndpoints(emulator) {
|
|
|
238
239
|
gcloudStorageAPI.get("/:bucketId/:objectId(**)", async (req, res) => {
|
|
239
240
|
let getObjectResponse;
|
|
240
241
|
try {
|
|
241
|
-
getObjectResponse = await
|
|
242
|
+
getObjectResponse = await adminStorageLayer.getObject({
|
|
242
243
|
bucketId: req.params.bucketId,
|
|
243
244
|
decodedObjectId: req.params.objectId,
|
|
244
|
-
}
|
|
245
|
+
});
|
|
245
246
|
}
|
|
246
247
|
catch (err) {
|
|
247
248
|
if (err instanceof errors_1.NotFoundError) {
|
|
248
249
|
return sendObjectNotFound(req, res);
|
|
249
250
|
}
|
|
250
251
|
if (err instanceof errors_1.ForbiddenError) {
|
|
251
|
-
|
|
252
|
+
return res.sendStatus(403);
|
|
252
253
|
}
|
|
253
254
|
throw err;
|
|
254
255
|
}
|
|
255
256
|
return sendFileBytes(getObjectResponse.metadata, getObjectResponse.data, req, res);
|
|
256
257
|
});
|
|
257
258
|
gcloudStorageAPI.post("/b/:bucketId/o/:objectId/:method(rewriteTo|copyTo)/b/:destBucketId/o/:destObjectId", (req, res, next) => {
|
|
258
|
-
const md = storageLayer.getMetadata(req.params.bucketId, req.params.objectId);
|
|
259
|
-
if (!md) {
|
|
260
|
-
return sendObjectNotFound(req, res);
|
|
261
|
-
}
|
|
262
259
|
if (req.params.method === "rewriteTo" && req.query.rewriteToken) {
|
|
263
260
|
return next();
|
|
264
261
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
262
|
+
let metadata;
|
|
263
|
+
try {
|
|
264
|
+
metadata = adminStorageLayer.copyObject({
|
|
265
|
+
sourceBucket: req.params.bucketId,
|
|
266
|
+
sourceObject: req.params.objectId,
|
|
267
|
+
destinationBucket: req.params.destBucketId,
|
|
268
|
+
destinationObject: req.params.destObjectId,
|
|
269
|
+
incomingMetadata: req.body,
|
|
270
|
+
authorization: "Bearer owner",
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
catch (err) {
|
|
274
|
+
if (err instanceof errors_1.NotFoundError) {
|
|
275
|
+
return sendObjectNotFound(req, res);
|
|
276
|
+
}
|
|
277
|
+
if (err instanceof errors_1.ForbiddenError) {
|
|
278
|
+
return res.sendStatus(403);
|
|
279
|
+
}
|
|
280
|
+
throw err;
|
|
269
281
|
}
|
|
270
282
|
const resource = new metadata_1.CloudStorageObjectMetadata(metadata);
|
|
271
283
|
res.status(200);
|
|
@@ -9,12 +9,10 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.StorageLayer = exports.StoredFile = void 0;
|
|
11
11
|
const fs_1 = require("fs");
|
|
12
|
-
const list_1 = require("./list");
|
|
13
12
|
const metadata_1 = require("./metadata");
|
|
14
13
|
const errors_1 = require("./errors");
|
|
15
14
|
const path = require("path");
|
|
16
15
|
const fse = require("fs-extra");
|
|
17
|
-
const cloudFunctions_1 = require("./cloudFunctions");
|
|
18
16
|
const logger_1 = require("../../logger");
|
|
19
17
|
const adminSdkConfig_1 = require("../adminSdkConfig");
|
|
20
18
|
const types_1 = require("./rules/types");
|
|
@@ -39,17 +37,14 @@ class StoredFile {
|
|
|
39
37
|
}
|
|
40
38
|
exports.StoredFile = StoredFile;
|
|
41
39
|
class StorageLayer {
|
|
42
|
-
constructor(_projectId, _rulesValidator, _adminCredsValidator, _persistence) {
|
|
40
|
+
constructor(_projectId, _files, _buckets, _rulesValidator, _adminCredsValidator, _persistence, _cloudFunctions) {
|
|
43
41
|
this._projectId = _projectId;
|
|
42
|
+
this._files = _files;
|
|
43
|
+
this._buckets = _buckets;
|
|
44
44
|
this._rulesValidator = _rulesValidator;
|
|
45
45
|
this._adminCredsValidator = _adminCredsValidator;
|
|
46
46
|
this._persistence = _persistence;
|
|
47
|
-
this.
|
|
48
|
-
this._cloudFunctions = new cloudFunctions_1.StorageCloudFunctions(this._projectId);
|
|
49
|
-
}
|
|
50
|
-
reset() {
|
|
51
|
-
this._files = new Map();
|
|
52
|
-
this._buckets = new Map();
|
|
47
|
+
this._cloudFunctions = _cloudFunctions;
|
|
53
48
|
}
|
|
54
49
|
createBucket(id) {
|
|
55
50
|
if (!this._buckets.has(id)) {
|
|
@@ -66,11 +61,11 @@ class StorageLayer {
|
|
|
66
61
|
}
|
|
67
62
|
return [...this._buckets.values()];
|
|
68
63
|
}
|
|
69
|
-
async
|
|
64
|
+
async getObject(request) {
|
|
70
65
|
var _a;
|
|
71
66
|
const metadata = this.getMetadata(request.bucketId, request.decodedObjectId);
|
|
72
67
|
const hasValidDownloadToken = ((metadata === null || metadata === void 0 ? void 0 : metadata.downloadTokens) || []).includes((_a = request.downloadToken) !== null && _a !== void 0 ? _a : "");
|
|
73
|
-
let authorized =
|
|
68
|
+
let authorized = hasValidDownloadToken;
|
|
74
69
|
if (!authorized) {
|
|
75
70
|
authorized = await this._rulesValidator.validate(["b", request.bucketId, "o", request.decodedObjectId].join("/"), request.bucketId, types_1.RulesetOperationMethod.GET, { before: metadata === null || metadata === void 0 ? void 0 : metadata.asRulesResource() }, request.authorization);
|
|
76
71
|
}
|
|
@@ -99,10 +94,9 @@ class StorageLayer {
|
|
|
99
94
|
}
|
|
100
95
|
return undefined;
|
|
101
96
|
}
|
|
102
|
-
async
|
|
97
|
+
async deleteObject(request) {
|
|
103
98
|
const storedMetadata = this.getMetadata(request.bucketId, request.decodedObjectId);
|
|
104
|
-
const authorized =
|
|
105
|
-
(await this._rulesValidator.validate(["b", request.bucketId, "o", request.decodedObjectId].join("/"), request.bucketId, types_1.RulesetOperationMethod.DELETE, { before: storedMetadata === null || storedMetadata === void 0 ? void 0 : storedMetadata.asRulesResource() }, request.authorization));
|
|
99
|
+
const authorized = await this._rulesValidator.validate(["b", request.bucketId, "o", request.decodedObjectId].join("/"), request.bucketId, types_1.RulesetOperationMethod.DELETE, { before: storedMetadata === null || storedMetadata === void 0 ? void 0 : storedMetadata.asRulesResource() }, request.authorization);
|
|
106
100
|
if (!authorized) {
|
|
107
101
|
throw new errors_1.ForbiddenError();
|
|
108
102
|
}
|
|
@@ -131,13 +125,12 @@ class StorageLayer {
|
|
|
131
125
|
return true;
|
|
132
126
|
}
|
|
133
127
|
}
|
|
134
|
-
async
|
|
128
|
+
async updateObjectMetadata(request) {
|
|
135
129
|
const storedMetadata = this.getMetadata(request.bucketId, request.decodedObjectId);
|
|
136
|
-
const authorized =
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}, request.authorization));
|
|
130
|
+
const authorized = await this._rulesValidator.validate(["b", request.bucketId, "o", request.decodedObjectId].join("/"), request.bucketId, types_1.RulesetOperationMethod.UPDATE, {
|
|
131
|
+
before: storedMetadata === null || storedMetadata === void 0 ? void 0 : storedMetadata.asRulesResource(),
|
|
132
|
+
after: storedMetadata === null || storedMetadata === void 0 ? void 0 : storedMetadata.asRulesResource(request.metadata),
|
|
133
|
+
}, request.authorization);
|
|
141
134
|
if (!authorized) {
|
|
142
135
|
throw new errors_1.ForbiddenError();
|
|
143
136
|
}
|
|
@@ -147,7 +140,7 @@ class StorageLayer {
|
|
|
147
140
|
storedMetadata.update(request.metadata);
|
|
148
141
|
return storedMetadata;
|
|
149
142
|
}
|
|
150
|
-
async
|
|
143
|
+
async uploadObject(upload) {
|
|
151
144
|
if (upload.status !== upload_1.UploadStatus.FINISHED) {
|
|
152
145
|
throw new Error(`Unexpected upload status encountered: ${upload.status}.`);
|
|
153
146
|
}
|
|
@@ -162,8 +155,7 @@ class StorageLayer {
|
|
|
162
155
|
cacheControl: upload.metadata.cacheControl,
|
|
163
156
|
customMetadata: upload.metadata.metadata,
|
|
164
157
|
}, this._cloudFunctions, this._persistence.readBytes(upload.path, upload.size));
|
|
165
|
-
const authorized =
|
|
166
|
-
(await this._rulesValidator.validate(["b", upload.bucketId, "o", upload.objectId].join("/"), upload.bucketId, types_1.RulesetOperationMethod.CREATE, { after: metadata === null || metadata === void 0 ? void 0 : metadata.asRulesResource() }, upload.authorization));
|
|
158
|
+
const authorized = await this._rulesValidator.validate(["b", upload.bucketId, "o", upload.objectId].join("/"), upload.bucketId, types_1.RulesetOperationMethod.CREATE, { after: metadata === null || metadata === void 0 ? void 0 : metadata.asRulesResource() }, upload.authorization);
|
|
167
159
|
if (!authorized) {
|
|
168
160
|
this._persistence.deleteFile(upload.path);
|
|
169
161
|
throw new errors_1.ForbiddenError();
|
|
@@ -174,17 +166,24 @@ class StorageLayer {
|
|
|
174
166
|
this._cloudFunctions.dispatch("finalize", new metadata_1.CloudStorageObjectMetadata(metadata));
|
|
175
167
|
return metadata;
|
|
176
168
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
this.
|
|
182
|
-
|
|
183
|
-
|
|
169
|
+
copyObject({ sourceBucket, sourceObject, destinationBucket, destinationObject, incomingMetadata, authorization, }) {
|
|
170
|
+
if (!this._adminCredsValidator.validate(authorization)) {
|
|
171
|
+
throw new errors_1.ForbiddenError();
|
|
172
|
+
}
|
|
173
|
+
const sourceMetadata = this.getMetadata(sourceBucket, sourceObject);
|
|
174
|
+
if (!sourceMetadata) {
|
|
175
|
+
throw new errors_1.NotFoundError();
|
|
176
|
+
}
|
|
177
|
+
const sourceBytes = this.getBytes(sourceBucket, sourceObject);
|
|
178
|
+
const destinationFilePath = this.path(destinationBucket, destinationObject);
|
|
179
|
+
this._persistence.deleteFile(destinationFilePath, true);
|
|
180
|
+
this._persistence.appendBytes(destinationFilePath, sourceBytes);
|
|
181
|
+
const newMetadata = Object.assign(Object.assign(Object.assign({}, sourceMetadata), { metadata: sourceMetadata.customMetadata }), incomingMetadata);
|
|
182
|
+
if (sourceMetadata.downloadTokens.length &&
|
|
184
183
|
!((incomingMetadata === null || incomingMetadata === void 0 ? void 0 : incomingMetadata.metadata) && Object.keys(incomingMetadata === null || incomingMetadata === void 0 ? void 0 : incomingMetadata.metadata).length)) {
|
|
185
184
|
if (!newMetadata.metadata)
|
|
186
185
|
newMetadata.metadata = {};
|
|
187
|
-
newMetadata.metadata.firebaseStorageDownloadTokens =
|
|
186
|
+
newMetadata.metadata.firebaseStorageDownloadTokens = sourceMetadata.downloadTokens.join(",");
|
|
188
187
|
}
|
|
189
188
|
if (newMetadata.metadata) {
|
|
190
189
|
for (const [k, v] of Object.entries(newMetadata.metadata)) {
|
|
@@ -201,27 +200,23 @@ class StorageLayer {
|
|
|
201
200
|
contentLanguage: newMetadata.contentLanguage,
|
|
202
201
|
cacheControl: newMetadata.cacheControl,
|
|
203
202
|
customMetadata: newMetadata.metadata,
|
|
204
|
-
}, this._cloudFunctions,
|
|
205
|
-
const file = new StoredFile(copiedFileMetadata, this._persistence.getDiskPath(
|
|
206
|
-
this._files.set(
|
|
203
|
+
}, this._cloudFunctions, sourceBytes, incomingMetadata);
|
|
204
|
+
const file = new StoredFile(copiedFileMetadata, this._persistence.getDiskPath(destinationFilePath));
|
|
205
|
+
this._files.set(destinationFilePath, file);
|
|
207
206
|
this._cloudFunctions.dispatch("finalize", new metadata_1.CloudStorageObjectMetadata(file.metadata));
|
|
208
207
|
return file.metadata;
|
|
209
208
|
}
|
|
210
|
-
async
|
|
211
|
-
var _a
|
|
212
|
-
const
|
|
213
|
-
|
|
209
|
+
async listObjects(request) {
|
|
210
|
+
var _a;
|
|
211
|
+
const { bucketId, prefix, delimiter, pageToken, authorization } = request;
|
|
212
|
+
const authorized = await this._rulesValidator.validate(["b", bucketId, "o", prefix].join("/"), bucketId, types_1.RulesetOperationMethod.LIST, {}, authorization);
|
|
214
213
|
if (!authorized) {
|
|
215
214
|
throw new errors_1.ForbiddenError();
|
|
216
215
|
}
|
|
217
|
-
const itemsResults = this.listItems(request.bucketId, request.prefix, request.delimiter, request.pageToken, request.maxResults);
|
|
218
|
-
return new list_1.ListResponse((_a = itemsResults.prefixes) !== null && _a !== void 0 ? _a : [], (_c = (_b = itemsResults.items) === null || _b === void 0 ? void 0 : _b.map((i) => new list_1.ListItem(i.name, i.bucket))) !== null && _c !== void 0 ? _c : [], itemsResults.nextPageToken);
|
|
219
|
-
}
|
|
220
|
-
listItems(bucket, prefix, delimiter, pageToken, maxResults) {
|
|
221
216
|
let items = [];
|
|
222
217
|
const prefixes = new Set();
|
|
223
218
|
for (const [, file] of this._files) {
|
|
224
|
-
if (file.metadata.bucket !==
|
|
219
|
+
if (file.metadata.bucket !== bucketId) {
|
|
225
220
|
continue;
|
|
226
221
|
}
|
|
227
222
|
const name = file.metadata.name;
|
|
@@ -258,9 +253,7 @@ class StorageLayer {
|
|
|
258
253
|
items = items.slice(idx);
|
|
259
254
|
}
|
|
260
255
|
}
|
|
261
|
-
|
|
262
|
-
maxResults = 1000;
|
|
263
|
-
}
|
|
256
|
+
const maxResults = (_a = request.maxResults) !== null && _a !== void 0 ? _a : 1000;
|
|
264
257
|
let nextPageToken = undefined;
|
|
265
258
|
if (items.length > maxResults) {
|
|
266
259
|
nextPageToken = items[maxResults].name;
|
|
@@ -269,10 +262,10 @@ class StorageLayer {
|
|
|
269
262
|
return {
|
|
270
263
|
nextPageToken,
|
|
271
264
|
prefixes: prefixes.size > 0 ? [...prefixes].sort() : undefined,
|
|
272
|
-
items: items.length > 0 ? items
|
|
265
|
+
items: items.length > 0 ? items : undefined,
|
|
273
266
|
};
|
|
274
267
|
}
|
|
275
|
-
|
|
268
|
+
createDownloadToken(request) {
|
|
276
269
|
if (!this._adminCredsValidator.validate(request.authorization)) {
|
|
277
270
|
throw new errors_1.ForbiddenError();
|
|
278
271
|
}
|
|
@@ -283,7 +276,7 @@ class StorageLayer {
|
|
|
283
276
|
metadata.addDownloadToken();
|
|
284
277
|
return metadata;
|
|
285
278
|
}
|
|
286
|
-
|
|
279
|
+
deleteDownloadToken(request) {
|
|
287
280
|
if (!this._adminCredsValidator.validate(request.authorization)) {
|
|
288
281
|
throw new errors_1.ForbiddenError();
|
|
289
282
|
}
|
|
@@ -13,19 +13,30 @@ const runtime_1 = require("./rules/runtime");
|
|
|
13
13
|
const utils_1 = require("./rules/utils");
|
|
14
14
|
const persistence_1 = require("./persistence");
|
|
15
15
|
const upload_1 = require("./upload");
|
|
16
|
+
const cloudFunctions_1 = require("./cloudFunctions");
|
|
16
17
|
class StorageEmulator {
|
|
17
18
|
constructor(args) {
|
|
18
19
|
this.args = args;
|
|
19
20
|
this._logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.STORAGE);
|
|
21
|
+
this._files = new Map();
|
|
22
|
+
this._buckets = new Map();
|
|
20
23
|
this._rulesRuntime = new runtime_1.StorageRulesRuntime();
|
|
21
24
|
this._rulesManager = (0, manager_1.createStorageRulesManager)(this.args.rules, this._rulesRuntime);
|
|
25
|
+
this._cloudFunctions = new cloudFunctions_1.StorageCloudFunctions(args.projectId);
|
|
22
26
|
this._persistence = new persistence_1.Persistence(this.getPersistenceTmpDir());
|
|
23
|
-
this._storageLayer = new files_1.StorageLayer(args.projectId, (0, utils_1.getRulesValidator)((resource) => this._rulesManager.getRuleset(resource)), (0, utils_1.getAdminCredentialValidator)(), this._persistence);
|
|
24
27
|
this._uploadService = new upload_1.UploadService(this._persistence);
|
|
28
|
+
const createStorageLayer = (rulesValidator) => {
|
|
29
|
+
return new files_1.StorageLayer(args.projectId, this._files, this._buckets, rulesValidator, (0, utils_1.getAdminCredentialValidator)(), this._persistence, this._cloudFunctions);
|
|
30
|
+
};
|
|
31
|
+
this._storageLayer = createStorageLayer((0, utils_1.getFirebaseRulesValidator)((resource) => this._rulesManager.getRuleset(resource)));
|
|
32
|
+
this._adminStorageLayer = createStorageLayer((0, utils_1.getAdminOnlyFirebaseRulesValidator)());
|
|
25
33
|
}
|
|
26
34
|
get storageLayer() {
|
|
27
35
|
return this._storageLayer;
|
|
28
36
|
}
|
|
37
|
+
get adminStorageLayer() {
|
|
38
|
+
return this._adminStorageLayer;
|
|
39
|
+
}
|
|
29
40
|
get uploadService() {
|
|
30
41
|
return this._uploadService;
|
|
31
42
|
}
|
|
@@ -36,7 +47,8 @@ class StorageEmulator {
|
|
|
36
47
|
return this._logger;
|
|
37
48
|
}
|
|
38
49
|
reset() {
|
|
39
|
-
this.
|
|
50
|
+
this._files.clear();
|
|
51
|
+
this._buckets.clear();
|
|
40
52
|
this._persistence.reset(this.getPersistenceTmpDir());
|
|
41
53
|
this._uploadService.reset();
|
|
42
54
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isPermitted = exports.getAdminCredentialValidator = exports.
|
|
3
|
+
exports.isPermitted = exports.getAdminCredentialValidator = exports.getAdminOnlyFirebaseRulesValidator = exports.getFirebaseRulesValidator = void 0;
|
|
4
4
|
const emulatorLogger_1 = require("../../emulatorLogger");
|
|
5
5
|
const types_1 = require("../../types");
|
|
6
|
-
function
|
|
6
|
+
function getFirebaseRulesValidator(rulesetProvider) {
|
|
7
7
|
return {
|
|
8
8
|
validate: async (path, bucketId, method, variableOverrides, authorization) => {
|
|
9
9
|
return await isPermitted({
|
|
@@ -16,7 +16,15 @@ function getRulesValidator(rulesetProvider) {
|
|
|
16
16
|
},
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
-
exports.
|
|
19
|
+
exports.getFirebaseRulesValidator = getFirebaseRulesValidator;
|
|
20
|
+
function getAdminOnlyFirebaseRulesValidator() {
|
|
21
|
+
return {
|
|
22
|
+
validate: (_path, _bucketId, _method, _variableOverrides, _authorization) => {
|
|
23
|
+
return Promise.resolve(true);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
exports.getAdminOnlyFirebaseRulesValidator = getAdminOnlyFirebaseRulesValidator;
|
|
20
28
|
function getAdminCredentialValidator() {
|
|
21
29
|
return { validate: isValidAdminCredentials };
|
|
22
30
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firebase-tools",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.5.0",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "firebase-tools",
|
|
9
|
-
"version": "10.
|
|
9
|
+
"version": "10.5.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@google-cloud/pubsub": "^2.18.4",
|
package/package.json
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ListResponse = exports.ListItem = void 0;
|
|
4
|
-
class ListItem {
|
|
5
|
-
constructor(name, bucket) {
|
|
6
|
-
this.name = name;
|
|
7
|
-
this.bucket = bucket;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
exports.ListItem = ListItem;
|
|
11
|
-
class ListResponse {
|
|
12
|
-
constructor(prefixes, items, nextPageToken) {
|
|
13
|
-
this.prefixes = prefixes;
|
|
14
|
-
this.items = items;
|
|
15
|
-
this.nextPageToken = nextPageToken;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
exports.ListResponse = ListResponse;
|