数据联动列表:数据权限隔离
This commit is contained in:
parent
f8a8474f0f
commit
5d8ae0e2f0
@ -73,11 +73,11 @@ public class NotifyTemplateServiceImpl implements INotifyTemplateService {
|
|||||||
// notifyTemplate.setTenantId(user.getUserId());
|
// notifyTemplate.setTenantId(user.getUserId());
|
||||||
// }
|
// }
|
||||||
// 查询所属机构
|
// 查询所属机构
|
||||||
if (null != user.getDeptId()) {
|
// if (null != user.getDeptId()) {
|
||||||
notifyTemplate.setTenantId(user.getDept().getDeptUserId());
|
// notifyTemplate.setTenantId(user.getDept().getDeptUserId());
|
||||||
} else {
|
// } else {
|
||||||
notifyTemplate.setTenantId(user.getUserId());
|
// notifyTemplate.setTenantId(user.getUserId());
|
||||||
}
|
// }
|
||||||
List<NotifyTemplate> notifyTemplates = notifyTemplateMapper.selectNotifyTemplateList(notifyTemplate);
|
List<NotifyTemplate> notifyTemplates = notifyTemplateMapper.selectNotifyTemplateList(notifyTemplate);
|
||||||
if (org.apache.commons.collections4.CollectionUtils.isEmpty(notifyTemplates)) {
|
if (org.apache.commons.collections4.CollectionUtils.isEmpty(notifyTemplates)) {
|
||||||
return notifyTemplates;
|
return notifyTemplates;
|
||||||
|
|||||||
@ -42,12 +42,16 @@ public class ThingsModelPushController extends BaseController {
|
|||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取详情 */
|
/** 获取详情(超管看全部,机构/终端用户只能看自己机构的) */
|
||||||
@ApiOperation("获取推送配置详情")
|
@ApiOperation("获取推送配置详情")
|
||||||
@PreAuthorize("@ss.hasPermi('iot:push:query')")
|
@PreAuthorize("@ss.hasPermi('iot:push:query')")
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public AjaxResult getById(@PathVariable Long id) {
|
public AjaxResult getById(@PathVariable Long id) {
|
||||||
return AjaxResult.success(pushConfigService.selectById(id));
|
ThingsModelPushConfig config = pushConfigService.selectById(id);
|
||||||
|
if (config == null) {
|
||||||
|
return AjaxResult.error("推送配置不存在或无访问权限");
|
||||||
|
}
|
||||||
|
return AjaxResult.success(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增 */
|
/** 新增 */
|
||||||
@ -66,6 +70,7 @@ public class ThingsModelPushController extends BaseController {
|
|||||||
@Log(title = "推送配置", businessType = BusinessType.UPDATE)
|
@Log(title = "推送配置", businessType = BusinessType.UPDATE)
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public AjaxResult edit(@RequestBody ThingsModelPushConfig config) {
|
public AjaxResult edit(@RequestBody ThingsModelPushConfig config) {
|
||||||
|
pushConfigService.assertOwned(config.getId());
|
||||||
return toAjax(pushConfigService.updateConfig(config));
|
return toAjax(pushConfigService.updateConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +80,7 @@ public class ThingsModelPushController extends BaseController {
|
|||||||
@Log(title = "推送配置状态", businessType = BusinessType.UPDATE)
|
@Log(title = "推送配置状态", businessType = BusinessType.UPDATE)
|
||||||
@PutMapping("/status")
|
@PutMapping("/status")
|
||||||
public AjaxResult changeStatus(@RequestBody ThingsModelPushConfig config) {
|
public AjaxResult changeStatus(@RequestBody ThingsModelPushConfig config) {
|
||||||
|
pushConfigService.assertOwned(config.getId());
|
||||||
return toAjax(pushConfigService.updateStatus(config.getId(), config.getStatus()));
|
return toAjax(pushConfigService.updateStatus(config.getId(), config.getStatus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +90,12 @@ public class ThingsModelPushController extends BaseController {
|
|||||||
@Log(title = "推送配置", businessType = BusinessType.DELETE)
|
@Log(title = "推送配置", businessType = BusinessType.DELETE)
|
||||||
@DeleteMapping("/{ids}")
|
@DeleteMapping("/{ids}")
|
||||||
public AjaxResult remove(@PathVariable Long[] ids) {
|
public AjaxResult remove(@PathVariable Long[] ids) {
|
||||||
|
if (ids == null || ids.length == 0) {
|
||||||
|
return AjaxResult.error("请选择要删除的推送配置");
|
||||||
|
}
|
||||||
|
for (Long id : ids) {
|
||||||
|
pushConfigService.assertOwned(id);
|
||||||
|
}
|
||||||
return toAjax(pushConfigService.deleteByIds(ids));
|
return toAjax(pushConfigService.deleteByIds(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +109,7 @@ public class ThingsModelPushController extends BaseController {
|
|||||||
public AjaxResult manualPush(@PathVariable Long id) {
|
public AjaxResult manualPush(@PathVariable Long id) {
|
||||||
ThingsModelPushConfig config = pushConfigService.selectById(id);
|
ThingsModelPushConfig config = pushConfigService.selectById(id);
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
return AjaxResult.error("推送配置不存在");
|
return AjaxResult.error("推送配置不存在或无访问权限");
|
||||||
}
|
}
|
||||||
if (config.getStatus() == null || config.getStatus() == 0) {
|
if (config.getStatus() == null || config.getStatus() == 0) {
|
||||||
return AjaxResult.error("推送配置已停用,请先启用");
|
return AjaxResult.error("推送配置已停用,请先启用");
|
||||||
|
|||||||
@ -71,7 +71,7 @@ public class ThingsModelPushConfig extends BaseEntity {
|
|||||||
@ApiModelProperty("租户名称")
|
@ApiModelProperty("租户名称")
|
||||||
private String tenantName;
|
private String tenantName;
|
||||||
|
|
||||||
@ApiModelProperty("配置归属用户ID(列表按此过滤;与接收用户 userIds 不同)")
|
@ApiModelProperty("创建人用户ID(数据隔离按 tenantId 过滤,与此字段及接收用户 userIds 均不同)")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
/** 物模型项列表(非持久化,前端用) */
|
/** 物模型项列表(非持久化,前端用) */
|
||||||
|
|||||||
@ -29,6 +29,14 @@ public interface DeviceMapper extends BaseMapperX<Device> {
|
|||||||
*/
|
*/
|
||||||
public Device selectDeviceByDeviceId(Long deviceId);
|
public Device selectDeviceByDeviceId(Long deviceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 只查设备的归属(tenant_id / tenant_name),用于按设备推导数据归属
|
||||||
|
*
|
||||||
|
* @param deviceId 设备主键
|
||||||
|
* @return 设备归属,设备不存在时返回 null
|
||||||
|
*/
|
||||||
|
Device selectTenantByDeviceId(Long deviceId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备和产品总数
|
* 查询设备和产品总数
|
||||||
*
|
*
|
||||||
|
|||||||
@ -19,6 +19,9 @@ public interface ThingsModelPushConfigMapper {
|
|||||||
|
|
||||||
ThingsModelPushConfig selectById(Long id);
|
ThingsModelPushConfig selectById(Long id);
|
||||||
|
|
||||||
|
/** 只查归属租户ID,用于越权校验(避免加载物模型项和接收用户) */
|
||||||
|
Long selectTenantIdById(Long id);
|
||||||
|
|
||||||
List<ThingsModelPushConfig> selectList(ThingsModelPushConfig query);
|
List<ThingsModelPushConfig> selectList(ThingsModelPushConfig query);
|
||||||
|
|
||||||
/** 查询所有启用的推送配置(含物模型项和接收用户) */
|
/** 查询所有启用的推送配置(含物模型项和接收用户) */
|
||||||
|
|||||||
@ -21,6 +21,11 @@ public interface IThingsModelPushConfigService {
|
|||||||
/** 按产品/设备查询启用配置 */
|
/** 按产品/设备查询启用配置 */
|
||||||
List<ThingsModelPushConfig> selectEnabledByProductAndDevice(Long productId, Long deviceId);
|
List<ThingsModelPushConfig> selectEnabledByProductAndDevice(Long productId, Long deviceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验配置在当前登录账号的数据范围内,越权抛异常
|
||||||
|
*/
|
||||||
|
void assertOwned(Long configId);
|
||||||
|
|
||||||
int insertConfig(ThingsModelPushConfig config);
|
int insertConfig(ThingsModelPushConfig config);
|
||||||
|
|
||||||
int updateConfig(ThingsModelPushConfig config);
|
int updateConfig(ThingsModelPushConfig config);
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
package com.fastbee.iot.service.impl;
|
package com.fastbee.iot.service.impl;
|
||||||
|
|
||||||
|
import com.fastbee.common.core.domain.entity.SysDept;
|
||||||
|
import com.fastbee.common.core.domain.entity.SysUser;
|
||||||
import com.fastbee.common.core.domain.model.LoginUser;
|
import com.fastbee.common.core.domain.model.LoginUser;
|
||||||
|
import com.fastbee.common.exception.ServiceException;
|
||||||
import com.fastbee.common.utils.DateUtils;
|
import com.fastbee.common.utils.DateUtils;
|
||||||
import com.fastbee.common.utils.SecurityUtils;
|
import com.fastbee.common.utils.SecurityUtils;
|
||||||
|
import com.fastbee.common.utils.StringUtils;
|
||||||
|
import com.fastbee.iot.domain.Device;
|
||||||
import com.fastbee.iot.domain.PushModelItem;
|
import com.fastbee.iot.domain.PushModelItem;
|
||||||
import com.fastbee.iot.domain.PushUser;
|
import com.fastbee.iot.domain.PushUser;
|
||||||
import com.fastbee.iot.domain.ThingsModelPushConfig;
|
import com.fastbee.iot.domain.ThingsModelPushConfig;
|
||||||
|
import com.fastbee.iot.mapper.DeviceMapper;
|
||||||
import com.fastbee.iot.mapper.ThingsModelPushConfigMapper;
|
import com.fastbee.iot.mapper.ThingsModelPushConfigMapper;
|
||||||
import com.fastbee.iot.service.IThingsModelPushConfigService;
|
import com.fastbee.iot.service.IThingsModelPushConfigService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -16,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,18 +36,31 @@ public class ThingsModelPushConfigServiceImpl implements IThingsModelPushConfigS
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ThingsModelPushConfigMapper mapper;
|
private ThingsModelPushConfigMapper mapper;
|
||||||
|
@Resource
|
||||||
|
private DeviceMapper deviceMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ThingsModelPushConfig selectById(Long id) {
|
public ThingsModelPushConfig selectById(Long id) {
|
||||||
return mapper.selectById(id);
|
ThingsModelPushConfig config = mapper.selectById(id);
|
||||||
|
if (config == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
assertInScope(config.getTenantId());
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ThingsModelPushConfig> selectList(ThingsModelPushConfig query) {
|
public List<ThingsModelPushConfig> selectList(ThingsModelPushConfig query) {
|
||||||
query.setUserId(SecurityUtils.getUserId());
|
// 归属条件只由服务端计算,忽略前端传入值:超管看全部,机构/终端用户只看自己
|
||||||
|
query.setTenantId(resolveScopeTenantId());
|
||||||
return mapper.selectList(query);
|
return mapper.selectList(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assertOwned(Long configId) {
|
||||||
|
assertInScope(mapper.selectTenantIdById(configId));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ThingsModelPushConfig> selectAllEnabled() {
|
public List<ThingsModelPushConfig> selectAllEnabled() {
|
||||||
return mapper.selectAllEnabled();
|
return mapper.selectAllEnabled();
|
||||||
@ -55,6 +75,11 @@ public class ThingsModelPushConfigServiceImpl implements IThingsModelPushConfigS
|
|||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public int insertConfig(ThingsModelPushConfig config) {
|
public int insertConfig(ThingsModelPushConfig config) {
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
Device deviceTenant = loadDeviceTenant(config.getDeviceId());
|
||||||
|
Long ownerTenantId = resolveOwnerTenantId(loginUser, deviceTenant);
|
||||||
|
config.setTenantId(ownerTenantId);
|
||||||
|
// 名称必须与最终归属ID同源,否则会写出 tenant_id=3 / tenant_name=admin 这类错配数据
|
||||||
|
config.setTenantName(resolveOwnerTenantName(loginUser, deviceTenant, ownerTenantId));
|
||||||
config.setUserId(loginUser.getUserId());
|
config.setUserId(loginUser.getUserId());
|
||||||
config.setCreateBy(loginUser.getUsername());
|
config.setCreateBy(loginUser.getUsername());
|
||||||
config.setCreateTime(DateUtils.getNowDate());
|
config.setCreateTime(DateUtils.getNowDate());
|
||||||
@ -110,6 +135,77 @@ public class ThingsModelPushConfigServiceImpl implements IThingsModelPushConfigS
|
|||||||
mapper.updateLastPushTime(id, new Date());
|
mapper.updateLastPushTime(id, new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前登录账号的查询范围:超级管理员返回 null(不限),其余账号返回其归属租户ID
|
||||||
|
*/
|
||||||
|
private Long resolveScopeTenantId() {
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (SecurityUtils.isAdmin(loginUser.getUserId())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return resolveAccountTenantId(loginUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据归属租户:<b>优先取所挂设备的归属</b>,设备无归属时回落登录账号的机构。
|
||||||
|
* 推送配置的主体是设备而非创建人——超管替下级机构建配置时必须落到该机构,否则机构看不到自己的配置。
|
||||||
|
*/
|
||||||
|
private Long resolveOwnerTenantId(LoginUser loginUser, Device deviceTenant) {
|
||||||
|
if (deviceTenant != null && deviceTenant.getTenantId() != null) {
|
||||||
|
return deviceTenant.getTenantId();
|
||||||
|
}
|
||||||
|
return resolveAccountTenantId(loginUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 归属名称,必须与 {@link #resolveOwnerTenantId} 的结果同源:
|
||||||
|
* 归属ID取自设备时名称就用设备的(哪怕为空,如实反映),否则回落登录账号。
|
||||||
|
*/
|
||||||
|
private String resolveOwnerTenantName(LoginUser loginUser, Device deviceTenant, Long ownerTenantId) {
|
||||||
|
if (deviceTenant != null && Objects.equals(deviceTenant.getTenantId(), ownerTenantId)) {
|
||||||
|
return deviceTenant.getTenantName();
|
||||||
|
}
|
||||||
|
return resolveAccountTenantName(loginUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录账号自身归属:机构用户取机构绑定的系统账号ID,终端用户(无机构)取自身账号ID
|
||||||
|
*/
|
||||||
|
private Long resolveAccountTenantId(LoginUser loginUser) {
|
||||||
|
SysUser user = loginUser.getUser();
|
||||||
|
SysDept dept = user.getDept();
|
||||||
|
if (user.getDeptId() != null && dept != null && dept.getDeptUserId() != null) {
|
||||||
|
return dept.getDeptUserId();
|
||||||
|
}
|
||||||
|
return loginUser.getUserId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveAccountTenantName(LoginUser loginUser) {
|
||||||
|
SysUser user = loginUser.getUser();
|
||||||
|
SysDept dept = user.getDept();
|
||||||
|
if (user.getDeptId() != null && dept != null && dept.getDeptUserId() != null
|
||||||
|
&& StringUtils.isNotEmpty(dept.getDeptUserName())) {
|
||||||
|
return dept.getDeptUserName();
|
||||||
|
}
|
||||||
|
return user.getUserName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 设备归属,deviceId 为空或 0(未指定/全设备)时返回 null */
|
||||||
|
private Device loadDeviceTenant(Long deviceId) {
|
||||||
|
if (deviceId == null || deviceId == 0L) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deviceMapper.selectTenantByDeviceId(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertInScope(Long tenantId) {
|
||||||
|
Long scopeTenantId = resolveScopeTenantId();
|
||||||
|
if (scopeTenantId == null || scopeTenantId.equals(tenantId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new ServiceException("推送配置不存在或无访问权限");
|
||||||
|
}
|
||||||
|
|
||||||
private void saveItemsAndUsers(ThingsModelPushConfig config) {
|
private void saveItemsAndUsers(ThingsModelPushConfig config) {
|
||||||
if (CollectionUtils.isNotEmpty(config.getItems())) {
|
if (CollectionUtils.isNotEmpty(config.getItems())) {
|
||||||
List<PushModelItem> items = config.getItems();
|
List<PushModelItem> items = config.getItems();
|
||||||
|
|||||||
@ -550,6 +550,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
where device_id = #{deviceId}
|
where device_id = #{deviceId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<resultMap type="com.fastbee.iot.domain.Device" id="DeviceTenantResult">
|
||||||
|
<result property="tenantId" column="tenant_id" />
|
||||||
|
<result property="tenantName" column="tenant_name" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="selectTenantByDeviceId" parameterType="Long" resultMap="DeviceTenantResult">
|
||||||
|
select d.tenant_id, d.tenant_name from iot_device d
|
||||||
|
where d.device_id = #{deviceId}
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectDeviceInfoBySerialNumber" parameterType="String" resultMap="DeviceImeiIccidTypeResult">
|
<select id="selectDeviceInfoBySerialNumber" parameterType="String" resultMap="DeviceImeiIccidTypeResult">
|
||||||
select
|
select
|
||||||
p.device_type as device_type,
|
p.device_type as device_type,
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
<result property="status" column="status"/>
|
<result property="status" column="status"/>
|
||||||
<result property="tenantId" column="tenant_id"/>
|
<result property="tenantId" column="tenant_id"/>
|
||||||
<result property="tenantName" column="tenant_name"/>
|
<result property="tenantName" column="tenant_name"/>
|
||||||
|
<result property="userId" column="user_id"/>
|
||||||
<result property="createBy" column="create_by"/>
|
<result property="createBy" column="create_by"/>
|
||||||
<result property="createTime" column="create_time"/>
|
<result property="createTime" column="create_time"/>
|
||||||
<result property="updateBy" column="update_by"/>
|
<result property="updateBy" column="update_by"/>
|
||||||
@ -53,9 +54,10 @@
|
|||||||
<sql id="baseColumns">
|
<sql id="baseColumns">
|
||||||
c.id, c.config_name, c.product_id, c.device_id, c.serial_number,
|
c.id, c.config_name, c.product_id, c.device_id, c.serial_number,
|
||||||
c.template_id, c.push_interval, c.last_push_time, c.status,
|
c.template_id, c.push_interval, c.last_push_time, c.status,
|
||||||
c.tenant_id, c.tenant_name, c.create_by, c.create_time,
|
c.tenant_id, c.tenant_name, c.user_id, c.create_by, c.create_time,
|
||||||
c.update_by, c.update_time,p.product_name, p.device_type,
|
c.update_by, c.update_time,p.product_name, p.device_type,
|
||||||
d.device_name,d.network_address AS device_address, nt.name AS template_name
|
d.device_name,
|
||||||
|
d.network_address AS device_address, nt.name AS template_name
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<sql id="baseJoins">
|
<sql id="baseJoins">
|
||||||
@ -74,6 +76,16 @@
|
|||||||
AND c.del_flag = '0'
|
AND c.del_flag = '0'
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTenantIdById" resultType="java.lang.Long">
|
||||||
|
SELECT
|
||||||
|
c.tenant_id
|
||||||
|
FROM
|
||||||
|
iot_things_model_push_config c
|
||||||
|
WHERE
|
||||||
|
c.id = #{id}
|
||||||
|
AND c.del_flag = '0'
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectList" resultMap="ConfigResult">
|
<select id="selectList" resultMap="ConfigResult">
|
||||||
SELECT
|
SELECT
|
||||||
<include refid="baseColumns"/>
|
<include refid="baseColumns"/>
|
||||||
@ -131,6 +143,7 @@
|
|||||||
status,
|
status,
|
||||||
tenant_id,
|
tenant_id,
|
||||||
tenant_name,
|
tenant_name,
|
||||||
|
user_id,
|
||||||
create_by,
|
create_by,
|
||||||
create_time,
|
create_time,
|
||||||
del_flag
|
del_flag
|
||||||
@ -146,6 +159,7 @@
|
|||||||
#{status},
|
#{status},
|
||||||
#{tenantId},
|
#{tenantId},
|
||||||
#{tenantName},
|
#{tenantName},
|
||||||
|
#{userId},
|
||||||
#{createBy},
|
#{createBy},
|
||||||
#{createTime},
|
#{createTime},
|
||||||
'0'
|
'0'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user