Fix user not always logged when opening export after relaunching the app (#3205)

* Also fix signup/login dialog closing before the signup/login is entirely finished
This commit is contained in:
Florian Rival
2021-10-27 15:43:39 +01:00
committed by GitHub
parent a3fdeec6a7
commit 7f5821a299
11 changed files with 350 additions and 283 deletions

View File

@@ -20,9 +20,9 @@ export type AuthenticatedUser = {|
onEdit: () => void,
onChangeEmail: () => void,
onCreateAccount: () => void,
onRefreshUserProfile: () => void,
onRefreshFirebaseProfile: () => void,
onSendEmailVerification: () => void,
onRefreshUserProfile: () => Promise<void>,
onRefreshFirebaseProfile: () => Promise<void>,
onSendEmailVerification: () => Promise<void>,
getAuthorizationHeader: () => Promise<string>,
|};
@@ -38,9 +38,9 @@ export const initialAuthenticatedUser = {
onEdit: () => {},
onChangeEmail: () => {},
onCreateAccount: () => {},
onRefreshUserProfile: () => {},
onRefreshFirebaseProfile: () => {},
onSendEmailVerification: () => {},
onRefreshUserProfile: async () => {},
onRefreshFirebaseProfile: async () => {},
onSendEmailVerification: async () => {},
getAuthorizationHeader: () => Promise.reject(new Error('Unimplemented')),
};

View File

@@ -15,7 +15,6 @@ import Authentication, {
} from '../Utils/GDevelopServices/Authentication';
import { User as FirebaseUser } from 'firebase/auth';
import LoginDialog from './LoginDialog';
import { watchPromiseInState } from '../Utils/WatchPromiseInState';
import { showWarningBox } from '../UI/Messages/MessageBox';
import { sendSignupDone } from '../Utils/Analytics/EventSender';
import AuthenticatedUserContext, {
@@ -67,11 +66,51 @@ export default class AuthenticatedUserProvider extends React.Component<
changeEmailDialogOpen: false,
changeEmailInProgress: false,
};
_automaticallyUpdateUserProfile = true;
componentDidMount() {
this._resetAuthenticatedUser();
this.props.authentication.setOnUserLogoutCallback(this._fetchUserProfile);
this._fetchUserProfile();
// Listen to when the user log out so that we reset the user profile.
this.props.authentication.setOnUserLogoutCallback(
this._fetchUserProfileWithoutThrowingErrors
);
// When the authenticated user changes, we need to react accordingly
// This can happen:
// - at the startup, because the authenticated Firebase user was not ready yet
// when this component mounted. So we'll fetch the user profile.
// - at the login, signup, profile edit. These methods are taking care of
// fetching the user profile by themselves, so they will disable the automatic
// refresh.
// - at any other moment (Firebase user was updated), in which case it's probably
// not a problem to fetch again the user profile.
this.props.authentication.setOnUserUpdateCallback(() => {
if (this._automaticallyUpdateUserProfile) {
console.info(
'Fetching user profile as the authenticated user changed...'
);
this._fetchUserProfileWithoutThrowingErrors();
} else {
console.info(
'The authenticated user changed, but not fetching the user profile again (deactivated).'
);
}
});
if (this.props.authentication.getFirebaseUserSync()) {
// The user is logged already: fetch its user profile (because the "user update"
// won't trigger, as registered too late).
console.info(
'Fetching user profile as authenticated user found at startup...'
);
this._automaticallyUpdateUserProfile = false;
this._fetchUserProfileWithoutThrowingErrors();
this._automaticallyUpdateUserProfile = true;
} else {
// Don't do anything. Either no user is logged (nothing to do)
// or is being logged (the "user udpate" callback will trigger later).
}
}
_resetAuthenticatedUser() {
@@ -84,7 +123,9 @@ export default class AuthenticatedUserProvider extends React.Component<
onChangeEmail: () => this.openChangeEmailDialog(true),
onCreateAccount: () => this.openCreateAccountDialog(true),
onRefreshUserProfile: this._fetchUserProfile,
onRefreshFirebaseProfile: this._reloadFirebaseProfile,
onRefreshFirebaseProfile: async () => {
await this._reloadFirebaseProfile();
},
onSendEmailVerification: this._doSendEmailVerification,
getAuthorizationHeader: () =>
this.props.authentication.getAuthorizationHeader(),
@@ -92,12 +133,13 @@ export default class AuthenticatedUserProvider extends React.Component<
}));
}
_reloadFirebaseProfile = (callback?: FirebaseUser => void) => {
_reloadFirebaseProfile = async (): Promise<?FirebaseUser> => {
const { authentication } = this.props;
authentication.getFirebaseUser((err, firebaseUser: ?FirebaseUser) => {
if (err && err.unauthenticated) {
return this.setState(({ authenticatedUser }) => ({
try {
const firebaseUser = await authentication.getFirebaseUser();
if (!firebaseUser) {
this.setState(({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
authenticated: false,
@@ -107,75 +149,97 @@ export default class AuthenticatedUserProvider extends React.Component<
subscription: null,
},
}));
} else if (err || !firebaseUser) {
console.error('Unable to fetch user profile', err);
return;
return null;
}
this.setState(
({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
authenticated: true,
firebaseUser,
},
}),
() => {
if (!firebaseUser || !callback) return;
callback(firebaseUser);
}
);
});
this.setState(({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
authenticated: true,
firebaseUser,
},
}));
return firebaseUser;
} catch (error) {
console.error('Unable to fetch the authenticated Firebase user:', error);
throw error;
}
};
_fetchUserProfile = () => {
_fetchUserProfileWithoutThrowingErrors = async () => {
try {
await this._fetchUserProfile();
} catch (error) {
console.error(
'Error while fetching the user profile - but ignoring it.',
error
);
}
};
_fetchUserProfile = async () => {
const { authentication } = this.props;
this._reloadFirebaseProfile((firebaseUser: FirebaseUser) => {
authentication
.getUserProfile(authentication.getAuthorizationHeader)
.then(user =>
this.setState(({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
profile: user,
},
}))
);
getUserUsages(
authentication.getAuthorizationHeader,
firebaseUser.uid
).then(usages =>
// First ensure the Firebase authenticated user is up to date
// (and let the error propagate if any).
const firebaseUser = await this._reloadFirebaseProfile();
if (!firebaseUser) return;
// Fetching user profile related information, but independently from
// the user profile itself, to not block in case one of these calls
// fails.
getUserUsages(authentication.getAuthorizationHeader, firebaseUser.uid).then(
usages =>
this.setState(({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
usages,
},
}))
);
getUserSubscription(
authentication.getAuthorizationHeader,
firebaseUser.uid
).then(subscription =>
})),
error => {
console.error('Error while loading user usages:', error);
}
);
getUserSubscription(
authentication.getAuthorizationHeader,
firebaseUser.uid
).then(
subscription =>
this.setState(({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
subscription,
},
}))
);
getUserLimits(
authentication.getAuthorizationHeader,
firebaseUser.uid
).then(limits =>
})),
error => {
console.error('Error while loading user subscriptions:', error);
}
);
getUserLimits(authentication.getAuthorizationHeader, firebaseUser.uid).then(
limits =>
this.setState(({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
limits,
},
}))
);
});
})),
error => {
console.error('Error while loading user limits:', error);
}
);
// Load and wait for the user profile to be fetched.
// (and let the error propagate if any).
const userProfile = await authentication.getUserProfile(
authentication.getAuthorizationHeader
);
this.setState(({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
profile: userProfile,
},
}));
};
_doLogout = () => {
@@ -183,119 +247,136 @@ export default class AuthenticatedUserProvider extends React.Component<
this._resetAuthenticatedUser();
};
_doLogin = (form: LoginForm) => {
_doLogin = async (form: LoginForm) => {
const { authentication } = this.props;
if (!authentication) return;
watchPromiseInState(this, 'loginInProgress', () =>
authentication.login(form).then(
() => {
this._fetchUserProfile();
this.openLoginDialog(false);
},
(authError: AuthError) => {
this.setState({
authError,
});
}
)
);
this.setState({
loginInProgress: true,
});
this._automaticallyUpdateUserProfile = false;
try {
await authentication.login(form);
await this._fetchUserProfileWithoutThrowingErrors();
this.openLoginDialog(false);
} catch (authError) {
this.setState({ authError });
}
this.setState({
loginInProgress: false,
});
this._automaticallyUpdateUserProfile = true;
};
_doEdit = (form: EditForm) => {
_doEdit = async (form: EditForm) => {
const { authentication } = this.props;
if (!authentication) return;
watchPromiseInState(this, 'editInProgress', () =>
authentication
.editUserProfile(authentication.getAuthorizationHeader, form)
.then(
() => {
this._fetchUserProfile();
this.openEditProfileDialog(false);
},
(authError: AuthError) => {
this.setState({
authError,
});
}
)
);
this.setState({
editInProgress: true,
});
this._automaticallyUpdateUserProfile = false;
try {
await authentication.editUserProfile(
authentication.getAuthorizationHeader,
form
);
await this._fetchUserProfileWithoutThrowingErrors();
this.openEditProfileDialog(false);
} catch (authError) {
this.setState({ authError });
}
this.setState({
editInProgress: false,
});
this._automaticallyUpdateUserProfile = true;
};
_doCreateAccount = (form: RegisterForm) => {
_doCreateAccount = async (form: RegisterForm) => {
const { authentication } = this.props;
if (!authentication) return;
watchPromiseInState(this, 'createAccountInProgress', () =>
authentication.createFirebaseAccount(form).then(
() => {
authentication
.createUser(authentication.getAuthorizationHeader, form)
.then(() => {
this._fetchUserProfile();
this.openLoginDialog(false);
sendSignupDone(form.email);
});
},
(authError: AuthError) => {
this.setState({
authError,
});
}
)
);
this.setState({
createAccountInProgress: true,
});
this._automaticallyUpdateUserProfile = false;
try {
await authentication.createFirebaseAccount(form);
try {
await authentication.createUser(
authentication.getAuthorizationHeader,
form
);
} catch (error) {
// Ignore this error - this is a best effort call
// and the user profile will be created on demand later
// by the API when fetched.
}
await this._fetchUserProfileWithoutThrowingErrors();
this.openLoginDialog(false);
sendSignupDone(form.email);
} catch (authError) {
this.setState({ authError });
}
this.setState({
createAccountInProgress: false,
});
this._automaticallyUpdateUserProfile = true;
};
_doForgotPassword = (form: LoginForm) => {
_doForgotPassword = async (form: LoginForm) => {
const { authentication } = this.props;
if (!authentication) return;
watchPromiseInState(this, 'forgotPasswordInProgress', () =>
authentication.forgotPassword(form).then(
() => {
this.openResetPassword(true);
},
(authError: AuthError) => {
this.setState({
authError,
});
showWarningBox(
"Unable to send you an email to reset your password. Please double-check that the email address that you've entered is valid."
);
}
)
);
};
_doSendEmailVerification = () => {
const { authentication } = this.props;
if (!authentication) return;
authentication.sendFirebaseEmailVerification(() => {
this.openEmailVerificationPendingDialog(true);
this.setState({
forgotPasswordInProgress: true,
});
try {
await authentication.forgotPassword(form);
this.openResetPassword(true);
} catch (authError) {
this.setState({ authError });
showWarningBox(
"Unable to send you an email to reset your password. Please double-check that the email address that you've entered is valid."
);
}
this.setState({
forgotPasswordInProgress: false,
});
};
_doChangeEmail = (form: ChangeEmailForm) => {
_doSendEmailVerification = async () => {
const { authentication } = this.props;
if (!authentication) return;
watchPromiseInState(this, 'changeEmailInProgress', () =>
authentication
.changeEmail(authentication.getAuthorizationHeader, form)
.then(
() => {
this._fetchUserProfile();
this.openChangeEmailDialog(false);
},
(authError: AuthError) => {
this.setState({
authError,
});
}
)
);
await authentication.sendFirebaseEmailVerification();
this.openEmailVerificationPendingDialog(true);
};
_doChangeEmail = async (form: ChangeEmailForm) => {
const { authentication } = this.props;
if (!authentication) return;
this.setState({
changeEmailInProgress: true,
});
this._automaticallyUpdateUserProfile = false;
try {
await authentication.changeEmail(
authentication.getAuthorizationHeader,
form
);
await this._fetchUserProfileWithoutThrowingErrors();
this.openChangeEmailDialog(false);
} catch (authError) {
this.setState({ authError });
}
this.setState({
changeEmailInProgress: false,
});
this._automaticallyUpdateUserProfile = true;
};
openEmailVerificationPendingDialog = (open: boolean = true) => {
@@ -394,7 +475,11 @@ export default class AuthenticatedUserProvider extends React.Component<
authenticatedUser={this.state.authenticatedUser}
onClose={() => {
this.openEmailVerificationPendingDialog(false);
this.state.authenticatedUser.onRefreshFirebaseProfile();
this.state.authenticatedUser
.onRefreshFirebaseProfile()
.catch(() => {
// Ignore any error, we can't do much.
});
}}
/>
)}

View File

@@ -18,7 +18,7 @@ import { getEmailErrorText } from './CreateAccountDialog';
type Props = {|
firebaseUser: FirebaseUser,
onClose: () => void,
onChangeEmail: (form: ChangeEmailForm) => void,
onChangeEmail: (form: ChangeEmailForm) => Promise<void>,
changeEmailInProgress: boolean,
error: ?AuthError,
|};

View File

@@ -20,7 +20,7 @@ import { UsernameField, isUsernameValid } from './UsernameField';
type Props = {|
onClose: () => void,
onGoToLogin: () => void,
onCreateAccount: (form: RegisterForm) => void,
onCreateAccount: (form: RegisterForm) => Promise<void>,
createAccountInProgress: boolean,
error: ?AuthError,
|};

View File

@@ -22,7 +22,7 @@ import TextField from '../UI/TextField';
type Props = {|
profile: Profile,
onClose: () => void,
onEdit: (form: EditForm) => void,
onEdit: (form: EditForm) => Promise<void>,
editInProgress: boolean,
error: ?AuthError,
|};

View File

@@ -27,7 +27,11 @@ export default function EmailVerificationPendingDialog({
!!authenticatedUser.firebaseUser &&
!!authenticatedUser.firebaseUser.emailVerified;
useInterval(
() => authenticatedUser.onRefreshFirebaseProfile(),
() => {
authenticatedUser.onRefreshFirebaseProfile().catch(() => {
// Ignore any error, will be retried anyway.
});
},
isVerified ? null : 3900
);

View File

@@ -21,8 +21,8 @@ import { ColumnStackLayout } from '../UI/Layout';
type Props = {|
onClose: () => void,
onGoToCreateAccount: () => void,
onLogin: (form: LoginForm) => void,
onForgotPassword: (form: LoginForm) => void,
onLogin: (form: LoginForm) => Promise<void>,
onForgotPassword: (form: LoginForm) => Promise<void>,
loginInProgress: boolean,
error: ?AuthError,
resetPasswordDialogOpen: boolean,

View File

@@ -27,7 +27,11 @@ export default function SubscriptionPendingDialog({
!!authenticatedUser.subscription &&
!!authenticatedUser.subscription.planId;
useInterval(
() => authenticatedUser.onRefreshUserProfile(),
() => {
authenticatedUser.onRefreshUserProfile().catch(() => {
// Ignore any error, will be retried anyway.
});
},
hasPlan ? null : 3900
);

View File

@@ -58,35 +58,36 @@ export type AuthError = {
};
export default class Authentication {
firebaseUser: ?FirebaseUser = null;
user: ?Profile = null;
auth: Auth;
_onUserLogoutCallback: ?() => void = null;
_onUserLogoutCallback: ?() => void | Promise<void> = null;
_onUserUpdateCallback: ?() => void | Promise<void> = null;
constructor() {
const app = initializeApp(GDevelopFirebaseConfig);
this.auth = getAuth(app);
onAuthStateChanged(this.auth, user => {
if (user) {
// User has been updated. No need to fetch more info,
// this is handled directly by the corresponding actions (edit, signup, login...)
this.firebaseUser = user;
// User has logged in or changed.
if (this._onUserUpdateCallback) this._onUserUpdateCallback();
} else {
// User has logged out.
this.firebaseUser = null;
if (this._onUserLogoutCallback) this._onUserLogoutCallback();
}
});
}
setOnUserLogoutCallback = (cb: () => void) => {
setOnUserLogoutCallback = (cb: () => void | Promise<void>) => {
this._onUserLogoutCallback = cb;
};
setOnUserUpdateCallback = (cb: () => void | Promise<void>) => {
this._onUserUpdateCallback = cb;
};
createFirebaseAccount = (form: RegisterForm): Promise<void> => {
return createUserWithEmailAndPassword(this.auth, form.email, form.password)
.then(userCredentials => {
this.firebaseUser = userCredentials.user;
// The user is now stored in `this.auth`.
sendEmailVerification(userCredentials.user);
})
.catch(error => {
@@ -101,7 +102,8 @@ export default class Authentication {
): Promise<void> => {
return getAuthorizationHeader()
.then(authorizationHeader => {
if (!this.firebaseUser) {
const { currentUser } = this.auth;
if (!currentUser) {
console.error(
'Cannot create the user as it is not logged in any more.'
);
@@ -112,13 +114,13 @@ export default class Authentication {
return axios.post(
`${GDevelopUserApi.baseUrl}/user`,
{
id: this.firebaseUser.uid,
id: currentUser.uid,
email: form.email,
username: form.username,
},
{
params: {
userId: this.firebaseUser.uid,
userId: currentUser.uid,
},
headers: {
Authorization: authorizationHeader,
@@ -126,8 +128,8 @@ export default class Authentication {
}
);
})
.then(response => {
this.user = response.data;
.then(() => {
// User successfully created
})
.catch(error => {
console.error('Error while creating user:', error);
@@ -138,7 +140,7 @@ export default class Authentication {
login = (form: LoginForm): Promise<void> => {
return signInWithEmailAndPassword(this.auth, form.email, form.password)
.then(userCredentials => {
this.firebaseUser = userCredentials.user;
// The user is now stored in `this.auth`.
})
.catch(error => {
console.error('Error while login:', error);
@@ -150,58 +152,66 @@ export default class Authentication {
return sendPasswordResetEmail(this.auth, form.email);
};
getFirebaseUser = (cb: (any, ?FirebaseUser) => void) => {
if (!this.isAuthenticated()) return cb({ unauthenticated: true });
getFirebaseUser = async (): Promise<?FirebaseUser> => {
const { currentUser } = this.auth;
if (!currentUser) {
return null;
}
// In order to fetch the latest firebaseUser properties (like emailVerified)
// we have to call the reload method.
this.auth.currentUser.reload().then(() => cb(null, this.firebaseUser));
await currentUser.reload();
return this.auth.currentUser;
};
sendFirebaseEmailVerification = (cb: () => void): Promise<void> => {
return this.auth.currentUser.reload().then(() => {
if (!this.firebaseUser || this.firebaseUser.emailVerified) return;
sendEmailVerification(this.auth.currentUser).then(
() => {
cb();
},
(error: Error) => {
showErrorBox({
message: 'An email has been sent recently, please try again later.',
rawError: error,
errorId: 'email-verification-send-error',
});
}
);
});
sendFirebaseEmailVerification = async (): Promise<void> => {
{
const { currentUser } = this.auth;
if (!currentUser)
throw new Error(
'Tried to send verification email while not authenticated.'
);
await currentUser.reload();
}
const { currentUser } = this.auth;
if (!currentUser || currentUser.emailVerified) return;
try {
sendEmailVerification(currentUser);
} catch (error) {
showErrorBox({
message:
'An email has been sent recently, check your inbox or please try again later.',
rawError: error,
errorId: 'email-verification-send-error',
});
}
};
changeEmail = (
changeEmail = async (
getAuthorizationHeader: () => Promise<string>,
form: ChangeEmailForm
) => {
return updateEmail(this.firebaseUser, form.email)
.then(() => sendEmailVerification(this.firebaseUser))
const { currentUser } = this.auth;
if (!currentUser)
throw new Error('Tried to change email while not authenticated.');
return updateEmail(currentUser, form.email)
.then(() => sendEmailVerification(currentUser))
.then(() => {
console.log('Email successfully changed in Firebase.');
return getAuthorizationHeader();
})
.then(authorizationHeader => {
if (!this.firebaseUser) {
console.error(
'Cannot finish editing the user email as it is not logged in any more.'
);
throw new Error(
'Cannot finish editing the user email as it is not logged in any more.'
);
}
return axios.patch(
`${GDevelopUserApi.baseUrl}/user/${this.firebaseUser.uid}`,
`${GDevelopUserApi.baseUrl}/user/${currentUser.uid}`,
{
email: form.email,
},
{
params: {
userId: this.firebaseUser.uid,
userId: currentUser.uid,
},
headers: {
Authorization: authorizationHeader,
@@ -218,28 +228,21 @@ export default class Authentication {
});
};
getUserProfile = (getAuthorizationHeader: () => Promise<string>) => {
getUserProfile = async (getAuthorizationHeader: () => Promise<string>) => {
const { currentUser } = this.auth;
if (!currentUser)
throw new Error('Tried to get user profile while not authenticated.');
return getAuthorizationHeader()
.then(authorizationHeader => {
if (!this.firebaseUser) {
console.error(
'Cannot get the user profile as it is not logged in any more.'
);
throw new Error(
'Cannot get the user profile as it is not logged in any more.'
);
}
return axios.get(
`${GDevelopUserApi.baseUrl}/user/${this.firebaseUser.uid}`,
{
params: {
userId: this.firebaseUser.uid,
},
headers: {
Authorization: authorizationHeader,
},
}
);
return axios.get(`${GDevelopUserApi.baseUrl}/user/${currentUser.uid}`, {
params: {
userId: currentUser.uid,
},
headers: {
Authorization: authorizationHeader,
},
});
})
.then(response => response.data)
.catch(error => {
@@ -248,30 +251,26 @@ export default class Authentication {
});
};
editUserProfile = (
editUserProfile = async (
getAuthorizationHeader: () => Promise<string>,
form: EditForm
) => {
const { currentUser } = this.auth;
if (!currentUser)
throw new Error('Tried to edit user profile while not authenticated.');
return getAuthorizationHeader()
.then(authorizationHeader => {
if (!this.firebaseUser) {
console.error(
'Cannot finish editing the user as it is not logged in any more.'
);
throw new Error(
'Cannot finish editing the user as it is not logged in any more.'
);
}
const { username, description } = form;
return axios.patch(
`${GDevelopUserApi.baseUrl}/user/${this.firebaseUser.uid}`,
`${GDevelopUserApi.baseUrl}/user/${currentUser.uid}`,
{
username,
description,
},
{
params: {
userId: this.firebaseUser.uid,
userId: currentUser.uid,
},
headers: {
Authorization: authorizationHeader,
@@ -287,7 +286,7 @@ export default class Authentication {
};
getFirebaseUserSync = (): ?FirebaseUser => {
return this.firebaseUser;
return this.auth.currentUser || null;
};
logout = () => {
@@ -301,14 +300,14 @@ export default class Authentication {
});
};
getAuthorizationHeader = (): Promise<string> => {
if (!this.firebaseUser)
return Promise.reject(new Error('User is not authenticated'));
getAuthorizationHeader = async (): Promise<string> => {
const { currentUser } = this.auth;
if (!currentUser) throw new Error('User is not authenticated.');
return this.firebaseUser.getIdToken().then(token => `Bearer ${token}`);
return currentUser.getIdToken().then(token => `Bearer ${token}`);
};
isAuthenticated = (): boolean => {
return !!this.firebaseUser;
return !!this.auth.currentUser;
};
}

View File

@@ -1,25 +0,0 @@
// @flow
import React from 'react';
export const watchPromiseInState = (
component: React.Component<*, *>,
stateField: string,
fn: () => Promise<any>
) => {
component.setState({
[stateField]: true,
});
return fn()
.then(value => {
component.setState({
[stateField]: false,
});
return value;
})
.catch(err => {
component.setState({
[stateField]: false,
});
throw err;
});
};

View File

@@ -102,13 +102,13 @@ export const fakeIndieAuthenticatedUser: AuthenticatedUser = {
onEdit: () => {},
onChangeEmail: () => {},
onCreateAccount: () => {},
onRefreshUserProfile: () => {
onRefreshUserProfile: async () => {
console.info('This should refresh the user profile');
},
onRefreshFirebaseProfile: () => {
onRefreshFirebaseProfile: async () => {
console.info('This should refresh the firebase profile');
},
onSendEmailVerification: () => {
onSendEmailVerification: async () => {
console.info('This should send the email verification');
},
getAuthorizationHeader: () => Promise.resolve('fake-authorization-header'),
@@ -126,13 +126,13 @@ export const fakeNoSubscriptionAuthenticatedUser: AuthenticatedUser = {
onEdit: () => {},
onChangeEmail: () => {},
onCreateAccount: () => {},
onRefreshUserProfile: () => {
onRefreshUserProfile: async () => {
console.info('This should refresh the user profile');
},
onRefreshFirebaseProfile: () => {
onRefreshFirebaseProfile: async () => {
console.info('This should refresh the firebase profile');
},
onSendEmailVerification: () => {
onSendEmailVerification: async () => {
console.info('This should send the email verification');
},
getAuthorizationHeader: () => Promise.resolve('fake-authorization-header'),
@@ -150,13 +150,13 @@ export const fakeAuthenticatedAndEmailVerifiedUser: AuthenticatedUser = {
onEdit: () => {},
onChangeEmail: () => {},
onCreateAccount: () => {},
onRefreshUserProfile: () => {
onRefreshUserProfile: async () => {
console.info('This should refresh the user profile');
},
onRefreshFirebaseProfile: () => {
onRefreshFirebaseProfile: async () => {
console.info('This should refresh the firebase profile');
},
onSendEmailVerification: () => {
onSendEmailVerification: async () => {
console.info('This should send the email verification');
},
getAuthorizationHeader: () => Promise.resolve('fake-authorization-header'),
@@ -174,13 +174,13 @@ export const fakeAuthenticatedButLoadingAuthenticatedUser: AuthenticatedUser = {
onEdit: () => {},
onChangeEmail: () => {},
onCreateAccount: () => {},
onRefreshUserProfile: () => {
onRefreshUserProfile: async () => {
console.info('This should refresh the user profile');
},
onRefreshFirebaseProfile: () => {
onRefreshFirebaseProfile: async () => {
console.info('This should refresh the firebase profile');
},
onSendEmailVerification: () => {
onSendEmailVerification: async () => {
console.info('This should send the email verification');
},
getAuthorizationHeader: () => Promise.resolve('fake-authorization-header'),
@@ -198,13 +198,13 @@ export const fakeNotAuthenticatedAuthenticatedUser: AuthenticatedUser = {
onEdit: () => {},
onChangeEmail: () => {},
onCreateAccount: () => {},
onRefreshUserProfile: () => {
onRefreshUserProfile: async () => {
console.info('This should refresh the user profile');
},
onRefreshFirebaseProfile: () => {
onRefreshFirebaseProfile: async () => {
console.info('This should refresh the firebase profile');
},
onSendEmailVerification: () => {
onSendEmailVerification: async () => {
console.info('This should send the email verification');
},
getAuthorizationHeader: () => Promise.resolve('fake-authorization-header'),