package com.zl.mjga.service; import static org.jooq.generated.mjga.tables.Permission.PERMISSION; import static org.jooq.generated.mjga.tables.Role.ROLE; import static org.jooq.generated.mjga.tables.User.USER; import com.zl.mjga.dto.PageRequestDto; import com.zl.mjga.dto.PageResponseDto; import com.zl.mjga.dto.department.DepartmentBindDto; import com.zl.mjga.dto.position.PositionBindDto; import com.zl.mjga.dto.urp.*; import com.zl.mjga.exception.BusinessException; import com.zl.mjga.model.urp.ERole; import com.zl.mjga.repository.*; import java.util.*; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.jooq.Record; import org.jooq.Result; import org.jooq.generated.mjga.tables.pojos.*; import org.jspecify.annotations.Nullable; import org.springframework.beans.BeanUtils; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Slf4j @RequiredArgsConstructor public class IdentityAccessService { private final UserRepository userRepository; private final RoleRepository roleRepository; private final UserRoleMapRepository userRoleMapRepository; private final PermissionRepository permissionRepository; private final RolePermissionMapRepository rolePermissionMapRepository; private final UserDepartmentMapRepository userDepartmentMapRepository; private final UserPositionMapRepository userPositionMapRepository; private final PasswordEncoder passwordEncoder; public void upsertUser(UserUpsertDto userUpsertDto) { User user = new User(); BeanUtils.copyProperties(userUpsertDto, user); if (StringUtils.isNotEmpty(userUpsertDto.getPassword())) { user.setPassword(passwordEncoder.encode(userUpsertDto.getPassword())); } userRepository.mergeWithoutNullFieldBy(user); } public void upsertRole(RoleUpsertDto roleUpsertDto) { Role role = new Role(); BeanUtils.copyProperties(roleUpsertDto, role); roleRepository.merge(role); } public void upsertPermission(PermissionUpsertDto permissionUpsertDto) { Permission permission = new Permission(); BeanUtils.copyProperties(permissionUpsertDto, permission); permissionRepository.merge(permission); } public PageResponseDto> pageQueryUser( PageRequestDto pageRequestDto, UserQueryDto userQueryDto) { Result userRecords = userRepository.pageFetchBy(pageRequestDto, userQueryDto); if (userRecords.isEmpty()) { return PageResponseDto.empty(); } List userRolePermissionDtoList = userRecords.stream() .map((record) -> queryUniqueUserWithRolePermission(record.getValue(USER.ID))) .toList(); return new PageResponseDto<>( userRecords.get(0).getValue("total_user", Integer.class), userRolePermissionDtoList); } public @Nullable UserRolePermissionDto queryUniqueUserWithRolePermission(Long userId) { return userRepository.fetchUniqueUserDtoWithNestedRolePermissionBy(userId); } public PageResponseDto> pageQueryRole( PageRequestDto pageRequestDto, RoleQueryDto roleQueryDto) { Result roleRecords = roleRepository.pageFetchBy(pageRequestDto, roleQueryDto); if (roleRecords.isEmpty()) { return PageResponseDto.empty(); } List roleRespDtoList = roleRecords.stream() .map( record -> { return RoleRespDto.builder() .id(record.getValue("id", Long.class)) .code(record.getValue("code", String.class)) .name(record.getValue("name", String.class)) .isBound( record.field("is_bound", Boolean.class) != null ? record.getValue("is_bound", Boolean.class) : null) .permissions(record.getValue("permissions", List.class)) .build(); }) .toList(); return new PageResponseDto<>( roleRecords.get(0).getValue("total_role", Integer.class), roleRespDtoList); } public @Nullable RoleRespDto queryUniqueRoleWithPermission(Long roleId) { Result roleWithPermissionRecords = roleRepository.fetchUniqueRoleWithPermission(roleId); if (roleWithPermissionRecords.isEmpty()) { return null; } RoleRespDto roleRespDto = createRbacDtoRolePart(roleWithPermissionRecords); setCurrentRolePermission(roleRespDto, roleWithPermissionRecords); return roleRespDto; } public PageResponseDto> pageQueryPermission( PageRequestDto pageRequestDto, PermissionQueryDto permissionQueryDto) { Result permissionRecords = permissionRepository.pageFetchBy(pageRequestDto, permissionQueryDto); if (permissionRecords.isEmpty()) { return PageResponseDto.empty(); } List permissionRespDtoList = permissionRecords.stream() .map( record -> PermissionRespDto.builder() .id(record.getValue("id", Long.class)) .name(record.getValue("name", String.class)) .code(record.getValue("code", String.class)) .isBound( record.field("is_bound", Boolean.class) != null ? record.getValue("is_bound", Boolean.class) : null) .build()) .toList(); return new PageResponseDto<>( permissionRecords.get(0).getValue("total_permission", Integer.class), permissionRespDtoList); } public void bindPermissionBy(Long roleId, List permissionIdList) { List permissionMapList = permissionIdList.stream() .map( (permissionId -> { RolePermissionMap rolePermissionMap = new RolePermissionMap(); rolePermissionMap.setRoleId(roleId); rolePermissionMap.setPermissionId(permissionId); return rolePermissionMap; })) .collect(Collectors.toList()); rolePermissionMapRepository.merge(permissionMapList); } public void unBindPermissionBy(Long roleId, List permissionIdList) { if (CollectionUtils.isEmpty(permissionIdList)) { return; } rolePermissionMapRepository.deleteBy(roleId, permissionIdList); } public void unBindRoleToUser(Long userId, List roleIdList) { if (CollectionUtils.isEmpty(roleIdList)) { return; } List roles = roleRepository.selectByRoleIdIn(roleIdList); if (CollectionUtils.isEmpty(roles)) { throw new BusinessException("unbind role not exist"); } userRoleMapRepository.deleteBy(userId, roleIdList); } public void bindRoleToUser(Long userId, List roleIdList) { List userRoleMapList = roleIdList.stream() .map( (roleId -> { UserRoleMap userRoleMap = new UserRoleMap(); userRoleMap.setUserId(userId); userRoleMap.setRoleId(roleId); return userRoleMap; })) .collect(Collectors.toList()); userRoleMapRepository.merge(userRoleMapList); } @Transactional(rollbackFor = Throwable.class) public void bindRoleModuleToUser(Long userId, List eRoleList) { bindRoleToUser( userId, roleRepository .selectByRoleCodeIn(eRoleList.stream().map(Enum::name).collect(Collectors.toList())) .stream() .map(Role::getId) .toList()); } private void setCurrentRolePermission(RoleRespDto roleRespDto, List roleResult) { if (roleResult.get(0).getValue(PERMISSION.ID) != null) { roleResult.forEach( (record) -> { PermissionRespDto permissionRespDto = createRbacDtoPermissionPart(record); roleRespDto.getPermissions().add(permissionRespDto); }); } } private PermissionRespDto createRbacDtoPermissionPart(Record record) { PermissionRespDto permissionRespDto = new PermissionRespDto(); permissionRespDto.setId(record.getValue(PERMISSION.ID)); permissionRespDto.setCode(record.getValue(PERMISSION.CODE)); permissionRespDto.setName(record.getValue(PERMISSION.NAME)); return permissionRespDto; } private RoleRespDto createRbacDtoRolePart(List roleResult) { RoleRespDto roleRespDto = new RoleRespDto(); roleRespDto.setId(roleResult.get(0).getValue(ROLE.ID)); roleRespDto.setCode(roleResult.get(0).getValue(ROLE.CODE)); roleRespDto.setName(roleResult.get(0).getValue(ROLE.NAME)); return roleRespDto; } public boolean isRoleDuplicate(String roleCode, String name) { return roleRepository.fetchOneByCode(roleCode) != null || roleRepository.fetchOneByName(name) != null; } public boolean isUsernameDuplicate(String username) { return userRepository.fetchOneByUsername(username) != null; } public boolean isPermissionDuplicate(String code, String name) { return permissionRepository.fetchOneByCode(code) != null || permissionRepository.fetchOneByName(name) != null; } @Transactional(rollbackFor = Throwable.class) public void bindDepartmentBy(DepartmentBindDto departmentBindDto) { List userDepartmentMaps = departmentBindDto.departmentIds().stream() .map( (departmentId) -> { UserDepartmentMap userDepartmentMap = new UserDepartmentMap(); userDepartmentMap.setUserId(departmentBindDto.userId()); userDepartmentMap.setDepartmentId(departmentId); return userDepartmentMap; }) .toList(); userDepartmentMapRepository.merge(userDepartmentMaps); } @Transactional(rollbackFor = Throwable.class) public void unBindDepartmentBy(DepartmentBindDto departmentBindDto) { for (Long departmentId : departmentBindDto.departmentIds()) { UserDepartmentMap userDepartmentMap = new UserDepartmentMap(); userDepartmentMap.setUserId(departmentBindDto.userId()); userDepartmentMap.setDepartmentId(departmentId); userDepartmentMapRepository.delete(userDepartmentMap); } } @Transactional(rollbackFor = Throwable.class) public void bindPositionBy(PositionBindDto positionBindDto) { List userPositionMaps = positionBindDto.positionIds().stream() .map( (positionId) -> { UserPositionMap userPositionMap = new UserPositionMap(); userPositionMap.setUserId(positionBindDto.userId()); userPositionMap.setPositionId(positionId); return userPositionMap; }) .toList(); userPositionMapRepository.merge(userPositionMaps); } @Transactional(rollbackFor = Throwable.class) public void unBindPositionBy(PositionBindDto positionBindDto) { for (Long positionId : positionBindDto.positionIds()) { UserPositionMap userPositionMap = new UserPositionMap(); userPositionMap.setUserId(positionBindDto.userId()); userPositionMap.setPositionId(positionId); userPositionMapRepository.delete(userPositionMap); } } }