Merge branch 'refactor-refreshing-token' into 'master'

Refactor refreshing token

See merge request framasoft/mobilizon!1005
This commit is contained in:
Thomas Citharel 2021-08-03 14:25:51 +00:00
commit d0ac3de354
5 changed files with 63 additions and 87 deletions

View file

@ -129,6 +129,7 @@ import RouteName from "../../router/name";
import { changeIdentity } from "../../utils/auth"; import { changeIdentity } from "../../utils/auth";
import identityEditionMixin from "../../mixins/identityEdition"; import identityEditionMixin from "../../mixins/identityEdition";
import { ApolloCache, FetchResult } from "@apollo/client/core"; import { ApolloCache, FetchResult } from "@apollo/client/core";
import { ActorType } from "@/types/enums";
@Component({ @Component({
apollo: { apollo: {
@ -180,8 +181,18 @@ export default class Register extends mixins(identityEditionMixin) {
}); });
if (identitiesData && localData) { if (identitiesData && localData) {
identitiesData.identities.push(localData.registerPerson); const newPersonData = {
store.writeQuery({ query: IDENTITIES, data: identitiesData }); ...localData.registerPerson,
type: ActorType.PERSON,
};
store.writeQuery({
query: IDENTITIES,
data: {
...identitiesData,
identities: [...identitiesData.identities, newPersonData],
},
});
} }
} }
}, },

View file

@ -1309,29 +1309,6 @@ export default class Event extends EventMixin {
} }
return null; return null;
} }
get shouldShowParticipationButton(): boolean {
// So that people can cancel their participation
if (
this.actorIsParticipant ||
(this.config.anonymous.participation.allowed &&
this.anonymousParticipation)
)
return true;
// You can participate to draft or cancelled events
if (this.event.draft || this.event.status === EventStatus.CANCELLED)
return false;
// Organizer can't participate
if (this.actorIsOrganizer) return false;
// If capacity is OK
if (this.eventCapacityOK) return true;
// Else
return false;
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View file

@ -259,7 +259,7 @@ export default class Login extends Vue {
await initializeCurrentActor(this.$apollo.provider.defaultClient); await initializeCurrentActor(this.$apollo.provider.defaultClient);
} catch (err) { } catch (err) {
if (err instanceof NoIdentitiesException) { if (err instanceof NoIdentitiesException) {
this.$router.push({ await this.$router.push({
name: RouteName.REGISTER_PROFILE, name: RouteName.REGISTER_PROFILE,
params: { params: {
email: this.currentUser.email, email: this.currentUser.email,

View file

@ -6,9 +6,9 @@ import {
ApolloClient, ApolloClient,
ApolloLink, ApolloLink,
defaultDataIdFromObject, defaultDataIdFromObject,
fromPromise,
InMemoryCache, InMemoryCache,
NormalizedCacheObject, NormalizedCacheObject,
Observable,
split, split,
} from "@apollo/client/core"; } from "@apollo/client/core";
import buildCurrentUserResolver from "@/apollo/user"; import buildCurrentUserResolver from "@/apollo/user";
@ -31,8 +31,8 @@ import { GraphQLError } from "graphql";
// Install the vue plugin // Install the vue plugin
Vue.use(VueApollo); Vue.use(VueApollo);
let refreshingTokenPromise: Promise<boolean> | undefined; let isRefreshing = false;
let alreadyRefreshedToken = false; let pendingRequests: any[] = [];
// Endpoints // Endpoints
const httpServer = GRAPHQL_API_ENDPOINT || "http://localhost:4000"; const httpServer = GRAPHQL_API_ENDPOINT || "http://localhost:4000";
@ -92,19 +92,23 @@ const link = split(
uploadLink uploadLink
); );
const resolvePendingRequests = () => {
pendingRequests.map((callback) => callback());
pendingRequests = [];
};
const errorLink = onError( const errorLink = onError(
({ graphQLErrors, networkError, forward, operation }) => { ({ graphQLErrors, networkError, forward, operation }) => {
if ( if (isServerError(networkError) && networkError?.statusCode === 401) {
isServerError(networkError) && let forwardOperation;
networkError?.statusCode === 401 &&
!alreadyRefreshedToken
) {
if (!refreshingTokenPromise)
refreshingTokenPromise = refreshAccessToken(apolloClient);
return promiseToObservable(refreshingTokenPromise).flatMap(() => { if (!isRefreshing) {
refreshingTokenPromise = undefined; isRefreshing = true;
alreadyRefreshedToken = true;
forwardOperation = fromPromise(
refreshAccessToken(apolloClient)
.then(() => {
resolvePendingRequests();
const context = operation.getContext(); const context = operation.getContext();
const oldHeaders = context.headers; const oldHeaders = context.headers;
@ -115,9 +119,28 @@ const errorLink = onError(
authorization: generateTokenHeader(), authorization: generateTokenHeader(),
}, },
}); });
return true;
})
.catch(() => {
pendingRequests = [];
logout(apolloClient);
return;
})
.finally(() => {
isRefreshing = false;
})
).filter((value) => Boolean(value));
} else {
forwardOperation = fromPromise(
new Promise((resolve) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
pendingRequests.push(() => resolve());
})
);
}
return forward(operation); return forwardOperation.flatMap(() => forward(operation));
});
} }
if (graphQLErrors) { if (graphQLErrors) {
@ -171,41 +194,3 @@ export default new VueApollo({
console.error(error); console.error(error);
}, },
}); });
// Thanks: https://github.com/apollographql/apollo-link/issues/747#issuecomment-502676676
const promiseToObservable = <T>(promise: Promise<T>) =>
new Observable<T>((subscriber) => {
promise.then(
(value) => {
if (subscriber.closed) {
return;
}
subscriber.next(value);
subscriber.complete();
},
(err) => {
console.error("Cannot refresh token.", err);
subscriber.error(err);
logout(apolloClient);
}
);
});
// Manually call this when user log in
// export function onLogin(apolloClient) {
// if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
// }
// Manually call this when user log out
// export async function onLogout() {
// if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
// We don't reset store because we rely on currentUser & currentActor
// which are in the cache (even null). Maybe try to rerun cache init after resetStore?
// try {
// await apolloClient.resetStore();
// } catch (e) {
// // eslint-disable-next-line no-console
// console.log('%cError on cache reset (logout)', 'color: orange;', e.message);
// }
// }

View file

@ -215,6 +215,9 @@ defmodule Mobilizon.Service.Auth.LDAPAuthenticator do
:ok -> :ok ->
:ok :ok
{:error, :tls_already_started} ->
:ok
error -> error ->
Logger.error("Could not start TLS: #{inspect(error)}") Logger.error("Could not start TLS: #{inspect(error)}")
end end