feat: implement account email mismatch error handling and improve user feedback in authentication flows

This commit is contained in:
Junyan Qin
2026-01-01 17:01:32 +08:00
parent 61f08f3218
commit 02e12cc1e4
10 changed files with 60 additions and 19 deletions

View File

@@ -48,9 +48,15 @@ function SpaceOAuthCallbackContent() {
setTimeout(() => {
router.push('/home');
}, 1000);
} catch {
} catch (err) {
setStatus('error');
setErrorMessage(t('common.spaceLoginFailed'));
const errorObj = err as { msg?: string };
const errMsg = (errorObj?.msg || '').toLowerCase();
if (errMsg.includes('account email mismatch')) {
setErrorMessage(t('account.spaceEmailMismatch'));
} else {
setErrorMessage(t('common.spaceLoginFailed'));
}
}
},
[router, t],
@@ -74,9 +80,13 @@ function SpaceOAuthCallbackContent() {
}, 1000);
} catch (err) {
setStatus('error');
setErrorMessage(
err instanceof Error ? err.message : t('account.bindSpaceFailed'),
);
const errorObj = err as { msg?: string };
const errMsg = (errorObj?.msg || '').toLowerCase();
if (errMsg.includes('account email mismatch')) {
setErrorMessage(t('account.spaceEmailMismatch'));
} else {
setErrorMessage(t('account.bindSpaceFailed'));
}
} finally {
setIsProcessing(false);
}

View File

@@ -753,7 +753,7 @@ export class BackendClient extends BaseHttpClient {
});
}
public bindSpaceAccount(
public async bindSpaceAccount(
code: string,
state: string,
): Promise<{
@@ -761,7 +761,17 @@ export class BackendClient extends BaseHttpClient {
user: string;
account_type: 'local' | 'space';
}> {
return this.post('/api/v1/user/bind-space', { code, state });
const response = await this.instance.post('/api/v1/user/bind-space', {
code,
state,
});
if (response.data.code !== 0) {
throw {
code: response.data.code,
msg: response.data.msg || 'Unknown error',
};
}
return response.data.data;
}
// ============ Space OAuth API (Redirect Flow) ============
@@ -778,10 +788,19 @@ export class BackendClient extends BaseHttpClient {
return this.get('/api/v1/user/space/authorize-url', params);
}
public exchangeSpaceOAuthCode(code: string): Promise<{
public async exchangeSpaceOAuthCode(code: string): Promise<{
token: string;
user: string;
}> {
return this.post('/api/v1/user/space/callback', { code });
const response = await this.instance.post('/api/v1/user/space/callback', {
code,
});
if (response.data.code !== 0) {
throw {
code: response.data.code,
msg: response.data.msg || 'Unknown error',
};
}
return response.data.data;
}
}

View File

@@ -93,9 +93,7 @@ export abstract class BaseHttpClient {
// 统一错误处理
if (error.response) {
const { status, data } = error.response;
// Backend uses 'msg' field, also check 'message' for compatibility
const errMessage =
(data as { msg?: string })?.msg || data?.message || error.message;
const errMsg = (data as { msg?: string })?.msg || error.message;
switch (status) {
case 401:
@@ -107,23 +105,23 @@ export abstract class BaseHttpClient {
}
break;
case 403:
console.error('Permission denied:', errMessage);
console.error('Permission denied:', errMsg);
break;
case 500:
console.error('Server error:', errMessage);
console.error('Server error:', errMsg);
break;
}
return Promise.reject({
code: data?.code || status,
message: errMessage,
msg: errMsg,
data: data?.data || null,
});
}
return Promise.reject({
code: -1,
message: error.message || 'Network Error',
msg: error.message || 'Network Error',
data: null,
});
},