├── src ├── main │ ├── resources │ │ ├── db │ │ │ └── data │ │ │ │ ├── im_role.sql │ │ │ │ ├── im_user_role.sql │ │ │ │ ├── im_friend.sql │ │ │ │ └── im_user.sql │ │ ├── spy.properties │ │ └── application-quartz.yml │ └── java │ │ └── com │ │ └── libre │ │ └── im │ │ ├── system │ │ ├── package-info.java │ │ ├── constant │ │ │ ├── RoleConstants.java │ │ │ ├── MenuConstants.java │ │ │ └── UserConstants.java │ │ ├── mapper │ │ │ ├── ClientMapper.java │ │ │ ├── SysMenuMapper.java │ │ │ ├── SysDeptMapper.java │ │ │ ├── SysPostMapper.java │ │ │ ├── SysRoleMapper.java │ │ │ ├── SysUserMapper.java │ │ │ ├── RoleDeptMapper.java │ │ │ ├── RoleMenuMapper.java │ │ │ ├── UserPostMapper.java │ │ │ ├── UserRoleMapper.java │ │ │ ├── SysDictInfoMapper.java │ │ │ └── SysDictMapper.java │ │ ├── pojo │ │ │ ├── dto │ │ │ │ ├── DictCriteria.java │ │ │ │ ├── DictInfoCriteria.java │ │ │ │ ├── MenuCriteria.java │ │ │ │ ├── RoleCriteria.java │ │ │ │ ├── DeptCriteria.java │ │ │ │ ├── RoleMenuDTO.java │ │ │ │ ├── UserCriteria.java │ │ │ │ ├── RoleDTO.java │ │ │ │ ├── UserDTO.java │ │ │ │ └── MenuDTO.java │ │ │ ├── vo │ │ │ │ ├── MenuMetaVO.java │ │ │ │ ├── RoleVO.java │ │ │ │ ├── DeptVO.java │ │ │ │ ├── MenuVO.java │ │ │ │ ├── TokenVO.java │ │ │ │ └── UserVO.java │ │ │ ├── entity │ │ │ │ ├── SysDict.java │ │ │ │ ├── SysRoleDept.java │ │ │ │ ├── SysUserPost.java │ │ │ │ ├── SysUserRole.java │ │ │ │ ├── SysRoleMenu.java │ │ │ │ ├── SysDept.java │ │ │ │ ├── SysPost.java │ │ │ │ ├── SysDictInfo.java │ │ │ │ ├── SysRole.java │ │ │ │ ├── SysUser.java │ │ │ │ └── Client.java │ │ │ └── SysMenu.java │ │ ├── service │ │ │ ├── ClientService.java │ │ │ ├── MonitorService.java │ │ │ ├── SysRoleDeptService.java │ │ │ ├── SysPostService.java │ │ │ ├── impl │ │ │ │ ├── ClientServiceImpl.java │ │ │ │ ├── SysRoleDeptServiceImpl.java │ │ │ │ ├── UserPostServiceImpl.java │ │ │ │ ├── SysPostServiceImpl.java │ │ │ │ ├── SysDictInfoServiceImpl.java │ │ │ │ ├── SysRoleMenuServiceImpl.java │ │ │ │ ├── SysUserRoleServiceImpl.java │ │ │ │ └── SysDictServiceImpl.java │ │ │ ├── SysUserPostService.java │ │ │ ├── mapstruct │ │ │ │ ├── SysMenuMapping.java │ │ │ │ ├── SysUserMapping.java │ │ │ │ └── SysRoleMapping.java │ │ │ ├── SysDictService.java │ │ │ ├── SysRoleMenuService.java │ │ │ ├── SysDictInfoService.java │ │ │ ├── SysMenuService.java │ │ │ ├── SysDeptService.java │ │ │ ├── SysUserRoleService.java │ │ │ ├── SysRoleService.java │ │ │ └── SysUserService.java │ │ ├── enums │ │ │ └── MenuType.java │ │ ├── controller │ │ │ ├── MonitorController.java │ │ │ ├── SysDeptController.java │ │ │ ├── SysDictController.java │ │ │ └── SysUserController.java │ │ └── toolkit │ │ │ └── MenuUtil.java │ │ ├── common │ │ ├── constant │ │ │ ├── package-info.java │ │ │ ├── CacheConstants.java │ │ │ └── LibreConstants.java │ │ ├── security │ │ │ ├── constant │ │ │ │ └── SecurityConstant.java │ │ │ ├── dto │ │ │ │ ├── RoleInfo.java │ │ │ │ ├── JwtUser.java │ │ │ │ └── AuthUser.java │ │ │ └── support │ │ │ │ ├── SecurityUtil.java │ │ │ │ └── AuthenticationHandler.java │ │ ├── result │ │ │ └── ApiCode.java │ │ ├── config │ │ │ ├── PostgresDdl.java │ │ │ ├── DdlConfiguration.java │ │ │ └── MybatisPlusMetaObjectHandler.java │ │ ├── mapstruct │ │ │ └── BooleanAndIntegerFormat.java │ │ ├── pojo │ │ │ ├── BaseCriteria.java │ │ │ └── BaseEntity.java │ │ └── exception │ │ │ └── GlobalExceptionAdvice.java │ │ ├── websocket │ │ ├── config │ │ │ ├── package-info.java │ │ │ ├── WebsocketServerProperties.java │ │ │ ├── LibreIMExceptionAdvice.java │ │ │ └── WebSocketServerConfiguration.java │ │ ├── mapper │ │ │ ├── package-info.java │ │ │ ├── FriendMapper.java │ │ │ ├── MessageMapper.java │ │ │ └── ConversationMapper.java │ │ ├── service │ │ │ ├── package-info.java │ │ │ ├── FriendService.java │ │ │ ├── MessageService.java │ │ │ ├── mapstruct │ │ │ │ ├── UserMapping.java │ │ │ │ └── FriendMapping.java │ │ │ ├── ConversationService.java │ │ │ └── impl │ │ │ │ ├── MessageServiceImpl.java │ │ │ │ └── FriendServiceImpl.java │ │ ├── controller │ │ │ ├── package-info.java │ │ │ ├── LibreUserController.java │ │ │ ├── FriendController.java │ │ │ └── ConversationController.java │ │ ├── core │ │ │ ├── codec │ │ │ │ ├── MessageCodec.java │ │ │ │ ├── ProtobufMessageDecoder.java │ │ │ │ ├── JacksonMessageEncoder.java │ │ │ │ ├── ProtobufMessageEncoder.java │ │ │ │ └── JacksonMessageDecoder.java │ │ │ ├── message │ │ │ │ ├── MessageSendListener.java │ │ │ │ ├── MediaMessage.java │ │ │ │ ├── TextMessage.java │ │ │ │ ├── enums │ │ │ │ │ ├── ConnectType.java │ │ │ │ │ ├── MessageStatus.java │ │ │ │ │ └── MessageBodyType.java │ │ │ │ ├── handler │ │ │ │ │ ├── MessageHandler.java │ │ │ │ │ ├── MessageHandlerFactory.java │ │ │ │ │ ├── MediaMessageHandler.java │ │ │ │ │ └── AbstractMessageHandler.java │ │ │ │ ├── Message.java │ │ │ │ ├── MessageFactory.java │ │ │ │ ├── MessageListener.java │ │ │ │ └── MessagePublisher.java │ │ │ ├── handler │ │ │ │ └── WebSocketServerHandler.java │ │ │ ├── proto │ │ │ │ └── TextMessage.proto │ │ │ ├── exception │ │ │ │ └── LibreImException.java │ │ │ ├── constant │ │ │ │ └── LibreIMConstants.java │ │ │ ├── session │ │ │ │ ├── AbstractSessionManager.java │ │ │ │ ├── Session.java │ │ │ │ ├── SessionManager.java │ │ │ │ ├── WebsocketSession.java │ │ │ │ ├── RedissonSessionManager.java │ │ │ │ ├── AbstractSession.java │ │ │ │ └── DefaultSessionManager.java │ │ │ └── mapstruct │ │ │ │ └── MessageMapping.java │ │ ├── constant │ │ │ ├── MessageConstant.java │ │ │ └── CacheKey.java │ │ └── pojo │ │ │ ├── ChatMessage.java │ │ │ ├── vo │ │ │ ├── UserVO.java │ │ │ ├── ConversationVO.java │ │ │ └── FriendVO.java │ │ │ ├── Friend.java │ │ │ ├── LibreUser.java │ │ │ └── Conversation.java │ │ ├── tookit │ │ ├── moudle │ │ │ ├── file │ │ │ │ ├── service │ │ │ │ │ ├── FileService.java │ │ │ │ │ ├── OssServiceImpl.java │ │ │ │ │ └── LocalFileServiceImpl.java │ │ │ │ └── controller │ │ │ │ │ └── SysFileController.java │ │ │ ├── quartz │ │ │ │ ├── mapper │ │ │ │ │ ├── SysJobMapper.java │ │ │ │ │ └── SysJobLogMapper.java │ │ │ │ ├── constant │ │ │ │ │ └── JobStatus.java │ │ │ │ ├── TestJob.java │ │ │ │ ├── pojo │ │ │ │ │ ├── SysJobCriteria.java │ │ │ │ │ ├── SysJobLog.java │ │ │ │ │ ├── SysJob.java │ │ │ │ │ └── SysJobVO.java │ │ │ │ ├── annotation │ │ │ │ │ └── ScheduleTask.java │ │ │ │ ├── service │ │ │ │ │ └── SysJobService.java │ │ │ │ ├── support │ │ │ │ │ ├── ScheduleJob.java │ │ │ │ │ └── ScheduleJobListener.java │ │ │ │ └── controller │ │ │ │ │ └── SysJobController.java │ │ │ └── email │ │ │ │ ├── mapper │ │ │ │ └── EMailConfigMapper.java │ │ │ │ ├── service │ │ │ │ └── EmailService.java │ │ │ │ └── pojo │ │ │ │ ├── SysFile.java │ │ │ │ └── MailConfig.java │ │ └── common │ │ │ └── SysJobConstant.java │ │ ├── log │ │ ├── support │ │ │ ├── SysLogType.java │ │ │ ├── SysLogConstant.java │ │ │ ├── SysLogMapping.java │ │ │ ├── ReflectionUtil.java │ │ │ ├── SysLogEvent.java │ │ │ ├── SysLogListener.java │ │ │ └── SysLogUtil.java │ │ ├── mapper │ │ │ └── SysLogMapper.java │ │ ├── annotation │ │ │ └── ApiLog.java │ │ ├── pojo │ │ │ └── SysLogCriteria.java │ │ ├── service │ │ │ ├── SysLogService.java │ │ │ └── impl │ │ │ │ └── SysLogServiceImpl.java │ │ └── controller │ │ │ └── SysLogController.java │ │ ├── security │ │ ├── service │ │ │ └── UserLockService.java │ │ ├── pojo │ │ │ ├── dto │ │ │ │ ├── AuthUserDTO.java │ │ │ │ ├── UserInfo.java │ │ │ │ └── OnlineUserDTO.java │ │ │ ├── DeptInfo.java │ │ │ ├── PostInfo.java │ │ │ └── vo │ │ │ │ └── TokenVO.java │ │ ├── auth │ │ │ ├── SecWebAuthDetailsSource.java │ │ │ ├── SecWebAuthenticationDetails.java │ │ │ └── AuthUserArgumentResolver.java │ │ ├── config │ │ │ └── LibreWebMvcConfiguration.java │ │ └── controller │ │ │ ├── AuthTokenController.java │ │ │ └── AuthorizationController.java │ │ └── LibreImApplication.java └── test │ └── java │ └── com │ └── libre │ └── im │ ├── PasswordTests.java │ └── MessageCodecTests.java ├── README.md └── .gitignore /src/main/resources/db/data/im_role.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO im_role (id, role_name, title) VALUES (1, 'admin', null); 2 | -------------------------------------------------------------------------------- /src/main/resources/db/data/im_user_role.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO im_user_role (id, user_id, role_id) VALUES (1, 1, 1); 2 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ZC 3 | * @date 2021/8/8 20:00 4 | */ 5 | package com.libre.im.system; 6 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/constant/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Libre 3 | * @date 2021/7/11 19:46 4 | */ 5 | package com.libre.im.common.constant; 6 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/config/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ZC 3 | * @date 2021/8/8 20:00 4 | */ 5 | package com.libre.im.websocket.config; 6 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/mapper/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ZC 3 | * @date 2021/8/8 19:58 4 | */ 5 | package com.libre.im.websocket.mapper; 6 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/service/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ZC 3 | * @date 2021/8/8 19:58 4 | */ 5 | package com.libre.im.websocket.service; 6 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/controller/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ZC 3 | * @date 2021/8/8 19:58 4 | */ 5 | package com.libre.im.websocket.controller; 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Libre-IM 2 | [![OSCS Status](https://www.oscs1024.com/platform/badge/zc-libre/Libre-IM.svg?size=small)](https://www.oscs1024.com/project/zc-libre/Libre-IM?ref=badge_small) 3 | 4 | 基于netty实时聊天系统 5 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/file/service/FileService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.file.service; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/12/30 8:43 PM 6 | */ 7 | public interface FileService { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/support/SysLogType.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.support; 2 | 3 | /** 4 | * 系统日志类型 5 | * 6 | * @author L.cm 7 | */ 8 | public enum SysLogType { 9 | 10 | /** 11 | * 日志类型,登陆、登出、接口 12 | */ 13 | Login, Logout, Api; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/support/SysLogConstant.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.support; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/12/17 7:10 PM 6 | */ 7 | public interface SysLogConstant { 8 | 9 | Integer SUCCESS = 0; 10 | 11 | Integer FAILED = 1; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/codec/MessageCodec.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.codec; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/5/1 7:36 AM 6 | */ 7 | public interface MessageCodec { 8 | 9 | void encode(); 10 | 11 | void decode(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/common/SysJobConstant.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.common; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/12/30 10:47 PM 6 | */ 7 | public interface SysJobConstant { 8 | 9 | Integer JOB_SUCCESS = 1; 10 | 11 | Integer JOB_FAILED = 0; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/db/data/im_friend.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO im_friend (id, friend_id, user_id, add_time, is_top, update_time) VALUES (1, 2, 1, '2022-06-21 22:16:16.000000', null, null); 2 | INSERT INTO im_friend (id, friend_id, user_id, add_time, is_top, update_time) VALUES (2, 3, 1, '2022-06-21 22:16:18.000000', null, null); 3 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/constant/RoleConstants.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.constant; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/8/27 12:11 PM 6 | */ 7 | public interface RoleConstants { 8 | 9 | /** 10 | * 角色是否启用 11 | */ 12 | Integer ROLE_ENABLE = 1; 13 | 14 | Integer ROLE_DISABLE = 0; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/ClientMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.Client; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface ClientMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/SysMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.SysMenu; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface SysMenuMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/DictCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 字典查询 7 | * 8 | * @author L.cm 9 | */ 10 | @Data 11 | public class DictCriteria { 12 | 13 | /** 14 | * 模糊查询:name,description 15 | */ 16 | private String blurry; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/SysDeptMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysDept; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface SysDeptMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/SysPostMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysPost; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface SysPostMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/SysRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysRole; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface SysRoleMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/SysUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysUser; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface SysUserMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/ClientService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.system.pojo.entity.Client; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface ClientService extends IService { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/file/service/OssServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.file.service; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2023/1/8 4:43 AM 8 | */ 9 | @Service 10 | public class OssServiceImpl implements FileService { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/constant/CacheConstants.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.constant; 2 | 3 | /** 4 | * @author Libre 5 | * @date 2022/1/1 18:39 6 | */ 7 | public interface CacheConstants { 8 | 9 | /** 10 | * 用户缓存名 11 | */ 12 | String SYS_USER_CACHE = "user"; 13 | 14 | String SYS_ROLE_CACHE = "role"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/mapper/SysLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.log.pojo.SysLog; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2022/12/17 6:04 PM 9 | */ 10 | public interface SysLogMapper extends BaseMapper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/RoleDeptMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysRoleDept; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface RoleDeptMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/RoleMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysRoleMenu; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface RoleMenuMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/UserPostMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysUserPost; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface UserPostMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/UserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysUserRole; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface UserRoleMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/constant/LibreConstants.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.constant; 2 | 3 | /** 4 | * @author Libre 5 | * @date 2021/7/12 19:25 6 | */ 7 | public interface LibreConstants { 8 | 9 | /** 10 | * 状态:0正常 11 | */ 12 | int STATUS_ON = 1; 13 | 14 | Integer DISABLE = 0; 15 | 16 | Integer ENABLE = 1; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/MonitorService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2023/1/8 12:09 AM 8 | */ 9 | public interface MonitorService { 10 | 11 | Map getServerInfo(); 12 | 13 | Map getRedisStat(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysRoleDeptService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.system.pojo.entity.SysRoleDept; 5 | 6 | /** 7 | * @author zhao.cheng 8 | */ 9 | public interface SysRoleDeptService extends IService { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/service/UserLockService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.service; 2 | 3 | import com.libre.im.common.security.dto.AuthUser; 4 | 5 | public interface UserLockService { 6 | 7 | /** 8 | * 锁定用户 9 | * @param authUser AuthUser 10 | * @return {boolean} 11 | */ 12 | boolean updateLockUser(AuthUser authUser); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/pojo/dto/AuthUserDTO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.pojo.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | 8 | @Getter 9 | @Setter 10 | public class AuthUserDTO { 11 | 12 | @NotBlank 13 | private String username; 14 | 15 | @NotBlank 16 | private String password; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/DictInfoCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 字典类型查询 7 | * 8 | * @author L.cm 9 | */ 10 | @Data 11 | public class DictInfoCriteria { 12 | 13 | /** 14 | * LIKE 15 | */ 16 | private String label; 17 | 18 | /** 19 | * dict name 20 | */ 21 | private String name; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/constant/MessageConstant.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.constant; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/6/21 10:02 PM 6 | */ 7 | public interface MessageConstant { 8 | 9 | /** 10 | * 未读消息 11 | */ 12 | Integer UNREAD = 0; 13 | 14 | /** 15 | * 已读消息 16 | */ 17 | Integer READ = 1; 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/MessageSendListener.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message; 2 | 3 | import org.springframework.context.event.EventListener; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2022/4/30 2:29 AM 8 | */ 9 | public class MessageSendListener { 10 | 11 | @EventListener 12 | public void textMessageSend() { 13 | 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/mapper/SysJobMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.tookit.moudle.quartz.pojo.SysJob; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2022/12/30 9:19 PM 9 | */ 10 | public interface SysJobMapper extends BaseMapper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/constant/CacheKey.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.constant; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/5/30 12:15 AM 6 | */ 7 | public interface CacheKey { 8 | 9 | String CACHE_KEY_PREFIX = "libre:im:"; 10 | String USER_CACHE_KEY = CACHE_KEY_PREFIX + "user"; 11 | String FRIEND_CACHE_KEY = CACHE_KEY_PREFIX + "friend"; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/security/constant/SecurityConstant.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.security.constant; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/8/27 9:13 PM 6 | */ 7 | public interface SecurityConstant { 8 | 9 | String PASSWORD_PREFIX = "{bcrypt}"; 10 | 11 | /** 12 | * 是否管理员 13 | */ 14 | Integer IS_ADMIN_YES = 1; 15 | 16 | Integer IS_ADMIN_NO = 0; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/constant/MenuConstants.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.constant; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/8/30 1:30 AM 6 | */ 7 | public interface MenuConstants { 8 | 9 | Integer IS_FRAME_YES = 1; 10 | 11 | Integer IS_FRAME_NO = 0; 12 | 13 | /** 14 | * 是否隐藏 15 | */ 16 | Integer IS_HIDDEN_YES = 1; 17 | 18 | Integer IS_HIDDEN_NO = 0; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/email/mapper/EMailConfigMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.email.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.tookit.moudle.email.pojo.MailConfig; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2023/1/12 1:31 AM 9 | */ 10 | public interface EMailConfigMapper extends BaseMapper { 11 | 12 | } -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/mapper/SysJobLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.tookit.moudle.quartz.pojo.SysJobLog; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2022/12/30 10:42 PM 9 | */ 10 | public interface SysJobLogMapper extends BaseMapper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/enums/MenuType.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2022/12/31 5:26 PM 9 | */ 10 | @Getter 11 | @AllArgsConstructor 12 | public enum MenuType { 13 | 14 | DIRECTORY(0), 15 | 16 | MENU(1), 17 | 18 | BUTTON(2),; 19 | 20 | private final Integer type; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/file/controller/SysFileController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.file.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2023/1/18 12:08 AM 9 | */ 10 | @RestController 11 | @RequiredArgsConstructor 12 | public class SysFileController { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/file/service/LocalFileServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.file.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.stereotype.Service; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2023/1/18 12:03 AM 9 | */ 10 | @Service 11 | @RequiredArgsConstructor 12 | public class LocalFileServiceImpl implements FileService { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/mapper/FriendMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.websocket.pojo.Friend; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author: Libre 9 | * @Date: 2022/5/3 2:49 AM 10 | */ 11 | @Mapper 12 | public interface FriendMapper extends BaseMapper { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/SysDictInfoMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.system.pojo.entity.SysDictInfo; 5 | 6 | /** 7 | *

8 | * 字典详情表 Mapper 接口 9 | *

10 | * 11 | * @author L.cm 12 | * @since 2020-07-19 13 | */ 14 | public interface SysDictInfoMapper extends BaseMapper { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/constant/JobStatus.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.constant; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2023/1/8 3:46 AM 9 | */ 10 | @Getter 11 | @AllArgsConstructor 12 | public enum JobStatus { 13 | 14 | EXECUTE(0), 15 | 16 | PAUSE(1),; 17 | 18 | private final Integer type; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/mapper/MessageMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.websocket.pojo.ChatMessage; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author: Libre 9 | * @Date: 2022/5/23 10:52 PM 10 | */ 11 | @Mapper 12 | public interface MessageMapper extends BaseMapper { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/pojo/DeptInfo.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.pojo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author Libre 9 | * @date 2021/7/12 10:23 10 | */ 11 | @Data 12 | public class DeptInfo implements Serializable { 13 | 14 | /** 15 | * 主键ID 16 | */ 17 | private Long id; 18 | 19 | /** 20 | * 部门名称 21 | */ 22 | private String name; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/constant/UserConstants.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.constant; 2 | 3 | /** 4 | * @author: Libre 5 | * @Date: 2022/8/26 10:47 PM 6 | */ 7 | public interface UserConstants { 8 | 9 | /** 10 | * 用户是否锁定 11 | */ 12 | Integer USER_LOCK = 1; 13 | 14 | Integer USER_UNLOCK = 0; 15 | 16 | /** 17 | * 用户是否启用 18 | */ 19 | Integer USER_ENABLE = 1; 20 | 21 | Integer USER_DISABLE = 0; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/TestJob.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz; 2 | 3 | import com.libre.im.tookit.moudle.quartz.annotation.ScheduleTask; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2022/12/30 10:57 PM 9 | */ 10 | @Slf4j 11 | @ScheduleTask 12 | public class TestJob { 13 | 14 | public void execute() { 15 | log.info("定时任务开始执行........."); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/mapper/ConversationMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.libre.im.websocket.pojo.Conversation; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author: Libre 9 | * @Date: 2022/6/13 11:01 PM 10 | */ 11 | @Mapper 12 | public interface ConversationMapper extends BaseMapper { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/MenuCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import com.libre.im.common.pojo.BaseCriteria; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @author: Libre 10 | * @Date: 2023/1/1 9:05 PM 11 | */ 12 | @Data 13 | @EqualsAndHashCode(callSuper = true) 14 | @ToString(callSuper = true) 15 | public class MenuCriteria extends BaseCriteria { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/RoleCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import com.libre.im.common.pojo.BaseCriteria; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @author: Libre 10 | * @Date: 2022/9/4 5:12 PM 11 | */ 12 | @Data 13 | @EqualsAndHashCode(callSuper = true) 14 | @ToString(callSuper = true) 15 | public class RoleCriteria extends BaseCriteria { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/vo/MenuMetaVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 前端菜单路由元数据 10 | * 11 | */ 12 | @Getter 13 | @RequiredArgsConstructor 14 | public class MenuMetaVO implements Serializable { 15 | 16 | private final String title; 17 | 18 | private final String icon; 19 | 20 | private final Boolean noCache; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/annotation/ApiLog.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.annotation; 2 | 3 | import com.libre.im.log.support.SysLogType; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * 操作日志注解 9 | * 10 | */ 11 | @Target(ElementType.METHOD) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Documented 14 | public @interface ApiLog { 15 | 16 | /** 17 | * 描述 18 | * @return {String} 19 | */ 20 | String value(); 21 | 22 | SysLogType type() default SysLogType.Api; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/mapper/SysDictMapper.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.mapper; 2 | 3 | import com.baomidou.mybatisplus.annotation.InterceptorIgnore; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.libre.im.system.pojo.entity.SysDict; 6 | 7 | /** 8 | *

9 | * 字典表 Mapper 接口 10 | *

11 | * 12 | * @author L.cm 13 | * @since 2020-07-19 14 | */ 15 | @InterceptorIgnore 16 | public interface SysDictMapper extends BaseMapper { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/DeptCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import com.libre.im.common.pojo.BaseCriteria; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @author Libre 10 | * @date 2022/2/2 19:16 11 | */ 12 | @Data 13 | @ToString(callSuper = true) 14 | @EqualsAndHashCode(callSuper = true) 15 | public class DeptCriteria extends BaseCriteria { 16 | 17 | private Long parentId; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/controller/LibreUserController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | /** 8 | * @author: Libre 9 | * @Date: 2022/5/3 2:45 AM 10 | */ 11 | @RestController 12 | @RequestMapping("/user") 13 | @RequiredArgsConstructor 14 | public class LibreUserController { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/security/dto/RoleInfo.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.security.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 角色信息 9 | * 10 | * @author L.cm 11 | */ 12 | @Data 13 | public class RoleInfo implements Serializable { 14 | 15 | /** 16 | * 角色id 17 | */ 18 | private Long id; 19 | 20 | /** 21 | * 角色名称 22 | */ 23 | private String name; 24 | 25 | /** 26 | * 角色权限字符串 27 | */ 28 | private String permission; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysPostService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.system.pojo.entity.SysPost; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author zhao.cheng 10 | */ 11 | public interface SysPostService extends IService { 12 | 13 | /** 14 | * 查找用户岗位信息 15 | * @param userId 用户id 16 | * @return 集合 17 | */ 18 | List getListByUserId(Long userId); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/email/service/EmailService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.email.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.tookit.moudle.email.pojo.MailConfig; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2023/1/12 1:31 AM 9 | */ 10 | public interface EmailService extends IService { 11 | 12 | MailConfig findByUsername(String username); 13 | 14 | void sendEmail(String address, String content); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/handler/WebSocketServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.handler; 2 | 3 | import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2023/1/21 4:29 AM 8 | */ 9 | public class WebSocketServerHandler extends WebSocketServerProtocolHandler { 10 | 11 | public WebSocketServerHandler(String websocketPath) { 12 | super(websocketPath, null, true, 10 * 1023, false, true); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/pojo/SysLogCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.pojo; 2 | 3 | import com.libre.im.common.pojo.BaseCriteria; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @author Libre 10 | * @date 2022/2/2 19:16 11 | */ 12 | @Data 13 | @ToString(callSuper = true) 14 | @EqualsAndHashCode(callSuper = true) 15 | public class SysLogCriteria extends BaseCriteria { 16 | 17 | private Integer success; 18 | 19 | private Long userId; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/MediaMessage.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.ToString; 6 | 7 | /** 8 | * @author ZC 9 | * @date 2021/8/6 23:27 10 | */ 11 | @Data 12 | @EqualsAndHashCode(callSuper = true) 13 | @ToString(callSuper = true) 14 | public class MediaMessage extends Message { 15 | 16 | @Override 17 | public Byte[] getBody() { 18 | return (Byte[]) body; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/TextMessage.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.ToString; 6 | 7 | /** 8 | * @author ZC 9 | * @date 2021/8/6 23:27 10 | */ 11 | @Data 12 | @EqualsAndHashCode(callSuper = true) 13 | @ToString(callSuper = true) 14 | public class TextMessage extends Message { 15 | 16 | @Override 17 | public String getBody() { 18 | return (String) body; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/RoleMenuDTO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotNull; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author: Libre 11 | * @Date: 2022/9/11 3:29 PM 12 | */ 13 | @Data 14 | public class RoleMenuDTO { 15 | 16 | /** 17 | * 角色id 18 | */ 19 | @NotNull 20 | private Long id; 21 | 22 | /** 23 | * 菜单id列表 24 | */ 25 | private List menuIds = new ArrayList<>(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/proto/TextMessage.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package com.libre.im.websocket.core.proto; 3 | option java_package = "com.libre.im.websocket.core.proto"; 4 | option java_outer_classname="TextMessageProto"; 5 | 6 | message TextMessage { 7 | uint64 id = 1; 8 | uint32 connectType = 2; 9 | uint32 messageBodyType = 3; 10 | uint64 sendUserId = 4; 11 | uint32 status = 5; 12 | string body = 6; 13 | uint64 acceptUserId = 7; 14 | uint64 acceptGroupId = 8; 15 | string createTime = 9; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/pojo/PostInfo.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.pojo; 2 | 3 | import lombok.Data; 4 | import org.springframework.lang.NonNull; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 岗位信息 10 | * 11 | * @author Libre 12 | */ 13 | @Data 14 | public class PostInfo implements Serializable { 15 | 16 | /** 17 | * 主键ID 18 | */ 19 | @NonNull 20 | private Long id; 21 | 22 | /** 23 | * 岗位编码 24 | */ 25 | private String code; 26 | 27 | /** 28 | * 岗位名称 29 | */ 30 | private String name; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/service/SysLogService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.libre.im.log.pojo.SysLog; 6 | import com.libre.im.log.pojo.SysLogCriteria; 7 | 8 | /** 9 | * @author: Libre 10 | * @Date: 2022/12/17 6:03 PM 11 | */ 12 | public interface SysLogService extends IService { 13 | 14 | PageDTO findPage(PageDTO page, SysLogCriteria criteria); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/pojo/SysJobCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.pojo; 2 | 3 | import com.libre.im.common.pojo.BaseCriteria; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @author: Libre 10 | * @Date: 2022/12/30 9:06 PM 11 | */ 12 | @Data 13 | @EqualsAndHashCode(callSuper = true) 14 | @ToString(callSuper = true) 15 | public class SysJobCriteria extends BaseCriteria { 16 | 17 | /** 18 | * 定时任务状态 19 | */ 20 | private String jobStatus; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/pojo/ChatMessage.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.pojo; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | /** 8 | * @author: Libre 9 | * @Date: 2022/5/23 10:13 PM 10 | */ 11 | @Data 12 | public class ChatMessage { 13 | 14 | private Long id; 15 | 16 | private String message; 17 | 18 | private Long sendUserId; 19 | 20 | private Long acceptUserId; 21 | 22 | private Integer type; 23 | 24 | private Integer status; 25 | 26 | private LocalDateTime createTime; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/service/FriendService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.websocket.pojo.Friend; 5 | import com.libre.im.websocket.pojo.vo.FriendVO; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author: Libre 11 | * @Date: 2022/5/3 2:48 AM 12 | */ 13 | public interface FriendService extends IService { 14 | 15 | List findListByUserId(Long userId); 16 | 17 | void removeFriend(Long friendId); 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/impl/ClientServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.libre.im.system.mapper.ClientMapper; 5 | import com.libre.im.system.pojo.entity.Client; 6 | import com.libre.im.system.service.ClientService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author zhao.cheng 11 | */ 12 | @Service 13 | public class ClientServiceImpl extends ServiceImpl implements ClientService { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/service/MessageService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.google.common.collect.ArrayListMultimap; 5 | import com.libre.im.websocket.pojo.ChatMessage; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * @author: Libre 11 | * @Date: 2022/5/23 10:54 PM 12 | */ 13 | public interface MessageService extends IService { 14 | 15 | ArrayListMultimap findMessagesBySendUserIds(Collection userIds); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysDict.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | *

7 | * 字典表 8 | *

9 | * 10 | * @author L.cm 11 | * @since 2020-07-07 12 | */ 13 | @Data 14 | public class SysDict { 15 | 16 | private Long id; 17 | 18 | /** 19 | * 字典名称 20 | */ 21 | private String name; 22 | 23 | /** 24 | * 字典描述 25 | */ 26 | private String description; 27 | 28 | /** 29 | * 状态(0正常 1停用) 30 | */ 31 | private Integer status; 32 | 33 | /** 34 | * 备注 35 | */ 36 | private String remark; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/vo/RoleVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | /** 8 | * 角色创建更新实体 9 | * 10 | * @author L.cm 11 | */ 12 | @Data 13 | public class RoleVO { 14 | 15 | /** 16 | * 主键 id 17 | */ 18 | private Long id; 19 | 20 | /** 21 | * 角色名称 22 | */ 23 | private String roleName; 24 | 25 | /** 26 | * 角色权限字符串 27 | */ 28 | private String permission; 29 | 30 | private Integer seq; 31 | 32 | /** 33 | * 创建时间 34 | */ 35 | private LocalDateTime gmtCreate; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/impl/SysRoleDeptServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.libre.im.system.mapper.RoleDeptMapper; 5 | import com.libre.im.system.pojo.entity.SysRoleDept; 6 | import com.libre.im.system.service.SysRoleDeptService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author Libre 11 | */ 12 | @Service 13 | public class SysRoleDeptServiceImpl extends ServiceImpl implements SysRoleDeptService { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/service/mapstruct/UserMapping.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.service.mapstruct; 2 | 3 | import com.libre.im.websocket.pojo.LibreUser; 4 | import com.libre.im.websocket.pojo.vo.UserVO; 5 | import com.libre.toolkit.mapstruct.BaseMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.factory.Mappers; 8 | 9 | /** 10 | * @author: Libre 11 | * @Date: 2022/6/21 9:52 PM 12 | */ 13 | @Mapper 14 | public interface UserMapping extends BaseMapping { 15 | 16 | UserMapping INSTANCE = Mappers.getMapper(UserMapping.class); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/pojo/vo/UserVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.pojo.vo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2022/6/21 9:48 PM 8 | */ 9 | @Data 10 | public class UserVO { 11 | 12 | private Long id; 13 | 14 | private String username; 15 | 16 | private String nikeName; 17 | 18 | private String avatar; 19 | 20 | private String chatCode; 21 | 22 | private String signature; 23 | 24 | private Integer age; 25 | 26 | private String address; 27 | 28 | private Integer gender; 29 | 30 | private String phone; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/support/SysLogMapping.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.support; 2 | 3 | import com.libre.boot.exception.LibreErrorEvent; 4 | import com.libre.im.log.pojo.SysLog; 5 | import com.libre.toolkit.mapstruct.BaseMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.factory.Mappers; 8 | 9 | /** 10 | * @author: Libre 11 | * @Date: 2022/12/17 6:05 PM 12 | */ 13 | @Mapper 14 | public interface SysLogMapping extends BaseMapping { 15 | 16 | SysLogMapping INSTANCE = Mappers.getMapper(SysLogMapping.class); 17 | 18 | SysLog convertToSysLog(LibreErrorEvent event); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/exception/LibreImException.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.exception; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2022/5/2 9:42 PM 8 | */ 9 | public class LibreImException extends RuntimeException { 10 | 11 | public LibreImException(String message) { 12 | super(message); 13 | } 14 | 15 | public LibreImException(String template, Object... args) { 16 | super(String.format(template, args)); 17 | } 18 | public LibreImException(String message, Throwable cause) { 19 | super(message, cause); 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/service/ConversationService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.websocket.pojo.Conversation; 5 | import com.libre.im.websocket.pojo.vo.ConversationVO; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author: Libre 11 | * @Date: 2022/6/13 10:55 PM 12 | */ 13 | public interface ConversationService extends IService { 14 | 15 | List listByUserId(Long userId); 16 | 17 | void removeByUserIdAndFriendId(Long userId, Long friendId); 18 | 19 | void add(Long friend); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/enums/ConnectType.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum ConnectType { 9 | 10 | HEART_BEAT(1), 11 | 12 | SEND(2), 13 | 14 | RECEIVED(3) 15 | ; 16 | 17 | private final Integer type; 18 | 19 | public static ConnectType find(Integer code) { 20 | ConnectType[] values = ConnectType.values(); 21 | for (ConnectType connectType : values) { 22 | if (connectType.getType().equals(code)) { 23 | return connectType; 24 | } 25 | } 26 | return null; 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/pojo/vo/ConversationVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.pojo.vo; 2 | 3 | import com.libre.im.websocket.pojo.ChatMessage; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @author: Libre 12 | * @Date: 2022/6/18 8:39 PM 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class ConversationVO implements Serializable { 18 | 19 | private Long userId; 20 | 21 | private UserVO user; 22 | 23 | private ChatMessage lastMessage; 24 | 25 | private Integer unreadMessageNum; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/UserCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import com.libre.im.common.pojo.BaseCriteria; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.ToString; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.util.Set; 10 | 11 | /** 12 | * @author Libre 13 | * @date 2022/1/1 18:21 14 | */ 15 | @Data 16 | @EqualsAndHashCode(callSuper = true) 17 | @ToString(callSuper = true) 18 | @Accessors(chain = true) 19 | public class UserCriteria extends BaseCriteria { 20 | 21 | private Boolean enabled; 22 | 23 | private Long deptId; 24 | 25 | private Set deptIds; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/pojo/Friend.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableId; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import lombok.Data; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * @author: Libre 11 | * @Date: 2022/5/3 2:47 AM 12 | */ 13 | @Data 14 | @TableName("im_friend") 15 | public class Friend { 16 | 17 | @TableId 18 | private Long id; 19 | 20 | private Long userId; 21 | 22 | private Long friendId; 23 | 24 | private Boolean isTop; 25 | 26 | private LocalDateTime addTime; 27 | 28 | private LocalDateTime updateTime; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/result/ApiCode.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.result; 2 | 3 | import com.libre.toolkit.result.IResultCode; 4 | import lombok.AllArgsConstructor; 5 | 6 | /** 7 | * @author Libre 8 | * @date 2022/1/1 18:56 9 | */ 10 | 11 | @AllArgsConstructor 12 | public enum ApiCode implements IResultCode { 13 | 14 | USER_NOT_EXIST(20001, "用户不存在"), USER_ALREADY_EXIST(20002, "用户已经存在"); 15 | 16 | private final Integer code; 17 | 18 | private final String message; 19 | 20 | @Override 21 | public String getMessage() { 22 | return this.message; 23 | } 24 | 25 | @Override 26 | public int getCode() { 27 | return this.code; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysRoleDept.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import io.swagger.annotations.ApiModel; 5 | import io.swagger.v3.oas.annotations.media.Schema; 6 | import lombok.Data; 7 | 8 | /** 9 | * 角色部门表 10 | * 11 | * @author zhao.cheng 12 | */ 13 | @ApiModel(value = "角色部门表") 14 | @Data 15 | @TableName(value = "sys_role_dept") 16 | public class SysRoleDept { 17 | 18 | /** 19 | * 角色id 20 | */ 21 | @Schema(description = "角色id") 22 | private Long roleId; 23 | 24 | /** 25 | * 部门id 26 | */ 27 | @Schema(description = "部门id") 28 | private Long deptId; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysUserPost.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import io.swagger.annotations.ApiModel; 5 | import io.swagger.v3.oas.annotations.media.Schema; 6 | import lombok.Data; 7 | 8 | /** 9 | * 用户岗位表 10 | * 11 | * @author zhao.cheng 12 | */ 13 | @ApiModel(value = "用户岗位表") 14 | @Data 15 | @TableName(value = "sys_user_post") 16 | public class SysUserPost { 17 | 18 | /** 19 | * 用户id 20 | */ 21 | @Schema(description = "用户id") 22 | private Long userId; 23 | 24 | /** 25 | * 岗位id 26 | */ 27 | @Schema(description = "岗位id") 28 | private Long postId; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysUserRole.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import io.swagger.annotations.ApiModel; 5 | import io.swagger.v3.oas.annotations.media.Schema; 6 | import lombok.Data; 7 | 8 | /** 9 | * 用户角色表 10 | * 11 | * @author zhao.cheng 12 | */ 13 | @ApiModel(value = "用户角色表") 14 | @Data 15 | @TableName(value = "sys_user_role") 16 | public class SysUserRole { 17 | 18 | /** 19 | * 用户id 20 | */ 21 | @Schema(description = "用户id") 22 | private Long userId; 23 | 24 | /** 25 | * 角色id 26 | */ 27 | @Schema(description = "角色id") 28 | private Long roleId; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/config/PostgresDdl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.config; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.libre.mybatis.ddl.SimpleDdl; 5 | 6 | import javax.sql.DataSource; 7 | import java.util.List; 8 | 9 | public class PostgresDdl extends SimpleDdl { 10 | 11 | private final DataSource dataSource; 12 | 13 | public PostgresDdl(DataSource dataSource) { 14 | super(dataSource); 15 | this.dataSource = dataSource; 16 | } 17 | 18 | /** 19 | * 执行 SQL 脚本方式 20 | */ 21 | @Override 22 | public List getSqlFiles() { 23 | return Lists.newArrayList("db/postgres/libre_table.sql", "db/postgres/libre_data.sql"); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/vo/DeptVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.vo; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | /** 10 | * @author Libre 11 | * @date 2022/2/2 15:43 12 | */ 13 | @Data 14 | public class DeptVO implements Serializable { 15 | 16 | private Long id; 17 | 18 | /** 19 | * 父id 20 | */ 21 | @Schema(description = "父id") 22 | private Long parentId; 23 | 24 | /** 25 | * 部门名称 26 | */ 27 | @Schema(description = "部门名称") 28 | private String deptName; 29 | 30 | /** 31 | * 子部门 32 | */ 33 | private List children; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysRoleMenu.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableId; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.v3.oas.annotations.media.Schema; 7 | import lombok.Data; 8 | 9 | /** 10 | * 角色菜单表 11 | * 12 | * @author zhao.cheng 13 | */ 14 | @ApiModel(value = "角色菜单表") 15 | @Data 16 | @TableName(value = "sys_role_menu") 17 | public class SysRoleMenu { 18 | 19 | @TableId 20 | private Long id; 21 | 22 | @Schema(description = "") 23 | private Long roleId; 24 | 25 | @Schema(description = "") 26 | private Long menuId; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/pojo/vo/FriendVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.pojo.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | /** 8 | * @author: Libre 9 | * @Date: 2022/5/3 7:52 AM 10 | */ 11 | @Data 12 | public class FriendVO { 13 | 14 | private Long friendId; 15 | 16 | private String username; 17 | 18 | private String nikeName; 19 | 20 | private String avatar; 21 | 22 | private String chatCode; 23 | 24 | private String signature; 25 | 26 | private Integer age; 27 | 28 | private String address; 29 | 30 | private Integer gender; 31 | 32 | private Boolean isTop; 33 | 34 | private LocalDateTime addTime; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/RoleDTO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import com.libre.toolkit.validation.UpdateGroup; 4 | import lombok.Data; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | import javax.validation.constraints.NotNull; 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @author: Libre 12 | * @Date: 2022/9/11 3:23 PM 13 | */ 14 | @Data 15 | public class RoleDTO implements Serializable { 16 | 17 | /** 18 | * 主键 id 19 | */ 20 | @NotNull(groups = UpdateGroup.class) 21 | private Long id; 22 | 23 | /** 24 | * 角色名称 25 | */ 26 | @NotBlank 27 | private String name; 28 | 29 | /** 30 | * 角色权限字符串 31 | */ 32 | @NotBlank 33 | private String permission; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysUserPostService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.system.pojo.entity.SysUserPost; 5 | 6 | import java.util.Collection; 7 | import java.util.List; 8 | 9 | /** 10 | * @author zhao.cheng 11 | */ 12 | public interface SysUserPostService extends IService { 13 | 14 | /** 15 | * 根据用户id查找 16 | * @param userId 用户id 17 | * @return 集合 18 | */ 19 | List getListByUserId(Long userId); 20 | 21 | /** 22 | * 根据用户id查找 23 | * @param userIds userIds 24 | * @return List 25 | */ 26 | List getListByUserIds(Collection userIds); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/UserDTO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | /** 10 | * 11 | */ 12 | @Data 13 | public class UserDTO implements Serializable { 14 | 15 | private Long id; 16 | 17 | private String username; 18 | 19 | private String nickName; 20 | 21 | private String email; 22 | 23 | private String phone; 24 | 25 | private String gender; 26 | 27 | private String avatarName; 28 | 29 | private String avatarPath; 30 | 31 | @JsonIgnore 32 | private String password; 33 | 34 | private Integer enabled; 35 | 36 | private List roleIds; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/mapstruct/SysMenuMapping.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.mapstruct; 2 | 3 | import com.libre.im.common.mapstruct.BooleanAndIntegerFormat; 4 | import com.libre.im.system.pojo.dto.MenuDTO; 5 | import com.libre.im.system.pojo.SysMenu; 6 | import com.libre.toolkit.mapstruct.BaseMapping; 7 | import org.mapstruct.Mapper; 8 | import org.mapstruct.factory.Mappers; 9 | 10 | /** 11 | * @author: Libre 12 | * @Date: 2023/1/8 1:38 AM 13 | */ 14 | @Mapper(uses = BooleanAndIntegerFormat.class) 15 | public interface SysMenuMapping extends BaseMapping { 16 | 17 | SysMenuMapping INSTANCE = Mappers.getMapper(SysMenuMapping.class); 18 | 19 | @Override 20 | SysMenu sourceToTarget(MenuDTO menuDTO); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/service/mapstruct/FriendMapping.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.service.mapstruct; 2 | 3 | import com.libre.im.websocket.pojo.Friend; 4 | import com.libre.im.websocket.pojo.LibreUser; 5 | import com.libre.im.websocket.pojo.vo.FriendVO; 6 | import com.libre.toolkit.mapstruct.BaseMapping; 7 | import org.mapstruct.Mapper; 8 | import org.mapstruct.Mapping; 9 | import org.mapstruct.factory.Mappers; 10 | 11 | /** 12 | * @author: Libre 13 | * @Date: 2022/5/3 7:55 AM 14 | */ 15 | @Mapper 16 | public interface FriendMapping extends BaseMapping { 17 | 18 | FriendMapping INSTANCE = Mappers.getMapper(FriendMapping.class); 19 | 20 | @Mapping(source = "id", target = "friendId") 21 | FriendVO chatUserToFriendVO(LibreUser user); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/enums/MessageStatus.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2022/5/5 3:38 AM 9 | */ 10 | @Getter 11 | @AllArgsConstructor 12 | public enum MessageStatus { 13 | 14 | ONLINE(1), 15 | 16 | OFFLINE(2), 17 | ; 18 | 19 | private final Integer status; 20 | 21 | public static MessageStatus find(Integer code) { 22 | MessageStatus[] values = MessageStatus.values(); 23 | for (MessageStatus messageStatus : values) { 24 | if (messageStatus.getStatus().equals(code)) { 25 | return messageStatus; 26 | } 27 | } 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysDept.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.libre.im.common.pojo.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.v3.oas.annotations.media.Schema; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | /** 11 | * 部门表 12 | * 13 | * @author zhao.cheng 14 | */ 15 | @ApiModel(value = "部门表") 16 | @Data 17 | @EqualsAndHashCode(callSuper = true) 18 | @TableName(value = "sys_dept") 19 | public class SysDept extends BaseEntity { 20 | 21 | /** 22 | * 父id 23 | */ 24 | @Schema(description = "父id") 25 | private Long parentId; 26 | 27 | /** 28 | * 部门名称 29 | */ 30 | @Schema(description = "部门名称") 31 | private String deptName; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/vo/MenuVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.vo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | /** 10 | * 前端菜单路由 11 | * 12 | * @author L.cm 13 | */ 14 | @Data 15 | public class MenuVO implements Serializable { 16 | 17 | private Long id; 18 | 19 | private Long parentId; 20 | 21 | private String name; 22 | 23 | private String path; 24 | 25 | private Integer type; 26 | 27 | private Boolean hidden; 28 | 29 | private String redirect; 30 | 31 | private String component; 32 | 33 | private Integer alwaysShow; 34 | 35 | private MenuMetaVO meta; 36 | 37 | @JsonInclude(JsonInclude.Include.NON_NULL) 38 | private List children; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/auth/SecWebAuthDetailsSource.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.auth; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.authentication.AuthenticationDetailsSource; 5 | import org.springframework.security.web.authentication.WebAuthenticationDetails; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | /** 10 | * 授权详情 添加验证码 11 | * 12 | * @author L.cm 13 | */ 14 | @Configuration(proxyBeanMethods = false) 15 | public class SecWebAuthDetailsSource 16 | implements AuthenticationDetailsSource { 17 | 18 | @Override 19 | public WebAuthenticationDetails buildDetails(HttpServletRequest context) { 20 | return new SecWebAuthenticationDetails(context); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### gradle ### 2 | .gradle 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .settings/ 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | bin/ 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | out/ 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | nbproject/private/ 24 | nbbuild/ 25 | dist/ 26 | nbdist/ 27 | .nb-gradle/ 28 | 29 | ### maven ### 30 | target/ 31 | *.war 32 | *.ear 33 | *.zip 34 | *.tar 35 | *.tar.gz 36 | 37 | ### npm ### 38 | node_modules/ 39 | 40 | # logs # 41 | logs 42 | 43 | # temp ignore 44 | *.log 45 | *.cache 46 | *.diff 47 | *.patch 48 | *.tmp 49 | *.java~ 50 | *.properties~ 51 | *.xml~ 52 | 53 | # system ignore 54 | .DS_Store 55 | Thumbs.db 56 | Servers 57 | .metadata 58 | upload 59 | gen_code 60 | rocksdb 61 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/mapstruct/BooleanAndIntegerFormat.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.mapstruct; 2 | 3 | import com.libre.im.common.constant.LibreConstants; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2023/1/8 1:42 AM 8 | */ 9 | public class BooleanAndIntegerFormat { 10 | 11 | public Integer toInteger(Boolean status) { 12 | if (Boolean.FALSE.equals(status)) { 13 | return LibreConstants.DISABLE; 14 | } 15 | else if (Boolean.TRUE.equals(status)) { 16 | return LibreConstants.ENABLE; 17 | } 18 | return null; 19 | } 20 | 21 | public Boolean toBoolean(Integer status) { 22 | if (LibreConstants.ENABLE.equals(status)) { 23 | return Boolean.TRUE; 24 | } 25 | else if (LibreConstants.DISABLE.equals(status)) { 26 | return Boolean.FALSE; 27 | } 28 | return null; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/config/DdlConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.config; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.libre.mybatis.ddl.DdlApplicationRunner; 5 | import com.libre.mybatis.ddl.IDdl; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | import javax.sql.DataSource; 10 | 11 | /** 12 | * @author: Libre 13 | * @Date: 2022/12/13 12:45 AM 14 | */ 15 | @Configuration(proxyBeanMethods = false) 16 | public class DdlConfiguration { 17 | 18 | @Bean 19 | public IDdl ddl(DataSource dataSource) { 20 | return new PostgresDdl(dataSource); 21 | } 22 | 23 | @Bean 24 | public DdlApplicationRunner ddlApplicationRunner(IDdl ddl) { 25 | return new DdlApplicationRunner(ImmutableList.of(ddl)); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/config/WebsocketServerProperties.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * @author ZC 8 | * @date 2021/8/1 13:28 9 | */ 10 | @Data 11 | @ConfigurationProperties("libre.im") 12 | public class WebsocketServerProperties { 13 | 14 | /** 15 | * 端口 16 | */ 17 | private Integer port = 8081; 18 | 19 | /** 20 | * url 21 | */ 22 | private String wsUri = "/ws"; 23 | 24 | /** 25 | * 读超时 s 26 | */ 27 | private Integer readIdleTimeOut = 60; 28 | 29 | /** 30 | * 写超时 31 | */ 32 | private Integer writeIdleTimeOut = 10; 33 | 34 | /** 35 | * 所有超时 36 | */ 37 | private Integer allIdleTimeOut = 10; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/annotation/ScheduleTask.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.annotation; 2 | 3 | import org.springframework.core.annotation.AliasFor; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.lang.annotation.*; 7 | 8 | /** 9 | * @author: Libre 10 | * @Date: 2022/12/30 10:56 PM 11 | */ 12 | 13 | @Target(ElementType.TYPE) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Documented 16 | @Component 17 | public @interface ScheduleTask { 18 | 19 | /** 20 | * The value may indicate a suggestion for a logical component name, to be turned into 21 | * a Spring bean in case of an autodetected component. 22 | * @return the suggested component name, if any (or empty String otherwise) 23 | */ 24 | @AliasFor(annotation = Component.class) 25 | String value() default ""; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/mapstruct/SysUserMapping.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.mapstruct; 2 | 3 | import com.libre.im.common.security.dto.AuthUser; 4 | import com.libre.im.security.pojo.dto.UserInfo; 5 | import com.libre.im.system.pojo.dto.UserDTO; 6 | import com.libre.im.system.pojo.entity.SysUser; 7 | import com.libre.im.system.pojo.vo.UserVO; 8 | import com.libre.toolkit.mapstruct.BaseMapping; 9 | import org.mapstruct.Mapper; 10 | import org.mapstruct.factory.Mappers; 11 | 12 | /** 13 | * @author Libre 14 | * @date 2022/1/1 18:34 15 | */ 16 | @Mapper 17 | public interface SysUserMapping extends BaseMapping { 18 | 19 | SysUserMapping INSTANCE = Mappers.getMapper(SysUserMapping.class); 20 | 21 | SysUser convertToUser(UserDTO userDTO); 22 | 23 | UserInfo convertToUserInfo(AuthUser authUser); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/pojo/dto/UserInfo.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.pojo.dto; 2 | 3 | import com.libre.im.system.pojo.entity.SysRole; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | import java.util.List; 10 | 11 | /** 12 | * @author: Libre 13 | * @Date: 2022/8/27 12:21 PM 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UserInfo implements Serializable { 19 | 20 | private String username; 21 | 22 | private String token; 23 | 24 | private String avatar; 25 | 26 | private List roleList; 27 | 28 | private List permissions; 29 | 30 | private Integer isAdmin; 31 | 32 | public UserInfo(String username, String token) { 33 | this.username = username; 34 | this.token = token; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysDictService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.Wrapper; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.libre.im.system.pojo.dto.DictCriteria; 6 | import com.libre.im.system.pojo.entity.SysDict; 7 | 8 | import java.util.Collection; 9 | 10 | /** 11 | *

12 | * 字典表 服务类 13 | *

14 | * 15 | * @author L.cm 16 | * @since 2020-07-19 17 | */ 18 | public interface SysDictService extends IService { 19 | 20 | /** 21 | * 根据 query 组装查询条件 22 | * @param query DeptQuery 23 | * @return Wrapper 24 | */ 25 | Wrapper getQueryWrapper(DictCriteria query); 26 | 27 | /** 28 | * 如果没有试用删除 29 | * @param ids id集合 30 | * @return 是否成功 31 | */ 32 | boolean deleteIfUnusedByIds(Collection ids); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/handler/MessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message.handler; 2 | 3 | import com.google.protobuf.MessageLite; 4 | import com.libre.im.websocket.core.message.Message; 5 | import com.libre.im.websocket.core.message.enums.MessageBodyType; 6 | 7 | /** 8 | * @author ZC 9 | * @date 2021/8/7 14:05 10 | */ 11 | public interface MessageHandler { 12 | 13 | /** 14 | * 获取对应消息类型 15 | * 16 | * @return MessageBodyType 17 | */ 18 | MessageBodyType getMessageType(); 19 | 20 | /** 21 | * 创建新Message对象 22 | * 23 | * @return t 24 | */ 25 | T newInstance(); 26 | 27 | MessageLite getMessage(Message message); 28 | /** 29 | * 消息发送 30 | * 31 | * @param message T 32 | */ 33 | void resolveMessage(Message message); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/constant/LibreIMConstants.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.constant; 2 | 3 | import io.netty.util.AttributeKey; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2022/4/30 2:52 AM 8 | */ 9 | public class LibreIMConstants { 10 | 11 | public final static String SERVER_SESSION_KEY = "SERVER_SESSION_ID"; 12 | 13 | public final static String SERVER_SESSION_HEART_BEAT_KEY = "SERVER_SESSION_HEART_BEAT"; 14 | 15 | public final static String PING = "PING"; 16 | 17 | public final static String PONG = "PONG"; 18 | 19 | public final static AttributeKey SERVER_SESSION_ID = AttributeKey.valueOf(SERVER_SESSION_KEY); 20 | 21 | public static final AttributeKey SERVER_SESSION_HEART_BEAT = AttributeKey 22 | .valueOf(SERVER_SESSION_HEART_BEAT_KEY); 23 | 24 | public final static String MESSAGE_TOPIC = "libre:im:message:topic"; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysRoleMenuService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.system.pojo.entity.SysRoleMenu; 5 | 6 | import java.util.Collection; 7 | import java.util.List; 8 | 9 | /** 10 | * @author zhao.cheng 11 | */ 12 | public interface SysRoleMenuService extends IService { 13 | 14 | /** 15 | * 角色菜单列表 16 | * @param roleIds 角色id集合 17 | * @return 角色菜单 18 | */ 19 | List getListByRoleIds(Collection roleIds); 20 | 21 | /** 22 | * 角色菜单 id 列表 23 | * @param roleIds 角色id集合 24 | * @return 角色菜单 25 | */ 26 | List getIdListByRoleIds(Collection roleIds); 27 | 28 | /** 29 | * 清空角色菜单 30 | * @param roleId 角色Id 31 | */ 32 | boolean deleteByRoleId(Long roleId); 33 | 34 | List getListByMenuIds(List ids); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/resources/db/data/im_user.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO im_user (id, nike_name, username, avatar, password, chat_code, signature, phone, address, email, age, gender, locked, enabled) VALUES (1, 'libre', 'admin', null, '{bcrypt}$2a$10$Lwu7FTLeebpx13Biy8Il3uZo9.O5tFtO6dRgPjprG50CW/n4kdIBm', null, null, null, null, null, null, null, 0, 1); 2 | INSERT INTO im_user (id, nike_name, username, avatar, password, chat_code, signature, phone, address, email, age, gender, locked, enabled) VALUES (2, 'zhangsan', 'zhangsan', null, '{bcrypt}$2a$10$Lwu7FTLeebpx13Biy8Il3uZo9.O5tFtO6dRgPjprG50CW/n4kdIBm', null, null, null, null, null, null, null, 0, 1); 3 | INSERT INTO im_user (id, nike_name, username, avatar, password, chat_code, signature, phone, address, email, age, gender, locked, enabled) VALUES (3, 'lisi', 'lisi', null, '{bcrypt}$2a$10$Lwu7FTLeebpx13Biy8Il3uZo9.O5tFtO6dRgPjprG50CW/n4kdIBm', null, null, null, null, null, null, null, 0, 1); 4 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysPost.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.libre.im.common.pojo.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.v3.oas.annotations.media.Schema; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | /** 11 | * 岗位表 12 | * 13 | * @author zhao.cheng 14 | */ 15 | @ApiModel(value = "岗位表") 16 | @Data 17 | @EqualsAndHashCode(callSuper = true) 18 | @TableName(value = "sys_post") 19 | public class SysPost extends BaseEntity { 20 | 21 | /** 22 | * 部门名称 23 | */ 24 | 25 | @Schema(description = "部门名称") 26 | private String postName; 27 | 28 | /** 29 | * 排序 30 | */ 31 | 32 | @Schema(description = "排序") 33 | private String sort; 34 | 35 | /** 36 | * 状态 37 | */ 38 | 39 | @Schema(description = "状态") 40 | private Integer status; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/config/LibreWebMvcConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.config; 2 | 3 | import com.libre.im.common.config.PageArgumentResolver; 4 | import com.libre.im.security.auth.AuthUserArgumentResolver; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author Libre 13 | * @date 2021/7/12 16:02 14 | */ 15 | @Configuration(proxyBeanMethods = false) 16 | public class LibreWebMvcConfiguration implements WebMvcConfigurer { 17 | 18 | @Override 19 | public void addArgumentResolvers(List argumentResolvers) { 20 | argumentResolvers.add(new AuthUserArgumentResolver()); 21 | argumentResolvers.add(new PageArgumentResolver()); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysDictInfo.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | *

7 | * 字典详情表 8 | *

9 | * 10 | * @author L.cm 11 | * @since 2020-07-07 12 | */ 13 | @Data 14 | public class SysDictInfo { 15 | 16 | private Long id; 17 | 18 | /** 19 | * 字典排序 20 | */ 21 | private Integer seq; 22 | 23 | /** 24 | * 字典标签 25 | */ 26 | private String label; 27 | 28 | /** 29 | * 字典键值 30 | */ 31 | private String value; 32 | 33 | /** 34 | * 字典类型 35 | */ 36 | private String type; 37 | 38 | /** 39 | * 样式属性(其他样式扩展) 40 | */ 41 | private String cssClass; 42 | 43 | /** 44 | * 表格回显样式 45 | */ 46 | private String listClass; 47 | 48 | /** 49 | * 是否默认(0否1是 ) 50 | */ 51 | private Integer isDefault; 52 | 53 | /** 54 | * 状态(0正常 1停用) 55 | */ 56 | private Integer status; 57 | 58 | /** 59 | * 备注 60 | */ 61 | private String remark; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysDictInfoService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.Wrapper; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.libre.im.system.pojo.dto.DictInfoCriteria; 6 | import com.libre.im.system.pojo.entity.SysDictInfo; 7 | 8 | import java.util.Collection; 9 | import java.util.List; 10 | 11 | /** 12 | *

13 | * 字典详情表 服务类 14 | *

15 | * 16 | * @author L.cm 17 | * @since 2020-07-19 18 | */ 19 | public interface SysDictInfoService extends IService { 20 | 21 | /** 22 | * 根据 query 组装查询条件 23 | * @param query DictInfoCriteria 24 | * @return Wrapper 25 | */ 26 | Wrapper getQueryWrapper(DictInfoCriteria query); 27 | 28 | /** 29 | * 获取字典详情集合 30 | * @param dictNameSet 字典名集合 31 | * @return 字典详情集合 32 | */ 33 | List getListByDictNames(Collection dictNameSet); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/session/AbstractSessionManager.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.session; 2 | 3 | import com.libre.im.websocket.core.constant.LibreIMConstants; 4 | import com.libre.toolkit.core.StringUtil; 5 | import io.netty.channel.Channel; 6 | import io.netty.channel.ChannelHandlerContext; 7 | 8 | /** 9 | * @author: Libre 10 | * @Date: 2022/5/5 2:30 AM 11 | */ 12 | public abstract class AbstractSessionManager implements SessionManager { 13 | 14 | @Override 15 | public Session getSession(ChannelHandlerContext ctx) { 16 | Long sessionId = ctx.channel().attr(LibreIMConstants.SERVER_SESSION_ID).get(); 17 | return getSession(sessionId); 18 | } 19 | 20 | 21 | @Override 22 | public void remove(ChannelHandlerContext ctx) { 23 | Channel channel = ctx.channel(); 24 | Long sessionId = channel.attr(LibreIMConstants.SERVER_SESSION_ID).get(); 25 | remove(sessionId); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/email/pojo/SysFile.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.email.pojo; 2 | 3 | import com.libre.im.common.pojo.BaseEntity; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.ToString; 8 | 9 | /** 10 | * @author: Libre 11 | * @Date: 2023/1/18 12:05 AM 12 | */ 13 | @Data 14 | @EqualsAndHashCode(callSuper = true) 15 | @ToString(callSuper = true) 16 | public class SysFile extends BaseEntity { 17 | 18 | private Long id; 19 | 20 | @ApiModelProperty(value = "真实文件名") 21 | private String realName; 22 | 23 | @ApiModelProperty(value = "文件名") 24 | private String name; 25 | 26 | @ApiModelProperty(value = "后缀") 27 | private String suffix; 28 | 29 | @ApiModelProperty(value = "路径") 30 | private String path; 31 | 32 | @ApiModelProperty(value = "类型") 33 | private String type; 34 | 35 | @ApiModelProperty(value = "大小") 36 | private String size; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/mapstruct/SysRoleMapping.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.mapstruct; 2 | 3 | import com.libre.im.common.security.dto.RoleInfo; 4 | import com.libre.im.system.pojo.dto.RoleDTO; 5 | import com.libre.im.system.pojo.entity.SysRole; 6 | import com.libre.im.system.pojo.vo.RoleVO; 7 | import com.libre.toolkit.mapstruct.BaseMapping; 8 | import org.mapstruct.Mapper; 9 | import org.mapstruct.Mapping; 10 | import org.mapstruct.factory.Mappers; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author Libre 16 | * @date 2021/7/12 14:48 17 | */ 18 | @Mapper 19 | public interface SysRoleMapping extends BaseMapping { 20 | 21 | SysRoleMapping INSTANCE = Mappers.getMapper(SysRoleMapping.class); 22 | 23 | List convertToRoleList(List roles); 24 | 25 | SysRole convertToRole(RoleDTO roleDTO); 26 | 27 | @Override 28 | @Mapping(source = "roleName", target = "name") 29 | RoleInfo sourceToTarget(SysRole sysRole); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/Message.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.libre.toolkit.time.DatePattern; 5 | import lombok.Data; 6 | import org.springframework.format.annotation.DateTimeFormat; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | /** 12 | * @author ZC 13 | * @date 2021/8/1 15:20 14 | */ 15 | @Data 16 | public abstract class Message implements Serializable { 17 | 18 | protected Long id; 19 | 20 | protected Integer connectType; 21 | 22 | protected Integer messageBodyType; 23 | 24 | protected Long sendUserId; 25 | 26 | protected Integer status; 27 | 28 | protected Object body; 29 | 30 | protected Long acceptUserId; 31 | 32 | protected Long acceptGroupId; 33 | 34 | @JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) 35 | @DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) 36 | protected LocalDateTime createTime; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/email/pojo/MailConfig.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.email.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.time.LocalDateTime; 11 | 12 | /** 13 | * @author: Libre 14 | * @Date: 2023/1/12 1:31 AM 15 | */ 16 | @Schema 17 | @Data 18 | @Builder 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @TableName(value = "libre_mail_config") 22 | public class MailConfig { 23 | 24 | private Long id; 25 | 26 | private String host; 27 | 28 | private Integer port; 29 | 30 | private String username; 31 | 32 | private String password; 33 | 34 | private String protocol; 35 | 36 | private String gmtModifiedName; 37 | 38 | private String gmtCreateName; 39 | 40 | private LocalDateTime gmtModified; 41 | 42 | private LocalDateTime gmtCreate; 43 | 44 | } -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/MessageFactory.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message; 2 | 3 | import com.libre.im.websocket.core.constant.LibreIMConstants; 4 | import com.libre.im.websocket.core.message.enums.ConnectType; 5 | import com.libre.im.websocket.core.message.enums.MessageBodyType; 6 | import lombok.experimental.UtilityClass; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @author: Libre 12 | * @Date: 2022/5/23 11:47 PM 13 | */ 14 | @UtilityClass 15 | public class MessageFactory { 16 | 17 | public static TextMessage buildHeartBeatMessage() { 18 | TextMessage heartBeatMessage = new TextMessage(); 19 | heartBeatMessage.setCreateTime(LocalDateTime.now()); 20 | heartBeatMessage.setBody(LibreIMConstants.PONG); 21 | heartBeatMessage.setMessageBodyType(MessageBodyType.TEXT.getCode()); 22 | heartBeatMessage.setConnectType(ConnectType.SEND.getType()); 23 | heartBeatMessage.setCreateTime(LocalDateTime.now()); 24 | return heartBeatMessage; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/security/dto/JwtUser.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.security.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * jwt token 中存储的用户新 9 | * 10 | * @author L.cm 11 | */ 12 | @Data 13 | public class JwtUser { 14 | 15 | /** 16 | * 用户id 17 | */ 18 | private Long id; 19 | 20 | private String token; 21 | 22 | /** 23 | * 登录名 24 | */ 25 | private String username; 26 | 27 | /** 28 | * 用户昵称 29 | */ 30 | private String nickName; 31 | 32 | /** 33 | * 用户性别(0男 1女 2未知) 34 | */ 35 | private Integer gender; 36 | 37 | /** 38 | * 头像地址 39 | */ 40 | private String avatar; 41 | 42 | /** 43 | * 用户邮箱 44 | */ 45 | private String email; 46 | 47 | /** 48 | * 手机号码 49 | */ 50 | private String phone; 51 | 52 | /** 53 | * 是否admin 54 | */ 55 | private Integer isAdmin; 56 | 57 | /** 58 | * 角色信息 59 | */ 60 | private List roles; 61 | 62 | /** 63 | * 角色信息 64 | */ 65 | private List roleList; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/pojo/LibreUser.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableId; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import lombok.Data; 6 | 7 | import java.util.Objects; 8 | 9 | /** 10 | * @author ZC 11 | * @date 2021/8/14 20:15 12 | */ 13 | @Data 14 | @TableName("im_user") 15 | public class LibreUser { 16 | 17 | @TableId 18 | private Long id; 19 | 20 | private String username; 21 | 22 | private String nikeName; 23 | 24 | private String avatar; 25 | 26 | private String password; 27 | 28 | private String chatCode; 29 | 30 | private String signature; 31 | 32 | private Integer age; 33 | 34 | private String address; 35 | 36 | private Integer gender; 37 | 38 | private String phone; 39 | 40 | private Integer enabled; 41 | 42 | private Integer locked; 43 | 44 | public Integer getEnabled() { 45 | return enabled; 46 | } 47 | 48 | public Integer getLocked() { 49 | return locked; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/pojo/BaseCriteria.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.pojo; 2 | 3 | import com.libre.toolkit.core.StringUtil; 4 | import lombok.Data; 5 | import org.apache.commons.collections4.CollectionUtils; 6 | 7 | import java.time.LocalDateTime; 8 | import java.util.List; 9 | 10 | /** 11 | * @author Libre 12 | * @date 2022/1/1 18:20 13 | */ 14 | @Data 15 | public abstract class BaseCriteria { 16 | 17 | private Long id; 18 | 19 | /** 20 | * 模糊搜索字段 21 | */ 22 | private String blurry; 23 | 24 | /** 25 | * 创建时间 26 | */ 27 | private List createTime; 28 | 29 | public boolean isBlurryQuery() { 30 | return StringUtil.isNotBlank(blurry); 31 | } 32 | 33 | public boolean haveTime() { 34 | return CollectionUtils.isNotEmpty(this.createTime) && this.createTime.size() == 2; 35 | } 36 | 37 | public LocalDateTime getStartTime() { 38 | return this.createTime.get(0); 39 | } 40 | 41 | public LocalDateTime getEndTime() { 42 | return this.createTime.get(1); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/MessageListener.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message; 2 | 3 | import com.libre.im.websocket.core.constant.LibreIMConstants; 4 | import com.libre.im.websocket.pojo.ChatMessage; 5 | import com.libre.im.websocket.service.MessageService; 6 | import com.libre.redisson.topic.RTopicEvent; 7 | import com.libre.redisson.topic.RTopicListener; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.scheduling.annotation.Async; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author: Libre 14 | * @Date: 2022/5/23 10:40 PM 15 | */ 16 | @Component 17 | @RequiredArgsConstructor 18 | public class MessageListener { 19 | 20 | private final MessageService messageService; 21 | 22 | @Async 23 | @RTopicListener(LibreIMConstants.MESSAGE_TOPIC) 24 | public void onSaveMessage(RTopicEvent event) { 25 | ChatMessage message = event.getMsg(); 26 | messageService.saveOrUpdate(message); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/pojo/dto/OnlineUserDTO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.pojo.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * 在线用户 11 | * 12 | * @author Zheng Jie 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class OnlineUserDTO { 18 | 19 | /** 20 | * 用户名 21 | */ 22 | private String userName; 23 | 24 | /** 25 | * 昵称 26 | */ 27 | private String nickName; 28 | 29 | /** 30 | * 部門 31 | */ 32 | private String dept; 33 | 34 | /** 35 | * 浏览器 36 | */ 37 | private String browser; 38 | 39 | /** 40 | * IP 41 | */ 42 | private String ip; 43 | 44 | /** 45 | * 地址 46 | */ 47 | private String address; 48 | 49 | /** 50 | * token 51 | */ 52 | private String key; 53 | 54 | /** 55 | * 32 位 token 摘要 56 | */ 57 | private String summary; 58 | 59 | /** 60 | * 登录时间 61 | */ 62 | private LocalDateTime loginTime; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/LibreImApplication.java: -------------------------------------------------------------------------------- 1 | package com.libre.im; 2 | 3 | import com.libre.im.websocket.core.server.LibreWebsocketServer; 4 | import lombok.RequiredArgsConstructor; 5 | import org.mybatis.spring.annotation.MapperScan; 6 | import org.springframework.boot.ApplicationArguments; 7 | import org.springframework.boot.ApplicationRunner; 8 | import org.springframework.boot.SpringApplication; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | 11 | /** 12 | * @author ZC 13 | * @date 2021/7/31 22:52 14 | */ 15 | @MapperScan("com.libre.**.mapper") 16 | @SpringBootApplication 17 | @RequiredArgsConstructor 18 | public class LibreImApplication implements ApplicationRunner { 19 | 20 | private final LibreWebsocketServer websocketServer; 21 | 22 | public static void main(String[] args) { 23 | SpringApplication.run(LibreImApplication.class, args); 24 | } 25 | 26 | @Override 27 | public void run(ApplicationArguments args) { 28 | websocketServer.run(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysRole.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.libre.im.common.pojo.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.v3.oas.annotations.media.Schema; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | /** 11 | * 角色表 12 | * 13 | * @author zhao.cheng 14 | */ 15 | @ApiModel(value = "角色表") 16 | @Data 17 | @EqualsAndHashCode(callSuper = true) 18 | @TableName(value = "sys_role") 19 | public class SysRole extends BaseEntity { 20 | 21 | /** 22 | * 角色名 23 | */ 24 | @Schema(description = "角色名") 25 | private String roleName; 26 | 27 | /** 28 | * 父id 29 | */ 30 | @Schema(description = "父id") 31 | private Long parentId; 32 | 33 | /** 34 | * 角色状态(0正常 1停用) 35 | */ 36 | @Schema(description = "角色状态(0正常 1停用)") 37 | private Integer status; 38 | 39 | /** 40 | * 角色权限字符串 41 | */ 42 | private String permission; 43 | 44 | private Integer seq; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/enums/MessageBodyType.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message.enums; 2 | 3 | import com.libre.im.websocket.core.message.MediaMessage; 4 | import com.libre.im.websocket.core.message.TextMessage; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | 8 | /** 9 | * @author ZC 10 | * @date 2021/8/1 15:21 11 | */ 12 | @Getter 13 | @AllArgsConstructor 14 | public enum MessageBodyType { 15 | 16 | /** 17 | * 文本 18 | */ 19 | TEXT(1, TextMessage.class), 20 | 21 | /** 22 | * 媒体 23 | */ 24 | MEDIA(2, MediaMessage.class); 25 | 26 | private final Integer code; 27 | private final Class clazz; 28 | 29 | public static MessageBodyType find(Integer code) { 30 | MessageBodyType[] values = MessageBodyType.values(); 31 | for (MessageBodyType message : values) { 32 | if (message.getCode().equals(code)) { 33 | return message; 34 | } 35 | } 36 | return null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/pojo/SysJobLog.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.pojo; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | /** 8 | * @author: Libre 9 | * @Date: 2022/12/30 10:35 PM 10 | */ 11 | @Data 12 | public class SysJobLog { 13 | 14 | private Long id; 15 | 16 | /** 17 | * 任务名称 18 | */ 19 | private String jobName; 20 | 21 | /** 22 | * 定时任务beanName 23 | */ 24 | private String beanName; 25 | 26 | /** 27 | * 方法名 28 | */ 29 | private String methodName; 30 | 31 | /** 32 | * 参数 33 | */ 34 | private String params; 35 | 36 | /** 37 | * cron 表达式 38 | */ 39 | private String cronExpression; 40 | 41 | /** 42 | * 执行时间 43 | */ 44 | private Long executeTime; 45 | 46 | /** 47 | * 是否成功 48 | */ 49 | private Integer success; 50 | 51 | /** 52 | * 异常信息 53 | */ 54 | private String exceptionDetail; 55 | 56 | /** 57 | * 最后一次执行时间 58 | */ 59 | private LocalDateTime lastExecuteTime; 60 | 61 | /** 62 | * 创建时间 63 | */ 64 | private LocalDateTime createTime; 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/libre/im/PasswordTests.java: -------------------------------------------------------------------------------- 1 | package com.libre.im; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.security.crypto.password.PasswordEncoder; 7 | 8 | /** 9 | * @author: Libre 10 | * @Date: 2022/5/30 11:08 PM 11 | */ 12 | @SpringBootTest 13 | public class PasswordTests { 14 | 15 | @Autowired 16 | private PasswordEncoder passwordEncoder; 17 | 18 | @Test 19 | void test() { 20 | String encode = passwordEncoder.encode("12345678"); 21 | System.out.println(encode); 22 | } 23 | 24 | @Test 25 | void passwordBase64() { 26 | // String s = RsaUtil.encryptToBase64("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9iBNqpPdFxYlCnjpqYvwFIq8GIBGsNsX2zCVY5AUBgY9+QD5Q6+kwVOWvaQX3/WPBlxDtyKP080Th+jZvMGQmJtRtQkTVIXdQps5QSaujuXoOAQ0cRW1zpXNHxAts" + 27 | // "YvZTroZrFYZvn1bJl85Ur91DJVfOggPB+g/9DtgcgMVJSQIDAQAB", "123456"); 28 | // System.out.println(s); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/auth/SecWebAuthenticationDetails.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.auth; 2 | 3 | import com.libre.toolkit.core.StringPool; 4 | import com.libre.toolkit.core.StringUtil; 5 | import lombok.Getter; 6 | import org.springframework.security.web.authentication.WebAuthenticationDetails; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | /** 11 | * 添加 验证码字段 12 | * 13 | * @author L.cm 14 | */ 15 | @Getter 16 | public class SecWebAuthenticationDetails extends WebAuthenticationDetails { 17 | 18 | private static final long serialVersionUID = -5705520861298051410L; 19 | 20 | private final boolean rememberMe; 21 | 22 | SecWebAuthenticationDetails(HttpServletRequest request) { 23 | super(request); 24 | this.rememberMe = getRememberMe(request.getParameter("remember-me")); 25 | } 26 | 27 | private static boolean getRememberMe(String value) { 28 | if (StringUtil.isBlank(value)) { 29 | return false; 30 | } 31 | if (StringPool.ONE.equals(value)) { 32 | return true; 33 | } 34 | return StringPool.TRUE.equalsIgnoreCase(value); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/controller/FriendController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.controller; 2 | 3 | import com.libre.im.websocket.pojo.vo.FriendVO; 4 | import com.libre.toolkit.result.R; 5 | import com.libre.im.websocket.service.FriendService; 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author: Libre 16 | * @Date: 2022/5/3 2:55 AM 17 | */ 18 | @RestController 19 | @RequestMapping("/friend") 20 | @RequiredArgsConstructor 21 | public class FriendController { 22 | 23 | private final FriendService friendService; 24 | 25 | @GetMapping("/list/{userId}") 26 | public R> list(@PathVariable Long userId) { 27 | List chatFriends = friendService.findListByUserId(userId); 28 | return R.data(chatFriends); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/impl/UserPostServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.libre.im.system.mapper.UserPostMapper; 6 | import com.libre.im.system.pojo.entity.SysUserPost; 7 | import com.libre.im.system.service.SysUserPostService; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.Collection; 11 | import java.util.List; 12 | 13 | /** 14 | * @author zhao.cheng 15 | */ 16 | @Service 17 | public class UserPostServiceImpl extends ServiceImpl implements SysUserPostService { 18 | 19 | @Override 20 | public List getListByUserId(Long userId) { 21 | return super.list(Wrappers.lambdaQuery().eq(SysUserPost::getUserId, userId)); 22 | } 23 | 24 | @Override 25 | public List getListByUserIds(Collection userIds) { 26 | return this.list(Wrappers.lambdaQuery().in(SysUserPost::getUserId, userIds)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/MessagePublisher.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message; 2 | 3 | import com.libre.boot.autoconfigure.SpringContext; 4 | import com.libre.im.websocket.core.constant.LibreIMConstants; 5 | import com.libre.toolkit.exception.LibreException; 6 | import com.libre.im.websocket.pojo.ChatMessage; 7 | import com.libre.redisson.topic.RedissonTopicEventPublisher; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.util.Optional; 11 | 12 | /** 13 | * @author: Libre 14 | * @Date: 2022/5/23 10:27 PM 15 | */ 16 | @Slf4j 17 | public class MessagePublisher { 18 | 19 | private final static RedissonTopicEventPublisher publisher; 20 | 21 | static { 22 | publisher = Optional.ofNullable(SpringContext.getBean(RedissonTopicEventPublisher.class)) 23 | .orElseThrow(() -> new LibreException("redissonClient must not be null")); 24 | } 25 | 26 | public static void publishSaveMessageEvent(ChatMessage message) { 27 | publisher.publish(LibreIMConstants.MESSAGE_TOPIC, message); 28 | log.debug("message publish success: {}", message); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/pojo/SysJob.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.libre.im.common.pojo.BaseEntity; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @author: Libre 12 | * @Date: 2022/12/30 8:44 PM 13 | */ 14 | @Data 15 | @EqualsAndHashCode(callSuper = true) 16 | @TableName("sys_job") 17 | public class SysJob extends BaseEntity implements Serializable { 18 | 19 | private static final long serialVersionUID = 42L; 20 | 21 | public static final String JOB_KEY = "JOB_KEY"; 22 | 23 | /** 24 | * 定时任务名称 25 | */ 26 | private String jobName; 27 | 28 | /** 29 | * 任务状态 30 | */ 31 | private Integer jobStatus; 32 | 33 | /** 34 | * 定时任务beanName 35 | */ 36 | private String beanName; 37 | 38 | /** 39 | * 方法名 40 | */ 41 | private String methodName; 42 | 43 | /** 44 | * 参数 45 | */ 46 | private String params; 47 | 48 | /** 49 | * cron 表达式 50 | */ 51 | private String cronExpression; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/mapstruct/MessageMapping.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.mapstruct; 2 | 3 | import com.libre.im.websocket.core.proto.TextMessageProto; 4 | import com.libre.toolkit.mapstruct.BaseMapping; 5 | import com.libre.toolkit.time.DatePattern; 6 | import com.libre.im.websocket.core.message.TextMessage; 7 | import com.libre.im.websocket.pojo.ChatMessage; 8 | import org.mapstruct.Mapper; 9 | import org.mapstruct.Mapping; 10 | import org.mapstruct.factory.Mappers; 11 | 12 | /** 13 | * @author: Libre 14 | * @Date: 2022/5/1 10:08 PM 15 | */ 16 | @Mapper 17 | public interface MessageMapping extends BaseMapping { 18 | 19 | MessageMapping INSTANCE = Mappers.getMapper(MessageMapping.class); 20 | 21 | @Override 22 | @Mapping(source = "createTime", target = "createTime", dateFormat = DatePattern.NORM_DATETIME_PATTERN) 23 | TextMessage sourceToTarget(TextMessageProto.TextMessage textMessage); 24 | 25 | @Mapping(source = "body", target = "message") 26 | ChatMessage convertToChatMessage(TextMessage textMessage); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/codec/ProtobufMessageDecoder.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.codec; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandler; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.MessageToMessageDecoder; 7 | import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; 8 | import io.netty.handler.codec.http.websocketx.WebSocketFrame; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author: Libre 16 | * @Date: 2022/5/1 7:13 AM 17 | */ 18 | @Slf4j 19 | @Component 20 | @ChannelHandler.Sharable 21 | public class ProtobufMessageDecoder extends MessageToMessageDecoder { 22 | 23 | @Override 24 | protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List out) throws Exception { 25 | if (frame instanceof BinaryWebSocketFrame) { 26 | ByteBuf buf = frame.content(); 27 | out.add(buf); 28 | buf.retain(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/auth/AuthUserArgumentResolver.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.auth; 2 | 3 | import com.libre.im.common.security.dto.AuthUser; 4 | import com.libre.im.common.security.support.SecurityUtil; 5 | import org.springframework.core.MethodParameter; 6 | import org.springframework.web.bind.support.WebDataBinderFactory; 7 | import org.springframework.web.context.request.NativeWebRequest; 8 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 9 | import org.springframework.web.method.support.ModelAndViewContainer; 10 | 11 | /** 12 | * 用户参数处理 13 | * 14 | * @author L.cm 15 | */ 16 | public class AuthUserArgumentResolver implements HandlerMethodArgumentResolver { 17 | 18 | @Override 19 | public boolean supportsParameter(MethodParameter parameter) { 20 | return parameter.getParameterType().equals(AuthUser.class); 21 | } 22 | 23 | @Override 24 | public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, 25 | NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { 26 | return SecurityUtil.getUser(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/vo/TokenVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.vo; 2 | 3 | import com.libre.toolkit.json.JsonUtil; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @author Libre 12 | * @date 2021/7/12 12:21 13 | */ 14 | @Getter 15 | @Setter 16 | public class TokenVO implements Serializable { 17 | 18 | /** 19 | * 用户名 20 | */ 21 | private String userName; 22 | 23 | /** 24 | * 昵称 25 | */ 26 | private String nickName; 27 | 28 | /** 29 | * 岗位 30 | */ 31 | private String dept; 32 | 33 | /** 34 | * 浏览器 35 | */ 36 | private String browser; 37 | 38 | /** 39 | * IP 40 | */ 41 | private String ip; 42 | 43 | /** 44 | * 地址 45 | */ 46 | private String address; 47 | 48 | /** 49 | * aes(token) = key 50 | */ 51 | private String key; 52 | 53 | /** 54 | * 32 位 token 摘要 55 | */ 56 | private String summary; 57 | 58 | /** 59 | * 登录时间 60 | */ 61 | private LocalDateTime loginTime; 62 | 63 | @Override 64 | public String toString() { 65 | return JsonUtil.toJson(this); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/session/Session.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.session; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | /** 6 | * @author ZC 7 | * @date 2021/8/7 22:10 8 | */ 9 | public interface Session { 10 | 11 | /** 12 | * 获取session Id 13 | * @return session id 14 | */ 15 | Long getSessionId(); 16 | 17 | /** 18 | * 设置key 19 | * @param key / 20 | */ 21 | void setKey(String key); 22 | 23 | /** 24 | * 获取key 25 | * @return / 26 | */ 27 | String getKey(); 28 | 29 | /** 30 | * 关闭 31 | */ 32 | void close(); 33 | 34 | /** 35 | * 添加属性 36 | * @param key / 37 | * @param value / 38 | */ 39 | void addAttribute(String key, Object value); 40 | 41 | /** 42 | * 获取属性 43 | * @param key / 44 | * @param / 45 | * @return / 46 | */ 47 | T getAttribute(String key); 48 | 49 | /** 50 | * 获取客户端地址 51 | * @return / 52 | */ 53 | String getRemoteAddress(); 54 | 55 | /** 56 | * 获取channel 57 | * @return / 58 | */ 59 | Channel getChannel(); 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/pojo/vo/TokenVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.pojo.vo; 2 | 3 | import com.libre.toolkit.json.JsonUtil; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * token vo 12 | * 13 | * @author L.cm 14 | */ 15 | @Getter 16 | @Setter 17 | public class TokenVO implements Serializable { 18 | 19 | private Long userId; 20 | /** 21 | * 用户名 22 | */ 23 | private String userName; 24 | 25 | /** 26 | * 昵称 27 | */ 28 | private String nickName; 29 | 30 | /** 31 | * 岗位 32 | */ 33 | private String dept; 34 | 35 | /** 36 | * 浏览器 37 | */ 38 | private String browser; 39 | 40 | /** 41 | * IP 42 | */ 43 | private String ip; 44 | 45 | /** 46 | * 地址 47 | */ 48 | private String address; 49 | 50 | /** 51 | * aes(token) = key 52 | */ 53 | private String key; 54 | 55 | /** 56 | * 32 位 token 摘要 57 | */ 58 | private String summary; 59 | 60 | /** 61 | * 登录时间 62 | */ 63 | private LocalDateTime loginTime; 64 | 65 | @Override 66 | public String toString() { 67 | return JsonUtil.toJson(this); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/pojo/SysJobVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.pojo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2022/12/30 11:03 PM 8 | */ 9 | @Data 10 | public class SysJobVO { 11 | 12 | public static final String JOB_KEY = "JOB_KEY"; 13 | 14 | /** 15 | * 定时任务名称 16 | */ 17 | private String jobName; 18 | 19 | /** 20 | * 定时任务组 21 | */ 22 | private String jobGroup; 23 | 24 | /** 25 | * 定时任务beanName 26 | */ 27 | private String beanName; 28 | 29 | /** 30 | * 方法名 31 | */ 32 | private String methodName; 33 | 34 | /** 35 | * 参数 36 | */ 37 | private String params; 38 | 39 | /** 40 | * 触发器名称 41 | */ 42 | private String triggerName; 43 | 44 | /** 45 | * 触发器组 46 | */ 47 | private String triggerGroup; 48 | 49 | /** 50 | * 重复间隔 51 | */ 52 | private Long repeatInterval; 53 | 54 | /** 55 | * 触发次数 56 | */ 57 | private Long timesTriggered; 58 | 59 | /** 60 | * cron 表达式 61 | */ 62 | private String cronExpression; 63 | 64 | /** 65 | * 时区 66 | */ 67 | private String timeZoneId; 68 | 69 | /** 70 | * 定时任务状态 71 | */ 72 | private String triggerState; 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/service/SysJobService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.libre.im.tookit.moudle.quartz.pojo.SysJob; 6 | import com.libre.im.tookit.moudle.quartz.pojo.SysJobCriteria; 7 | 8 | /** 9 | *

10 | * Job Service 11 | *

12 | * 13 | * @author yangkai.shen 14 | * @author L.cm 15 | */ 16 | public interface SysJobService extends IService { 17 | 18 | /** 19 | * 查询定时任务列表 20 | * @param page 分页对象 21 | * @param criteria 查询对象 22 | * @return 定时任务列表 23 | */ 24 | PageDTO findByPage(PageDTO page, SysJobCriteria criteria); 25 | 26 | /** 27 | * 添加并启动定时任务 28 | * 29 | */ 30 | void addJob(SysJob job); 31 | 32 | /** 33 | * 删除定时任务 34 | * 35 | */ 36 | void deleteJob(Long jobId); 37 | 38 | /** 39 | * 暂停定时任务 40 | * 41 | */ 42 | void pauseJob(SysJob sysJob); 43 | 44 | /** 45 | * 恢复定时任务 46 | * 47 | */ 48 | void resumeJob(SysJob sysJob); 49 | 50 | void updateJobStatus(SysJob sysJob); 51 | 52 | /** 53 | * 重新配置定时任务 54 | * 55 | */ 56 | void cronJob(SysJob sysJob); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/dto/MenuDTO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author: Libre 7 | * @Date: 2023/1/8 1:37 AM 8 | */ 9 | @Data 10 | public class MenuDTO { 11 | 12 | private Long id; 13 | 14 | /** 15 | * 父菜单ID 16 | */ 17 | private Long parentId; 18 | 19 | /** 20 | * 菜单标题 21 | */ 22 | private String title; 23 | 24 | /** 25 | * 菜单名称 26 | */ 27 | private String name; 28 | 29 | /** 30 | * 显示顺序 31 | */ 32 | private Integer seq; 33 | 34 | /** 35 | * 路由地址 36 | */ 37 | private String path; 38 | 39 | /** 40 | * 权限标识 41 | */ 42 | private String permission; 43 | 44 | /** 45 | * 组件路径 46 | */ 47 | private String component; 48 | 49 | /** 50 | * 菜单图标 51 | */ 52 | private String icon; 53 | 54 | /** 55 | * 是否为外链(0否 1是) 56 | */ 57 | private Boolean isFrame; 58 | 59 | /** 60 | * 菜单类型(0目录 1菜单 2按钮) 61 | */ 62 | private Integer type; 63 | 64 | /** 65 | * 缓存(0否 1是) 66 | */ 67 | private Boolean cache; 68 | 69 | /** 70 | * 显示状态(0显示,1隐藏) 71 | */ 72 | private Boolean hidden; 73 | 74 | /** 75 | * 菜单状态(0正常 1停用) 76 | */ 77 | private Boolean status; 78 | 79 | /** 80 | * 备注 81 | */ 82 | private String remark; 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/pojo/Conversation.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.io.Serializable; 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @author: Libre 15 | * @Date: 2022/6/13 10:56 PM 16 | */ 17 | @Data 18 | @TableName("im_conversation") 19 | @NoArgsConstructor 20 | public class Conversation implements Serializable { 21 | 22 | @TableId 23 | private Long id; 24 | 25 | private Long userId; 26 | 27 | private Long friendId; 28 | 29 | @TableField(fill = FieldFill.INSERT) 30 | private LocalDateTime createTime; 31 | 32 | private Conversation(Long userId, Long friendId, LocalDateTime createTime) { 33 | this.userId = userId; 34 | this.friendId = friendId; 35 | this.createTime = createTime; 36 | } 37 | 38 | public static Conversation of(Long userId, Long friendId, LocalDateTime createTime) { 39 | return new Conversation(userId, friendId, createTime); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/exception/GlobalExceptionAdvice.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.exception; 2 | 3 | import com.libre.boot.exception.ErrorUtil; 4 | import com.libre.toolkit.exception.LibreException; 5 | import com.libre.toolkit.result.R; 6 | import com.libre.toolkit.result.ResultCode; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.security.authentication.LockedException; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestControllerAdvice; 13 | 14 | /** 15 | * @author: Libre 16 | * @Date: 2022/8/26 11:02 PM 17 | */ 18 | @Slf4j 19 | @RestControllerAdvice 20 | public class GlobalExceptionAdvice { 21 | 22 | @ExceptionHandler(LockedException.class) 23 | @ResponseStatus(HttpStatus.FORBIDDEN) 24 | public R handleError(LockedException e) { 25 | return R.fail(ResultCode.UN_AUTHORIZED, e.getMessage()); 26 | } 27 | 28 | @ExceptionHandler(LibreException.class) 29 | @ResponseStatus(HttpStatus.BAD_REQUEST) 30 | public R handle(LibreException e) { 31 | ErrorUtil.publishEvent(e); 32 | return R.fail(ResultCode.FAILURE, e.getMessage()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysMenuService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.libre.im.system.pojo.dto.MenuCriteria; 6 | import com.libre.im.system.pojo.SysMenu; 7 | 8 | import java.util.Collection; 9 | import java.util.List; 10 | 11 | /** 12 | * @author zhao.cheng 13 | */ 14 | public interface SysMenuService extends IService { 15 | 16 | /** 17 | * 根据角色 id 列表查找菜单 18 | * @param roleIds 角色id 19 | * @return 菜单列表 20 | */ 21 | List getListByRoleIds(Collection roleIds); 22 | 23 | /** 24 | * 超级管理员获取所有菜单 25 | * @return 菜单列表 26 | */ 27 | List getAllMenu(); 28 | 29 | /** 30 | * 根据角色 id 列表查找导航的菜单 31 | * @param roleIds 角色id 32 | * @return 菜单列表 33 | */ 34 | List getNavByRoleIds(Collection roleIds); 35 | 36 | /** 37 | * 添加菜单 38 | * @param menu menu 39 | * @return / 40 | */ 41 | boolean add(SysMenu menu); 42 | 43 | List getSuperior(List ids); 44 | 45 | boolean deleteByIds(List ids); 46 | 47 | List getMenuListByUsername(String username); 48 | 49 | PageDTO findByPage(MenuCriteria criteria); 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/resources/spy.properties: -------------------------------------------------------------------------------- 1 | #3.2.1\u4EE5\u4E0A\u4F7F\u7528 2 | modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory 3 | #3.2.1\u4EE5\u4E0B\u4F7F\u7528\u6216\u8005\u4E0D\u914D\u7F6E 4 | #modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory 5 | # \u81EA\u5B9A\u4E49\u65E5\u5FD7\u6253\u5370 6 | logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger 7 | #\u65E5\u5FD7\u8F93\u51FA\u5230\u63A7\u5236\u53F0 8 | appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger 9 | # \u4F7F\u7528\u65E5\u5FD7\u7CFB\u7EDF\u8BB0\u5F55 sql 10 | #appender=com.p6spy.engine.spy.appender.Slf4JLogger 11 | # \u8BBE\u7F6E p6spy driver \u4EE3\u7406 12 | deregisterdrivers=true 13 | # \u53D6\u6D88JDBC URL\u524D\u7F00 14 | useprefix=true 15 | # \u914D\u7F6E\u8BB0\u5F55 Log \u4F8B\u5916,\u53EF\u53BB\u6389\u7684\u7ED3\u679C\u96C6\u6709error,info,batch,debug,statement,commit,rollback,result,resultset. 16 | excludecategories=info,debug,result,commit,resultset 17 | # \u65E5\u671F\u683C\u5F0F 18 | dateformat=yyyy-MM-dd HH:mm:ss 19 | # \u5B9E\u9645\u9A71\u52A8\u53EF\u591A\u4E2A 20 | driverlist=org.postgresql.Driver 21 | # \u662F\u5426\u5F00\u542F\u6162SQL\u8BB0\u5F55 22 | outagedetection=true 23 | # \u6162SQL\u8BB0\u5F55\u6807\u51C6 2 \u79D2 24 | outagedetectioninterval=2 25 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysDeptService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.libre.im.system.pojo.dto.DeptCriteria; 6 | import com.libre.im.system.pojo.entity.SysDept; 7 | 8 | import java.util.Collection; 9 | import java.util.List; 10 | 11 | /** 12 | * @author zhao.cheng 13 | */ 14 | public interface SysDeptService extends IService { 15 | 16 | /** 17 | * 获取所有的父类 18 | * @param deptList deptList 19 | * @param superiorList 父类 20 | * @return deptList 21 | */ 22 | List getSuperior(List deptList, List superiorList); 23 | 24 | /** 25 | * 获取父级路径ids 26 | * @param deptId / 27 | * @return / 28 | */ 29 | List findSuperiorIds(Long deptId); 30 | 31 | /** 32 | * 获取所有的子部门 33 | * @param deptIdList 部门id列表 34 | * @param childrenList 子部门 35 | * @return deptList 36 | */ 37 | List getChildren(List deptIdList, List childrenList); 38 | 39 | /** 40 | * 如果没用使用时删除 41 | * @param ids id集合 42 | * @return 是否成功 43 | */ 44 | boolean deleteIfUnusedByIds(Collection ids); 45 | 46 | /** 47 | * 分页查询 48 | * @param param / 49 | * @return / 50 | */ 51 | Page findByPage(DeptCriteria param); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/handler/MessageHandlerFactory.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message.handler; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.libre.boot.autoconfigure.SpringContext; 5 | import com.libre.im.websocket.core.exception.LibreImException; 6 | import lombok.experimental.UtilityClass; 7 | import org.springframework.context.ApplicationContext; 8 | 9 | import java.util.Map; 10 | import java.util.Optional; 11 | 12 | /** 13 | * @author ZC 14 | * @date 2021/8/7 14:36 15 | */ 16 | @SuppressWarnings({ "rawtypes", "unchecked" }) 17 | @UtilityClass 18 | public class MessageHandlerFactory { 19 | 20 | private final static Map messageHandlerContext = Maps.newHashMap(); 21 | 22 | static { 23 | ApplicationContext applicationContext = Optional.ofNullable(SpringContext.getContext()) 24 | .orElseThrow(() -> new LibreImException("applicationContext must not be null")); 25 | Map map = applicationContext.getBeansOfType(MessageHandler.class); 26 | for (MessageHandler handler : map.values()) { 27 | Integer code = handler.getMessageType().getCode(); 28 | messageHandlerContext.put(code, handler); 29 | } 30 | } 31 | 32 | public static > T getMessageHandler(Integer type) { 33 | return (T) messageHandlerContext.get(type); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysUserRoleService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.libre.im.system.pojo.entity.SysUserRole; 5 | 6 | import java.util.Collection; 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | /** 11 | * @author zhao.cheng 12 | */ 13 | public interface SysUserRoleService extends IService { 14 | 15 | /** 16 | * 根据用户id获取用户角色关系列表 17 | * @param userId 用户id 18 | * @return 用户角色关系列表 19 | */ 20 | List getListByUserId(Long userId); 21 | 22 | /** 23 | * 根据用户id获取用户角色关系列表 24 | * @param userIds 用户id 25 | * @return 用户角色关系列表 26 | */ 27 | List getListByUserIds(Collection userIds); 28 | 29 | /** 30 | * 根据角色id列表获取用户角色关系 31 | * @param roleIds 角色id 32 | * @return 用户角色关系列表 33 | */ 34 | List getListByRoleIds(Collection roleIds); 35 | 36 | /** 37 | * 保存用户角色 38 | * @param userId 用户id 39 | * @param roleIds 角色id列表 40 | * @return 是否成功 41 | */ 42 | boolean saveByUserIdAndRoleIds(Long userId, List roleIds); 43 | 44 | /** 45 | * 删除用户角色 46 | * @param userId 用户id 47 | * @return 是否成功 48 | */ 49 | boolean deleteByUserId(Long userId); 50 | 51 | /** 52 | * 批量删除用户角色 53 | * @param userIds 用户id 54 | * @return 是否成功 55 | */ 56 | boolean deleteByUserIds(Set userIds); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/session/SessionManager.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.session; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | 5 | /** 6 | * @author ZC 7 | * @date 2021/8/8 16:27 8 | */ 9 | public interface SessionManager { 10 | 11 | /** 12 | * 获取session 13 | * @param sessionId sessionId 14 | * @return {@link Session} 15 | */ 16 | Session getSession(Long sessionId); 17 | 18 | /** 19 | * 获取session 20 | * @param ctx {@link ChannelHandlerContext} 21 | * @return {@link Session} 22 | */ 23 | Session getSession(ChannelHandlerContext ctx); 24 | 25 | /** 26 | * 保存session 27 | * @param sessionId sessionId 28 | * @param session {@link Session} 29 | */ 30 | void put(Long sessionId, Session session); 31 | 32 | 33 | /** 34 | * 移除session 35 | * @param sessionId sessionId 36 | */ 37 | void remove(Long sessionId); 38 | 39 | /** 40 | * 删除Session 41 | * @param Session {@link Session} 42 | */ 43 | void remove(Session Session); 44 | 45 | /** 46 | * 删除Session 47 | * @param ctx {@link ChannelHandlerContext} 48 | */ 49 | void remove(ChannelHandlerContext ctx); 50 | 51 | /** 52 | * 是否存在session 53 | * @param sessionId sessionId 54 | * @return boolean 55 | */ 56 | boolean isExist(Long sessionId); 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/session/WebsocketSession.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.session; 2 | 3 | import io.netty.channel.Channel; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.util.AttributeKey; 6 | 7 | /** 8 | * @author ZC 9 | * @date 2021/8/7 22:32 10 | */ 11 | 12 | public class WebsocketSession extends AbstractSession { 13 | 14 | private WebsocketSession(ChannelHandlerContext ctx, Long sessionId) { 15 | super(ctx, sessionId); 16 | } 17 | 18 | public static WebsocketSession of(ChannelHandlerContext ctx, Long sessionId) { 19 | return new WebsocketSession(ctx, sessionId); 20 | } 21 | 22 | @Override 23 | public Long getSessionId() { 24 | return this.sessionId; 25 | } 26 | 27 | @Override 28 | public Channel getChannel() { 29 | return channel; 30 | } 31 | 32 | @Override 33 | public void setKey(String key) { 34 | 35 | } 36 | 37 | @Override 38 | public String getKey() { 39 | return null; 40 | } 41 | 42 | @Override 43 | public void addAttribute(String key, Object value) { 44 | channel.attr(AttributeKey.valueOf(key)).set(value); 45 | } 46 | 47 | @Override 48 | @SuppressWarnings("unchecked") 49 | public T getAttribute(String key) { 50 | return (T) channel.attr(AttributeKey.valueOf(key)).get(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/codec/JacksonMessageEncoder.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.codec; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.libre.im.websocket.core.message.Message; 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToMessageEncoder; 8 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 9 | 10 | import java.util.List; 11 | import java.util.Objects; 12 | import java.util.Optional; 13 | 14 | import static io.netty.buffer.Unpooled.wrappedBuffer; 15 | 16 | /** 17 | * @author: Libre 18 | * @Date: 2022/5/1 12:45 AM 19 | */ 20 | public class JacksonMessageEncoder extends MessageToMessageEncoder { 21 | 22 | private final ObjectMapper objectMapper; 23 | 24 | public JacksonMessageEncoder(ObjectMapper objectMapper) { 25 | Optional.ofNullable(objectMapper).orElseGet(ObjectMapper::new); 26 | this.objectMapper = objectMapper; 27 | } 28 | 29 | @Override 30 | protected void encode(ChannelHandlerContext channelHandlerContext, Message message, List list) 31 | throws Exception { 32 | if (Objects.isNull(message)) { 33 | return; 34 | } 35 | ByteBuf buf = wrappedBuffer(objectMapper.writeValueAsBytes(message)); 36 | TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(buf); 37 | list.add(textWebSocketFrame); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/impl/SysPostServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.libre.im.system.mapper.SysPostMapper; 5 | import com.libre.im.system.pojo.entity.SysPost; 6 | import com.libre.im.system.pojo.entity.SysUserPost; 7 | import com.libre.im.system.service.SysPostService; 8 | import com.libre.im.system.service.SysUserPostService; 9 | import lombok.RequiredArgsConstructor; 10 | import org.apache.commons.collections4.CollectionUtils; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | import java.util.Set; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * @author zhao.cheng 20 | */ 21 | @Service 22 | @RequiredArgsConstructor 23 | public class SysPostServiceImpl extends ServiceImpl implements SysPostService { 24 | 25 | private final SysUserPostService userPostService; 26 | 27 | @Override 28 | public List getListByUserId(Long userId) { 29 | List userPostList = userPostService.getListByUserId(userId); 30 | if (CollectionUtils.isEmpty(userPostList)) { 31 | return Collections.emptyList(); 32 | } 33 | Set postIds = userPostList.stream().map(SysUserPost::getPostId).collect(Collectors.toSet()); 34 | 35 | return super.listByIds(postIds); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/controller/ConversationController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.controller; 2 | 3 | import com.libre.im.common.security.support.SecurityUtil; 4 | import com.libre.im.websocket.pojo.vo.ConversationVO; 5 | import com.libre.toolkit.result.R; 6 | import com.libre.im.websocket.service.ConversationService; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author: Libre 14 | * @Date: 2022/6/13 11:09 PM 15 | */ 16 | @RestController 17 | @RequestMapping("/conversation") 18 | @RequiredArgsConstructor 19 | public class ConversationController { 20 | 21 | private final ConversationService conversationService; 22 | 23 | @GetMapping("/list") 24 | public R> listByUserId() { 25 | Long userId = SecurityUtil.getUser().getUserId(); 26 | List conversations = conversationService.listByUserId(userId); 27 | return R.data(conversations); 28 | } 29 | 30 | 31 | @PutMapping 32 | public R add(@RequestParam Long friend) { 33 | conversationService.add(friend); 34 | return R.status(Boolean.TRUE); 35 | } 36 | 37 | @DeleteMapping 38 | public R remove(@RequestParam Long friendId) { 39 | Long userId = SecurityUtil.getUser().getUserId(); 40 | conversationService.removeByUserIdAndFriendId(userId, friendId); 41 | return R.status(Boolean.TRUE); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/codec/ProtobufMessageEncoder.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.codec; 2 | 3 | import com.google.protobuf.MessageLite; 4 | import com.libre.im.websocket.core.message.handler.MessageHandler; 5 | import com.libre.im.websocket.core.message.Message; 6 | import com.libre.im.websocket.core.message.handler.MessageHandlerFactory; 7 | import io.netty.buffer.ByteBuf; 8 | import io.netty.buffer.Unpooled; 9 | import io.netty.channel.ChannelHandler; 10 | import io.netty.channel.ChannelHandlerContext; 11 | import io.netty.handler.codec.MessageToMessageEncoder; 12 | import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; 13 | import io.netty.handler.codec.http.websocketx.WebSocketFrame; 14 | import org.springframework.stereotype.Component; 15 | 16 | import java.util.List; 17 | 18 | 19 | @Component 20 | @ChannelHandler.Sharable 21 | public class ProtobufMessageEncoder extends MessageToMessageEncoder { 22 | @Override 23 | protected void encode(ChannelHandlerContext channelHandlerContext, Message message, List list) throws Exception { 24 | MessageHandler messageHandler = MessageHandlerFactory.getMessageHandler(message.getMessageBodyType()); 25 | MessageLite messageLite = messageHandler.getMessage(message); 26 | ByteBuf result = Unpooled.wrappedBuffer((messageLite).toByteArray()); 27 | WebSocketFrame frame = new BinaryWebSocketFrame(result); 28 | list.add(frame); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysRoleService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | import com.libre.im.system.pojo.dto.RoleCriteria; 7 | import com.libre.im.system.pojo.dto.RoleDTO; 8 | import com.libre.im.system.pojo.entity.SysRole; 9 | import com.libre.im.system.pojo.vo.RoleVO; 10 | 11 | import java.util.Collection; 12 | import java.util.List; 13 | 14 | /** 15 | * @author zhao.cheng 16 | */ 17 | public interface SysRoleService extends IService { 18 | 19 | /** 20 | * 分页查询 21 | * @param page 分页对象 22 | * @param roleCriteria 查询对象 23 | * @return PageDTO 24 | */ 25 | PageDTO findByPage(Page page, RoleCriteria roleCriteria); 26 | 27 | /** 28 | * 根据用户 id 获取角色列表 29 | * @param userId 用户id 30 | * @return 角色列表 31 | */ 32 | List getListByUserId(Long userId); 33 | 34 | /** 35 | * 更新角色菜单 36 | * @param role 角色 37 | * @param menuIds 菜单列表 38 | * @return 是否成功 39 | */ 40 | boolean updateMenus(SysRole role, List menuIds); 41 | 42 | /** 43 | * 如果没有使用,删除 44 | * @param ids id 集合 45 | * @return 是否成功 46 | */ 47 | boolean deleteIfUnusedByIds(Collection ids); 48 | 49 | /** 50 | * 编辑 51 | * @param roleDTO / 52 | * @return / 53 | */ 54 | boolean edit(RoleDTO roleDTO); 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/SysUserService.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | import com.libre.im.security.pojo.dto.UserInfo; 7 | import com.libre.im.system.pojo.dto.UserCriteria; 8 | import com.libre.im.system.pojo.dto.UserDTO; 9 | import com.libre.im.system.pojo.entity.SysUser; 10 | import com.libre.im.system.pojo.vo.UserVO; 11 | 12 | import java.util.Set; 13 | 14 | /** 15 | * @author zhao.cheng 16 | */ 17 | public interface SysUserService extends IService { 18 | 19 | /** 20 | * 分页查询 21 | * @param page page 22 | * @param userParam userParam 23 | * @return IPage 24 | */ 25 | PageDTO findByPage(Page page, UserCriteria userParam); 26 | 27 | /** 28 | * 通过id查找用户 29 | * @param id / 30 | * @return / 31 | */ 32 | SysUser findUserById(Long id); 33 | 34 | /** 35 | * 根据登录名查找用户 36 | * @param username 登录名 37 | * @return 用户 38 | */ 39 | SysUser getByUsername(String username); 40 | 41 | /** 42 | * 按照用户账号更新 43 | * @param sysUser 用户 44 | */ 45 | boolean updateByUsername(String username, SysUser sysUser); 46 | 47 | UserInfo findUserInfoByUsername(String username); 48 | 49 | boolean createUser(UserDTO user); 50 | 51 | boolean updateUser(UserDTO user); 52 | 53 | boolean deleteUserByIds(Set ids); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/support/ReflectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.support; 2 | 3 | import org.springframework.core.DefaultParameterNameDiscoverer; 4 | import org.springframework.core.MethodParameter; 5 | import org.springframework.core.ParameterNameDiscoverer; 6 | import org.springframework.core.annotation.SynthesizingMethodParameter; 7 | import org.springframework.util.ReflectionUtils; 8 | 9 | import java.lang.reflect.Constructor; 10 | import java.lang.reflect.Method; 11 | 12 | /** 13 | * @author: Libre 14 | * @Date: 2022/12/17 6:41 PM 15 | */ 16 | public class ReflectionUtil extends ReflectionUtils { 17 | 18 | private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); 19 | 20 | public static MethodParameter getMethodParameter(Constructor constructor, int parameterIndex) { 21 | MethodParameter methodParameter = new SynthesizingMethodParameter(constructor, parameterIndex); 22 | methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER); 23 | return methodParameter; 24 | } 25 | 26 | /** 27 | * 获取方法参数信息 28 | * @param method 方法 29 | * @param parameterIndex 参数序号 30 | * @return {MethodParameter} 31 | */ 32 | public static MethodParameter getMethodParameter(Method method, int parameterIndex) { 33 | MethodParameter methodParameter = new SynthesizingMethodParameter(method, parameterIndex); 34 | methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER); 35 | return methodParameter; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/SysMenu.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.libre.im.common.pojo.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | /** 10 | * 菜单表 11 | * 12 | * @author zhao.cheng 13 | */ 14 | @ApiModel(value = "菜单表") 15 | @Data 16 | @EqualsAndHashCode(callSuper = true) 17 | @TableName(value = "sys_menu") 18 | public class SysMenu extends BaseEntity { 19 | 20 | /** 21 | * 父菜单ID 22 | */ 23 | private Long parentId; 24 | 25 | /** 26 | * 菜单标题 27 | */ 28 | private String title; 29 | 30 | /** 31 | * 菜单名称 32 | */ 33 | private String name; 34 | 35 | /** 36 | * 显示顺序 37 | */ 38 | private Integer seq; 39 | 40 | /** 41 | * 路由地址 42 | */ 43 | private String path; 44 | 45 | /** 46 | * 权限标识 47 | */ 48 | private String permission; 49 | 50 | /** 51 | * 组件路径 52 | */ 53 | private String component; 54 | 55 | /** 56 | * 菜单图标 57 | */ 58 | private String icon; 59 | 60 | /** 61 | * 是否为外链(0否 1是) 62 | */ 63 | private Integer isFrame; 64 | 65 | /** 66 | * 菜单类型(0目录 1菜单 2按钮) 67 | */ 68 | private Integer type; 69 | 70 | /** 71 | * 缓存(0否 1是) 72 | */ 73 | private Integer cache; 74 | 75 | /** 76 | * 显示状态(0显示,1隐藏) 77 | */ 78 | private Integer hidden; 79 | 80 | /** 81 | * 菜单状态(0正常 1停用) 82 | */ 83 | private Integer status; 84 | 85 | /** 86 | * 备注 87 | */ 88 | private String remark; 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/test/java/com/libre/im/MessageCodecTests.java: -------------------------------------------------------------------------------- 1 | package com.libre.im; 2 | 3 | import com.libre.im.websocket.core.codec.ProtobufMessageDecoder; 4 | import com.libre.im.websocket.core.codec.ProtobufMessageEncoder; 5 | import com.libre.im.websocket.core.proto.TextMessageProto; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.channel.SimpleChannelInboundHandler; 8 | import io.netty.channel.embedded.EmbeddedChannel; 9 | import io.netty.handler.codec.protobuf.ProtobufDecoder; 10 | 11 | /** 12 | * @author: Libre 13 | * @Date: 2022/5/1 9:16 AM 14 | */ 15 | public class MessageCodecTests { 16 | 17 | public static void test() { 18 | EmbeddedChannel embeddedChannel = new EmbeddedChannel( 19 | new ProtobufMessageDecoder(), 20 | new ProtobufMessageEncoder(), 21 | new ProtobufDecoder(TextMessageProto.TextMessage.getDefaultInstance()), 22 | new SimpleChannelInboundHandler() { 23 | @Override 24 | protected void channelRead0(ChannelHandlerContext ctx, TextMessageProto.TextMessage msg) throws Exception { 25 | System.out.println(msg); 26 | } 27 | } 28 | ); 29 | 30 | TextMessageProto.TextMessage.Builder builder = TextMessageProto.TextMessage.newBuilder(); 31 | TextMessageProto.TextMessage message = builder.setBody("124").build(); 32 | embeddedChannel.writeInbound(message); 33 | } 34 | 35 | public static void main(String[] args) { 36 | test(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/impl/SysDictInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.Wrapper; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.libre.im.system.mapper.SysDictInfoMapper; 7 | import com.libre.im.system.pojo.dto.DictInfoCriteria; 8 | import com.libre.im.system.pojo.entity.SysDictInfo; 9 | import com.libre.im.system.service.SysDictInfoService; 10 | import com.libre.toolkit.core.StringUtil; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.Collection; 14 | import java.util.List; 15 | 16 | /** 17 | *

18 | * 字典详情表 服务实现类 19 | *

20 | * 21 | * @author L.cm 22 | * @since 2020-07-19 23 | */ 24 | @Service 25 | public class SysDictInfoServiceImpl extends ServiceImpl implements SysDictInfoService { 26 | 27 | @Override 28 | public Wrapper getQueryWrapper(DictInfoCriteria query) { 29 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 30 | wrapper.like(StringUtil.isNotBlank(query.getLabel()), SysDictInfo::getLabel, query.getLabel()); 31 | wrapper.eq(StringUtil.isNotBlank(query.getName()), SysDictInfo::getType, query.getName()); 32 | return wrapper; 33 | } 34 | 35 | @Override 36 | public List getListByDictNames(Collection dictNames) { 37 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 38 | wrapper.in(SysDictInfo::getType, dictNames); 39 | return super.list(wrapper); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/session/RedissonSessionManager.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.session; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.redisson.api.*; 5 | 6 | /** 7 | * @author: Libre 8 | * @Date: 2022/5/5 2:30 AM 9 | */ 10 | 11 | @RequiredArgsConstructor 12 | public class RedissonSessionManager extends AbstractSessionManager { 13 | 14 | private final RedissonClient redissonClient; 15 | public final static String SESSION_KEY = "libre:im:session:"; 16 | 17 | @Override 18 | public Session getSession(Long sessionId) { 19 | RBucket bucket = getSessionBucket(sessionId); 20 | return bucket.get(); 21 | } 22 | 23 | @Override 24 | public void put(Long sessionId, Session session) { 25 | RBucket bucket = getSessionBucket(sessionId); 26 | bucket.set(session); 27 | } 28 | 29 | @Override 30 | public void remove(Long sessionId) { 31 | RBucket bucket = getSessionBucket(sessionId); 32 | bucket.deleteAsync(); 33 | } 34 | 35 | 36 | @Override 37 | public void remove(Session Session) { 38 | Long sessionId = Session.getSessionId(); 39 | remove(sessionId); 40 | } 41 | 42 | 43 | @Override 44 | public boolean isExist(Long sessionId) { 45 | RBucket bucket = getSessionBucket(sessionId); 46 | return bucket.isExists(); 47 | } 48 | 49 | private RBucket getSessionBucket(Long sessionId) { 50 | return redissonClient.getBucket(getSessionKey(sessionId)); 51 | } 52 | 53 | private String getSessionKey(Long sessionId) { 54 | return SESSION_KEY + sessionId; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/config/MybatisPlusMetaObjectHandler.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.config; 2 | 3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; 4 | import com.libre.im.common.security.dto.AuthUser; 5 | import com.libre.im.common.security.support.SecurityUtil; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.ibatis.reflection.MetaObject; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.time.LocalDateTime; 11 | import java.util.Objects; 12 | 13 | /** 14 | * @author Libre 15 | * @date 2021/7/13 16:33 16 | */ 17 | @Slf4j 18 | @Component 19 | public class MybatisPlusMetaObjectHandler implements MetaObjectHandler { 20 | 21 | private static final String SYSTEM = "System"; 22 | 23 | @Override 24 | public void insertFill(MetaObject metaObject) { 25 | this.strictInsertFill(metaObject, "gmtCreate", LocalDateTime.class, LocalDateTime.now()); 26 | this.strictInsertFill(metaObject, "gmtModified", LocalDateTime.class, LocalDateTime.now()); 27 | this.strictInsertFill(metaObject, "gmtCreateName", String.class, getUsername()); 28 | this.strictInsertFill(metaObject, "gmtModifiedName", String.class, getUsername()); 29 | } 30 | 31 | @Override 32 | public void updateFill(MetaObject metaObject) { 33 | this.strictInsertFill(metaObject, "gmtModified", LocalDateTime.class, LocalDateTime.now()); 34 | this.strictInsertFill(metaObject, "gmtModifiedName", String.class, getUsername()); 35 | } 36 | 37 | private String getUsername() { 38 | AuthUser user = SecurityUtil.getUser(); 39 | if (Objects.isNull(user)) { 40 | return SYSTEM; 41 | } 42 | String username = user.getUsername(); 43 | return username == null ? SYSTEM : username; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/SysUser.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.libre.im.common.pojo.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.v3.oas.annotations.media.Schema; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | import lombok.ToString; 10 | 11 | /** 12 | * 用户表 13 | * 14 | * @author zhao.cheng 15 | */ 16 | @ApiModel(value = "用户表") 17 | @Data 18 | @EqualsAndHashCode(callSuper = true) 19 | @ToString(callSuper = true) 20 | @TableName(value = "sys_user") 21 | public class SysUser extends BaseEntity { 22 | 23 | /** 24 | * 账户 25 | */ 26 | @Schema(description = "账户") 27 | private String username; 28 | 29 | /** 30 | * 密码 31 | */ 32 | @Schema(description = "密码") 33 | private String password; 34 | 35 | /** 36 | * 昵称 37 | */ 38 | @Schema(description = "昵称") 39 | private String nickName; 40 | 41 | /** 42 | * 头像 43 | */ 44 | @Schema(description = "头像") 45 | private String avatar; 46 | 47 | /** 48 | * 电话 49 | */ 50 | @Schema(description = "电话") 51 | private String phone; 52 | 53 | /** 54 | * 邮件 55 | */ 56 | @Schema(description = "邮件") 57 | private String email; 58 | 59 | /** 60 | * 性别 61 | */ 62 | @Schema(description = "性别") 63 | private Integer gender; 64 | 65 | /** 66 | * 用户类型(0系统用户 1管理员) 67 | */ 68 | @Schema(description = "用户类型(0系统用户 1管理员)") 69 | private Integer isAdmin; 70 | 71 | /** 72 | * 帐号状态(0停用 1正常) 73 | */ 74 | @Schema(description = "帐号状态(0停用 1正常)") 75 | private Integer enabled; 76 | 77 | /** 78 | * 登录状态(0:正常 1:锁定) 79 | */ 80 | @Schema(description = "登录状态") 81 | private Integer locked; 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/support/ScheduleJob.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.support; 2 | 3 | import com.libre.boot.autoconfigure.SpringContext; 4 | import com.libre.im.log.support.ReflectionUtil; 5 | import com.libre.im.tookit.moudle.quartz.pojo.SysJob; 6 | import com.libre.toolkit.exception.LibreException; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.quartz.JobExecutionContext; 10 | import org.springframework.scheduling.quartz.QuartzJobBean; 11 | 12 | import java.lang.reflect.Method; 13 | import java.util.Objects; 14 | 15 | @Slf4j 16 | public class ScheduleJob extends QuartzJobBean { 17 | 18 | @Override 19 | protected void executeInternal(JobExecutionContext context) { 20 | SysJob scheduleJob = (SysJob) context.getMergedJobDataMap().get(SysJob.JOB_KEY); 21 | 22 | Object bean = SpringContext.getBean(scheduleJob.getBeanName()); 23 | 24 | if (Objects.isNull(bean)) { 25 | throw new LibreException("bean is not exist, beanName: " + scheduleJob.getBeanName()); 26 | } 27 | String methodName = scheduleJob.getMethodName(); 28 | Method method; 29 | 30 | String params = scheduleJob.getParams(); 31 | try { 32 | if (StringUtils.isNotBlank(params)) { 33 | method = bean.getClass().getDeclaredMethod(methodName, String.class); 34 | ReflectionUtil.makeAccessible(method); 35 | ReflectionUtil.invokeMethod(method, bean, params); 36 | } 37 | else { 38 | method = bean.getClass().getDeclaredMethod(methodName); 39 | ReflectionUtil.makeAccessible(method); 40 | ReflectionUtil.invokeMethod(method, bean); 41 | } 42 | } 43 | catch (NoSuchMethodException e) { 44 | throw new RuntimeException(e); 45 | } 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/handler/MediaMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message.handler; 2 | 3 | import com.libre.im.websocket.core.exception.LibreImException; 4 | import com.libre.im.websocket.core.message.MediaMessage; 5 | import com.libre.im.websocket.core.message.Message; 6 | import com.libre.im.websocket.core.message.enums.MessageBodyType; 7 | import com.libre.im.websocket.core.proto.TextMessageProto; 8 | import com.libre.im.websocket.core.session.SessionManager; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.util.ObjectUtils; 12 | 13 | /** 14 | * @author ZC 15 | * @date 2021/8/7 14:07 16 | */ 17 | @Slf4j 18 | @Component 19 | public class MediaMessageHandler extends AbstractMessageHandler { 20 | private final SessionManager sessionManager; 21 | public MediaMessageHandler(SessionManager sessionManager) { 22 | super(sessionManager); 23 | this.sessionManager = sessionManager; 24 | } 25 | 26 | @Override 27 | public MessageBodyType getMessageType() { 28 | return MessageBodyType.MEDIA; 29 | } 30 | 31 | @Override 32 | public MediaMessage newInstance() { 33 | return new MediaMessage(); 34 | } 35 | 36 | @Override 37 | public TextMessageProto.TextMessage getMessage(Message message) { 38 | if (ObjectUtils.nullSafeEquals(getMessageType().getCode(), message.getMessageBodyType())) { 39 | MediaMessage mediaMessage = (MediaMessage) message; 40 | } 41 | throw new LibreImException("messageBodyType match failed"); 42 | } 43 | 44 | @Override 45 | protected void sendMessage(Message message) { 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/session/AbstractSession.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.session; 2 | 3 | import com.libre.im.websocket.core.constant.LibreIMConstants; 4 | import io.netty.channel.Channel; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.ChannelFutureListener; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.handler.codec.http.DefaultFullHttpResponse; 9 | import io.netty.handler.codec.http.HttpResponseStatus; 10 | import io.netty.handler.codec.http.HttpVersion; 11 | import org.springframework.util.Assert; 12 | 13 | import java.net.InetSocketAddress; 14 | 15 | /** 16 | * @author ZC 17 | * @date 2021/8/7 22:26 18 | */ 19 | public abstract class AbstractSession implements Session { 20 | 21 | protected final ChannelHandlerContext ctx; 22 | protected final Long sessionId; 23 | protected final Channel channel; 24 | 25 | protected AbstractSession(ChannelHandlerContext ctx, Long sessionId) { 26 | Assert.notNull(ctx, "ChannelHandlerContext must not be null"); 27 | this.ctx = ctx; 28 | Assert.notNull(sessionId, "sessionId must not be null"); 29 | this.sessionId = sessionId; 30 | this.channel = ctx.channel(); 31 | ctx.channel().attr(LibreIMConstants.SERVER_SESSION_ID).set(sessionId); 32 | } 33 | 34 | @Override 35 | public String getRemoteAddress() { 36 | InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress(); 37 | return socketAddress.getAddress().toString(); 38 | } 39 | 40 | @Override 41 | public void close() { 42 | ChannelFuture cf = ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN)); 43 | cf.addListener(ChannelFutureListener.CLOSE); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/config/LibreIMExceptionAdvice.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.config; 2 | 3 | import com.libre.toolkit.result.R; 4 | import com.libre.toolkit.result.ResultCode; 5 | import com.libre.toolkit.core.Exceptions; 6 | import com.libre.im.websocket.core.exception.LibreImException; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.security.authentication.BadCredentialsException; 10 | import org.springframework.security.authentication.LockedException; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.ResponseStatus; 13 | import org.springframework.web.bind.annotation.RestControllerAdvice; 14 | 15 | /** 16 | * @author: Libre 17 | * @Date: 2022/5/30 11:46 PM 18 | */ 19 | @Slf4j 20 | @RestControllerAdvice 21 | public class LibreIMExceptionAdvice { 22 | 23 | @ExceptionHandler(BadCredentialsException.class) 24 | @ResponseStatus(HttpStatus.UNAUTHORIZED) 25 | public R handleError(BadCredentialsException e) { 26 | log.error("认证失败: {}", Exceptions.getStackTraceAsString(e)); 27 | String message = String.format("%s", e.getMessage()); 28 | return R.fail(ResultCode.UN_AUTHORIZED, message); 29 | } 30 | 31 | @ExceptionHandler(LockedException.class) 32 | @ResponseStatus(HttpStatus.UNAUTHORIZED) 33 | public R handleError(LockedException e) { 34 | String message = String.format("%s", e.getMessage()); 35 | return R.fail(ResultCode.UN_AUTHORIZED, message); 36 | } 37 | 38 | @ExceptionHandler(LibreImException.class) 39 | @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 40 | public R handleError(LibreImException e) { 41 | String message = String.format("%s", e.getMessage()); 42 | return R.fail(ResultCode.INTERNAL_SERVER_ERROR, message); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/controller/AuthTokenController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.controller; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 5 | import com.libre.im.security.pojo.vo.TokenVO; 6 | import com.libre.im.security.jwt.JwtTokenStore; 7 | import com.libre.toolkit.result.R; 8 | import io.swagger.v3.oas.annotations.Operation; 9 | import io.swagger.v3.oas.annotations.tags.Tag; 10 | import lombok.RequiredArgsConstructor; 11 | import org.springframework.security.access.prepost.PreAuthorize; 12 | import org.springframework.validation.annotation.Validated; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | import javax.validation.constraints.NotEmpty; 16 | import java.util.Set; 17 | 18 | /** 19 | * 认证 token 管理 20 | * 21 | * @author L.cm 22 | */ 23 | @Validated 24 | @RestController 25 | @RequiredArgsConstructor 26 | @RequestMapping("/api/auth/token") 27 | @Tag(name = "系统:token管理") 28 | public class AuthTokenController { 29 | 30 | private final JwtTokenStore tokenStore; 31 | 32 | // @Operation(summary = "导出数据") 33 | // @GetMapping("/download") 34 | // @ResponseExcel(name = "认证token") 35 | // @PreAuthorize("@sec.isAuthenticated()") 36 | // public List download(String filter) { 37 | // return tokenStore.getAll(filter); 38 | // } 39 | 40 | @Operation(summary = "查询列表") 41 | @GetMapping 42 | @PreAuthorize("@sec.isAuthenticated()") 43 | public R> query(PageDTO page, String filter) { 44 | return R.data(tokenStore.page(page, filter)); 45 | } 46 | 47 | @Operation(summary = "踢出用户") 48 | @DeleteMapping 49 | @PreAuthorize("@sec.isAdmin()") 50 | public R delete(@NotEmpty @RequestBody Set keys) { 51 | tokenStore.remove(keys); 52 | return R.status(true); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/codec/JacksonMessageDecoder.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.codec; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.libre.im.websocket.core.message.MediaMessage; 5 | import com.libre.im.websocket.core.message.TextMessage; 6 | import io.netty.buffer.ByteBuf; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.handler.codec.MessageToMessageDecoder; 9 | import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; 10 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 11 | import io.netty.handler.codec.http.websocketx.WebSocketFrame; 12 | 13 | import java.util.List; 14 | import java.util.Optional; 15 | 16 | /** 17 | * @author: Libre 18 | * @Date: 2022/4/30 3:21 AM 19 | */ 20 | public class JacksonMessageDecoder extends MessageToMessageDecoder { 21 | 22 | private final ObjectMapper objectMapper; 23 | 24 | public JacksonMessageDecoder(ObjectMapper objectMapper) { 25 | Optional.ofNullable(objectMapper).orElseGet(ObjectMapper::new); 26 | this.objectMapper = objectMapper; 27 | } 28 | 29 | @Override 30 | protected void decode(ChannelHandlerContext channelHandlerContext, WebSocketFrame webSocketFrame, List objects) throws Exception { 31 | ByteBuf byteBuf = webSocketFrame.content(); 32 | byte[] data = new byte[byteBuf.readableBytes()]; 33 | byteBuf.readBytes(data); 34 | if (webSocketFrame instanceof TextWebSocketFrame) { 35 | TextMessage textMessage = objectMapper.readValue(data, TextMessage.class); 36 | objects.add(textMessage); 37 | } else if (webSocketFrame instanceof BinaryWebSocketFrame) { 38 | MediaMessage mediaMessage = objectMapper.readValue(data, MediaMessage.class); 39 | objects.add(mediaMessage); 40 | } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/controller/MonitorController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.controller; 2 | 3 | import com.libre.im.system.service.MonitorService; 4 | import com.libre.toolkit.result.R; 5 | import io.swagger.v3.oas.annotations.Operation; 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.security.access.prepost.PreAuthorize; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import javax.sql.DataSource; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | /** 17 | * @author: Libre 18 | * @Date: 2022/12/18 7:37 PM 19 | */ 20 | 21 | @RequestMapping("/api/sys/monitor") 22 | @RestController 23 | @RequiredArgsConstructor 24 | public class MonitorController { 25 | 26 | private final MonitorService monitorService; 27 | 28 | private final DataSource dataSource; 29 | 30 | @GetMapping("/server") 31 | @Operation(summary = "服务器监控") 32 | @PreAuthorize("@sec.hasPermission('system:monitor:servers')") 33 | public R> server() { 34 | Map serverInfo = monitorService.getServerInfo(); 35 | return R.data(serverInfo); 36 | } 37 | 38 | // @GetMapping("sql") 39 | // @Operation(summary = "sql监控") 40 | // @PreAuthorize("@sec.hasPermission('system:monitor:sql')") 41 | // public R>> sqlStat() { 42 | // DruidStatManagerFacade statManagerFacade = DruidStatManagerFacade.getInstance(); 43 | // return R.data(statManagerFacade.getSqlStatDataList(dataSource)); 44 | // } 45 | 46 | @GetMapping("redis") 47 | @Operation(summary = "redis监控") 48 | @PreAuthorize("@sec.hasPermission('system:monitor:redis')") 49 | public R> redisStat() { 50 | Map redisStat = monitorService.getRedisStat(); 51 | return R.data(redisStat); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/entity/Client.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import com.libre.im.common.pojo.BaseEntity; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.v3.oas.annotations.media.Schema; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | /** 11 | * 客户端表 12 | * 13 | * @author zhao.cheng 14 | */ 15 | @ApiModel(value = "客户端表") 16 | @Data 17 | @EqualsAndHashCode(callSuper = true) 18 | @TableName(value = "sys_client") 19 | public class Client extends BaseEntity { 20 | 21 | /** 22 | * 客户端id 23 | */ 24 | @Schema(description = "客户端id") 25 | private String clientId; 26 | 27 | /** 28 | * 客户端密钥 29 | */ 30 | @Schema(description = "客户端密钥") 31 | private String clientSecret; 32 | 33 | /** 34 | * 资源集合 35 | */ 36 | @Schema(description = "资源集合") 37 | private String resourceIds; 38 | 39 | /** 40 | * 授权范围 41 | */ 42 | @Schema(description = "授权范围") 43 | private String scope; 44 | 45 | /** 46 | * 授权类型 47 | */ 48 | @Schema(description = "授权类型") 49 | private String authorizedGrantTypes; 50 | 51 | /** 52 | * 回调地址 53 | */ 54 | @Schema(description = "回调地址") 55 | private String webServerRedirectUri; 56 | 57 | /** 58 | * 权限 59 | */ 60 | @Schema(description = "权限") 61 | private String authorities; 62 | 63 | /** 64 | * 令牌过期秒数 65 | */ 66 | @Schema(description = "令牌过期秒数") 67 | private Integer accessTokenValidity; 68 | 69 | /** 70 | * 刷新令牌过期秒数 71 | */ 72 | @Schema(description = "刷新令牌过期秒数") 73 | private Integer refreshTokenValidity; 74 | 75 | /** 76 | * 附加说明 77 | */ 78 | @Schema(description = "附加说明") 79 | private String additionalInformation; 80 | 81 | /** 82 | * 自动授权 83 | */ 84 | @Schema(description = "自动授权") 85 | private String autoapprove; 86 | 87 | /** 88 | * 状态 89 | */ 90 | @Schema(description = "状态") 91 | private Integer status; 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/service/impl/MessageServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.google.common.collect.ArrayListMultimap; 6 | import com.libre.im.websocket.constant.MessageConstant; 7 | import com.libre.im.websocket.pojo.ChatMessage; 8 | import com.libre.toolkit.core.StreamUtils; 9 | import com.libre.im.websocket.mapper.MessageMapper; 10 | import com.libre.im.websocket.service.MessageService; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.util.CollectionUtils; 13 | 14 | import java.util.*; 15 | import java.util.stream.Collectors; 16 | 17 | /** 18 | * @author: Libre 19 | * @Date: 2022/5/23 10:54 PM 20 | */ 21 | @Service 22 | public class MessageServiceImpl extends ServiceImpl implements MessageService { 23 | 24 | @Override 25 | public ArrayListMultimap findMessagesBySendUserIds(Collection userIds) { 26 | ArrayListMultimap messageMultimap = ArrayListMultimap.create(); 27 | if (CollectionUtils.isEmpty(userIds)) { 28 | return messageMultimap; 29 | } 30 | List messageList = this.list(Wrappers.lambdaQuery() 31 | .eq(ChatMessage::getStatus, MessageConstant.UNREAD).in(ChatMessage::getSendUserId, userIds)); 32 | if (CollectionUtils.isEmpty(messageList)) { 33 | return messageMultimap; 34 | } 35 | Map> messageMap = StreamUtils.listGroupBy(messageList, ChatMessage::getSendUserId); 36 | messageMap.forEach((userId, messages) -> { 37 | List chatMessages = messages.stream() 38 | .sorted(Comparator.comparing(ChatMessage::getCreateTime).reversed()).collect(Collectors.toList()); 39 | messageMultimap.putAll(userId, chatMessages); 40 | }); 41 | return messageMultimap; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/resources/application-quartz.yml: -------------------------------------------------------------------------------- 1 | # quartz 配置 2 | spring: 3 | quartz: 4 | auto-startup: true 5 | startup-delay: 3s 6 | job-store-type: jdbc #数据库方式 7 | wait-for-jobs-to-complete-on-shutdown: true 8 | jdbc: 9 | initialize-schema: never # 首次可以采用 always, never 不初始化表结构 10 | properties: 11 | org: 12 | quartz: 13 | scheduler: 14 | instanceId: AUTO #默认主机名和时间戳生成实例ID,可以是任何字符串,但对于所有调度程序来说,必须是唯一的 对应qrtz_scheduler_state INSTANCE_NAME字段 15 | instanceName: ${spring.application.name} #defaultScheduler #quartzScheduler 16 | skipUpdateCheck: true 17 | jobStore: 18 | class: org.springframework.scheduling.quartz.LocalDataSourceJobStore # springboot > 2.5.6后使用这个。 19 | driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate #我们仅为数据库制作了特定于数据库的代理 20 | useProperties: false #以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串,因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看,这是更安全的,因为您避免了将非String类序列化为BLOB的类版本问题。 21 | tablePrefix: qrtz_ #数据库表前缀 22 | misfireThreshold: 60000 #在被认为“失火”之前,调度程序将“容忍”一个Triggers将其下一个启动时间通过的毫秒数。默认值(如果您在配置中未输入此属性)为60000(60秒)。 23 | clusterCheckinInterval: 5000 #设置此实例“检入”*与群集的其他实例的频率(以毫秒为单位)。影响检测失败实例的速度。 24 | isClustered: true #打开群集功能 25 | acquireTriggersWithinLock: true # 在调度流程的第一步,也就是拉取待即将触发的triggers时,是上锁的状态,即不会同时存在多个线程拉取到相同的trigger的情况,也就避免的重复调度的危险。参考:https://segmentfault.com/a/1190000015492260 26 | threadPool: #线程池 27 | class: org.quartz.simpl.SimpleThreadPool 28 | threadCount: 10 29 | threadPriority: 5 30 | threadsInheritContextClassLoaderOfInitializingThread: true 31 | plugin: 32 | triggHistory: 33 | class: org.quartz.plugins.history.LoggingJobHistoryPlugin 34 | shutdownhook: 35 | class: org.quartz.plugins.management.ShutdownHookPlugin 36 | cleanShutdown: true -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/pojo/vo/UserVO.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.pojo.vo; 2 | 3 | import com.libre.im.system.pojo.entity.SysDept; 4 | import com.libre.im.system.pojo.entity.SysPost; 5 | import com.libre.im.system.pojo.entity.SysRole; 6 | import lombok.Data; 7 | 8 | import java.time.LocalDateTime; 9 | import java.util.List; 10 | 11 | /** 12 | * @author Libre 13 | * @date 2022/1/1 18:31 14 | */ 15 | @Data 16 | public class UserVO { 17 | 18 | /** 19 | * 主键ID 20 | */ 21 | private Long id; 22 | 23 | /** 24 | * 部门ID 25 | */ 26 | private Long deptId; 27 | 28 | /** 29 | * 部门信息 {id: 2, name: "研发部"} 30 | */ 31 | private SysDept dept; 32 | 33 | /** 34 | * 岗位信息 [{id: 12, name: "软件测试"}] 35 | */ 36 | private List posts; 37 | 38 | /** 39 | * 角色信息 [{id: 2, name: "普通用户", level: 2, dataScope: "自定义"}, {id: 1, name: "超级管理员", 40 | * level: 1, dataScope: "全部"}] 41 | */ 42 | private List roles; 43 | 44 | private List permissions; 45 | 46 | /** 47 | * 用户账号 48 | */ 49 | private String username; 50 | 51 | /** 52 | * 用户昵称 53 | */ 54 | private String nickName; 55 | 56 | /** 57 | * 用户邮箱 58 | */ 59 | private String email; 60 | 61 | /** 62 | * 手机号码 63 | */ 64 | private String phone; 65 | 66 | /** 67 | * 用户性别(0男 1女 2未知) 68 | */ 69 | private Integer gender; 70 | 71 | /** 72 | * 头像地址 73 | */ 74 | private String avatar; 75 | 76 | /** 77 | * 用户类型(0系统用户 1管理员) 78 | */ 79 | private Integer isAdmin; 80 | 81 | /** 82 | * 帐号状态(0停用 1正常) 83 | */ 84 | private Integer enabled; 85 | 86 | /** 87 | * 登录状态(0:正常 1:锁定) 88 | */ 89 | private Integer locked; 90 | 91 | /** 92 | * 备注 93 | */ 94 | private String remark; 95 | 96 | /** 97 | * 创建时间 98 | */ 99 | private LocalDateTime gmtCreate; 100 | 101 | /** 102 | * 更新时间 103 | */ 104 | private LocalDateTime gmtModified; 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/impl/SysRoleMenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.Wrapper; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import com.libre.im.system.mapper.RoleMenuMapper; 8 | import com.libre.im.system.pojo.entity.SysRoleMenu; 9 | import com.libre.im.system.service.SysRoleMenuService; 10 | import org.apache.commons.collections4.CollectionUtils; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.Collection; 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * @author Libre 20 | */ 21 | @Service 22 | public class SysRoleMenuServiceImpl extends ServiceImpl implements SysRoleMenuService { 23 | 24 | @Override 25 | public List getListByRoleIds(Collection roleIds) { 26 | return super.list(Wrappers.lambdaQuery().in(SysRoleMenu::getRoleId, roleIds)); 27 | } 28 | 29 | @Override 30 | public List getIdListByRoleIds(Collection roleIds) { 31 | List roleMenuList = this.getListByRoleIds(roleIds); 32 | if (CollectionUtils.isEmpty(roleMenuList)) { 33 | return Collections.emptyList(); 34 | } 35 | return roleMenuList.stream().map(SysRoleMenu::getMenuId).distinct().collect(Collectors.toList()); 36 | } 37 | 38 | @Override 39 | public boolean deleteByRoleId(Long roleId) { 40 | Wrapper wrapper = new LambdaQueryWrapper().eq(SysRoleMenu::getRoleId, roleId); 41 | return super.remove(wrapper); 42 | } 43 | 44 | @Override 45 | public List getListByMenuIds(List ids) { 46 | Wrapper wrapper = new LambdaQueryWrapper().in(SysRoleMenu::getMenuId, ids); 47 | return super.list(wrapper); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/security/support/SecurityUtil.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.security.support; 2 | 3 | import com.libre.boot.toolkit.RequestUtils; 4 | import com.libre.im.common.security.constant.SecurityConstant; 5 | import com.libre.im.common.security.dto.AuthUser; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | /** 13 | * @author Libre 14 | * @date 2021/7/12 14:53 15 | */ 16 | public class SecurityUtil { 17 | 18 | /** 19 | * 角色前缀 20 | */ 21 | public static final String SECURITY_ROLE_PREFIX = "ROLE_"; 22 | 23 | /** 24 | * 获取Authentication 25 | */ 26 | public static Authentication getAuthentication() { 27 | return SecurityContextHolder.getContext().getAuthentication(); 28 | } 29 | 30 | /** 31 | * 获取用户 32 | */ 33 | public static AuthUser getUser(Authentication authentication) { 34 | Object principal = authentication.getPrincipal(); 35 | if (principal instanceof AuthUser) { 36 | return ((AuthUser) principal); 37 | } 38 | return null; 39 | } 40 | 41 | /** 42 | * 获取用户 43 | */ 44 | public static AuthUser getUser() { 45 | Authentication authentication = getAuthentication(); 46 | if (authentication == null) { 47 | return null; 48 | } 49 | return getUser(authentication); 50 | } 51 | 52 | /** 53 | * 获取用户名 54 | */ 55 | public static String getUserName() { 56 | AuthUser authUser = getUser(); 57 | return authUser == null ? null : authUser.getUsername(); 58 | } 59 | 60 | /** 61 | * 退出 62 | */ 63 | public static void logout() { 64 | HttpServletRequest request = RequestUtils.getRequest(); 65 | new SecurityContextLogoutHandler().logout(request, null, null); 66 | } 67 | 68 | public static boolean isAdmin(Integer isAdmin) { 69 | return SecurityConstant.IS_ADMIN_YES.equals(isAdmin); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/session/DefaultSessionManager.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.session; 2 | 3 | import com.google.common.cache.Cache; 4 | import com.libre.im.websocket.core.constant.LibreIMConstants; 5 | import com.libre.toolkit.core.StringUtil; 6 | import io.netty.channel.Channel; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.util.ObjectUtils; 9 | 10 | import java.util.Objects; 11 | 12 | /** 13 | * @author ZC 14 | * @date 2021/8/8 16:42 15 | */ 16 | @RequiredArgsConstructor 17 | public class DefaultSessionManager extends AbstractSessionManager { 18 | 19 | private final Cache cache; 20 | 21 | @Override 22 | public Session getSession(Long sessionId) { 23 | return cache.getIfPresent(sessionId); 24 | } 25 | 26 | @Override 27 | public void put(Long sessionId, Session session) { 28 | if (Objects.nonNull(sessionId)) { 29 | cache.put(sessionId, session); 30 | } 31 | } 32 | 33 | @Override 34 | public void remove(Long sessionId) { 35 | Session session = getSession(sessionId); 36 | if (Objects.isNull(session)) { 37 | return; 38 | } 39 | session.close(); 40 | cache.invalidate(sessionId); 41 | } 42 | 43 | 44 | @Override 45 | public void remove(Session session) { 46 | Long sessionId = session.getSessionId(); 47 | remove(sessionId); 48 | } 49 | 50 | @Override 51 | public boolean isExist(Long sessionId) { 52 | Session session = cache.getIfPresent(sessionId); 53 | if (Objects.isNull(session)) { 54 | return false; 55 | } 56 | Channel channel = session.getChannel(); 57 | if (!channel.hasAttr(LibreIMConstants.SERVER_SESSION_ID)) { 58 | return false; 59 | } 60 | Long id = channel.attr(LibreIMConstants.SERVER_SESSION_ID).get(); 61 | return Objects.nonNull(id) && ObjectUtils.nullSafeEquals(sessionId, id); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/service/impl/SysLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.Wrapper; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import com.libre.im.log.mapper.SysLogMapper; 8 | import com.libre.im.log.service.SysLogService; 9 | import com.libre.im.log.pojo.SysLog; 10 | import com.libre.im.log.pojo.SysLogCriteria; 11 | import com.libre.toolkit.core.StringUtil; 12 | import org.springframework.stereotype.Component; 13 | 14 | import java.util.Objects; 15 | 16 | /** 17 | * @author: Libre 18 | * @Date: 2022/12/17 6:04 PM 19 | */ 20 | @Component 21 | public class SysLogServiceImpl extends ServiceImpl implements SysLogService { 22 | 23 | public PageDTO findPage(PageDTO page, SysLogCriteria criteria) { 24 | return this.page(page, getQueryWrapper(criteria)); 25 | } 26 | 27 | private Wrapper getQueryWrapper(SysLogCriteria query) { 28 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 29 | wrapper.eq(SysLog::getSuccess, query.getSuccess()); 30 | String blurry = query.getBlurry(); 31 | // 模糊查询字段 username,description,address,requestIp,method,params 32 | wrapper.and(StringUtil.isNotBlank(blurry), 33 | w -> w.like(SysLog::getUsername, blurry).or().like(SysLog::getUsername, blurry).or() 34 | .like(SysLog::getDescription, blurry).or().like(SysLog::getAddress, blurry).or() 35 | .like(SysLog::getRequestIp, blurry).or().like(SysLog::getClassMethod, blurry).or() 36 | .like(SysLog::getParams, blurry)); 37 | 38 | wrapper.eq(Objects.nonNull(query.getUserId()), SysLog::getUserId, query.getUserId()); 39 | if (query.haveTime()) { 40 | wrapper.between(SysLog::getGmtCreate, query.getStartTime(), query.getEndTime()); 41 | } 42 | wrapper.orderByDesc(SysLog::getGmtCreate); 43 | return wrapper; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/controller/SysLogController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.controller; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 4 | import com.libre.im.common.security.dto.AuthUser; 5 | import com.libre.im.common.security.support.SecurityUtil; 6 | import com.libre.im.log.pojo.SysLog; 7 | import com.libre.im.log.pojo.SysLogCriteria; 8 | import com.libre.im.log.service.SysLogService; 9 | import com.libre.im.log.support.SysLogConstant; 10 | import com.libre.toolkit.result.R; 11 | import io.swagger.v3.oas.annotations.Operation; 12 | import lombok.RequiredArgsConstructor; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | import java.util.Optional; 16 | 17 | /** 18 | * @author: Libre 19 | * @Date: 2022/12/17 8:10 PM 20 | */ 21 | 22 | @RestController 23 | @RequestMapping("/api/sys/log") 24 | @RequiredArgsConstructor 25 | public class SysLogController { 26 | 27 | private final SysLogService sysLogService; 28 | 29 | @GetMapping("info") 30 | public R> pageInfo(PageDTO page, SysLogCriteria criteria) { 31 | criteria.setSuccess(SysLogConstant.SUCCESS); 32 | PageDTO result = sysLogService.findPage(page, criteria); 33 | return R.data(result); 34 | } 35 | 36 | @GetMapping("error") 37 | public R> pageError(PageDTO page, SysLogCriteria criteria) { 38 | criteria.setSuccess(SysLogConstant.FAILED); 39 | PageDTO result = sysLogService.findPage(page, criteria); 40 | return R.data(result); 41 | } 42 | 43 | @PostMapping("user") 44 | public R> queryUserLog(PageDTO page, SysLogCriteria criteria) { 45 | AuthUser user = SecurityUtil.getUser(); 46 | Optional.ofNullable(user).ifPresent(authUser -> criteria.setUserId(user.getUserId())); 47 | PageDTO result = sysLogService.findPage(page, criteria); 48 | return R.data(result); 49 | } 50 | 51 | @GetMapping("error/{id}") 52 | @Operation(summary = "日志异常详情查询") 53 | public R queryErrorLogs(@PathVariable Long id) { 54 | SysLog sysLog = sysLogService.getById(id); 55 | return R.data(sysLog); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/core/message/handler/AbstractMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.core.message.handler; 2 | 3 | import com.libre.im.websocket.core.mapstruct.MessageMapping; 4 | import com.libre.im.websocket.core.message.*; 5 | import com.libre.im.websocket.core.message.enums.ConnectType; 6 | import com.libre.im.websocket.core.session.Session; 7 | import com.libre.im.websocket.core.session.SessionManager; 8 | import com.libre.im.websocket.pojo.ChatMessage; 9 | import io.netty.channel.Channel; 10 | 11 | import java.util.Objects; 12 | 13 | /** 14 | * @author: Libre 15 | * @Date: 2022/4/30 10:54 PM 16 | */ 17 | public abstract class AbstractMessageHandler implements MessageHandler { 18 | 19 | protected final SessionManager sessionManager; 20 | 21 | protected Class clazz; 22 | 23 | protected AbstractMessageHandler(SessionManager sessionManager) { 24 | this.sessionManager = sessionManager; 25 | } 26 | 27 | @Override 28 | public void resolveMessage(Message message) { 29 | Integer connectType = message.getConnectType(); 30 | if (Objects.equals(connectType, ConnectType.SEND.getType())) { 31 | sendMessage(message); 32 | } 33 | else if (Objects.equals(connectType, ConnectType.RECEIVED.getType())) { 34 | MessageMapping mapping = MessageMapping.INSTANCE; 35 | if (message instanceof TextMessage) { 36 | TextMessage textMessage = (TextMessage) message; 37 | ChatMessage chatMessage = mapping.convertToChatMessage(textMessage); 38 | MessagePublisher.publishSaveMessageEvent(chatMessage); 39 | } 40 | else if (message instanceof MediaMessage) { 41 | MediaMessage mediaMessage = (MediaMessage) message; 42 | } 43 | } 44 | } 45 | 46 | public void sendHeartBeatMessage(Long sessionId) { 47 | TextMessage heartBeatMessage = MessageFactory.buildHeartBeatMessage(); 48 | Session session = sessionManager.getSession(sessionId); 49 | if (Objects.nonNull(session)) { 50 | Channel channel = session.getChannel(); 51 | channel.writeAndFlush(heartBeatMessage); 52 | } 53 | } 54 | 55 | protected abstract void sendMessage(Message message); 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/impl/SysUserRoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.libre.im.system.mapper.UserRoleMapper; 6 | import com.libre.im.system.pojo.entity.SysUserRole; 7 | import com.libre.im.system.service.SysUserRoleService; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.Collection; 11 | import java.util.List; 12 | import java.util.Set; 13 | import java.util.stream.Collectors; 14 | 15 | /** 16 | * @author Libre 17 | */ 18 | @Service 19 | public class SysUserRoleServiceImpl extends ServiceImpl implements SysUserRoleService { 20 | 21 | @Override 22 | public List getListByUserId(Long userId) { 23 | return this.list(Wrappers.lambdaQuery().eq(SysUserRole::getUserId, userId)); 24 | } 25 | 26 | @Override 27 | public List getListByUserIds(Collection userIds) { 28 | return this.list(Wrappers.lambdaQuery().in(SysUserRole::getUserId, userIds)); 29 | } 30 | 31 | @Override 32 | public List getListByRoleIds(Collection roleIds) { 33 | return super.list(Wrappers.lambdaQuery().in(SysUserRole::getRoleId, roleIds)); 34 | } 35 | 36 | @Override 37 | public boolean saveByUserIdAndRoleIds(Long userId, List roleIds) { 38 | List userRoleList = roleIds.stream().map(roleId -> { 39 | SysUserRole userRole = new SysUserRole(); 40 | userRole.setUserId(userId); 41 | userRole.setRoleId(roleId); 42 | return userRole; 43 | }).distinct().collect(Collectors.toList()); 44 | return super.saveBatch(userRoleList); 45 | } 46 | 47 | @Override 48 | public boolean deleteByUserId(Long userId) { 49 | return super.remove(Wrappers.lambdaQuery().eq(SysUserRole::getUserId, userId)); 50 | } 51 | 52 | @Override 53 | public boolean deleteByUserIds(Set userIds) { 54 | return super.remove(Wrappers.lambdaQuery().in(SysUserRole::getUserId, userIds)); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/pojo/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableLogic; 7 | import com.fasterxml.jackson.annotation.JsonFormat; 8 | import com.libre.toolkit.time.DatePattern; 9 | import com.libre.toolkit.validation.CreateGroup; 10 | import com.libre.toolkit.validation.UpdateGroup; 11 | import io.swagger.v3.oas.annotations.media.Schema; 12 | import lombok.Data; 13 | import org.springframework.format.annotation.DateTimeFormat; 14 | 15 | import javax.validation.constraints.NotNull; 16 | import javax.validation.constraints.Null; 17 | import java.time.LocalDateTime; 18 | 19 | /** 20 | * @author zhao.cheng 21 | * @date 2021/5/9 11:52 22 | */ 23 | @Data 24 | public abstract class BaseEntity { 25 | 26 | /** 27 | * 主键id 28 | */ 29 | @TableId 30 | @Schema(description = "主键id") 31 | @Null(groups = CreateGroup.class) 32 | @NotNull(groups = UpdateGroup.class) 33 | private Long id; 34 | 35 | /** 36 | * 创建时间 37 | */ 38 | @DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) 39 | @JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) 40 | @Schema(description = "创建时间") 41 | @TableField(fill = FieldFill.INSERT) 42 | private LocalDateTime gmtCreate; 43 | 44 | /** 45 | * 更新时间 46 | */ 47 | @DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) 48 | @JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) 49 | @Schema(description = "更新时间") 50 | @TableField(fill = FieldFill.INSERT_UPDATE) 51 | private LocalDateTime gmtModified; 52 | 53 | /** 54 | * 创建人 55 | */ 56 | @Schema(description = "创建人") 57 | @TableField(fill = FieldFill.INSERT) 58 | private String gmtCreateName; 59 | 60 | /** 61 | * 更新人 62 | */ 63 | @Schema(description = "更新人") 64 | @TableField(fill = FieldFill.INSERT_UPDATE) 65 | private String gmtModifiedName; 66 | 67 | /** 68 | * 0删除 1未删除 69 | */ 70 | @TableLogic(value = "0", delval = "1") 71 | @Schema(description = "1删除 0未删除") 72 | private Integer isDeleted; 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/config/WebSocketServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.config; 2 | 3 | import com.google.common.cache.Cache; 4 | import com.google.common.cache.CacheBuilder; 5 | import com.libre.boot.autoconfigure.SpringContext; 6 | import com.libre.im.websocket.core.session.DefaultSessionManager; 7 | import com.libre.im.websocket.core.session.RedissonSessionManager; 8 | import com.libre.im.websocket.core.session.Session; 9 | import com.libre.im.websocket.core.session.SessionManager; 10 | import io.netty.channel.group.ChannelGroup; 11 | import io.netty.channel.group.DefaultChannelGroup; 12 | import io.netty.util.concurrent.GlobalEventExecutor; 13 | import org.redisson.api.RedissonClient; 14 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 15 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 16 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 17 | import org.springframework.context.annotation.Bean; 18 | import org.springframework.context.annotation.Configuration; 19 | 20 | import java.time.Duration; 21 | 22 | /** 23 | * @author ZC 24 | * @date 2021/8/1 13:07 25 | */ 26 | @EnableConfigurationProperties(WebsocketServerProperties.class) 27 | @Configuration(proxyBeanMethods = false) 28 | public class WebSocketServerConfiguration { 29 | 30 | @Bean 31 | public ChannelGroup channelGroup() { 32 | return new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); 33 | } 34 | 35 | @Bean 36 | @ConditionalOnBean(RedissonClient.class) 37 | public SessionManager redissonSessionManager(RedissonClient redissonClient) { 38 | return new RedissonSessionManager(redissonClient); 39 | } 40 | 41 | @Bean 42 | @ConditionalOnMissingBean(RedissonClient.class) 43 | public SessionManager defaultSessionManager() { 44 | CacheBuilder sessionCacheBuilder = CacheBuilder.newBuilder(); 45 | Cache sessionCache = sessionCacheBuilder 46 | .expireAfterAccess(Duration.ofMinutes(30)) 47 | .build(); 48 | return new DefaultSessionManager(sessionCache); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/security/support/AuthenticationHandler.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.security.support; 2 | 3 | import com.libre.im.common.security.dto.AuthUser; 4 | import com.libre.toolkit.core.StringUtil; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.util.PatternMatchUtils; 9 | 10 | import java.util.Collection; 11 | 12 | /** 13 | * 权限判断 14 | *

15 | * url: ... 17 | * 18 | * @author l.cm 19 | */ 20 | @Service("sec") 21 | public class AuthenticationHandler { 22 | 23 | /** 24 | * 提供给页面输出当前用户 25 | * @return {AuthUser} 26 | */ 27 | public AuthUser currentUser() { 28 | return SecurityUtil.getUser(); 29 | } 30 | 31 | /** 32 | * 判断是否超级管理员 33 | * @return 是否管理员 34 | */ 35 | public boolean isAdmin() { 36 | AuthUser authUser = this.currentUser(); 37 | if (authUser == null) { 38 | return false; 39 | } 40 | return SecurityUtil.isAdmin(authUser.getIsAdmin()); 41 | } 42 | 43 | /** 44 | * 已经授权的 45 | * @return 是否授权 46 | */ 47 | public boolean isAuthenticated() { 48 | return this.currentUser() != null; 49 | } 50 | 51 | /** 52 | * 判断按钮是否有xxx:xxx权限 53 | * @param permissions 权限表达式 54 | * @return {boolean} 55 | */ 56 | public boolean hasPermission(String... permissions) { 57 | if (StringUtil.isAnyBlank(permissions)) { 58 | return false; 59 | } 60 | Authentication authentication = SecurityUtil.getAuthentication(); 61 | if (authentication == null) { 62 | return false; 63 | } 64 | AuthUser authUser = SecurityUtil.getUser(authentication); 65 | if (authUser == null) { 66 | return false; 67 | } 68 | // admin 有所有权限 69 | if (SecurityUtil.isAdmin(authUser.getIsAdmin())) { 70 | return true; 71 | } 72 | Collection authorities = authentication.getAuthorities(); 73 | return authorities.stream().map(GrantedAuthority::getAuthority).filter(StringUtil::isNotBlank) 74 | .anyMatch(x -> PatternMatchUtils.simpleMatch(permissions, x)); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/security/controller/AuthorizationController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.security.controller; 2 | 3 | import com.libre.im.common.security.constant.SecurityConstant; 4 | import com.libre.im.common.security.dto.AuthUser; 5 | import com.libre.im.common.security.dto.JwtUser; 6 | import com.libre.im.common.security.dto.RoleInfo; 7 | import com.libre.im.system.pojo.SysMenu; 8 | import com.libre.im.system.pojo.vo.MenuVO; 9 | import com.libre.im.system.service.SysMenuService; 10 | import com.libre.im.system.toolkit.MenuUtil; 11 | import com.libre.toolkit.result.R; 12 | import io.swagger.annotations.Api; 13 | import io.swagger.annotations.ApiOperation; 14 | import lombok.RequiredArgsConstructor; 15 | import lombok.extern.slf4j.Slf4j; 16 | import org.springframework.web.bind.annotation.GetMapping; 17 | import org.springframework.web.bind.annotation.RequestMapping; 18 | import org.springframework.web.bind.annotation.RestController; 19 | 20 | import java.util.Collections; 21 | import java.util.List; 22 | import java.util.Set; 23 | import java.util.stream.Collectors; 24 | 25 | /** 26 | * @author Libre 27 | * @date 2021/7/12 17:54 28 | */ 29 | @Slf4j 30 | @Api(tags = "授权管理") 31 | @RestController 32 | @RequestMapping("/api/auth") 33 | @RequiredArgsConstructor 34 | public class AuthorizationController { 35 | 36 | private final SysMenuService menuService; 37 | 38 | @ApiOperation("获取用户信息") 39 | @GetMapping("/info") 40 | public R getUserInfo(AuthUser authUser) { 41 | JwtUser jwtUser = authUser.toJwtUser(); 42 | return R.data(jwtUser); 43 | } 44 | 45 | @GetMapping("/menus") 46 | public R> getMenus(AuthUser user) { // 1. 超级管理员 47 | if (SecurityConstant.IS_ADMIN_YES.equals(user.getIsAdmin())) { 48 | List menuList = menuService.getAllMenu(); 49 | return R.data(MenuUtil.transformList(menuList)); 50 | } 51 | // 2. 其他用户 52 | List roleList = user.getRoleList(); 53 | if (roleList == null || roleList.isEmpty()) { 54 | return R.data(Collections.emptyList()); 55 | } 56 | Set roleIds = roleList.stream().map(RoleInfo::getId).collect(Collectors.toSet()); 57 | List menuList = menuService.getNavByRoleIds(roleIds); 58 | return R.data(MenuUtil.transformList(menuList)); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/common/security/dto/AuthUser.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.common.security.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.userdetails.User; 7 | 8 | import java.util.Collection; 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | /** 13 | * security 用户 14 | * 15 | * @author L.cm 16 | */ 17 | @Getter 18 | @Setter 19 | public class AuthUser extends User { 20 | 21 | private Long userId; 22 | 23 | private String nickName; 24 | 25 | private Integer gender; 26 | 27 | private Integer isAdmin; 28 | 29 | private String avatar; 30 | 31 | private String email; 32 | 33 | private String phone; 34 | 35 | private List roleList; 36 | 37 | public AuthUser(String username, String password, boolean enabled, boolean accountNonLocked, 38 | Collection authorities) { 39 | super(username, password, enabled, true, true, accountNonLocked, authorities); 40 | } 41 | 42 | public JwtUser toJwtUser() { 43 | JwtUser jwtUser = new JwtUser(); 44 | jwtUser.setId(this.getUserId()); 45 | jwtUser.setUsername(this.getUsername()); 46 | jwtUser.setNickName(this.getNickName()); 47 | jwtUser.setGender(this.getGender()); 48 | jwtUser.setAvatar(this.getAvatar()); 49 | jwtUser.setEmail(this.getEmail()); 50 | jwtUser.setPhone(this.getPhone()); 51 | jwtUser.setIsAdmin(this.getIsAdmin()); 52 | 53 | jwtUser.setRoles(this.getRoleList()); 54 | jwtUser.setRoleList(this.getRoleList().stream().map(RoleInfo::getPermission).collect(Collectors.toList())); 55 | return jwtUser; 56 | } 57 | 58 | public static AuthUser formMicaUser(AuthUser user, String newPassword) { 59 | AuthUser authUser = new AuthUser(user.getUsername(), newPassword, user.isEnabled(), user.isAccountNonLocked(), 60 | user.getAuthorities()); 61 | authUser.setUserId(user.getUserId()); 62 | authUser.setNickName(user.getNickName()); 63 | authUser.setIsAdmin(user.getIsAdmin()); 64 | authUser.setGender(user.getGender()); 65 | authUser.setAvatar(user.getAvatar()); 66 | authUser.setEmail(user.getEmail()); 67 | authUser.setPhone(user.getPhone()); 68 | authUser.setRoleList(user.getRoleList()); 69 | return authUser; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/websocket/service/impl/FriendServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.websocket.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.libre.im.system.service.SysUserService; 5 | import com.libre.im.websocket.service.FriendService; 6 | import com.libre.im.websocket.constant.CacheKey; 7 | import com.libre.im.websocket.mapper.FriendMapper; 8 | import com.libre.im.websocket.pojo.Friend; 9 | import com.libre.im.websocket.pojo.vo.FriendVO; 10 | import lombok.RequiredArgsConstructor; 11 | import org.springframework.cache.annotation.CacheConfig; 12 | import org.springframework.cache.annotation.CacheEvict; 13 | import org.springframework.cache.annotation.Cacheable; 14 | import org.springframework.stereotype.Service; 15 | 16 | import java.util.*; 17 | 18 | /** 19 | * @author: Libre 20 | * @Date: 2022/5/3 2:49 AM 21 | */ 22 | @Service 23 | @RequiredArgsConstructor 24 | @CacheConfig(cacheNames = CacheKey.FRIEND_CACHE_KEY) 25 | public class FriendServiceImpl extends ServiceImpl implements FriendService { 26 | 27 | private final SysUserService sysUserService; 28 | 29 | @Override 30 | @Cacheable(key = "#userId") 31 | public List findListByUserId(Long userId) { 32 | // List friends = this.list(Wrappers.lambdaQuery().eq(Friend::getUserId, userId)); 33 | // if (CollectionUtils.isEmpty(friends)) { 34 | // return Collections.emptyList(); 35 | // } 36 | // 37 | // Map friendMap = StreamUtils.map(friends, Friend::getFriendId, chatFriend -> chatFriend); 38 | // List libreUsers = sysUserService.listByIds(friendMap.keySet()); 39 | // 40 | // List voList = Lists.newArrayList(); 41 | // FriendMapping mapping = FriendMapping.INSTANCE; 42 | // for (LibreUser libreUser : libreUsers) { 43 | // Friend friend = friendMap.get(libreUser.getId()); 44 | // if (Objects.isNull(friend)) { 45 | // continue; 46 | // } 47 | // FriendVO friendVO = mapping.chatUserToFriendVO(libreUser); 48 | // friendVO.setIsTop(friend.getIsTop()); 49 | // friendVO.setAddTime(friend.getAddTime()); 50 | // voList.add(friendVO); 51 | // } 52 | // return voList; 53 | return null; 54 | } 55 | 56 | @Override 57 | @CacheEvict(allEntries = true) 58 | public void removeFriend(Long friendId) { 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/service/impl/SysDictServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.Wrapper; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.libre.im.system.mapper.SysDictMapper; 7 | import com.libre.im.system.pojo.dto.DictCriteria; 8 | import com.libre.im.system.pojo.entity.SysDict; 9 | import com.libre.im.system.pojo.entity.SysDictInfo; 10 | import com.libre.im.system.service.SysDictInfoService; 11 | import com.libre.im.system.service.SysDictService; 12 | import com.libre.toolkit.core.StringUtil; 13 | import com.libre.toolkit.exception.LibreException; 14 | import lombok.RequiredArgsConstructor; 15 | import org.springframework.stereotype.Service; 16 | 17 | import java.util.Collection; 18 | import java.util.List; 19 | import java.util.Set; 20 | import java.util.stream.Collectors; 21 | 22 | /** 23 | *

24 | * 字典表 服务实现类 25 | *

26 | * 27 | * @author L.cm 28 | * @since 2020-07-19 29 | */ 30 | @Service 31 | @RequiredArgsConstructor 32 | public class SysDictServiceImpl extends ServiceImpl implements SysDictService { 33 | 34 | private final SysDictInfoService dictInfoService; 35 | 36 | @Override 37 | public Wrapper getQueryWrapper(DictCriteria query) { 38 | String queryBlurry = query.getBlurry(); 39 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 40 | // name,description 41 | wrapper.and(StringUtil.isNotBlank(queryBlurry), w -> w.like(SysDict::getName, queryBlurry).or() 42 | .like(SysDict::getDescription, queryBlurry).or().like(SysDict::getRemark, queryBlurry)); 43 | return wrapper; 44 | } 45 | 46 | @Override 47 | public boolean deleteIfUnusedByIds(Collection ids) { 48 | List sysDictList = super.listByIds(ids); 49 | if (sysDictList == null || sysDictList.isEmpty()) { 50 | return false; 51 | } 52 | Set dictNameSet = sysDictList.stream().map(SysDict::getName).collect(Collectors.toSet()); 53 | List dictInfoList = dictInfoService.getListByDictNames(dictNameSet); 54 | if (dictInfoList != null && !dictInfoList.isEmpty()) { 55 | throw new LibreException("存在字典详情关系"); 56 | } 57 | return super.removeByIds(ids); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/controller/SysDeptController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.controller; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.libre.im.system.pojo.dto.DeptCriteria; 5 | import com.libre.im.system.pojo.entity.SysDept; 6 | import com.libre.im.system.service.SysDeptService; 7 | import com.libre.toolkit.result.R; 8 | import com.libre.toolkit.validation.CreateGroup; 9 | import com.libre.toolkit.validation.UpdateGroup; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiOperation; 12 | import lombok.RequiredArgsConstructor; 13 | import org.apache.commons.collections4.CollectionUtils; 14 | import org.springframework.validation.annotation.Validated; 15 | import org.springframework.web.bind.annotation.*; 16 | 17 | import javax.validation.constraints.NotEmpty; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.Set; 21 | 22 | /** 23 | * @author Libre 24 | * @date 2022/2/2 15:35 25 | */ 26 | @Api(tags = "用户管理") 27 | @RestController 28 | @RequestMapping("/api/sys/dept") 29 | @RequiredArgsConstructor 30 | public class SysDeptController { 31 | 32 | private final SysDeptService deptService; 33 | 34 | @ApiOperation("查询部门") 35 | @GetMapping 36 | public R> query(DeptCriteria param) { 37 | Page page = deptService.findByPage(param); 38 | return R.data(page); 39 | } 40 | 41 | @ApiOperation("查询部门:根据ID获取同级与上级数据") 42 | @PostMapping("superior") 43 | public List getSuperior(@RequestBody List ids) { 44 | if (CollectionUtils.isEmpty(ids)) { 45 | return deptService.list(); 46 | } 47 | List deptList = deptService.listByIds(ids); 48 | List superiorList = new ArrayList<>(deptList); 49 | deptService.getSuperior(deptList, superiorList); 50 | return superiorList; 51 | } 52 | 53 | @ApiOperation("新增部门") 54 | @PostMapping 55 | public void create(@Validated(CreateGroup.class) @RequestBody SysDept entity) { 56 | deptService.save(entity); 57 | } 58 | 59 | @ApiOperation("修改部门") 60 | @PutMapping 61 | public void update(@Validated(UpdateGroup.class) @RequestBody SysDept entity) { 62 | deptService.updateById(entity); 63 | } 64 | 65 | @ApiOperation("删除部门") 66 | @DeleteMapping 67 | public void delete(@NotEmpty @RequestBody Set ids) { 68 | deptService.deleteIfUnusedByIds(ids); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/support/SysLogEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.libre.im.log.support; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | import org.springframework.lang.Nullable; 22 | 23 | /** 24 | * SysLog 数据承载 25 | * 26 | * @author L.cm 27 | */ 28 | @Getter 29 | @Setter 30 | public class SysLogEvent { 31 | 32 | /** 33 | * 用户id 34 | */ 35 | private Long userId; 36 | 37 | private String appName; 38 | 39 | /** 40 | * 登陆名 41 | */ 42 | private String username; 43 | 44 | /** 45 | * 日志类别 46 | */ 47 | private String logType; 48 | 49 | /** 50 | * 描述 51 | */ 52 | private String description; 53 | 54 | /** 55 | * 请求参数 56 | */ 57 | private String params; 58 | 59 | /** 60 | * post data 61 | */ 62 | private String data; 63 | 64 | /** 65 | * 是否成功[0失败,1成功] 66 | */ 67 | private Integer success; 68 | 69 | /** 70 | * 请求ip 71 | */ 72 | private String requestIp; 73 | 74 | private String requestMethod; 75 | 76 | /** 77 | * 请求耗时 78 | */ 79 | private Long requestTime; 80 | 81 | /** 82 | * ua 信息 83 | */ 84 | private String userAgent; 85 | 86 | private String stackTrace; 87 | 88 | /** 89 | * 异常名 90 | */ 91 | 92 | private String exceptionName; 93 | 94 | /** 95 | * 异常消息 96 | */ 97 | @Nullable 98 | private String message; 99 | 100 | /** 101 | * 类名 102 | */ 103 | @Nullable 104 | private String className; 105 | 106 | /** 107 | * 文件名 108 | */ 109 | @Nullable 110 | private String fileName; 111 | 112 | /** 113 | * 方法名 114 | */ 115 | @Nullable 116 | private String methodName; 117 | 118 | /** 119 | * 代码行数 120 | */ 121 | @Nullable 122 | private Integer lineNumber; 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/controller/SysDictController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.controller; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.libre.im.log.annotation.ApiLog; 6 | import com.libre.im.system.pojo.dto.DictCriteria; 7 | import com.libre.im.system.pojo.entity.SysDict; 8 | import com.libre.im.system.service.SysDictService; 9 | import com.libre.toolkit.result.R; 10 | import com.libre.toolkit.validation.CreateGroup; 11 | import com.libre.toolkit.validation.UpdateGroup; 12 | import io.swagger.v3.oas.annotations.Operation; 13 | import io.swagger.v3.oas.annotations.tags.Tag; 14 | import lombok.RequiredArgsConstructor; 15 | import org.springframework.security.access.prepost.PreAuthorize; 16 | import org.springframework.validation.annotation.Validated; 17 | import org.springframework.web.bind.annotation.*; 18 | 19 | import javax.validation.constraints.NotEmpty; 20 | import java.util.Set; 21 | 22 | /** 23 | *

24 | * 字典 前端控制器 25 | *

26 | * 27 | * @author L.cm 28 | * @since 2020-05-05 29 | */ 30 | @Validated 31 | @RestController 32 | @RequestMapping("/api/sys/dict") 33 | @Tag(name = "系统:字典管理") 34 | @RequiredArgsConstructor 35 | public class SysDictController { 36 | 37 | private final SysDictService dictService; 38 | 39 | @ApiLog("查询字典") 40 | @Operation(summary = "查询字典") 41 | @GetMapping 42 | public R> query(Page page, DictCriteria query) { 43 | Page dictPage = dictService.page(page, dictService.getQueryWrapper(query)); 44 | return R.data(dictPage); 45 | } 46 | 47 | @ApiLog("新增字典") 48 | @Operation(summary = "新增字典") 49 | @PostMapping 50 | @PreAuthorize("@sec.hasPermission('system:dict:add')") 51 | public R create(@Validated(CreateGroup.class) @RequestBody SysDict entity) { 52 | dictService.save(entity); 53 | return R.status(true); 54 | } 55 | 56 | @ApiLog("修改字典") 57 | @Operation(summary = "修改字典") 58 | @PutMapping 59 | @PreAuthorize("@sec.hasPermission('system:dict:edit')") 60 | public R update(@Validated(UpdateGroup.class) @RequestBody SysDict entity) { 61 | dictService.updateById(entity); 62 | return R.status(true); 63 | } 64 | 65 | @ApiLog("删除字典") 66 | @Operation(summary = "删除字典") 67 | @DeleteMapping 68 | @PreAuthorize("@sec.hasPermission('system:dict:del')") 69 | public R delete(@NotEmpty @RequestBody Set ids) { 70 | dictService.deleteIfUnusedByIds(ids); 71 | return R.status(true); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/controller/SysUserController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.controller; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 5 | import com.libre.im.common.security.constant.SecurityConstant; 6 | import com.libre.im.log.annotation.ApiLog; 7 | import com.libre.im.system.pojo.dto.UserCriteria; 8 | import com.libre.im.system.pojo.dto.UserDTO; 9 | import com.libre.im.system.pojo.entity.SysUser; 10 | import com.libre.im.system.pojo.vo.UserVO; 11 | import com.libre.im.system.service.SysUserService; 12 | import com.libre.toolkit.core.StringPool; 13 | import com.libre.toolkit.result.R; 14 | import io.swagger.annotations.Api; 15 | import io.swagger.annotations.ApiOperation; 16 | import lombok.RequiredArgsConstructor; 17 | import org.springframework.security.crypto.password.PasswordEncoder; 18 | import org.springframework.web.bind.annotation.*; 19 | 20 | import javax.validation.constraints.NotEmpty; 21 | import java.util.Set; 22 | 23 | /** 24 | * @author zhao.cheng 25 | */ 26 | @Api(tags = "用户管理") 27 | @RestController 28 | @RequestMapping("/api/sys/user") 29 | @RequiredArgsConstructor 30 | public class SysUserController { 31 | 32 | private final SysUserService sysUserService; 33 | 34 | private final PasswordEncoder passwordEncoder; 35 | 36 | @ApiOperation("用户列表") 37 | @GetMapping("/page") 38 | public R> page(Page page, UserCriteria param) { 39 | PageDTO userPage = sysUserService.findByPage(page, param); 40 | return R.data(userPage); 41 | } 42 | 43 | @ApiOperation("获取用户") 44 | @GetMapping("/get/{id}") 45 | public R info(@PathVariable Long id) { 46 | return R.data(sysUserService.findUserById(id)); 47 | } 48 | 49 | @ApiLog("创建用户") 50 | @PutMapping("/save") 51 | public R save(@RequestBody UserDTO user) { 52 | String password = passwordEncoder.encode("123456"); 53 | user.setPassword(password.replace(SecurityConstant.PASSWORD_PREFIX, StringPool.EMPTY)); 54 | boolean res = sysUserService.createUser(user); 55 | return R.status(res); 56 | } 57 | 58 | @ApiLog("修改用户") 59 | @PostMapping("edit") 60 | public R update(@RequestBody UserDTO user) { 61 | boolean res = sysUserService.updateUser(user); 62 | return R.status(res); 63 | } 64 | 65 | @ApiLog("删除用户") 66 | @DeleteMapping 67 | public R delete(@NotEmpty @RequestBody Set ids) { 68 | boolean res = sysUserService.deleteUserByIds(ids); 69 | return R.status(res); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/support/SysLogListener.java: -------------------------------------------------------------------------------- 1 | 2 | package com.libre.im.log.support; 3 | 4 | import com.libre.boot.exception.LibreErrorEvent; 5 | import com.libre.im.log.service.SysLogService; 6 | import com.libre.im.log.pojo.SysLog; 7 | import com.libre.ip2region.core.Ip2regionSearcher; 8 | import com.libre.toolkit.core.StringUtil; 9 | import eu.bitwalker.useragentutils.Browser; 10 | import eu.bitwalker.useragentutils.OperatingSystem; 11 | import eu.bitwalker.useragentutils.UserAgent; 12 | import lombok.RequiredArgsConstructor; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.context.event.EventListener; 15 | import org.springframework.core.annotation.Order; 16 | import org.springframework.scheduling.annotation.Async; 17 | 18 | /** 19 | * 监听系统日志事件,系统日志入库 20 | * 21 | * @author L.cm 22 | */ 23 | @RequiredArgsConstructor 24 | @Configuration(proxyBeanMethods = false) 25 | public class SysLogListener { 26 | 27 | private final SysLogService sysLogService; 28 | 29 | private final Ip2regionSearcher searcher; 30 | 31 | @Async 32 | @Order 33 | @EventListener(SysLogEvent.class) 34 | public void saveSysLog(SysLogEvent event) { 35 | SysLogMapping mapping = SysLogMapping.INSTANCE; 36 | SysLog sysLog = mapping.sourceToTarget(event); 37 | // 获取操作系统和浏览器信息 38 | UserAgent userAgent = UserAgent.parseUserAgentString(event.getUserAgent()); 39 | OperatingSystem system = userAgent.getOperatingSystem(); 40 | sysLog.setOs(system.getName()); 41 | Browser browser = userAgent.getBrowser(); 42 | sysLog.setBrowser(browser.getName()); 43 | String requestIp = event.getRequestIp(); 44 | // ip 不为空,查找 ip 的地理信息 45 | if (StringUtil.isNotBlank(requestIp)) { 46 | String address = searcher.getAddress(requestIp); 47 | if (StringUtil.isBlank(address) && StringUtil.equals(requestIp, "127.0.0.1")) { 48 | address = "内网IP"; 49 | } 50 | sysLog.setAddress(address); 51 | } 52 | sysLogService.save(sysLog); 53 | } 54 | 55 | @Async 56 | @Order 57 | @EventListener(LibreErrorEvent.class) 58 | public void saveErrorEvent(LibreErrorEvent event) { 59 | // SysLogMapping mapping = SysLogMapping.INSTANCE; 60 | // SysLog sysLog = mapping.convertToSysLog(event); 61 | // AuthUser authUser = SecurityUtil.getUser(); 62 | // Optional.ofNullable(SecurityUtil.getUser()).ifPresent(user -> { 63 | // sysLog.setUserId(user.getUserId()); 64 | // sysLog.setUsername(user.getUsername()); 65 | // }); 66 | // sysLog.setSuccess(SysLogConstant.FAILED); 67 | // sysLogService.save(sysLog); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/support/ScheduleJobListener.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.support; 2 | 3 | import com.google.common.base.Throwables; 4 | import com.libre.im.tookit.common.SysJobConstant; 5 | import com.libre.im.tookit.moudle.quartz.mapper.SysJobLogMapper; 6 | import com.libre.im.tookit.moudle.quartz.pojo.SysJob; 7 | import com.libre.im.tookit.moudle.quartz.pojo.SysJobLog; 8 | import lombok.RequiredArgsConstructor; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.quartz.*; 11 | import org.quartz.impl.matchers.EverythingMatcher; 12 | import org.springframework.scheduling.quartz.SchedulerFactoryBean; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.annotation.PostConstruct; 16 | import java.time.LocalDateTime; 17 | import java.util.Optional; 18 | 19 | /** 20 | * @author: Libre 21 | * @Date: 2022/12/30 10:26 PM 22 | */ 23 | @Slf4j 24 | @Component 25 | @RequiredArgsConstructor 26 | public class ScheduleJobListener implements JobListener { 27 | 28 | private final SchedulerFactoryBean schedulerFactory; 29 | 30 | private final SysJobLogMapper sysJobLogMapper; 31 | 32 | @Override 33 | public String getName() { 34 | return this.getClass().getSimpleName(); 35 | } 36 | 37 | @Override 38 | public void jobToBeExecuted(JobExecutionContext jobExecutionContext) { 39 | 40 | } 41 | 42 | @Override 43 | public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) { 44 | 45 | } 46 | 47 | @Override 48 | public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) { 49 | SysJob sysJob = (SysJob) jobExecutionContext.getMergedJobDataMap().get(SysJob.JOB_KEY); 50 | SysJobLog sysJobLog = new SysJobLog(); 51 | sysJobLog.setJobName(sysJob.getJobName()); 52 | sysJobLog.setBeanName(sysJobLog.getBeanName()); 53 | sysJobLog.setMethodName(sysJobLog.getMethodName()); 54 | sysJobLog.setParams(sysJob.getParams()); 55 | sysJobLog.setCronExpression(sysJobLog.getCronExpression()); 56 | sysJobLog.setCreateTime(LocalDateTime.now()); 57 | sysJobLog.setLastExecuteTime(LocalDateTime.now()); 58 | sysJobLog.setSuccess(SysJobConstant.JOB_SUCCESS); 59 | Optional.ofNullable(e).ifPresent(exception -> { 60 | sysJobLog.setExceptionDetail(Throwables.getStackTraceAsString(exception)); 61 | sysJobLog.setSuccess(SysJobConstant.JOB_FAILED); 62 | }); 63 | sysJobLogMapper.insert(sysJobLog); 64 | } 65 | 66 | // 注册 JobListener 到 Quartz 中 67 | @PostConstruct 68 | public void init() throws SchedulerException { 69 | Scheduler scheduler = schedulerFactory.getScheduler(); 70 | scheduler.getListenerManager().addJobListener(this, EverythingMatcher.allJobs()); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/system/toolkit/MenuUtil.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.system.toolkit; 2 | 3 | import com.libre.im.system.constant.MenuConstants; 4 | import com.libre.im.system.pojo.SysMenu; 5 | import com.libre.im.system.pojo.vo.MenuMetaVO; 6 | import com.libre.im.system.pojo.vo.MenuVO; 7 | import com.libre.toolkit.core.StringPool; 8 | import com.libre.toolkit.core.StringUtil; 9 | import org.apache.commons.collections4.CollectionUtils; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.Objects; 14 | import java.util.stream.Collectors; 15 | 16 | /** 17 | * 菜单处理过滤 18 | * 19 | * @author Libre 20 | * @date 2021/7/12 19:28 21 | */ 22 | public class MenuUtil { 23 | 24 | public static List transformTree(List menuList) { 25 | List menuVOList = transformList(menuList); 26 | return menuVOList.stream().filter(menuVO -> menuVO.getParentId() == 0).peek(menuVO -> { 27 | List children = getChildren(menuVO, menuVOList); 28 | if (CollectionUtils.isNotEmpty(children)) { 29 | menuVO.setChildren(children); 30 | } 31 | }).collect(Collectors.toList()); 32 | } 33 | 34 | public static List transformList(List menuList) { 35 | List menuVoList = new ArrayList<>(); 36 | for (SysMenu menu : menuList) { 37 | String name = menu.getName(); 38 | String path = menu.getPath(); 39 | String title = menu.getTitle(); 40 | String component = menu.getComponent(); 41 | MenuVO menuVo = new MenuVO(); 42 | menuVo.setId(menu.getId()); 43 | menuVo.setParentId(menu.getParentId()); 44 | menuVo.setName(StringUtil.isNotBlank(name) ? name : title); 45 | // 一级目录需要加斜杠,不然会报警告 46 | Long parentId = menu.getParentId(); 47 | if (parentId == null && !path.startsWith("http")) { 48 | menuVo.setPath(StringPool.SLASH + path); 49 | } 50 | else { 51 | menuVo.setPath(path); 52 | } 53 | menuVo.setHidden(Boolean.FALSE); 54 | // 如果不是外链 55 | if (MenuConstants.IS_FRAME_NO.equals(menu.getIsFrame())) { 56 | if (parentId == null || parentId == 0) { 57 | menuVo.setComponent(StringUtil.isBlank(component) ? "Layout" : component); 58 | } 59 | else if (StringUtil.isNotBlank(component)) { 60 | menuVo.setComponent(component); 61 | } 62 | } 63 | menuVo.setMeta(new MenuMetaVO(title, menu.getIcon(), Boolean.TRUE)); 64 | menuVoList.add(menuVo); 65 | } 66 | return menuVoList; 67 | } 68 | 69 | private static List getChildren(MenuVO menuVO, List menus) { 70 | return menus.stream().filter(item -> Objects.equals(item.getParentId(), menuVO.getId())) 71 | .peek(menu -> menu.setChildren(getChildren(menu, menus))).collect(Collectors.toList()); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/tookit/moudle/quartz/controller/SysJobController.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.tookit.moudle.quartz.controller; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; 5 | import com.libre.im.tookit.moudle.quartz.pojo.SysJob; 6 | import com.libre.im.tookit.moudle.quartz.pojo.SysJobCriteria; 7 | import com.libre.im.tookit.moudle.quartz.service.SysJobService; 8 | import com.libre.toolkit.result.R; 9 | import com.libre.toolkit.validation.UpdateGroup; 10 | import io.swagger.v3.oas.annotations.Operation; 11 | import io.swagger.v3.oas.annotations.tags.Tag; 12 | import lombok.RequiredArgsConstructor; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.validation.annotation.Validated; 15 | import org.springframework.web.bind.annotation.*; 16 | 17 | /** 18 | *

19 | * Job Controller 20 | *

21 | * 22 | * @author yangkai.shen 23 | * @author L.cm 24 | */ 25 | @Slf4j 26 | @Validated 27 | @RestController 28 | @RequestMapping("/api/sys/job") 29 | @RequiredArgsConstructor 30 | @Tag(name = "系统:任务管理") 31 | public class SysJobController { 32 | 33 | private final SysJobService jobService; 34 | 35 | /** 36 | * 任务列表查询 37 | */ 38 | @Operation(summary = "任务列表查询") 39 | @GetMapping("page") 40 | public R> jobList(PageDTO page, SysJobCriteria query) { 41 | IPage jobPage = jobService.findByPage(page, query); 42 | return R.data(jobPage); 43 | } 44 | 45 | /** 46 | * 保存定时任务 47 | */ 48 | @Operation(summary = "保存定时任务") 49 | @PostMapping 50 | public void addJob(@Validated @RequestBody SysJob form) { 51 | jobService.addJob(form); 52 | } 53 | 54 | /** 55 | * 暂停定时任务 56 | */ 57 | @Operation(summary = "暂停定时任务") 58 | @PutMapping("/pause") 59 | public void pauseJob(@Validated(UpdateGroup.class) @RequestBody SysJob form) { 60 | jobService.pauseJob(form); 61 | } 62 | 63 | @Operation(summary = "恢复定时任务") 64 | @PutMapping("/update/{id}") 65 | public void update(@PathVariable Long id) { 66 | SysJob sysJob = jobService.getById(id); 67 | jobService.updateJobStatus(sysJob); 68 | } 69 | 70 | /** 71 | * 恢复定时任务 72 | */ 73 | @Operation(summary = "恢复定时任务") 74 | @PutMapping("/resume") 75 | public void resumeJob(@Validated(UpdateGroup.class) @RequestBody SysJob form) { 76 | jobService.resumeJob(form); 77 | } 78 | 79 | /** 80 | * 修改定时任务,定时时间 81 | */ 82 | @Operation(summary = "修改定时任务") 83 | @PutMapping("/cron") 84 | public void cronJob(@Validated @RequestBody SysJob form) { 85 | jobService.cronJob(form); 86 | } 87 | 88 | /** 89 | * 删除定时任务 90 | */ 91 | @Operation(summary = "删除定时任务") 92 | @DeleteMapping("{id}") 93 | public void deleteJob(@PathVariable Long id) { 94 | jobService.deleteJob(id); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/libre/im/log/support/SysLogUtil.java: -------------------------------------------------------------------------------- 1 | package com.libre.im.log.support; 2 | 3 | import com.libre.boot.toolkit.RequestUtils; 4 | import com.libre.im.common.security.dto.AuthUser; 5 | import com.libre.im.common.security.support.SecurityUtil; 6 | import com.libre.toolkit.core.*; 7 | import org.springframework.http.HttpHeaders; 8 | import org.springframework.util.CollectionUtils; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | import java.util.Map; 12 | import java.util.Objects; 13 | 14 | /** 15 | * 系统日志工具类 16 | */ 17 | public class SysLogUtil { 18 | 19 | /** 20 | * 构造 SysLogEvent 21 | * @param logType SysLogType 22 | * @return SysLogEvent 23 | */ 24 | public static SysLogEvent buildSysLogEvent(SysLogType logType) { 25 | SysLogEvent event = new SysLogEvent(); 26 | event.setLogType(logType.name()); 27 | HttpServletRequest request = RequestUtils.getRequest(); 28 | String method = request.getMethod(); 29 | event.setRequestMethod(method); 30 | // 请求信息 GET /api/test/xx 31 | String requestInfo = method + StringPool.SPACE + request.getRequestURI(); 32 | // paraMap 33 | Map paraMap = request.getParameterMap(); 34 | if (CollectionUtils.isEmpty(paraMap)) { 35 | event.setParams(requestInfo); 36 | } 37 | else { 38 | StringBuilder builder = new StringBuilder(requestInfo).append(CharPool.QUESTION_MARK); 39 | paraMap.forEach((key, values) -> { 40 | builder.append(key).append(CharPool.EQUALS); 41 | if ("password".equalsIgnoreCase(key)) { 42 | builder.append("******"); 43 | } 44 | else { 45 | builder.append(StringUtil.join(values)); 46 | } 47 | builder.append(CharPool.AMPERSAND); 48 | }); 49 | builder.deleteCharAt(builder.length() - 1); 50 | event.setParams(builder.toString()); 51 | } 52 | // 获取请求 ip 和 ua 53 | event.setRequestIp(RequestUtils.getIp()); 54 | event.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); 55 | // 用户信息 56 | AuthUser authUser = SecurityUtil.getUser(); 57 | if (Objects.nonNull(authUser)) { 58 | event.setUserId(authUser.getUserId()); 59 | event.setUsername(authUser.getUsername()); 60 | } 61 | return event; 62 | } 63 | 64 | public static void initErrorInfo(Throwable error, SysLogEvent event) { 65 | // 堆栈信息 66 | event.setStackTrace(Exceptions.getStackTraceAsString(error)); 67 | event.setExceptionName(error.getClass().getSimpleName()); 68 | event.setMessage(error.getMessage()); 69 | StackTraceElement[] elements = error.getStackTrace(); 70 | if (ObjectUtil.isNotEmpty(elements)) { 71 | // 报错的类信息 72 | StackTraceElement element = elements[0]; 73 | event.setClassName(element.getClassName()); 74 | event.setFileName(element.getFileName()); 75 | event.setMethodName(element.getMethodName()); 76 | event.setLineNumber(element.getLineNumber()); 77 | } 78 | } 79 | 80 | } 81 | --------------------------------------------------------------------------------