diff --git a/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/UserFreightRestController.java b/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/UserFreightRestController.java index dad72527..fd1296ad 100644 --- a/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/UserFreightRestController.java +++ b/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/UserFreightRestController.java @@ -5,8 +5,11 @@ import com.alibaba.excel.EasyExcel; import com.red.circle.console.app.dto.clienobject.user.UserFreightBalanceCO; import com.red.circle.console.app.dto.clienobject.user.UserFreightBalanceRunningWaterCO; import com.red.circle.console.app.excel.model.freight.UserFreightBalanceRunningWaterExportModel; +import com.red.circle.console.app.service.admin.UserAccountService; import com.red.circle.console.app.service.app.user.UserFreightService; import com.red.circle.console.infra.annotations.OpsOperationReqLog; +import com.red.circle.console.inner.error.ConsoleErrorCode; +import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.web.controller.BaseController; import com.red.circle.other.inner.model.cmd.user.UserFreightBalanceCmd; @@ -42,8 +45,10 @@ import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor public class UserFreightRestController extends BaseController { + private static final String FREIGHT_SHIP_MENU_ALIAS = "user:freight:ship"; private final UserFreightService userFreightService; + private final UserAccountService userAccountService; /** * 获取代理账户信息-分页列表. @@ -59,7 +64,11 @@ public class UserFreightRestController extends BaseController { @OpsOperationReqLog("货运代理-发货") @PostMapping("/ship") public void ship(@RequestBody @Validated UserFreightBalanceCmd param) { - param.setOperationUser(param.requiredReqUserId()); + Long reqUserId = param.requiredReqUserId(); + // 发货会直接增加币商余额,不能只依赖前端隐藏按钮,接口层必须再次校验显式按钮权限。 + ResponseAssert.isTrue(ConsoleErrorCode.ACCOUNT_NOT_PERMISSIONS, + userAccountService.hasButtonsAlias(reqUserId.intValue(), FREIGHT_SHIP_MENU_ALIAS)); + param.setOperationUser(reqUserId); userFreightService.ship(param); } diff --git a/rc-service/rc-service-console/console-adapter/src/test/java/com/red/circle/console/adapter/app/user/UserFreightRestControllerTest.java b/rc-service/rc-service-console/console-adapter/src/test/java/com/red/circle/console/adapter/app/user/UserFreightRestControllerTest.java new file mode 100644 index 00000000..e55876e4 --- /dev/null +++ b/rc-service/rc-service-console/console-adapter/src/test/java/com/red/circle/console/adapter/app/user/UserFreightRestControllerTest.java @@ -0,0 +1,56 @@ +package com.red.circle.console.adapter.app.user; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.red.circle.console.app.service.admin.UserAccountService; +import com.red.circle.console.app.service.app.user.UserFreightService; +import com.red.circle.other.inner.model.cmd.user.UserFreightBalanceCmd; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class UserFreightRestControllerTest { + + private static final Long ADMIN_USER_ID = 227L; + private static final String FREIGHT_SHIP_MENU_ALIAS = "user:freight:ship"; + + private UserFreightService userFreightService; + private UserAccountService userAccountService; + private UserFreightRestController controller; + + @BeforeEach + void setUp() { + userFreightService = Mockito.mock(UserFreightService.class); + userAccountService = Mockito.mock(UserAccountService.class); + controller = new UserFreightRestController(userFreightService, userAccountService); + } + + @Test + void shipAllowsUserWithExplicitPermission() { + UserFreightBalanceCmd cmd = new UserFreightBalanceCmd(); + cmd.setReqUserId(ADMIN_USER_ID); + when(userAccountService.hasButtonsAlias(ADMIN_USER_ID.intValue(), FREIGHT_SHIP_MENU_ALIAS)) + .thenReturn(true); + + controller.ship(cmd); + + verify(userFreightService).ship(cmd); + org.assertj.core.api.Assertions.assertThat(cmd.getOperationUser()).isEqualTo(ADMIN_USER_ID); + } + + @Test + void shipRejectsUserWithoutExplicitPermission() { + UserFreightBalanceCmd cmd = new UserFreightBalanceCmd(); + cmd.setReqUserId(ADMIN_USER_ID); + when(userAccountService.hasButtonsAlias(ADMIN_USER_ID.intValue(), FREIGHT_SHIP_MENU_ALIAS)) + .thenReturn(false); + + // 无权限账号必须在进入余额变更服务前被拒绝,防止绕过前端直接调用接口发货。 + assertThrows(RuntimeException.class, () -> controller.ship(cmd)); + + verify(userFreightService, never()).ship(cmd); + } +}