firebase-functions 3.24.0 → 4.0.0-rc.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/README.md +7 -9
- package/lib/bin/firebase-functions.js +13 -15
- package/lib/common/app.d.ts +14 -0
- package/lib/common/app.js +62 -0
- package/lib/common/change.d.ts +0 -5
- package/lib/common/change.js +5 -7
- package/lib/common/config.d.ts +6 -0
- package/lib/common/config.js +49 -0
- package/lib/common/debug.js +2 -2
- package/lib/common/encoding.d.ts +0 -8
- package/lib/common/encoding.js +6 -29
- package/lib/common/options.d.ts +14 -0
- package/lib/common/options.js +44 -0
- package/lib/common/params.d.ts +32 -0
- package/lib/common/params.js +23 -0
- package/lib/common/providers/database.d.ts +17 -19
- package/lib/common/providers/database.js +68 -39
- package/lib/common/providers/https.d.ts +11 -52
- package/lib/common/providers/https.js +115 -110
- package/lib/common/providers/identity.d.ts +8 -8
- package/lib/common/providers/identity.js +71 -79
- package/lib/common/providers/tasks.d.ts +11 -10
- package/lib/common/providers/tasks.js +10 -9
- package/lib/common/timezone.js +538 -538
- package/lib/common/trace.d.ts +14 -0
- package/lib/common/trace.js +69 -0
- package/lib/{encoder.d.ts → common/utilities/encoder.d.ts} +0 -0
- package/lib/{encoder.js → common/utilities/encoder.js} +1 -1
- package/lib/{utilities → common/utilities}/path-pattern.d.ts +0 -0
- package/lib/{utilities → common/utilities}/path-pattern.js +17 -16
- package/lib/{utilities → common/utilities}/path.d.ts +0 -0
- package/lib/{utilities → common/utilities}/path.js +5 -7
- package/lib/{utils.d.ts → common/utilities/utils.d.ts} +1 -1
- package/lib/{utils.js → common/utilities/utils.js} +18 -12
- package/lib/logger/common.d.ts +1 -3
- package/lib/logger/common.js +9 -14
- package/lib/logger/compat.js +9 -9
- package/lib/logger/index.d.ts +1 -1
- package/lib/logger/index.js +24 -30
- package/lib/{v2/params → params}/index.d.ts +22 -9
- package/lib/{v2/params → params}/index.js +22 -14
- package/lib/params/types.d.ts +180 -0
- package/lib/params/types.js +289 -0
- package/lib/runtime/loader.js +12 -14
- package/lib/runtime/manifest.d.ts +56 -24
- package/lib/runtime/manifest.js +114 -4
- package/lib/v1/cloud-functions.d.ts +232 -0
- package/lib/v1/cloud-functions.js +205 -0
- package/lib/v1/config.d.ts +8 -0
- package/lib/v1/config.js +75 -0
- package/lib/{function-builder.d.ts → v1/function-builder.d.ts} +16 -16
- package/lib/{function-builder.js → v1/function-builder.js} +56 -46
- package/lib/v1/function-configuration.d.ts +197 -0
- package/lib/v1/function-configuration.js +70 -0
- package/lib/v1/index.d.ts +20 -0
- package/lib/{index.js → v1/index.js} +5 -10
- package/lib/{providers → v1/providers}/analytics.d.ts +5 -11
- package/lib/{providers → v1/providers}/analytics.js +49 -43
- package/lib/{providers → v1/providers}/auth.d.ts +28 -18
- package/lib/{providers → v1/providers}/auth.js +45 -34
- package/lib/{providers → v1/providers}/database.d.ts +25 -42
- package/lib/{providers → v1/providers}/database.js +46 -46
- package/lib/{providers → v1/providers}/firestore.d.ts +15 -33
- package/lib/{providers → v1/providers}/firestore.js +40 -44
- package/lib/{providers → v1/providers}/https.d.ts +3 -8
- package/lib/{providers → v1/providers}/https.js +14 -22
- package/lib/{providers → v1/providers}/pubsub.d.ts +8 -16
- package/lib/{providers → v1/providers}/pubsub.js +22 -26
- package/lib/{providers → v1/providers}/remoteConfig.d.ts +2 -11
- package/lib/{providers → v1/providers}/remoteConfig.js +9 -9
- package/lib/{providers → v1/providers}/storage.d.ts +11 -26
- package/lib/{providers → v1/providers}/storage.js +24 -29
- package/lib/{providers → v1/providers}/tasks.d.ts +6 -8
- package/lib/{providers → v1/providers}/tasks.js +12 -17
- package/lib/{providers → v1/providers}/testLab.d.ts +86 -46
- package/lib/{providers → v1/providers}/testLab.js +14 -14
- package/lib/v2/core.d.ts +4 -5
- package/lib/v2/index.d.ts +16 -14
- package/lib/v2/index.js +5 -1
- package/lib/v2/options.d.ts +52 -32
- package/lib/v2/options.js +32 -47
- package/lib/v2/providers/alerts/alerts.d.ts +20 -18
- package/lib/v2/providers/alerts/alerts.js +9 -6
- package/lib/v2/providers/alerts/appDistribution.d.ts +36 -26
- package/lib/v2/providers/alerts/appDistribution.js +10 -7
- package/lib/v2/providers/alerts/billing.d.ts +5 -5
- package/lib/v2/providers/alerts/billing.js +5 -4
- package/lib/v2/providers/alerts/crashlytics.d.ts +32 -30
- package/lib/v2/providers/alerts/crashlytics.js +10 -9
- package/lib/v2/providers/alerts/index.d.ts +5 -5
- package/lib/v2/providers/alerts/performance.d.ts +15 -3
- package/lib/v2/providers/alerts/performance.js +5 -7
- package/lib/v2/providers/database.d.ts +41 -38
- package/lib/v2/providers/database.js +22 -17
- package/lib/v2/providers/eventarc.d.ts +25 -23
- package/lib/v2/providers/eventarc.js +10 -7
- package/lib/v2/providers/https.d.ts +43 -33
- package/lib/v2/providers/https.js +18 -56
- package/lib/v2/providers/identity.d.ts +25 -23
- package/lib/v2/providers/identity.js +10 -7
- package/lib/v2/providers/pubsub.d.ts +25 -23
- package/lib/v2/providers/pubsub.js +11 -27
- package/lib/v2/providers/remoteConfig.d.ts +63 -0
- package/lib/v2/providers/remoteConfig.js +65 -0
- package/lib/v2/providers/scheduler.d.ts +14 -12
- package/lib/v2/providers/scheduler.js +16 -14
- package/lib/v2/providers/storage.d.ts +32 -30
- package/lib/v2/providers/storage.js +16 -32
- package/lib/v2/providers/tasks.d.ts +30 -26
- package/lib/v2/providers/tasks.js +14 -31
- package/lib/v2/providers/testLab.d.ts +110 -0
- package/lib/v2/providers/testLab.js +65 -0
- package/lib/v2/trace.d.ts +4 -0
- package/lib/v2/trace.js +21 -0
- package/package.json +62 -67
- package/lib/apps.d.ts +0 -35
- package/lib/apps.js +0 -112
- package/lib/cloud-functions.d.ts +0 -231
- package/lib/cloud-functions.js +0 -251
- package/lib/config.d.ts +0 -24
- package/lib/config.js +0 -117
- package/lib/function-configuration.d.ts +0 -108
- package/lib/function-configuration.js +0 -71
- package/lib/handler-builder.d.ts +0 -256
- package/lib/handler-builder.js +0 -349
- package/lib/index.d.ts +0 -19
- package/lib/setup.d.ts +0 -1
- package/lib/setup.js +0 -60
- package/lib/v2/params/types.d.ts +0 -118
- package/lib/v2/params/types.js +0 -196
|
@@ -22,32 +22,33 @@
|
|
|
22
22
|
// SOFTWARE.
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.wrapHandler = exports.getUpdateMask = exports.validateAuthResponse = exports.parseAuthEventContext = exports.parseAuthUserRecord = exports.parseMultiFactor = exports.parseDate = exports.parseProviderData = exports.parseMetadata = exports.isValidRequest = exports.userRecordConstructor = exports.UserRecordMetadata = exports.HttpsError = void 0;
|
|
25
|
-
const
|
|
26
|
-
const
|
|
25
|
+
const auth = require("firebase-admin/auth");
|
|
26
|
+
const logger = require("../../logger");
|
|
27
|
+
const app_1 = require("../app");
|
|
27
28
|
const debug_1 = require("../debug");
|
|
28
29
|
const https_1 = require("./https");
|
|
29
30
|
Object.defineProperty(exports, "HttpsError", { enumerable: true, get: function () { return https_1.HttpsError; } });
|
|
30
31
|
const DISALLOWED_CUSTOM_CLAIMS = [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
"acr",
|
|
33
|
+
"amr",
|
|
34
|
+
"at_hash",
|
|
35
|
+
"aud",
|
|
36
|
+
"auth_time",
|
|
37
|
+
"azp",
|
|
38
|
+
"cnf",
|
|
39
|
+
"c_hash",
|
|
40
|
+
"exp",
|
|
41
|
+
"iat",
|
|
42
|
+
"iss",
|
|
43
|
+
"jti",
|
|
44
|
+
"nbf",
|
|
45
|
+
"nonce",
|
|
46
|
+
"firebase",
|
|
46
47
|
];
|
|
47
48
|
const CLAIMS_MAX_PAYLOAD_SIZE = 1000;
|
|
48
49
|
const EVENT_MAPPING = {
|
|
49
|
-
beforeCreate:
|
|
50
|
-
beforeSignIn:
|
|
50
|
+
beforeCreate: "providers/cloud.auth/eventTypes/user.beforeCreate",
|
|
51
|
+
beforeSignIn: "providers/cloud.auth/eventTypes/user.beforeSignIn",
|
|
51
52
|
};
|
|
52
53
|
/**
|
|
53
54
|
* Helper class to create the user metadata in a UserRecord object
|
|
@@ -126,17 +127,17 @@ exports.userRecordConstructor = userRecordConstructor;
|
|
|
126
127
|
*/
|
|
127
128
|
function isValidRequest(req) {
|
|
128
129
|
var _a, _b;
|
|
129
|
-
if (req.method !==
|
|
130
|
-
|
|
130
|
+
if (req.method !== "POST") {
|
|
131
|
+
logger.warn(`Request has invalid method "${req.method}".`);
|
|
131
132
|
return false;
|
|
132
133
|
}
|
|
133
|
-
const contentType = (req.header(
|
|
134
|
-
if (!contentType.includes(
|
|
135
|
-
|
|
134
|
+
const contentType = (req.header("Content-Type") || "").toLowerCase();
|
|
135
|
+
if (!contentType.includes("application/json")) {
|
|
136
|
+
logger.warn("Request has invalid header Content-Type.");
|
|
136
137
|
return false;
|
|
137
138
|
}
|
|
138
139
|
if (!((_b = (_a = req.body) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.jwt)) {
|
|
139
|
-
|
|
140
|
+
logger.warn("Request has an invalid body.");
|
|
140
141
|
return false;
|
|
141
142
|
}
|
|
142
143
|
return true;
|
|
@@ -205,7 +206,9 @@ function parseDate(tokensValidAfterTime) {
|
|
|
205
206
|
return date.toUTCString();
|
|
206
207
|
}
|
|
207
208
|
}
|
|
208
|
-
catch
|
|
209
|
+
catch {
|
|
210
|
+
// ignore error
|
|
211
|
+
}
|
|
209
212
|
return null;
|
|
210
213
|
}
|
|
211
214
|
exports.parseDate = parseDate;
|
|
@@ -220,16 +223,14 @@ function parseMultiFactor(multiFactor) {
|
|
|
220
223
|
const parsedEnrolledFactors = [];
|
|
221
224
|
for (const factor of multiFactor.enrolled_factors || []) {
|
|
222
225
|
if (!factor.uid) {
|
|
223
|
-
throw new https_1.HttpsError(
|
|
226
|
+
throw new https_1.HttpsError("internal", "INTERNAL ASSERT FAILED: Invalid multi-factor info response");
|
|
224
227
|
}
|
|
225
228
|
const enrollmentTime = factor.enrollment_time
|
|
226
229
|
? new Date(factor.enrollment_time).toUTCString()
|
|
227
230
|
: null;
|
|
228
231
|
parsedEnrolledFactors.push({
|
|
229
232
|
uid: factor.uid,
|
|
230
|
-
factorId: factor.phone_number
|
|
231
|
-
? factor.factor_id || 'phone'
|
|
232
|
-
: factor.factor_id,
|
|
233
|
+
factorId: factor.phone_number ? factor.factor_id || "phone" : factor.factor_id,
|
|
233
234
|
displayName: factor.display_name,
|
|
234
235
|
enrollmentTime,
|
|
235
236
|
phoneNumber: factor.phone_number,
|
|
@@ -249,7 +250,7 @@ exports.parseMultiFactor = parseMultiFactor;
|
|
|
249
250
|
*/
|
|
250
251
|
function parseAuthUserRecord(decodedJWTUserRecord) {
|
|
251
252
|
if (!decodedJWTUserRecord.uid) {
|
|
252
|
-
throw new https_1.HttpsError(
|
|
253
|
+
throw new https_1.HttpsError("internal", "INTERNAL ASSERT FAILED: Invalid user response");
|
|
253
254
|
}
|
|
254
255
|
const disabled = decodedJWTUserRecord.disabled || false;
|
|
255
256
|
const metadata = parseMetadata(decodedJWTUserRecord.metadata);
|
|
@@ -277,30 +278,29 @@ function parseAuthUserRecord(decodedJWTUserRecord) {
|
|
|
277
278
|
exports.parseAuthUserRecord = parseAuthUserRecord;
|
|
278
279
|
/** Helper to get the AdditionalUserInfo from the decoded jwt */
|
|
279
280
|
function parseAdditionalUserInfo(decodedJWT) {
|
|
280
|
-
let profile
|
|
281
|
+
let profile;
|
|
282
|
+
let username;
|
|
281
283
|
if (decodedJWT.raw_user_info) {
|
|
282
284
|
try {
|
|
283
285
|
profile = JSON.parse(decodedJWT.raw_user_info);
|
|
284
286
|
}
|
|
285
287
|
catch (err) {
|
|
286
|
-
|
|
288
|
+
logger.debug(`Parse Error: ${err.message}`);
|
|
287
289
|
}
|
|
288
290
|
}
|
|
289
291
|
if (profile) {
|
|
290
|
-
if (decodedJWT.sign_in_method ===
|
|
292
|
+
if (decodedJWT.sign_in_method === "github.com") {
|
|
291
293
|
username = profile.login;
|
|
292
294
|
}
|
|
293
|
-
if (decodedJWT.sign_in_method ===
|
|
295
|
+
if (decodedJWT.sign_in_method === "twitter.com") {
|
|
294
296
|
username = profile.screen_name;
|
|
295
297
|
}
|
|
296
298
|
}
|
|
297
299
|
return {
|
|
298
|
-
providerId: decodedJWT.sign_in_method ===
|
|
299
|
-
? 'password'
|
|
300
|
-
: decodedJWT.sign_in_method,
|
|
300
|
+
providerId: decodedJWT.sign_in_method === "emailLink" ? "password" : decodedJWT.sign_in_method,
|
|
301
301
|
profile,
|
|
302
302
|
username,
|
|
303
|
-
isNewUser: decodedJWT.event_type ===
|
|
303
|
+
isNewUser: decodedJWT.event_type === "beforeCreate" ? true : false,
|
|
304
304
|
};
|
|
305
305
|
}
|
|
306
306
|
/** Helper to get the Credential from the decoded jwt */
|
|
@@ -320,9 +320,7 @@ function parseAuthCredential(decodedJWT, time) {
|
|
|
320
320
|
? new Date(time + decodedJWT.oauth_expires_in * 1000).toUTCString()
|
|
321
321
|
: undefined,
|
|
322
322
|
secret: decodedJWT.oauth_token_secret,
|
|
323
|
-
providerId: decodedJWT.sign_in_method ===
|
|
324
|
-
? 'password'
|
|
325
|
-
: decodedJWT.sign_in_method,
|
|
323
|
+
providerId: decodedJWT.sign_in_method === "emailLink" ? "password" : decodedJWT.sign_in_method,
|
|
326
324
|
signInMethod: decodedJWT.sign_in_method,
|
|
327
325
|
};
|
|
328
326
|
}
|
|
@@ -332,18 +330,18 @@ function parseAuthCredential(decodedJWT, time) {
|
|
|
332
330
|
*/
|
|
333
331
|
function parseAuthEventContext(decodedJWT, projectId, time = new Date().getTime()) {
|
|
334
332
|
const eventType = (EVENT_MAPPING[decodedJWT.event_type] || decodedJWT.event_type) +
|
|
335
|
-
(decodedJWT.sign_in_method ? `:${decodedJWT.sign_in_method}` :
|
|
333
|
+
(decodedJWT.sign_in_method ? `:${decodedJWT.sign_in_method}` : "");
|
|
336
334
|
return {
|
|
337
335
|
locale: decodedJWT.locale,
|
|
338
336
|
ipAddress: decodedJWT.ip_address,
|
|
339
337
|
userAgent: decodedJWT.user_agent,
|
|
340
338
|
eventId: decodedJWT.event_id,
|
|
341
339
|
eventType,
|
|
342
|
-
authType:
|
|
340
|
+
authType: decodedJWT.user_record ? "USER" : "UNAUTHENTICATED",
|
|
343
341
|
resource: {
|
|
344
342
|
// TODO(colerogers): figure out the correct service
|
|
345
|
-
service:
|
|
346
|
-
name:
|
|
343
|
+
service: "identitytoolkit.googleapis.com",
|
|
344
|
+
name: decodedJWT.tenant_id
|
|
347
345
|
? `projects/${projectId}/tenants/${decodedJWT.tenant_id}`
|
|
348
346
|
: `projects/${projectId}`,
|
|
349
347
|
},
|
|
@@ -365,28 +363,27 @@ function validateAuthResponse(eventType, authRequest) {
|
|
|
365
363
|
if (authRequest.customClaims) {
|
|
366
364
|
const invalidClaims = DISALLOWED_CUSTOM_CLAIMS.filter((claim) => authRequest.customClaims.hasOwnProperty(claim));
|
|
367
365
|
if (invalidClaims.length > 0) {
|
|
368
|
-
throw new https_1.HttpsError(
|
|
366
|
+
throw new https_1.HttpsError("invalid-argument", `The customClaims claims "${invalidClaims.join(",")}" are reserved and cannot be specified.`);
|
|
369
367
|
}
|
|
370
368
|
if (JSON.stringify(authRequest.customClaims).length > CLAIMS_MAX_PAYLOAD_SIZE) {
|
|
371
|
-
throw new https_1.HttpsError(
|
|
369
|
+
throw new https_1.HttpsError("invalid-argument", `The customClaims payload should not exceed ${CLAIMS_MAX_PAYLOAD_SIZE} characters.`);
|
|
372
370
|
}
|
|
373
371
|
}
|
|
374
|
-
if (eventType ===
|
|
375
|
-
authRequest.sessionClaims) {
|
|
372
|
+
if (eventType === "beforeSignIn" && authRequest.sessionClaims) {
|
|
376
373
|
const invalidClaims = DISALLOWED_CUSTOM_CLAIMS.filter((claim) => authRequest.sessionClaims.hasOwnProperty(claim));
|
|
377
374
|
if (invalidClaims.length > 0) {
|
|
378
|
-
throw new https_1.HttpsError(
|
|
375
|
+
throw new https_1.HttpsError("invalid-argument", `The sessionClaims claims "${invalidClaims.join(",")}" are reserved and cannot be specified.`);
|
|
379
376
|
}
|
|
380
|
-
if (JSON.stringify(authRequest.sessionClaims)
|
|
381
|
-
|
|
382
|
-
throw new https_1.HttpsError(
|
|
377
|
+
if (JSON.stringify(authRequest.sessionClaims).length >
|
|
378
|
+
CLAIMS_MAX_PAYLOAD_SIZE) {
|
|
379
|
+
throw new https_1.HttpsError("invalid-argument", `The sessionClaims payload should not exceed ${CLAIMS_MAX_PAYLOAD_SIZE} characters.`);
|
|
383
380
|
}
|
|
384
381
|
const combinedClaims = {
|
|
385
382
|
...authRequest.customClaims,
|
|
386
383
|
...authRequest.sessionClaims,
|
|
387
384
|
};
|
|
388
385
|
if (JSON.stringify(combinedClaims).length > CLAIMS_MAX_PAYLOAD_SIZE) {
|
|
389
|
-
throw new https_1.HttpsError(
|
|
386
|
+
throw new https_1.HttpsError("invalid-argument", `The customClaims and sessionClaims payloads should not exceed ${CLAIMS_MAX_PAYLOAD_SIZE} characters combined.`);
|
|
390
387
|
}
|
|
391
388
|
}
|
|
392
389
|
}
|
|
@@ -397,16 +394,15 @@ exports.validateAuthResponse = validateAuthResponse;
|
|
|
397
394
|
*/
|
|
398
395
|
function getUpdateMask(authResponse) {
|
|
399
396
|
if (!authResponse) {
|
|
400
|
-
return
|
|
397
|
+
return "";
|
|
401
398
|
}
|
|
402
399
|
const updateMask = [];
|
|
403
400
|
for (const key in authResponse) {
|
|
404
|
-
if (authResponse.hasOwnProperty(key) &&
|
|
405
|
-
typeof authResponse[key] !== 'undefined') {
|
|
401
|
+
if (authResponse.hasOwnProperty(key) && typeof authResponse[key] !== "undefined") {
|
|
406
402
|
updateMask.push(key);
|
|
407
403
|
}
|
|
408
404
|
}
|
|
409
|
-
return updateMask.join(
|
|
405
|
+
return updateMask.join(",");
|
|
410
406
|
}
|
|
411
407
|
exports.getUpdateMask = getUpdateMask;
|
|
412
408
|
/** @internal */
|
|
@@ -415,28 +411,23 @@ function wrapHandler(eventType, handler) {
|
|
|
415
411
|
try {
|
|
416
412
|
const projectId = process.env.GCLOUD_PROJECT;
|
|
417
413
|
if (!isValidRequest(req)) {
|
|
418
|
-
|
|
419
|
-
throw new https_1.HttpsError(
|
|
414
|
+
logger.error("Invalid request, unable to process");
|
|
415
|
+
throw new https_1.HttpsError("invalid-argument", "Bad Request");
|
|
420
416
|
}
|
|
421
|
-
if (!(0,
|
|
422
|
-
throw new Error(
|
|
417
|
+
if (!auth.getAuth((0, app_1.getApp)())._verifyAuthBlockingToken) {
|
|
418
|
+
throw new Error("Cannot validate Auth Blocking token. Please update Firebase Admin SDK to >= v10.1.0");
|
|
423
419
|
}
|
|
424
|
-
const decodedPayload = (0, debug_1.isDebugFeatureEnabled)(
|
|
420
|
+
const decodedPayload = (0, debug_1.isDebugFeatureEnabled)("skipTokenVerification")
|
|
425
421
|
? unsafeDecodeAuthBlockingToken(req.body.data.jwt)
|
|
426
422
|
: handler.length === 2
|
|
427
|
-
? await (0,
|
|
428
|
-
|
|
429
|
-
._verifyAuthBlockingToken(req.body.data.jwt)
|
|
430
|
-
: await (0, apps_1.apps)()
|
|
431
|
-
.admin.auth()
|
|
432
|
-
._verifyAuthBlockingToken(req.body.data.jwt, 'run.app');
|
|
423
|
+
? await auth.getAuth((0, app_1.getApp)())._verifyAuthBlockingToken(req.body.data.jwt)
|
|
424
|
+
: await auth.getAuth((0, app_1.getApp)())._verifyAuthBlockingToken(req.body.data.jwt, "run.app");
|
|
433
425
|
const authUserRecord = parseAuthUserRecord(decodedPayload.user_record);
|
|
434
426
|
const authEventContext = parseAuthEventContext(decodedPayload, projectId);
|
|
435
427
|
let authResponse;
|
|
436
428
|
if (handler.length === 2) {
|
|
437
429
|
authResponse =
|
|
438
|
-
(await handler(authUserRecord, authEventContext)) ||
|
|
439
|
-
undefined;
|
|
430
|
+
(await handler(authUserRecord, authEventContext)) || undefined;
|
|
440
431
|
}
|
|
441
432
|
else {
|
|
442
433
|
authResponse =
|
|
@@ -456,18 +447,19 @@ function wrapHandler(eventType, handler) {
|
|
|
456
447
|
},
|
|
457
448
|
};
|
|
458
449
|
res.status(200);
|
|
459
|
-
res.setHeader(
|
|
450
|
+
res.setHeader("Content-Type", "application/json");
|
|
460
451
|
res.send(JSON.stringify(result));
|
|
461
452
|
}
|
|
462
453
|
catch (err) {
|
|
463
|
-
|
|
454
|
+
let httpErr = err;
|
|
455
|
+
if (!(httpErr instanceof https_1.HttpsError)) {
|
|
464
456
|
// This doesn't count as an 'explicit' error.
|
|
465
|
-
|
|
466
|
-
|
|
457
|
+
logger.error("Unhandled error", err);
|
|
458
|
+
httpErr = new https_1.HttpsError("internal", "An unexpected error occurred.");
|
|
467
459
|
}
|
|
468
|
-
const { status } =
|
|
469
|
-
const body = { error:
|
|
470
|
-
res.setHeader(
|
|
460
|
+
const { status } = httpErr.httpErrorCode;
|
|
461
|
+
const body = { error: httpErr.toJSON() };
|
|
462
|
+
res.setHeader("Content-Type", "application/json");
|
|
471
463
|
res.status(status).send(body);
|
|
472
464
|
}
|
|
473
465
|
};
|
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Expression } from
|
|
1
|
+
import { DecodedIdToken } from "firebase-admin/auth";
|
|
2
|
+
import { Expression } from "../../params";
|
|
3
|
+
import { ResetValue } from "../options";
|
|
3
4
|
/** How a task should be retried in the event of a non-2xx return. */
|
|
4
5
|
export interface RetryConfig {
|
|
5
6
|
/**
|
|
6
7
|
* Maximum number of times a request should be attempted.
|
|
7
8
|
* If left unspecified, will default to 3.
|
|
8
9
|
*/
|
|
9
|
-
maxAttempts?: number | Expression<number> |
|
|
10
|
+
maxAttempts?: number | Expression<number> | ResetValue;
|
|
10
11
|
/**
|
|
11
12
|
* Maximum amount of time for retrying failed task.
|
|
12
13
|
* If left unspecified will retry indefinitely.
|
|
13
14
|
*/
|
|
14
|
-
maxRetrySeconds?: number | Expression<number> |
|
|
15
|
+
maxRetrySeconds?: number | Expression<number> | ResetValue;
|
|
15
16
|
/**
|
|
16
17
|
* The maximum amount of time to wait between attempts.
|
|
17
18
|
* If left unspecified will default to 1hr.
|
|
18
19
|
*/
|
|
19
|
-
maxBackoffSeconds?: number | Expression<number> |
|
|
20
|
+
maxBackoffSeconds?: number | Expression<number> | ResetValue;
|
|
20
21
|
/**
|
|
21
22
|
* The maximum number of times to double the backoff between
|
|
22
23
|
* retries. If left unspecified will default to 16.
|
|
23
24
|
*/
|
|
24
|
-
maxDoublings?: number | Expression<number> |
|
|
25
|
+
maxDoublings?: number | Expression<number> | ResetValue;
|
|
25
26
|
/**
|
|
26
27
|
* The minimum time to wait between attempts. If left unspecified
|
|
27
28
|
* will default to 100ms.
|
|
28
29
|
*/
|
|
29
|
-
minBackoffSeconds?: number | Expression<number> |
|
|
30
|
+
minBackoffSeconds?: number | Expression<number> | ResetValue;
|
|
30
31
|
}
|
|
31
32
|
/** How congestion control should be applied to the function. */
|
|
32
33
|
export interface RateLimits {
|
|
@@ -34,17 +35,17 @@ export interface RateLimits {
|
|
|
34
35
|
* The maximum number of requests that can be outstanding at a time.
|
|
35
36
|
* If left unspecified, will default to 1000.
|
|
36
37
|
*/
|
|
37
|
-
maxConcurrentDispatches?: number | Expression<number> |
|
|
38
|
+
maxConcurrentDispatches?: number | Expression<number> | ResetValue;
|
|
38
39
|
/**
|
|
39
40
|
* The maximum number of requests that can be invoked per second.
|
|
40
41
|
* If left unspecified, will default to 500.
|
|
41
42
|
*/
|
|
42
|
-
maxDispatchesPerSecond?: number | Expression<number> |
|
|
43
|
+
maxDispatchesPerSecond?: number | Expression<number> | ResetValue;
|
|
43
44
|
}
|
|
44
45
|
/** Metadata about the authorization used to invoke a function. */
|
|
45
46
|
export interface AuthData {
|
|
46
47
|
uid: string;
|
|
47
|
-
token:
|
|
48
|
+
token: DecodedIdToken;
|
|
48
49
|
}
|
|
49
50
|
/** Metadata about a call to a Task Queue function. */
|
|
50
51
|
export interface TaskContext {
|
|
@@ -30,19 +30,19 @@ function onDispatchHandler(handler) {
|
|
|
30
30
|
var _a;
|
|
31
31
|
try {
|
|
32
32
|
if (!https.isValidRequest(req)) {
|
|
33
|
-
logger.error(
|
|
34
|
-
throw new https.HttpsError(
|
|
33
|
+
logger.error("Invalid request, unable to process.");
|
|
34
|
+
throw new https.HttpsError("invalid-argument", "Bad Request");
|
|
35
35
|
}
|
|
36
36
|
const context = {};
|
|
37
37
|
if (!process.env.FUNCTIONS_EMULATOR) {
|
|
38
|
-
const authHeader = req.header(
|
|
38
|
+
const authHeader = req.header("Authorization") || "";
|
|
39
39
|
const token = (_a = authHeader.match(/^Bearer (.*)$/)) === null || _a === void 0 ? void 0 : _a[1];
|
|
40
40
|
// Note: this should never happen since task queue functions are guarded by IAM.
|
|
41
41
|
if (!token) {
|
|
42
|
-
throw new https.HttpsError(
|
|
42
|
+
throw new https.HttpsError("unauthenticated", "Unauthenticated");
|
|
43
43
|
}
|
|
44
44
|
// We skip authenticating the token since tq functions are guarded by IAM.
|
|
45
|
-
const authToken =
|
|
45
|
+
const authToken = https.unsafeDecodeIdToken(token);
|
|
46
46
|
context.auth = {
|
|
47
47
|
uid: authToken.uid,
|
|
48
48
|
token: authToken,
|
|
@@ -64,13 +64,14 @@ function onDispatchHandler(handler) {
|
|
|
64
64
|
res.status(204).end();
|
|
65
65
|
}
|
|
66
66
|
catch (err) {
|
|
67
|
+
let httpErr = err;
|
|
67
68
|
if (!(err instanceof https.HttpsError)) {
|
|
68
69
|
// This doesn't count as an 'explicit' error.
|
|
69
|
-
logger.error(
|
|
70
|
-
|
|
70
|
+
logger.error("Unhandled error", err);
|
|
71
|
+
httpErr = new https.HttpsError("internal", "INTERNAL");
|
|
71
72
|
}
|
|
72
|
-
const { status } =
|
|
73
|
-
const body = { error:
|
|
73
|
+
const { status } = httpErr.httpErrorCode;
|
|
74
|
+
const body = { error: httpErr.toJSON() };
|
|
74
75
|
res.status(status).send(body);
|
|
75
76
|
}
|
|
76
77
|
};
|