Skip to content

Commit

Permalink
Fix constant loading (#316)
Browse files Browse the repository at this point in the history
* Check token validity before any request

* refactor unwrap conditions
  • Loading branch information
zaelgohary authored Jan 28, 2024
1 parent c02c7c8 commit 2bbfa7f
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 38 deletions.
15 changes: 7 additions & 8 deletions client/src/clients/api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@ export class AuthApi extends ApiClientBase {
}

async refresh(input: Api.Inputs.Refresh) {
ApiClientBase.assertUser()
const res = await this.unwrap(
this.$http.post<Api.Returns.Refresh>(this.getUrl('/token/refresh/'), input)
)

ApiClientBase.refresh()

return res
try {
const res = await this.$http.post<Api.Returns.Refresh>(this.getUrl('/token/refresh'), input)
ApiClientBase.refresh(res.data)
return true
} catch (error) {
return false
}
}

async changePassword(input: Api.Inputs.ChangePassword) {
Expand Down
47 changes: 20 additions & 27 deletions client/src/clients/api/base.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { AxiosError, AxiosInstance, AxiosResponse } from 'axios'

import { panic, resolve } from '@/utils'
import { isValidToken, panic, resolve } from '@/utils'
import type { Api } from '@/types'
import type { NotifierService } from 'vue3-notifier'
import type { ApiClient } from './index'
import { useStorage } from '@vueuse/core'
import { useState } from '@/store'
import { capitalize } from 'vue'
import { useRouter } from 'vue-router'

export abstract class ApiClientBase {
public static $api: ApiClient
Expand All @@ -27,6 +28,7 @@ export abstract class ApiClientBase {
this.$http = options.$http
}

protected static $router = useRouter()
protected static login(user: Api.LoginUser) {
ApiClientBase.USER = user
const state = useState()
Expand All @@ -37,14 +39,12 @@ export abstract class ApiClientBase {
useStorage('refresh_token', refresh_token.value, localStorage, { mergeDefaults: true })
}

protected static refresh() {
const state = useState()
const {access_token, refresh_token } = state;
ApiClientBase.assertUser()
protected static refresh(res: Api.Returns.Refresh) {
this.assertUser()
ApiClientBase.USER = {
...ApiClientBase.USER!,
access_token: access_token.value,
refresh_token: refresh_token.value
access_token: res.access,
refresh_token: res.refresh
}
}

Expand Down Expand Up @@ -87,28 +87,9 @@ export abstract class ApiClientBase {
const refresh_token = localStorage.getItem("refresh_token")

// check if error indicate the token needs to be refreshed
if (
err &&
err.response.status == 401 &&
err.response.data.code == 'token_not_valid' &&
ApiClientBase.USER &&
refresh_token !== null
) {
if (access_token && refresh_token && !isValidToken(access_token) && isValidToken(refresh_token)) {
await ApiClientBase.$api.auth.refresh({ refresh: refresh_token })
}
if (err && !ApiClientBase.USER && access_token !== null && refresh_token !== null) {
const user = await ApiClientBase.$api.myprofile.getUser();
ApiClientBase.USER = {...user, access_token, refresh_token}
}

if (err) {
ApiClientBase.$notifier?.notify({
type: 'error',
description: options.normalizeError?.(err, res) ?? ApiClientBase.normalizeError(err) ?? err
})

panic(err)
}

if (
(res.config.method === 'post' || res.config.method === 'put') &&
Expand All @@ -121,6 +102,18 @@ export abstract class ApiClientBase {
})
}

if (err) {
ApiClientBase.$notifier?.notify({
type: 'error',
description: options.normalizeError?.(err, res) ?? ApiClientBase.normalizeError(err) ?? err
})
if (err.response.status == 401) {
ApiClientBase.$router.push('/login')
}
panic(err)
}


return (options.transform?.(res.data, res) ?? res.data) as R
}
}
3 changes: 2 additions & 1 deletion client/src/hooks/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useState } from '@/store'
import { isValidToken } from '@/utils'
import { type App, inject, computed } from 'vue'

export const $globals_key = Symbol('key:$globals')
const state = useState()

export const isAuthenticated = computed(() => {
return state.access_token.value ? true : false
return state.access_token.value && isValidToken(state.access_token.value) ? true : false
})

export const isAdmin = computed(() => {
Expand Down
5 changes: 3 additions & 2 deletions client/src/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export function decodeAccessToken(token: string): JWTokenObject {
return JSON.parse(jsonPayload);
}

export function isValidToken(token: string): boolean{
return Date.now() >= decodeAccessToken(token).exp * 1000
export function isValidToken(token: string): boolean {
const decodedToken = decodeAccessToken(token);
return Date.now() < decodedToken.exp * 1000;
}

0 comments on commit 2bbfa7f

Please sign in to comment.