数据权限

master
zzy 2026-04-21 14:23:47 +08:00
parent 76ed1f579c
commit 3acdbeeb37
20 changed files with 98 additions and 104 deletions

View File

@ -110,8 +110,6 @@ public class CommunityController {
.streetName("幸福街道")
.districtName("和谐社区")
.communityAddress("阳光路 1 号")
.username("ygxq")
.password("123456")
.visitAuditStr("需要审核")
.gateAuditStr("需要审核")
.build(),
@ -120,8 +118,6 @@ public class CommunityController {
.streetName("平安街道")
.districtName("光明社区")
.communityAddress("月亮湾路 88 号")
.username("ylwxq")
.password("123456")
.visitAuditStr("无需审核")
.gateAuditStr("无需审核")
.build()

View File

@ -38,12 +38,6 @@ public class CommunityImportExcelVO {
@ExcelProperty("小区物业")
private String propertyCompany;
@ExcelProperty("用户名")
private String username;
@ExcelProperty("密码")
private String password;
@ExcelProperty(value = "来访审核")
private String visitAuditStr;

View File

@ -2,11 +2,8 @@ package com.fjrcloud.community.module.community.controller.admin.community.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 小区信息主表comm_community新增/修改 Request VO")
@ -45,13 +42,4 @@ public class CommunitySaveReqVO {
@Schema(description = "道闸申请配置1需要审核0无需审核", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean gateAudit;
@Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin")
@Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户名由 数字、字母 组成")
@Size(min = 4, max = 30, message = "用户名长度为 4-30 个字符")
private String username;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin123")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
}

View File

@ -64,11 +64,6 @@ public class CommunityServiceImpl implements CommunityService {
tenantReqVO.setPackageId(TENANT_PACKAGE_ID);
tenantReqVO.setExpireTime(LocalDateTime.now().plusYears(100));
tenantReqVO.setAccountCount(9999);
// 使用传入的用户名和密码创建租户管理员
tenantReqVO.setUsername(createReqVO.getUsername());
tenantReqVO.setPassword(createReqVO.getPassword());
Long tenantId = tenantService.createTenant(tenantReqVO);
// 创建小区记录ID与租户ID一致
@ -264,8 +259,6 @@ public class CommunityServiceImpl implements CommunityService {
createReqVO.setLongitude(importCommunity.getLongitude());
createReqVO.setLatitude(importCommunity.getLatitude());
createReqVO.setPropertyCompany(importCommunity.getPropertyCompany());
createReqVO.setUsername(importCommunity.getUsername());
createReqVO.setPassword(importCommunity.getPassword());
createReqVO.setVisitAudit(visitAudit);
createReqVO.setGateAudit(gateAudit);
@ -332,12 +325,6 @@ public class CommunityServiceImpl implements CommunityService {
if (StrUtil.isBlank(importCommunity.getCommunityAddress())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:小区地址不能为空");
}
if (StrUtil.isBlank(importCommunity.getUsername())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:用户名不能为空");
}
if (StrUtil.isBlank(importCommunity.getPassword())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:密码不能为空");
}
if (importCommunity.getVisitAuditStr() == null) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:来访审核不能为空");
}

View File

@ -1,15 +1,9 @@
package com.fjrcloud.community.module.system.controller.admin.tenant.vo.tenant;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.List;
@ -53,19 +47,19 @@ public class TenantSaveReqVO {
// ========== 仅【创建】时,需要传递的字段 ==========
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "fjrcloud")
@Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成")
@Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符")
// @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成")
// @Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符")
private String username;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
// @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
@AssertTrue(message = "用户账号、密码不能为空")
@JsonIgnore
public boolean isUsernameValid() {
return id != null // 修改时,不需要传递
|| (ObjectUtil.isAllNotEmpty(username, password)); // 新增时,必须都传递 username、password
}
// @AssertTrue(message = "用户账号、密码不能为空")
// @JsonIgnore
// public boolean isUsernameValid() {
// return id != null // 修改时,不需要传递
// || (ObjectUtil.isAllNotEmpty(username, password)); // 新增时,必须都传递 username、password
// }
}

View File

@ -116,7 +116,7 @@ public class UserController {
convertList(pageResult.getList(), AdminUserDO::getDeptId));
List<UserRespVO> list = UserConvert.INSTANCE.convertList(pageResult.getList(), deptMap);
userService.fillUserTenantNames(list);
userService.fillUserTenantInfo(list);
return success(new PageResult<>(list, pageResult.getTotal()));
}
@ -142,7 +142,7 @@ public class UserController {
DeptDO dept = deptService.getDept(user.getDeptId());
UserRespVO userVO = UserConvert.INSTANCE.convert(user, dept);
userService.fillUserTenantNames(Collections.singletonList(userVO));
userService.fillUserTenantInfo(Collections.singletonList(userVO));
return success(userVO);
}
@ -159,7 +159,7 @@ public class UserController {
convertList(list, AdminUserDO::getDeptId));
List<UserRespVO> userVOList = UserConvert.INSTANCE.convertList(list, deptMap);
userService.fillUserTenantNames(userVOList);
userService.fillUserTenantInfo(userVOList);
ExcelUtils.write(response, "用户数据.xls", "数据", UserRespVO.class, userVOList);
}

View File

@ -9,6 +9,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
@Schema(description = "管理后台 - 用户信息 Response VO")
@ -69,6 +70,9 @@ public class UserRespVO{
@ExcelProperty("数据权限")
private String tenantNames;
@Schema(description = "用户有权限的租户ID列表", example = "[1, 2, 3]")
private List<Long> tenantList;
@Schema(description = "最后登录时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
@ExcelProperty("最后登录时间")
private LocalDateTime loginDate;

View File

@ -4,7 +4,8 @@ import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
import com.fjrcloud.community.framework.tenant.core.db.TenantBaseDO;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
import com.fjrcloud.community.module.system.dal.dataobject.user.AdminUserDO;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -18,8 +19,9 @@ import lombok.EqualsAndHashCode;
@TableName("system_dept")
@KeySequence("system_dept_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@TenantIgnore
@EqualsAndHashCode(callSuper = true)
public class DeptDO extends TenantBaseDO {
public class DeptDO extends BaseDO {
public static final Long PARENT_ID_ROOT = 0L;

View File

@ -1,10 +1,11 @@
package com.fjrcloud.community.module.system.dal.dataobject.dept;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -16,6 +17,7 @@ import lombok.EqualsAndHashCode;
@TableName("system_post")
@KeySequence("system_post_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@TenantIgnore
@EqualsAndHashCode(callSuper = true)
public class PostDO extends BaseDO {

View File

@ -1,10 +1,11 @@
package com.fjrcloud.community.module.system.dal.dataobject.dept;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.module.system.dal.dataobject.user.AdminUserDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
import com.fjrcloud.community.module.system.dal.dataobject.user.AdminUserDO;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -16,6 +17,7 @@ import lombok.EqualsAndHashCode;
@TableName("system_user_post")
@KeySequence("system_user_post_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@TenantIgnore
@EqualsAndHashCode(callSuper = true)
public class UserPostDO extends BaseDO {

View File

@ -1,14 +1,15 @@
package com.fjrcloud.community.module.system.dal.dataobject.permission;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
import com.fjrcloud.community.framework.tenant.core.db.TenantBaseDO;
import com.fjrcloud.community.module.system.enums.permission.DataScopeEnum;
import com.fjrcloud.community.module.system.enums.permission.RoleTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
import com.fjrcloud.community.module.system.enums.permission.DataScopeEnum;
import com.fjrcloud.community.module.system.enums.permission.RoleTypeEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -23,7 +24,8 @@ import java.util.Set;
@KeySequence("system_role_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
public class RoleDO extends TenantBaseDO {
@TenantIgnore
public class RoleDO extends BaseDO {
/**
* ID

View File

@ -1,9 +1,10 @@
package com.fjrcloud.community.module.system.dal.dataobject.permission;
import com.fjrcloud.community.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -16,7 +17,8 @@ import lombok.EqualsAndHashCode;
@KeySequence("system_role_menu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
public class RoleMenuDO extends TenantBaseDO {
@TenantIgnore
public class RoleMenuDO extends BaseDO {
/**
*

View File

@ -1,9 +1,10 @@
package com.fjrcloud.community.module.system.dal.dataobject.permission;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -16,6 +17,7 @@ import lombok.EqualsAndHashCode;
@KeySequence("system_user_role_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@TenantIgnore
public class UserRoleDO extends BaseDO {
/**

View File

@ -6,7 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
import com.fjrcloud.community.framework.tenant.core.db.TenantBaseDO;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
import com.fjrcloud.community.module.system.enums.common.SexEnum;
import lombok.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@ -26,7 +27,8 @@ import java.util.Set;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AdminUserDO extends TenantBaseDO {
@TenantIgnore
public class AdminUserDO extends BaseDO {
/**
* ID

View File

@ -25,4 +25,9 @@ public interface UserTenantRelMapper extends BaseMapperX<UserTenantRelDO> {
.eq(UserTenantRelDO::getUserId, userId)
.eq(UserTenantRelDO::getDefaultTenant, true));
}
default int deleteByUserId(Long userId) {
return delete(new LambdaQueryWrapperX<UserTenantRelDO>()
.eq(UserTenantRelDO::getUserId, userId));
}
}

View File

@ -32,6 +32,7 @@ import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static com.fjrcloud.community.framework.common.util.collection.CollectionUtils.convertSet;
@ -223,9 +224,10 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
return Collections.emptyMap();
}
if (userType.equals(UserTypeEnum.ADMIN.getValue())) {
AdminUserDO user = adminUserService.getUser(userId);
return MapUtil.builder(LoginUser.INFO_KEY_NICKNAME, user.getNickname())
.put(LoginUser.INFO_KEY_DEPT_ID, StrUtil.toStringOrNull(user.getDeptId())).build();
AtomicReference<AdminUserDO> user = new AtomicReference<>();
TenantUtils.executeIgnore(() -> user.set(adminUserService.getUser(userId)));
return MapUtil.builder(LoginUser.INFO_KEY_NICKNAME, user.get().getNickname())
.put(LoginUser.INFO_KEY_DEPT_ID, StrUtil.toStringOrNull(user.get().getDeptId())).build();
} else if (userType.equals(UserTypeEnum.MEMBER.getValue())) {
// 注意:目前 Member 暂时不读取,可以按需实现
return Collections.emptyMap();

View File

@ -1,7 +1,6 @@
package com.fjrcloud.community.module.system.service.tenant;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
@ -116,14 +115,14 @@ public class TenantServiceImpl implements TenantService {
TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class);
tenantMapper.insert(tenant);
// 创建租户的管理员
TenantUtils.execute(tenant.getId(), () -> {
// 创建角色
Long roleId = createRole(tenantPackage);
// 创建用户,并分配角色
Long userId = createUser(roleId, createReqVO);
// 修改租户的管理员
tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId));
});
// TenantUtils.execute(tenant.getId(), () -> {
// // 创建角色
// Long roleId = createRole(tenantPackage);
// // 创建用户,并分配角色
// Long userId = createUser(roleId, createReqVO);
// // 修改租户的管理员
// tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId));
// });
return tenant.getId();
}
@ -200,24 +199,19 @@ public class TenantServiceImpl implements TenantService {
@DSTransactional
public void updateTenantRoleMenu(Long tenantId, Set<Long> menuIds) {
TenantUtils.execute(tenantId, () -> {
// 获得所有角色
List<RoleDO> roles = roleService.getRoleList();
roles.forEach(role -> Assert.isTrue(tenantId.equals(role.getTenantId()), "角色({}/{}) 租户不匹配",
role.getId(), role.getTenantId(), tenantId)); // 兜底校验
// 重新分配每个角色的权限
roles.forEach(role -> {
// 如果是租户管理员,重新分配其权限为租户套餐的权限
for (RoleDO role : roles) {
if (Objects.equals(role.getCode(), RoleCodeEnum.TENANT_ADMIN.getCode())) {
permissionService.assignRoleMenu(role.getId(), menuIds);
log.info("[updateTenantRoleMenu][租户管理员({}/{}) 的权限修改为({})]", role.getId(), role.getTenantId(), menuIds);
return;
}
// 如果是其他角色,则去掉超过套餐的权限
log.info("[updateTenantRoleMenu][租户管理员({}) 的权限修改为({})]", role.getId(), menuIds);
} else {
Set<Long> roleMenuIds = permissionService.getRoleMenuListByRoleId(role.getId());
roleMenuIds = CollUtil.intersectionDistinct(roleMenuIds, menuIds);
permissionService.assignRoleMenu(role.getId(), roleMenuIds);
log.info("[updateTenantRoleMenu][角色({}/{}) 的权限修改为({})]", role.getId(), role.getTenantId(), roleMenuIds);
});
log.info("[updateTenantRoleMenu][角色({}) 的权限修改为({})]", role.getId(), roleMenuIds);
}
}
});
}

View File

@ -185,7 +185,7 @@ public interface AdminUserService {
*/
List<AdminUserDO> getUserListByNickname(String nickname);
void fillUserTenantNames(List<UserRespVO> userList);
void fillUserTenantInfo(List<UserRespVO> userList);
UserImportRespVO importUserList(List<UserImportExcelVO> importUsers, boolean isUpdateSupport);

View File

@ -489,7 +489,7 @@ public class AdminUserServiceImpl implements AdminUserService {
}
@Override
public void fillUserTenantNames(List<UserRespVO> userList) {
public void fillUserTenantInfo(List<UserRespVO> userList) {
if (CollUtil.isEmpty(userList)) {
return;
}
@ -499,9 +499,19 @@ public class AdminUserServiceImpl implements AdminUserService {
for (UserRespVO userVO : userList) {
Long userId = userVO.getId();
if (userId != null && tenantNameMap.containsKey(userId)) {
if (userId != null) {
if (tenantNameMap.containsKey(userId)) {
userVO.setTenantNames(tenantNameMap.get(userId));
}
if (userTenantRelMap.containsKey(userId)) {
List<Long> tenantIds = userTenantRelMap.get(userId).stream()
.map(UserTenantRelDO::getTenantId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
userVO.setTenantList(tenantIds);
}
}
}
}

View File

@ -1,7 +1,6 @@
package com.fjrcloud.community.module.system.service.usertenant;
import cn.hutool.core.collection.CollUtil;
import com.fjrcloud.community.framework.common.exception.ServiceException;
import com.fjrcloud.community.module.system.controller.admin.auth.vo.TenantInfoVO;
import com.fjrcloud.community.module.system.dal.dataobject.tenant.TenantDO;
import com.fjrcloud.community.module.system.dal.dataobject.user.UserTenantRelDO;
@ -96,16 +95,23 @@ public class UserTenantRelServiceImpl implements UserTenantRelService {
@Override
@Transactional(rollbackFor = Exception.class)
public void batchAssignUserToTenants(Long userId, List<Long> tenantIds) {
userTenantRelMapper.deleteByUserId(userId);
if (CollUtil.isEmpty(tenantIds)) {
return;
}
for (Long tenantId : tenantIds) {
try {
assignUserToTenant(userId, tenantId, false);
} catch (ServiceException e) {
// 忽略已存在的关联
TenantDO tenant = tenantMapper.selectById(tenantId);
if (tenant == null) {
throw exception(ErrorCodeConstants.TENANT_NOT_EXISTS);
}
UserTenantRelDO rel = new UserTenantRelDO();
rel.setUserId(userId);
rel.setTenantId(tenantId);
rel.setDefaultTenant(false);
userTenantRelMapper.insert(rel);
}
}