diff --git a/src/main/java/com/yunhai/userhome/controller/api/MiscController.java b/src/main/java/com/yunhai/userhome/controller/api/MiscController.java index a1aba21..dadfeae 100644 --- a/src/main/java/com/yunhai/userhome/controller/api/MiscController.java +++ b/src/main/java/com/yunhai/userhome/controller/api/MiscController.java @@ -1,11 +1,12 @@ package com.yunhai.userhome.controller.api; import com.yunhai.platform.apistd.BizException; -import com.yunhai.platform.openapi.client.YschBaseOpenApi; +import com.yunhai.platform.openapi.client.OpenApiUserClient; import com.yunhai.platform.utils.exception.ErrorCode; import com.yunhai.platform.utils.model.BoaUser; import com.yunhai.userhome.config.Config; import com.yunhai.userhome.utils.OtherUtil; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.view.RedirectView; @@ -25,6 +26,9 @@ import java.util.Map; @RequestMapping(value = Config.API_PATH) public class MiscController { + @Autowired + private OpenApiUserClient openApiUserClient; + /** * 修改用户密码(对齐旧 UserController.updateUserPassword)。 * 前端调用:BaseApi.updatePassword → POST /api/updateUserPassword @@ -40,7 +44,7 @@ public class MiscController { throw new BizException(ErrorCode.CUSTOM, "新密码不得与旧密码相同!"); } try { - YschBaseOpenApi.updateUserPassword(authUserWithDept.getId(), oldPassword, password); + openApiUserClient.updateUserPassword(authUserWithDept.getId(), oldPassword, password); } catch (Exception e) { throw new BizException(ErrorCode.CUSTOM, e.getMessage()); } diff --git a/src/main/java/com/yunhai/userhome/controller/api/UserController.java b/src/main/java/com/yunhai/userhome/controller/api/UserController.java index 36650ab..482b33d 100644 --- a/src/main/java/com/yunhai/userhome/controller/api/UserController.java +++ b/src/main/java/com/yunhai/userhome/controller/api/UserController.java @@ -1,6 +1,7 @@ package com.yunhai.userhome.controller.api; import com.yunhai.platform.apistd.BizException; +import com.yunhai.platform.openapi.client.OpenApiUserClient; import com.yunhai.platform.openapi.client.YschBaseOpenApi; import com.yunhai.platform.utils.exception.ErrorCode; import com.yunhai.platform.utils.model.BoaApp; @@ -8,9 +9,7 @@ import com.yunhai.platform.utils.model.BoaAppType; import com.yunhai.platform.utils.model.BoaRoleInfo; import com.yunhai.platform.utils.model.BoaUser; import com.yunhai.userhome.config.Config; -import com.yunhai.userhome.entity.UserCurrentRole; import com.yunhai.userhome.service.AppRemoteService; -import com.yunhai.userhome.service.IUserCurrentRoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -33,7 +32,7 @@ public class UserController { private AppRemoteService appRemoteService; @Autowired - private IUserCurrentRoleService userCurrentRoleService; + private OpenApiUserClient openApiUserClient; /** 当前登录用户信息(CAS 注入)。 */ @@ -76,23 +75,21 @@ public class UserController { return YschBaseOpenApi.getUserRoleList(authUserWithDept.getId()); } - /** 当前用户激活的角色(本地 user_current_role,可能为空)。 */ + /** 当前用户激活的身份(UserBase 单一权威源;未切换时兜底主身份,无身份为 null)。 */ @GetMapping("findUserRole") - public UserCurrentRole findUserRole(BoaUser authUserWithDept) { - return userCurrentRoleService.findById(authUserWithDept.getId()).orElse(null); + public BoaRoleInfo findUserRole(BoaUser authUserWithDept) { + return YschBaseOpenApi.getCurrentIdentity(authUserWithDept.getId()); } - /** 保存当前激活角色(校验所选 学校+角色 属于用户角色列表,防越权)。 */ + /** + * 保存当前激活角色:userId 只取 CAS 会话(无视请求体,防切他人), + * 目标 (roleId, schId) 是否属该用户由 UserBase 侧 sys_user_role_rel 三元组校验。 + */ @PostMapping("savUserRole") - public void savUserRole(BoaUser authUserWithDept, @RequestBody UserCurrentRole roleInfo) { - List roleList = YschBaseOpenApi.getUserRoleList(authUserWithDept.getId()); - boolean exists = roleList.stream().anyMatch(r -> - r.getRoleId() != null && r.getRoleId().equals(roleInfo.getRoleId()) - && r.getSchId() != null && r.getSchId().equals(roleInfo.getSchId())); - if (!exists) { - throw new BizException(ErrorCode.FORBIDDEN, "非法操作,没有权限"); + public void savUserRole(BoaUser authUserWithDept, @RequestBody BoaRoleInfo roleInfo) { + if (roleInfo.getRoleId() == null || roleInfo.getSchId() == null) { + throw new BizException(ErrorCode.PARAM_ERROR, "角色或学校不能为空"); } - roleInfo.setUserId(authUserWithDept.getId()); - userCurrentRoleService.save(roleInfo); + openApiUserClient.switchIdentity(authUserWithDept.getId(), roleInfo.getRoleId(), roleInfo.getSchId()); } } diff --git a/src/main/java/com/yunhai/userhome/entity/MenuBar.java b/src/main/java/com/yunhai/userhome/entity/MenuBar.java index 6c1bb6c..78f6f94 100644 --- a/src/main/java/com/yunhai/userhome/entity/MenuBar.java +++ b/src/main/java/com/yunhai/userhome/entity/MenuBar.java @@ -9,6 +9,7 @@ import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -51,7 +52,7 @@ public class MenuBar { private Integer schId; - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "menu_bar_role") @Column(name = "role_ids") private List roleIds = new ArrayList<>(); diff --git a/src/main/java/com/yunhai/userhome/entity/UserCurrentRole.java b/src/main/java/com/yunhai/userhome/entity/UserCurrentRole.java index 5250dc4..2e74272 100644 --- a/src/main/java/com/yunhai/userhome/entity/UserCurrentRole.java +++ b/src/main/java/com/yunhai/userhome/entity/UserCurrentRole.java @@ -1,30 +1,16 @@ package com.yunhai.userhome.entity; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Index; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; - /** - * 用户当前激活角色(会话态,本地表 user_current_role)。 - * 对应旧 UserHome 同名单表:一用户一行,记录当前角色 + 学校。 + * 用户当前激活角色(纯 DTO,非持久化)。
+ * 自多角色迁移方案落地后,UserHome 不再持有本地角色存储——数据由 UserBase 单一权威源提供: + * {@code UserCurrentRoleServiceImpl.findById} 经 SDK 调 UserBase {@code /oapi/identity/current}。 + * 字段与 {@code BoaRoleInfo}(roleId/roleName/schId/schName/childId/childName)完全一致,保留以稳定既有调用点。 */ @Data -@Entity -@Table( - name = "user_current_role", - uniqueConstraints = @UniqueConstraint(columnNames = {"userId"}), - indexes = {@Index(columnList = "userId")} -) public class UserCurrentRole { - @Id - @JsonIgnore private Integer userId; private Integer roleId; diff --git a/src/main/java/com/yunhai/userhome/repository/MenuBarRepository.java b/src/main/java/com/yunhai/userhome/repository/MenuBarRepository.java index 8144361..7de1c6f 100644 --- a/src/main/java/com/yunhai/userhome/repository/MenuBarRepository.java +++ b/src/main/java/com/yunhai/userhome/repository/MenuBarRepository.java @@ -3,12 +3,16 @@ package com.yunhai.userhome.repository; import com.yunhai.userhome.entity.MenuBar; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; public interface MenuBarRepository extends JpaRepository, JpaSpecificationExecutor { - List findBySchId(Integer schId); + @Query("select m from MenuBar m left join fetch m.hideSchIds where m.schId = :schId") + List findBySchId(@Param("schId") Integer schId); - List findBySchIdIn(List schIds); + @Query("select m from MenuBar m left join fetch m.hideSchIds where m.schId in :schIds") + List findBySchIdIn(@Param("schIds") List schIds); } diff --git a/src/main/java/com/yunhai/userhome/repository/UserCurrentRoleRepository.java b/src/main/java/com/yunhai/userhome/repository/UserCurrentRoleRepository.java deleted file mode 100644 index 57fe257..0000000 --- a/src/main/java/com/yunhai/userhome/repository/UserCurrentRoleRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.yunhai.userhome.repository; - -import com.yunhai.userhome.entity.UserCurrentRole; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface UserCurrentRoleRepository extends JpaRepository { - - Optional findByUserId(Integer userId); -} diff --git a/src/main/java/com/yunhai/userhome/service/IUserCurrentRoleService.java b/src/main/java/com/yunhai/userhome/service/IUserCurrentRoleService.java index 3561658..08bb88c 100644 --- a/src/main/java/com/yunhai/userhome/service/IUserCurrentRoleService.java +++ b/src/main/java/com/yunhai/userhome/service/IUserCurrentRoleService.java @@ -5,13 +5,14 @@ import com.yunhai.userhome.entity.UserCurrentRole; import java.util.Optional; /** - * 用户当前激活角色(user_current_role 表读写)。 + * 用户当前激活角色访问(UserBase 单一权威源,经 SDK 走 oapi,本地无存储)。
+ * 保留接口以稳定既有 81 处消费点(仅读 roleId/schId);实现由本地表改为 UserBase 开放接口。 */ public interface IUserCurrentRoleService { - /** 取用户当前角色(可能不存在)。 */ + /** 取用户当前激活角色(未切换时兜底主身份;无任何身份返回 Optional.empty)。 */ Optional findById(Integer userId); - /** 保存/覆盖用户当前角色。 */ + /** 切换用户当前激活角色(目标身份须属该用户,由 UserBase 校验)。 */ void save(UserCurrentRole role); } diff --git a/src/main/java/com/yunhai/userhome/service/impl/MenuBarServiceImpl.java b/src/main/java/com/yunhai/userhome/service/impl/MenuBarServiceImpl.java index 4f2e257..eb176f9 100644 --- a/src/main/java/com/yunhai/userhome/service/impl/MenuBarServiceImpl.java +++ b/src/main/java/com/yunhai/userhome/service/impl/MenuBarServiceImpl.java @@ -9,6 +9,7 @@ import com.yunhai.userhome.service.IMenuBarService; import com.yunhai.userhome.service.IUserCurrentRoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.stream.Collectors; @@ -55,6 +56,7 @@ public class MenuBarServiceImpl implements IMenuBarService { } @Override + @Transactional public void saveMenuBar(MenuBar menuBar) { if (menuBar.getId() != null) { Optional optional = menuBarRepository.findById(menuBar.getId()); @@ -76,6 +78,7 @@ public class MenuBarServiceImpl implements IMenuBarService { } @Override + @Transactional public void toggleMenuBarShow(Integer id, Integer schId) { Optional optionalMenuBar = menuBarRepository.findById(id); if (!optionalMenuBar.isPresent()) diff --git a/src/main/java/com/yunhai/userhome/service/impl/UserCurrentRoleServiceImpl.java b/src/main/java/com/yunhai/userhome/service/impl/UserCurrentRoleServiceImpl.java index f22f8b5..a8d3128 100644 --- a/src/main/java/com/yunhai/userhome/service/impl/UserCurrentRoleServiceImpl.java +++ b/src/main/java/com/yunhai/userhome/service/impl/UserCurrentRoleServiceImpl.java @@ -1,26 +1,68 @@ package com.yunhai.userhome.service.impl; +import com.yunhai.platform.openapi.client.OpenApiUserClient; +import com.yunhai.platform.utils.model.BoaRoleInfo; import com.yunhai.userhome.entity.UserCurrentRole; -import com.yunhai.userhome.repository.UserCurrentRoleRepository; import com.yunhai.userhome.service.IUserCurrentRoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Optional; +/** + * 用户当前激活角色访问实现:数据源由本地 {@code user_current_role} 表迁移至 UserBase 单一权威源 + * (多角色迁移方案)。
+ * {@link #findById} → UserBase {@code /oapi/identity/current}(未切换兜底 is_main 主身份); + * {@link #save} → UserBase {@code /oapi/identity/switch}(目标身份属主校验 + 白名单,均在 UserBase 侧)。 + */ @Service public class UserCurrentRoleServiceImpl implements IUserCurrentRoleService { @Autowired - private UserCurrentRoleRepository repository; + private OpenApiUserClient openApiUserClient; @Override public Optional findById(Integer userId) { - return repository.findByUserId(userId); + if (userId == null) { + return Optional.empty(); + } + BoaRoleInfo info = openApiUserClient.getCurrentIdentity(userId); + if (info == null) { + // 无当前身份(超管等平台账号):兜底平台级默认身份(schId=0),避免下游 orElseThrow 抛错 / 拿空菜单 + return Optional.of(platformDefaultRole(userId)); + } + return Optional.of(toRole(info)); } @Override public void save(UserCurrentRole role) { - repository.save(role); + if (role == null || role.getUserId() == null) { + throw new IllegalArgumentException("用户ID不能为空"); + } + openApiUserClient.switchIdentity(role.getUserId(), role.getRoleId(), role.getSchId()); + } + + /** BoaRoleInfo → UserCurrentRole(字段同名,纯 DTO 映射) */ + private UserCurrentRole toRole(BoaRoleInfo info) { + if (info == null) { + return null; + } + UserCurrentRole role = new UserCurrentRole(); + role.setRoleId(info.getRoleId()); + role.setRoleName(info.getRoleName()); + role.setSchId(info.getSchId()); + role.setSchName(info.getSchName()); + role.setChildId(info.getChildId()); + role.setChildName(info.getChildName()); + return role; + } + + /** 平台级默认身份:超管 roleId=0、schId=0(对齐各控制器 type==1 → schId=0 的既有约定) */ + private UserCurrentRole platformDefaultRole(Integer userId) { + UserCurrentRole role = new UserCurrentRole(); + role.setUserId(userId); + role.setRoleId(0); + role.setSchId(0); + return role; } }