From 4831379d131505f7ebc109edc142e63182c44275 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Fri, 13 Aug 2021 16:56:27 +0200 Subject: [PATCH 1/4] Allow prop for EventBanner to be null Signed-off-by: Thomas Citharel --- js/src/components/Event/EventBanner.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/components/Event/EventBanner.vue b/js/src/components/Event/EventBanner.vue index f2d429ab2..5e653725d 100644 --- a/js/src/components/Event/EventBanner.vue +++ b/js/src/components/Event/EventBanner.vue @@ -15,7 +15,7 @@ import LazyImageWrapper from "../Image/LazyImageWrapper.vue"; }, }) export default class EventBanner extends Vue { - @Prop({ required: true, default: null, type: Object as PropType }) + @Prop({ default: null, type: Object as PropType }) picture!: IMedia | null; } From d71e76d6921c4d630e1ec2f53964e664f44962d4 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Fri, 13 Aug 2021 16:56:51 +0200 Subject: [PATCH 2/4] Fix some queries being called even when not logged-in Signed-off-by: Thomas Citharel --- js/src/components/NavBar.vue | 2 +- js/src/views/Event/Event.vue | 1 + js/src/views/Home.vue | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/js/src/components/NavBar.vue b/js/src/components/NavBar.vue index 44a892aef..834de6654 100644 --- a/js/src/components/NavBar.vue +++ b/js/src/components/NavBar.vue @@ -216,7 +216,7 @@ import RouteName from "../router/name"; loggedUser: { query: USER_SETTINGS, skip() { - return this.currentUser.isLoggedIn === false; + return !this.currentUser || this.currentUser.isLoggedIn === false; }, }, }, diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue index 31e4fe785..5ac44b715 100755 --- a/js/src/views/Event/Event.vue +++ b/js/src/views/Event/Event.vue @@ -592,6 +592,7 @@ import { eventMetaDataList } from "../../services/EventMetadata"; }, skip() { return ( + !this.currentActor.id || !this.event?.attributedTo || !this.event?.attributedTo?.preferredUsername ); diff --git a/js/src/views/Home.vue b/js/src/views/Home.vue index fe2110ff9..3aca6994d 100644 --- a/js/src/views/Home.vue +++ b/js/src/views/Home.vue @@ -372,7 +372,9 @@ import Subtitle from "../components/Utils/Subtitle.vue"; currentUser: CURRENT_USER_CLIENT, loggedUser: { query: USER_SETTINGS, - fetchPolicy: "no-cache", + skip() { + return !this.currentUser || this.currentUser.isLoggedIn === false; + }, error() { return null; }, From e781fd5b495e956191d2c2a390af1179bb352e2e Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Fri, 13 Aug 2021 17:00:21 +0200 Subject: [PATCH 3/4] Fix search on 404 page Signed-off-by: Thomas Citharel --- js/src/views/PageNotFound.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/views/PageNotFound.vue b/js/src/views/PageNotFound.vue index dc0412ad7..27fab110b 100644 --- a/js/src/views/PageNotFound.vue +++ b/js/src/views/PageNotFound.vue @@ -38,7 +38,7 @@ }}

-
+ Date: Fri, 13 Aug 2021 17:47:26 +0200 Subject: [PATCH 4/4] Fix session issues Close #809 Signed-off-by: Thomas Citharel --- js/src/apollo/utils.ts | 6 ++++++ js/src/types/apollo.ts | 10 --------- js/src/utils/auth.ts | 17 ++++++++------- js/src/vue-apollo.ts | 47 +++++++++++++++++++++++++++++++++++------- 4 files changed, 56 insertions(+), 24 deletions(-) delete mode 100644 js/src/types/apollo.ts diff --git a/js/src/apollo/utils.ts b/js/src/apollo/utils.ts index d47680ba5..84ba969e9 100644 --- a/js/src/apollo/utils.ts +++ b/js/src/apollo/utils.ts @@ -104,6 +104,11 @@ export async function refreshAccessToken( const refreshToken = localStorage.getItem(AUTH_REFRESH_TOKEN); + if (!refreshToken) { + console.debug("Refresh token not found"); + return false; + } + console.log("Refreshing access token."); try { @@ -118,6 +123,7 @@ export async function refreshAccessToken( return true; } catch (err) { + console.debug("Failed to refresh token"); return false; } } diff --git a/js/src/types/apollo.ts b/js/src/types/apollo.ts deleted file mode 100644 index da8b84b34..000000000 --- a/js/src/types/apollo.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ServerParseError } from "@apollo/client/link/http"; -import { ServerError } from "@apollo/client/link/utils"; - -function isServerError( - err: Error | ServerError | ServerParseError | undefined -): err is ServerError { - return !!err && (err as ServerError).statusCode !== undefined; -} - -export { isServerError }; diff --git a/js/src/utils/auth.ts b/js/src/utils/auth.ts index 2feb49244..4c61a87a5 100644 --- a/js/src/utils/auth.ts +++ b/js/src/utils/auth.ts @@ -95,14 +95,17 @@ export async function initializeCurrentActor( } export async function logout( - apollo: ApolloClient + apollo: ApolloClient, + performServerLogout = true ): Promise { - await apollo.mutate({ - mutation: LOGOUT, - variables: { - refreshToken: localStorage.getItem(AUTH_REFRESH_TOKEN), - }, - }); + if (performServerLogout) { + await apollo.mutate({ + mutation: LOGOUT, + variables: { + refreshToken: localStorage.getItem(AUTH_REFRESH_TOKEN), + }, + }); + } await apollo.mutate({ mutation: UPDATE_CURRENT_USER_CLIENT, diff --git a/js/src/vue-apollo.ts b/js/src/vue-apollo.ts index 9b1a7714c..abfa694f6 100644 --- a/js/src/vue-apollo.ts +++ b/js/src/vue-apollo.ts @@ -11,8 +11,8 @@ import { NormalizedCacheObject, split, } from "@apollo/client/core"; +import { RetryLink } from "@apollo/client/link/retry"; import buildCurrentUserResolver from "@/apollo/user"; -import { isServerError } from "@/types/apollo"; import { AUTH_ACCESS_TOKEN } from "@/constants"; import { logout } from "@/utils/auth"; import { Socket as PhoenixSocket } from "phoenix"; @@ -61,9 +61,17 @@ const authMiddleware = new ApolloLink((operation, forward) => { return null; }); +const customFetch = async (uri: string, options: any) => { + const response = await fetch(uri, options); + if (response.status >= 400) { + return Promise.reject(response.status); + } + return response; +}; + const uploadLink = createLink({ uri: httpEndpoint, - fetch, + fetch: customFetch, }); const phoenixSocket = new PhoenixSocket(wsEndpoint, { @@ -97,17 +105,35 @@ const resolvePendingRequests = () => { pendingRequests = []; }; +const isAuthError = (graphQLError: GraphQLError | undefined) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return graphQLError && [403, 401].includes(graphQLError.status_code); +}; + const errorLink = onError( ({ graphQLErrors, networkError, forward, operation }) => { - if (isServerError(networkError) && networkError?.statusCode === 401) { + console.debug("We have an apollo error", [graphQLErrors, networkError]); + if ( + graphQLErrors?.some((graphQLError) => isAuthError(graphQLError)) || + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + networkError === 401 + ) { + console.debug("It's a authorization error (statusCode 401)"); let forwardOperation; if (!isRefreshing) { + console.debug("Setting isRefreshing to true"); isRefreshing = true; forwardOperation = fromPromise( refreshAccessToken(apolloClient) - .then(() => { + .then((res) => { + if (res !== true) { + // failed to refresh the token + throw "Failed to refresh the token"; + } resolvePendingRequests(); const context = operation.getContext(); @@ -121,9 +147,11 @@ const errorLink = onError( }); return true; }) - .catch(() => { + .catch((e) => { + console.debug("Something failed, let's logout", e); pendingRequests = []; - logout(apolloClient); + // don't perform a logout since we don't have any working access/refresh tokens + logout(apolloClient, false); return; }) .finally(() => { @@ -161,7 +189,12 @@ const errorLink = onError( } ); -const fullLink = authMiddleware.concat(errorLink).concat(link); +const retryLink = new RetryLink(); + +const fullLink = authMiddleware + .concat(retryLink) + .concat(errorLink) + .concat(link); const cache = new InMemoryCache({ addTypename: true,