@zssz-soft/firebase-functions-shared 1.2.13 → 1.2.14
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/modules/user/index.d.ts +1 -0
- package/lib/modules/user/index.d.ts.map +1 -1
- package/lib/modules/user/index.js +1 -0
- package/lib/modules/user/index.js.map +1 -1
- package/lib/modules/user/user-auth.triggers.d.ts +41 -0
- package/lib/modules/user/user-auth.triggers.d.ts.map +1 -0
- package/lib/modules/user/user-auth.triggers.js +150 -0
- package/lib/modules/user/user-auth.triggers.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/user/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/user/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
|
|
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./user.models"), exports);
|
|
18
18
|
__exportStar(require("./user"), exports);
|
|
19
19
|
__exportStar(require("./user-management"), exports);
|
|
20
|
+
__exportStar(require("./user-auth.triggers"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/user/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,yCAAuB;AACvB,oDAAkC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/user/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,yCAAuB;AACvB,oDAAkC;AAClC,uDAAqC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Auth Triggers for User Document Management
|
|
3
|
+
*
|
|
4
|
+
* Creates Firestore user documents automatically when users sign up
|
|
5
|
+
* via Firebase Auth (email/password, Google, etc.)
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Configuration for user auth triggers
|
|
9
|
+
*/
|
|
10
|
+
export interface UserAuthTriggerConfig {
|
|
11
|
+
/** Region for the trigger function */
|
|
12
|
+
region?: string;
|
|
13
|
+
/** Collection name for user documents */
|
|
14
|
+
userCollection?: string;
|
|
15
|
+
/** Default role ID for new users */
|
|
16
|
+
defaultRoleId?: string;
|
|
17
|
+
/** Whether to create user document automatically */
|
|
18
|
+
autoCreateUserDocument?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Return type for user auth triggers factory
|
|
22
|
+
* Using generic function signature to avoid firebase-functions internal type dependencies
|
|
23
|
+
*/
|
|
24
|
+
export interface UserAuthTriggers {
|
|
25
|
+
beforeUserCreated: any;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Factory function to create the beforeUserCreated trigger
|
|
29
|
+
*
|
|
30
|
+
* This blocking function runs BEFORE a new user is created in Firebase Auth.
|
|
31
|
+
* It allows us to:
|
|
32
|
+
* 1. Create the Firestore user document with admin privileges
|
|
33
|
+
* 2. Reject the sign-up if something goes wrong
|
|
34
|
+
*
|
|
35
|
+
* Benefits of beforeUserCreated vs onCreate:
|
|
36
|
+
* - Runs synchronously before user is fully created
|
|
37
|
+
* - Can reject the sign-up if Firestore write fails
|
|
38
|
+
* - User document exists immediately when auth flow completes
|
|
39
|
+
*/
|
|
40
|
+
export declare function createUserAuthTriggers(config?: UserAuthTriggerConfig): UserAuthTriggers;
|
|
41
|
+
//# sourceMappingURL=user-auth.triggers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-auth.triggers.d.ts","sourceRoot":"","sources":["../../../src/modules/user/user-auth.triggers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAE/B,iBAAiB,EAAE,GAAG,CAAC;CACxB;AAiBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,qBAA0B,GAAG,gBAAgB,CA0F3F"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Firebase Auth Triggers for User Document Management
|
|
4
|
+
*
|
|
5
|
+
* Creates Firestore user documents automatically when users sign up
|
|
6
|
+
* via Firebase Auth (email/password, Google, etc.)
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.createUserAuthTriggers = createUserAuthTriggers;
|
|
43
|
+
const firestore_1 = require("firebase-admin/firestore");
|
|
44
|
+
const identity_1 = require("firebase-functions/v2/identity");
|
|
45
|
+
const logger = __importStar(require("firebase-functions/logger"));
|
|
46
|
+
const config_1 = require("../../config");
|
|
47
|
+
const user_models_1 = require("./user.models");
|
|
48
|
+
const DEFAULT_CONFIG = {
|
|
49
|
+
userCollection: user_models_1.USER_FEATURE_KEY,
|
|
50
|
+
defaultRoleId: 'guest',
|
|
51
|
+
autoCreateUserDocument: true,
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Get Firestore instance based on config
|
|
55
|
+
*/
|
|
56
|
+
function getFirestoreInstance() {
|
|
57
|
+
const appConfig = (0, config_1.getConfig)();
|
|
58
|
+
const databaseId = appConfig.firestoreDatabaseId;
|
|
59
|
+
return databaseId ? (0, firestore_1.getFirestore)(databaseId) : (0, firestore_1.getFirestore)();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Factory function to create the beforeUserCreated trigger
|
|
63
|
+
*
|
|
64
|
+
* This blocking function runs BEFORE a new user is created in Firebase Auth.
|
|
65
|
+
* It allows us to:
|
|
66
|
+
* 1. Create the Firestore user document with admin privileges
|
|
67
|
+
* 2. Reject the sign-up if something goes wrong
|
|
68
|
+
*
|
|
69
|
+
* Benefits of beforeUserCreated vs onCreate:
|
|
70
|
+
* - Runs synchronously before user is fully created
|
|
71
|
+
* - Can reject the sign-up if Firestore write fails
|
|
72
|
+
* - User document exists immediately when auth flow completes
|
|
73
|
+
*/
|
|
74
|
+
function createUserAuthTriggers(config = {}) {
|
|
75
|
+
const cfg = Object.assign(Object.assign({}, DEFAULT_CONFIG), config);
|
|
76
|
+
const appConfig = (0, config_1.getConfig)();
|
|
77
|
+
return {
|
|
78
|
+
/**
|
|
79
|
+
* Blocking function that creates Firestore user document before auth user is finalized
|
|
80
|
+
*/
|
|
81
|
+
beforeUserCreated: (0, identity_1.beforeUserCreated)({
|
|
82
|
+
region: cfg.region || appConfig.region,
|
|
83
|
+
}, async (event) => {
|
|
84
|
+
var _a;
|
|
85
|
+
if (!cfg.autoCreateUserDocument) {
|
|
86
|
+
logger.info('Auto-create user document disabled, skipping');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const user = event.data;
|
|
90
|
+
if (!user) {
|
|
91
|
+
logger.error('No user data in event');
|
|
92
|
+
throw new identity_1.HttpsError('internal', 'No user data provided');
|
|
93
|
+
}
|
|
94
|
+
const uid = user.uid;
|
|
95
|
+
const email = user.email || '';
|
|
96
|
+
const displayName = user.displayName || email.split('@')[0] || 'User';
|
|
97
|
+
const authProvider = event.eventType.includes('google')
|
|
98
|
+
? 'google.com'
|
|
99
|
+
: event.eventType.includes('password')
|
|
100
|
+
? 'password'
|
|
101
|
+
: ((_a = event.additionalUserInfo) === null || _a === void 0 ? void 0 : _a.providerId) || 'unknown';
|
|
102
|
+
logger.info(`Creating user document for new auth user: ${uid} (${email})`);
|
|
103
|
+
try {
|
|
104
|
+
const db = getFirestoreInstance();
|
|
105
|
+
const userDocRef = db.collection(cfg.userCollection).doc(uid);
|
|
106
|
+
// Check if document already exists (shouldn't happen, but be safe)
|
|
107
|
+
const existingDoc = await userDocRef.get();
|
|
108
|
+
if (existingDoc.exists) {
|
|
109
|
+
logger.info(`User document already exists for ${uid}, skipping creation`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Parse display name into first/last name
|
|
113
|
+
const nameParts = displayName.split(' ');
|
|
114
|
+
const firstName = nameParts[0] || '';
|
|
115
|
+
const lastName = nameParts.slice(1).join(' ') || '';
|
|
116
|
+
const now = new Date().toISOString();
|
|
117
|
+
const userDocument = {
|
|
118
|
+
id: uid,
|
|
119
|
+
email,
|
|
120
|
+
displayName,
|
|
121
|
+
firstName,
|
|
122
|
+
lastName,
|
|
123
|
+
photoURL: user.photoURL || null,
|
|
124
|
+
phoneNumber: user.phoneNumber || null,
|
|
125
|
+
emailVerified: user.emailVerified || false,
|
|
126
|
+
authProvider,
|
|
127
|
+
roleIds: [cfg.defaultRoleId],
|
|
128
|
+
meta: {
|
|
129
|
+
createdAt: now,
|
|
130
|
+
updatedAt: now,
|
|
131
|
+
createdBy: 'auth-trigger',
|
|
132
|
+
updatedBy: 'auth-trigger',
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
await userDocRef.set(userDocument);
|
|
136
|
+
logger.info(`User document created successfully for ${uid}`);
|
|
137
|
+
// The beforeUserCreated trigger can return custom claims or session claims
|
|
138
|
+
// We don't need any here, just log success
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
logger.error(`Failed to create user document for ${uid}:`, error);
|
|
143
|
+
// Throwing an error here will BLOCK the user creation
|
|
144
|
+
// This ensures we don't have auth users without Firestore documents
|
|
145
|
+
throw new identity_1.HttpsError('internal', 'Failed to create user profile. Please try again.');
|
|
146
|
+
}
|
|
147
|
+
}),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=user-auth.triggers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-auth.triggers.js","sourceRoot":"","sources":["../../../src/modules/user/user-auth.triggers.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED