Skip to content

Commit 1de6be4

Browse files
Merge master into release
2 parents 90725ba + 0bab0b7 commit 1de6be4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+833
-182
lines changed

.changeset/chilled-boats-report.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/auth': patch
3+
---
4+
5+
Expose TOKEN_EXPIRED error when mfa unenroll logs out the user.

.changeset/fresh-experts-mix.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@firebase/database-compat": patch
3+
"@firebase/database": patch
4+
---
5+
6+
Fixed issue where hostname set by `connectDatabaseEmulator` was being overridden by longpolling response

.changeset/hungry-glasses-impress.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"firebase": minor
3+
"@firebase/storage": minor
4+
"@firebase/storage-types": minor
5+
"@firebase/storage-compat": minor
6+
---
7+
8+
Fixed issue where users were unable to check if an Error was an instance of `StorageError`.

.changeset/ninety-taxis-study.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
'@firebase/auth': patch
3+
'@firebase/auth-compat': patch
4+
'@firebase/database': patch
5+
'@firebase/database-compat': patch
6+
'firebase': patch
7+
'@firebase/firestore': patch
8+
'@firebase/firestore-compat': patch
9+
'@firebase/functions': patch
10+
'@firebase/functions-compat': patch
11+
'@firebase/messaging': patch
12+
'@firebase/messaging-compat': patch
13+
'@firebase/rules-unit-testing': patch
14+
'@firebase/storage': patch
15+
'@firebase/template': patch
16+
'@firebase/util': patch
17+
---
18+
19+
Added browser CJS entry points (expected by Jest when using JSDOM mode).

.changeset/slimy-elephants-hear.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/firestore": patch
3+
---
4+
5+
Reduce memory usage by applying query check sooner in remote document cache.

common/api-review/storage.api.md

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,11 @@ export function getStorage(app?: FirebaseApp, bucketUrl?: string): FirebaseStora
134134
// @public
135135
export function getStream(ref: StorageReference, maxDownloadSizeBytes?: number): NodeJS.ReadableStream;
136136

137-
// Warning: (ae-forgotten-export) The symbol "StorageError" needs to be exported by the entry point index.d.ts
138-
//
139137
// @internal (undocumented)
140-
export function _invalidArgument(message: string): StorageError_2;
138+
export function _invalidArgument(message: string): StorageError;
141139

142140
// @internal (undocumented)
143-
export function _invalidRootOperation(name: string): StorageError_2;
141+
export function _invalidRootOperation(name: string): StorageError;
144142

145143
// @public
146144
export function list(ref: StorageReference, options?: ListOptions): Promise<ListResult>;
@@ -217,8 +215,71 @@ export interface SettableMetadata {
217215
}
218216

219217
// @public
220-
export interface StorageError extends FirebaseError {
221-
serverResponse: string | null;
218+
export class StorageError extends FirebaseError {
219+
constructor(code: StorageErrorCode, message: string, status_?: number);
220+
_codeEquals(code: StorageErrorCode): boolean;
221+
customData: {
222+
serverResponse: string | null;
223+
};
224+
get serverResponse(): null | string;
225+
set serverResponse(serverResponse: string | null);
226+
// (undocumented)
227+
get status(): number;
228+
set status(status: number);
229+
}
230+
231+
// @public
232+
export enum StorageErrorCode {
233+
// (undocumented)
234+
APP_DELETED = "app-deleted",
235+
// (undocumented)
236+
BUCKET_NOT_FOUND = "bucket-not-found",
237+
// (undocumented)
238+
CANCELED = "canceled",
239+
// (undocumented)
240+
CANNOT_SLICE_BLOB = "cannot-slice-blob",
241+
// (undocumented)
242+
INTERNAL_ERROR = "internal-error",
243+
// (undocumented)
244+
INVALID_ARGUMENT = "invalid-argument",
245+
// (undocumented)
246+
INVALID_ARGUMENT_COUNT = "invalid-argument-count",
247+
// (undocumented)
248+
INVALID_CHECKSUM = "invalid-checksum",
249+
// (undocumented)
250+
INVALID_DEFAULT_BUCKET = "invalid-default-bucket",
251+
// (undocumented)
252+
INVALID_EVENT_NAME = "invalid-event-name",
253+
// (undocumented)
254+
INVALID_FORMAT = "invalid-format",
255+
// (undocumented)
256+
INVALID_ROOT_OPERATION = "invalid-root-operation",
257+
// (undocumented)
258+
INVALID_URL = "invalid-url",
259+
// (undocumented)
260+
NO_DEFAULT_BUCKET = "no-default-bucket",
261+
// (undocumented)
262+
NO_DOWNLOAD_URL = "no-download-url",
263+
// (undocumented)
264+
OBJECT_NOT_FOUND = "object-not-found",
265+
// (undocumented)
266+
PROJECT_NOT_FOUND = "project-not-found",
267+
// (undocumented)
268+
QUOTA_EXCEEDED = "quota-exceeded",
269+
// (undocumented)
270+
RETRY_LIMIT_EXCEEDED = "retry-limit-exceeded",
271+
// (undocumented)
272+
SERVER_FILE_WRONG_SIZE = "server-file-wrong-size",
273+
// (undocumented)
274+
UNAUTHENTICATED = "unauthenticated",
275+
// (undocumented)
276+
UNAUTHORIZED = "unauthorized",
277+
// (undocumented)
278+
UNAUTHORIZED_APP = "unauthorized-app",
279+
// (undocumented)
280+
UNKNOWN = "unknown",
281+
// (undocumented)
282+
UNSUPPORTED_ENVIRONMENT = "unsupported-environment"
222283
}
223284

224285
// @public
@@ -318,20 +379,20 @@ export class _UploadTask {
318379
constructor(ref: _Reference, blob: _FbsBlob, metadata?: Metadata | null);
319380
_blob: _FbsBlob;
320381
cancel(): boolean;
321-
catch<T>(onRejected: (p1: StorageError_2) => T | Promise<T>): Promise<T>;
382+
catch<T>(onRejected: (p1: StorageError) => T | Promise<T>): Promise<T>;
322383
// (undocumented)
323384
isExponentialBackoffExpired(): boolean;
324385
// Warning: (ae-forgotten-export) The symbol "Metadata" needs to be exported by the entry point index.d.ts
325386
_metadata: Metadata | null;
326387
// Warning: (ae-forgotten-export) The symbol "Unsubscribe" needs to be exported by the entry point index.d.ts
327388
// Warning: (ae-forgotten-export) The symbol "Subscribe" needs to be exported by the entry point index.d.ts
328-
on(type: _TaskEvent, nextOrObserver?: StorageObserver<UploadTaskSnapshot> | null | ((snapshot: UploadTaskSnapshot) => unknown), error?: ((a: StorageError_2) => unknown) | null, completed?: CompleteFn | null): Unsubscribe_2 | Subscribe_2<UploadTaskSnapshot>;
389+
on(type: _TaskEvent, nextOrObserver?: StorageObserver<UploadTaskSnapshot> | null | ((snapshot: UploadTaskSnapshot) => unknown), error?: ((a: StorageError) => unknown) | null, completed?: CompleteFn | null): Unsubscribe_2 | Subscribe_2<UploadTaskSnapshot>;
329390
pause(): boolean;
330391
resume(): boolean;
331392
get snapshot(): UploadTaskSnapshot;
332393
// Warning: (ae-forgotten-export) The symbol "InternalTaskState" needs to be exported by the entry point index.d.ts
333394
_state: InternalTaskState;
334-
then<U>(onFulfilled?: ((value: UploadTaskSnapshot) => U | Promise<U>) | null, onRejected?: ((error: StorageError_2) => U | Promise<U>) | null): Promise<U>;
395+
then<U>(onFulfilled?: ((value: UploadTaskSnapshot) => U | Promise<U>) | null, onRejected?: ((error: StorageError) => U | Promise<U>) | null): Promise<U>;
335396
_transferred: number;
336397
}
337398

packages/analytics-types/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ export interface Promotion {
651651

652652
/**
653653
* Dynamic configuration fetched from server.
654-
* See https://firebase.google.com/docs/projects/api/reference/rest/v1beta1/projects.webApps/getConfig
654+
* See https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.webApps/getConfig
655655
*/
656656
interface DynamicConfig {
657657
projectId: string;

packages/analytics/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export interface ThrottleMetadata {
3434

3535
/**
3636
* Dynamic configuration fetched from server.
37-
* See https://firebase.google.com/docs/projects/api/reference/rest/v1beta1/projects.webApps/getConfig
37+
* See https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.webApps/getConfig
3838
*/
3939
export interface DynamicConfig {
4040
projectId: string;

packages/auth-compat/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
"require": "./dist/index.node.cjs.js"
1717
},
1818
"esm5": "./dist/index.esm.js",
19-
"default": "./dist/index.esm2017.js"
19+
"default": "./dist/index.esm2017.js",
20+
"browser": {
21+
"require": "./dist/index.cjs.js",
22+
"import": "./dist/index.esm2017.js"
23+
}
2024
},
2125
"./package.json": "./package.json"
2226
},

packages/auth-compat/rollup.config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ const browserBuilds = [
7373
treeshake: {
7474
moduleSideEffects: false
7575
}
76+
},
77+
{
78+
input: 'index.ts',
79+
output: {
80+
file: 'dist/index.cjs.js',
81+
format: 'cjs',
82+
sourcemap: true
83+
},
84+
plugins: es2017BuildPlugins,
85+
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)),
86+
treeshake: {
87+
moduleSideEffects: false
88+
}
7689
}
7790
];
7891

packages/auth/demo/public/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@
252252
id="sign-in-with-email-and-password">
253253
Sign In with Email and Password
254254
</button>
255+
<button class="btn btn-block btn-primary"
256+
id="reauth-with-email-and-password">
257+
Reauthenticate with Email and Password
258+
</button>
255259
</form>
256260
<form class="form form-bordered no-submit">
257261
<input type="text" id="user-custom-token" class="form-control"

packages/auth/demo/src/index.js

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ function showMultiFactorStatus(activeUser) {
247247
const label = info && (info.displayName || info.uid);
248248
if (label) {
249249
$('#enrolled-factors-drop-down').removeClass('open');
250+
// Set the last user, in case the current user is logged out.
251+
// This can happen if the MFA option being unenrolled is the one that was most recently enrolled into.
252+
// See - https://github.com/firebase/firebase-js-sdk/issues/3233
253+
setLastUser(activeUser);
250254
mfaUser.unenroll(info).then(() => {
251255
refreshUserData();
252256
alertSuccess('Multi-factor successfully unenrolled.');
@@ -278,6 +282,9 @@ function onAuthError(error) {
278282
handleMultiFactorSignIn(getMultiFactorResolver(auth, error));
279283
} else {
280284
alertError('Error: ' + error.code);
285+
if (error.code === 'auth/user-token-expired') {
286+
alertError('Token expired, please reauthenticate.');
287+
}
281288
}
282289
}
283290

@@ -403,13 +410,41 @@ function onLinkWithEmailLink() {
403410
* Re-authenticate a user with email link credential.
404411
*/
405412
function onReauthenticateWithEmailLink() {
413+
if (!activeUser()) {
414+
alertError(
415+
'No user logged in. Select the "Last User" tab to reauth the previous user.'
416+
);
417+
return;
418+
}
406419
const email = $('#link-with-email-link-email').val();
407420
const link = $('#link-with-email-link-link').val() || undefined;
408421
const credential = EmailAuthProvider.credentialWithLink(email, link);
422+
// This will not set auth.currentUser to lastUser if the lastUser is reauthenticated.
409423
reauthenticateWithCredential(activeUser(), credential).then(result => {
410424
logAdditionalUserInfo(result);
411425
refreshUserData();
412-
alertSuccess('User reauthenticated!');
426+
alertSuccess('User reauthenticated with email link!');
427+
}, onAuthError);
428+
}
429+
430+
/**
431+
* Re-authenticate a user with email and password.
432+
*/
433+
function onReauthenticateWithEmailAndPassword() {
434+
if (!activeUser()) {
435+
alertError(
436+
'No user logged in. Select the "Last User" tab to reauth the previous user.'
437+
);
438+
return;
439+
}
440+
const email = $('#signin-email').val();
441+
const password = $('#signin-password').val();
442+
const credential = EmailAuthProvider.credential(email, password);
443+
// This will not set auth.currentUser to lastUser if the lastUser is reauthenticated.
444+
reauthenticateWithCredential(activeUser(), credential).then(result => {
445+
logAdditionalUserInfo(result);
446+
refreshUserData();
447+
alertSuccess('User reauthenticated with email/password!');
413448
}, onAuthError);
414449
}
415450

@@ -1264,7 +1299,9 @@ function signInWithPopupRedirect(provider) {
12641299
break;
12651300
case 'reauthenticate':
12661301
if (!activeUser()) {
1267-
alertError('No user logged in.');
1302+
alertError(
1303+
'No user logged in. Select the "Last User" tab to reauth the previous user.'
1304+
);
12681305
return;
12691306
}
12701307
inst = activeUser();
@@ -1860,6 +1897,9 @@ function initApp() {
18601897
// Actions listeners.
18611898
$('#sign-up-with-email-and-password').click(onSignUp);
18621899
$('#sign-in-with-email-and-password').click(onSignInWithEmailAndPassword);
1900+
$('#reauth-with-email-and-password').click(
1901+
onReauthenticateWithEmailAndPassword
1902+
);
18631903
$('.sign-in-with-custom-token').click(onSignInWithCustomToken);
18641904
$('#sign-in-anonymously').click(onSignInAnonymously);
18651905
$('#sign-in-with-generic-idp-credential').click(

packages/auth/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@
3131
"default": "./dist/index.webworker.esm5.js"
3232
},
3333
"esm5": "./dist/esm5/index.js",
34-
"default": "./dist/esm2017/index.js"
34+
"default": "./dist/esm2017/index.js",
35+
"browser": {
36+
"require": "./dist/browser-cjs/index.js",
37+
"import": "./dist/esm2017/index.js"
38+
}
3539
},
3640
"./cordova": {
3741
"types": "./dist/cordova/index.cordova.d.ts",
@@ -57,7 +61,11 @@
5761
"default": "./dist/cordova/internal.js"
5862
},
5963
"esm5": "./dist/esm5/internal.js",
60-
"default": "./dist/esm2017/internal.js"
64+
"default": "./dist/esm2017/internal.js",
65+
"browser": {
66+
"require": "./dist/browser-cjs/internal.js",
67+
"import": "./dist/esm2017/internal.js"
68+
}
6169
},
6270
"./package.json": "./package.json"
6371
},

packages/auth/rollup.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ const browserBuilds = [
9797
replace(generateBuildTargetReplaceConfig('esm', 2017))
9898
],
9999
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
100+
},
101+
{
102+
input: {
103+
index: 'index.ts',
104+
internal: 'internal/index.ts'
105+
},
106+
output: [{ dir: 'dist/browser-cjs', format: 'cjs', sourcemap: true }],
107+
plugins: [
108+
...es2017BuildPlugins,
109+
replace(generateBuildTargetReplaceConfig('cjs', 2017))
110+
],
111+
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
100112
}
101113
];
102114

packages/auth/src/core/strategies/credential.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ export async function linkWithCredential(
9696
*
9797
* @remarks
9898
* Use before operations such as {@link updatePassword} that require tokens from recent sign-in
99-
* attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error.
99+
* attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error
100+
* or a `TOKEN_EXPIRED` error.
100101
*
101102
* @param user - The user.
102103
* @param credential - The auth credential.

packages/auth/src/mfa/mfa_user.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,10 @@ describe('core/mfa/mfa_user/MultiFactorUser', () => {
235235
);
236236
});
237237

238-
it('should swallow the error', async () => {
239-
await mfaUser.unenroll(mfaInfo);
238+
it('should throw TOKEN_EXPIRED error', async () => {
239+
await expect(mfaUser.unenroll(mfaInfo)).to.be.rejectedWith(
240+
'auth/user-token-expired'
241+
);
240242
});
241243
});
242244
});

0 commit comments

Comments
 (0)