aboutsummaryrefslogtreecommitdiff
path: root/src/client/apis/GoogleAuthenticationManager.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-06-19 15:34:13 -0400
committerbobzel <zzzman@gmail.com>2025-06-19 15:34:13 -0400
commit21fb3a555cdd861452e2e54de3d0524e29f2bc08 (patch)
tree44b93ba0b4f9a85dafdb744ccb11dfe3386f4829 /src/client/apis/GoogleAuthenticationManager.tsx
parentabdfe5b109f42cd5da4aceef1bd667c8e1f6cbbd (diff)
parent765c7a3870a1d446622a28b157ab00a4dced2879 (diff)
Merge branch 'task_nodes_aarav'
Diffstat (limited to 'src/client/apis/GoogleAuthenticationManager.tsx')
-rw-r--r--src/client/apis/GoogleAuthenticationManager.tsx84
1 files changed, 46 insertions, 38 deletions
diff --git a/src/client/apis/GoogleAuthenticationManager.tsx b/src/client/apis/GoogleAuthenticationManager.tsx
index 94ce42d8d..67a6e01e9 100644
--- a/src/client/apis/GoogleAuthenticationManager.tsx
+++ b/src/client/apis/GoogleAuthenticationManager.tsx
@@ -1,4 +1,4 @@
-import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { action, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Opt } from '../../fields/Doc';
@@ -6,12 +6,12 @@ import { Networking } from '../Network';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { MainViewModal } from '../views/MainViewModal';
import './GoogleAuthenticationManager.scss';
+import { ObservableReactComponent } from '../views/ObservableReactComponent';
-const AuthenticationUrl = 'https://accounts.google.com/o/oauth2/v2/auth';
const prompt = 'Paste authorization code here...';
@observer
-export class GoogleAuthenticationManager extends React.Component<object> {
+export class GoogleAuthenticationManager extends ObservableReactComponent<object> {
// eslint-disable-next-line no-use-before-define
public static Instance: GoogleAuthenticationManager;
private authenticationLink: Opt<string> = undefined;
@@ -23,6 +23,12 @@ export class GoogleAuthenticationManager extends React.Component<object> {
@observable private credentials: { user_info: { name: string; picture: string }; access_token: string } | undefined = undefined;
private disposer: Opt<IReactionDisposer>;
+ constructor(props: object) {
+ super(props);
+ makeObservable(this);
+ GoogleAuthenticationManager.Instance = this;
+ }
+
private set isOpen(value: boolean) {
runInAction(() => (this.openState = value));
}
@@ -35,44 +41,51 @@ export class GoogleAuthenticationManager extends React.Component<object> {
this.openState && this.resetState(0, 0);
}
- public fetchOrGenerateAccessToken = async (displayIfFound = false) => {
+ public fetchOrGenerateAccessToken = async (): Promise<string | undefined> => {
const response = 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>(resolve => {
- this.disposer?.();
- this.disposer = reaction(
- () => this.authenticationCode,
- async authenticationCode => {
- if (authenticationCode && /\d{1}\/[\w-]{55}/.test(authenticationCode)) {
- this.disposer?.();
- const response2 = await Networking.PostToServer('/writeGoogleAccessToken', { authenticationCode });
- runInAction(() => {
- this.success = true;
- this.credentials = response2 as { user_info: { name: string; picture: string }; access_token: string };
- });
- this.resetState();
- resolve((response2 as { access_token: string }).access_token);
- }
- }
- );
+
+ // This will return a JSON object with { access_token, user_info } if already linked
+ try {
+ const parsed = JSON.parse(response) as { access_token: string; user_info: { name: string; picture: string } };
+
+ runInAction(() => {
+ this.success = true;
+ this.credentials = parsed;
});
+
+ return parsed.access_token;
+ } catch {
+ console.warn('Not linked yet or invalid JSON. open auth...');
+ // This is an auth URL — redirect the user to /refreshGoogle
+ if (typeof response === 'string' && response.startsWith('http')) {
+ if (window.confirm('Authorize Dash to access your Google account?')) {
+ window.open(response)?.focus();
+ return undefined;
+ }
+ }
+
+ throw new Error('Unable to fetch Google access token.');
}
+ };
- // otherwise, we already have a valid, stored access token and user info
- const response2 = JSON.parse(response) as { user_info: { name: string; picture: string }; access_token: string };
- if (displayIfFound) {
+ public fetchAccessTokenSilently = async (): Promise<string | undefined> => {
+ const response = await Networking.FetchFromServer('/readGoogleAccessToken');
+
+ try {
+ const parsed = JSON.parse(response) as { access_token: string; user_info: { name: string; picture: string } };
+
runInAction(() => {
this.success = true;
- this.credentials = response2;
+ this.credentials = parsed;
});
- this.resetState(-1, -1);
- this.isOpen = true;
+
+ return parsed.access_token;
+ } catch {
+ // Do nothing — just return undefined silently
+ return undefined;
}
- return (response2 as { access_token: string }).access_token;
};
+
resetState = action((visibleForMS: number = 3000, fadesOutInMS: number = 500) => {
if (!visibleForMS && !fadesOutInMS) {
@@ -107,11 +120,6 @@ export class GoogleAuthenticationManager extends React.Component<object> {
}
});
- constructor(props: object) {
- super(props);
- GoogleAuthenticationManager.Instance = this;
- }
-
private get renderPrompt() {
return (
<div className={'authorize-container'}>
@@ -127,7 +135,7 @@ export class GoogleAuthenticationManager extends React.Component<object> {
</button>
) : null}
{this.showPasteTargetState ? <input className={'paste-target'} onChange={action(e => (this.authenticationCode = e.currentTarget.value))} placeholder={prompt} /> : null}
- {this.credentials ? (
+ {this.credentials?.user_info?.picture ? (
<>
<img className={'avatar'} src={this.credentials.user_info.picture} />
<span className={'welcome'}>Welcome to Dash, {this.credentials.user_info.name}</span>