nuxtjs page render the expressions before nuxtServerInit finish - vue.js

I am using nuxtjs to develop my app, I want the page rendering userinfo if request already had the cookie['token']. I found that the page render the expressions before nuxtServerInit finish.
How can I fix this problem?
store/index.js
export const state = () => ({
user: null,
token: null
});
export const mutations = {
saveUser(state, userValue) {
console.log("store.user.save = " + JSON.stringify(userValue));
state.user = userValue;
},
saveToken(state, token) {
console.log("store.token.save = " + token);
state.token = token;
}
};
export const actions = {
nuxtServerInit({ commit }, app) {
const token = app.$cookies.get("token") && app.$cookies.get("token").indexOf("Bearer ") == 0 ? app.$cookies.get("token") : null;
console.log('nuxtserver init token = ', token)
if (token) {
commit("saveToken", app.$cookies.get("token"));
this.$axios.post("/api/me").then(res => {
commit("saveUser", res.data.data);
});
}
}
};
pages/index.vue
<template>
<div>{{user}}</div>
</template>
<script>
export default {
computed: {
user() {
console.log("computed " + this.$store.state.token)
return this.$store.state.user;
},
},
}
</script>
<style>
</style>
output
nuxtserver init token = Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI0OWYxMjgwZTkxODRjZmMyIiwiZXhwIjoxNjA1NTE2OTAyfQ.ozioLM26fGVO8SfqfZllwp8j6Gy_PWoDsntPzlvXor0 14:25:53
store.token.save = Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI0OWYxMjgwZTkxODRjZmMyIiwiZXhwIjoxNjA1NTE2OTAyfQ.ozioLM26fGVO8SfqfZllwp8j6Gy_PWoDsntPzlvXor0 14:25:53
Making request to /api/me 14:25:53
computed null 14:25:53
store.user.save = {"id":"49f1280e9184cfc2","nickname":"test","avatar":"https://vip1.loli.net/2020/11/15/Eqlr5T7JcmOuDWk.jpg"} 14:25:53

Yes because an axios call is asynchronous. You can use async / await to make it "syncrhonouse"
export const actions = {
async nuxtServerInit({ commit }, app) {
const token = app.$cookies.get("token") && app.$cookies.get("token").indexOf("Bearer ") == 0 ? app.$cookies.get("token") : null;
console.log('nuxtserver init token = ', token)
if (token) {
commit("saveToken", app.$cookies.get("token"));
let {data} = await this.$axios.post("/api/me")
commit("saveUser", data.data);
}
}
};

Related

how to update the refreshToken on page refresh in next-auth?

Summary
I have implemented next-auth to get the accessToken from the provider and pass the same as argument to my mutation, then use the token generated from our backend on consecutive API calls.
The token rotation has been implemented based on the next-auth doc refresh token rotation
Problem
After 1 min (my token expiry time) if the session is untouched/running in background then probably it calls the api and updates with the new refreshToken (works as intended) but when we refresh/reload the page after one minute it signs out of the session.
When I check the terminal, it looks like when I reload the page, the old refreshToken is not getting updated with new refreshToken. It still has the same refreshToken (the one session had before reload) in client but no the issue when we leave the app untouched 😕
Is there any work around for this? Or what am I doing wrong here?
Thanks in advance!
Snippet
here's the pages/api/[..nextauth].tsx
import NextAuth, { NextAuthOptions } from "next-auth"
import { JWT } from "next-auth/jwt"
import GithubProvider from "next-auth/providers/github"
import { Provider, RefreshToken } from "../../../generated/graphql"
const loginQuery = `mutation login($AccessToken: String!, $Provider: Provider!) {
login(accessToken: $AccessToken, provider: $Provider) {
refreshToken
token
tokenExpiry
}
}`
const refreshTokenQuery = `mutation refreshToken($RefreshToken: String!) {
refreshToken(refreshToken: $RefreshToken) {
refreshToken
token
tokenExpiry
}
}`
const authMutation = (query, variables) : Promise<RefreshToken | null> => {
return fetch(process.env.NEXT_PUBLIC_API_URL, {
method: 'POST',
body: JSON.stringify({
query: query,
variables: variables
})
})
.then(res => res.json())
.then(data => {
if (data.errors) {
return null;
} else {
let response = data.data.refreshToken || data.data.login;
if (response.refreshToken === undefined ||
response.tokenExpiry === undefined ||
response.token === undefined) return null
return <RefreshToken> response;
}
})
.catch(error => {
console.log(error);
return null;
});
};
async function login(account, user: any) {
let provider: Provider;
if (account?.provider === 'github') provider = Provider.GitHub
if(provider === undefined) return
const variables = {
AccessToken: account.access_token,
Provider: provider
};
const response = await authMutation(loginQuery, variables)
if (response === null) return
console.log("new refresh token..", response.refreshToken)
return {
accessToken: response.token,
accessTokenExpires: response.tokenExpiry * 1000,
refreshToken: response.refreshToken,
user,
}
}
async function refreshAccessToken(token: any) {
const variables = {
RefreshToken: token.refreshToken,
};
console.log("variables", variables)
const response = await authMutation(refreshTokenQuery, variables)
if (response === null) return
console.log("new refresh token..", response.refreshToken)
return {
...token,
accessToken: response.token,
accessTokenExpires: response.tokenExpiry * 1000,
refreshToken: response.refreshToken,
}
}
export const authOptions: NextAuthOptions = {
providers: [
GithubProvider({
clientId: process.env.NEXT_PUBLIC_GITHUB_OAUTH_CLIENT_ID,
clientSecret: process.env.NEXT_PUBLIC_GITHUB_OAUTH_CLIENT_SECRET,
}),
],
theme: {
colorScheme: "light",
},
callbacks: {
jwt: async ({ account, token, user }: any): Promise<JWT> => {
console.log("current refreshToken", token.refreshToken, token.accessTokenExpires)
// Initial Sign In
if (account && user) {
console.log("initial login", account)
return login(account, user)
}
// Return previous token if the access token has not expired yet
if (Date.now() < token.accessTokenExpires){
console.log("token not expired")
return token
}
// Rotate refresh_token and fetch new access_token if current one is expired
if (token){
console.log("token expired")
return refreshAccessToken(token)
}
},
session: async ({ session, token }: any) => {
if (!session?.user || !token?.accessToken) return
session.accessToken = token.accessToken as string
session.error = token.error as string | undefined
session.user = token.user
return session
},
},
}
export default NextAuth(authOptions)
and this how _app.tsx looks like,
import "../styles/globals.css"
import { SessionProvider as NextSessionProvider } from "next-auth/react"
import UrqlProvider from "../lib/provider"
import { AppProps } from "next/app"
function App({ Component, pageProps }: AppProps) {
const { session } = pageProps
return (
<>
<NextSessionProvider session={session}>
<UrqlProvider>
<Component {...pageProps} />
</UrqlProvider>
</NextSessionProvider>
</>
)
}
export default App

Vue JWT token is only attached after refresh

Token is null right after login, It stores only if I refresh the page. It should store just after login without need to reload.
src/stores/index.ts:
const initialUser = JSON.parse(sessionStorage.getItem('Project:token') || '{}');
const useProject = defineStore('project-store', {
state: () => ({
token: initialUser as string | null,
status: initialUser ? { loggedIn: false } : { loggedIn: true },
}),
actions: {
async login(user: User) {
const token = await grantAuth(user);
this.loginSuccess = token;
},
loginSuccess(token: string) {
this.token = token;
this.status.loggedIn = !!token;
},
src/services/entryPoint.js:
import store from '../stores/index';
export default async function entryPoint() {
const getStore = async () => {
if (!store) {
store = await import('../stores/index');
} else {
if (store) {
const { token } = store;
if (token) {
return token;
}
}
}
};
}
src/services/api.js:
import axios from 'axios';
import entryPoint from './entryPoint';
const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_URL });
const entry = entryPoint();
if (entry) {
api.defaults.headers.Authorization = `Bearer ${entry}`;
}
export default api;
src/services/auth.js:
import api from './api';
const requestToken = encodedData => {
return api.post('/projects/login', null, {
headers: {
Authorization: `Basic ${encodedData}`,
},
});
}
const registerToken = data => {
if (data && data.token) {
sessionStorage.setItem('Project:token', JSON.stringify(data.token));
}
};
export const grantAuth = async user => {
const flatData = `${user.username.toUpperCase()}:${user.password}`;
const encodedData = btoa(flatData);
const response = await requestToken(encodedData);
registerToken(response.data);
return response.data ? response.data.token : null;
};
A solution would be to give the command window.location.reload(), however It is not viable for a SPA, It is preferable that the token to be available right after login

How to set authorization header coorectly?

Problem:
In my react native app in order to remove repeated calls I have developed a general POST GET methods in httpClient file. It code is look likes this.
import axios from 'axios';
import AsyncStorage from '#react-native-community/async-storage';
axios.defaults.headers.post['Content-Type'] = 'application/json';
var instance = null;
const setAuthorisationHeder = async () => {
const token = JSON.parse(await AsyncStorage.getItem('auth_data'));
if (token) {
console.log('>>>>>> instance', instance);
Object.assign(instance.headers, {
Authorization: 'Bearer' + token.accessToken,
});
} else {
console.log('>>>>>> instance', instance);
Object.assign(instance.headers, {
Authorization: '',
});
}
};
export const setHeader = () => {
console.log('>>>>>>>> HIIII');
instance = axios.create({
baseURL: '',
timeout: 150000,
headers: {
'Content-Type': 'application/json',
},
});
instance.interceptors.response.use(
function (response) {
return response;
},
async function (error) {
if (error.response.status) {
if (error.response.status === 401) {
AsyncStorage.removeItem('auth_data');
} else {
throw error;
}
} else {
console.log(error);
}
},
);
};
export const Get = (route, data) => {
function getData() {
return instance.get(
route,
data == null ? {data: {}} : {data: JSON.stringify(data)},
);
}
if (instance) {
console.log('>>>>>> HIIIIii');
// setAuthorisationHeder();
return getData();
}
return setHeader().then(getData);
};
export const Post = (route, data) => {
console.log('>>>>>> route', route);
function postData() {
return instance.post(route, JSON.stringify(data));
}
if (instance) {
console.log('>>>>>> HIIIIii');
// setAuthorisationHeder();
// setAuthorisationHeder();
return postData();
}
return setHeader().then(postData);
};
Can some tell me a way to add an authorization header to this instance? My token is storing the Asyncstorage in the middle of some actions so at the beginning called I don't have the token. As my code setHeader is running only one time so I created a method call setAuthorisationHeder() function. But it is giving me can not find property .then error when I am putting a request. Can someone help me to solve this issue? Thank you?
you can define global headers once and use it in every network call.
https://github.com/axios/axios#global-axios-defaults
Create a global auth variable where you'll store the auth data from storage. Before making a request get the auth data and use interceptor to set the bearer token.
let authToken = '';
const getAuthToken = async () => {
// asumming auth token was saved as string
authToken = await AsyncStorage.getItem('auth_data');
};
Interceptor
// request interceptor
axiosInstance.interceptors.request.use(
function (config) {
// Do something before request is sent
config.headers.Authorization = `Bearer ${authToken}`;
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
complete code
import axios from 'axios';
import AsyncStorage from '#react-native-community/async-storage';
let authToken = '';
const axiosInstance = axios.create({
baseURL: '',
timeout: 150000,
headers: {
'Content-Type': 'application/json',
},
});
// request interceptor
axiosInstance.interceptors.request.use(
function (config) {
// Do something before request is sent
config.headers.Authorization = `Bearer ${authToken}`;
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
const getAuthToken = async () => {
// asumming auth token was saved as string
authToken = await AsyncStorage.getItem('auth_data');
};
export const Get = async (route, data = {}) => {
// get and set auth token
await getAuthToken();
// route = /user?id=787878 or /user/787878
return await axiosInstance.get(route);
};
export const Post = async (route, data = {}) => {
await getAuthToken();
return await axiosInstance.post(route, data);
};

How to refresh JWT token using Apollo and GraphQL

So we're creating a React-Native app using Apollo and GraphQL. I'm using JWT based authentication(when user logs in both an activeToken and refreshToken is created), and want to implement a flow where the token gets refreshed automatically when the server notices it's been expired.
The Apollo Docs for Apollo-Link-Error provides a good starting point to catch the error from the ApolloClient:
onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
for (let err of graphQLErrors) {
switch (err.extensions.code) {
case 'UNAUTHENTICATED':
// error code is set to UNAUTHENTICATED
// when AuthenticationError thrown in resolver
// modify the operation context with a new token
const oldHeaders = operation.getContext().headers;
operation.setContext({
headers: {
...oldHeaders,
authorization: getNewToken(),
},
});
// retry the request, returning the new observable
return forward(operation);
}
}
}
})
However, I am really struggling to figure out how to implement getNewToken().
My GraphQL endpoint has the resolver to create new tokens, but I can't call it from Apollo-Link-Error right?
So how do you refresh the token if the Token is created in the GraphQL endpoint that your Apollo Client will connect to?
The example given in the the Apollo Error Link documentation is a good starting point but assumes that the getNewToken() operation is synchronous.
In your case, you have to hit your GraphQL endpoint to retrieve a new access token. This is an asynchronous operation and you have to use the fromPromise utility function from the apollo-link package to transform your Promise to an Observable.
import React from "react";
import { AppRegistry } from 'react-native';
import { onError } from "apollo-link-error";
import { fromPromise, ApolloLink } from "apollo-link";
import { ApolloClient } from "apollo-client";
let apolloClient;
const getNewToken = () => {
return apolloClient.query({ query: GET_TOKEN_QUERY }).then((response) => {
// extract your accessToken from your response data and return it
const { accessToken } = response.data;
return accessToken;
});
};
const errorLink = onError(
({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
for (let err of graphQLErrors) {
switch (err.extensions.code) {
case "UNAUTHENTICATED":
return fromPromise(
getNewToken().catch((error) => {
// Handle token refresh errors e.g clear stored tokens, redirect to login
return;
})
)
.filter((value) => Boolean(value))
.flatMap((accessToken) => {
const oldHeaders = operation.getContext().headers;
// modify the operation context with a new token
operation.setContext({
headers: {
...oldHeaders,
authorization: `Bearer ${accessToken}`,
},
});
// retry the request, returning the new observable
return forward(operation);
});
}
}
}
}
);
apolloClient = new ApolloClient({
link: ApolloLink.from([errorLink, authLink, httpLink]),
});
const App = () => (
<ApolloProvider client={apolloClient}>
<MyRootComponent />
</ApolloProvider>
);
AppRegistry.registerComponent('MyApplication', () => App);
You can stop at the above implementation which worked correctly until two or more requests failed concurrently. So, to handle concurrent requests failure on token expiration, have a look at this post.
Update - Jan 2022
you can see basic React JWT Authentication Setup from: https://github.com/bilguun-zorigt/React-GraphQL-JWT-Authentication-Example
I've also added the safety points to consider when setting up authentication on both the frontend and backend on the Readme section of the repository. (XSS attack, csrf attack etc...)
Original answer - Dec 2021
My solution:
Works with concurrent requests (by using single promise for all requests)
Doesn't wait for error to happen
Used second client for refresh mutation
import { setContext } from '#apollo/client/link/context';
async function getRefreshedAccessTokenPromise() {
try {
const { data } = await apolloClientAuth.mutate({ mutation: REFRESH })
// maybe dispatch result to redux or something
return data.refreshToken.token
} catch (error) {
// logout, show alert or something
return error
}
}
let pendingAccessTokenPromise = null
export function getAccessTokenPromise() {
const authTokenState = reduxStoreMain.getState().authToken
const currentNumericDate = Math.round(Date.now() / 1000)
if (authTokenState && authTokenState.token && authTokenState.payload &&
currentNumericDate + 1 * 60 <= authTokenState.payload.exp) {
//if (currentNumericDate + 3 * 60 >= authTokenState.payload.exp) getRefreshedAccessTokenPromise()
return new Promise(resolve => resolve(authTokenState.token))
}
if (!pendingAccessTokenPromise) pendingAccessTokenPromise = getRefreshedAccessTokenPromise().finally(() => pendingAccessTokenPromise = null)
return pendingAccessTokenPromise
}
export const linkTokenHeader = setContext(async (_, { headers }) => {
const accessToken = await getAccessTokenPromise()
return {
headers: {
...headers,
Authorization: accessToken ? `JWT ${accessToken}` : '',
}
}
})
export const apolloClientMain = new ApolloClient({
link: ApolloLink.from([
linkError,
linkTokenHeader,
linkMain
]),
cache: inMemoryCache
});
If you are using JWT, you should be able to detect when your JWT token is about to expire or if it is already expired.
Therefore, you do not need to make a request that will always fail with 401 unauthorized.
You can simplify the implementation this way:
const REFRESH_TOKEN_LEGROOM = 5 * 60
export function getTokenState(token?: string | null) {
if (!token) {
return { valid: false, needRefresh: true }
}
const decoded = decode(token)
if (!decoded) {
return { valid: false, needRefresh: true }
} else if (decoded.exp && (timestamp() + REFRESH_TOKEN_LEGROOM) > decoded.exp) {
return { valid: true, needRefresh: true }
} else {
return { valid: true, needRefresh: false }
}
}
export let apolloClient : ApolloClient<NormalizedCacheObject>
const refreshAuthToken = async () => {
return apolloClient.mutate({
mutation: gql```
query refreshAuthToken {
refreshAuthToken {
value
}```,
}).then((res) => {
const newAccessToken = res.data?.refreshAuthToken?.value
localStorage.setString('accessToken', newAccessToken);
return newAccessToken
})
}
const apolloHttpLink = createHttpLink({
uri: Config.graphqlUrl
})
const apolloAuthLink = setContext(async (request, { headers }) => {
// set token as refreshToken for refreshing token request
if (request.operationName === 'refreshAuthToken') {
let refreshToken = localStorage.getString("refreshToken")
if (refreshToken) {
return {
headers: {
...headers,
authorization: `Bearer ${refreshToken}`,
}
}
} else {
return { headers }
}
}
let token = localStorage.getString("accessToken")
const tokenState = getTokenState(token)
if (token && tokenState.needRefresh) {
const refreshPromise = refreshAuthToken()
if (tokenState.valid === false) {
token = await refreshPromise
}
}
if (token) {
return {
headers: {
...headers,
authorization: `Bearer ${token}`,
}
}
} else {
return { headers }
}
})
apolloClient = new ApolloClient({
link: apolloAuthLink.concat(apolloHttpLink),
cache: new InMemoryCache()
})
The advantage of this implementation:
If the access token is about to expire (REFRESH_TOKEN_LEGROOM), it will request a refresh token without stopping the current query. Which should be invisible to your user
If the access token is already expired, it will refresh the token and wait for the response to update it. Much faster than waiting for the error back
The disadvantage:
If you make many requests at once, it may request several times a refresh. You can easily protect against it by waiting a global promise for example. But you will have to implement a proper race condition check if you want to guaranty only one refresh.
after checking this topic and some others very good on internet, my code worked with the following solution
ApolloClient,
NormalizedCacheObject,
gql,
createHttpLink,
InMemoryCache,
} from '#apollo/client';
import { setContext } from '#apollo/client/link/context';
import jwt_decode, { JwtPayload } from 'jwt-decode';
import {
getStorageData,
setStorageData,
STORAGE_CONTANTS,
} from '../utils/local';
export function isRefreshNeeded(token?: string | null) {
if (!token) {
return { valid: false, needRefresh: true };
}
const decoded = jwt_decode<JwtPayload>(token);
if (!decoded) {
return { valid: false, needRefresh: true };
}
if (decoded.exp && Date.now() >= decoded.exp * 1000) {
return { valid: false, needRefresh: true };
}
return { valid: true, needRefresh: false };
}
export let client: ApolloClient<NormalizedCacheObject>;
const refreshAuthToken = async () => {
const refreshToken = getStorageData(STORAGE_CONTANTS.REFRESHTOKEN);
const newToken = await client
.mutate({
mutation: gql`
mutation RefreshToken($refreshAccessTokenRefreshToken: String!) {
refreshAccessToken(refreshToken: $refreshAccessTokenRefreshToken) {
accessToken
status
}
}
`,
variables: { refreshAccessTokenRefreshToken: refreshToken },
})
.then(res => {
const newAccessToken = res.data?.refreshAccessToken?.accessToken;
setStorageData(STORAGE_CONTANTS.AUTHTOKEN, newAccessToken, true);
return newAccessToken;
});
return newToken;
};
const apolloHttpLink = createHttpLink({
uri: process.env.REACT_APP_API_URL,
});
const apolloAuthLink = setContext(async (request, { headers }) => {
if (request.operationName !== 'RefreshToken') {
let token = getStorageData(STORAGE_CONTANTS.AUTHTOKEN);
const shouldRefresh = isRefreshNeeded(token);
if (token && shouldRefresh.needRefresh) {
const refreshPromise = await refreshAuthToken();
if (shouldRefresh.valid === false) {
token = await refreshPromise;
}
}
if (token) {
return {
headers: {
...headers,
authorization: `${token}`,
},
};
}
return { headers };
}
return { headers };
});
client = new ApolloClient({
link: apolloAuthLink.concat(apolloHttpLink),
cache: new InMemoryCache(),
});
A much simpler solution is using RetryLink. retryIf supports async operations so one could do something like this:
class GraphQLClient {
constructor() {
const httpLink = new HttpLink({ uri: '<graphql-endpoint>', fetch: fetch })
const authLink = setContext((_, { headers }) => this._getAuthHeaders(headers))
const retryLink = new RetryLink({
delay: { initial: 300, max: Infinity, jitter: false },
attempts: {
max: 3,
retryIf: (error, operation) => this._handleRetry(error, operation)
}})
this.client = new ApolloClient({
link: ApolloLink.from([ authLink, retryLink, httpLink ]),
cache: new InMemoryCache()
})
}
async _handleRetry(error, operation) {
let requiresRetry = false
if (error.statusCode === 401) {
requiresRetry = true
if (!this.refreshingToken) {
this.refreshingToken = true
await this.requestNewAccessToken()
operation.setContext(({ headers = {} }) => this._getAuthHeaders(headers))
this.refreshingToken = false
}
}
return requiresRetry
}
async requestNewAccessToken() {
// get new access token
}
_getAuthHeaders(headers) {
// return headers
}
}

Multiple API providers with nuxt-axios and a plugin for default headers

I have a Nuxt app with many request to the same API, but also i need to make request to different providers apart of my main API and i don't know how to manage the default headers.
This is my working setup create a plugin to add the headers to all the request like this:
plugins/axios.js
export default function({ $axios, store, redirect }) {
$axios.onRequest(config => {
config.headers.common.Authorization = 'token 123';
config.headers.common["Custom-header"] = 'blablabla';
}
}
nuxt.config.js
module.exports = {
plugins: ["#/plugins/axios"],
axios: {
baseURL: process.env.API_URL,
}
}
store.js
async changeKeyVersionOnline({ commit }) {
const response = await this.$axios.get(
`users/1`
);
return response;
},
This works great for the main API but the problem is i need also to make request to other endpoints of third party service provider and of course the headers should be different.
How can i do that, i read about the proxy option of the nuxt-axios package but what i understand is this only changes the request base URL, i cant find how to set different headers to a specific request.
My final solution was based on create some actions in a central store so the axios requests are made trough this actions.
central.js (Where the axios related actions live)
import qs from "qs";
export const state = () => ({
accessToken: "",
clientId: 0
});
export const getters = {
getHeadersWithAuth: state => {
const config = {
headers: {
Authorization: "Bearer " + state.accessToken
}
};
return config;
},
getHeadersWithAuthClient: state => {
const config = {
headers: {
Authorization: "Bearer " + state.accessToken,
Client: state.clientId
}
};
return config;
}
};
export const mutations = {};
export const actions = {
async getWithAuth({ getters }, { path, params }) {
const config = getters.getHeadersWithAuth;
config.params = params;
config.paramsSerializer = function(params) {
return qs.stringify(params, { encode: false });
};
const result = await this.$axios.get(path, config);
return result;
},
async getWithAuthClient({ getters }, { path, params }) {
const config = getters.getHeadersWithAuthClient;
config.params = params;
config.paramsSerializer = function(params) {
return qs.stringify(params, { encode: false });
};
const result = await this.$axios.get(path, config);
return result;
},
async putWithAuthClient({ getters }, { path, body, params }) {
const config = getters.getHeadersWithAuthClient;
config.params = params;
config.paramsSerializer = function(params) {
return qs.stringify(params, { encode: false });
};
const result = await this.$axios.put(path, body, config);
return result;
}
};
test.js Other store which use the custom axios requests
async updateProductDetailsAction({ commit, dispatch, state }, productData) {
const request = {
path: `endpoints/` + productData.id + `/details`,
body: {
length: 123,
name: 'The product name'
},
params: {}
};
const result = await dispatch("auth/putWithAuthClient", request, {
root: true
});
await commit("setProductDetails", productData.id);
return result;
}