Skip to content

Commit 8a9a81f

Browse files
Merge master into release
2 parents d2e4774 + f002ef3 commit 8a9a81f

32 files changed

+365
-200
lines changed

.changeset/afraid-waves-remember.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/auth": patch
3+
---
4+
5+
Fix FetchProvider in non-browser environments, by trying to get the `fetch` implementation from not only `self` but also standard `globalThis`.

.changeset/flat-eagles-obey.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

.changeset/khaki-apricots-doubt.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@firebase/auth': patch
3+
---
4+
5+
Create getProviderEnforcementState method to get reCAPTCHA Enterprise enforcement state of a provider.
6+
This is an internal code change preparing for future features.

.changeset/lucky-dragons-juggle.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/auth': patch
3+
---
4+
5+
Create handleRecaptchaFlow helper method

.changeset/quick-otters-applaud.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/firestore': patch
3+
---
4+
5+
Clarify method documentation.

.github/workflows/test-changed-firestore-integration.yml

+15-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
- uses: 'google-github-actions/auth@v0'
1717
with:
1818
credentials_json: '${{ secrets.JSSDK_ACTIONS_SA_KEY }}'
19+
1920
# create composite indexes with Terraform
2021
- name: Setup Terraform
2122
uses: hashicorp/setup-terraform@v2
@@ -29,8 +30,21 @@ jobs:
2930
if: github.event_name == 'pull_request'
3031
run: |
3132
cd packages/firestore
32-
terraform apply -var-file=../../config/project.json -auto-approve
33+
34+
# Define a temporary file, redirect both stdout and stderr to it
35+
output_file=$(mktemp)
36+
if ! terraform apply -var-file=../../config/project.json -auto-approve > "$output_file" 2>&1 ; then
37+
cat "$output_file"
38+
if cat "$output_file" | grep -q "index already exists"; then
39+
echo "==================================================================================="
40+
echo -e "\e[93m\e[1mTerraform apply failed due to index already exists; We can safely ignore this error.\e[0m"
41+
echo "==================================================================================="
42+
fi
43+
exit 1
44+
fi
45+
rm -f "$output_file"
3346
continue-on-error: true
47+
3448
- name: Set up Node (16)
3549
uses: actions/setup-node@v3
3650
with:

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,4 @@ toc/
9797
.terraform/*
9898
.terraform.lock.hcl
9999
*.tfstate
100-
*.tfstate.*
100+
*.tfstate.*

common/api-review/firestore.api.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -299,15 +299,15 @@ export function getDocsFromCache<AppModelType, DbModelType extends DocumentData>
299299
// @public
300300
export function getDocsFromServer<AppModelType, DbModelType extends DocumentData>(query: Query<AppModelType, DbModelType>): Promise<QuerySnapshot<AppModelType, DbModelType>>;
301301

302+
// @public
303+
export function getFirestore(): Firestore;
304+
302305
// @public
303306
export function getFirestore(app: FirebaseApp): Firestore;
304307

305308
// @beta
306309
export function getFirestore(databaseId: string): Firestore;
307310

308-
// @public
309-
export function getFirestore(): Firestore;
310-
311311
// @beta
312312
export function getFirestore(app: FirebaseApp, databaseId: string): Firestore;
313313

docs-devsite/app-check.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export declare function onTokenChanged(appCheckInstance: AppCheck, onNext: (toke
155155
| Parameter | Type | Description |
156156
| --- | --- | --- |
157157
| appCheckInstance | [AppCheck](./app-check.appcheck.md#appcheck_interface) | The App Check service instance. |
158-
| onNext | (tokenResult: [AppCheckTokenResult](./app-check.appchecktokenresult.md#appchecktokenresult_interface)<!-- -->) =&gt; void | When the token changes, this function is called with aa [AppCheckTokenResult](./app-check.appchecktokenresult.md#appchecktokenresult_interface)<!-- -->. |
158+
| onNext | (tokenResult: [AppCheckTokenResult](./app-check.appchecktokenresult.md#appchecktokenresult_interface)<!-- -->) =&gt; void | When the token changes, this function is called with an [AppCheckTokenResult](./app-check.appchecktokenresult.md#appchecktokenresult_interface)<!-- -->. |
159159
| onError | (error: Error) =&gt; void | Optional. Called if there is an error thrown by the listener (the <code>onNext</code> function). |
160160
| onCompletion | () =&gt; void | Currently unused, as the token stream is unending. |
161161

docs-devsite/firestore_.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ https://github.com/firebase/firebase-js-sdk
1717
| --- | --- |
1818
| <b>function(app...)</b> |
1919
| [getFirestore(app)](./firestore_.md#getfirestore) | Returns the existing default [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the provided [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings. |
20-
| [getFirestore(app, databaseId)](./firestore_.md#getfirestore) | <b><i>(BETA)</i></b> Returns the existing default [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the provided [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings. |
20+
| [getFirestore(app, databaseId)](./firestore_.md#getfirestore) | <b><i>(BETA)</i></b> Returns the existing named [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the provided [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings. |
2121
| [initializeFirestore(app, settings, databaseId)](./firestore_.md#initializefirestore) | Initializes a new instance of [Firestore](./firestore_.firestore.md#firestore_class) with the provided settings. Can only be called before any other function, including [getFirestore()](./firestore_.md#getfirestore)<!-- -->. If the custom settings are empty, this function is equivalent to calling [getFirestore()](./firestore_.md#getfirestore)<!-- -->. |
2222
| <b>function(firestore...)</b> |
2323
| [clearIndexedDbPersistence(firestore)](./firestore_.md#clearindexeddbpersistence) | Clears the persistent storage. This includes pending writes and cached documents.<!-- -->Must be called while the [Firestore](./firestore_.firestore.md#firestore_class) instance is not started (after the app is terminated or when the app is first initialized). On startup, this function must be called before other functions (other than [initializeFirestore()](./firestore_.md#initializefirestore) or [getFirestore()](./firestore_.md#getfirestore)<!-- -->)). If the [Firestore](./firestore_.firestore.md#firestore_class) instance is still running, the promise will be rejected with the error code of <code>failed-precondition</code>.<!-- -->Note: <code>clearIndexedDbPersistence()</code> is primarily intended to help write reliable tests that use Cloud Firestore. It uses an efficient mechanism for dropping existing data but does not attempt to securely overwrite or otherwise make cached data unrecoverable. For applications that are sensitive to the disclosure of cached data in between user sessions, we strongly recommend not enabling persistence at all. |
@@ -49,7 +49,7 @@ https://github.com/firebase/firebase-js-sdk
4949
| [persistentMultipleTabManager()](./firestore_.md#persistentmultipletabmanager) | Creates an instance of <code>PersistentMultipleTabManager</code>. |
5050
| [serverTimestamp()](./firestore_.md#servertimestamp) | Returns a sentinel used with [setDoc()](./firestore_lite.md#setdoc) or [updateDoc()](./firestore_lite.md#updatedoc) to include a server-generated timestamp in the written data. |
5151
| <b>function(databaseId...)</b> |
52-
| [getFirestore(databaseId)](./firestore_.md#getfirestore) | <b><i>(BETA)</i></b> Returns the existing [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the default [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings. |
52+
| [getFirestore(databaseId)](./firestore_.md#getfirestore) | <b><i>(BETA)</i></b> Returns the existing named [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the default [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings. |
5353
| <b>function(elements...)</b> |
5454
| [arrayRemove(elements)](./firestore_.md#arrayremove) | Returns a special value that can be used with [setDoc()](./firestore_.md#setdoc) or that tells the server to remove the given elements from any array value that already exists on the server. All instances of each element specified will be removed from the array. If the field being modified is not already an array it will be overwritten with an empty array. |
5555
| [arrayUnion(elements)](./firestore_.md#arrayunion) | Returns a special value that can be used with [setDoc()](./firestore_lite.md#setdoc) or [updateDoc()](./firestore_lite.md#updatedoc) that tells the server to union the given elements with any array value that already exists on the server. Each specified element that doesn't already exist in the array will be added to the end. If the field being modified is not already an array it will be overwritten with an array containing exactly the specified elements. |
@@ -240,14 +240,14 @@ export declare function getFirestore(app: FirebaseApp): Firestore;
240240

241241
[Firestore](./firestore_.firestore.md#firestore_class)
242242

243-
The [Firestore](./firestore_.firestore.md#firestore_class) instance of the provided app.
243+
The default [Firestore](./firestore_.firestore.md#firestore_class) instance of the provided app.
244244

245245
## getFirestore()
246246

247247
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
248248
>
249249
250-
Returns the existing default [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the provided [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings.
250+
Returns the existing named [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the provided [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings.
251251

252252
<b>Signature:</b>
253253

@@ -266,7 +266,7 @@ export declare function getFirestore(app: FirebaseApp, databaseId: string): Fire
266266

267267
[Firestore](./firestore_.firestore.md#firestore_class)
268268

269-
The [Firestore](./firestore_.firestore.md#firestore_class) instance of the provided app.
269+
The named [Firestore](./firestore_.firestore.md#firestore_class) instance of the provided app.
270270

271271
## initializeFirestore()
272272

@@ -901,7 +901,7 @@ export declare function getFirestore(): Firestore;
901901

902902
[Firestore](./firestore_.firestore.md#firestore_class)
903903

904-
The [Firestore](./firestore_.firestore.md#firestore_class) instance of the provided app.
904+
The default [Firestore](./firestore_.firestore.md#firestore_class) instance of the default app.
905905

906906
## memoryEagerGarbageCollector()
907907

@@ -947,7 +947,7 @@ export declare function serverTimestamp(): FieldValue;
947947
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
948948
>
949949
950-
Returns the existing [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the default [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings.
950+
Returns the existing named [Firestore](./firestore_.firestore.md#firestore_class) instance that is associated with the default [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface)<!-- -->. If no instance exists, initializes a new instance with default settings.
951951

952952
<b>Signature:</b>
953953

@@ -965,7 +965,7 @@ export declare function getFirestore(databaseId: string): Firestore;
965965

966966
[Firestore](./firestore_.firestore.md#firestore_class)
967967

968-
The [Firestore](./firestore_.firestore.md#firestore_class) instance of the provided app.
968+
The named [Firestore](./firestore_.firestore.md#firestore_class) instance of the default app.
969969

970970
## arrayRemove()
971971

integration/firestore/gulpfile.js

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function copyTests() {
4242
.src(
4343
[
4444
testBase + '/integration/api/*.ts',
45+
testBase + '/integration/util/composite_index_test_helper.ts',
4546
testBase + '/integration/util/events_accumulator.ts',
4647
testBase + '/integration/util/helpers.ts',
4748
testBase + '/integration/util/settings.ts',

packages/app-check/src/api.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ export function onTokenChanged(
259259
* the current token associated with this App Check instance changes.
260260
*
261261
* @param appCheckInstance - The App Check service instance.
262-
* @param onNext - When the token changes, this function is called with aa
262+
* @param onNext - When the token changes, this function is called with an
263263
* {@link AppCheckTokenResult}.
264264
* @param onError - Optional. Called if there is an error thrown by the
265265
* listener (the `onNext` function).

packages/auth/src/api/authentication/recaptcha.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ interface GetRecaptchaConfigRequest {
4848
version?: RecaptchaVersion;
4949
}
5050

51-
interface RecaptchaEnforcementState {
51+
export interface RecaptchaEnforcementProviderState {
5252
provider: string;
5353
enforcementState: string;
5454
}
5555

5656
export interface GetRecaptchaConfigResponse {
5757
recaptchaKey: string;
58-
recaptchaEnforcementState: RecaptchaEnforcementState[];
58+
recaptchaEnforcementState: RecaptchaEnforcementProviderState[];
5959
}
6060

6161
export async function getRecaptchaConfig(

packages/auth/src/api/index.ts

+27
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ export const enum RecaptchaActionName {
8787
SIGN_UP_PASSWORD = 'signUpPassword'
8888
}
8989

90+
export const enum EnforcementState {
91+
ENFORCE = 'ENFORCE',
92+
AUDIT = 'AUDIT',
93+
OFF = 'OFF',
94+
ENFORCEMENT_STATE_UNSPECIFIED = 'ENFORCEMENT_STATE_UNSPECIFIED'
95+
}
96+
97+
// Providers that have reCAPTCHA Enterprise support.
98+
export const enum RecaptchaProvider {
99+
EMAIL_PASSWORD_PROVIDER = 'EMAIL_PASSWORD_PROVIDER'
100+
}
101+
90102
export const DEFAULT_API_TIMEOUT_MS = new Delay(30_000, 60_000);
91103

92104
export function _addTidIfNecessary<T extends { tenantId?: string }>(
@@ -245,6 +257,21 @@ export function _getFinalTarget(
245257
return _emulatorUrl(auth.config as ConfigInternal, base);
246258
}
247259

260+
export function _parseEnforcementState(
261+
enforcementStateStr: string
262+
): EnforcementState {
263+
switch (enforcementStateStr) {
264+
case 'ENFORCE':
265+
return EnforcementState.ENFORCE;
266+
case 'AUDIT':
267+
return EnforcementState.AUDIT;
268+
case 'OFF':
269+
return EnforcementState.OFF;
270+
default:
271+
return EnforcementState.ENFORCEMENT_STATE_UNSPECIFIED;
272+
}
273+
}
274+
248275
class NetworkTimeout<T> {
249276
// Node timers and browser timers are fundamentally incompatible, but we
250277
// don't care about the value here

packages/auth/src/core/auth/auth_impl.test.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -710,11 +710,21 @@ describe('core/auth/auth_impl', () => {
710710
]
711711
};
712712
const cachedRecaptchaConfigEnforce = {
713-
emailPasswordEnabled: true,
713+
recaptchaEnforcementState: [
714+
{
715+
'enforcementState': 'ENFORCE',
716+
'provider': 'EMAIL_PASSWORD_PROVIDER'
717+
}
718+
],
714719
siteKey: 'site-key'
715720
};
716721
const cachedRecaptchaConfigOFF = {
717-
emailPasswordEnabled: false,
722+
recaptchaEnforcementState: [
723+
{
724+
'enforcementState': 'OFF',
725+
'provider': 'EMAIL_PASSWORD_PROVIDER'
726+
}
727+
],
718728
siteKey: 'site-key'
719729
};
720730

packages/auth/src/core/credentials/email.ts

+7-27
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { IdTokenResponse } from '../../model/id_token';
3131
import { AuthErrorCode } from '../errors';
3232
import { _fail } from '../util/assert';
3333
import { AuthCredential } from './auth_credential';
34-
import { injectRecaptchaFields } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
34+
import { handleRecaptchaFlow } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
3535
import { RecaptchaActionName, RecaptchaClientType } from '../../api';
3636
/**
3737
* Interface that represents the credentials returned by {@link EmailAuthProvider} for
@@ -123,32 +123,12 @@ export class EmailAuthCredential extends AuthCredential {
123123
password: this._password,
124124
clientType: RecaptchaClientType.WEB
125125
};
126-
if (auth._getRecaptchaConfig()?.emailPasswordEnabled) {
127-
const requestWithRecaptcha = await injectRecaptchaFields(
128-
auth,
129-
request,
130-
RecaptchaActionName.SIGN_IN_WITH_PASSWORD
131-
);
132-
return signInWithPassword(auth, requestWithRecaptcha);
133-
} else {
134-
return signInWithPassword(auth, request).catch(async error => {
135-
if (
136-
error.code === `auth/${AuthErrorCode.MISSING_RECAPTCHA_TOKEN}`
137-
) {
138-
console.log(
139-
'Sign-in with email address and password is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-in flow.'
140-
);
141-
const requestWithRecaptcha = await injectRecaptchaFields(
142-
auth,
143-
request,
144-
RecaptchaActionName.SIGN_IN_WITH_PASSWORD
145-
);
146-
return signInWithPassword(auth, requestWithRecaptcha);
147-
} else {
148-
return Promise.reject(error);
149-
}
150-
});
151-
}
126+
return handleRecaptchaFlow(
127+
auth,
128+
request,
129+
RecaptchaActionName.SIGN_IN_WITH_PASSWORD,
130+
signInWithPassword
131+
);
152132
case SignInMethod.EMAIL_LINK:
153133
return signInWithEmailLink(auth, {
154134
email: this._email,

0 commit comments

Comments
 (0)