diff --git a/mateclaw-server/src/main/java/vip/mate/approval/grant/controller/ApprovalGrantController.java b/mateclaw-server/src/main/java/vip/mate/approval/grant/controller/ApprovalGrantController.java index 5c4f7989..36a99acd 100644 --- a/mateclaw-server/src/main/java/vip/mate/approval/grant/controller/ApprovalGrantController.java +++ b/mateclaw-server/src/main/java/vip/mate/approval/grant/controller/ApprovalGrantController.java @@ -141,7 +141,12 @@ public class ApprovalGrantController { public R> activeSummary( @RequestHeader(value = "X-Workspace-Id", required = false) Long workspaceId) { Long ws = workspaceId != null ? workspaceId : DEFAULT_WORKSPACE_ID; - long count = grantService.countActiveInWorkspace(ws); + // Cast to int: this is a per-workspace grant count, never bigger than a + // few hundred. Returning Long here would be serialized as a JSON string + // by the global Long→String serializer (CLAUDE.md precision convention + // for snowflake ids), but count is not a snowflake — the frontend wants + // a real number for the chip badge and `count > 0` checks. + int count = (int) Math.min(grantService.countActiveInWorkspace(ws), Integer.MAX_VALUE); // hasWorkspaceWide: workspace + tool_name IS NULL — the dangerous one. Long workspaceWide = grantMapper.selectCount( Wrappers.lambdaQuery() diff --git a/mateclaw-server/src/main/java/vip/mate/auth/service/AuthService.java b/mateclaw-server/src/main/java/vip/mate/auth/service/AuthService.java index 6e412854..07ccad95 100644 --- a/mateclaw-server/src/main/java/vip/mate/auth/service/AuthService.java +++ b/mateclaw-server/src/main/java/vip/mate/auth/service/AuthService.java @@ -131,10 +131,16 @@ public class AuthService { public void verifyCurrentUserPassword(Long userId, String rawPassword) { UserEntity user = userMapper.selectById(userId); if (user == null) { - throw new MateClawException("err.auth.user_not_found", "用户不存在"); + // 404: target user no longer exists; surfacing as 401 would mask the cause. + throw new MateClawException("err.auth.user_not_found", 404, "用户不存在"); } if (rawPassword == null || !passwordEncoder.matches(rawPassword, user.getPassword())) { - throw new MateClawException("err.auth.wrong_password", "原密码错误"); + // 403, not 401: 401 would trigger the global http interceptor's + // handleAuthFailure() and log the user out, but this is a step-up + // re-confirmation (token is still valid). Falling through to the + // default 500 looks like a server fault on the client; 403 cleanly + // communicates "valid session, wrong second-factor". + throw new MateClawException("err.auth.wrong_password", 403, "原密码错误"); } } diff --git a/mateclaw-ui/src/i18n/locales/en-US.ts b/mateclaw-ui/src/i18n/locales/en-US.ts index 2b460736..c0ae094f 100644 --- a/mateclaw-ui/src/i18n/locales/en-US.ts +++ b/mateclaw-ui/src/i18n/locales/en-US.ts @@ -13,6 +13,9 @@ export default { create: 'Create', update: 'Update', loading: 'Loading...', + processing: 'Processing...', + success: 'Done', + revoked: 'Revoked', enabled: 'Enabled', disabled: 'Disabled', default: 'Default', diff --git a/mateclaw-ui/src/i18n/locales/zh-CN.ts b/mateclaw-ui/src/i18n/locales/zh-CN.ts index 8cfdf272..91b55e4a 100644 --- a/mateclaw-ui/src/i18n/locales/zh-CN.ts +++ b/mateclaw-ui/src/i18n/locales/zh-CN.ts @@ -13,6 +13,9 @@ export default { create: '创建', update: '更新', loading: '加载中...', + processing: '处理中...', + success: '操作成功', + revoked: '已撤销', enabled: '启用', disabled: '停用', default: '默认', diff --git a/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue b/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue index 354735ba..c7dbd212 100644 --- a/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue +++ b/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue @@ -53,7 +53,7 @@ @click="confirmRevoke(g)"> {{ t('approval.grant.revokeBtn') }} - {{ t('common.revoked') || 'revoked' }} + {{ t('common.revoked') }} @@ -244,7 +244,7 @@ async function submitCreate() { payload.password = form.password } await approvalApi.createGrant(payload) - ElMessage.success(t('common.success') || 'Created') + ElMessage.success(t('common.success')) dialogOpen.value = false await loadGrants() } catch (e: any) { @@ -266,7 +266,7 @@ async function confirmRevoke(g: ApprovalGrant) { } try { await approvalApi.revokeGrant(g.id) - ElMessage.success(t('common.success') || 'Revoked') + ElMessage.success(t('common.success')) await loadGrants() } catch (e: any) { ElMessage.error(e?.message || 'Failed to revoke')