@zssz-soft/firebase-functions-shared 1.2.6 → 1.2.8
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/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/modules/e2e/e2e-reset.d.ts +57 -0
- package/lib/modules/e2e/e2e-reset.d.ts.map +1 -0
- package/lib/modules/e2e/e2e-reset.js +234 -0
- package/lib/modules/e2e/e2e-reset.js.map +1 -0
- package/lib/modules/e2e/index.d.ts +8 -0
- package/lib/modules/e2e/index.d.ts.map +1 -0
- package/lib/modules/e2e/index.js +24 -0
- package/lib/modules/e2e/index.js.map +1 -0
- package/lib/modules/user/user-auth.triggers.d.ts +25 -0
- package/lib/modules/user/user-auth.triggers.d.ts.map +1 -0
- package/lib/modules/user/user-auth.triggers.js +154 -0
- package/lib/modules/user/user-auth.triggers.js.map +1 -0
- package/package.json +3 -7
package/lib/index.d.ts
CHANGED
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -26,4 +26,5 @@ __exportStar(require("./modules/email"), exports);
|
|
|
26
26
|
__exportStar(require("./modules/storage"), exports);
|
|
27
27
|
__exportStar(require("./modules/user"), exports);
|
|
28
28
|
__exportStar(require("./modules/security"), exports);
|
|
29
|
+
__exportStar(require("./modules/e2e"), exports);
|
|
29
30
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;AAEH,2CAAyB;AACzB,sDAAoC;AACpC,kDAAgC;AAChC,oDAAkC;AAClC,iDAA+B;AAC/B,qDAAmC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;AAEH,2CAAyB;AACzB,sDAAoC;AACpC,kDAAgC;AAChC,oDAAkC;AAClC,iDAA+B;AAC/B,qDAAmC;AACnC,gDAA8B"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E Reset Cloud Function
|
|
3
|
+
*
|
|
4
|
+
* Provides functionality to reset the Firebase environment for E2E testing.
|
|
5
|
+
* This function clears all Firestore collections and deletes all Firebase Auth users.
|
|
6
|
+
*
|
|
7
|
+
* SECURITY: This function is protected by a secret header and should only be
|
|
8
|
+
* deployed to test environments.
|
|
9
|
+
*/
|
|
10
|
+
import { Firestore } from 'firebase-admin/firestore';
|
|
11
|
+
import { AppConfig } from '../../config';
|
|
12
|
+
/**
|
|
13
|
+
* Collections to clear during E2E reset
|
|
14
|
+
* Based on domain models in projects/api/src/lib/domain/
|
|
15
|
+
*/
|
|
16
|
+
export declare const COLLECTIONS_TO_CLEAR: readonly ["user", "role", "booking", "apartment", "document", "equipment", "app-config", "article", "audit_logs", "security"];
|
|
17
|
+
/**
|
|
18
|
+
* Result of an E2E reset operation
|
|
19
|
+
*/
|
|
20
|
+
export interface E2EResetResult {
|
|
21
|
+
success: boolean;
|
|
22
|
+
message: string;
|
|
23
|
+
deletedDocuments: number;
|
|
24
|
+
deletedUsers: number;
|
|
25
|
+
deletedCollections: string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Delete all documents in a collection using batch operations
|
|
29
|
+
* Returns the number of deleted documents
|
|
30
|
+
*/
|
|
31
|
+
export declare function deleteCollection(firestore: Firestore, collectionPath: string, batchSize?: number): Promise<number>;
|
|
32
|
+
/**
|
|
33
|
+
* Delete all subcollections for documents in a collection
|
|
34
|
+
* This handles nested data like apartment/rules and booking/workflow_history
|
|
35
|
+
*/
|
|
36
|
+
export declare function deleteSubcollections(firestore: Firestore, parentCollection: string, subcollectionName: string, batchSize?: number): Promise<number>;
|
|
37
|
+
/**
|
|
38
|
+
* Delete the security/users subcollections (effective_permissions)
|
|
39
|
+
*/
|
|
40
|
+
export declare function deleteSecuritySubcollections(firestore: Firestore, batchSize?: number): Promise<number>;
|
|
41
|
+
/**
|
|
42
|
+
* Delete all Firebase Auth users
|
|
43
|
+
* Returns the number of deleted users
|
|
44
|
+
*/
|
|
45
|
+
export declare function deleteAllAuthUsers(): Promise<number>;
|
|
46
|
+
/**
|
|
47
|
+
* Core E2E reset logic - exported for testing
|
|
48
|
+
*/
|
|
49
|
+
export declare function executeE2EReset(config: AppConfig): Promise<E2EResetResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Factory function to create e2eReset HTTP function
|
|
52
|
+
*
|
|
53
|
+
* @param secretEnvVar - Environment variable name containing the reset secret
|
|
54
|
+
* Default: 'E2E_RESET_SECRET'
|
|
55
|
+
*/
|
|
56
|
+
export declare function createE2EResetFunction(secretEnvVar?: string): import("firebase-functions/https").HttpsFunction;
|
|
57
|
+
//# sourceMappingURL=e2e-reset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e-reset.d.ts","sourceRoot":"","sources":["../../../src/modules/e2e/e2e-reset.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAgB,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAKnE,OAAO,EAAE,SAAS,EAAa,MAAM,cAAc,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,+HAWvB,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AASD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,MAAM,EACtB,SAAS,SAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,MAAM,EACxB,iBAAiB,EAAE,MAAM,EACzB,SAAS,SAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAChD,SAAS,EAAE,SAAS,EACpB,SAAS,SAAM,GACd,OAAO,CAAC,MAAM,CAAC,CA0BjB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAiB1D;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC,CAiDhF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,SAAqB,oDA6CvE"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* E2E Reset Cloud Function
|
|
4
|
+
*
|
|
5
|
+
* Provides functionality to reset the Firebase environment for E2E testing.
|
|
6
|
+
* This function clears all Firestore collections and deletes all Firebase Auth users.
|
|
7
|
+
*
|
|
8
|
+
* SECURITY: This function is protected by a secret header and should only be
|
|
9
|
+
* deployed to test environments.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.COLLECTIONS_TO_CLEAR = void 0;
|
|
13
|
+
exports.deleteCollection = deleteCollection;
|
|
14
|
+
exports.deleteSubcollections = deleteSubcollections;
|
|
15
|
+
exports.deleteSecuritySubcollections = deleteSecuritySubcollections;
|
|
16
|
+
exports.deleteAllAuthUsers = deleteAllAuthUsers;
|
|
17
|
+
exports.executeE2EReset = executeE2EReset;
|
|
18
|
+
exports.createE2EResetFunction = createE2EResetFunction;
|
|
19
|
+
const firestore_1 = require("firebase-admin/firestore");
|
|
20
|
+
const auth_1 = require("firebase-admin/auth");
|
|
21
|
+
const firebase_functions_1 = require("firebase-functions");
|
|
22
|
+
const https_1 = require("firebase-functions/https");
|
|
23
|
+
const config_1 = require("../../config");
|
|
24
|
+
/**
|
|
25
|
+
* Collections to clear during E2E reset
|
|
26
|
+
* Based on domain models in projects/api/src/lib/domain/
|
|
27
|
+
*/
|
|
28
|
+
exports.COLLECTIONS_TO_CLEAR = [
|
|
29
|
+
'user',
|
|
30
|
+
'role',
|
|
31
|
+
'booking',
|
|
32
|
+
'apartment',
|
|
33
|
+
'document',
|
|
34
|
+
'equipment',
|
|
35
|
+
'app-config',
|
|
36
|
+
'article',
|
|
37
|
+
'audit_logs',
|
|
38
|
+
'security',
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Get Firestore instance based on config
|
|
42
|
+
*/
|
|
43
|
+
function getFirestoreInstance(config) {
|
|
44
|
+
return config.firestoreDatabaseId ? (0, firestore_1.getFirestore)(config.firestoreDatabaseId) : (0, firestore_1.getFirestore)();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Delete all documents in a collection using batch operations
|
|
48
|
+
* Returns the number of deleted documents
|
|
49
|
+
*/
|
|
50
|
+
async function deleteCollection(firestore, collectionPath, batchSize = 100) {
|
|
51
|
+
const collectionRef = firestore.collection(collectionPath);
|
|
52
|
+
let deletedCount = 0;
|
|
53
|
+
while (true) {
|
|
54
|
+
const snapshot = await collectionRef.limit(batchSize).get();
|
|
55
|
+
if (snapshot.empty) {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
const batch = firestore.batch();
|
|
59
|
+
snapshot.docs.forEach((doc) => {
|
|
60
|
+
batch.delete(doc.ref);
|
|
61
|
+
});
|
|
62
|
+
await batch.commit();
|
|
63
|
+
deletedCount += snapshot.size;
|
|
64
|
+
firebase_functions_1.logger.info(`Deleted ${snapshot.size} documents from ${collectionPath}`);
|
|
65
|
+
}
|
|
66
|
+
return deletedCount;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Delete all subcollections for documents in a collection
|
|
70
|
+
* This handles nested data like apartment/rules and booking/workflow_history
|
|
71
|
+
*/
|
|
72
|
+
async function deleteSubcollections(firestore, parentCollection, subcollectionName, batchSize = 100) {
|
|
73
|
+
const parentRef = firestore.collection(parentCollection);
|
|
74
|
+
const parentDocs = await parentRef.listDocuments();
|
|
75
|
+
let totalDeleted = 0;
|
|
76
|
+
for (const parentDoc of parentDocs) {
|
|
77
|
+
const subcollectionRef = parentDoc.collection(subcollectionName);
|
|
78
|
+
let deletedInSubcollection = 0;
|
|
79
|
+
while (true) {
|
|
80
|
+
const snapshot = await subcollectionRef.limit(batchSize).get();
|
|
81
|
+
if (snapshot.empty) {
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
const batch = firestore.batch();
|
|
85
|
+
snapshot.docs.forEach((doc) => {
|
|
86
|
+
batch.delete(doc.ref);
|
|
87
|
+
});
|
|
88
|
+
await batch.commit();
|
|
89
|
+
deletedInSubcollection += snapshot.size;
|
|
90
|
+
}
|
|
91
|
+
if (deletedInSubcollection > 0) {
|
|
92
|
+
firebase_functions_1.logger.info(`Deleted ${deletedInSubcollection} documents from ${parentCollection}/${parentDoc.id}/${subcollectionName}`);
|
|
93
|
+
totalDeleted += deletedInSubcollection;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return totalDeleted;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Delete the security/users subcollections (effective_permissions)
|
|
100
|
+
*/
|
|
101
|
+
async function deleteSecuritySubcollections(firestore, batchSize = 100) {
|
|
102
|
+
const securityUsersRef = firestore.collection('security').doc('users');
|
|
103
|
+
const userSubcollections = await securityUsersRef.listCollections();
|
|
104
|
+
let totalDeleted = 0;
|
|
105
|
+
for (const userCollection of userSubcollections) {
|
|
106
|
+
while (true) {
|
|
107
|
+
const snapshot = await userCollection.limit(batchSize).get();
|
|
108
|
+
if (snapshot.empty) {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
const batch = firestore.batch();
|
|
112
|
+
snapshot.docs.forEach((doc) => {
|
|
113
|
+
batch.delete(doc.ref);
|
|
114
|
+
});
|
|
115
|
+
await batch.commit();
|
|
116
|
+
totalDeleted += snapshot.size;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (totalDeleted > 0) {
|
|
120
|
+
firebase_functions_1.logger.info(`Deleted ${totalDeleted} effective_permissions documents`);
|
|
121
|
+
}
|
|
122
|
+
return totalDeleted;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Delete all Firebase Auth users
|
|
126
|
+
* Returns the number of deleted users
|
|
127
|
+
*/
|
|
128
|
+
async function deleteAllAuthUsers() {
|
|
129
|
+
const auth = (0, auth_1.getAuth)();
|
|
130
|
+
let deletedCount = 0;
|
|
131
|
+
let pageToken;
|
|
132
|
+
do {
|
|
133
|
+
const listResult = await auth.listUsers(1000, pageToken);
|
|
134
|
+
if (listResult.users.length > 0) {
|
|
135
|
+
const uids = listResult.users.map((user) => user.uid);
|
|
136
|
+
await auth.deleteUsers(uids);
|
|
137
|
+
deletedCount += uids.length;
|
|
138
|
+
firebase_functions_1.logger.info(`Deleted ${uids.length} auth users`);
|
|
139
|
+
}
|
|
140
|
+
pageToken = listResult.pageToken;
|
|
141
|
+
} while (pageToken);
|
|
142
|
+
return deletedCount;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Core E2E reset logic - exported for testing
|
|
146
|
+
*/
|
|
147
|
+
async function executeE2EReset(config) {
|
|
148
|
+
const firestore = getFirestoreInstance(config);
|
|
149
|
+
let totalDeletedDocs = 0;
|
|
150
|
+
const deletedCollections = [];
|
|
151
|
+
firebase_functions_1.logger.info('Starting E2E reset...');
|
|
152
|
+
// Delete subcollections first (before parent documents)
|
|
153
|
+
const subcollectionDefs = [
|
|
154
|
+
{ parent: 'apartment', sub: 'rule' },
|
|
155
|
+
{ parent: 'booking', sub: 'workflow_history' },
|
|
156
|
+
];
|
|
157
|
+
for (const { parent, sub } of subcollectionDefs) {
|
|
158
|
+
const count = await deleteSubcollections(firestore, parent, sub);
|
|
159
|
+
if (count > 0) {
|
|
160
|
+
totalDeletedDocs += count;
|
|
161
|
+
deletedCollections.push(`${parent}/${sub}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Delete security subcollections (effective_permissions)
|
|
165
|
+
const securityCount = await deleteSecuritySubcollections(firestore);
|
|
166
|
+
if (securityCount > 0) {
|
|
167
|
+
totalDeletedDocs += securityCount;
|
|
168
|
+
deletedCollections.push('security/users/*/effective_permissions');
|
|
169
|
+
}
|
|
170
|
+
// Delete main collections
|
|
171
|
+
for (const collection of exports.COLLECTIONS_TO_CLEAR) {
|
|
172
|
+
const count = await deleteCollection(firestore, collection);
|
|
173
|
+
if (count > 0) {
|
|
174
|
+
totalDeletedDocs += count;
|
|
175
|
+
deletedCollections.push(collection);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Delete all Auth users
|
|
179
|
+
const deletedUsers = await deleteAllAuthUsers();
|
|
180
|
+
firebase_functions_1.logger.info(`E2E reset completed: ${totalDeletedDocs} documents, ${deletedUsers} users deleted`);
|
|
181
|
+
return {
|
|
182
|
+
success: true,
|
|
183
|
+
message: 'E2E reset completed successfully',
|
|
184
|
+
deletedDocuments: totalDeletedDocs,
|
|
185
|
+
deletedUsers,
|
|
186
|
+
deletedCollections,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Factory function to create e2eReset HTTP function
|
|
191
|
+
*
|
|
192
|
+
* @param secretEnvVar - Environment variable name containing the reset secret
|
|
193
|
+
* Default: 'E2E_RESET_SECRET'
|
|
194
|
+
*/
|
|
195
|
+
function createE2EResetFunction(secretEnvVar = 'E2E_RESET_SECRET') {
|
|
196
|
+
const config = (0, config_1.getConfig)();
|
|
197
|
+
return (0, https_1.onRequest)({
|
|
198
|
+
region: config.region,
|
|
199
|
+
maxInstances: 1,
|
|
200
|
+
timeoutSeconds: 540, // 9 minutes for large datasets
|
|
201
|
+
}, async (req, res) => {
|
|
202
|
+
// Only allow POST requests
|
|
203
|
+
if (req.method !== 'POST') {
|
|
204
|
+
res.status(405).json({ error: 'Method not allowed. Use POST.' });
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
// Verify secret header
|
|
208
|
+
const providedSecret = req.headers['x-e2e-reset-secret'];
|
|
209
|
+
const expectedSecret = process.env[secretEnvVar];
|
|
210
|
+
if (!expectedSecret) {
|
|
211
|
+
firebase_functions_1.logger.error(`E2E reset secret not configured (${secretEnvVar} environment variable)`);
|
|
212
|
+
res.status(500).json({ error: 'E2E reset not configured on server' });
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (!providedSecret || providedSecret !== expectedSecret) {
|
|
216
|
+
firebase_functions_1.logger.warn('E2E reset attempted with invalid or missing secret');
|
|
217
|
+
res.status(403).json({ error: 'Invalid or missing X-E2E-Reset-Secret header' });
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
firebase_functions_1.logger.info('E2E reset authorized, starting reset process...');
|
|
222
|
+
const result = await executeE2EReset(config);
|
|
223
|
+
res.status(200).json(result);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
firebase_functions_1.logger.error('E2E reset failed:', error);
|
|
227
|
+
res.status(500).json({
|
|
228
|
+
success: false,
|
|
229
|
+
error: error instanceof Error ? error.message : 'Unknown error during E2E reset',
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=e2e-reset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e-reset.js","sourceRoot":"","sources":["../../../src/modules/e2e/e2e-reset.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/e2e/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* E2E Testing Module
|
|
4
|
+
*
|
|
5
|
+
* Provides Cloud Functions for E2E testing support.
|
|
6
|
+
* These functions should only be deployed to test environments.
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
__exportStar(require("./e2e-reset"), exports);
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/e2e/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;AAEH,8CAA4B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Auth Triggers
|
|
3
|
+
*
|
|
4
|
+
* Firebase Auth triggers that automatically create/sync user documents
|
|
5
|
+
* when users sign up with any provider (email, Google, etc.)
|
|
6
|
+
*/
|
|
7
|
+
import { beforeUserCreated, beforeUserSignedIn } from 'firebase-functions/v2/identity';
|
|
8
|
+
export interface UserAuthTriggersConfig {
|
|
9
|
+
region?: string;
|
|
10
|
+
defaultRoleId?: string;
|
|
11
|
+
firestoreDatabaseId?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a factory for the beforeUserCreated trigger
|
|
15
|
+
* This trigger runs before a new user is created in Firebase Auth
|
|
16
|
+
* It can be used to validate or modify the user data
|
|
17
|
+
*/
|
|
18
|
+
export declare function createBeforeUserCreatedFunction(triggerConfig?: UserAuthTriggersConfig): ReturnType<typeof beforeUserCreated>;
|
|
19
|
+
/**
|
|
20
|
+
* Create a factory for the beforeUserSignedIn trigger
|
|
21
|
+
* This trigger runs every time a user signs in
|
|
22
|
+
* We use it to ensure the user document exists in Firestore
|
|
23
|
+
*/
|
|
24
|
+
export declare function createBeforeUserSignedInFunction(triggerConfig?: UserAuthTriggersConfig): ReturnType<typeof beforeUserSignedIn>;
|
|
25
|
+
//# 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;AAIH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAKvF,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAWD;;;;GAIG;AAEH,wBAAgB,+BAA+B,CAC7C,aAAa,GAAE,sBAA2B,GACzC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAoBtC;AAED;;;;GAIG;AAEH,wBAAgB,gCAAgC,CAC9C,aAAa,GAAE,sBAA2B,GACzC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CA0EvC"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* User Auth Triggers
|
|
4
|
+
*
|
|
5
|
+
* Firebase Auth triggers that automatically create/sync user documents
|
|
6
|
+
* when users sign up with any provider (email, 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.createBeforeUserCreatedFunction = createBeforeUserCreatedFunction;
|
|
43
|
+
exports.createBeforeUserSignedInFunction = createBeforeUserSignedInFunction;
|
|
44
|
+
const firestore_1 = require("firebase-admin/firestore");
|
|
45
|
+
const logger = __importStar(require("firebase-functions/logger"));
|
|
46
|
+
const identity_1 = require("firebase-functions/v2/identity");
|
|
47
|
+
const config_1 = require("../../config");
|
|
48
|
+
const user_models_1 = require("./user.models");
|
|
49
|
+
/**
|
|
50
|
+
* Get Firestore instance based on config
|
|
51
|
+
*/
|
|
52
|
+
function getFirestoreInstance(config) {
|
|
53
|
+
return config.firestoreDatabaseId
|
|
54
|
+
? (0, firestore_1.getFirestore)(config.firestoreDatabaseId)
|
|
55
|
+
: (0, firestore_1.getFirestore)();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a factory for the beforeUserCreated trigger
|
|
59
|
+
* This trigger runs before a new user is created in Firebase Auth
|
|
60
|
+
* It can be used to validate or modify the user data
|
|
61
|
+
*/
|
|
62
|
+
// Return type is BlockingFunction from firebase-functions, using ReturnType for better compatibility
|
|
63
|
+
function createBeforeUserCreatedFunction(triggerConfig = {}) {
|
|
64
|
+
const config = (0, config_1.getConfig)();
|
|
65
|
+
const region = triggerConfig.region || config.region;
|
|
66
|
+
return (0, identity_1.beforeUserCreated)({ region }, async (event) => {
|
|
67
|
+
var _a;
|
|
68
|
+
const user = event.data;
|
|
69
|
+
if (!user) {
|
|
70
|
+
logger.warn('beforeUserCreated: No user data in event');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
logger.info('beforeUserCreated trigger fired:', {
|
|
74
|
+
uid: user.uid,
|
|
75
|
+
email: user.email,
|
|
76
|
+
provider: (_a = event.credential) === null || _a === void 0 ? void 0 : _a.providerId,
|
|
77
|
+
});
|
|
78
|
+
// Can add validation logic here if needed
|
|
79
|
+
// Return nothing to allow user creation to proceed
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create a factory for the beforeUserSignedIn trigger
|
|
84
|
+
* This trigger runs every time a user signs in
|
|
85
|
+
* We use it to ensure the user document exists in Firestore
|
|
86
|
+
*/
|
|
87
|
+
// Return type is BlockingFunction from firebase-functions, using ReturnType for better compatibility
|
|
88
|
+
function createBeforeUserSignedInFunction(triggerConfig = {}) {
|
|
89
|
+
const config = (0, config_1.getConfig)();
|
|
90
|
+
const region = triggerConfig.region || config.region;
|
|
91
|
+
return (0, identity_1.beforeUserSignedIn)({ region }, async (event) => {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
const user = event.data;
|
|
94
|
+
if (!user) {
|
|
95
|
+
logger.warn('beforeUserSignedIn: No user data in event');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const providerId = ((_a = event.credential) === null || _a === void 0 ? void 0 : _a.providerId) || 'unknown';
|
|
99
|
+
logger.info('beforeUserSignedIn trigger fired:', {
|
|
100
|
+
uid: user.uid,
|
|
101
|
+
email: user.email,
|
|
102
|
+
provider: providerId,
|
|
103
|
+
});
|
|
104
|
+
// Check if user document exists in Firestore
|
|
105
|
+
const firestore = getFirestoreInstance(config);
|
|
106
|
+
const userDocRef = firestore.collection(user_models_1.USER_FEATURE_KEY).doc(user.uid);
|
|
107
|
+
const userDoc = await userDocRef.get();
|
|
108
|
+
if (!userDoc.exists) {
|
|
109
|
+
// Create user document for new OAuth users
|
|
110
|
+
logger.info('Creating user document for OAuth user:', user.uid);
|
|
111
|
+
const now = new Date().toISOString();
|
|
112
|
+
const defaultRoleId = triggerConfig.defaultRoleId || config.defaultUserRoleId;
|
|
113
|
+
// Parse display name into first/last name
|
|
114
|
+
const nameParts = (user.displayName || '').split(' ');
|
|
115
|
+
const firstName = nameParts[0] || '';
|
|
116
|
+
const lastName = nameParts.slice(1).join(' ') || '';
|
|
117
|
+
const userDocument = {
|
|
118
|
+
id: user.uid,
|
|
119
|
+
email: user.email || '',
|
|
120
|
+
displayName: user.displayName || ((_b = user.email) === null || _b === void 0 ? void 0 : _b.split('@')[0]) || 'User',
|
|
121
|
+
firstName,
|
|
122
|
+
lastName,
|
|
123
|
+
photoURL: user.photoURL || null,
|
|
124
|
+
phoneNumber: user.phoneNumber || null,
|
|
125
|
+
emailVerified: user.emailVerified || false,
|
|
126
|
+
authProvider: providerId,
|
|
127
|
+
roleIds: [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:', user.uid);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// Optionally update some fields for existing users
|
|
140
|
+
const existingData = userDoc.data();
|
|
141
|
+
// Update photoURL if it changed (e.g., user updated their Google profile picture)
|
|
142
|
+
if (user.photoURL && (existingData === null || existingData === void 0 ? void 0 : existingData.photoURL) !== user.photoURL) {
|
|
143
|
+
await userDocRef.update({
|
|
144
|
+
photoURL: user.photoURL,
|
|
145
|
+
'meta.updatedAt': new Date().toISOString(),
|
|
146
|
+
'meta.updatedBy': 'auth-trigger',
|
|
147
|
+
});
|
|
148
|
+
logger.info('Updated user photoURL:', user.uid);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Return nothing to allow sign-in to proceed
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
//# 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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zssz-soft/firebase-functions-shared",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"description": "Shared Firebase Cloud Functions modules for LodgeFlow applications",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"node": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"firebase-admin": "^
|
|
50
|
-
"firebase-functions": "^
|
|
49
|
+
"firebase-admin": "^13.6.0",
|
|
50
|
+
"firebase-functions": "^7.0.2",
|
|
51
51
|
"googleapis": "^165.0.0",
|
|
52
52
|
"heic-convert": "^2.1.0",
|
|
53
53
|
"nodemailer": "^7.0.10",
|
|
@@ -63,10 +63,6 @@
|
|
|
63
63
|
"ts-jest": "^29.4.5",
|
|
64
64
|
"typescript": "^5.0.0"
|
|
65
65
|
},
|
|
66
|
-
"peerDependencies": {
|
|
67
|
-
"firebase-admin": "^12.0.0",
|
|
68
|
-
"firebase-functions": "^6.6.0"
|
|
69
|
-
},
|
|
70
66
|
"publishConfig": {
|
|
71
67
|
"access": "public"
|
|
72
68
|
}
|