Skip to content

Commit 2c45653

Browse files
committed
rename user to token, save login state in browser
1 parent a2099f5 commit 2c45653

4 files changed

Lines changed: 71 additions & 38 deletions

File tree

gatsby/onInitialClientRender.js

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import loadScript from "load-script"
22
import { store } from "./wrapRootElement"
33

44
export const onInitialClientRender = () => {
5-
65
const gapiPromise = new Promise((resolve, reject) => {
76
loadScript("https://apis.google.com/js/api.js", err => {
87
if (err) {
@@ -36,6 +35,22 @@ export const onInitialClientRender = () => {
3635
return
3736
}
3837

38+
try {
39+
const storedTokenString = localStorage.getItem("google_token")
40+
if (storedTokenString) {
41+
const storedToken = JSON.parse(storedTokenString)
42+
if (storedToken.expires_at > Date.now()) {
43+
gapi.client.setToken(storedToken)
44+
store.dispatch({ type: "setToken", token: storedToken })
45+
} else {
46+
localStorage.removeItem("google_token")
47+
}
48+
}
49+
} catch (e) {
50+
console.error("Unable to restore token from localStorage:", e)
51+
localStorage.removeItem("google_token")
52+
}
53+
3954
Promise.all([
4055
gapi.client.load(
4156
"https://analyticsdata.googleapis.com/$discovery/rest"
@@ -51,28 +66,43 @@ export const onInitialClientRender = () => {
5166
client_id: clientId,
5267
scope: SCOPES.join(" "),
5368
callback: tokenResponse => {
54-
console.log("onInitialClientRender: callback invoked", tokenResponse)
69+
console.log(
70+
"onInitialClientRender: callback invoked",
71+
tokenResponse
72+
)
5573
if (tokenResponse && tokenResponse.access_token) {
56-
gapi.client.setToken(tokenResponse.access_token)
57-
console.log("onInitialClientRender: setUser", tokenResponse);
58-
store.dispatch({ type: "setUser", user: tokenResponse })
74+
const tokenWithExpiry = {
75+
...tokenResponse,
76+
expires_at: Date.now() + tokenResponse.expires_in * 1000,
77+
}
78+
localStorage.setItem(
79+
"google_token",
80+
JSON.stringify(tokenWithExpiry)
81+
)
82+
gapi.client.setToken(tokenResponse)
83+
console.log("onInitialClientRender: setToken", tokenResponse)
84+
store.dispatch({ type: "setToken", token: tokenResponse })
5985
} else {
60-
console.error("onInitialClientRender: tokenResponse did not contain access_token.", tokenResponse);
61-
store.dispatch({ type: "setUser", user: undefined })
86+
console.error(
87+
"onInitialClientRender: tokenResponse did not contain access_token.",
88+
tokenResponse
89+
)
90+
store.dispatch({ type: "setToken", token: undefined })
6291
}
63-
}, error_callback: (error) => {
64-
console.error("GIS Error:", error);
92+
},
93+
error_callback: error => {
94+
console.error("GIS Error:", error)
6595
},
6696
})
6797

6898
store.dispatch({ type: "setGapi", gapi })
6999
store.dispatch({ type: "gapiStatus", status: "initialized" })
70100
store.dispatch({ type: "setGoogle", google })
71101
store.dispatch({ type: "setTokenClient", tokenClient })
72-
})
102+
})
73103
.catch(e => {
74104
store.dispatch({ type: "setGapi", gapi })
75-
store.dispatch({ type: "setUser", user: undefined })
105+
store.dispatch({ type: "setToken", token: undefined })
76106
store.dispatch({ type: "gapiStatus", status: "cannot initialize" })
77107
console.error(e)
78108
})

gatsby/wrapRootElement.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {PartialDeep} from 'type-fest';
1818

1919
type State =
2020
{
21-
user?: {},
21+
token?: {},
2222
gapi?: PartialDeep<typeof gapi>,
2323
google?: any,
2424
tokenClient?: any,
@@ -27,16 +27,16 @@ type State =
2727
}
2828

2929
type Action =
30-
| { type: 'setUser', user: {} | undefined }
30+
| { type: 'setToken', token: {} | undefined }
3131
| { type: 'setGapi', gapi: PartialDeep<typeof gapi> | undefined }
3232
| { type: 'setGoogle', google: any }
3333
| { type: 'setTokenClient', tokenClient: any }
3434
| { type: 'setToast', toast: string | undefined }
3535
| { type: 'gapiStatus', status: string | undefined };
3636
const reducer = (state: State = {}, action: Action) => {
3737
switch (action.type) {
38-
case "setUser":
39-
return { ...state, user: action.user }
38+
case "setToken":
39+
return { ...state, user: action.token }
4040
case "setGapi":
4141
return { ...state, gapi: action.gapi }
4242
case "setGoogle":

src/components/Layout/useLogin.ts

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Requestable, RequestStatus } from "@/types"
22
import { useState, useEffect, useCallback } from "react"
33

4-
import { useSelector } from "react-redux"
4+
import { useSelector, useDispatch } from "react-redux"
55

66
export enum UserStatus {
77
SignedIn,
@@ -11,7 +11,7 @@ export enum UserStatus {
1111

1212
interface Successful {
1313
userStatus: UserStatus
14-
user: gapi.auth2.GoogleUser | undefined
14+
user: any
1515
logout: () => void
1616
login: () => void
1717
}
@@ -21,24 +21,35 @@ interface Failed {
2121
}
2222
const useLogin = (): Requestable<Successful, {}, InProgress, Failed> => {
2323
const [requestStatus, setRequestStatus] = useState(RequestStatus.NotStarted)
24-
const user = useSelector((state: AppState) => state.user)
24+
const token = useSelector((state: AppState) => state.token)
2525
const gapi = useSelector((state: AppState) => state.gapi)
2626
const gapiStatus = useSelector((state: AppState) => state.gapiStatus)
27-
const [userStatus, setUserStatus] = useState<UserStatus>(UserStatus.Pending)
27+
const tokenClient = useSelector((state: AppState) => state.tokenClient)
28+
const google = useSelector((state: AppState) => state.google)
29+
const dispatch = useDispatch()
30+
31+
console.log("useLogin: token", token);
32+
console.log("useLogin: gapiStatus", gapiStatus);
33+
const userStatus = token ? UserStatus.SignedIn : UserStatus.SignedOut
2834

2935
const login = useCallback(() => {
30-
if (gapi === undefined) {
31-
return
36+
console.log("login called. tokenClient:", tokenClient)
37+
if (tokenClient) {
38+
console.log("requesting access token")
39+
tokenClient.requestAccessToken()
3240
}
33-
gapi.auth2.getAuthInstance().signIn()
34-
}, [gapi])
41+
}, [tokenClient])
3542

3643
const logout = useCallback(() => {
37-
if (gapi === undefined) {
38-
return
44+
const token = gapi?.client.getToken()
45+
if (token && google) {
46+
google.accounts.oauth2.revoke(token.access_token, () => {
47+
gapi?.client.setToken(null)
48+
dispatch({ type: "setUser", user: undefined })
49+
localStorage.removeItem("google_token")
50+
})
3951
}
40-
gapi.auth2.getAuthInstance().signOut()
41-
}, [gapi])
52+
}, [gapi, google, dispatch])
4253

4354
useEffect(() => {
4455
if (gapiStatus === "cannot initialize") {
@@ -61,19 +72,11 @@ const useLogin = (): Requestable<Successful, {}, InProgress, Failed> => {
6172
setRequestStatus(RequestStatus.InProgress)
6273
}
6374

64-
gapi.auth2.getAuthInstance().isSignedIn.listen(signedIn => {
65-
setUserStatus(signedIn ? UserStatus.SignedIn : UserStatus.SignedOut)
66-
})
67-
68-
gapi.auth2.getAuthInstance().isSignedIn.get()
69-
? setUserStatus(UserStatus.SignedIn)
70-
: setUserStatus(UserStatus.SignedOut)
71-
7275
setRequestStatus(RequestStatus.Successful)
7376
}, [gapi, requestStatus, gapiStatus])
7477

7578
if (requestStatus === RequestStatus.Successful) {
76-
return { status: requestStatus, userStatus, user, login, logout }
79+
return { status: requestStatus, userStatus, user: token, login, logout }
7780
}
7881
if (requestStatus === RequestStatus.Failed) {
7982
return { status: requestStatus, message: gapiStatus || "unknown" }
@@ -82,4 +85,4 @@ const useLogin = (): Requestable<Successful, {}, InProgress, Failed> => {
8285
return { status: requestStatus }
8386
}
8487

85-
export default useLogin
88+
export default useLogin

src/global.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ declare module "*.svg" {
2323
declare module "*.module.css";
2424

2525
declare interface AppState {
26-
user?: User
26+
token?: Token
2727
gapi?: typeof gapi
2828
gapiStatus?: string
2929
measurementID: string

0 commit comments

Comments
 (0)