fix(approval): three minor issues surfaced by end-to-end testing

This commit is contained in:
matevip 2026-05-27 14:08:12 +08:00
parent f15b2dced3
commit 2f5e06f286
5 changed files with 23 additions and 6 deletions

View File

@ -141,7 +141,12 @@ public class ApprovalGrantController {
public R<Map<String, Object>> 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 LongString 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.<ApprovalGrant>lambdaQuery()

View File

@ -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, "原密码错误");
}
}

View File

@ -13,6 +13,9 @@ export default {
create: 'Create',
update: 'Update',
loading: 'Loading...',
processing: 'Processing...',
success: 'Done',
revoked: 'Revoked',
enabled: 'Enabled',
disabled: 'Disabled',
default: 'Default',

View File

@ -13,6 +13,9 @@ export default {
create: '创建',
update: '更新',
loading: '加载中...',
processing: '处理中...',
success: '操作成功',
revoked: '已撤销',
enabled: '启用',
disabled: '停用',
default: '默认',

View File

@ -53,7 +53,7 @@
@click="confirmRevoke(g)">
{{ t('approval.grant.revokeBtn') }}
</button>
<span v-else class="muted">{{ t('common.revoked') || 'revoked' }}</span>
<span v-else class="muted">{{ t('common.revoked') }}</span>
</td>
</tr>
</tbody>
@ -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')