feat: show generic error message for API response 40x error (#816)

* feat: add generic error for API response 40X

Signed-off-by: Andy Lee <andy.lee@suse.com>

* refactor: fallback error msg

Signed-off-by: Andy Lee <andy.lee@suse.com>

* refactor: update error msg

Signed-off-by: Andy Lee <andy.lee@suse.com>

* refactor: based on comment

Signed-off-by: Andy Lee <andy.lee@suse.com>

---------

Signed-off-by: Andy Lee <andy.lee@suse.com>
This commit is contained in:
Andy Lee 2026-04-21 17:55:30 +08:00 committed by GitHub
parent 9ce95daf76
commit 7d0f33f31d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 36 additions and 3 deletions

View File

@ -8,6 +8,7 @@ import FileSelector, { createOnSelected } from '@shell/components/form/FileSelec
import { randomStr } from '@shell/utils/string'; import { randomStr } from '@shell/utils/string';
import CreateEditView from '@shell/mixins/create-edit-view'; import CreateEditView from '@shell/mixins/create-edit-view';
import { getLoginAwareErrors } from '../utils/error';
export default { export default {
name: 'HarvesterEditKeypair', name: 'HarvesterEditKeypair',
@ -63,6 +64,14 @@ export default {
} }
}, },
computed: {
normalizedErrors() {
const message = this.t('harvester.virtualMachine.genericLoginError');
return getLoginAwareErrors(this.errors, message);
}
},
methods: { onKeySelected: createOnSelected('publicKey') }, methods: { onKeySelected: createOnSelected('publicKey') },
}; };
</script> </script>
@ -72,10 +81,9 @@ export default {
:done-route="doneRoute" :done-route="doneRoute"
:resource="value" :resource="value"
:mode="mode" :mode="mode"
:errors="errors" :errors="normalizedErrors"
:apply-hooks="applyHooks" :apply-hooks="applyHooks"
@finish="save" @finish="save"
@error="e=>errors=e"
> >
<div class="header mb-20"> <div class="header mb-20">
<FileSelector <FileSelector

View File

@ -10,6 +10,7 @@ import { _VIEW } from '@shell/config/query-params';
import { NAMESPACE } from '@shell/config/types'; import { NAMESPACE } from '@shell/config/types';
import { HCI } from '../../types'; import { HCI } from '../../types';
import { getLoginAwareErrors } from '../../utils/error';
const _NEW = '_NEW'; const _NEW = '_NEW';
@ -214,7 +215,9 @@ export default {
buttonCb(true); buttonCb(true);
this.cancel(); this.cancel();
} catch (err) { } catch (err) {
this.errors = [err.message]; const message = this.t('harvester.virtualMachine.genericLoginError');
this.errors = getLoginAwareErrors(err, message);
buttonCb(false); buttonCb(false);
} }
}, },

View File

@ -726,6 +726,7 @@ harvester:
other {Start} other {Start}
} Now } Now
createSSHKey: Create a New... createSSHKey: Create a New...
genericLoginError: Authentication failed. Please re-log in and try again.
installAgent: Install guest agent installAgent: Install guest agent
enableUsb: Enable USB Tablet enableUsb: Enable USB Tablet
advancedOptions: advancedOptions:

View File

@ -0,0 +1,21 @@
const AUTH_ERROR_CODES = [401, 403, 404];
export function getLoginAwareErrors(err, message = '') {
const errors = Array.isArray(err) ? err : (err ? [err] : []);
if (!errors.length) {
return [];
}
const generic = message;
if (errors.some((e) => AUTH_ERROR_CODES.includes(e?._status || e?.response?.status))) {
return [generic];
}
const msgs = errors
.map((e) => (typeof e === 'string' ? e : (e?.message || e?._statusText || '')))
.filter(Boolean);
return msgs.length ? msgs : [generic];
}