diff options
| author | Andy Rickert <andrew_rickert@brown.edu> | 2020-05-12 17:37:54 -0700 | 
|---|---|---|
| committer | Andy Rickert <andrew_rickert@brown.edu> | 2020-05-12 17:37:54 -0700 | 
| commit | 9ad062907d38a7a853ba89fa31433380ae3cd7b3 (patch) | |
| tree | 707855e1bc6fa8ac3d1f51447815a51eb83b8aa3 /src/client/apis/GoogleAuthenticationManager.tsx | |
| parent | 1848c78f889470d6c558f709efe1b521402b2793 (diff) | |
| parent | 4bd011dcc6a3f009fa10932c7c6ca1932b784fde (diff) | |
merge
Diffstat (limited to 'src/client/apis/GoogleAuthenticationManager.tsx')
| -rw-r--r-- | src/client/apis/GoogleAuthenticationManager.tsx | 124 | 
1 files changed, 81 insertions, 43 deletions
| diff --git a/src/client/apis/GoogleAuthenticationManager.tsx b/src/client/apis/GoogleAuthenticationManager.tsx index 417dc3c3b..22d6fb582 100644 --- a/src/client/apis/GoogleAuthenticationManager.tsx +++ b/src/client/apis/GoogleAuthenticationManager.tsx @@ -1,10 +1,11 @@ -import { observable, action, reaction, runInAction } from "mobx"; +import { observable, action, reaction, runInAction, IReactionDisposer } from "mobx";  import { observer } from "mobx-react";  import * as React from "react";  import MainViewModal from "../views/MainViewModal";  import { Opt } from "../../new_fields/Doc";  import { Networking } from "../Network";  import "./GoogleAuthenticationManager.scss"; +import { Scripting } from "../util/Scripting";  const AuthenticationUrl = "https://accounts.google.com/o/oauth2/v2/auth";  const prompt = "Paste authorization code here..."; @@ -15,64 +16,88 @@ export default class GoogleAuthenticationManager extends React.Component<{}> {      private authenticationLink: Opt<string> = undefined;      @observable private openState = false;      @observable private authenticationCode: Opt<string> = undefined; -    @observable private clickedState = false; +    @observable private showPasteTargetState = false;      @observable private success: Opt<boolean> = undefined;      @observable private displayLauncher = true; -    @observable private avatar: Opt<string> = undefined; -    @observable private username: Opt<string> = undefined; +    @observable private credentials: any; +    private disposer: Opt<IReactionDisposer>;      private set isOpen(value: boolean) {          runInAction(() => this.openState = value);      } -    private set hasBeenClicked(value: boolean) { -        runInAction(() => this.clickedState = value); +    private set shouldShowPasteTarget(value: boolean) { +        runInAction(() => this.showPasteTargetState = value);      } -    public fetchOrGenerateAccessToken = async () => { -        const response = await Networking.FetchFromServer("/readGoogleAccessToken"); +    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<string>(async resolve => { -                const disposer = reaction( +                this.disposer?.(); +                this.disposer = reaction(                      () => this.authenticationCode,                      async authenticationCode => { -                        if (authenticationCode) { -                            disposer(); -                            const { access_token, avatar, name } = await Networking.PostToServer("/writeGoogleAccessToken", { authenticationCode }); +                        if (authenticationCode && /\d{1}\/[\w-]{55}/.test(authenticationCode)) { +                            this.disposer?.(); +                            const response = await Networking.PostToServer("/writeGoogleAccessToken", { authenticationCode });                              runInAction(() => { -                                this.avatar = avatar; -                                this.username = name; -                                this.hasBeenClicked = false; -                                this.success = false; +                                this.success = true; +                                this.credentials = response;                              }); -                            this.beginFadeout(); -                            resolve(access_token); +                            this.resetState(); +                            resolve(response.access_token);                          }                      }                  );              });          } -        // otherwise, we already have a valid, stored access token -        return response; + +        // 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;      } -    beginFadeout = action(() => { -        this.success = true; +    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.hasBeenClicked = false; -        setTimeout(action(() => { -            this.isOpen = false; +        this.shouldShowPasteTarget = false; +        if (visibleForMS > 0 && fadesOutInMS > 0) {              setTimeout(action(() => { -                this.success = undefined; -                this.displayLauncher = true; -                this.avatar = undefined; -                this.username = undefined; -            }), 500); -        }), 3000); +                this.isOpen = false; +                setTimeout(action(() => { +                    this.success = undefined; +                    this.displayLauncher = true; +                    this.credentials = undefined; +                }), fadesOutInMS); +            }), visibleForMS); +        }      });      constructor(props: {}) { @@ -83,27 +108,38 @@ export default class GoogleAuthenticationManager extends React.Component<{}> {      private get renderPrompt() {          return (              <div className={'authorize-container'}> +                  {this.displayLauncher ? <button                      className={"dispatch"}                      onClick={() => {                          window.open(this.authenticationLink); -                        setTimeout(() => this.hasBeenClicked = true, 500); +                        setTimeout(() => this.shouldShowPasteTarget = true, 500);                      }} -                    style={{ marginBottom: this.clickedState ? 15 : 0 }} +                    style={{ marginBottom: this.showPasteTargetState ? 15 : 0 }}                  >Authorize a Google account...</button> : (null)} -                {this.clickedState ? <input +                {this.showPasteTargetState ? <input                      className={'paste-target'}                      onChange={action(e => this.authenticationCode = e.currentTarget.value)}                      placeholder={prompt}                  /> : (null)} -                {this.avatar ? <img -                    className={'avatar'} -                    src={this.avatar} -                /> : (null)} -                {this.username ? <span -                    className={'welcome'} -                >Welcome to Dash, {this.username} -                </span> : (null)} +                {this.credentials ? +                    <> +                        <img +                            className={'avatar'} +                            src={this.credentials.userInfo.picture} +                        /> +                        <span +                            className={'welcome'} +                        >Welcome to Dash, {this.credentials.userInfo.name} +                        </span> +                        <div +                            className={'disconnect'} +                            onClick={async () => { +                                await Networking.FetchFromServer("/revokeGoogleAccessToken"); +                                this.resetState(0, 0); +                            }} +                        >Disconnect Account</div> +                    </> : (null)}              </div>          );      } @@ -125,4 +161,6 @@ export default class GoogleAuthenticationManager extends React.Component<{}> {          );      } -}
\ No newline at end of file +} + +Scripting.addGlobal("GoogleAuthenticationManager", GoogleAuthenticationManager);
\ No newline at end of file | 
