firebase-functions 0.1.2__tar.gz → 0.3.0__tar.gz

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.
Files changed (55) hide show
  1. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/PKG-INFO +1 -1
  2. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/setup.py +2 -0
  3. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/__init__.py +1 -1
  4. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/alerts_fn.py +2 -2
  5. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/core.py +1 -1
  6. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/db_fn.py +5 -5
  7. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/firestore_fn.py +255 -12
  8. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/https_fn.py +20 -9
  9. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/identity_fn.py +15 -4
  10. firebase_functions-0.3.0/src/firebase_functions/logger.py +133 -0
  11. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/options.py +15 -0
  12. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/params.py +47 -4
  13. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/private/_alerts_fn.py +13 -2
  14. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/private/_identity_fn.py +29 -8
  15. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/private/manifest.py +8 -3
  16. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/private/path_pattern.py +4 -1
  17. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/private/util.py +53 -13
  18. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/pubsub_fn.py +1 -1
  19. firebase_functions-0.3.0/src/firebase_functions/py.typed +0 -0
  20. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/remote_config_fn.py +8 -2
  21. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/storage_fn.py +1 -1
  22. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/tasks_fn.py +5 -2
  23. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/test_lab_fn.py +6 -0
  24. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions.egg-info/PKG-INFO +1 -1
  25. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions.egg-info/SOURCES.txt +4 -0
  26. firebase_functions-0.3.0/tests/test_firestore_fn.py +72 -0
  27. firebase_functions-0.3.0/tests/test_logger.py +81 -0
  28. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_manifest.py +25 -27
  29. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_params.py +36 -0
  30. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_tasks_fn.py +35 -0
  31. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_util.py +9 -1
  32. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/LICENSE +0 -0
  33. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/README.md +0 -0
  34. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/pyproject.toml +0 -0
  35. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/setup.cfg +0 -0
  36. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/alerts/__init__.py +0 -0
  37. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/alerts/app_distribution_fn.py +0 -0
  38. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/alerts/billing_fn.py +0 -0
  39. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/alerts/crashlytics_fn.py +0 -0
  40. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/alerts/performance_fn.py +0 -0
  41. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/eventarc_fn.py +0 -0
  42. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/private/__init__.py +0 -0
  43. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/private/serving.py +0 -0
  44. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/private/token_verifier.py +0 -0
  45. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions/scheduler_fn.py +0 -0
  46. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions.egg-info/dependency_links.txt +0 -0
  47. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions.egg-info/requires.txt +0 -0
  48. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/src/firebase_functions.egg-info/top_level.txt +0 -0
  49. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_eventarc_fn.py +0 -0
  50. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_options.py +0 -0
  51. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_path_pattern.py +0 -0
  52. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_pubsub_fn.py +0 -0
  53. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_remote_config_fn.py +0 -0
  54. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_scheduler_fn.py +0 -0
  55. {firebase_functions-0.1.2 → firebase_functions-0.3.0}/tests/test_test_lab_fn.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: firebase_functions
3
- Version: 0.1.2
3
+ Version: 0.3.0
4
4
  Summary: Firebase Functions Python SDK
5
5
  Home-page: https://github.com/firebase/firebase-functions-python
6
6
  Author: Firebase Team
@@ -56,6 +56,8 @@ setup(
56
56
  extras_require={'dev': dev_requires},
57
57
  packages=find_packages(where='src'),
58
58
  package_dir={'': 'src'},
59
+ include_package_data=True,
60
+ package_data={'firebase_functions': ['py.typed']},
59
61
  python_requires='>=3.10',
60
62
  classifiers=[
61
63
  'Development Status :: 4 - Beta',
@@ -15,4 +15,4 @@
15
15
  Firebase Functions for Python.
16
16
  """
17
17
 
18
- __version__ = "0.1.2"
18
+ __version__ = "0.3.0"
@@ -46,7 +46,7 @@ class AlertEvent(_CloudEvent[T]):
46
46
  app_id: str | None
47
47
  """
48
48
  The Firebase App ID that's associated with the alert. This is optional,
49
- and only present when the alert is targeting at a specific Firebase App.
49
+ and only present when the alert is targeting a specific Firebase App.
50
50
  """
51
51
 
52
52
 
@@ -66,7 +66,7 @@ def on_alert_published(
66
66
  **kwargs
67
67
  ) -> _typing.Callable[[OnAlertPublishedCallable], OnAlertPublishedCallable]:
68
68
  """
69
- Event handler which triggers when a Firebase Alerts event is published.
69
+ Event handler that triggers when a Firebase Alerts event is published.
70
70
 
71
71
  Example:
72
72
 
@@ -25,7 +25,7 @@ T = _typing.TypeVar("T")
25
25
  class CloudEvent(_typing.Generic[T]):
26
26
  """
27
27
  A CloudEvent is the base of a cross-platform format for encoding a serverless event.
28
- More information can be found at https://github.com/cloudevents/spec
28
+ More information can be found at https://github.com/cloudevents/spec.
29
29
  """
30
30
 
31
31
  specversion: str
@@ -61,7 +61,7 @@ class Event(_core.CloudEvent[T]):
61
61
 
62
62
  params: dict[str, str]
63
63
  """
64
- An dict containing the values of the path patterns.
64
+ A dict containing the values of the path patterns.
65
65
  Only named capture groups are populated - {key}, {key=*}, {key=**}
66
66
  """
67
67
 
@@ -125,7 +125,7 @@ def _db_endpoint_handler(
125
125
  @_util.copy_func_kwargs(DatabaseOptions)
126
126
  def on_value_written(**kwargs) -> _typing.Callable[[_C1], _C1]:
127
127
  """
128
- Event handler which triggers when data is created, updated, or deleted in Realtime Database.
128
+ Event handler that triggers when data is created, updated, or deleted in Realtime Database.
129
129
 
130
130
  Example:
131
131
 
@@ -175,7 +175,7 @@ def on_value_written(**kwargs) -> _typing.Callable[[_C1], _C1]:
175
175
  @_util.copy_func_kwargs(DatabaseOptions)
176
176
  def on_value_updated(**kwargs) -> _typing.Callable[[_C1], _C1]:
177
177
  """
178
- Event handler which triggers when data is updated in Realtime Database.
178
+ Event handler that triggers when data is updated in Realtime Database.
179
179
 
180
180
  Example:
181
181
 
@@ -225,7 +225,7 @@ def on_value_updated(**kwargs) -> _typing.Callable[[_C1], _C1]:
225
225
  @_util.copy_func_kwargs(DatabaseOptions)
226
226
  def on_value_created(**kwargs) -> _typing.Callable[[_C2], _C2]:
227
227
  """
228
- Event handler which triggers when data is created in Realtime Database.
228
+ Event handler that triggers when data is created in Realtime Database.
229
229
 
230
230
  Example:
231
231
 
@@ -275,7 +275,7 @@ def on_value_created(**kwargs) -> _typing.Callable[[_C2], _C2]:
275
275
  @_util.copy_func_kwargs(DatabaseOptions)
276
276
  def on_value_deleted(**kwargs) -> _typing.Callable[[_C2], _C2]:
277
277
  """
278
- Event handler which triggers when data is deleted in Realtime Database.
278
+ Event handler that triggers when data is deleted in Realtime Database.
279
279
 
280
280
  Example:
281
281
 
@@ -38,6 +38,11 @@ _event_type_created = "google.cloud.firestore.document.v1.created"
38
38
  _event_type_updated = "google.cloud.firestore.document.v1.updated"
39
39
  _event_type_deleted = "google.cloud.firestore.document.v1.deleted"
40
40
 
41
+ _event_type_written_with_auth_context = "google.cloud.firestore.document.v1.written.withAuthContext"
42
+ _event_type_created_with_auth_context = "google.cloud.firestore.document.v1.created.withAuthContext"
43
+ _event_type_updated_with_auth_context = "google.cloud.firestore.document.v1.updated.withAuthContext"
44
+ _event_type_deleted_with_auth_context = "google.cloud.firestore.document.v1.deleted.withAuthContext"
45
+
41
46
 
42
47
  @_dataclass.dataclass(frozen=True)
43
48
  class Event(_core.CloudEvent[_core.T]):
@@ -82,9 +87,26 @@ _E2 = Event[DocumentSnapshot | None]
82
87
  _C1 = _typing.Callable[[_E1], None]
83
88
  _C2 = _typing.Callable[[_E2], None]
84
89
 
90
+ AuthType = _typing.Literal["service_account", "api_key", "system",
91
+ "unauthenticated", "unknown"]
92
+
93
+
94
+ @_dataclass.dataclass(frozen=True)
95
+ class AuthEvent(Event[_core.T]):
96
+ auth_type: AuthType
97
+ """The type of principal that triggered the event"""
98
+ auth_id: str | None
99
+ """The unique identifier for the principal"""
100
+
101
+
102
+ _E3 = AuthEvent[Change[DocumentSnapshot | None]]
103
+ _E4 = AuthEvent[DocumentSnapshot | None]
104
+ _C3 = _typing.Callable[[_E3], None]
105
+ _C4 = _typing.Callable[[_E4], None]
106
+
85
107
 
86
108
  def _firestore_endpoint_handler(
87
- func: _C1 | _C2,
109
+ func: _C1 | _C2 | _C3 | _C4,
88
110
  event_type: str,
89
111
  document_pattern: _path_pattern.PathPattern,
90
112
  raw: _ce.CloudEvent,
@@ -94,12 +116,14 @@ def _firestore_endpoint_handler(
94
116
  firestore_event_data: _firestore.DocumentEventData
95
117
  content_type: str = event_attributes["datacontenttype"]
96
118
  if "application/json" in content_type or isinstance(event_data, dict):
97
- firestore_event_data = _firestore.DocumentEventData.from_json(
98
- event_data)
119
+ firestore_event_data = _typing.cast(
120
+ _firestore.DocumentEventData,
121
+ _firestore.DocumentEventData.from_json(event_data))
99
122
  elif "application/protobuf" in content_type or isinstance(
100
123
  event_data, bytes):
101
- firestore_event_data = _firestore.DocumentEventData.deserialize(
102
- event_data)
124
+ firestore_event_data = _typing.cast(
125
+ _firestore.DocumentEventData,
126
+ _firestore.DocumentEventData.deserialize(event_data))
103
127
  else:
104
128
  actual_type = type(event_data)
105
129
  raise TypeError(f"Firestore: Cannot parse event payload of data type "
@@ -110,6 +134,8 @@ def _firestore_endpoint_handler(
110
134
  event_namespace = event_attributes["namespace"]
111
135
  event_document = event_attributes["document"]
112
136
  event_database = event_attributes["database"]
137
+ event_auth_type = event_attributes["authtype"]
138
+ event_auth_id = event_attributes["authid"]
113
139
 
114
140
  time = event_attributes["time"]
115
141
  event_time = _util.timestamp_conversion(time)
@@ -146,18 +172,23 @@ def _firestore_endpoint_handler(
146
172
  firestore_event_data.old_value.update_time,
147
173
  )
148
174
  if event_type == _event_type_deleted:
149
- firestore_event_data = old_value_snapshot
175
+ firestore_event_data = _typing.cast(_firestore.DocumentEventData,
176
+ old_value_snapshot)
150
177
  if event_type == _event_type_created:
151
- firestore_event_data = value_snapshot
178
+ firestore_event_data = _typing.cast(_firestore.DocumentEventData,
179
+ value_snapshot)
152
180
  if event_type in (_event_type_written, _event_type_updated):
153
- firestore_event_data = Change(
154
- before=old_value_snapshot,
155
- after=value_snapshot,
156
- )
181
+ firestore_event_data = _typing.cast(
182
+ _firestore.DocumentEventData,
183
+ Change(
184
+ before=old_value_snapshot,
185
+ after=value_snapshot,
186
+ ))
157
187
 
158
188
  params: dict[str, str] = {
159
189
  **document_pattern.extract_matches(event_document),
160
190
  }
191
+
161
192
  database_event = Event(
162
193
  project=event_project,
163
194
  namespace=event_namespace,
@@ -173,7 +204,15 @@ def _firestore_endpoint_handler(
173
204
  subject=event_attributes["subject"],
174
205
  params=params,
175
206
  )
176
- func(database_event)
207
+
208
+ if event_type.endswith(".withAuthContext"):
209
+ database_event_with_auth_context = AuthEvent(**vars(database_event),
210
+ auth_type=event_auth_type,
211
+ auth_id=event_auth_id)
212
+ func(database_event_with_auth_context)
213
+ else:
214
+ # mypy cannot infer that the event type is correct, hence the cast
215
+ _typing.cast(_C1 | _C2, func)(database_event)
177
216
 
178
217
 
179
218
  @_util.copy_func_kwargs(FirestoreOptions)
@@ -224,6 +263,57 @@ def on_document_written(**kwargs) -> _typing.Callable[[_C1], _C1]:
224
263
  return on_document_written_inner_decorator
225
264
 
226
265
 
266
+ @_util.copy_func_kwargs(FirestoreOptions)
267
+ def on_document_written_with_auth_context(**kwargs
268
+ ) -> _typing.Callable[[_C1], _C1]:
269
+ """
270
+ Event handler that triggers when a document is created, updated, or deleted in Firestore.
271
+ This trigger will also provide the authentication context of the principal who triggered
272
+ the event.
273
+
274
+ Example:
275
+
276
+ .. code-block:: python
277
+
278
+ @on_document_written_with_auth_context(document="*")
279
+ def example(event: AuthEvent[Change[DocumentSnapshot]]) -> None:
280
+ pass
281
+
282
+ :param \\*\\*kwargs: Firestore options.
283
+ :type \\*\\*kwargs: as :exc:`firebase_functions.options.FirestoreOptions`
284
+ :rtype: :exc:`typing.Callable`
285
+ \\[ \\[ :exc:`firebase_functions.firestore_fn.AuthEvent` \\[
286
+ :exc:`firebase_functions.db.Change` \\] \\], `None` \\]
287
+ A function that takes a Firestore event and returns ``None``.
288
+ """
289
+ options = FirestoreOptions(**kwargs)
290
+
291
+ def on_document_written_with_auth_context_inner_decorator(func: _C1):
292
+ document_pattern = _path_pattern.PathPattern(
293
+ _util.normalize_path(options.document))
294
+
295
+ @_functools.wraps(func)
296
+ def on_document_written_with_auth_context_wrapped(raw: _ce.CloudEvent):
297
+ return _firestore_endpoint_handler(
298
+ func,
299
+ _event_type_written_with_auth_context,
300
+ document_pattern,
301
+ raw,
302
+ )
303
+
304
+ _util.set_func_endpoint_attr(
305
+ on_document_written_with_auth_context_wrapped,
306
+ options._endpoint(
307
+ event_type=_event_type_written,
308
+ func_name=func.__name__,
309
+ document_pattern=document_pattern,
310
+ ),
311
+ )
312
+ return on_document_written_with_auth_context_wrapped
313
+
314
+ return on_document_written_with_auth_context_inner_decorator
315
+
316
+
227
317
  @_util.copy_func_kwargs(FirestoreOptions)
228
318
  def on_document_updated(**kwargs) -> _typing.Callable[[_C1], _C1]:
229
319
  """
@@ -272,6 +362,57 @@ def on_document_updated(**kwargs) -> _typing.Callable[[_C1], _C1]:
272
362
  return on_document_updated_inner_decorator
273
363
 
274
364
 
365
+ @_util.copy_func_kwargs(FirestoreOptions)
366
+ def on_document_updated_with_auth_context(**kwargs
367
+ ) -> _typing.Callable[[_C1], _C1]:
368
+ """
369
+ Event handler that triggers when a document is updated in Firestore.
370
+ This trigger will also provide the authentication context of the principal who triggered
371
+ the event.
372
+
373
+ Example:
374
+
375
+ .. code-block:: python
376
+
377
+ @on_document_updated_with_auth_context(document="*")
378
+ def example(event: AuthEvent[Change[DocumentSnapshot]]) -> None:
379
+ pass
380
+
381
+ :param \\*\\*kwargs: Firestore options.
382
+ :type \\*\\*kwargs: as :exc:`firebase_functions.options.FirestoreOptions`
383
+ :rtype: :exc:`typing.Callable`
384
+ \\[ \\[ :exc:`firebase_functions.firestore_fn.AuthEvent` \\[
385
+ :exc:`firebase_functions.db.Change` \\] \\], `None` \\]
386
+ A function that takes a Firestore event and returns ``None``.
387
+ """
388
+ options = FirestoreOptions(**kwargs)
389
+
390
+ def on_document_updated_with_auth_context_inner_decorator(func: _C1):
391
+ document_pattern = _path_pattern.PathPattern(
392
+ _util.normalize_path(options.document))
393
+
394
+ @_functools.wraps(func)
395
+ def on_document_updated_with_auth_context_wrapped(raw: _ce.CloudEvent):
396
+ return _firestore_endpoint_handler(
397
+ func,
398
+ _event_type_updated_with_auth_context,
399
+ document_pattern,
400
+ raw,
401
+ )
402
+
403
+ _util.set_func_endpoint_attr(
404
+ on_document_updated_with_auth_context_wrapped,
405
+ options._endpoint(
406
+ event_type=_event_type_updated_with_auth_context,
407
+ func_name=func.__name__,
408
+ document_pattern=document_pattern,
409
+ ),
410
+ )
411
+ return on_document_updated_with_auth_context_wrapped
412
+
413
+ return on_document_updated_with_auth_context_inner_decorator
414
+
415
+
275
416
  @_util.copy_func_kwargs(FirestoreOptions)
276
417
  def on_document_created(**kwargs) -> _typing.Callable[[_C2], _C2]:
277
418
  """
@@ -320,6 +461,57 @@ def on_document_created(**kwargs) -> _typing.Callable[[_C2], _C2]:
320
461
  return on_document_created_inner_decorator
321
462
 
322
463
 
464
+ @_util.copy_func_kwargs(FirestoreOptions)
465
+ def on_document_created_with_auth_context(**kwargs
466
+ ) -> _typing.Callable[[_C2], _C2]:
467
+ """
468
+ Event handler that triggers when a document is created in Firestore.
469
+ This trigger will also provide the authentication context of the principal who triggered
470
+ the event.
471
+
472
+ Example:
473
+
474
+ .. code-block:: python
475
+
476
+ @on_document_created_with_auth_context(document="*")
477
+ def example(event: AuthEvent[DocumentSnapshot]):
478
+ pass
479
+
480
+ :param \\*\\*kwargs: Firestore options.
481
+ :type \\*\\*kwargs: as :exc:`firebase_functions.options.FirestoreOptions`
482
+ :rtype: :exc:`typing.Callable`
483
+ \\[ \\[ :exc:`firebase_functions.firestore_fn.AuthEvent` \\[
484
+ :exc:`object` \\] \\], `None` \\]
485
+ A function that takes a Firestore event and returns ``None``.
486
+ """
487
+ options = FirestoreOptions(**kwargs)
488
+
489
+ def on_document_created_with_auth_context_inner_decorator(func: _C2):
490
+ document_pattern = _path_pattern.PathPattern(
491
+ _util.normalize_path(options.document))
492
+
493
+ @_functools.wraps(func)
494
+ def on_document_created_with_auth_context_wrapped(raw: _ce.CloudEvent):
495
+ return _firestore_endpoint_handler(
496
+ func,
497
+ _event_type_created_with_auth_context,
498
+ document_pattern,
499
+ raw,
500
+ )
501
+
502
+ _util.set_func_endpoint_attr(
503
+ on_document_created_with_auth_context_wrapped,
504
+ options._endpoint(
505
+ event_type=_event_type_created_with_auth_context,
506
+ func_name=func.__name__,
507
+ document_pattern=document_pattern,
508
+ ),
509
+ )
510
+ return on_document_created_with_auth_context_wrapped
511
+
512
+ return on_document_created_with_auth_context_inner_decorator
513
+
514
+
323
515
  @_util.copy_func_kwargs(FirestoreOptions)
324
516
  def on_document_deleted(**kwargs) -> _typing.Callable[[_C2], _C2]:
325
517
  """
@@ -366,3 +558,54 @@ def on_document_deleted(**kwargs) -> _typing.Callable[[_C2], _C2]:
366
558
  return on_document_deleted_wrapped
367
559
 
368
560
  return on_document_deleted_inner_decorator
561
+
562
+
563
+ @_util.copy_func_kwargs(FirestoreOptions)
564
+ def on_document_deleted_with_auth_context(**kwargs
565
+ ) -> _typing.Callable[[_C2], _C2]:
566
+ """
567
+ Event handler that triggers when a document is deleted in Firestore.
568
+ This trigger will also provide the authentication context of the principal who triggered
569
+ the event.
570
+
571
+ Example:
572
+
573
+ .. code-block:: python
574
+
575
+ @on_document_deleted_with_auth_context(document="*")
576
+ def example(event: AuthEvent[DocumentSnapshot]) -> None:
577
+ pass
578
+
579
+ :param \\*\\*kwargs: Firestore options.
580
+ :type \\*\\*kwargs: as :exc:`firebase_functions.options.FirestoreOptions`
581
+ :rtype: :exc:`typing.Callable`
582
+ \\[ \\[ :exc:`firebase_functions.firestore_fn.AuthEvent` \\[
583
+ :exc:`object` \\] \\], `None` \\]
584
+ A function that takes a Firestore event and returns ``None``.
585
+ """
586
+ options = FirestoreOptions(**kwargs)
587
+
588
+ def on_document_deleted_with_auth_context_inner_decorator(func: _C2):
589
+ document_pattern = _path_pattern.PathPattern(
590
+ _util.normalize_path(options.document))
591
+
592
+ @_functools.wraps(func)
593
+ def on_document_deleted_with_auth_context_wrapped(raw: _ce.CloudEvent):
594
+ return _firestore_endpoint_handler(
595
+ func,
596
+ _event_type_deleted_with_auth_context,
597
+ document_pattern,
598
+ raw,
599
+ )
600
+
601
+ _util.set_func_endpoint_attr(
602
+ on_document_deleted_with_auth_context_wrapped,
603
+ options._endpoint(
604
+ event_type=_event_type_deleted_with_auth_context,
605
+ func_name=func.__name__,
606
+ document_pattern=document_pattern,
607
+ ),
608
+ )
609
+ return on_document_deleted_with_auth_context_wrapped
610
+
611
+ return on_document_deleted_with_auth_context_inner_decorator
@@ -119,9 +119,9 @@ class FunctionsErrorCode(str, _enum.Enum):
119
119
 
120
120
  INTERNAL = "internal"
121
121
  """
122
- Internal errors. Means some invariants expected by
122
+ Internal errors. Means some invariants expected by the
123
123
  underlying system have been broken. If you see one of these errors,
124
- something is very broken.
124
+ something is severely broken.
125
125
  """
126
126
 
127
127
  UNAVAILABLE = "unavailable"
@@ -135,6 +135,9 @@ class FunctionsErrorCode(str, _enum.Enum):
135
135
  Unrecoverable data loss or corruption.
136
136
  """
137
137
 
138
+ def __str__(self) -> str:
139
+ return self.value
140
+
138
141
 
139
142
  class _CanonicalErrorCodeName(str, _enum.Enum):
140
143
  """The canonical error code name for a given error code."""
@@ -157,6 +160,9 @@ class _CanonicalErrorCodeName(str, _enum.Enum):
157
160
  UNAVAILABLE = "UNAVAILABLE"
158
161
  DATA_LOSS = "DATA_LOSS"
159
162
 
163
+ def __str__(self) -> str:
164
+ return self.value
165
+
160
166
 
161
167
  @_dataclasses.dataclass(frozen=True)
162
168
  class _HttpErrorCode:
@@ -280,7 +286,7 @@ class AuthData:
280
286
  The interface for Auth tokens verified in Callable functions
281
287
  """
282
288
 
283
- uid: str
289
+ uid: str | None
284
290
  """
285
291
  User ID of the ID token.
286
292
  """
@@ -346,8 +352,10 @@ _C1 = _typing.Callable[[Request], Response]
346
352
  _C2 = _typing.Callable[[CallableRequest[_typing.Any]], _typing.Any]
347
353
 
348
354
 
349
- def _on_call_handler(func: _C2, request: Request,
350
- enforce_app_check: bool) -> Response:
355
+ def _on_call_handler(func: _C2,
356
+ request: Request,
357
+ enforce_app_check: bool,
358
+ verify_token: bool = True) -> Response:
351
359
  try:
352
360
  if not _util.valid_on_call_request(request):
353
361
  _logging.error("Invalid request, unable to process.")
@@ -357,7 +365,8 @@ def _on_call_handler(func: _C2, request: Request,
357
365
  data=_json.loads(request.data)["data"],
358
366
  )
359
367
 
360
- token_status = _util.on_call_check_tokens(request)
368
+ token_status = _util.on_call_check_tokens(request,
369
+ verify_token=verify_token)
361
370
 
362
371
  if token_status.auth == _util.OnCallTokenState.INVALID:
363
372
  raise HttpsError(FunctionsErrorCode.UNAUTHENTICATED,
@@ -377,8 +386,10 @@ def _on_call_handler(func: _C2, request: Request,
377
386
  if token_status.auth_token is not None:
378
387
  context = _dataclasses.replace(
379
388
  context,
380
- auth=AuthData(token_status.auth_token["uid"],
381
- token_status.auth_token),
389
+ auth=AuthData(
390
+ token_status.auth_token["uid"]
391
+ if "uid" in token_status.auth_token else None,
392
+ token_status.auth_token),
382
393
  )
383
394
 
384
395
  instance_id = request.headers.get("Firebase-Instance-ID-Token")
@@ -399,7 +410,7 @@ def _on_call_handler(func: _C2, request: Request,
399
410
  # pylint: disable=broad-except
400
411
  except Exception as err:
401
412
  if not isinstance(err, HttpsError):
402
- _logging.error("Unhandled error", err)
413
+ _logging.error("Unhandled error: %s", err)
403
414
  err = HttpsError(FunctionsErrorCode.INTERNAL, "INTERNAL")
404
415
  status = err._http_error_code.status
405
416
  return _make_response(_jsonify(error=err._as_dict()), status)
@@ -36,7 +36,7 @@ class AuthUserInfo:
36
36
  """The user identifier for the linked provider."""
37
37
 
38
38
  provider_id: str
39
- """The linked provider ID (e.g., "google.com" for the Google provider)."""
39
+ """The linked provider ID (such as "google.com" for the Google provider)."""
40
40
 
41
41
  display_name: str | None = None
42
42
  """The display name for the linked provider."""
@@ -110,7 +110,7 @@ class AuthMultiFactorSettings:
110
110
  @_dataclasses.dataclass(frozen=True)
111
111
  class AuthUserRecord:
112
112
  """
113
- The UserRecord passed to auth blocking Cloud Functions from the identity platform.
113
+ The UserRecord passed to auth blocking functions from the identity platform.
114
114
  """
115
115
 
116
116
  uid: str
@@ -155,7 +155,7 @@ class AuthUserRecord:
155
155
 
156
156
  provider_data: list[AuthUserInfo]
157
157
  """
158
- An array of providers (e.g., Google, Facebook) linked to the user.
158
+ An array of providers (such as Google or Facebook) linked to the user.
159
159
  """
160
160
 
161
161
  password_hash: str | None
@@ -203,6 +203,9 @@ class AdditionalUserInfo:
203
203
  is_new_user: bool
204
204
  """A boolean indicating if the user is new or not."""
205
205
 
206
+ recaptcha_score: float | None
207
+ """The user's reCAPTCHA score, if available."""
208
+
206
209
 
207
210
  @_dataclasses.dataclass(frozen=True)
208
211
  class Credential:
@@ -243,7 +246,7 @@ class AuthBlockingEvent:
243
246
 
244
247
  data: AuthUserRecord
245
248
  """
246
- The UserRecord passed to auth blocking Cloud Functions from the identity platform.
249
+ The UserRecord passed to auth blocking functions from the identity platform.
247
250
  """
248
251
 
249
252
  locale: str | None
@@ -282,6 +285,12 @@ class AuthBlockingEvent:
282
285
  The time the event was triggered."""
283
286
 
284
287
 
288
+ RecaptchaActionOptions = _typing.Literal["ALLOW", "BLOCK"]
289
+ """
290
+ The reCAPTCHA action options.
291
+ """
292
+
293
+
285
294
  class BeforeCreateResponse(_typing.TypedDict, total=False):
286
295
  """
287
296
  The handler response type for 'before_user_created' blocking events.
@@ -302,6 +311,8 @@ class BeforeCreateResponse(_typing.TypedDict, total=False):
302
311
  custom_claims: dict[str, _typing.Any] | None
303
312
  """The user's custom claims object if available."""
304
313
 
314
+ recaptcha_action_override: RecaptchaActionOptions | None
315
+
305
316
 
306
317
  class BeforeSignInResponse(BeforeCreateResponse, total=False):
307
318
  """