/* * Copyright 2019-2020 Zheng Jie * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.zhengjie.modules.system.rest; import cn.hutool.core.collection.CollectionUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import me.zhengjie.annotation.AnonymousAccess; import me.zhengjie.annotation.Log; import me.zhengjie.config.RsaProperties; import me.zhengjie.modules.dm.user.domain.DmUser; import me.zhengjie.modules.dm.user.service.DmUserService; import me.zhengjie.modules.dm.user.service.dto.DmUserDto; import me.zhengjie.modules.system.domain.Dept; import me.zhengjie.modules.system.service.DataService; import me.zhengjie.modules.system.domain.User; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.system.domain.vo.UserPassVo; import me.zhengjie.modules.system.service.DeptService; import me.zhengjie.modules.system.service.RoleService; import me.zhengjie.modules.system.service.dto.RoleSmallDto; import me.zhengjie.modules.system.service.dto.UserDto; import me.zhengjie.modules.system.service.dto.UserQueryCriteria; import me.zhengjie.modules.system.service.VerifyService; import me.zhengjie.utils.*; import me.zhengjie.modules.system.service.UserService; import me.zhengjie.utils.enums.CodeEnum; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; /** * @author Zheng Jie * @date 2018-11-23 */ @Api(tags = "系统:用户管理") @RestController @RequestMapping("/api/users") @RequiredArgsConstructor public class UserController { private final PasswordEncoder passwordEncoder; private final UserService userService; private final DataService dataService; private final DeptService deptService; private final RoleService roleService; private final VerifyService verificationCodeService; private final DmUserService dmUserService; @ApiOperation("导出用户数据") @GetMapping(value = "/download") @PreAuthorize("@el.check('user:list')") public void download(HttpServletResponse response, UserQueryCriteria criteria) throws IOException { userService.download(userService.queryAll(criteria), response); } @ApiOperation("查询用户") @GetMapping @PreAuthorize("@el.check('user:list')") public ResponseEntity query(UserQueryCriteria criteria, Pageable pageable){ if (!ObjectUtils.isEmpty(criteria.getDeptId())) { criteria.getDeptIds().add(criteria.getDeptId()); criteria.getDeptIds().addAll(deptService.getDeptChildren(deptService.findByPid(criteria.getDeptId()))); } // 数据权限 List dataScopes = dataService.getDeptIds(userService.findByName(SecurityUtils.getCurrentUsername())); // criteria.getDeptIds() 不为空并且数据权限不为空则取交集 if (!CollectionUtils.isEmpty(criteria.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)){ // 取交集 criteria.getDeptIds().retainAll(dataScopes); if(!CollectionUtil.isEmpty(criteria.getDeptIds())){ return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK); } } else { // 否则取并集 criteria.getDeptIds().addAll(dataScopes); return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK); } return new ResponseEntity<>(PageUtil.toPage(null,0),HttpStatus.OK); } @Log("新增用户") @ApiOperation("新增用户") @PostMapping @PreAuthorize("@el.check('user:add')") public ResponseEntity create(@Validated @RequestBody User resources){ checkLevel(resources); // 默认密码 123456 /*resources.setPassword(passwordEncoder.encode("123456"));*/ resources.setPassword(passwordEncoder.encode(resources.getOrgPassword())); userService.create(resources); return new ResponseEntity<>(HttpStatus.CREATED); } @Log("修改用户") @ApiOperation("修改用户") @PutMapping @PreAuthorize("@el.check('user:edit')") public ResponseEntity update(@Validated(User.Update.class) @RequestBody User resources) throws Exception { checkLevel(resources); userService.update(resources); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @Log("修改用户:个人中心") @ApiOperation("修改用户:个人中心") @PutMapping(value = "center") public ResponseEntity center(@Validated(User.Update.class) @RequestBody User resources){ if(!resources.getId().equals(SecurityUtils.getCurrentUserId())){ throw new BadRequestException("不能修改他人资料"); } userService.updateCenter(resources); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @Log("删除用户") @ApiOperation("删除用户") @DeleteMapping @PreAuthorize("@el.check('user:del')") public ResponseEntity delete(@RequestBody Set ids){ for (String id : ids) { Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); Integer optLevel = Collections.min(roleService.findByUsersId(id).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); if (currentLevel > optLevel) { throw new BadRequestException("角色权限不足,不能删除:" + userService.findById(id).getUsername()); } } userService.delete(ids); return new ResponseEntity<>(HttpStatus.OK); } @ApiOperation("修改密码") @PostMapping(value = "/updatePass") public ResponseEntity updatePass(@RequestBody UserPassVo passVo) throws Exception { String oldPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getOldPass()); String newPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getNewPass()); UserDto user = userService.findByName(SecurityUtils.getCurrentUsername()); if(!passwordEncoder.matches(oldPass, user.getPassword())){ throw new BadRequestException("修改失败,旧密码错误"); } if(passwordEncoder.matches(newPass, user.getPassword())){ throw new BadRequestException("新密码不能与旧密码相同"); } userService.updatePass(user.getUsername(),passwordEncoder.encode(newPass)); return new ResponseEntity<>(HttpStatus.OK); } @ApiOperation("修改头像") @PostMapping(value = "/updateAvatar") public ResponseEntity updateAvatar(@RequestParam MultipartFile avatar){ return new ResponseEntity<>(userService.updateAvatar(avatar), HttpStatus.OK); } @Log("修改邮箱") @ApiOperation("修改邮箱") @PostMapping(value = "/updateEmail/{code}") public ResponseEntity updateEmail(@PathVariable String code,@RequestBody User user) throws Exception { String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,user.getPassword()); UserDto userDto = userService.findByName(SecurityUtils.getCurrentUsername()); if(!passwordEncoder.matches(password, userDto.getPassword())){ throw new BadRequestException("密码错误"); } verificationCodeService.validated(CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey() + user.getEmail(), code); userService.updateEmail(userDto.getUsername(),user.getEmail()); return new ResponseEntity<>(HttpStatus.OK); } /** * 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误 * @param resources / */ private void checkLevel(User resources) { Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); Integer optLevel = roleService.findByRoles(resources.getRoles()); if (currentLevel > optLevel) { throw new BadRequestException("角色权限不足"); } } @ApiOperation("解绑用户") @PostMapping(value = "/unBindDmUser") @Log("解绑账号用户") public ResponseEntity unBindDmUser(@RequestBody Set ids) throws Exception{ userService.unBindDmUser(ids); return new ResponseEntity<>(HttpStatus.OK); } }