Merge branch 'session-issues' into 'master'

Various issues

Closes #809

See merge request framasoft/mobilizon!1030
This commit is contained in:
Thomas Citharel 2021-08-13 17:17:59 +00:00
commit b4d1252ece
9 changed files with 63 additions and 28 deletions

View File

@ -104,6 +104,11 @@ export async function refreshAccessToken(
const refreshToken = localStorage.getItem(AUTH_REFRESH_TOKEN); const refreshToken = localStorage.getItem(AUTH_REFRESH_TOKEN);
if (!refreshToken) {
console.debug("Refresh token not found");
return false;
}
console.log("Refreshing access token."); console.log("Refreshing access token.");
try { try {
@ -118,6 +123,7 @@ export async function refreshAccessToken(
return true; return true;
} catch (err) { } catch (err) {
console.debug("Failed to refresh token");
return false; return false;
} }
} }

View File

@ -15,7 +15,7 @@ import LazyImageWrapper from "../Image/LazyImageWrapper.vue";
}, },
}) })
export default class EventBanner extends Vue { export default class EventBanner extends Vue {
@Prop({ required: true, default: null, type: Object as PropType<IMedia> }) @Prop({ default: null, type: Object as PropType<IMedia> })
picture!: IMedia | null; picture!: IMedia | null;
} }
</script> </script>

View File

@ -216,7 +216,7 @@ import RouteName from "../router/name";
loggedUser: { loggedUser: {
query: USER_SETTINGS, query: USER_SETTINGS,
skip() { skip() {
return this.currentUser.isLoggedIn === false; return !this.currentUser || this.currentUser.isLoggedIn === false;
}, },
}, },
}, },

View File

@ -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 };

View File

@ -95,14 +95,17 @@ export async function initializeCurrentActor(
} }
export async function logout( export async function logout(
apollo: ApolloClient<NormalizedCacheObject> apollo: ApolloClient<NormalizedCacheObject>,
performServerLogout = true
): Promise<void> { ): Promise<void> {
await apollo.mutate({ if (performServerLogout) {
mutation: LOGOUT, await apollo.mutate({
variables: { mutation: LOGOUT,
refreshToken: localStorage.getItem(AUTH_REFRESH_TOKEN), variables: {
}, refreshToken: localStorage.getItem(AUTH_REFRESH_TOKEN),
}); },
});
}
await apollo.mutate({ await apollo.mutate({
mutation: UPDATE_CURRENT_USER_CLIENT, mutation: UPDATE_CURRENT_USER_CLIENT,

View File

@ -592,6 +592,7 @@ import { eventMetaDataList } from "../../services/EventMetadata";
}, },
skip() { skip() {
return ( return (
!this.currentActor.id ||
!this.event?.attributedTo || !this.event?.attributedTo ||
!this.event?.attributedTo?.preferredUsername !this.event?.attributedTo?.preferredUsername
); );

View File

@ -372,7 +372,9 @@ import Subtitle from "../components/Utils/Subtitle.vue";
currentUser: CURRENT_USER_CLIENT, currentUser: CURRENT_USER_CLIENT,
loggedUser: { loggedUser: {
query: USER_SETTINGS, query: USER_SETTINGS,
fetchPolicy: "no-cache", skip() {
return !this.currentUser || this.currentUser.isLoggedIn === false;
},
error() { error() {
return null; return null;
}, },

View File

@ -38,7 +38,7 @@
}} }}
</p> </p>
<!-- The following should just be replaced with the SearchField component but it fails for some reason --> <!-- The following should just be replaced with the SearchField component but it fails for some reason -->
<form @submit="enter"> <form @submit.prevent="enter">
<b-field class="search"> <b-field class="search">
<b-input <b-input
expanded expanded

View File

@ -11,8 +11,8 @@ import {
NormalizedCacheObject, NormalizedCacheObject,
split, split,
} from "@apollo/client/core"; } from "@apollo/client/core";
import { RetryLink } from "@apollo/client/link/retry";
import buildCurrentUserResolver from "@/apollo/user"; import buildCurrentUserResolver from "@/apollo/user";
import { isServerError } from "@/types/apollo";
import { AUTH_ACCESS_TOKEN } from "@/constants"; import { AUTH_ACCESS_TOKEN } from "@/constants";
import { logout } from "@/utils/auth"; import { logout } from "@/utils/auth";
import { Socket as PhoenixSocket } from "phoenix"; import { Socket as PhoenixSocket } from "phoenix";
@ -61,9 +61,17 @@ const authMiddleware = new ApolloLink((operation, forward) => {
return null; 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({ const uploadLink = createLink({
uri: httpEndpoint, uri: httpEndpoint,
fetch, fetch: customFetch,
}); });
const phoenixSocket = new PhoenixSocket(wsEndpoint, { const phoenixSocket = new PhoenixSocket(wsEndpoint, {
@ -97,17 +105,35 @@ const resolvePendingRequests = () => {
pendingRequests = []; 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( const errorLink = onError(
({ graphQLErrors, networkError, forward, operation }) => { ({ 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; let forwardOperation;
if (!isRefreshing) { if (!isRefreshing) {
console.debug("Setting isRefreshing to true");
isRefreshing = true; isRefreshing = true;
forwardOperation = fromPromise( forwardOperation = fromPromise(
refreshAccessToken(apolloClient) refreshAccessToken(apolloClient)
.then(() => { .then((res) => {
if (res !== true) {
// failed to refresh the token
throw "Failed to refresh the token";
}
resolvePendingRequests(); resolvePendingRequests();
const context = operation.getContext(); const context = operation.getContext();
@ -121,9 +147,11 @@ const errorLink = onError(
}); });
return true; return true;
}) })
.catch(() => { .catch((e) => {
console.debug("Something failed, let's logout", e);
pendingRequests = []; pendingRequests = [];
logout(apolloClient); // don't perform a logout since we don't have any working access/refresh tokens
logout(apolloClient, false);
return; return;
}) })
.finally(() => { .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({ const cache = new InMemoryCache({
addTypename: true, addTypename: true,