fix: remove token from local storage if invalid

this required expanding our custom error classes with support for
arbitrary internal api error codes

however it'll only be used for invalid token errors for now (10001)

no plan to assign codes to other existing api errors
at that point it's probably better to redo the whole api infrastructure
This commit is contained in:
Bobby 2022-05-06 21:58:23 +07:00
parent 3f900a1ac5
commit b35f4ae6eb
No known key found for this signature in database
GPG Key ID: 941839794CBF5A09
7 changed files with 64 additions and 44 deletions

View File

@ -21,12 +21,22 @@ module.exports = (error, req, res, next) => {
? error.statusCode
: 500
const json = {}
const description = (isClientError || isServerError)
? error.message
: 'An unexpected error occurred. Try again?'
if (description) {
return res.status(statusCode).json({ success: false, description })
json.description = description
}
if ((isClientError || isServerError) && error.code) {
json.code = error.code
}
if (Object.keys(json).length) {
json.success = false
return res.status(statusCode).json(json)
} else {
return res.status(statusCode).end()
}

View File

@ -49,7 +49,9 @@ self.verify = async (req, res, next) => {
.select('username', 'permission')
.first()
if (!user) throw new ClientError('Invalid token.', { statusCode: 403 })
if (!user) {
throw new ClientError('Invalid token.', { statusCode: 403, code: 10001 })
}
const obj = {
success: true,

View File

@ -3,12 +3,15 @@ class ClientError extends Error {
super(message)
const {
statusCode
statusCode,
code
} = options
this.statusCode = statusCode !== undefined
? statusCode
: 400
this.code = code
}
}

View File

@ -4,6 +4,7 @@ class ServerError extends Error {
const {
statusCode,
code,
logStack
} = options
@ -11,6 +12,8 @@ class ServerError extends Error {
? statusCode
: 500
this.code = code
this.logStack = logStack || false
}
}

View File

@ -86,6 +86,9 @@ page.verify = () => {
// Redirect to dashboard if token is valid
window.location = 'dashboard'
}).catch(error => {
if (error.response.data && error.response.data.code === 10001) {
localStorage.removeItem(lsKeys.token)
}
page.unhide()
page.onAxiosError(error)
})

View File

@ -158,7 +158,7 @@ page.onAxiosError = error => {
}
page.preparePage = () => {
if (page.token) page.verifyToken(page.token, true)
if (page.token) page.verifyToken(page.token)
else window.location = 'auth'
}
@ -182,20 +182,8 @@ page.checkClientVersion = apiVersion => {
}
}
page.verifyToken = (token, reloadOnError) => {
page.verifyToken = token => {
axios.post('api/tokens/verify', { token }).then(response => {
if (response.data.success === false) {
return swal({
title: 'An error occurred!',
text: response.data.description,
icon: 'error'
}).then(() => {
if (!reloadOnError) return
localStorage.removeItem(lsKeys.token)
window.location = 'auth'
})
}
axios.defaults.headers.common.token = token
localStorage[lsKeys.token] = token
@ -207,7 +195,18 @@ page.verifyToken = (token, reloadOnError) => {
page.username = response.data.username
page.permissions = response.data.permissions
page.prepareDashboard()
}).catch(page.onAxiosError)
}).catch(error => {
return swal({
title: 'An error occurred!',
text: error.response.data ? error.response.data.description : error.toString(),
icon: 'error'
}).then(() => {
if (error.response.data && error.response.data.code === 10001) {
localStorage.removeItem(lsKeys.token)
window.location = 'auth'
}
})
})
}
page.prepareDashboard = () => {

View File

@ -81,6 +81,7 @@ page.onInitError = error => {
window.location.reload()
})
if (!error) return
if (error.response) page.onAxiosError(error)
else page.onError(error)
}
@ -189,42 +190,41 @@ page.checkIfPublic = () => {
}
page.preparePage = () => {
if (page.private) {
if (page.token) {
return page.verifyToken(page.token, true)
if (page.token) {
return page.verifyToken(page.token)
} else if (page.private) {
const button = document.querySelector('#loginToUpload')
button.href = 'auth'
button.classList.remove('is-loading')
if (page.enableUserAccounts) {
button.innerText = 'Anonymous upload is disabled.\nLog in or register to upload.'
} else {
const button = document.querySelector('#loginToUpload')
button.href = 'auth'
button.classList.remove('is-loading')
if (page.enableUserAccounts) {
button.innerText = 'Anonymous upload is disabled.\nLog in or register to upload.'
} else {
button.innerText = 'Running in private mode.\nLog in to upload.'
}
button.innerText = 'Running in private mode.\nLog in to upload.'
}
} else {
return page.prepareUpload()
}
}
page.verifyToken = (token, reloadOnError) => {
page.verifyToken = token => {
return axios.post('api/tokens/verify', { token }).then(response => {
if (response.data.success === false) {
return swal({
title: 'An error occurred!',
text: response.data.description,
icon: 'error'
}).then(() => {
if (!reloadOnError) return
localStorage.removeItem('token')
window.location.reload()
})
}
localStorage[lsKeys.token] = token
page.token = token
return page.prepareUpload()
}).catch(page.onInitError)
}).catch(error => {
return swal({
title: 'An error occurred!',
text: error.response.data ? error.response.data.description : error.toString(),
icon: 'error'
}).then(() => {
if (error.response.data && error.response.data.code === 10001) {
localStorage.removeItem(lsKeys.token)
window.location.reload()
} else {
page.onInitError()
}
})
})
}
page.prepareUpload = () => {