fix(git-gateway): wait for identity widget to initialize (#3660)

This commit is contained in:
Erez Rokah 2020-04-30 17:46:07 +03:00 committed by GitHub
parent 213ae86b54
commit 6c229c5149
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 27 deletions

View File

@ -125,7 +125,7 @@ export default class GitGatewayAuthenticationPage extends React.Component {
this.setState({ ...this.state, [name]: e.target.value }); this.setState({ ...this.state, [name]: e.target.value });
}; };
handleLogin = e => { handleLogin = async e => {
e.preventDefault(); e.preventDefault();
const { email, password } = this.state; const { email, password } = this.state;
@ -143,17 +143,16 @@ export default class GitGatewayAuthenticationPage extends React.Component {
return; return;
} }
GitGatewayAuthenticationPage.authClient try {
.login(this.state.email, this.state.password, true) const client = await GitGatewayAuthenticationPage.authClient();
.then(user => { const user = await client.login(this.state.email, this.state.password, true);
this.props.onLogin(user); this.props.onLogin(user);
}) } catch (error) {
.catch(error => { this.setState({
this.setState({ errors: { server: error.description || error.msg || error },
errors: { server: error.description || error.msg || error }, loggingIn: false,
loggingIn: false,
});
}); });
}
}; };
render() { render() {

View File

@ -33,9 +33,22 @@ import GitLabAPI from './GitLabAPI';
import AuthenticationPage from './AuthenticationPage'; import AuthenticationPage from './AuthenticationPage';
import { getClient, Client } from './netlify-lfs-client'; import { getClient, Client } from './netlify-lfs-client';
type NetlifyIdentity = {
logout: () => void;
currentUser: () => User;
on: (event: string, args: unknown) => void;
init: () => void;
};
type AuthClient = {
logout: () => void;
currentUser: () => unknown;
login?(email: string, password: string, remember?: boolean): Promise<unknown>;
};
declare global { declare global {
interface Window { interface Window {
netlifyIdentity?: { gotrue: GoTrue; logout: () => void }; netlifyIdentity?: NetlifyIdentity;
} }
} }
@ -69,6 +82,27 @@ function getEndpoint(endpoint: string, netlifySiteURL: string | null) {
return endpoint; return endpoint;
} }
// wait for identity widget to initialize
// force init on timeout
let initPromise = Promise.resolve() as Promise<unknown>;
if (window.netlifyIdentity) {
let initialized = false;
initPromise = Promise.race([
new Promise(resolve => {
window.netlifyIdentity?.on('init', () => {
initialized = true;
resolve();
});
}),
new Promise(resolve => setTimeout(resolve, 2500)).then(() => {
if (!initialized) {
console.log('Manually initializing identity widget');
window.netlifyIdentity?.init();
}
}),
]);
}
interface NetlifyUser extends Credentials { interface NetlifyUser extends Credentials {
jwt: () => Promise<string>; jwt: () => Promise<string>;
email: string; email: string;
@ -85,7 +119,8 @@ export default class GitGateway implements Implementation {
gatewayUrl: string; gatewayUrl: string;
netlifyLargeMediaURL: string; netlifyLargeMediaURL: string;
backendType: string | null; backendType: string | null;
authClient: GoTrue; apiUrl: string;
authClient?: AuthClient;
backend: GitHubBackend | GitLabBackend | BitbucketBackend | null; backend: GitHubBackend | GitLabBackend | BitbucketBackend | null;
acceptRoles?: string[]; acceptRoles?: string[];
tokenPromise?: () => Promise<string>; tokenPromise?: () => Promise<string>;
@ -110,7 +145,7 @@ export default class GitGateway implements Implementation {
this.transformImages = config.backend.use_large_media_transforms_in_media_library || true; this.transformImages = config.backend.use_large_media_transforms_in_media_library || true;
const netlifySiteURL = localStorage.getItem('netlifySiteURL'); const netlifySiteURL = localStorage.getItem('netlifySiteURL');
const APIUrl = getEndpoint(config.backend.identity_url || defaults.identity, netlifySiteURL); this.apiUrl = getEndpoint(config.backend.identity_url || defaults.identity, netlifySiteURL);
this.gatewayUrl = getEndpoint(config.backend.gateway_url || defaults.gateway, netlifySiteURL); this.gatewayUrl = getEndpoint(config.backend.gateway_url || defaults.gateway, netlifySiteURL);
this.netlifyLargeMediaURL = getEndpoint( this.netlifyLargeMediaURL = getEndpoint(
config.backend.large_media_url || defaults.largeMedia, config.backend.large_media_url || defaults.largeMedia,
@ -125,18 +160,40 @@ export default class GitGateway implements Implementation {
this.backendType = null; this.backendType = null;
} }
this.authClient = window.netlifyIdentity
? window.netlifyIdentity.gotrue
: new GoTrue({ APIUrl });
AuthenticationPage.authClient = this.authClient;
this.backend = null; this.backend = null;
AuthenticationPage.authClient = () => this.getAuthClient();
} }
isGitBackend() { isGitBackend() {
return true; return true;
} }
async getAuthClient() {
if (this.authClient) {
return this.authClient;
}
await initPromise;
if (window.netlifyIdentity) {
this.authClient = {
logout: () => window.netlifyIdentity?.logout(),
currentUser: () => window.netlifyIdentity?.currentUser(),
};
} else {
const goTrue = new GoTrue({ APIUrl: this.apiUrl });
this.authClient = {
logout: () => {
const user = goTrue.currentUser();
if (user) {
return user.logout();
}
},
currentUser: () => goTrue.currentUser(),
login: goTrue.login.bind(goTrue),
};
}
return this.authClient;
}
requestFunction = (req: ApiRequest) => requestFunction = (req: ApiRequest) =>
this.tokenPromise!() this.tokenPromise!()
.then( .then(
@ -233,8 +290,9 @@ export default class GitGateway implements Implementation {
return { name: userData.name, login: userData.email } as User; return { name: userData.name, login: userData.email } as User;
}); });
} }
restoreUser() { async restoreUser() {
const user = this.authClient && this.authClient.currentUser(); const client = await this.getAuthClient();
const user = client.currentUser();
if (!user) return Promise.reject(); if (!user) return Promise.reject();
return this.authenticate(user as Credentials); return this.authenticate(user as Credentials);
} }
@ -242,12 +300,9 @@ export default class GitGateway implements Implementation {
return AuthenticationPage; return AuthenticationPage;
} }
logout() { async logout() {
if (window.netlifyIdentity) { const client = await this.getAuthClient();
return window.netlifyIdentity.logout(); return client.logout();
}
const user = this.authClient.currentUser();
return user && user.logout();
} }
getToken() { getToken() {
return this.tokenPromise!(); return this.tokenPromise!();