diff --git a/warpgate-web/src/admin/CreateRole.svelte b/warpgate-web/src/admin/CreateRole.svelte index 36d5c2a7d..c974bd7d1 100644 --- a/warpgate-web/src/admin/CreateRole.svelte +++ b/warpgate-web/src/admin/CreateRole.svelte @@ -3,8 +3,9 @@ import { api } from 'admin/lib/api' import AsyncButton from 'common/AsyncButton.svelte' import { replace } from 'svelte-spa-router' import { Alert, FormGroup } from '@sveltestrap/sveltestrap' +import { stringifyError } from 'common/errors' -let error: Error|null = null +let error: string|null = null let name = '' async function create () { @@ -19,7 +20,7 @@ async function create () { }) replace(`/roles/${role.id}`) } catch (err) { - error = err as Error + error = await stringifyError(err) } } diff --git a/warpgate-web/src/admin/CreateTarget.svelte b/warpgate-web/src/admin/CreateTarget.svelte index 7c01e5887..fe5827ccd 100644 --- a/warpgate-web/src/admin/CreateTarget.svelte +++ b/warpgate-web/src/admin/CreateTarget.svelte @@ -3,8 +3,9 @@ import { api, type TargetOptions, TlsMode } from 'admin/lib/api' import AsyncButton from 'common/AsyncButton.svelte' import { replace } from 'svelte-spa-router' import { Alert, FormGroup } from '@sveltestrap/sveltestrap' +import { stringifyError } from 'common/errors' -let error: Error|null = null +let error: string|null = null let name = '' let type: 'Http' | 'MySql' | 'Ssh' | 'Postgres' = 'Ssh' @@ -65,7 +66,7 @@ async function create () { }) replace(`/targets/${target.id}`) } catch (err) { - error = err as Error + error = await stringifyError(err) } } diff --git a/warpgate-web/src/admin/CreateTicket.svelte b/warpgate-web/src/admin/CreateTicket.svelte index 2e6e9e926..2b1c364f3 100644 --- a/warpgate-web/src/admin/CreateTicket.svelte +++ b/warpgate-web/src/admin/CreateTicket.svelte @@ -6,8 +6,9 @@ import { TargetKind } from 'gateway/lib/api' import { link } from 'svelte-spa-router' import { Alert, FormGroup } from '@sveltestrap/sveltestrap' import { firstBy } from 'thenby' +import { stringifyError } from 'common/errors' -let error: Error|null = null +let error: string|null = null let targets: Target[]|undefined let users: User[]|undefined let selectedTarget: Target|undefined @@ -26,8 +27,8 @@ async function load () { users.sort(firstBy('username')) } -load().catch(e => { - error = e +load().catch(async e => { + error = await stringifyError(e) }) async function create () { @@ -44,7 +45,7 @@ async function create () { }, }) } catch (err) { - error = err as Error + error = await stringifyError(err) } } diff --git a/warpgate-web/src/admin/CreateUser.svelte b/warpgate-web/src/admin/CreateUser.svelte index 492569a7c..0d8bd8bd3 100644 --- a/warpgate-web/src/admin/CreateUser.svelte +++ b/warpgate-web/src/admin/CreateUser.svelte @@ -3,8 +3,9 @@ import { api } from 'admin/lib/api' import AsyncButton from 'common/AsyncButton.svelte' import { replace } from 'svelte-spa-router' import { Alert, FormGroup } from '@sveltestrap/sveltestrap' +import { stringifyError } from 'common/errors' -let error: Error|null = null +let error: string|null = null let username = '' async function create () { @@ -21,7 +22,7 @@ async function create () { }) replace(`/users/${user.id}`) } catch (err) { - error = err as Error + error = await stringifyError(err) } } diff --git a/warpgate-web/src/admin/LogViewer.svelte b/warpgate-web/src/admin/LogViewer.svelte index c3a55e634..2c48265c5 100644 --- a/warpgate-web/src/admin/LogViewer.svelte +++ b/warpgate-web/src/admin/LogViewer.svelte @@ -5,12 +5,13 @@ import { firstBy } from 'thenby' import IntersectionObserver from 'svelte-intersection-observer' import { link } from 'svelte-spa-router' import { onDestroy, onMount } from 'svelte' +import { stringifyError } from 'common/errors' export let filters: { sessionId?: string, } | undefined -let error: Error|undefined +let error: string|null = null let items: LogEntry[]|undefined let visibleItems: LogEntry[]|undefined let loading = true @@ -92,8 +93,8 @@ function stringifyDate (date: Date) { return date.toLocaleString() } -loadOlder().catch(e => { - error = e +loadOlder().catch(async e => { + error = await stringifyError(e) }) onMount(() => { diff --git a/warpgate-web/src/admin/Recording.svelte b/warpgate-web/src/admin/Recording.svelte index bb6f79a71..dbe8d6cf5 100644 --- a/warpgate-web/src/admin/Recording.svelte +++ b/warpgate-web/src/admin/Recording.svelte @@ -3,10 +3,11 @@ import { api, type Recording } from 'admin/lib/api' import { Alert } from '@sveltestrap/sveltestrap' import TerminalRecordingPlayer from 'admin/player/TerminalRecordingPlayer.svelte' import DelayedSpinner from 'common/DelayedSpinner.svelte' +import { stringifyError } from 'common/errors' export let params = { id: '' } -let error: Error|null = null +let error: string|null = null let recording: Recording|null = null async function load () { @@ -17,8 +18,8 @@ function getTCPDumpURL () { return `/@warpgate/api/recordings/${recording?.id}/tcpdump` } -load().catch(e => { - error = e +load().catch(async e => { + error = await stringifyError(e) }) diff --git a/warpgate-web/src/admin/Role.svelte b/warpgate-web/src/admin/Role.svelte index fd1da520f..a809c250f 100644 --- a/warpgate-web/src/admin/Role.svelte +++ b/warpgate-web/src/admin/Role.svelte @@ -4,17 +4,18 @@ import AsyncButton from 'common/AsyncButton.svelte' import DelayedSpinner from 'common/DelayedSpinner.svelte' import { replace } from 'svelte-spa-router' import { Alert, FormGroup } from '@sveltestrap/sveltestrap' +import { stringifyError } from 'common/errors' export let params: { id: string } -let error: Error|undefined +let error: string|null = null let role: Role async function load () { try { role = await api.getRole({ id: params.id }) } catch (err) { - error = err as Error + error = await stringifyError(err) } } @@ -25,7 +26,7 @@ async function update () { roleDataRequest: role, }) } catch (err) { - error = err as Error + error = await stringifyError(err) } } diff --git a/warpgate-web/src/admin/SSH.svelte b/warpgate-web/src/admin/SSH.svelte index 7d19f199a..239b3c209 100644 --- a/warpgate-web/src/admin/SSH.svelte +++ b/warpgate-web/src/admin/SSH.svelte @@ -2,8 +2,9 @@ import { api, type SSHKey, type SSHKnownHost } from 'admin/lib/api' import CopyButton from 'common/CopyButton.svelte' import { Alert } from '@sveltestrap/sveltestrap' +import { stringifyError } from 'common/errors' -let error: Error|undefined +let error: string|undefined let knownHosts: SSHKnownHost[]|undefined let ownKeys: SSHKey[]|undefined @@ -12,8 +13,8 @@ async function load () { knownHosts = await api.getSshKnownHosts() } -load().catch(e => { - error = e +load().catch(async e => { + error = await stringifyError(e) }) async function deleteHost (host: SSHKnownHost) { diff --git a/warpgate-web/src/admin/Session.svelte b/warpgate-web/src/admin/Session.svelte index 0b3f66f6f..bfc0887f9 100644 --- a/warpgate-web/src/admin/Session.svelte +++ b/warpgate-web/src/admin/Session.svelte @@ -9,10 +9,11 @@ import { link } from 'svelte-spa-router' import { Alert } from '@sveltestrap/sveltestrap' import LogViewer from './LogViewer.svelte' import RelativeDate from './RelativeDate.svelte' +import { stringifyError } from 'common/errors' export let params = { id: '' } -let error: Error|null = null +let error: string|null = null let session: SessionSnapshot|null = null let recordings: Recording[]|null = null @@ -50,8 +51,8 @@ function getTargetDescription () { } } -load().catch(e => { - error = e +load().catch(async e => { + error = await stringifyError(e) }) const interval = setInterval(load, 1000) diff --git a/warpgate-web/src/admin/Target.svelte b/warpgate-web/src/admin/Target.svelte index 81fbac763..7692f99e2 100644 --- a/warpgate-web/src/admin/Target.svelte +++ b/warpgate-web/src/admin/Target.svelte @@ -10,10 +10,11 @@ import Fa from 'svelte-fa' import { replace } from 'svelte-spa-router' import { Alert, FormGroup, Input } from '@sveltestrap/sveltestrap' import TlsConfiguration from './TlsConfiguration.svelte' +import { stringifyError } from 'common/errors' export let params: { id: string } -let error: Error|undefined +let error: string|undefined let selectedUser: User|undefined let target: Target let allRoles: Role[] = [] @@ -23,7 +24,7 @@ async function load () { try { target = await api.getTarget({ id: params.id }) } catch (err) { - error = err as Error + error = await stringifyError(err) } } @@ -44,7 +45,7 @@ async function update () { targetDataRequest: target, }) } catch (err) { - error = err as Error + error = await stringifyError(err) } } diff --git a/warpgate-web/src/admin/Tickets.svelte b/warpgate-web/src/admin/Tickets.svelte index b820ce1c6..be6db1b23 100644 --- a/warpgate-web/src/admin/Tickets.svelte +++ b/warpgate-web/src/admin/Tickets.svelte @@ -5,16 +5,17 @@ import { Alert } from '@sveltestrap/sveltestrap' import RelativeDate from './RelativeDate.svelte' import Fa from 'svelte-fa' import { faCalendarXmark, faCalendarCheck, faSquareXmark, faSquareCheck } from '@fortawesome/free-solid-svg-icons' +import { stringifyError } from 'common/errors' -let error: Error|undefined +let error: string|undefined let tickets: Ticket[]|undefined async function load () { tickets = await api.getTickets() } -load().catch(e => { - error = e +load().catch(async e => { + error = await stringifyError(e) }) async function deleteTicket (ticket: Ticket) { diff --git a/warpgate-web/src/admin/User.svelte b/warpgate-web/src/admin/User.svelte index bbf7e52f8..0a50498c1 100644 --- a/warpgate-web/src/admin/User.svelte +++ b/warpgate-web/src/admin/User.svelte @@ -8,10 +8,11 @@ import { replace } from 'svelte-spa-router' import { Alert, Button, FormGroup, Input } from '@sveltestrap/sveltestrap' import AuthPolicyEditor from './AuthPolicyEditor.svelte' import UserCredentialModal from './UserCredentialModal.svelte' +import { stringifyError } from 'common/errors' export let params: { id: string } -let error: Error|undefined +let error: string|null = null let user: User let editingCredential: UserAuthCredential|undefined let policy: UserRequireCredentialsPolicy @@ -42,7 +43,7 @@ async function load () { const allowedRoles = await api.getUserRoles(user) roleIsAllowed = Object.fromEntries(allowedRoles.map(r => [r.id, true])) } catch (err) { - error = err as Error + error = await stringifyError(err) } } @@ -61,7 +62,7 @@ async function update () { userDataRequest: user, }) } catch (err) { - error = err as Error + error = await stringifyError(err) } } diff --git a/warpgate-web/src/admin/lib/api.ts b/warpgate-web/src/admin/lib/api.ts index e218f5177..c616649c5 100644 --- a/warpgate-web/src/admin/lib/api.ts +++ b/warpgate-web/src/admin/lib/api.ts @@ -1,4 +1,4 @@ -import { DefaultApi, Configuration } from './api-client/dist' +import { DefaultApi, Configuration, ResponseError } from './api-client/dist' const configuration = new Configuration({ basePath: '/@warpgate/admin/api', @@ -6,3 +6,7 @@ const configuration = new Configuration({ export const api = new DefaultApi(configuration) export * from './api-client' + +export async function stringifyError (err: ResponseError): Promise { + return `API error: ${await err.response.text()}` +} diff --git a/warpgate-web/src/common/errors.ts b/warpgate-web/src/common/errors.ts new file mode 100644 index 000000000..7e2ef7529 --- /dev/null +++ b/warpgate-web/src/common/errors.ts @@ -0,0 +1,13 @@ +import * as admin from 'admin/lib/api' +import * as gw from 'gateway/lib/api' + +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export async function stringifyError (err: any): Promise { + if (err instanceof gw.ResponseError) { + return gw.stringifyError(err) + } + if (err instanceof admin.ResponseError) { + return admin.stringifyError(err) + } + return err.toString() +} diff --git a/warpgate-web/src/gateway/Login.svelte b/warpgate-web/src/gateway/Login.svelte index a61e1232c..641815c70 100644 --- a/warpgate-web/src/gateway/Login.svelte +++ b/warpgate-web/src/gateway/Login.svelte @@ -10,10 +10,11 @@ import { api, ApiAuthState, LoginFailureResponseFromJSON, type SsoProviderDescri import { reloadServerInfo } from 'gateway/lib/store' import AsyncButton from 'common/AsyncButton.svelte' import DelayedSpinner from 'common/DelayedSpinner.svelte' +import { stringifyError } from 'common/errors' export const params: { stateId?: string } = {} -let error: Error|null = null +let error: string|null = null let username = '' let password = '' let otp = '' @@ -102,10 +103,10 @@ async function _login () { continueWithState() } else { - error = new Error(await err.response.text()) + error = await err.response.text() } } else { - error = err as Error + error = await stringifyError(err) } } } @@ -127,7 +128,8 @@ async function startSSO (provider: SsoProviderDescription) { try { const p = await api.startSso({ name: provider.name, next: nextURL }) location.href = p.url - } catch { + } catch (err) { + error = await stringifyError(err) busy = false } } diff --git a/warpgate-web/src/gateway/lib/api.ts b/warpgate-web/src/gateway/lib/api.ts index d2ae9c871..812dcd246 100644 --- a/warpgate-web/src/gateway/lib/api.ts +++ b/warpgate-web/src/gateway/lib/api.ts @@ -1,4 +1,4 @@ -import { DefaultApi, Configuration } from './api-client' +import { DefaultApi, Configuration, ResponseError } from './api-client' const configuration = new Configuration({ basePath: '/@warpgate/api', @@ -6,3 +6,7 @@ const configuration = new Configuration({ export const api = new DefaultApi(configuration) export * from './api-client' + +export async function stringifyError (err: ResponseError): Promise { + return `API error: ${await err.response.text()}` +}