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 identityEditionMixin from "../../mixins/identityEdition";
import { ApolloCache, FetchResult } from "@apollo/client/core";
import { ActorType } from "@/types/enums";
@Component({
apollo: {
@ -180,8 +181,18 @@ export default class Register extends mixins(identityEditionMixin) {
});
if (identitiesData && localData) {
identitiesData.identities.push(localData.registerPerson);
store.writeQuery({ query: IDENTITIES, data: identitiesData });
const newPersonData = {
...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;
}
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>
<style lang="scss" scoped>

View file

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

View file

@ -6,9 +6,9 @@ import {
ApolloClient,
ApolloLink,
defaultDataIdFromObject,
fromPromise,
InMemoryCache,
NormalizedCacheObject,
Observable,
split,
} from "@apollo/client/core";
import buildCurrentUserResolver from "@/apollo/user";
@ -31,8 +31,8 @@ import { GraphQLError } from "graphql";
// Install the vue plugin
Vue.use(VueApollo);
let refreshingTokenPromise: Promise<boolean> | undefined;
let alreadyRefreshedToken = false;
let isRefreshing = false;
let pendingRequests: any[] = [];
// Endpoints
const httpServer = GRAPHQL_API_ENDPOINT || "http://localhost:4000";
@ -92,32 +92,55 @@ const link = split(
uploadLink
);
const resolvePendingRequests = () => {
pendingRequests.map((callback) => callback());
pendingRequests = [];
};
const errorLink = onError(
({ graphQLErrors, networkError, forward, operation }) => {
if (
isServerError(networkError) &&
networkError?.statusCode === 401 &&
!alreadyRefreshedToken
) {
if (!refreshingTokenPromise)
refreshingTokenPromise = refreshAccessToken(apolloClient);
if (isServerError(networkError) && networkError?.statusCode === 401) {
let forwardOperation;
return promiseToObservable(refreshingTokenPromise).flatMap(() => {
refreshingTokenPromise = undefined;
alreadyRefreshedToken = true;
if (!isRefreshing) {
isRefreshing = true;
const context = operation.getContext();
const oldHeaders = context.headers;
forwardOperation = fromPromise(
refreshAccessToken(apolloClient)
.then(() => {
resolvePendingRequests();
operation.setContext({
headers: {
...oldHeaders,
authorization: generateTokenHeader(),
},
});
const context = operation.getContext();
const oldHeaders = context.headers;
return forward(operation);
});
operation.setContext({
headers: {
...oldHeaders,
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 forwardOperation.flatMap(() => forward(operation));
}
if (graphQLErrors) {
@ -171,41 +194,3 @@ export default new VueApollo({
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
{:error, :tls_already_started} ->
:ok
error ->
Logger.error("Could not start TLS: #{inspect(error)}")
end