mirror of
https://gitee.com/pnoker/iot-dc3.git
synced 2026-11-03 11:42:04 +08:00
fix(security): enforce gateway user and command tenant scope
This commit is contained in:
+24
-2
@@ -32,15 +32,37 @@ public interface PointValueCommandService {
|
||||
/**
|
||||
* Read command
|
||||
*
|
||||
* @param tenantId current tenant id
|
||||
* @param entityVO PointValueReadVO
|
||||
*/
|
||||
void read(PointValueReadVO entityVO);
|
||||
void read(Long tenantId, PointValueReadVO entityVO);
|
||||
|
||||
/**
|
||||
* Read command from trusted internal callers that do not carry request tenant
|
||||
* context.
|
||||
*
|
||||
* @param entityVO PointValueReadVO
|
||||
*/
|
||||
default void read(PointValueReadVO entityVO) {
|
||||
read(null, entityVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write command
|
||||
*
|
||||
* @param tenantId current tenant id
|
||||
* @param entityVO PointValueWriteVO
|
||||
*/
|
||||
void write(PointValueWriteVO entityVO);
|
||||
void write(Long tenantId, PointValueWriteVO entityVO);
|
||||
|
||||
/**
|
||||
* Write command from trusted internal callers that do not carry request tenant
|
||||
* context.
|
||||
*
|
||||
* @param entityVO PointValueWriteVO
|
||||
*/
|
||||
default void write(PointValueWriteVO entityVO) {
|
||||
write(null, entityVO);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+40
-2
@@ -17,14 +17,21 @@
|
||||
|
||||
package io.github.pnoker.common.data.biz.impl;
|
||||
|
||||
import io.github.pnoker.common.constant.common.ExceptionConstant;
|
||||
import io.github.pnoker.common.constant.driver.RabbitConstant;
|
||||
import io.github.pnoker.common.data.biz.PointValueCommandService;
|
||||
import io.github.pnoker.common.data.entity.vo.PointValueReadVO;
|
||||
import io.github.pnoker.common.data.entity.vo.PointValueWriteVO;
|
||||
import io.github.pnoker.common.entity.dto.DeviceCommandDTO;
|
||||
import io.github.pnoker.common.enums.DeviceCommandTypeEnum;
|
||||
import io.github.pnoker.common.exception.NotFoundException;
|
||||
import io.github.pnoker.common.exception.UnAuthorizedException;
|
||||
import io.github.pnoker.common.facade.api.DeviceFacade;
|
||||
import io.github.pnoker.common.facade.api.DriverFacade;
|
||||
import io.github.pnoker.common.facade.api.PointFacade;
|
||||
import io.github.pnoker.common.facade.entity.bo.FacadeDeviceBO;
|
||||
import io.github.pnoker.common.facade.entity.bo.FacadeDriverBO;
|
||||
import io.github.pnoker.common.facade.entity.bo.FacadePointBO;
|
||||
import io.github.pnoker.common.utils.JsonUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -42,14 +49,22 @@ import java.util.Objects;
|
||||
@Service
|
||||
public class PointValueCommandServiceImpl implements PointValueCommandService {
|
||||
|
||||
@Resource
|
||||
private DeviceFacade deviceFacade;
|
||||
|
||||
@Resource
|
||||
private DriverFacade driverFacade;
|
||||
|
||||
@Resource
|
||||
private PointFacade pointFacade;
|
||||
|
||||
@Resource
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Override
|
||||
public void read(PointValueReadVO entityVO) {
|
||||
public void read(Long tenantId, PointValueReadVO entityVO) {
|
||||
validateCommandScope(tenantId, entityVO.getDeviceId(), entityVO.getPointId());
|
||||
|
||||
FacadeDriverBO driver = driverFacade.selectByDeviceId(entityVO.getDeviceId());
|
||||
if (Objects.isNull(driver)) {
|
||||
return;
|
||||
@@ -64,7 +79,9 @@ public class PointValueCommandServiceImpl implements PointValueCommandService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PointValueWriteVO entityVO) {
|
||||
public void write(Long tenantId, PointValueWriteVO entityVO) {
|
||||
validateCommandScope(tenantId, entityVO.getDeviceId(), entityVO.getPointId());
|
||||
|
||||
FacadeDriverBO driver = driverFacade.selectByDeviceId(entityVO.getDeviceId());
|
||||
if (Objects.isNull(driver)) {
|
||||
return;
|
||||
@@ -78,4 +95,25 @@ public class PointValueCommandServiceImpl implements PointValueCommandService {
|
||||
RabbitConstant.ROUTING_DEVICE_COMMAND_PREFIX + driver.getServiceName(), deviceCommandDTO);
|
||||
}
|
||||
|
||||
private void validateCommandScope(Long tenantId, Long deviceId, Long pointId) {
|
||||
FacadeDeviceBO device = deviceFacade.selectById(deviceId);
|
||||
if (Objects.isNull(device)) {
|
||||
throw new NotFoundException("Device does not exist");
|
||||
}
|
||||
if (Objects.nonNull(tenantId) && !tenantId.equals(device.getTenantId())) {
|
||||
throw new UnAuthorizedException(ExceptionConstant.NO_AVAILABLE_AUTH);
|
||||
}
|
||||
|
||||
FacadePointBO point = pointFacade.selectById(pointId);
|
||||
if (Objects.isNull(point)) {
|
||||
throw new NotFoundException("Point does not exist");
|
||||
}
|
||||
if (Objects.nonNull(tenantId) && !tenantId.equals(point.getTenantId())) {
|
||||
throw new UnAuthorizedException(ExceptionConstant.NO_AVAILABLE_AUTH);
|
||||
}
|
||||
if (Objects.isNull(device.getProfileIds()) || !device.getProfileIds().contains(point.getProfileId())) {
|
||||
throw new UnAuthorizedException(ExceptionConstant.NO_AVAILABLE_AUTH);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-6
@@ -57,10 +57,10 @@ public class PointValueCommandController implements BaseController {
|
||||
*/
|
||||
@PostMapping("/read")
|
||||
public Mono<R<Boolean>> read(@Validated @RequestBody PointValueReadVO entityVO) {
|
||||
return async(() -> {
|
||||
pointValueCommandService.read(entityVO);
|
||||
return getTenantId().flatMap(tenantId -> async(() -> {
|
||||
pointValueCommandService.read(tenantId, entityVO);
|
||||
return R.ok();
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,10 +71,10 @@ public class PointValueCommandController implements BaseController {
|
||||
*/
|
||||
@PostMapping("/write")
|
||||
public Mono<R<Boolean>> write(@Validated @RequestBody PointValueWriteVO entityVO) {
|
||||
return async(() -> {
|
||||
pointValueCommandService.write(entityVO);
|
||||
return getTenantId().flatMap(tenantId -> async(() -> {
|
||||
pointValueCommandService.write(tenantId, entityVO);
|
||||
return R.ok();
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-3
@@ -112,9 +112,12 @@ public class FilterServiceImpl implements FilterService {
|
||||
|
||||
@Override
|
||||
public RequestHeader.UserHeader getUser(FacadeUserLoginBO userLogin, FacadeTenantBO tenant) {
|
||||
// Preserves the existing (surprising) behavior: lookup UserApi by UserLogin.id,
|
||||
// not UserLogin.userId. Changing that belongs in a separate bug-fix PR.
|
||||
FacadeUserBO user = userCache.get(userLogin.getId(), id -> Optional.ofNullable(userFacade.selectById(id)))
|
||||
Long userId = userLogin.getUserId();
|
||||
if (Objects.isNull(userId)) {
|
||||
throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
|
||||
}
|
||||
|
||||
FacadeUserBO user = userCache.get(userId, id -> Optional.ofNullable(userFacade.selectById(id)))
|
||||
.orElse(null);
|
||||
if (Objects.isNull(user)) {
|
||||
throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
|
||||
|
||||
Reference in New Issue
Block a user