import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Opt } from '../../fields/Doc'; import { Networking } from '../Network'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { MainViewModal } from '../views/MainViewModal'; import './GoogleAuthenticationManager.scss'; const AuthenticationUrl = 'https://accounts.google.com/o/oauth2/v2/auth'; const prompt = 'Paste authorization code here...'; @observer export class GoogleAuthenticationManager extends React.Component<{}> { public static Instance: GoogleAuthenticationManager; private authenticationLink: Opt = undefined; @observable private openState = false; @observable private authenticationCode: Opt = undefined; @observable private showPasteTargetState = false; @observable private success: Opt = undefined; @observable private displayLauncher = true; @observable private credentials: any; private disposer: Opt; private set isOpen(value: boolean) { runInAction(() => (this.openState = value)); } private set shouldShowPasteTarget(value: boolean) { runInAction(() => (this.showPasteTargetState = value)); } public cancel() { this.openState && this.resetState(0, 0); } public fetchOrGenerateAccessToken = async (displayIfFound = false) => { let response: any = await Networking.FetchFromServer('/readGoogleAccessToken'); // if this is an authentication url, activate the UI to register the new access token if (new RegExp(AuthenticationUrl).test(response)) { this.isOpen = true; this.authenticationLink = response; return new Promise(async resolve => { this.disposer?.(); this.disposer = reaction( () => this.authenticationCode, async authenticationCode => { if (authenticationCode && /\d{1}\/[\w-]{55}/.test(authenticationCode)) { this.disposer?.(); const response = await Networking.PostToServer('/writeGoogleAccessToken', { authenticationCode }); runInAction(() => { this.success = true; this.credentials = response; }); this.resetState(); resolve(response.access_token); } } ); }); } // otherwise, we already have a valid, stored access token and user info response = JSON.parse(response); if (displayIfFound) { runInAction(() => { this.success = true; this.credentials = response; }); this.resetState(-1, -1); this.isOpen = true; } return response.access_token; }; resetState = action((visibleForMS: number = 3000, fadesOutInMS: number = 500) => { if (!visibleForMS && !fadesOutInMS) { runInAction(() => { this.isOpen = false; this.success = undefined; this.displayLauncher = true; this.credentials = undefined; this.shouldShowPasteTarget = false; this.authenticationCode = undefined; }); return; } this.authenticationCode = undefined; this.displayLauncher = false; this.shouldShowPasteTarget = false; if (visibleForMS > 0 && fadesOutInMS > 0) { setTimeout( action(() => { this.isOpen = false; setTimeout( action(() => { this.success = undefined; this.displayLauncher = true; this.credentials = undefined; }), fadesOutInMS ); }), visibleForMS ); } }); constructor(props: {}) { super(props); GoogleAuthenticationManager.Instance = this; } private get renderPrompt() { return (
{this.displayLauncher ? ( ) : null} {this.showPasteTargetState ? (this.authenticationCode = e.currentTarget.value))} placeholder={prompt} /> : null} {this.credentials ? ( <> Welcome to Dash, {this.credentials.userInfo.name}
{ await Networking.FetchFromServer('/revokeGoogleAccessToken'); this.resetState(0, 0); }}> Disconnect Account
) : null}
); } private get dialogueBoxStyle() { const borderColor = this.success === undefined ? 'black' : this.success ? 'green' : 'red'; return { borderColor, transition: '0.2s borderColor ease', zIndex: 1002 }; } render() { return (this.isOpen = false))} />; } } ScriptingGlobals.add('GoogleAuthenticationManager', GoogleAuthenticationManager);