@dereekb/firebase-server 13.36.0 → 13.38.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/calcom/package.json +10 -10
- package/discord/package.json +10 -10
- package/index.cjs.js +1732 -510
- package/index.esm.js +1717 -513
- package/mailgun/package.json +9 -9
- package/mcp/index.cjs.js +913 -167
- package/mcp/index.esm.js +906 -166
- package/mcp/package.json +13 -12
- package/mcp/src/lib/controller/mcp.controller.d.ts +28 -3
- package/mcp/src/lib/controller/mcp.wellknown.controller.d.ts +21 -1
- package/mcp/src/lib/mcp.config.d.ts +31 -8
- package/mcp/src/lib/mcp.module.d.ts +2 -1
- package/mcp/src/lib/service/index.d.ts +1 -0
- package/mcp/src/lib/service/mcp.server.factory.d.ts +8 -6
- package/mcp/src/lib/service/mcp.tool-generator.d.ts +1 -1
- package/mcp/src/lib/service/mcp.visibility.d.ts +1 -1
- package/mcp/src/lib/service/tools/mcp.tool.model-roles.d.ts +95 -0
- package/mcp/src/lib/transport/streamable-http.transport.d.ts +16 -11
- package/model/index.cjs.js +1 -1
- package/model/index.esm.js +1 -1
- package/model/package.json +9 -9
- package/oidc/index.cjs.js +257 -67
- package/oidc/index.esm.js +256 -69
- package/oidc/package.json +10 -10
- package/oidc/src/lib/profile.d.ts +21 -0
- package/oidc/src/lib/service/index.d.ts +1 -0
- package/oidc/src/lib/service/oidc.config.service.d.ts +14 -0
- package/oidc/src/lib/service/oidc.interaction-policy.d.ts +35 -0
- package/oidc/src/lib/service/oidc.service.d.ts +29 -0
- package/package.json +14 -13
- package/src/lib/env/env.service.d.ts +27 -3
- package/src/lib/nest/controller/api.scope.d.ts +63 -0
- package/src/lib/nest/controller/index.d.ts +2 -0
- package/src/lib/nest/controller/model/model.api.get.service.d.ts +146 -1
- package/src/lib/nest/controller/model/model.api.scope.d.ts +3 -2
- package/src/lib/nest/controller/session/index.d.ts +4 -0
- package/src/lib/nest/controller/session/session.api.config.d.ts +104 -0
- package/src/lib/nest/controller/session/session.api.controller.d.ts +26 -0
- package/src/lib/nest/controller/session/session.api.module.d.ts +49 -0
- package/src/lib/nest/controller/session/session.api.service.d.ts +71 -0
- package/test/index.cjs.js +8 -8
- package/test/index.esm.js +8 -8
- package/test/package.json +11 -11
- package/twilio/package.json +8 -8
- package/zoho/package.json +10 -10
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ModuleMetadata } from '@nestjs/common';
|
|
2
|
+
import { type ClassType } from '@dereekb/util';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for {@link sessionApiModuleMetadata}.
|
|
5
|
+
*/
|
|
6
|
+
export interface SessionApiModuleMetadataConfig extends Pick<ModuleMetadata, 'imports' | 'exports' | 'providers'> {
|
|
7
|
+
/**
|
|
8
|
+
* Module that exports the session endpoint's dependencies.
|
|
9
|
+
*
|
|
10
|
+
* Should provide:
|
|
11
|
+
* - `FIRESTORE_SESSION_ADMIN_PREDICATE` — the app's admin check. Without it the endpoint rejects
|
|
12
|
+
* EVERY caller (fail-closed), and logs a warning at boot.
|
|
13
|
+
* - {@link SessionApiModuleConfig} — the registered web app's `appId` to mint App Check tokens for,
|
|
14
|
+
* plus optional TTL / scope overrides. Without it sessions carry no App Check attestation.
|
|
15
|
+
*
|
|
16
|
+
* `FIREBASE_APP_TOKEN` is not listed because `nestServerInstance` provides it globally.
|
|
17
|
+
*/
|
|
18
|
+
readonly dependencyModule: ClassType;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Generates NestJS module metadata for the direct-Firestore session API.
|
|
22
|
+
*
|
|
23
|
+
* Mirrors the convention used by `modelApiModuleMetadata` and `mcpModuleMetadata`: the consumer
|
|
24
|
+
* provides a dependency module exposing the required tokens, and this factory wires the controller +
|
|
25
|
+
* service.
|
|
26
|
+
*
|
|
27
|
+
* Remember to add `FIREBASE_SERVER_SESSION_API_PROTECTED_PATH` (`'/api/session'`) to the OIDC module's
|
|
28
|
+
* `protectedPaths` — the controller relies on the bearer middleware having populated `req.auth`.
|
|
29
|
+
*
|
|
30
|
+
* @param metadataConfig - Configuration including the dependency module.
|
|
31
|
+
* @returns NestJS module metadata exposing the session controller + service.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* @Module({
|
|
36
|
+
* imports: [DemoApiAuthModule],
|
|
37
|
+
* providers: [
|
|
38
|
+
* { provide: SessionApiModuleConfig, useValue: { appCheckAppId: environment.firebase.appId } },
|
|
39
|
+
* { provide: FIRESTORE_SESSION_ADMIN_PREDICATE, useValue: (auth) => DEMO_AUTH_CLAIMS_SERVICE.toRoles(auth?.token ?? {}).has('admin') }
|
|
40
|
+
* ],
|
|
41
|
+
* exports: [SessionApiModuleConfig, FIRESTORE_SESSION_ADMIN_PREDICATE]
|
|
42
|
+
* })
|
|
43
|
+
* export class DemoSessionApiDependencyModule {}
|
|
44
|
+
*
|
|
45
|
+
* @Module(sessionApiModuleMetadata({ dependencyModule: DemoSessionApiDependencyModule }))
|
|
46
|
+
* export class DemoSessionApiModule {}
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function sessionApiModuleMetadata(metadataConfig: SessionApiModuleMetadataConfig): ModuleMetadata;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type * as admin from 'firebase-admin';
|
|
2
|
+
import { type ISO8601DateString, type Maybe } from '@dereekb/util';
|
|
3
|
+
import { type FirebaseAuthUserId } from '@dereekb/firebase';
|
|
4
|
+
import { type FirebaseServerAuthData } from '../auth.context.server';
|
|
5
|
+
import { type FirestoreSessionAdminPredicate, SessionApiModuleConfig } from './session.api.config';
|
|
6
|
+
/**
|
|
7
|
+
* Error code thrown when the caller is not authorized to open a direct-Firestore session.
|
|
8
|
+
*/
|
|
9
|
+
export declare const FIRESTORE_SESSION_FORBIDDEN_ERROR_CODE = "FIRESTORE_SESSION_FORBIDDEN_ERROR";
|
|
10
|
+
/**
|
|
11
|
+
* A short-lived credential bundle that lets a headless client connect directly to Firestore as the
|
|
12
|
+
* authenticated user, through the app's security rules.
|
|
13
|
+
*/
|
|
14
|
+
export interface FirestoreSessionResult {
|
|
15
|
+
/**
|
|
16
|
+
* The uid the session was minted for — the calling user's real Firebase Auth uid.
|
|
17
|
+
*/
|
|
18
|
+
readonly uid: FirebaseAuthUserId;
|
|
19
|
+
/**
|
|
20
|
+
* A Firebase Auth custom token to exchange via `signInWithCustomToken`. The user's stored
|
|
21
|
+
* `setCustomUserClaims` claims are spread at the TOP LEVEL of the exchanged ID token, so security
|
|
22
|
+
* rules reading `request.auth.token.<claim>` behave exactly as they do for the browser app.
|
|
23
|
+
*/
|
|
24
|
+
readonly customToken: string;
|
|
25
|
+
/**
|
|
26
|
+
* An App Check attestation minted for the project's registered web app, for clients that cannot run
|
|
27
|
+
* a browser-only attestation provider (reCAPTCHA v3). Feed it to `initializeAppCheck` through a
|
|
28
|
+
* `CustomProvider`.
|
|
29
|
+
*
|
|
30
|
+
* Omitted when the app did not configure {@link SessionApiModuleConfig.appCheckAppId}.
|
|
31
|
+
*/
|
|
32
|
+
readonly appCheckToken?: string;
|
|
33
|
+
/**
|
|
34
|
+
* When the session as a whole stops being usable — the earliest expiry among its credentials.
|
|
35
|
+
* A long-running client should re-fetch rather than assume one session covers the whole job.
|
|
36
|
+
*/
|
|
37
|
+
readonly expiresAt: ISO8601DateString;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Mints the direct-Firestore session credential bundle returned by `SessionApiController`.
|
|
41
|
+
*
|
|
42
|
+
* ## Security
|
|
43
|
+
*
|
|
44
|
+
* This service hands out a valid web-app App Check token and a custom token for the caller's own uid.
|
|
45
|
+
* Two gates apply, in order:
|
|
46
|
+
*
|
|
47
|
+
* 1. The app-supplied {@link FirestoreSessionAdminPredicate} — the load-bearing check. **Fails closed**
|
|
48
|
+
* when the app provides no predicate.
|
|
49
|
+
* 2. The OIDC scope requirement (default {@link FIRESTORE_SESSION_OIDC_SCOPE}) — defence in depth only.
|
|
50
|
+
* It cannot stand alone: a non-OIDC caller carries no `scope` claim and every enforcement site in
|
|
51
|
+
* this codebase treats that as "skip".
|
|
52
|
+
*
|
|
53
|
+
* The custom token is ALWAYS minted for `auth.uid`; there is no way to ask for someone else's session,
|
|
54
|
+
* so a granted session is exactly as privileged as the caller already is under Firestore rules.
|
|
55
|
+
*/
|
|
56
|
+
export declare class FirestoreSessionApiService {
|
|
57
|
+
private readonly _logger;
|
|
58
|
+
private readonly _app;
|
|
59
|
+
private readonly _config;
|
|
60
|
+
private readonly _adminPredicate;
|
|
61
|
+
constructor(app: admin.app.App, config?: SessionApiModuleConfig, adminPredicate?: FirestoreSessionAdminPredicate);
|
|
62
|
+
/**
|
|
63
|
+
* Mints a direct-Firestore session for the calling user after enforcing the admin predicate and the
|
|
64
|
+
* OIDC scope requirement.
|
|
65
|
+
*
|
|
66
|
+
* @param auth - The authenticated request's auth data (`req.auth`).
|
|
67
|
+
* @returns The credential bundle the client needs to connect to Firestore as this user.
|
|
68
|
+
* @throws {HttpsError} A `401` when the request carries no uid, or a `403` when either gate rejects the caller.
|
|
69
|
+
*/
|
|
70
|
+
createFirestoreSession(auth: Maybe<FirebaseServerAuthData>): Promise<FirestoreSessionResult>;
|
|
71
|
+
}
|
package/test/index.cjs.js
CHANGED
|
@@ -824,7 +824,7 @@ function _ts_generator$a(thisArg, body) {
|
|
|
824
824
|
auth_time: decoded.iat,
|
|
825
825
|
firebase: (_ref = (_decoded_claims = decoded.claims) === null || _decoded_claims === void 0 ? void 0 : _decoded_claims.firebase) !== null && _ref !== void 0 ? _ref : {}
|
|
826
826
|
});
|
|
827
|
-
delete decodedToken
|
|
827
|
+
delete decodedToken['claims']; // remove the "claims" item if it exists.
|
|
828
828
|
return decodedToken;
|
|
829
829
|
}
|
|
830
830
|
/**
|
|
@@ -1318,8 +1318,8 @@ var adminEnvironmentInitialized = false;
|
|
|
1318
1318
|
* @returns The newly generated project ID.
|
|
1319
1319
|
*/ function rollNewGCloudProjectEnvironmentVariable() {
|
|
1320
1320
|
var projectId = generateNewProjectId();
|
|
1321
|
-
process.env
|
|
1322
|
-
process.env
|
|
1321
|
+
process.env['GCLOUD_TEST_PROJECT'] = projectId;
|
|
1322
|
+
process.env['GCLOUD_PROJECT'] = projectId;
|
|
1323
1323
|
applyFirebaseGCloudTestProjectIdToFirebaseConfigEnv();
|
|
1324
1324
|
return projectId;
|
|
1325
1325
|
}
|
|
@@ -1330,7 +1330,7 @@ var adminEnvironmentInitialized = false;
|
|
|
1330
1330
|
*
|
|
1331
1331
|
* @returns The current value of `process.env.GCLOUD_PROJECT`, or `undefined` when unset.
|
|
1332
1332
|
*/ function getGCloudProjectId() {
|
|
1333
|
-
return process.env
|
|
1333
|
+
return process.env['GCLOUD_PROJECT'];
|
|
1334
1334
|
}
|
|
1335
1335
|
/**
|
|
1336
1336
|
* Reads the current `GCLOUD_TEST_PROJECT` environment variable.
|
|
@@ -1341,7 +1341,7 @@ var adminEnvironmentInitialized = false;
|
|
|
1341
1341
|
*
|
|
1342
1342
|
* @returns The current value of `process.env.GCLOUD_TEST_PROJECT`, or `undefined` when unset.
|
|
1343
1343
|
*/ function getGCloudTestProjectId() {
|
|
1344
|
-
return process.env
|
|
1344
|
+
return process.env['GCLOUD_TEST_PROJECT'];
|
|
1345
1345
|
}
|
|
1346
1346
|
/**
|
|
1347
1347
|
* Applies the current GCLOUD_PROJECT to FIREBASE_CONFIG.
|
|
@@ -1360,10 +1360,10 @@ var adminEnvironmentInitialized = false;
|
|
|
1360
1360
|
if (!testProjectId) {
|
|
1361
1361
|
throw new Error('No test project id was available in the environment. Did you call initFirebaseAdminTestEnvironment() first?');
|
|
1362
1362
|
}
|
|
1363
|
-
var config = JSON.parse((_process_env_FIREBASE_CONFIG = process.env
|
|
1363
|
+
var config = JSON.parse((_process_env_FIREBASE_CONFIG = process.env['FIREBASE_CONFIG']) !== null && _process_env_FIREBASE_CONFIG !== void 0 ? _process_env_FIREBASE_CONFIG : '{}');
|
|
1364
1364
|
config.projectId = testProjectId;
|
|
1365
|
-
process.env
|
|
1366
|
-
process.env
|
|
1365
|
+
process.env['FIREBASE_CONFIG'] = JSON.stringify(config);
|
|
1366
|
+
process.env['GCLOUD_PROJECT'] = testProjectId; // re-apply to GCLOUD_PROJECT too
|
|
1367
1367
|
return testProjectId;
|
|
1368
1368
|
}
|
|
1369
1369
|
/**
|
package/test/index.esm.js
CHANGED
|
@@ -823,7 +823,7 @@ function _ts_generator$a(thisArg, body) {
|
|
|
823
823
|
auth_time: decoded.iat,
|
|
824
824
|
firebase: (_ref = (_decoded_claims = decoded.claims) === null || _decoded_claims === void 0 ? void 0 : _decoded_claims.firebase) !== null && _ref !== void 0 ? _ref : {}
|
|
825
825
|
});
|
|
826
|
-
delete decodedToken
|
|
826
|
+
delete decodedToken['claims']; // remove the "claims" item if it exists.
|
|
827
827
|
return decodedToken;
|
|
828
828
|
}
|
|
829
829
|
/**
|
|
@@ -1317,8 +1317,8 @@ var adminEnvironmentInitialized = false;
|
|
|
1317
1317
|
* @returns The newly generated project ID.
|
|
1318
1318
|
*/ function rollNewGCloudProjectEnvironmentVariable() {
|
|
1319
1319
|
var projectId = generateNewProjectId();
|
|
1320
|
-
process.env
|
|
1321
|
-
process.env
|
|
1320
|
+
process.env['GCLOUD_TEST_PROJECT'] = projectId;
|
|
1321
|
+
process.env['GCLOUD_PROJECT'] = projectId;
|
|
1322
1322
|
applyFirebaseGCloudTestProjectIdToFirebaseConfigEnv();
|
|
1323
1323
|
return projectId;
|
|
1324
1324
|
}
|
|
@@ -1329,7 +1329,7 @@ var adminEnvironmentInitialized = false;
|
|
|
1329
1329
|
*
|
|
1330
1330
|
* @returns The current value of `process.env.GCLOUD_PROJECT`, or `undefined` when unset.
|
|
1331
1331
|
*/ function getGCloudProjectId() {
|
|
1332
|
-
return process.env
|
|
1332
|
+
return process.env['GCLOUD_PROJECT'];
|
|
1333
1333
|
}
|
|
1334
1334
|
/**
|
|
1335
1335
|
* Reads the current `GCLOUD_TEST_PROJECT` environment variable.
|
|
@@ -1340,7 +1340,7 @@ var adminEnvironmentInitialized = false;
|
|
|
1340
1340
|
*
|
|
1341
1341
|
* @returns The current value of `process.env.GCLOUD_TEST_PROJECT`, or `undefined` when unset.
|
|
1342
1342
|
*/ function getGCloudTestProjectId() {
|
|
1343
|
-
return process.env
|
|
1343
|
+
return process.env['GCLOUD_TEST_PROJECT'];
|
|
1344
1344
|
}
|
|
1345
1345
|
/**
|
|
1346
1346
|
* Applies the current GCLOUD_PROJECT to FIREBASE_CONFIG.
|
|
@@ -1359,10 +1359,10 @@ var adminEnvironmentInitialized = false;
|
|
|
1359
1359
|
if (!testProjectId) {
|
|
1360
1360
|
throw new Error('No test project id was available in the environment. Did you call initFirebaseAdminTestEnvironment() first?');
|
|
1361
1361
|
}
|
|
1362
|
-
var config = JSON.parse((_process_env_FIREBASE_CONFIG = process.env
|
|
1362
|
+
var config = JSON.parse((_process_env_FIREBASE_CONFIG = process.env['FIREBASE_CONFIG']) !== null && _process_env_FIREBASE_CONFIG !== void 0 ? _process_env_FIREBASE_CONFIG : '{}');
|
|
1363
1363
|
config.projectId = testProjectId;
|
|
1364
|
-
process.env
|
|
1365
|
-
process.env
|
|
1364
|
+
process.env['FIREBASE_CONFIG'] = JSON.stringify(config);
|
|
1365
|
+
process.env['GCLOUD_PROJECT'] = testProjectId; // re-apply to GCLOUD_PROJECT too
|
|
1366
1366
|
return testProjectId;
|
|
1367
1367
|
}
|
|
1368
1368
|
/**
|
package/test/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/test",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.38.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/analytics": "13.
|
|
6
|
-
"@dereekb/date": "13.
|
|
7
|
-
"@dereekb/firebase": "13.
|
|
8
|
-
"@dereekb/firebase-server": "13.
|
|
9
|
-
"@dereekb/firebase-server/oidc": "13.
|
|
10
|
-
"@dereekb/model": "13.
|
|
11
|
-
"@dereekb/nestjs": "13.
|
|
12
|
-
"@dereekb/rxjs": "13.
|
|
13
|
-
"@dereekb/util": "13.
|
|
5
|
+
"@dereekb/analytics": "13.38.0",
|
|
6
|
+
"@dereekb/date": "13.38.0",
|
|
7
|
+
"@dereekb/firebase": "13.38.0",
|
|
8
|
+
"@dereekb/firebase-server": "13.38.0",
|
|
9
|
+
"@dereekb/firebase-server/oidc": "13.38.0",
|
|
10
|
+
"@dereekb/model": "13.38.0",
|
|
11
|
+
"@dereekb/nestjs": "13.38.0",
|
|
12
|
+
"@dereekb/rxjs": "13.38.0",
|
|
13
|
+
"@dereekb/util": "13.38.0",
|
|
14
14
|
"@google-cloud/firestore": "^7.11.6",
|
|
15
15
|
"@google-cloud/storage": "^7.19.0",
|
|
16
16
|
"@nestjs/common": "^11.1.19",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"supertest": "^7.2.2"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@dereekb/nestjs": "13.
|
|
26
|
+
"@dereekb/nestjs": "13.38.0"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
29
|
"./package.json": "./package.json",
|
package/twilio/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/twilio",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.38.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/date": "13.
|
|
6
|
-
"@dereekb/firebase": "13.
|
|
7
|
-
"@dereekb/firebase-server": "13.
|
|
8
|
-
"@dereekb/model": "13.
|
|
9
|
-
"@dereekb/nestjs": "13.
|
|
10
|
-
"@dereekb/rxjs": "13.
|
|
11
|
-
"@dereekb/util": "13.
|
|
5
|
+
"@dereekb/date": "13.38.0",
|
|
6
|
+
"@dereekb/firebase": "13.38.0",
|
|
7
|
+
"@dereekb/firebase-server": "13.38.0",
|
|
8
|
+
"@dereekb/model": "13.38.0",
|
|
9
|
+
"@dereekb/nestjs": "13.38.0",
|
|
10
|
+
"@dereekb/rxjs": "13.38.0",
|
|
11
|
+
"@dereekb/util": "13.38.0"
|
|
12
12
|
},
|
|
13
13
|
"exports": {
|
|
14
14
|
"./package.json": "./package.json",
|
package/zoho/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/zoho",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.38.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/analytics": "13.
|
|
6
|
-
"@dereekb/date": "13.
|
|
7
|
-
"@dereekb/model": "13.
|
|
8
|
-
"@dereekb/nestjs": "13.
|
|
9
|
-
"@dereekb/rxjs": "13.
|
|
10
|
-
"@dereekb/firebase": "13.
|
|
11
|
-
"@dereekb/firebase-server": "13.
|
|
12
|
-
"@dereekb/util": "13.
|
|
13
|
-
"@dereekb/zoho": "13.
|
|
5
|
+
"@dereekb/analytics": "13.38.0",
|
|
6
|
+
"@dereekb/date": "13.38.0",
|
|
7
|
+
"@dereekb/model": "13.38.0",
|
|
8
|
+
"@dereekb/nestjs": "13.38.0",
|
|
9
|
+
"@dereekb/rxjs": "13.38.0",
|
|
10
|
+
"@dereekb/firebase": "13.38.0",
|
|
11
|
+
"@dereekb/firebase-server": "13.38.0",
|
|
12
|
+
"@dereekb/util": "13.38.0",
|
|
13
|
+
"@dereekb/zoho": "13.38.0",
|
|
14
14
|
"@nestjs/common": "^11.1.19",
|
|
15
15
|
"@nestjs/config": "^4.0.4",
|
|
16
16
|
"express": "^5.2.1"
|