21
21
import com .google .cloud .functions .invoker .CloudFunctionsContext .Nullable ;
22
22
import com .google .cloud .functions .invoker .CloudFunctionsContext .Resource ;
23
23
import com .google .gson .Gson ;
24
+ import com .google .gson .GsonBuilder ;
24
25
import com .google .gson .JsonObject ;
25
26
import io .cloudevents .CloudEvent ;
26
27
import io .cloudevents .core .builder .CloudEventBuilder ;
39
40
*/
40
41
class GcfEvents {
41
42
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" ;
42
45
private static final String FIRESTORE_SERVICE = "firestore.googleapis.com" ;
43
46
private static final String PUB_SUB_SERVICE = "pubsub.googleapis.com" ;
44
47
private static final String STORAGE_SERVICE = "storage.googleapis.com" ;
@@ -71,25 +74,25 @@ class GcfEvents {
71
74
FIRESTORE_SERVICE )),
72
75
73
76
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" )),
75
78
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" )),
77
80
78
81
entry ("providers/google.firebase.analytics/eventTypes/event.log" ,
79
82
new FirestoreFirebaseEventAdapter ("google.firebase.analytics.log.v1.written" , FIREBASE_SERVICE )),
80
83
81
84
entry ("providers/google.firebase.database/eventTypes/ref.create" ,
82
85
new FirestoreFirebaseEventAdapter ("google.firebase.database.document.v1.created" ,
83
- FIREBASE_SERVICE )),
86
+ FIREBASE_DB_SERVICE )),
84
87
entry ("providers/google.firebase.database/eventTypes/ref.write" ,
85
88
new FirestoreFirebaseEventAdapter ("google.firebase.database.document.v1.written" ,
86
- FIREBASE_SERVICE )),
89
+ FIREBASE_DB_SERVICE )),
87
90
entry ("providers/google.firebase.database/eventTypes/ref.update" ,
88
91
new FirestoreFirebaseEventAdapter ("google.firebase.database.document.v1.updated" ,
89
- FIREBASE_SERVICE )),
92
+ FIREBASE_DB_SERVICE )),
90
93
entry ("providers/google.firebase.database/eventTypes/ref.delete" ,
91
94
new FirestoreFirebaseEventAdapter ("google.firebase.database.document.v1.deleted" ,
92
- FIREBASE_SERVICE )),
95
+ FIREBASE_DB_SERVICE )),
93
96
94
97
entry ("providers/cloud.pubsub/eventTypes/topic.publish" ,
95
98
new PubSubEventAdapter (PUB_SUB_MESSAGE_PUBLISHED )),
@@ -98,7 +101,7 @@ class GcfEvents {
98
101
new StorageEventAdapter ("google.cloud.storage.object.v1.changed" ))
99
102
);
100
103
101
- private static final Gson GSON = new Gson ();
104
+ private static final Gson GSON = new GsonBuilder (). serializeNulls (). create ();
102
105
103
106
static CloudEvent convertToCloudEvent (Event legacyEvent ) {
104
107
String eventType = legacyEvent .getContext ().eventType ();
@@ -135,7 +138,7 @@ final CloudEvent convertToCloudEvent(Event legacyEvent) {
135
138
Resource resource = Resource .from (legacyEvent .getContext ().resource ());
136
139
String service = Optional .ofNullable (resource .service ()).orElse (defaultService );
137
140
String resourceName = resource .name ();
138
- SourceAndSubject sourceAndSubject = convertResourceToSourceAndSubject (resourceName );
141
+ SourceAndSubject sourceAndSubject = convertResourceToSourceAndSubject (resourceName , legacyEvent );
139
142
URI source = URI .create ("//" + service + "/" + sourceAndSubject .source ());
140
143
OffsetDateTime timestamp =
141
144
Optional .ofNullable (legacyEvent .getContext ().timestamp ())
@@ -156,7 +159,7 @@ String maybeReshapeData(Event legacyEvent, String jsonData) {
156
159
return jsonData ;
157
160
}
158
161
159
- SourceAndSubject convertResourceToSourceAndSubject (String resourceName ) {
162
+ SourceAndSubject convertResourceToSourceAndSubject (String resourceName , Event legacyEvent ) {
160
163
return SourceAndSubject .of (resourceName , null );
161
164
}
162
165
}
@@ -184,32 +187,34 @@ private static class StorageEventAdapter extends EventAdapter {
184
187
}
185
188
186
189
@ Override
187
- SourceAndSubject convertResourceToSourceAndSubject (String resourceName ) {
190
+ SourceAndSubject convertResourceToSourceAndSubject (String resourceName , Event legacyEvent ) {
188
191
Matcher matcher = STORAGE_RESOURCE_PATTERN .matcher (resourceName );
189
192
if (matcher .matches ()) {
190
193
String resource = matcher .group (1 );
191
194
String subject = matcher .group (2 );
192
195
return SourceAndSubject .of (resource , subject );
193
196
}
194
- return super .convertResourceToSourceAndSubject (resourceName );
197
+ return super .convertResourceToSourceAndSubject (resourceName , legacyEvent );
195
198
}
196
199
}
197
200
198
201
private static class FirestoreFirebaseEventAdapter extends EventAdapter {
202
+ private static final Pattern FIRESTORE_RESOURCE_PATTERN =
203
+ Pattern .compile ("^(projects/.+)/((documents|refs)/.+)$" );
204
+
199
205
FirestoreFirebaseEventAdapter (String cloudEventType , String defaultService ) {
200
206
super (cloudEventType , defaultService );
201
207
}
202
208
203
209
@ 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 );
209
216
}
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 );
213
218
}
214
219
215
220
@ Override
@@ -226,4 +231,38 @@ String maybeReshapeData(Event legacyEvent, String jsonData) {
226
231
return GSON .toJson (jsonObject );
227
232
}
228
233
}
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
+ }
229
268
}
0 commit comments