2121import com .google .cloud .functions .invoker .CloudFunctionsContext .Nullable ;
2222import com .google .cloud .functions .invoker .CloudFunctionsContext .Resource ;
2323import com .google .gson .Gson ;
24+ import com .google .gson .GsonBuilder ;
2425import com .google .gson .JsonObject ;
2526import io .cloudevents .CloudEvent ;
2627import io .cloudevents .core .builder .CloudEventBuilder ;
3940 */
4041class GcfEvents {
4142 private static final String FIREBASE_SERVICE = "firebase.googleapis.com" ;
43+ private static final String FIREBASE_AUTH_SERVICE = "firebaseauth.googleapis.com" ;
44+ private static final String FIREBASE_DB_SERVICE = "firebasedatabase.googleapis.com" ;
4245 private static final String FIRESTORE_SERVICE = "firestore.googleapis.com" ;
4346 private static final String PUB_SUB_SERVICE = "pubsub.googleapis.com" ;
4447 private static final String STORAGE_SERVICE = "storage.googleapis.com" ;
@@ -71,25 +74,25 @@ class GcfEvents {
7174 FIRESTORE_SERVICE )),
7275
7376 entry ("providers/firebase.auth/eventTypes/user.create" ,
74- new FirestoreFirebaseEventAdapter ("google.firebase.auth.user.v1.created" , FIREBASE_SERVICE )),
77+ new FirebaseAuthEventAdapter ("google.firebase.auth.user.v1.created" )),
7578 entry ("providers/firebase.auth/eventTypes/user.delete" ,
76- new FirestoreFirebaseEventAdapter ("google.firebase.auth.user.v1.deleted" , FIREBASE_SERVICE )),
79+ new FirebaseAuthEventAdapter ("google.firebase.auth.user.v1.deleted" )),
7780
7881 entry ("providers/google.firebase.analytics/eventTypes/event.log" ,
7982 new FirestoreFirebaseEventAdapter ("google.firebase.analytics.log.v1.written" , FIREBASE_SERVICE )),
8083
8184 entry ("providers/google.firebase.database/eventTypes/ref.create" ,
8285 new FirestoreFirebaseEventAdapter ("google.firebase.database.document.v1.created" ,
83- FIREBASE_SERVICE )),
86+ FIREBASE_DB_SERVICE )),
8487 entry ("providers/google.firebase.database/eventTypes/ref.write" ,
8588 new FirestoreFirebaseEventAdapter ("google.firebase.database.document.v1.written" ,
86- FIREBASE_SERVICE )),
89+ FIREBASE_DB_SERVICE )),
8790 entry ("providers/google.firebase.database/eventTypes/ref.update" ,
8891 new FirestoreFirebaseEventAdapter ("google.firebase.database.document.v1.updated" ,
89- FIREBASE_SERVICE )),
92+ FIREBASE_DB_SERVICE )),
9093 entry ("providers/google.firebase.database/eventTypes/ref.delete" ,
9194 new FirestoreFirebaseEventAdapter ("google.firebase.database.document.v1.deleted" ,
92- FIREBASE_SERVICE )),
95+ FIREBASE_DB_SERVICE )),
9396
9497 entry ("providers/cloud.pubsub/eventTypes/topic.publish" ,
9598 new PubSubEventAdapter (PUB_SUB_MESSAGE_PUBLISHED )),
@@ -98,7 +101,7 @@ class GcfEvents {
98101 new StorageEventAdapter ("google.cloud.storage.object.v1.changed" ))
99102 );
100103
101- private static final Gson GSON = new Gson ();
104+ private static final Gson GSON = new GsonBuilder (). serializeNulls (). create ();
102105
103106 static CloudEvent convertToCloudEvent (Event legacyEvent ) {
104107 String eventType = legacyEvent .getContext ().eventType ();
@@ -135,7 +138,7 @@ final CloudEvent convertToCloudEvent(Event legacyEvent) {
135138 Resource resource = Resource .from (legacyEvent .getContext ().resource ());
136139 String service = Optional .ofNullable (resource .service ()).orElse (defaultService );
137140 String resourceName = resource .name ();
138- SourceAndSubject sourceAndSubject = convertResourceToSourceAndSubject (resourceName );
141+ SourceAndSubject sourceAndSubject = convertResourceToSourceAndSubject (resourceName , legacyEvent );
139142 URI source = URI .create ("//" + service + "/" + sourceAndSubject .source ());
140143 OffsetDateTime timestamp =
141144 Optional .ofNullable (legacyEvent .getContext ().timestamp ())
@@ -156,7 +159,7 @@ String maybeReshapeData(Event legacyEvent, String jsonData) {
156159 return jsonData ;
157160 }
158161
159- SourceAndSubject convertResourceToSourceAndSubject (String resourceName ) {
162+ SourceAndSubject convertResourceToSourceAndSubject (String resourceName , Event legacyEvent ) {
160163 return SourceAndSubject .of (resourceName , null );
161164 }
162165 }
@@ -184,32 +187,34 @@ private static class StorageEventAdapter extends EventAdapter {
184187 }
185188
186189 @ Override
187- SourceAndSubject convertResourceToSourceAndSubject (String resourceName ) {
190+ SourceAndSubject convertResourceToSourceAndSubject (String resourceName , Event legacyEvent ) {
188191 Matcher matcher = STORAGE_RESOURCE_PATTERN .matcher (resourceName );
189192 if (matcher .matches ()) {
190193 String resource = matcher .group (1 );
191194 String subject = matcher .group (2 );
192195 return SourceAndSubject .of (resource , subject );
193196 }
194- return super .convertResourceToSourceAndSubject (resourceName );
197+ return super .convertResourceToSourceAndSubject (resourceName , legacyEvent );
195198 }
196199 }
197200
198201 private static class FirestoreFirebaseEventAdapter extends EventAdapter {
202+ private static final Pattern FIRESTORE_RESOURCE_PATTERN =
203+ Pattern .compile ("^(projects/.+)/((documents|refs)/.+)$" );
204+
199205 FirestoreFirebaseEventAdapter (String cloudEventType , String defaultService ) {
200206 super (cloudEventType , defaultService );
201207 }
202208
203209 @ Override
204- SourceAndSubject convertResourceToSourceAndSubject (String resourceName ) {
205- List <String > resourceSegments = Arrays .asList (resourceName .split ("/" ));
206- int documentsIndex = resourceSegments .indexOf ("documents" );
207- if (documentsIndex < 0 ) {
208- return super .convertResourceToSourceAndSubject (resourceName );
210+ SourceAndSubject convertResourceToSourceAndSubject (String resourceName , Event legacyEvent ) {
211+ Matcher matcher = FIRESTORE_RESOURCE_PATTERN .matcher (resourceName );
212+ if (matcher .matches ()) {
213+ String resource = matcher .group (1 );
214+ String subject = matcher .group (2 );
215+ return SourceAndSubject .of (resource , subject );
209216 }
210- String sourcePath = String .join ("/" , resourceSegments .subList (0 , documentsIndex ));
211- String subject = String .join ("/" , resourceSegments .subList (documentsIndex , resourceSegments .size ()));
212- return SourceAndSubject .of (sourcePath , subject );
217+ return super .convertResourceToSourceAndSubject (resourceName , legacyEvent );
213218 }
214219
215220 @ Override
@@ -226,4 +231,38 @@ String maybeReshapeData(Event legacyEvent, String jsonData) {
226231 return GSON .toJson (jsonObject );
227232 }
228233 }
234+
235+ private static class FirebaseAuthEventAdapter extends EventAdapter {
236+ FirebaseAuthEventAdapter (String cloudEventType ) {
237+ super (cloudEventType , FIREBASE_AUTH_SERVICE );
238+ }
239+
240+ @ Override
241+ SourceAndSubject convertResourceToSourceAndSubject (String resourceName , Event legacyEvent ) {
242+ String subject = null ;
243+ JsonObject data = legacyEvent .getData ().getAsJsonObject ();
244+ if (data .has ("uid" )) {
245+ subject = "users/" + data .get ("uid" ).getAsString ();
246+ }
247+ return SourceAndSubject .of (resourceName , subject );
248+ }
249+
250+ @ Override
251+ String maybeReshapeData (Event legacyEvent , String jsonData ) {
252+ JsonObject jsonObject = GSON .fromJson (jsonData , JsonObject .class );
253+ if (!jsonObject .has ("metadata" )) {
254+ return jsonData ;
255+ }
256+ JsonObject metadata = jsonObject .getAsJsonObject ("metadata" );
257+ if (metadata .has ("createdAt" )) {
258+ metadata .add ("createTime" , metadata .get ("createdAt" ));
259+ metadata .remove ("createdAt" );
260+ }
261+ if (metadata .has ("lastSignedInAt" )) {
262+ metadata .add ("lastSignInTime" , metadata .get ("lastSignedInAt" ));
263+ metadata .remove ("lastSignedInAt" );
264+ }
265+ return GSON .toJson (jsonObject );
266+ }
267+ }
229268}
0 commit comments