Skip to content

Commit 84a929e

Browse files
committed
PR feedback
1 parent f8c8ea8 commit 84a929e

File tree

6 files changed

+78
-37
lines changed

6 files changed

+78
-37
lines changed

packages-exp/auth-exp/src/core/auth/auth_event_manager.test.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@ import * as sinon from 'sinon';
2020
import * as sinonChai from 'sinon-chai';
2121

2222
import {
23-
AuthEvent,
24-
AuthEventConsumer,
25-
AuthEventType
23+
AuthEvent, AuthEventConsumer, AuthEventError, AuthEventType
2624
} from '../../model/popup_redirect';
25+
import { AuthErrorCode } from '../errors';
2726
import { AuthEventManager } from './auth_event_manager';
2827

2928
use(sinonChai);
@@ -37,7 +36,8 @@ describe('src/core/auth/auth_event_manager', () => {
3736
const stub = sinon.stub({
3837
filter,
3938
isMatchingEvent: () => true,
40-
onAuthEvent: () => {}
39+
onAuthEvent: () => {},
40+
onError: () => {}
4141
});
4242

4343
// Make isMatchingEvent call through by default
@@ -54,7 +54,7 @@ describe('src/core/auth/auth_event_manager', () => {
5454
}
5555

5656
beforeEach(() => {
57-
manager = new AuthEventManager();
57+
manager = new AuthEventManager('app-name');
5858
});
5959

6060
it('multiple consumers may be registered for one event type', () => {
@@ -107,4 +107,33 @@ describe('src/core/auth/auth_event_manager', () => {
107107
expect(consumer.onAuthEvent).not.to.have.been.called;
108108
expect(consumer.isMatchingEvent).to.have.been.called;
109109
});
110+
111+
it('converts errors into FirebaseError if the type matches', () => {
112+
const consumer = makeConsumer(AuthEventType.REAUTH_VIA_POPUP);
113+
manager.registerConsumer(consumer);
114+
const event = makeEvent(AuthEventType.REAUTH_VIA_POPUP);
115+
event.error = {
116+
code: `auth/${AuthErrorCode.INVALID_APP_CREDENTIAL}`,
117+
message: 'foo',
118+
name: 'name',
119+
};
120+
121+
manager.onEvent(event);
122+
const error = consumer.onError.getCall(0).args[0];
123+
expect(error.code).to.eq(`auth/${AuthErrorCode.INVALID_APP_CREDENTIAL}`);
124+
});
125+
126+
it('converts random errors into FirebaseError with internal error', () => {
127+
const consumer = makeConsumer(AuthEventType.REAUTH_VIA_POPUP);
128+
manager.registerConsumer(consumer);
129+
const event = makeEvent(AuthEventType.REAUTH_VIA_POPUP);
130+
event.error = {
131+
message: 'foo',
132+
name: 'name',
133+
} as AuthEventError;
134+
135+
manager.onEvent(event);
136+
const error = consumer.onError.getCall(0).args[0];
137+
expect(error.code).to.eq(`auth/${AuthErrorCode.INTERNAL_ERROR}`);
138+
});
110139
});

packages-exp/auth-exp/src/core/auth/auth_event_manager.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,14 @@
1515
* limitations under the License.
1616
*/
1717

18-
import {
19-
AuthEvent,
20-
AuthEventConsumer,
21-
EventManager
22-
} from '../../model/popup_redirect';
18+
import { AuthEvent, AuthEventConsumer, EventManager } from '../../model/popup_redirect';
19+
import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors';
2320

2421
export class AuthEventManager implements EventManager {
2522
private readonly consumers: Set<AuthEventConsumer> = new Set();
2623

24+
constructor(private readonly appName: string) {}
25+
2726
registerConsumer(authEventConsumer: AuthEventConsumer): void {
2827
this.consumers.add(authEventConsumer);
2928
}
@@ -38,7 +37,15 @@ export class AuthEventManager implements EventManager {
3837
consumer.filter === event.type &&
3938
consumer.isMatchingEvent(event.eventId)
4039
) {
41-
consumer.onAuthEvent(event);
40+
if (event.error) {
41+
console.error('ERROR');
42+
const code = event.error.code?.split('auth/')[1] as AuthErrorCode || AuthErrorCode.INTERNAL_ERROR;
43+
consumer.onError(AUTH_ERROR_FACTORY.create(code, {
44+
appName: this.appName
45+
}));
46+
} else {
47+
consumer.onAuthEvent(event);
48+
}
4249
}
4350
});
4451
}

packages-exp/auth-exp/src/core/providers/oauth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class OAuthProvider implements externs.AuthProvider {
3232
defaultLanguageCode: string | null = null;
3333
private scopes: string[] = [];
3434
private customParameters: CustomParameters = {};
35-
private constructor(readonly providerId: externs.ProviderId) {}
35+
constructor(readonly providerId: externs.ProviderId) {}
3636
static credentialFromResult(
3737
_userCredential: externs.UserCredential
3838
): externs.OAuthCredential | null {

packages-exp/auth-exp/src/model/popup_redirect.d.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
import * as externs from '@firebase/auth-types-exp';
19+
import { FirebaseError } from '@firebase/util';
1920

2021
import { AuthPopup } from '../core/util/popup';
2122
import { Auth } from './auth';
@@ -45,7 +46,6 @@ export const enum AuthEventType {
4546
VERIFY_APP = 'verifyApp'
4647
}
4748

48-
// TODO: convert from these to FirebaseError
4949
export interface AuthEventError extends Error {
5050
code: string; // in the form of auth/${AuthErrorCode}
5151
message: string;
@@ -65,6 +65,7 @@ export interface AuthEventConsumer {
6565
readonly filter: AuthEventType;
6666
isMatchingEvent(eventId: string | null): boolean;
6767
onAuthEvent(event: AuthEvent): unknown;
68+
onError(error: FirebaseError): unknown;
6869
}
6970

7071
export interface EventManager {
@@ -73,8 +74,8 @@ export interface EventManager {
7374
}
7475

7576
export interface PopupRedirectResolver extends externs.PopupRedirectResolver {
76-
initialize(auth: Auth): Promise<EventManager>;
77-
openPopup(
77+
_initialize(auth: Auth): Promise<EventManager>;
78+
_openPopup(
7879
auth: Auth,
7980
provider: externs.AuthProvider,
8081
authType: AuthEventType,

packages-exp/auth-exp/src/platform_browser/popup_redirect.test.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,7 @@ import { TEST_AUTH_DOMAIN, TEST_KEY, testAuth } from '../../test/mock_auth';
2828
import { AuthEventManager } from '../core/auth/auth_event_manager';
2929
import { OAuthProvider } from '../core/providers/oauth';
3030
import { Auth } from '../model/auth';
31-
import {
32-
AuthEvent,
33-
AuthEventType,
34-
GapiAuthEvent
35-
} from '../model/popup_redirect';
31+
import { AuthEvent, AuthEventType, GapiAuthEvent } from '../model/popup_redirect';
3632
import * as gapiLoader from './iframe/gapi';
3733
import { BrowserPopupRedirectResolver } from './popup_redirect';
3834

@@ -70,7 +66,7 @@ describe('src/platform_browser/popup_redirect', () => {
7066
provider.addScope('some-scope-b');
7167
provider.setCustomParameters({ foo: 'bar' });
7268

73-
await resolver.openPopup(auth, provider, event);
69+
await resolver._openPopup(auth, provider, event);
7470
expect(popupUrl).to.include(
7571
`https://${TEST_AUTH_DOMAIN}/__/auth/handler`
7672
);
@@ -88,15 +84,15 @@ describe('src/platform_browser/popup_redirect', () => {
8884
delete auth.config.authDomain;
8985

9086
await expect(
91-
resolver.openPopup(auth, provider, event)
87+
resolver._openPopup(auth, provider, event)
9288
).to.be.rejectedWith(FirebaseError, 'auth/auth-domain-config-required');
9389
});
9490

9591
it('throws an error if apiKey is unspecified', async () => {
9692
delete auth.config.apiKey;
9793

9894
await expect(
99-
resolver.openPopup(auth, provider, event)
95+
resolver._openPopup(auth, provider, event)
10096
).to.be.rejectedWith(FirebaseError, 'auth/invalid-api-key');
10197
});
10298
});
@@ -118,12 +114,12 @@ describe('src/platform_browser/popup_redirect', () => {
118114
});
119115

120116
it('only registers once, returns same event manager', async () => {
121-
const manager = await resolver.initialize(auth);
122-
expect(await resolver.initialize(auth)).to.eq(manager);
117+
const manager = await resolver._initialize(auth);
118+
expect(await resolver._initialize(auth)).to.eq(manager);
123119
});
124120

125121
it('iframe event goes through to the manager', async () => {
126-
const manager = (await resolver.initialize(auth)) as AuthEventManager;
122+
const manager = (await resolver._initialize(auth)) as AuthEventManager;
127123
sinon.spy(manager, 'onEvent');
128124
const response = await onIframeMessage({
129125
type: 'authEvent',

packages-exp/auth-exp/src/platform_browser/popup_redirect.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,13 @@ import { isEmpty, querystring } from '@firebase/util';
2222
import { AuthEventManager } from '../core/auth/auth_event_manager';
2323
import { AuthErrorCode } from '../core/errors';
2424
import { OAuthProvider } from '../core/providers/oauth';
25-
import { assert } from '../core/util/assert';
25+
import { assert, debugAssert } from '../core/util/assert';
2626
import { _generateEventId } from '../core/util/event_id';
2727
import { _getCurrentUrl } from '../core/util/location';
2828
import { _open, AuthPopup } from '../core/util/popup';
2929
import { ApiKey, AppName, Auth } from '../model/auth';
3030
import {
31-
AuthEventType,
32-
EventManager,
33-
GapiAuthEvent,
34-
GapiOutcome,
35-
PopupRedirectResolver
31+
AuthEventType, EventManager, GapiAuthEvent, GapiOutcome, PopupRedirectResolver
3632
} from '../model/popup_redirect';
3733
import { _openIframe } from './iframe/iframe';
3834

@@ -43,26 +39,36 @@ const WIDGET_URL = '__/auth/handler';
4339

4440
export class BrowserPopupRedirectResolver implements PopupRedirectResolver {
4541
private eventManager: EventManager | null = null;
42+
private initializationPromise: Promise<EventManager>|null = null;
4643

4744
// Wrapping in async even though we don't await anywhere in order
4845
// to make sure errors are raised as promise rejections
49-
async openPopup(
46+
async _openPopup(
5047
auth: Auth,
5148
provider: externs.AuthProvider,
5249
authType: AuthEventType,
5350
eventId?: string
5451
): Promise<AuthPopup> {
52+
debugAssert(this.eventManager, '_initialize() not called before _openPopup()');
5553
const url = getRedirectUrl(auth, provider, authType, eventId);
5654
return _open(auth.name, url, _generateEventId());
5755
}
5856

59-
async initialize(auth: Auth): Promise<EventManager> {
57+
_initialize(auth: Auth): Promise<EventManager> {
6058
if (this.eventManager) {
61-
return this.eventManager;
59+
return Promise.resolve(this.eventManager);
6260
}
6361

62+
if (!this.initializationPromise) {
63+
this.initializationPromise = this.initAndGetManager(auth);
64+
}
65+
66+
return this.initializationPromise;
67+
}
68+
69+
private async initAndGetManager(auth: Auth): Promise<EventManager> {
6470
const iframe = await _openIframe(auth);
65-
const eventManager = new AuthEventManager();
71+
const eventManager = new AuthEventManager(auth.name);
6672
iframe.register<GapiAuthEvent>(
6773
'authEvent',
6874
async (message: GapiAuthEvent) => {
@@ -90,6 +96,7 @@ type WidgetParams = {
9096
scopes?: string;
9197
customParameters?: string;
9298
eventId?: string;
99+
tid?: string;
93100
};
94101

95102
function getRedirectUrl(
@@ -107,7 +114,8 @@ function getRedirectUrl(
107114
authType,
108115
redirectUrl: _getCurrentUrl(),
109116
v: SDK_VERSION,
110-
eventId
117+
eventId,
118+
tid: auth.tenantId || undefined,
111119
};
112120

113121
if (provider instanceof OAuthProvider) {

0 commit comments

Comments
 (0)