package tech.powerjob.server.web.controller; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import tech.powerjob.common.exception.PowerJobException; import tech.powerjob.common.response.ResultDTO; import tech.powerjob.server.auth.Permission; import tech.powerjob.server.auth.PowerJobUser; import tech.powerjob.server.auth.Role; import tech.powerjob.server.auth.RoleScope; import tech.powerjob.common.enums.ErrorCodes; import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.interceptor.ApiPermission; import tech.powerjob.server.auth.service.WebAuthService; import tech.powerjob.server.auth.service.login.PowerJobLoginService; import tech.powerjob.common.enums.SwitchableStatus; import tech.powerjob.server.persistence.remote.model.AppInfoDO; import tech.powerjob.server.persistence.remote.model.NamespaceDO; import tech.powerjob.server.persistence.remote.model.UserInfoDO; import tech.powerjob.server.persistence.remote.repository.AppInfoRepository; import tech.powerjob.server.persistence.remote.repository.NamespaceRepository; import tech.powerjob.server.persistence.remote.repository.UserInfoRepository; import tech.powerjob.server.web.converter.NamespaceConverter; import tech.powerjob.server.web.converter.UserConverter; import tech.powerjob.server.web.request.ModifyUserInfoRequest; import tech.powerjob.server.web.request.QueryUserRequest; import tech.powerjob.server.web.response.AppBaseVO; import tech.powerjob.server.web.response.NamespaceBaseVO; import tech.powerjob.server.web.response.UserBaseVO; import tech.powerjob.server.web.response.UserDetailVO; import tech.powerjob.server.web.service.UserWebService; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.stream.Collectors; /** * 用户信息控制层 * * @author tjq * @since 2020/4/12 */ @Slf4j @RestController @RequestMapping("/user") public class UserInfoController { @Resource private UserWebService userWebService; @Resource private UserInfoRepository userInfoRepository; @Resource private PowerJobLoginService powerJobLoginService; @Resource private WebAuthService webAuthService; @Resource private NamespaceRepository namespaceRepository; @Resource private AppInfoRepository appInfoRepository; @SneakyThrows @PostMapping("/modify") public ResultDTO modifyUser(@RequestBody ModifyUserInfoRequest modifyUserInfoRequest, HttpServletRequest httpServletRequest) { Long userId = modifyUserInfoRequest.getId(); checkModifyUserPermission(userId, httpServletRequest); Optional userOpt = userInfoRepository.findById(userId); if (!userOpt.isPresent()) { throw new IllegalArgumentException("can't find user by userId:" + userId); } UserInfoDO dbUser = userOpt.get(); // 拷入允许修改的内容 if (StringUtils.isNotEmpty(modifyUserInfoRequest.getNick())) { dbUser.setNick(modifyUserInfoRequest.getNick()); } if (StringUtils.isNotEmpty(modifyUserInfoRequest.getPhone())) { dbUser.setPhone(modifyUserInfoRequest.getPhone()); } if (StringUtils.isNotEmpty(modifyUserInfoRequest.getEmail())) { dbUser.setEmail(modifyUserInfoRequest.getEmail()); } if (StringUtils.isNotEmpty(modifyUserInfoRequest.getWebHook())) { dbUser.setWebHook(modifyUserInfoRequest.getWebHook()); } if (StringUtils.isNotEmpty(modifyUserInfoRequest.getExtra())) { dbUser.setExtra(modifyUserInfoRequest.getExtra()); } dbUser.setGmtModified(new Date()); userInfoRepository.saveAndFlush(dbUser); return ResultDTO.success(null); } @GetMapping("/list") public ResultDTO> list(@RequestParam(required = false) String name) { List result; if (StringUtils.isEmpty(name)) { result = userInfoRepository.findAll(); }else { result = userInfoRepository.findByUsernameLike("%" + name + "%"); } return ResultDTO.success(convert(result)); } /** * 查询用户信息(用于管理员操作,会返回敏感信息) * @param queryUserRequest 查询请求 * @return 响应 */ @PostMapping("/query") @ApiPermission(name = "User-Query", roleScope = RoleScope.GLOBAL, requiredPermission = Permission.SU) public ResultDTO> query(@RequestBody QueryUserRequest queryUserRequest) { List userInfoDos = userWebService.list(queryUserRequest); List userBaseVOS = userInfoDos.stream().map(x -> UserConverter.do2BaseVo(x, true)).collect(Collectors.toList()); return ResultDTO.success(userBaseVOS); } @GetMapping("/detail") public ResultDTO getUserDetail(HttpServletRequest httpServletRequest) { Optional powerJobUserOpt = powerJobLoginService.ifLogin(httpServletRequest); if (!powerJobUserOpt.isPresent()) { throw new PowerJobAuthException(ErrorCodes.USER_NOT_LOGIN); } Optional userinfoDoOpt = userInfoRepository.findById(powerJobUserOpt.get().getId()); if (!userinfoDoOpt.isPresent()) { throw new IllegalArgumentException("can't find user by id: " + powerJobUserOpt.get().getId()); } UserDetailVO userDetailVO = new UserDetailVO(); BeanUtils.copyProperties(userinfoDoOpt.get(), userDetailVO); userDetailVO.genShowName(); // 权限信息 Map> globalPermissions = webAuthService.fetchMyPermissionTargets(RoleScope.GLOBAL); userDetailVO.setGlobalRoles(globalPermissions.keySet().stream().map(Enum::name).collect(Collectors.toList())); Map> namespacePermissions = webAuthService.fetchMyPermissionTargets(RoleScope.NAMESPACE); List nsList = namespaceRepository.findAllByIdIn(mergeIds(namespacePermissions)); Map id2NamespaceDo = Maps.newHashMap(); nsList.forEach(x -> id2NamespaceDo.put(x.getId(), x)); Map> role2NamespaceBaseVo = Maps.newHashMap(); namespacePermissions.forEach((k, v) -> { List namespaceBaseVOS = Lists.newArrayList(); role2NamespaceBaseVo.put(k.name(), namespaceBaseVOS); v.forEach(nId -> { NamespaceDO namespaceDO = id2NamespaceDo.get(nId); if (namespaceDO == null) { return; } NamespaceBaseVO namespaceBaseVO = NamespaceConverter.do2BaseVo(namespaceDO); namespaceBaseVOS.add(namespaceBaseVO); }); }); userDetailVO.setRole2NamespaceList(role2NamespaceBaseVo); Map> appPermissions = webAuthService.fetchMyPermissionTargets(RoleScope.APP); List appList = appInfoRepository.findAllByIdIn(mergeIds(appPermissions)); Map id2AppInfo = Maps.newHashMap(); appList.forEach(x -> id2AppInfo.put(x.getId(), x)); Map> role2AppBaseVo = Maps.newHashMap(); appPermissions.forEach((k, v) -> { List appBaseVOS = Lists.newArrayList(); role2AppBaseVo.put(k.name(), appBaseVOS); v.forEach(nId -> { AppInfoDO appInfoDO = id2AppInfo.get(nId); if (appInfoDO == null) { return; } AppBaseVO appBaseVO = new AppBaseVO(); BeanUtils.copyProperties(appInfoDO, appBaseVO); appBaseVOS.add(appBaseVO); }); }); userDetailVO.setRole2AppList(role2AppBaseVo); return ResultDTO.success(userDetailVO); } @PostMapping("/disable") public ResultDTO disableUser(Long uid, HttpServletRequest httpServletRequest) { changeAccountStatus(uid, SwitchableStatus.DISABLE, httpServletRequest); return ResultDTO.success(null); } @PostMapping("/enable") public ResultDTO enableUser(Long uid, HttpServletRequest httpServletRequest) { changeAccountStatus(uid, SwitchableStatus.ENABLE, httpServletRequest); return ResultDTO.success(null); } private void changeAccountStatus(Long uid, SwitchableStatus targetStatus, HttpServletRequest httpServletRequest) { checkModifyUserPermission(uid, httpServletRequest); Optional userOpt = userInfoRepository.findById(uid); if (!userOpt.isPresent()) { throw new IllegalArgumentException("can't find user by userId:" + uid); } UserInfoDO dbUser = userOpt.get(); dbUser.setStatus(targetStatus.getV()); dbUser.setGmtModified(new Date()); userInfoRepository.saveAndFlush(dbUser); log.info("[UserInfoController] changeAccountStatus, userId={},targetStatus={}", uid, targetStatus); } /** * 检查针对 user 处理的权限 * @param uid 目标 userId * @param httpServletRequest http 上下文请求 */ private void checkModifyUserPermission(Long uid, HttpServletRequest httpServletRequest) { Optional powerJobUserOpt = powerJobLoginService.ifLogin(httpServletRequest); if (!powerJobUserOpt.isPresent()) { throw new PowerJobAuthException(ErrorCodes.USER_NOT_LOGIN); } PowerJobUser currentLoginUser = powerJobUserOpt.get(); boolean myself = uid.equals(currentLoginUser.getId()); boolean globalAdmin = webAuthService.isGlobalAdmin(); if (myself || globalAdmin) { return; } throw new PowerJobException("Only the administrator and account owner can modify the account"); } private static List convert(List data) { if (CollectionUtils.isEmpty(data)) { return Lists.newLinkedList(); } return data.stream().map(x -> UserConverter.do2BaseVo(x, false)).collect(Collectors.toList()); } private static Set mergeIds(Map> map) { Set ids = Sets.newHashSet(); map.values().forEach(ids::addAll); return ids; } }