firebase-tools 10.4.0 → 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.
Files changed (45) hide show
  1. package/lib/accountExporter.js +95 -84
  2. package/lib/bin/firebase.js +1 -1
  3. package/lib/commands/emulators-start.js +6 -1
  4. package/lib/commands/ext-configure.js +4 -4
  5. package/lib/commands/ext-dev-emulators-start.js +5 -1
  6. package/lib/commands/ext-install.js +5 -4
  7. package/lib/commands/ext-update.js +2 -1
  8. package/lib/commands/functions-config-export.js +3 -1
  9. package/lib/config.js +11 -4
  10. package/lib/deploy/functions/checkIam.js +44 -1
  11. package/lib/deploy/functions/deploy.js +3 -7
  12. package/lib/deploy/functions/prepare.js +7 -5
  13. package/lib/deploy/functions/prepareFunctionsUpload.js +7 -13
  14. package/lib/deploy/functions/release/fabricator.js +13 -1
  15. package/lib/deploy/functions/release/index.js +1 -1
  16. package/lib/deploy/functions/services/firebaseAlerts.js +1 -17
  17. package/lib/deploy/functions/services/index.js +2 -1
  18. package/lib/deploy/hosting/deploy.js +10 -0
  19. package/lib/emulator/auth/operations.js +21 -20
  20. package/lib/emulator/auth/state.js +79 -43
  21. package/lib/emulator/commandUtils.js +72 -2
  22. package/lib/emulator/controller.js +23 -8
  23. package/lib/emulator/downloadableEmulators.js +18 -11
  24. package/lib/emulator/functionsEmulator.js +8 -18
  25. package/lib/emulator/functionsEmulatorShared.js +27 -1
  26. package/lib/emulator/shared/request.js +19 -0
  27. package/lib/emulator/storage/apis/firebase.js +20 -28
  28. package/lib/emulator/storage/apis/gcloud.js +69 -57
  29. package/lib/emulator/storage/files.js +42 -49
  30. package/lib/emulator/storage/index.js +14 -2
  31. package/lib/emulator/storage/rules/utils.js +11 -3
  32. package/lib/extensions/askUserForParam.js +43 -15
  33. package/lib/extensions/extensionsHelper.js +11 -2
  34. package/lib/extensions/paramHelper.js +7 -3
  35. package/lib/functions/projectConfig.js +34 -0
  36. package/lib/init/features/functions/index.js +4 -2
  37. package/lib/init/features/hosting/index.js +32 -41
  38. package/lib/init/features/index.js +22 -12
  39. package/lib/init/index.js +28 -11
  40. package/lib/requirePermissions.js +4 -1
  41. package/lib/serve/functions.js +5 -5
  42. package/npm-shrinkwrap.json +2 -2
  43. package/package.json +1 -1
  44. package/schema/firebase-config.json +93 -36
  45. package/lib/emulator/storage/list.js +0 -18
@@ -289,7 +289,7 @@ class FunctionsEmulator {
289
289
  });
290
290
  for (const definition of toSetup) {
291
291
  try {
292
- (0, validate_1.functionIdsAreValid)([definition]);
292
+ (0, validate_1.functionIdsAreValid)([Object.assign(Object.assign({}, definition), { id: definition.name })]);
293
293
  }
294
294
  catch (e) {
295
295
  this.logger.logLabeled("WARN", `functions[${definition.id}]`, `Invalid function id: ${e.message}`);
@@ -488,26 +488,16 @@ class FunctionsEmulator {
488
488
  return def.eventTrigger ? `${def.id}-${this.triggerGeneration}` : def.id;
489
489
  }
490
490
  getBackendInfo() {
491
- const cf3Triggers = Object.values(this.triggers)
492
- .filter((t) => !t.backend.extensionInstanceId)
493
- .map((t) => t.def);
491
+ const cf3Triggers = this.getCF3Triggers();
494
492
  return this.args.emulatableBackends.map((e) => {
495
- var _a;
496
- const envWithSecrets = Object.assign({}, e.env);
497
- for (const s of e.secretEnv) {
498
- envWithSecrets[s.key] = backend.secretVersionName(s);
499
- }
500
- return {
501
- directory: e.functionsDir,
502
- env: envWithSecrets,
503
- extensionInstanceId: e.extensionInstanceId,
504
- extension: e.extension,
505
- extensionVersion: e.extensionVersion,
506
- extensionSpec: e.extensionSpec,
507
- functionTriggers: (_a = e.predefinedTriggers) !== null && _a !== void 0 ? _a : cf3Triggers,
508
- };
493
+ return (0, functionsEmulatorShared_1.toBackendInfo)(e, cf3Triggers);
509
494
  });
510
495
  }
496
+ getCF3Triggers() {
497
+ return Object.values(this.triggers)
498
+ .filter((t) => !t.backend.extensionInstanceId)
499
+ .map((t) => t.def);
500
+ }
511
501
  addTriggerRecord(def, opts) {
512
502
  const key = this.getTriggerKey(def);
513
503
  this.triggers[key] = {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSecretLocalPath = exports.getSignatureType = exports.formatHost = exports.findModuleRoot = exports.waitForBody = exports.getServiceFromEventType = exports.getFunctionService = exports.getTemporarySocketPath = exports.getEmulatedTriggersFromDefinitions = exports.emulatedFunctionsByRegion = exports.emulatedFunctionsFromEndpoints = exports.EmulatedTrigger = exports.HttpConstants = void 0;
3
+ exports.toBackendInfo = exports.getSecretLocalPath = exports.getSignatureType = exports.formatHost = exports.findModuleRoot = exports.waitForBody = exports.getServiceFromEventType = exports.getFunctionService = exports.getTemporarySocketPath = exports.getEmulatedTriggersFromDefinitions = exports.emulatedFunctionsByRegion = exports.emulatedFunctionsFromEndpoints = exports.EmulatedTrigger = exports.HttpConstants = void 0;
4
4
  const _ = require("lodash");
5
5
  const os = require("os");
6
6
  const path = require("path");
@@ -10,6 +10,7 @@ const constants_1 = require("./constants");
10
10
  const proto_1 = require("../gcp/proto");
11
11
  const logger_1 = require("../logger");
12
12
  const manifest_1 = require("../extensions/manifest");
13
+ const extensionsHelper_1 = require("../extensions/extensionsHelper");
13
14
  const memoryLookup = {
14
15
  "128MB": 128,
15
16
  "256MB": 256,
@@ -242,3 +243,28 @@ function getSecretLocalPath(backend, projectDir) {
242
243
  return path.join(secretDirectory, secretsFile);
243
244
  }
244
245
  exports.getSecretLocalPath = getSecretLocalPath;
246
+ function toBackendInfo(e, cf3Triggers) {
247
+ var _a;
248
+ const envWithSecrets = Object.assign({}, e.env);
249
+ for (const s of e.secretEnv) {
250
+ envWithSecrets[s.key] = backend.secretVersionName(s);
251
+ }
252
+ let extensionVersion = e.extensionVersion;
253
+ if (extensionVersion) {
254
+ extensionVersion = (0, extensionsHelper_1.substituteParams)(extensionVersion, e.env);
255
+ }
256
+ let extensionSpec = e.extensionSpec;
257
+ if (extensionSpec) {
258
+ extensionSpec = (0, extensionsHelper_1.substituteParams)(extensionSpec, e.env);
259
+ }
260
+ return JSON.parse(JSON.stringify({
261
+ directory: e.functionsDir,
262
+ env: envWithSecrets,
263
+ extensionInstanceId: e.extensionInstanceId,
264
+ extension: e.extension,
265
+ extensionVersion: extensionVersion,
266
+ extensionSpec: extensionSpec,
267
+ functionTriggers: (_a = e.predefinedTriggers) !== null && _a !== void 0 ? _a : cf3Triggers,
268
+ }));
269
+ }
270
+ exports.toBackendInfo = toBackendInfo;
@@ -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.handleGetObject({
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 response;
123
+ let listResponse;
123
124
  try {
124
- response = await storageLayer.handleListObjects({
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(response);
145
- });
146
- const reqBodyToBuffer = async (req) => {
147
- if (req.body instanceof Buffer) {
148
- return Buffer.from(req.body);
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
- await new Promise((resolve) => {
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.handleUploadObject(upload);
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.handleUploadObject(upload);
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.handleCreateDownloadToken({
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.handleDeleteDownloadToken({
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.handleUpdateObjectMetadata({
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.handleDeleteObject({
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 { storageLayer, uploadService } = emulator;
17
+ const { adminStorageLayer, uploadService } = emulator;
17
18
  gcloudStorageAPI.use(/.*\/b\/(.+?)\/.*/, (req, res, next) => {
18
- storageLayer.createBucket(req.params[0]);
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 storageLayer.listBuckets(),
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 storageLayer.handleGetObject({
31
+ getObjectResponse = await adminStorageLayer.getObject({
31
32
  bucketId: req.params.bucketId,
32
33
  decodedObjectId: req.params.objectId,
33
- }, true);
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
- throw new Error("Request failed unexpectedly due to Firebase Rules.");
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 storageLayer.handleUpdateObjectMetadata({
53
+ updatedMetadata = await adminStorageLayer.updateObjectMetadata({
53
54
  bucketId: req.params.bucketId,
54
55
  decodedObjectId: req.params.objectId,
55
56
  metadata: req.body,
56
- }, true);
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
- throw new Error("Request failed unexpectedly due to Firebase Rules.");
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
- let maxRes = undefined;
71
- if (req.query.maxResults) {
72
- maxRes = +req.query.maxResults.toString();
73
- }
74
- const delimiter = req.query.delimiter ? req.query.delimiter.toString() : "";
75
- const pageToken = req.query.pageToken ? req.query.pageToken.toString() : undefined;
76
- const prefix = req.query.prefix ? req.query.prefix.toString() : "";
77
- const listResult = storageLayer.listItems(req.params.bucketId, prefix, delimiter, pageToken, maxRes);
78
- res.json(Object.assign(Object.assign({}, listResult), { kind: "#storage/objects" }));
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 storageLayer.handleDeleteObject({
98
+ await adminStorageLayer.deleteObject({
83
99
  bucketId: req.params.bucketId,
84
100
  decodedObjectId: req.params.objectId,
85
- }, true);
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
- throw new Error("Request failed unexpectedly due to Firebase Rules.");
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 storageLayer.handleUploadObject(upload, true);
136
+ metadata = await adminStorageLayer.uploadObject(upload);
136
137
  }
137
138
  catch (err) {
138
139
  if (err instanceof errors_1.ForbiddenError) {
139
- throw new Error("Request failed unexpectedly due to Firebase Rules.");
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 storageLayer.handleGetObject({
151
+ getObjectResponse = await adminStorageLayer.getObject({
151
152
  bucketId: req.params.bucketId,
152
153
  decodedObjectId: req.params.objectId,
153
- }, true);
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
- throw new Error("Request failed unexpectedly due to Firebase Rules.");
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 storageLayer.handleUploadObject(upload, true);
229
+ metadata = await adminStorageLayer.uploadObject(upload);
229
230
  }
230
231
  catch (err) {
231
232
  if (err instanceof errors_1.ForbiddenError) {
232
- throw new Error("Request failed unexpectedly due to Firebase Rules.");
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 storageLayer.handleGetObject({
242
+ getObjectResponse = await adminStorageLayer.getObject({
242
243
  bucketId: req.params.bucketId,
243
244
  decodedObjectId: req.params.objectId,
244
- }, true);
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
- throw new Error("Request failed unexpectedly due to Firebase Rules.");
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
- const metadata = storageLayer.copyFile(md, req.params.destBucketId, req.params.destObjectId, req.body);
266
- if (!metadata) {
267
- res.sendStatus(400);
268
- return;
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);