firebase-functions 0.1.2__tar.gz → 0.2.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.
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/PKG-INFO +1 -1
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/__init__.py +1 -1
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/alerts_fn.py +2 -2
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/core.py +1 -1
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/db_fn.py +5 -5
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/https_fn.py +2 -2
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/identity_fn.py +15 -4
- firebase_functions-0.2.0/src/firebase_functions/logger.py +130 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/params.py +3 -3
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/_identity_fn.py +29 -8
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/util.py +2 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/pubsub_fn.py +1 -1
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/remote_config_fn.py +2 -2
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/storage_fn.py +1 -1
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/tasks_fn.py +1 -1
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions.egg-info/PKG-INFO +1 -1
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions.egg-info/SOURCES.txt +2 -0
- firebase_functions-0.2.0/tests/test_logger.py +81 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/LICENSE +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/README.md +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/pyproject.toml +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/setup.cfg +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/setup.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/alerts/__init__.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/alerts/app_distribution_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/alerts/billing_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/alerts/crashlytics_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/alerts/performance_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/eventarc_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/firestore_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/options.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/__init__.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/_alerts_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/manifest.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/path_pattern.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/serving.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/token_verifier.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/scheduler_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/test_lab_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions.egg-info/dependency_links.txt +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions.egg-info/requires.txt +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions.egg-info/top_level.txt +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_eventarc_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_manifest.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_options.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_params.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_path_pattern.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_pubsub_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_remote_config_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_scheduler_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_tasks_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_test_lab_fn.py +0 -0
- {firebase_functions-0.1.2 → firebase_functions-0.2.0}/tests/test_util.py +0 -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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
278
|
+
Event handler that triggers when data is deleted in Realtime Database.
|
|
279
279
|
|
|
280
280
|
Example:
|
|
281
281
|
|
|
@@ -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
|
|
124
|
+
something is severely broken.
|
|
125
125
|
"""
|
|
126
126
|
|
|
127
127
|
UNAVAILABLE = "unavailable"
|
|
@@ -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 (
|
|
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
|
|
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 (
|
|
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
|
|
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
|
"""
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Logger module for Firebase Functions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import enum as _enum
|
|
6
|
+
import json as _json
|
|
7
|
+
import sys as _sys
|
|
8
|
+
import typing as _typing
|
|
9
|
+
import typing_extensions as _typing_extensions
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LogSeverity(str, _enum.Enum):
|
|
13
|
+
"""
|
|
14
|
+
`LogSeverity` indicates the detailed severity of the log entry. See
|
|
15
|
+
`LogSeverity <https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity>`.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
DEBUG = "DEBUG"
|
|
19
|
+
INFO = "INFO"
|
|
20
|
+
NOTICE = "NOTICE"
|
|
21
|
+
WARNING = "WARNING"
|
|
22
|
+
ERROR = "ERROR"
|
|
23
|
+
CRITICAL = "CRITICAL"
|
|
24
|
+
ALERT = "ALERT"
|
|
25
|
+
EMERGENCY = "EMERGENCY"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class LogEntry(_typing.TypedDict):
|
|
29
|
+
"""
|
|
30
|
+
`LogEntry` represents a log entry.
|
|
31
|
+
See `LogEntry <https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry>`_.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
severity: _typing_extensions.Required[LogSeverity]
|
|
35
|
+
message: _typing_extensions.NotRequired[str]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _entry_from_args(severity: LogSeverity, *args, **kwargs) -> LogEntry:
|
|
39
|
+
"""
|
|
40
|
+
Creates a `LogEntry` from the given arguments.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
message: str = " ".join([
|
|
44
|
+
value
|
|
45
|
+
if isinstance(value, str) else _json.dumps(_remove_circular(value))
|
|
46
|
+
for value in args
|
|
47
|
+
])
|
|
48
|
+
|
|
49
|
+
other: _typing.Dict[str, _typing.Any] = {
|
|
50
|
+
key: value if isinstance(value, str) else _remove_circular(value)
|
|
51
|
+
for key, value in kwargs.items()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
entry: _typing.Dict[str, _typing.Any] = {"severity": severity, **other}
|
|
55
|
+
if message:
|
|
56
|
+
entry["message"] = message
|
|
57
|
+
|
|
58
|
+
return _typing.cast(LogEntry, entry)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _remove_circular(obj: _typing.Any,
|
|
62
|
+
refs: _typing.Set[_typing.Any] | None = None):
|
|
63
|
+
"""
|
|
64
|
+
Removes circular references from the given object and replaces them with "[CIRCULAR]".
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
if refs is None:
|
|
68
|
+
refs = set()
|
|
69
|
+
|
|
70
|
+
if id(obj) in refs:
|
|
71
|
+
return "[CIRCULAR]"
|
|
72
|
+
|
|
73
|
+
if not isinstance(obj, (str, int, float, bool, type(None))):
|
|
74
|
+
refs.add(id(obj))
|
|
75
|
+
|
|
76
|
+
if isinstance(obj, dict):
|
|
77
|
+
return {key: _remove_circular(value, refs) for key, value in obj.items()}
|
|
78
|
+
elif isinstance(obj, list):
|
|
79
|
+
return [_remove_circular(value, refs) for _, value in enumerate(obj)]
|
|
80
|
+
elif isinstance(obj, tuple):
|
|
81
|
+
return tuple(
|
|
82
|
+
_remove_circular(value, refs) for _, value in enumerate(obj))
|
|
83
|
+
else:
|
|
84
|
+
return obj
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _get_write_file(severity: LogSeverity) -> _typing.TextIO:
|
|
88
|
+
if severity == LogSeverity.ERROR:
|
|
89
|
+
return _sys.stderr
|
|
90
|
+
return _sys.stdout
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def write(entry: LogEntry) -> None:
|
|
94
|
+
write_file = _get_write_file(entry["severity"])
|
|
95
|
+
print(_json.dumps(_remove_circular(entry)), file=write_file)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def debug(*args, **kwargs) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Logs a debug message.
|
|
101
|
+
"""
|
|
102
|
+
write(_entry_from_args(LogSeverity.DEBUG, *args, **kwargs))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def log(*args, **kwargs) -> None:
|
|
106
|
+
"""
|
|
107
|
+
Logs a log message.
|
|
108
|
+
"""
|
|
109
|
+
write(_entry_from_args(LogSeverity.NOTICE, *args, **kwargs))
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def info(*args, **kwargs) -> None:
|
|
113
|
+
"""
|
|
114
|
+
Logs an info message.
|
|
115
|
+
"""
|
|
116
|
+
write(_entry_from_args(LogSeverity.INFO, *args, **kwargs))
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def warn(*args, **kwargs) -> None:
|
|
120
|
+
"""
|
|
121
|
+
Logs a warning message.
|
|
122
|
+
"""
|
|
123
|
+
write(_entry_from_args(LogSeverity.WARNING, *args, **kwargs))
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def error(*args, **kwargs) -> None:
|
|
127
|
+
"""
|
|
128
|
+
Logs an error message.
|
|
129
|
+
"""
|
|
130
|
+
write(_entry_from_args(LogSeverity.ERROR, *args, **kwargs))
|
|
@@ -144,18 +144,18 @@ class TextInput:
|
|
|
144
144
|
"""
|
|
145
145
|
Specifies that a Param's value should be determined by prompting the user
|
|
146
146
|
to type it in interactively at deploy-time. Input that does not match the provided
|
|
147
|
-
validation_regex, if present,
|
|
147
|
+
validation_regex, if present, is retried.
|
|
148
148
|
"""
|
|
149
149
|
|
|
150
150
|
example: str | None = None
|
|
151
151
|
"""
|
|
152
|
-
An example of the input required that
|
|
152
|
+
An example of the input required that is displayed alongside the input prompt.
|
|
153
153
|
"""
|
|
154
154
|
|
|
155
155
|
validation_regex: str | None = None
|
|
156
156
|
"""
|
|
157
157
|
Validation regex for the input.
|
|
158
|
-
Input that does not match this regex, if present,
|
|
158
|
+
Input that does not match this regex, if present, is retried.
|
|
159
159
|
"""
|
|
160
160
|
|
|
161
161
|
validation_error_message: str | None = None
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/_identity_fn.py
RENAMED
|
@@ -114,7 +114,7 @@ def _auth_user_record_from_token_data(token_data: dict[str, _typing.Any]):
|
|
|
114
114
|
return AuthUserRecord(
|
|
115
115
|
uid=token_data["uid"],
|
|
116
116
|
email=token_data.get("email"),
|
|
117
|
-
email_verified=token_data.get("email_verified"),
|
|
117
|
+
email_verified=bool(token_data.get("email_verified")),
|
|
118
118
|
display_name=token_data.get("display_name"),
|
|
119
119
|
photo_url=token_data.get("photo_url"),
|
|
120
120
|
phone_number=token_data.get("phone_number"),
|
|
@@ -165,6 +165,7 @@ def _additional_user_info_from_token_data(token_data: dict[str, _typing.Any]):
|
|
|
165
165
|
profile=profile,
|
|
166
166
|
username=username,
|
|
167
167
|
is_new_user=is_new_user,
|
|
168
|
+
recaptcha_score=token_data.get("recaptcha_score"),
|
|
168
169
|
)
|
|
169
170
|
|
|
170
171
|
|
|
@@ -302,9 +303,35 @@ def _validate_auth_response(
|
|
|
302
303
|
auth_response_dict["customClaims"] = auth_response["custom_claims"]
|
|
303
304
|
if "session_claims" in auth_response_keys:
|
|
304
305
|
auth_response_dict["sessionClaims"] = auth_response["session_claims"]
|
|
306
|
+
if "recaptcha_action_override" in auth_response_keys:
|
|
307
|
+
auth_response_dict["recaptchaActionOverride"] = auth_response[
|
|
308
|
+
"recaptcha_action_override"]
|
|
305
309
|
return auth_response_dict
|
|
306
310
|
|
|
307
311
|
|
|
312
|
+
def _generate_response_payload(
|
|
313
|
+
auth_response_dict: dict[str, _typing.Any] | None
|
|
314
|
+
) -> dict[str, _typing.Any]:
|
|
315
|
+
if not auth_response_dict:
|
|
316
|
+
return {}
|
|
317
|
+
|
|
318
|
+
formatted_auth_response = auth_response_dict.copy()
|
|
319
|
+
recaptcha_action_override = formatted_auth_response.pop(
|
|
320
|
+
"recaptchaActionOverride", None)
|
|
321
|
+
result = {}
|
|
322
|
+
update_mask = ",".join(formatted_auth_response.keys())
|
|
323
|
+
|
|
324
|
+
if len(update_mask) != 0:
|
|
325
|
+
result["userRecord"] = {
|
|
326
|
+
**formatted_auth_response, "updateMask": update_mask
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if recaptcha_action_override is not None:
|
|
330
|
+
result["recaptchaActionOverride"] = recaptcha_action_override
|
|
331
|
+
|
|
332
|
+
return result
|
|
333
|
+
|
|
334
|
+
|
|
308
335
|
def before_operation_handler(
|
|
309
336
|
func: _typing.Callable,
|
|
310
337
|
event_type: str,
|
|
@@ -329,13 +356,7 @@ def before_operation_handler(
|
|
|
329
356
|
if not auth_response:
|
|
330
357
|
return _jsonify({})
|
|
331
358
|
auth_response_dict = _validate_auth_response(event_type, auth_response)
|
|
332
|
-
|
|
333
|
-
result = {
|
|
334
|
-
"userRecord": {
|
|
335
|
-
**auth_response_dict,
|
|
336
|
-
"updateMask": update_mask,
|
|
337
|
-
}
|
|
338
|
-
}
|
|
359
|
+
result = _generate_response_payload(auth_response_dict)
|
|
339
360
|
return _jsonify(result)
|
|
340
361
|
# Disable broad exceptions lint since we want to handle all exceptions.
|
|
341
362
|
# pylint: disable=broad-except
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/util.py
RENAMED
|
@@ -387,6 +387,8 @@ def timestamp_conversion(time: str) -> _dt.datetime:
|
|
|
387
387
|
elif precision_timestamp == PrecisionTimestamp.SECONDS:
|
|
388
388
|
return second_timestamp_conversion(time)
|
|
389
389
|
|
|
390
|
+
raise ValueError("Invalid timestamp")
|
|
391
|
+
|
|
390
392
|
|
|
391
393
|
def microsecond_timestamp_conversion(time: str) -> _dt.datetime:
|
|
392
394
|
"""Converts a microsecond timestamp and returns a datetime object of the current time in UTC"""
|
|
@@ -157,7 +157,7 @@ def _message_handler(
|
|
|
157
157
|
@_util.copy_func_kwargs(PubSubOptions)
|
|
158
158
|
def on_message_published(**kwargs) -> _typing.Callable[[_C1], _C1]:
|
|
159
159
|
"""
|
|
160
|
-
Event handler
|
|
160
|
+
Event handler that triggers on a message being published to a Pub/Sub topic.
|
|
161
161
|
|
|
162
162
|
Example:
|
|
163
163
|
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/remote_config_fn.py
RENAMED
|
@@ -141,8 +141,8 @@ class ConfigUpdateData:
|
|
|
141
141
|
|
|
142
142
|
rollback_source: int | None = None
|
|
143
143
|
"""
|
|
144
|
-
Only present if this version is the result of a rollback, and
|
|
145
|
-
the version number of the Remote Config template that was rolled
|
|
144
|
+
Only present if this version is the result of a rollback, and is
|
|
145
|
+
the version number of the Remote Config template that was rolled back to.
|
|
146
146
|
"""
|
|
147
147
|
|
|
148
148
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""
|
|
15
|
-
|
|
15
|
+
Functions to handle events from Google Cloud Storage.
|
|
16
16
|
"""
|
|
17
17
|
# pylint: disable=protected-access
|
|
18
18
|
import dataclasses as _dataclasses
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
"""
|
|
14
|
+
"""Functions to handle Tasks enqueued with Google Cloud Tasks."""
|
|
15
15
|
|
|
16
16
|
# pylint: disable=protected-access
|
|
17
17
|
import typing as _typing
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions.egg-info/SOURCES.txt
RENAMED
|
@@ -10,6 +10,7 @@ src/firebase_functions/eventarc_fn.py
|
|
|
10
10
|
src/firebase_functions/firestore_fn.py
|
|
11
11
|
src/firebase_functions/https_fn.py
|
|
12
12
|
src/firebase_functions/identity_fn.py
|
|
13
|
+
src/firebase_functions/logger.py
|
|
13
14
|
src/firebase_functions/options.py
|
|
14
15
|
src/firebase_functions/params.py
|
|
15
16
|
src/firebase_functions/pubsub_fn.py
|
|
@@ -37,6 +38,7 @@ src/firebase_functions/private/serving.py
|
|
|
37
38
|
src/firebase_functions/private/token_verifier.py
|
|
38
39
|
src/firebase_functions/private/util.py
|
|
39
40
|
tests/test_eventarc_fn.py
|
|
41
|
+
tests/test_logger.py
|
|
40
42
|
tests/test_manifest.py
|
|
41
43
|
tests/test_options.py
|
|
42
44
|
tests/test_params.py
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Logger module tests.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
import json
|
|
7
|
+
from firebase_functions import logger
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestLogger:
|
|
11
|
+
"""
|
|
12
|
+
Tests for the logger module.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def test_format_should_be_valid_json(self,
|
|
16
|
+
capsys: pytest.CaptureFixture[str]):
|
|
17
|
+
logger.log(foo="bar")
|
|
18
|
+
raw_log_output = capsys.readouterr().out
|
|
19
|
+
try:
|
|
20
|
+
json.loads(raw_log_output)
|
|
21
|
+
except json.JSONDecodeError:
|
|
22
|
+
pytest.fail("Log output was not valid JSON.")
|
|
23
|
+
|
|
24
|
+
def test_log_should_have_severity(self, capsys: pytest.CaptureFixture[str]):
|
|
25
|
+
logger.log(foo="bar")
|
|
26
|
+
raw_log_output = capsys.readouterr().out
|
|
27
|
+
log_output = json.loads(raw_log_output)
|
|
28
|
+
assert "severity" in log_output
|
|
29
|
+
|
|
30
|
+
def test_severity_should_be_debug(self, capsys: pytest.CaptureFixture[str]):
|
|
31
|
+
logger.debug(foo="bar")
|
|
32
|
+
raw_log_output = capsys.readouterr().out
|
|
33
|
+
log_output = json.loads(raw_log_output)
|
|
34
|
+
assert log_output["severity"] == "DEBUG"
|
|
35
|
+
|
|
36
|
+
def test_severity_should_be_notice(self,
|
|
37
|
+
capsys: pytest.CaptureFixture[str]):
|
|
38
|
+
logger.log(foo="bar")
|
|
39
|
+
raw_log_output = capsys.readouterr().out
|
|
40
|
+
log_output = json.loads(raw_log_output)
|
|
41
|
+
assert log_output["severity"] == "NOTICE"
|
|
42
|
+
|
|
43
|
+
def test_severity_should_be_info(self, capsys: pytest.CaptureFixture[str]):
|
|
44
|
+
logger.info(foo="bar")
|
|
45
|
+
raw_log_output = capsys.readouterr().out
|
|
46
|
+
log_output = json.loads(raw_log_output)
|
|
47
|
+
assert log_output["severity"] == "INFO"
|
|
48
|
+
|
|
49
|
+
def test_severity_should_be_warning(self,
|
|
50
|
+
capsys: pytest.CaptureFixture[str]):
|
|
51
|
+
logger.warn(foo="bar")
|
|
52
|
+
raw_log_output = capsys.readouterr().out
|
|
53
|
+
log_output = json.loads(raw_log_output)
|
|
54
|
+
assert log_output["severity"] == "WARNING"
|
|
55
|
+
|
|
56
|
+
def test_severity_should_be_error(self, capsys: pytest.CaptureFixture[str]):
|
|
57
|
+
logger.error(foo="bar")
|
|
58
|
+
raw_log_output = capsys.readouterr().err
|
|
59
|
+
log_output = json.loads(raw_log_output)
|
|
60
|
+
assert log_output["severity"] == "ERROR"
|
|
61
|
+
|
|
62
|
+
def test_log_should_have_message(self, capsys: pytest.CaptureFixture[str]):
|
|
63
|
+
logger.log("bar")
|
|
64
|
+
raw_log_output = capsys.readouterr().out
|
|
65
|
+
log_output = json.loads(raw_log_output)
|
|
66
|
+
assert "message" in log_output
|
|
67
|
+
|
|
68
|
+
def test_log_should_have_other_keys(self,
|
|
69
|
+
capsys: pytest.CaptureFixture[str]):
|
|
70
|
+
logger.log(foo="bar")
|
|
71
|
+
raw_log_output = capsys.readouterr().out
|
|
72
|
+
log_output = json.loads(raw_log_output)
|
|
73
|
+
assert "foo" in log_output
|
|
74
|
+
|
|
75
|
+
def test_message_should_be_space_separated(
|
|
76
|
+
self, capsys: pytest.CaptureFixture[str]):
|
|
77
|
+
logger.log("bar", "qux")
|
|
78
|
+
expected_message = "bar qux"
|
|
79
|
+
raw_log_output = capsys.readouterr().out
|
|
80
|
+
log_output = json.loads(raw_log_output)
|
|
81
|
+
assert log_output["message"] == expected_message
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/alerts/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/alerts/billing_fn.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/firestore_fn.py
RENAMED
|
File without changes
|
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/__init__.py
RENAMED
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/_alerts_fn.py
RENAMED
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/manifest.py
RENAMED
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/path_pattern.py
RENAMED
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/private/serving.py
RENAMED
|
File without changes
|
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions/scheduler_fn.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions.egg-info/requires.txt
RENAMED
|
File without changes
|
{firebase_functions-0.1.2 → firebase_functions-0.2.0}/src/firebase_functions.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|