@@ -0,0 +1,146 @@
|
||||
package com.yunhai.userbase.service.impl;
|
||||
|
||||
import com.yunhai.platform.utils.exception.DException;
|
||||
import com.yunhai.userbase.entity.SysGroup;
|
||||
import com.yunhai.userbase.entity.SysUserCurrentRole;
|
||||
import com.yunhai.userbase.entity.SysUserRoleRel;
|
||||
import com.yunhai.userbase.enums.IEnum;
|
||||
import com.yunhai.userbase.enums.StatusEnum;
|
||||
import com.yunhai.userbase.enums.SysRoleEnum;
|
||||
import com.yunhai.userbase.model.identity.IdentityCurrentVo;
|
||||
import com.yunhai.userbase.model.identity.IdentityOptionVo;
|
||||
import com.yunhai.userbase.model.identity.IdentitySwitchRequest;
|
||||
import com.yunhai.userbase.repository.SysGroupRepository;
|
||||
import com.yunhai.userbase.repository.SysUserCurrentRoleRepository;
|
||||
import com.yunhai.userbase.repository.SysUserRoleRelRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 用户身份服务:管理「平台身份角色 × 学校」维度的当前激活状态与可选清单。<br><br>
|
||||
* 身份 = (userId, roleId, schoolId) 三元组,权威源为 {@code sys_user_role_rel};<br>
|
||||
* 当前激活状态存 {@code sys_user_current_role}(1:1,每用户一条)。<br>
|
||||
* 本服务不处理业务权限角色(sys_app_role),那套与学校维度无关。
|
||||
*
|
||||
* @author chenx
|
||||
* @date 2026/8/18
|
||||
*/
|
||||
@Service
|
||||
public class IdentityService {
|
||||
|
||||
@Autowired
|
||||
private SysUserRoleRelRepository sysUserRoleRelRepository;
|
||||
@Autowired
|
||||
private SysUserCurrentRoleRepository sysUserCurrentRoleRepository;
|
||||
@Autowired
|
||||
private SysGroupRepository sysGroupRepository;
|
||||
|
||||
/**
|
||||
* 用户全部可选身份(正常态),用于「切换身份」页渲染。
|
||||
*/
|
||||
public List<IdentityOptionVo> listAvailable(Integer userId) {
|
||||
List<SysUserRoleRel> rels = sysUserRoleRelRepository
|
||||
.findByUserIdAndStatus(userId, StatusEnum.NORMAL);
|
||||
List<IdentityOptionVo> result = new ArrayList<>(rels.size());
|
||||
for (SysUserRoleRel rel : rels) {
|
||||
IdentityOptionVo vo = new IdentityOptionVo();
|
||||
vo.setRoleId(rel.getRoleId());
|
||||
vo.setRoleName(roleName(rel.getRoleId()));
|
||||
vo.setSchoolId(rel.getSchoolId());
|
||||
vo.setSchoolName(schoolName(rel.getSchoolId()));
|
||||
vo.setIsMain(rel.getIsMain() != null && rel.getIsMain() == 1);
|
||||
result.add(vo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前激活身份:优先读 sys_user_current_role;无切换记录时兜底主身份(isMain=1)。
|
||||
*/
|
||||
public IdentityCurrentVo getCurrent(Integer userId) {
|
||||
Optional<SysUserCurrentRole> currentOpt = sysUserCurrentRoleRepository.findByUserId(userId);
|
||||
IdentityCurrentVo vo = new IdentityCurrentVo();
|
||||
if (currentOpt.isPresent()) {
|
||||
SysUserCurrentRole current = currentOpt.get();
|
||||
vo.setRoleId(current.getRoleId());
|
||||
vo.setRoleName(roleName(current.getRoleId()));
|
||||
vo.setSchoolId(current.getSchoolId());
|
||||
vo.setSchoolName(current.getSchoolName());
|
||||
vo.setFallback(false);
|
||||
return vo;
|
||||
}
|
||||
// 兜底:主身份整条记录(isMain=1)
|
||||
SysUserRoleRel mainRel = sysUserRoleRelRepository.findByUserIdAndIsMain(userId, 1).orElse(null);
|
||||
if (mainRel != null) {
|
||||
vo.setRoleId(mainRel.getRoleId());
|
||||
vo.setRoleName(roleName(mainRel.getRoleId()));
|
||||
vo.setSchoolId(mainRel.getSchoolId());
|
||||
vo.setSchoolName(schoolName(mainRel.getSchoolId()));
|
||||
vo.setFallback(true);
|
||||
return vo;
|
||||
}
|
||||
// 连主身份都没有(测试期初数据尚未建立):返回空对象,前端引导创建身份
|
||||
vo.setFallback(true);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换身份:校验 (userId, roleId, schoolId) 在 sys_user_role_rel 正常态中存在,
|
||||
* 再 UPSERT sys_user_current_role(按 userId 唯一)。
|
||||
*/
|
||||
public IdentityCurrentVo switchIdentity(Integer userId, IdentitySwitchRequest request) {
|
||||
Integer roleId = request.getRoleId();
|
||||
Integer schoolId = request.getSchoolId();
|
||||
// 校验目标身份确属该用户且正常态,防越权切换
|
||||
SysUserRoleRel rel = sysUserRoleRelRepository
|
||||
.findByUserIdAndSchoolIdAndStatus(userId, schoolId, StatusEnum.NORMAL)
|
||||
.stream()
|
||||
.filter(r -> Objects.equals(r.getRoleId(), roleId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (rel == null) {
|
||||
throw new DException("目标身份不存在或非正常态,无法切换");
|
||||
}
|
||||
|
||||
SysUserCurrentRole current = sysUserCurrentRoleRepository.findByUserId(userId).orElse(null);
|
||||
if (current == null) {
|
||||
current = new SysUserCurrentRole();
|
||||
current.setUserId(userId);
|
||||
}
|
||||
current.setRoleId(roleId);
|
||||
current.setSchoolId(schoolId);
|
||||
current.setSchoolName(schoolName(schoolId));
|
||||
current.setSwitchTime(LocalDateTime.now());
|
||||
sysUserCurrentRoleRepository.save(current);
|
||||
|
||||
IdentityCurrentVo vo = new IdentityCurrentVo();
|
||||
vo.setRoleId(roleId);
|
||||
vo.setRoleName(roleName(roleId));
|
||||
vo.setSchoolId(schoolId);
|
||||
vo.setSchoolName(current.getSchoolName());
|
||||
vo.setFallback(false);
|
||||
return vo;
|
||||
}
|
||||
|
||||
private String roleName(Integer roleId) {
|
||||
if (roleId == null) {
|
||||
return null;
|
||||
}
|
||||
SysRoleEnum e = IEnum.getByKey(SysRoleEnum.class, roleId);
|
||||
return e != null ? e.getValue() : null;
|
||||
}
|
||||
|
||||
private String schoolName(Integer schoolId) {
|
||||
if (schoolId == null || schoolId <= 0) {
|
||||
return null;
|
||||
}
|
||||
SysGroup g = sysGroupRepository.findById(schoolId).orElse(null);
|
||||
return g != null ? g.getName() : null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user