fix: fix auth/graphql errors causing errors on logout (#2772)
This commit is contained in:
@@ -54,88 +54,112 @@ export type GQLClientErrorEvent =
|
|||||||
*/
|
*/
|
||||||
export const gqlClientError$ = new Subject<GQLClientErrorEvent>()
|
export const gqlClientError$ = new Subject<GQLClientErrorEvent>()
|
||||||
|
|
||||||
const subscriptionClient = new SubscriptionClient(BACKEND_WS_URL, {
|
const createSubscriptionClient = () => {
|
||||||
reconnect: true,
|
return new SubscriptionClient(BACKEND_WS_URL, {
|
||||||
connectionParams: () => {
|
reconnect: true,
|
||||||
return {
|
connectionParams: () => {
|
||||||
authorization: `Bearer ${authIdToken$.value}`,
|
return {
|
||||||
}
|
authorization: `Bearer ${authIdToken$.value}`,
|
||||||
},
|
}
|
||||||
connectionCallback(error) {
|
},
|
||||||
if (error?.length > 0) {
|
connectionCallback(error) {
|
||||||
gqlClientError$.next({
|
if (error?.length > 0) {
|
||||||
type: "SUBSCRIPTION_CONN_CALLBACK_ERR_REPORT",
|
gqlClientError$.next({
|
||||||
errors: error,
|
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 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())
|
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()
|
client.value = createHoppClient()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import * as E from "fp-ts/Either"
|
|||||||
import { BehaviorSubject } from "rxjs"
|
import { BehaviorSubject } from "rxjs"
|
||||||
import { GQLError, runGQLQuery } from "../backend/GQLClient"
|
import { GQLError, runGQLQuery } from "../backend/GQLClient"
|
||||||
import { GetMyTeamsDocument, GetMyTeamsQuery } from "../backend/graphql"
|
import { GetMyTeamsDocument, GetMyTeamsQuery } from "../backend/graphql"
|
||||||
|
import { authIdToken$ } from "~/helpers/fb/auth"
|
||||||
|
|
||||||
const BACKEND_PAGE_SIZE = 10
|
const BACKEND_PAGE_SIZE = 10
|
||||||
const POLL_DURATION = 10000
|
const POLL_DURATION = 10000
|
||||||
@@ -46,6 +47,9 @@ export default class TeamListAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetchList() {
|
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)
|
this.loading$.next(true)
|
||||||
|
|
||||||
const results: GetMyTeamsQuery["myTeams"] = []
|
const results: GetMyTeamsQuery["myTeams"] = []
|
||||||
|
|||||||
Reference in New Issue
Block a user