diff --git a/front/src/components/audio/ChannelForm.vue b/front/src/components/audio/ChannelForm.vue
index 6849d1861..ae8d3a8a2 100644
--- a/front/src/components/audio/ChannelForm.vue
+++ b/front/src/components/audio/ChannelForm.vue
@@ -95,7 +95,6 @@
diff --git a/front/src/components/auth/Settings.vue b/front/src/components/auth/Settings.vue
index 7b07eb5ce..d58bf2118 100644
--- a/front/src/components/auth/Settings.vue
+++ b/front/src/components/auth/Settings.vue
@@ -109,12 +109,10 @@
- {{ }}
@@ -739,7 +737,7 @@ export default {
// properties that will be used in it
old_password: '',
new_password: '',
- avatar: { ...(this.$store.state.auth.profile.avatar || { uuid: null }) },
+ avatar: { ...(this.$store.state.auth.profile?.avatar ?? { uuid: null }) },
passwordError: '',
password: '',
isLoading: false,
diff --git a/front/src/components/channels/UploadMetadataForm.vue b/front/src/components/channels/UploadMetadataForm.vue
index 17d676d8d..27832d8be 100644
--- a/front/src/components/channels/UploadMetadataForm.vue
+++ b/front/src/components/channels/UploadMetadataForm.vue
@@ -11,7 +11,6 @@
diff --git a/front/src/components/common/AttachmentInput.vue b/front/src/components/common/AttachmentInput.vue
index 64931b990..ffc1e53aa 100644
--- a/front/src/components/common/AttachmentInput.vue
+++ b/front/src/components/common/AttachmentInput.vue
@@ -1,3 +1,93 @@
+
+
-
diff --git a/front/src/init/axios.ts b/front/src/init/axios.ts
index ac6b8cb83..e390e7731 100644
--- a/front/src/init/axios.ts
+++ b/front/src/init/axios.ts
@@ -1,4 +1,4 @@
-import { InitModule } from '~/types'
+import { BackendError, InitModule, RateLimitStatus } from '~/types'
import createAuthRefreshInterceptor from 'axios-auth-refresh'
import axios, { AxiosError } from 'axios'
@@ -28,36 +28,35 @@ export const install: InitModule = ({ store, router }) => {
// Add a response interceptor
axios.interceptors.response.use(function (response) {
return response
- }, async (error) => {
+ }, async (error: BackendError) => {
error.backendErrors = []
- if (store.state.auth.authenticated && !store.state.auth.oauth.accessToken && error.response.status === 401) {
+ if (store.state.auth.authenticated && !store.state.auth.oauth.accessToken && error.response?.status === 401) {
store.commit('auth/authenticated', false)
logger.warn('Received 401 response from API, redirecting to login form', router.currentRoute.value.fullPath)
await router.push({ name: 'login', query: { next: router.currentRoute.value.fullPath } })
}
- if (error.response.status === 404) {
+ if (error.response?.status === 404) {
error.backendErrors.push('Resource not found')
- const message = error.response.data
+ const message = error.response?.data
store.commit('ui/addMessage', {
content: message,
class: 'error'
})
- } else if (error.response.status === 403) {
+ } else if (error.response?.status === 403) {
error.backendErrors.push('Permission denied')
- } else if (error.response.status === 429) {
+ } else if (error.response?.status === 429) {
let message
- const rateLimitStatus = {
- limit: error.response.headers['x-ratelimit-limit'],
- scope: error.response.headers['x-ratelimit-scope'],
- remaining: error.response.headers['x-ratelimit-remaining'],
- duration: error.response.headers['x-ratelimit-duration'],
- availableSeconds: error.response.headers['retry-after'],
- reset: error.response.headers['x-ratelimit-reset'],
- resetSeconds: error.response.headers['x-ratelimit-resetseconds']
+ const rateLimitStatus: RateLimitStatus = {
+ limit: error.response?.headers['x-ratelimit-limit'],
+ scope: error.response?.headers['x-ratelimit-scope'],
+ remaining: error.response?.headers['x-ratelimit-remaining'],
+ duration: error.response?.headers['x-ratelimit-duration'],
+ availableSeconds: parseInt(error.response?.headers['retry-after'] ?? 60),
+ reset: error.response?.headers['x-ratelimit-reset'],
+ resetSeconds: error.response?.headers['x-ratelimit-resetseconds']
}
if (rateLimitStatus.availableSeconds) {
- rateLimitStatus.availableSeconds = parseInt(rateLimitStatus.availableSeconds)
const tryAgain = moment().add(rateLimitStatus.availableSeconds, 's').toNow(true)
message = $pgettext('*/Error/Paragraph', 'You sent too many requests and have been rate limited, please try again in %{ delay }')
message = $gettext(message, { delay: tryAgain })
@@ -71,10 +70,10 @@ export const install: InitModule = ({ store, router }) => {
class: 'error'
})
logger.error('This client is rate-limited!', rateLimitStatus)
- } else if (error.response.status === 500) {
+ } else if (error.response?.status === 500) {
error.backendErrors.push('A server error occurred')
- } else if (error.response.data) {
- if (error.response.data.detail) {
+ } else if (error.response?.data) {
+ if (error.response?.data.detail) {
error.backendErrors.push(error.response.data.detail)
} else {
error.rawPayload = error.response.data
diff --git a/front/src/types.ts b/front/src/types.ts
index 679ba0456..967f0699b 100644
--- a/front/src/types.ts
+++ b/front/src/types.ts
@@ -1,6 +1,7 @@
import type { App } from 'vue'
import type { Store } from 'vuex'
import { Router } from 'vue-router'
+import {AxiosError} from "axios";
declare global {
interface Window {
@@ -47,6 +48,21 @@ export interface APIErrorResponse {
[key: string]: APIErrorResponse | string[]
}
+export interface BackendError extends AxiosError {
+ backendErrors: string[]
+ rawPayload?: object
+}
+
+export interface RateLimitStatus {
+ limit: string
+ scope: string
+ remaining: string
+ duration: string
+ availableSeconds: number
+ reset: string
+ resetSeconds: string
+}
+
// WebSocket stuff
export interface PendingReviewEditsWSEvent {
pending_review_count: number