fix: fix auth/graphql errors causing errors on logout (#2772)

This commit is contained in:
Akash K
2022-10-11 14:06:22 +05:30
committed by GitHub
parent 4046b91609
commit 4d19b9249b
2 changed files with 106 additions and 78 deletions

View File

@@ -54,88 +54,112 @@ export type GQLClientErrorEvent =
*/
export const gqlClientError$ = new Subject<GQLClientErrorEvent>()
const subscriptionClient = new SubscriptionClient(BACKEND_WS_URL, {
reconnect: true,
connectionParams: () => {
return {
authorization: `Bearer ${authIdToken$.value}`,
}
},
connectionCallback(error) {
if (error?.length > 0) {
gqlClientError$.next({
type: "SUBSCRIPTION_CONN_CALLBACK_ERR_REPORT",
errors: error,
})
}
},
})
authIdToken$.subscribe(() => {
subscriptionClient.client?.close()
})
const createHoppClient = () =>
createClient({
url: BACKEND_GQL_URL,
exchanges: [
devtoolsExchange,
dedupExchange,
authExchange({
addAuthToOperation({ authState, operation }) {
if (!authState || !authState.authToken) {
return operation
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {}
return makeOperation(operation.kind, operation, {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
Authorization: `Bearer ${authState.authToken}`,
},
},
})
},
willAuthError({ authState }) {
return !authState || !authState.authToken
},
getAuth: async () => {
if (!probableUser$.value) return { authToken: null }
await waitProbableLoginToConfirm()
return {
authToken: getAuthIDToken(),
}
},
}),
fetchExchange,
subscriptionExchange({
forwardSubscription: (operation) =>
subscriptionClient.request(operation),
}),
errorExchange({
onError(error, op) {
gqlClientError$.next({
type: "CLIENT_REPORTED_ERROR",
error,
op,
})
},
}),
],
const createSubscriptionClient = () => {
return new SubscriptionClient(BACKEND_WS_URL, {
reconnect: true,
connectionParams: () => {
return {
authorization: `Bearer ${authIdToken$.value}`,
}
},
connectionCallback(error) {
if (error?.length > 0) {
gqlClientError$.next({
type: "SUBSCRIPTION_CONN_CALLBACK_ERR_REPORT",
errors: error,
})
}
},
})
}
const createHoppClient = () => {
const exchanges = [
devtoolsExchange,
dedupExchange,
authExchange({
addAuthToOperation({ authState, operation }) {
if (!authState || !authState.authToken) {
return operation
}
const fetchOptions =
typeof operation.context.fetchOptions === "function"
? operation.context.fetchOptions()
: operation.context.fetchOptions || {}
return makeOperation(operation.kind, operation, {
...operation.context,
fetchOptions: {
...fetchOptions,
headers: {
...fetchOptions.headers,
Authorization: `Bearer ${authState.authToken}`,
},
},
})
},
willAuthError({ authState }) {
return !authState || !authState.authToken
},
getAuth: async () => {
if (!probableUser$.value) return { authToken: null }
await waitProbableLoginToConfirm()
return {
authToken: getAuthIDToken(),
}
},
}),
fetchExchange,
errorExchange({
onError(error, op) {
gqlClientError$.next({
type: "CLIENT_REPORTED_ERROR",
error,
op,
})
},
}),
]
if (subscriptionClient) {
exchanges.push(
subscriptionExchange({
forwardSubscription: (operation) => {
return subscriptionClient!.request(operation)
},
})
)
}
return createClient({
url: BACKEND_GQL_URL,
exchanges,
})
}
let subscriptionClient: SubscriptionClient | null
export const client = ref(createHoppClient())
authIdToken$.subscribe(() => {
authIdToken$.subscribe((idToken) => {
// triggering reconnect by closing the websocket client
if (idToken && subscriptionClient) {
subscriptionClient?.client?.close()
}
// creating new subscription
if (idToken && !subscriptionClient) {
subscriptionClient = createSubscriptionClient()
}
// closing existing subscription client.
if (!idToken && subscriptionClient) {
subscriptionClient.close()
subscriptionClient = null
}
client.value = createHoppClient()
})

View File

@@ -2,6 +2,7 @@ import * as E from "fp-ts/Either"
import { BehaviorSubject } from "rxjs"
import { GQLError, runGQLQuery } from "../backend/GQLClient"
import { GetMyTeamsDocument, GetMyTeamsQuery } from "../backend/graphql"
import { authIdToken$ } from "~/helpers/fb/auth"
const BACKEND_PAGE_SIZE = 10
const POLL_DURATION = 10000
@@ -46,6 +47,9 @@ export default class TeamListAdapter {
}
async fetchList() {
// if the authIdToken is not present, don't fetch the teams list, as it will fail anyway
if (!authIdToken$.value) return
this.loading$.next(true)
const results: GetMyTeamsQuery["myTeams"] = []