@@ -16,7 +16,96 @@ if (!process.env.TARGET_BUCKET) {
1616
1717admin . initializeApp ( ) ;
1818console . log ( "Firebase admin initialized." ) ;
19+ export const damaTest = onCall (
20+ {
21+ enforceAppCheck : true ,
22+ secrets : [ ] ,
23+ } ,
24+ async ( request ) => {
25+ const data = request . data ;
26+
27+ if ( ! data || typeof data !== "object" || Object . keys ( data ) . length === 0 ) {
28+ throw new HttpsError (
29+ "invalid-argument" ,
30+ "Data must be a non-empty JSON object."
31+ ) ;
32+ }
33+
34+ const { folderPrefix, userPseudoID, payload} = data ;
35+ const appCheckToken = request . rawRequest . headers [ "x-firebase-appcheck" ] as string ;
36+
37+ const isEmulator = process . env . FUNCTIONS_EMULATOR === "true" ;
38+ let firebaseAppId = "emulator_app_id" ;
39+
40+ if ( isEmulator ) {
41+ logger . debug ( "Running in emulator, skipping App Check verification." ) ;
42+ firebaseAppId = "emulator_app_id" ;
43+ } else {
44+ if ( ! appCheckToken || typeof appCheckToken !== "string" ) {
45+ throw new HttpsError ( "unauthenticated" , "App Check token is missing or malformed." ) ;
46+ }
47+
48+ try {
49+ const decodedAppCheckToken = await admin . appCheck ( ) . verifyToken ( appCheckToken ) ;
50+ firebaseAppId = decodedAppCheckToken . appId ;
51+ } catch ( err ) {
52+ logger . error ( "App Check token verification failed:" , err ) ;
53+ throw new HttpsError ( "unauthenticated" , "Invalid App Check token." ) ;
54+ }
55+ }
56+
57+ if ( ! payload || typeof payload !== "object" || Object . keys ( payload ) . length === 0 ) {
58+ throw new HttpsError (
59+ "invalid-argument" ,
60+ "Payload must be a non-empty JSON object."
61+ ) ;
62+ }
63+
64+ if ( ! folderPrefix || ! userPseudoID ) {
65+ throw new HttpsError (
66+ "invalid-argument" ,
67+ "Missing folderPrefix or userPseudoID in the payload."
68+ ) ;
69+ }
70+
71+ const projectId = process . env . GCP_PROJECT || process . env . GCLOUD_PROJECT ;
72+
73+ if ( ! projectId ) {
74+ logger . error ( "Project ID is not set. Ensure GCP_PROJECT or GCLOUD_PROJECT is defined in the environment." ) ;
75+ throw new HttpsError ( "internal" , "Missing project ID configuration." ) ;
76+ }
77+
78+ const appInfo = await mapAppIdToAppDetails ( projectId ! , firebaseAppId ) ;
79+ const platformId = appInfo . platformId ;
80+
81+ const filePath = generateFilePath ( userPseudoID , folderPrefix , platformId ) ;
82+
83+ logger . log ( "Saving Payload data to:" , filePath ) ;
84+
85+ const bucketName = process . env . TARGET_BUCKET ;
1986
87+ console . log ( "TARGET_BUCKET:" , bucketName ) ;
88+
89+ if ( ! bucketName ) {
90+ throw new HttpsError (
91+ "internal" ,
92+ "TARGET_BUCKET environment variable is not set."
93+ ) ;
94+ }
95+
96+ const bucket = admin . storage ( ) . bucket ( bucketName ) ;
97+
98+ await checkBucketWritePermission ( bucket ) ;
99+
100+ const jsonLines = JSON . stringify ( JSON . parse ( JSON . stringify ( payload , Object . keys ( payload ) . sort ( ) ) ) ) ;
101+
102+ await bucket . file ( filePath ) . save ( jsonLines , {
103+ contentType : "application/json" ,
104+ } ) ;
105+
106+ return { success : true , filePath : `gs://${ bucketName } /${ filePath } ` } ;
107+ }
108+ ) ;
20109export const savePayload = onCall (
21110 {
22111 enforceAppCheck : true ,
0 commit comments