Compare commits

..
45 Commits
Author SHA1 Message Date
heavyrian2012 08b813cd9f version 1.2.0 and release note 2023-11-18 20:28:35 +08:00
heavyrian2012 24c6538084 添加配置,处理多端同时加入聊天室的问题 2023-11-17 09:06:49 +08:00
heavyrian2012 724be0b273 添加获取用户聊天室状态的API 2023-11-17 09:06:00 +08:00
heavyrian2012 63f0fc66ce 支持按照用户ID来搜索用户 2023-11-15 15:38:22 +08:00
heavyrian2012 327b8d43a8 解决某些特殊情况下获取网卡信息失败导致启动失败的问题 2023-11-15 10:21:57 +08:00
imndx df67b8e0c8 禁止私聊时,只要发送者或接受者一方在允许私聊的列表里面,就允许私聊 fix #663 2023-11-10 11:00:45 +08:00
heavyrian2012 b4fcef1ced 会议事件添加时间戳 2023-11-05 10:51:46 +08:00
heavyrian2012 c43dfe26f4 更新SDK的依赖说明 2023-10-21 10:22:24 +08:00
heavyrian2012 aa1161131d 更新readme 2023-10-14 09:11:25 +08:00
heavyrian2012 a1188f5d52 添加配置开关,可以关掉api/version检查接口 2023-10-12 15:44:00 +08:00
heavyrian2012 6a10412940 version 1.1.9 and release note 2023-10-12 10:17:12 +08:00
heavyrian2012 8e3100e5b7 添加配置,是否允许群主和群管理员不受限制撤回自己的发言 2023-10-10 21:53:03 +08:00
heavyrian2012 c17a5be171 支持获取用户群组指定群成员类型 2023-10-10 12:51:40 +08:00
heavyrian2012 7727fad4dc 避免无限制重复好友请求,好友请求在5分钟之内只允许重复请求一次 2023-09-29 11:26:16 +08:00
heavyrian2012 dd5b9b1847 解决好友请求被拒绝后可能还能再次请求的问题 2023-09-29 10:45:41 +08:00
heavyrian2012 92c3c98553 解决重复发送好友请求时,请求时间没有更新的问题 2023-09-29 10:32:52 +08:00
heavyrian2012 d13ed6f989 sdk打印出请求的完整路径,方便问题排查 2023-09-26 09:58:12 +08:00
heavyrian2012 4e6188ee32 添加推送过期配置 2023-09-13 11:16:54 +08:00
heavyrian2012 a183d30f89 解决服务器时间过大的问题 https://github.com/wildfirechat/android-chat/issues/795 2023-09-11 11:12:50 +08:00
heavyrian2012 3f4c2b0cea version 1.1.8 & release note 2023-09-07 22:09:08 +08:00
heavyrian2012 932ee9235f 解决撤回消息中原消息中二进制消息数据格式错误问题 2023-09-07 22:01:37 +08:00
heavyrian2012 1e5ac9b787 修改配置文件注释 2023-09-07 09:56:41 +08:00
heavyrian2012 ad5d4991c8 发送好友请求之后5分钟之内可以再次发送 2023-09-06 19:47:24 +08:00
heavyrian2012 a2ee6c87eb 不能把群主设置为管理员 2023-09-06 15:20:38 +08:00
heavyrian2012 30e01a7040 修改docker说明 2023-08-26 10:40:07 +08:00
heavyrian2012 082f42af77 1.1.7 version and release note 2023-08-07 08:54:14 +08:00
heavyrian2012 2bec610552 优化撤回消息 2023-08-05 10:58:22 +08:00
heavyrian2012 f3a2603309 推送信息中,目标名称考虑到群备注,另外添加发送者和目标的头像 2023-08-04 11:20:09 +08:00
heavyrian2012 7d10251bd9 优化用户搜索 2023-08-04 09:47:07 +08:00
heavyrian2012 5c7b320b04 同步专业版IM服务代码 2023-08-01 14:24:19 +08:00
heavyrian2012 509048da04 1.1.6 version and release node 2023-07-20 21:22:57 +08:00
heavyrian2012 15f7777d78 添加获取订阅频道的功能 2023-07-20 21:07:58 +08:00
heavyrian2012 45b1b9cf96 解决搜索用户时返回用户类型问题 2023-07-08 13:34:05 +08:00
heavyrian2012 57314e673a 用户设置查找自己的方法 2023-06-28 16:14:15 +08:00
heavyrian2012 0a7b8f9587 version and release note 2023-06-20 17:59:11 +08:00
heavyrian2012 c8ff39c2ab 添加获取所有用户的Server API 2023-06-20 15:14:57 +08:00
heavyrian2012 252204a760 添加好友时,只检查对方的黑名单状态 2023-05-27 10:15:07 +08:00
heavyrian2012 26fbde676e stop脚本等待时间延长到30秒 2023-05-17 17:58:03 +08:00
heavyrian2012 81585ec146 docker file 为启动脚本添加执行属性 2023-05-17 17:57:47 +08:00
heavyrian2012 4ad0437730 更新版本号和release note 2023-05-10 20:19:45 +08:00
heavyrian2012 6245fe37fc 添加配置,请求机器人好友时,是否自动接受 2023-05-04 21:39:45 +08:00
heavyrian2012 ca50872913 server api添加获取单个群成员信息的接口 2023-05-04 19:00:08 +08:00
heavyrian2012 3c11c368a3 update readme 2023-04-28 11:32:47 +08:00
heavyrian2012 145709fd76 支持AES256配置 2023-04-24 11:51:13 +08:00
heavyrian2012 758c5de2c7 解决pc多端登录互踢时pc在线状态没有更新的问题 2023-04-24 11:26:55 +08:00
60 changed files with 1524 additions and 197 deletions
+15 -2
View File
@@ -20,7 +20,8 @@
* 结构设计合理,客户端分功能库、UI库和应用三层。应用成熟完善,开箱即用,也可把SDK嵌入其它应用。
* 拥有应用开放平台,可以开发和创建自建应用,扩展您的工作台。
* API丰富,方便与其它服务系统的对接。
* 拥有机器人和公众号功能。
* 拥有机器人和公众号功能,免费的频道(公众号)管理后台。
* 超级群组功能,可以支持万人大群。
* 社区版IM服务和移动端免费商用,可以免费构建出完备的移动互联网应用。
* 收费项目非常便宜,野火独有的试用模式,可以先部署到客户环境试用6个月,试用满意后再购买,避免上当受骗。
* 技术支持专业和高效,核心研发人员及时处理issue和论坛回复。
@@ -53,6 +54,9 @@
## 野火开发文档
[在线文档](https://docs.wildfirechat.cn/)
## 野火IM论坛
[野火IM论坛](https://bbs.wildfirechat.cn)
## 野火性能测试报告及测试方法
[Github](https://github.com/wildfirechat/Performance_Test), [码云](https://gitee.com/wfchat/Performance_Test)。
@@ -69,7 +73,7 @@ PC客户端点[这里](https://github.com/wildfirechat/vue-pc-chat/releases)下
![野火IM](http://static.wildfirechat.net/wx.jpg)
## 快速使用
## 快速开始
可以按照[快速开始](https://docs.wildfirechat.cn/quick_start/)来部署应用服务和IM服务,然后打包移动端,就可以完成聊天和通话功能。
之后再部署开放平台服务、频道(公众号)服务、机器人服务、推送服务、Turn服务(音视频服务)来实现完整的应用功能,详情可以详细阅读文档。
@@ -127,6 +131,15 @@ mvn clean package
9. 从0.79 版本起把log4j升级到log4j2,因为log4j已经不再维护而且还有已知的漏洞,建议所有客户都升级,升级时注意更新log4j2的配置文件
10. 0.97版本更改了启动脚本```wildfirechat.sh```,如果是升级服务,请注意更新启动脚本。
## 维护说明
野火设计理念当中,IM服务和客户端协议栈构成个管道工具,数据在人和人或者人和服务或者服务和服务之间传递,可以通过Server API和自定义消息来对接和开发业务。业务系统把IM系统当作一个工具来使用,是不需要把任何业务逻辑写在IM服务中的。
如果修改了IM服务可能会引起跟客户端协议栈的不兼容,以后也没有可能从社区版IM服务迁移到专业版IM服务,还有一旦修改就跟我们代码不一样了,如果出了问题我们就无法分析和解决。所以 ***我们强烈不推荐在IM服务修改代码,如果修改过就不再提供任何技术支持和服务了***。除了IM服务以外的所有代码可以任意修改。
现有接口足够对接和二开任何业务了,如果发现无法实现你们的业务需求,可以在[论坛](https://bbs.wildfirechat.cn)来咨询,我们会分析如何实现,如果需要添加新接口,我们会及时免费添加。请切记:***不要修改IM服务的代码!*** ***不要修改IM服务的代码!*** ***不要修改IM服务的代码!***
详细维护说明请参考 [野火维护说明](https://docs.wildfirechat.cn/base_knowledge/maintain.html)。
## 应用截图
登录界面
+31 -2
View File
@@ -65,6 +65,9 @@ token.key testim
##是否拒绝空签名的android客户端, 默认为true。当有旧的客户端需要兼容时改成false,当所有都是新客户端时,改成true。
#connect.reject_empty_signature true
##是否使用AES256加密。默认客户端和服务器都是AES128加密,如果需要开启AES256,需要客户端和IM服务同时开通。
#encrypt.use_aes256 true
##首次登录,是否接收之前的历史消息。
##0 不接收历史消息,只接收${message.compensate_time_limit}毫秒以内的消息,由于服务器没有保存已经收取记录,所以如果有超过${message.compensate_time_limit}毫秒之前未收取的消息也不会收取下拉;
##1接收,会接收 message.max_queue 配置的条数的历史消息
@@ -120,6 +123,9 @@ message.group_mute_exception_types 401,402,403,404,405,407,408,410,411
## 用户被全局禁言时允许发送的消息类型
message.global_mute_exception_types 401,402,403,404,405,407,408,410,411
## 离线用户推送过期天数,0是永不过期,建议配置为7天。
message.push_expired_days 7
## 消息转发功能开启时,开关是否不转发server api接口消息。
## 当为true时,不转发server api发送的消息;当为false时,转发server api发送的消息。
message.no_forward_admin_message false
@@ -139,6 +145,9 @@ friend.disable_search false
##禁止按照昵称搜索用户。
friend.disable_nick_name_search false
##禁止按照用户id搜索用户,默认为true。
friend.disable_user_id_search true
##禁止发送好友邀请,通过server api添加好友不受此限制(force参数需要为true)
friend.disable_friend_request false
@@ -151,6 +160,9 @@ friend.reject_request_duration 2592000000
##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。
friend.request_expiration_duration 604800000
##请求添加机器人为好友时,机器人是否自动接受,默认为true
friend.robot_auto_accept true
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
chatroom.participant_idle_time 900000
@@ -160,6 +172,18 @@ chatroom.rejoin_when_active true
## 当一个聊天室不存在时,如果有用户加入就自动创建
chatroom.create_when_not_exist true
## 一个用户同一时刻只能加入一个聊天室。
## 当一个客户端加入一个聊天室时,如果这个客户端已经加入另外一个聊天室了,会自动退出之前的聊天室。
## 当一个客户端加入一个聊天室时,如果这个用户的其他端已经加入一个聊天室了,kickoff_other_platform为true时会自动退出之前的聊天室,为false时会返回225的错误码。
## 当自动退出聊天室时,客户端不会收到任何通知,只是不会再收到消息。
chatroom.kickoff_other_platform true
## 是否允许群主不受限制地撤回自己发送的消息。false可以${message.recall_time_limit}撤回自己的消息;true可以撤回任意时间自己的消息。默认为true。
group.allow_owner_recall_self_msg true
## 是否允许群管理员不受限制地撤回自己发送的消息。false可以${message.recall_time_limit}撤回自己的消息;true可以撤回任意时间自己的消息。默认为false。
group.allow_manager_recall_self_msg false
## 是否允许客户端发送操作群的自定义群通知消息
group.allow_client_custom_operation_notification true
@@ -186,6 +210,9 @@ user.keep_display_name_when_destroy true
# 因此需要分段多次同步,此开关定义了每次同步的数据的条数。此需要客户端支持,客户端SDK在2021.5.25日后支持此功能。如果确认所有客户端都在这个日志之后才可以打开此设置。
#sync.data_part_size 1000
## 是否关闭api/version接口。api/version方法可以用来检查IM服务版本,上线确认无问题后,可以关掉这个接口。
#http.close_api_version false
#*********************************************************************
# 限频配置
#*********************************************************************
@@ -351,10 +378,12 @@ push.ios.server.address http://localhost:8085/ios/push
#*********************************************************************
# Sensitive configuration
#*********************************************************************
## 内置文本敏感词过滤处理方法,0 发送失败;1 发送成功但消息被服务器直接丢弃;2 命中的敏感词被替换成***;3 记录并继续发送
## 内置文本敏感词过滤处理方法,当命中敏感词后,消息会被记录到t_sensitive_messages表中,然后根据type类型做不同的处理,处理方式如下:
## 0 发送失败;1 发送成功但消息被服务器直接丢弃;2 命中的敏感词被替换成***然后正常发送;3 正常发送。
## 如果开启 message.sensitive.forward.url 配置,命中敏感词的消息还会被回调到这个地址
sensitive.filter.type 0
## 如果内置敏感词库无法满足您的需求,可以自己开发部署敏感词审核服务。配置如下地址和消息类型,IM服务会把指定消息类型的消息回调到指定地址
## 如果内置敏感词库无法满足您的需求,可以开发部署独立敏感词审核服务。配置如下地址和消息类型,IM服务会把指定消息类型的消息回调到指定地址,内置的敏感词审核和敏感词转发功能就不再起作用了。
## 审核服务返回状态码200表示继续发送,如果需要替换内容,返回状态码200并且内容为替换后的内容。返回403表示不允许发送。其它错误继续发送。
## 独立审核服务地址,IM服务会post SendMessageData。如果需要修改消息内容,返回 MessagePayload。请参考应用服务中 "/message/censor" Mapping.
#sensitive.remote_server_url http://192.168.3.202:8888/message/censor
+1 -1
View File
@@ -5,7 +5,7 @@
<relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>1.1.3</version>
<version>1.2.0</version>
</parent>
<artifactId>moquette-broker</artifactId>
@@ -12,9 +12,11 @@ package cn.wildfirechat.push;
public class PushMessage {
public String sender;
public String senderName;
public String senderPortrait;
public int convType;
public String target;
public String targetName;
public String targetPortrait;
public String userId;
public int line;
public int cntType;
@@ -34,12 +36,14 @@ public class PushMessage {
public String language;
public long messageId;
public PushMessage(String sender, int conversationType, String target, int line, int messageContentType, long serverTime, String senderName, String targetName, int unReceivedMsg, int mentionedType, boolean isHiddenDetail, String language) {
public PushMessage(String sender, int conversationType, String target, int line, int messageContentType, long serverTime, String senderName, String senderPortrait, String targetName, String targetPortrait, int unReceivedMsg, int mentionedType, boolean isHiddenDetail, String language) {
this.sender = sender;
this.convType = conversationType;
this.target = target;
this.senderName = senderName;
this.senderPortrait = senderPortrait;
this.targetName = targetName;
this.targetPortrait = targetPortrait;
this.line = line;
this.cntType = messageContentType;
this.serverTime = serverTime;
@@ -47,6 +47,8 @@ abstract public class Action {
protected static RateLimiter robotLimiter = null;
protected static RateLimiter channelLimiter = null;
protected static boolean closeApiVersion = false;
public static void init(IConfig config) {
int adminRate = 10000;
int robotRate = 1000;
@@ -70,6 +72,11 @@ abstract public class Action {
adminLimiter = new RateLimiter(10, adminRate);
robotLimiter = new RateLimiter(10, robotRate);
channelLimiter = new RateLimiter(10, channelRate);
try {
closeApiVersion = Boolean.parseBoolean(config.getProperty(HTTP_CLOSE_API_VERSION, "false"));
} catch (Exception e) {
}
}
protected class Result {
@@ -31,6 +31,11 @@ public class CheckTokenAction extends Action {
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
if(closeApiVersion) {
response.sendError(HttpResponseStatus.NOT_FOUND, "404 Not found!");
return true;
}
response.setStatus(HttpResponseStatus.OK);
String userId = request.getParam("userId");
String clientId = request.getParam("clientId");
@@ -30,8 +30,12 @@ public class VersionAction extends Action {
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
response.setStatus(HttpResponseStatus.OK);
if(closeApiVersion) {
response.sendError(HttpResponseStatus.NOT_FOUND, "404 Not found!");
return true;
}
response.setStatus(HttpResponseStatus.OK);
try {
response.setContent(Utility.formatJson(gson.toJson(GitRepositoryState.getGitRepositoryState())));
@@ -0,0 +1,59 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputGetUserInfo;
import cn.wildfirechat.pojos.InputGetUserList;
import cn.wildfirechat.pojos.InputOutputUserInfo;
import cn.wildfirechat.pojos.OutputGetUserList;
import cn.wildfirechat.proto.WFCMessage;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.User_Get_All)
@HttpMethod("POST")
public class GetAllUserAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetUserList input = getRequestBody(request.getNettyRequest(), InputGetUserList.class);
if (input != null && input.count > 0 && input.offset >= 0) {
List<WFCMessage.User> users = messagesStore.getUserInfoList(input.count, input.offset);
OutputGetUserList outputGetUserList = new OutputGetUserList();
outputGetUserList.userInfoList = new ArrayList<>();
for (WFCMessage.User user : users) {
outputGetUserList.userInfoList.add(InputOutputUserInfo.fromPbUser(user));
}
RestResult result = RestResult.ok(outputGetUserList);
setResponseContent(result, response);
} else {
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
}
}
return true;
}
}
@@ -0,0 +1,69 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputGetGroup;
import cn.wildfirechat.pojos.InputGetGroupMember;
import cn.wildfirechat.pojos.OutputGroupMemberList;
import cn.wildfirechat.pojos.PojoGroupMember;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.Group_Member_Get)
@HttpMethod("POST")
public class GetGroupMemberAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetGroupMember input = getRequestBody(request.getNettyRequest(), InputGetGroupMember.class);
if (input != null
&& (!StringUtil.isNullOrEmpty(input.getGroupId()))
&& (!StringUtil.isNullOrEmpty(input.getMemberId()))) {
WFCMessage.GroupMember groupMember = messagesStore.getGroupMember(input.getGroupId(), input.getMemberId());
RestResult result;
if (groupMember == null || StringUtil.isNullOrEmpty(groupMember.getMemberId()) || groupMember.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Removed) {
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
} else {
PojoGroupMember pm = new PojoGroupMember();
pm.setMember_id(groupMember.getMemberId());
pm.setAlias(groupMember.getAlias());
pm.setType(groupMember.getType());
pm.setExtra(groupMember.getExtra());
pm.setCreateDt(groupMember.getCreateDt());
result = RestResult.ok(pm);
}
setResponseContent(result, response);
} else {
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
}
}
return true;
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputGetChatroomInfo;
import cn.wildfirechat.pojos.InputUserId;
import cn.wildfirechat.pojos.OutputStringList;
import cn.wildfirechat.pojos.OutputUserChatroom;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.persistence.UserClientEntry;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Route(APIPath.Chatroom_GetUserChatroom)
@HttpMethod("POST")
public class GetUserChatroomAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputUserId inputUserId = getRequestBody(request.getNettyRequest(), InputUserId.class);
String userId = inputUserId.getUserId();
if (!StringUtil.isNullOrEmpty(userId)) {
OutputUserChatroom outputUserChatroom = messagesStore.getUserChatroom(userId);
RestResult result;
if (outputUserChatroom != null) {
result = RestResult.ok(outputUserChatroom);
} else {
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
}
setResponseContent(result, response);
} else {
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
}
}
return true;
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputGetUserGroupByType;
import cn.wildfirechat.pojos.InputUserId;
import cn.wildfirechat.pojos.OutputGroupIds;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.Set;
@Route(APIPath.Get_User_Groups_By_Type)
@HttpMethod("POST")
public class GetUserGroupsByTypeAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetUserGroupByType input = getRequestBody(request.getNettyRequest(), InputGetUserGroupByType.class);
if (input != null
&& (!StringUtil.isNullOrEmpty(input.getUserId()))) {
Set<String> groupIds = messagesStore.getUserGroupIds(input.getUserId(), input.getGroupMemberTypes());
OutputGroupIds outputGroupIds = new OutputGroupIds();
outputGroupIds.setGroupIds(new ArrayList<>(groupIds));
RestResult result = RestResult.ok(outputGroupIds);
setResponseContent(result, response);
} else {
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
}
}
return true;
}
}
@@ -25,6 +25,9 @@ import io.netty.util.internal.StringUtil;
import cn.wildfirechat.common.ErrorCode;
import win.liyufan.im.IMTopic;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@Route(APIPath.Msg_Recall)
@HttpMethod("POST")
public class RecallMessageAction extends AdminAction {
@@ -42,10 +45,9 @@ public class RecallMessageAction extends AdminAction {
WFCMessage.INT64Buf idBuf = WFCMessage.INT64Buf.newBuilder().setId(recallMessageData.getMessageUid()).build();
sendApiMessage(response, recallMessageData.getOperator(), IMTopic.RecallMessageTopic, idBuf.toByteArray(), result -> {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(result);
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
return new Result(errorCode);
ErrorCode errorCode = ErrorCode.fromCode(result[0]);
byte[] data = Arrays.copyOfRange(result,1, result.length);
return new Result(errorCode, new String(data, StandardCharsets.UTF_8));
});
return false;
} else {
@@ -0,0 +1,98 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.robot;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputGetGroup;
import cn.wildfirechat.pojos.InputGetGroupMember;
import cn.wildfirechat.pojos.OutputGroupMemberList;
import cn.wildfirechat.pojos.PojoGroupMember;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.Robot_Group_Member_Get)
@HttpMethod("POST")
public class GetGroupMemberAction extends RobotAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetGroupMember input = getRequestBody(request.getNettyRequest(), InputGetGroupMember.class);
String robotId = robot.getUid();
if (input != null
&& (!StringUtil.isNullOrEmpty(input.getGroupId()))
&& (!StringUtil.isNullOrEmpty(input.getMemberId()))) {
List<WFCMessage.GroupMember> members = new ArrayList<>();
ErrorCode errorCode = messagesStore.getGroupMembers(null, input.getGroupId(), 0, members);
RestResult result;
if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
result = RestResult.resultOf(errorCode);
} else {
WFCMessage.GroupMember groupMember = null;
boolean isInGroup = false;
for (WFCMessage.GroupMember member : members) {
if (member.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Removed) {
continue;
}
if(member.getMemberId().equals(robotId)) {
isInGroup = true;
if(groupMember != null) {
break;
}
}
if(member.getMemberId().equals(input.getMemberId())) {
groupMember = member;
if(isInGroup) {
break;
}
}
}
if(!isInGroup) {
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_IN_GROUP);
} else {
if(groupMember == null) {
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
} else {
PojoGroupMember pm = new PojoGroupMember();
pm.setMember_id(groupMember.getMemberId());
pm.setAlias(groupMember.getAlias());
pm.setType(groupMember.getType());
pm.setExtra(groupMember.getExtra());
pm.setCreateDt(groupMember.getCreateDt());
result = RestResult.ok(pm);
}
}
}
setResponseContent(result, response);
} else {
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
}
}
return true;
}
}
@@ -29,6 +29,8 @@ public final class BrokerConstants {
public static final String HTTP_SERVER_PORT = "http_port";
public static final String HTTP_LOCAL_PORT = "local_port";
public static final String ENCRYPT_AES256 = "encrypt.use_aes256";
public static final String HTTP_ADMIN_PORT = "http.admin.port";
public static final String DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME = "moquette_store.mapdb";
public static final String DEFAULT_PERSISTENT_PATH = System.getProperty("user.dir") + File.separator
@@ -151,22 +153,29 @@ public final class BrokerConstants {
public static final String MESSAGE_NO_Forward_Admin_Message = "message.no_forward_admin_message";
public static final String MESSAGE_Push_Expired_Days = "message.push_expired_days";
public static final String MESSAGE_Forward_With_Client_Info = "message.forward_with_client_info";
public static final String ROBOT_Callback_With_Client_Info = "robot.callback_with_client_info";
public static final String CHANNEL_Callback_With_Client_Info = "channel.callback_with_client_info";
public static final String FRIEND_Disable_Search = "friend.disable_search";
public static final String FRIEND_Disable_NickName_Search = "friend.disable_nick_name_search";
public static final String FRIEND_Disable_UserId_Search = "friend.disable_user_id_search";
public static final String FRIEND_Disable_Friend_Request = "friend.disable_friend_request";
public static final String FRIEND_Repeat_Request_Duration = "friend.repeat_request_duration";
public static final String FRIEND_Reject_Request_Duration = "friend.reject_request_duration";
public static final String FRIEND_Request_Expiration_Duration = "friend.request_expiration_duration";
public static final String FRIEND_Request_Robot_Auto_Accept = "friend.robot_auto_accept";
public static final String CHATROOM_Participant_Idle_Time = "chatroom.participant_idle_time";
public static final String CHATROOM_Rejoin_When_Active = "chatroom.rejoin_when_active";
public static final String CHATROOM_Create_When_Not_Exist = "chatroom.create_when_not_exist";
public static final String CHATROOM_Kickoff_Other_Platform = "chatroom.kickoff_other_platform";
public static final String GROUP_Allow_Owner_Recall_Self_Msg = "group.allow_owner_recall_self_msg";
public static final String GROUP_Allow_Manager_Recall_Self_Msg = "group.allow_manager_recall_self_msg";
public static final String GROUP_Allow_Client_Custom_Operation_Notification = "group.allow_client_custom_operation_notification";
public static final String GROUP_Allow_Robot_Custom_Operation_Notification = "group.allow_robot_custom_operation_notificatio";
@@ -195,6 +204,9 @@ public final class BrokerConstants {
public static final String HTTP_CHANNEL_RATE_LIMIT = "http.channel.rate_limit";
public static final String CLIENT_REQUEST_RATE_LIMIT = "client.request_rate_limit";
public static final String HTTP_CLOSE_API_VERSION = "http.close_api_version";
private BrokerConstants() {
}
}
@@ -30,8 +30,10 @@ public class AddFriendHandler extends GroupHandler<WFCMessage.AddFriendRequest>
if (user != null && user.getType() == ProtoConstants.UserType.UserType_Normal) {
publisher.publishNotification(IMTopic.NotifyFriendRequestTopic, request.getTargetUid(), head[0], fromUser, request.getReason());
} else if(user != null && user.getType() == ProtoConstants.UserType.UserType_Robot) {
WFCMessage.HandleFriendRequest handleFriendRequest = WFCMessage.HandleFriendRequest.newBuilder().setTargetUid(fromUser).setStatus(ProtoConstants.FriendRequestStatus.RequestStatus_Accepted).build();
mServer.onApiMessage(request.getTargetUid(), null, handleFriendRequest.toByteArray(), 0, fromUser, HandleFriendRequestTopic, requestSourceType);
if(m_messagesStore.isRobotAutoAcceptFriendRequest()) {
WFCMessage.HandleFriendRequest handleFriendRequest = WFCMessage.HandleFriendRequest.newBuilder().setTargetUid(fromUser).setStatus(ProtoConstants.FriendRequestStatus.RequestStatus_Accepted).build();
mServer.onApiMessage(request.getTargetUid(), null, handleFriendRequest.toByteArray(), 0, fromUser, HandleFriendRequestTopic, requestSourceType);
}
}
}
return errorCode;
@@ -0,0 +1,23 @@
package io.moquette.imhandler;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import win.liyufan.im.IMTopic;
import java.util.List;
@Handler(IMTopic.ListenedChannelListTopic)
public class ChannelListenedListHandler extends IMHandler<Void> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, Void request, Qos1PublishHandler.IMCallback callback) {
List<String> channelInfoList = m_messagesStore.getListenedChannels(fromUser);
WFCMessage.IDListBuf.Builder builder = WFCMessage.IDListBuf.newBuilder();
builder.addAllId(channelInfoList);
byte[] data = builder.build().toByteArray();
ackPayload.ensureWritable(data.length).writeBytes(data);
return ErrorCode.ERROR_CODE_SUCCESS;
}
}
@@ -23,7 +23,7 @@ public class RecallMessageHandler extends IMHandler<WFCMessage.INT64Buf> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.INT64Buf int64Buf, Qos1PublishHandler.IMCallback callback) {
boolean isAdmin = requestSourceType == ProtoConstants.RequestSourceType.Request_From_Admin;
ErrorCode errorCode = m_messagesStore.recallMessage(int64Buf.getId(), fromUser, clientID, isAdmin);
ErrorCode errorCode = m_messagesStore.recallMessage(int64Buf.getId(), fromUser, clientID, isAdmin, ackPayload);
if(errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
return errorCode;
@@ -12,7 +12,6 @@ import cn.wildfirechat.pojos.SystemSettingPojo;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import cn.wildfirechat.server.ThreadPoolExecutorWrapper;
import com.google.protobuf.InvalidProtocolBufferException;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.MultiMap;
import com.hazelcast.util.StringUtil;
@@ -39,6 +38,7 @@ import static cn.wildfirechat.common.IMExceptionEvent.EventType.RDBS_Exception;
import static cn.wildfirechat.proto.ProtoConstants.PersistFlag.Transparent;
import static io.moquette.server.Constants.MAX_MESSAGE_QUEUE;
import static cn.wildfirechat.proto.ProtoConstants.SearchUserType.*;
import static win.liyufan.im.UserSettingScope.kUserSettingPrivacySearchable;
public class DatabaseStore {
private static final Logger LOG = LoggerFactory.getLogger(DatabaseStore.class);
@@ -161,18 +161,12 @@ public class DatabaseStore {
}
return null;
}
//searchType
// 0 模糊匹配displayName, 精确匹配账户名和电话号码
// 1 精确匹配账户名和电话号码
// 2 精确匹配账户名
// 3 精确匹配电话号码
List<WFCMessage.User> searchUserFromDB(String keyword, int searchType, int page) {
List<WFCMessage.User> searchUserByNameMobileUserId(String keyword, int searchType) {
ArrayList<WFCMessage.User> out = new ArrayList<>();
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
ArrayList<WFCMessage.User> out = new ArrayList<>();
try {
connection = DBUtil.getConnection();
String sql = "select `_uid`, `_name`" +
@@ -185,61 +179,42 @@ public class DatabaseStore {
", `_company`" +
", `_social`" +
", `_extra`" +
", `_dt` from t_user";
switch (searchType) {
case SearchUserType_Name_Mobile:
sql += " where (`_name` = ? or `_mobile` = ?) ";
break;
case SearchUserType_Name:
sql += " where `_name` = ? ";
break;
case SearchUserType_Mobile:
sql += " where `_mobile` = ? ";
break;
case SearchUserType_General:
default:
sql += " where (`_display_name` like ? or `_name` = ? or `_mobile` = ?) ";
break;
}
", `_dt`, `_type` from t_user";
int sqlParaCount = 1;
if(searchType == SearchUserType_Name) {
sql += " where `_name` = ? ";
} else if(searchType == SearchUserType_Mobile) {
sql += " where `_mobile` = ? ";
} else if(searchType == SearchUserType_UserId) {
sql += " where `_uid` = ? ";
} else if(searchType == SearchUserType_Name_Mobile) {
sqlParaCount = 2;
sql += " where (`_name` = ? or `_mobile` = ?) ";
} else {
sqlParaCount = 3;
sql += " where (`_name` = ? or `_mobile` = ? or `_uid` = ?) ";
}
sql += " and `_type` <> 2 and `_deleted` = 0"; //can search normal user(0) and robot(1) and admin(100), can not search things
if (searchType == SearchUserType_Name_Mobile || searchType == SearchUserType_Name || searchType == SearchUserType_Mobile) {
if(searchType == SearchUserType_Name || searchType == SearchUserType_Mobile || searchType == SearchUserType_UserId) {
sql += " limit 1";
} else if(searchType == SearchUserType_Name_Mobile) {
sql += " limit 2";
} else {
sql += " limit 20";
}
if (page > 0) {
sql += " offset " + page * 20;
sql += " limit 3";
}
statement = connection.prepareStatement(sql);
int index = 1;
switch (searchType) {
case SearchUserType_Name_Mobile:
statement.setString(index++, keyword);
statement.setString(index++, keyword);
break;
case SearchUserType_Name:
case SearchUserType_Mobile:
statement.setString(index++, keyword);
break;
case SearchUserType_General:
default:
statement.setString(index++, "%" + keyword + "%");
statement.setString(index++, keyword);
statement.setString(index++, keyword);
break;
for (int i = 0; i < sqlParaCount; i++) {
statement.setString(i+1, keyword);
}
rs = statement.executeQuery();
while (rs.next()) {
WFCMessage.User.Builder builder = WFCMessage.User.newBuilder();
index = 1;
int index = 1;
String value = rs.getString(index++);
value = (value == null ? "" : value);
@@ -287,6 +262,9 @@ public class DatabaseStore {
long longValue = rs.getLong(index++);
builder.setUpdateDt(longValue);
int type = rs.getInt(index++);
builder.setType( type);
WFCMessage.User user = builder.build();
out.add(user);
@@ -298,6 +276,252 @@ public class DatabaseStore {
} finally {
DBUtil.closeDB(connection, statement, rs);
}
List<WFCMessage.User> filter = new ArrayList<>();
for (WFCMessage.User user : out) {
WFCMessage.UserSettingEntry userSettingEntry = Server.getServer().getStore().messagesStore().getUserSetting(user.getUid(), kUserSettingPrivacySearchable, null);
if(userSettingEntry != null) {
int value = 0;
try {
value = StringUtil.isNullOrEmpty(userSettingEntry.getValue())?0:Integer.parseInt(userSettingEntry.getValue());
} catch (NumberFormatException e) {
e.printStackTrace();
}
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0) {
if (searchType == SearchUserType_Name) {
filter.add(user);
continue;
} else if(searchType == SearchUserType_Name_Mobile) {
if(keyword.equals(user.getName())) {
if(!keyword.equals(user.getMobile())) {
filter.add(user);
continue;
} else if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
filter.add(user);
continue;
}
}
} else if(searchType == SearchUserType_Name_Mobile_UserId) {
if(keyword.equals(user.getName())) {
if(keyword.equals(user.getMobile()) && keyword.equals(user.getUid())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0 && (value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
filter.add(user);
continue;
}
} else if(keyword.equals(user.getMobile())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
filter.add(user);
continue;
}
} else if(keyword.equals(user.getUid())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
filter.add(user);
continue;
}
} else {
filter.add(user);
continue;
}
}
}
}
if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
if (searchType == SearchUserType_Mobile) {
filter.add(user);
continue;
} else if(searchType == SearchUserType_Name_Mobile) {
if(keyword.equals(user.getMobile())) {
if(!keyword.equals(user.getName())) {
filter.add(user);
continue;
} else if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0) {
filter.add(user);
continue;
}
}
} else if(searchType == SearchUserType_Name_Mobile_UserId) {
if(keyword.equals(user.getMobile())) {
if(keyword.equals(user.getName()) && keyword.equals(user.getUid())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0 && (value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
filter.add(user);
continue;
}
} else if(keyword.equals(user.getName())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0) {
filter.add(user);
continue;
}
} else if(keyword.equals(user.getUid())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
filter.add(user);
continue;
}
} else {
filter.add(user);
continue;
}
}
}
}
if((value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
if (searchType == SearchUserType_UserId) {
filter.add(user);
continue;
} else if(searchType == SearchUserType_Name_Mobile_UserId) {
if(keyword.equals(user.getUid())) {
if(keyword.equals(user.getName()) && keyword.equals(user.getMobile())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0 && (value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
filter.add(user);
continue;
}
} else if(keyword.equals(user.getName())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0) {
filter.add(user);
continue;
}
} else if(keyword.equals(user.getMobile())) {
if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
filter.add(user);
continue;
}
} else {
filter.add(user);
continue;
}
}
}
}
}
}
out.removeAll(filter);
return out;
}
List<WFCMessage.User> searchUserByDisplayName(String keyword, int page, List<WFCMessage.User> nameOrIdMatched) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
ArrayList<WFCMessage.User> out = new ArrayList<>();
try {
connection = DBUtil.getConnection();
String sql = "select u._uid, u._name, u._display_name, u._portrait, u._mobile, u._gender, u._email, u._address, u._company, u._social, u._extra, u._dt, u._type " +
" from t_user u left join (select _uid, _value from t_user_setting where _scope = 27) s on u._uid = s._uid " +
" where u._display_name like ? and u._type <> 2 and u._deleted = 0 ";
if(nameOrIdMatched.size() == 1) {
sql += " and u._uid <> ? and u._name <> ?";
} else if(nameOrIdMatched.size() == 2) {
sql += " and u._uid <> ? and u._uid <>? and u._name <> ? and u._name <>? ";
}
sql += " and (s._value is null or (s._value <> 1 and s._value <> 3 and s._value <> 5 and s._value <> 7)) limit ";
if(page == 0) {
sql += (20 - nameOrIdMatched.size());
} else {
sql += 20;
}
if (page > 0) {
sql += " offset " + (page * 20 - nameOrIdMatched.size());
}
statement = connection.prepareStatement(sql);
statement.setString(1, "%" + keyword + "%");
if(nameOrIdMatched.size() == 1) {
statement.setString(2, nameOrIdMatched.toArray(new WFCMessage.User[0])[0].getUid());
statement.setString(3, nameOrIdMatched.toArray(new WFCMessage.User[0])[0].getUid());
} else if(nameOrIdMatched.size() == 2) {
statement.setString(2, nameOrIdMatched.toArray(new WFCMessage.User[0])[0].getUid());
statement.setString(3, nameOrIdMatched.toArray(new WFCMessage.User[0])[1].getUid());
statement.setString(4, nameOrIdMatched.toArray(new WFCMessage.User[0])[0].getUid());
statement.setString(5, nameOrIdMatched.toArray(new WFCMessage.User[0])[1].getUid());
}
rs = statement.executeQuery();
while (rs.next()) {
WFCMessage.User.Builder builder = WFCMessage.User.newBuilder();
int index = 1;
String value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setUid(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setName(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setDisplayName(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setPortrait(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setMobile(value);
int gender = rs.getInt(index++);
builder.setGender(gender);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setEmail(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setAddress(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setCompany(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setSocial(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setExtra(value);
long longValue = rs.getLong(index++);
builder.setUpdateDt(longValue);
int type = rs.getInt(index++);
builder.setType(type);
WFCMessage.User user = builder.build();
out.add(user);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception);
} finally {
DBUtil.closeDB(connection, statement, rs);
}
return out;
}
List<WFCMessage.User> searchUserFromDB(String keyword, int searchType, int page) {
List<WFCMessage.User> nameOrIdMatched = searchUserByNameMobileUserId(keyword, searchType);
List<WFCMessage.User> out = new ArrayList<>();
if(page == 0) {
out.addAll(nameOrIdMatched);
}
if(searchType == SearchUserType_General) {
List<WFCMessage.User> general = searchUserByDisplayName(keyword, page, nameOrIdMatched);
general.removeAll(nameOrIdMatched);
out.addAll(general);
}
return out;
}
@@ -1709,6 +1933,45 @@ public class DatabaseStore {
return null;
}
Set<String> getUserGroupIds(String userId, List<Integer> memberTypes) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
try {
connection = DBUtil.getConnection();
String sql = "select _gid from t_group_member where _mid = ? ";
if(!memberTypes.isEmpty()) {
sql += " and _type in (";
for (int i = 0; i < memberTypes.size(); i++) {
if(i > 0) {
sql += ",";
}
sql += memberTypes.get(i);
}
sql += ")";
}
statement = connection.prepareStatement(sql);
statement.setString(1, userId);
rs = statement.executeQuery();
Set<String> out = new HashSet<>();
while (rs.next()) {
String uid = rs.getString(1);
out.add(uid);
}
return out;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception);
} finally {
DBUtil.closeDB(connection, statement, rs);
}
return null;
}
Set<String> getCommonGroupIds(String userId1, String userId2) {
Connection connection = null;
PreparedStatement statement = null;
@@ -2640,6 +2903,103 @@ public class DatabaseStore {
return null;
}
List<WFCMessage.User> getAllUsers(int count, int offset) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
List<WFCMessage.User> outList = new ArrayList<>();
try {
connection = DBUtil.getConnection();
String sql = "select `_uid`, `_name`" +
", `_display_name`" +
", `_portrait`" +
", `_mobile`" +
", `_gender`" +
", `_email`" +
", `_address`" +
", `_company`" +
", `_social`" +
", `_extra`" +
", `_type`" +
", `_deleted`" +
", `_dt` from t_user where `_deleted` = 0 order by _createTime limit ? offset ?";
statement = connection.prepareStatement(sql);
int index = 1;
statement.setInt(1, count);
statement.setInt(2, offset);
rs = statement.executeQuery();
while (rs.next()) {
WFCMessage.User.Builder builder = WFCMessage.User.newBuilder();
index = 1;
String value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setUid(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setName(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setDisplayName(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setPortrait(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setMobile(value);
int gender = rs.getInt(index++);
builder.setGender(gender);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setEmail(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setAddress(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setCompany(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setSocial(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setExtra(value);
int type = rs.getInt(index++);
builder.setType(type);
int deleted = rs.getInt(index++);
builder.setDeleted(deleted);
long longValue = rs.getLong(index++);
if(longValue <= 0)
longValue = 1;
builder.setUpdateDt(longValue);
outList.add(builder.build());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception);
} finally {
DBUtil.closeDB(connection, statement, rs);
}
return outList;
}
Set<String> getAllEnds() {
Connection connection = null;
PreparedStatement statement = null;
@@ -35,6 +35,7 @@ import io.moquette.spi.IMessagesStore;
import io.moquette.spi.impl.security.AES;
import io.moquette.spi.security.Tokenor;
import io.moquette.spi.impl.subscriptions.Topic;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.mqtt.MqttVersion;
import org.apache.commons.codec.digest.DigestUtils;
import org.json.simple.JSONObject;
@@ -44,6 +45,7 @@ import win.liyufan.im.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@@ -135,12 +137,23 @@ public class MemoryMessagesStore implements IMessagesStore {
private ConcurrentHashMap<String, Boolean> userPushHiddenDetail = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Boolean> userConvSlientMap = new ConcurrentHashMap<>();
private LinkedHashMap<String, Long> repeatFriendRequest = new LinkedHashMap<String, Long>() {
@Override
protected boolean removeEldestEntry(Map.Entry<String, Long> eldest) {
return System.currentTimeMillis() - eldest.getValue() > 5 * 60 * 1000;
}
};
private boolean mDisableSearch = false;
private boolean mDisableNicknameSearch = false;
private boolean mDisableUserIdSearch = false;
private boolean mDisableFriendRequest = false;
private long mFriendRequestDuration = 7 * 24 * 60 * 60 * 1000;
private long mFriendRejectDuration = 30 * 24 * 60 * 60 * 1000;
private long mFriendRequestExpiration = 7 * 24 * 60 * 60 * 1000;
private boolean mFriendRobotAutoAccept = true;
private long mPushExpiredTimes = 604800000L;
private boolean mMultiPlatformNotification = false;
private boolean mMobileDefaultSilentWhenPCOnline = true;
@@ -153,6 +166,7 @@ public class MemoryMessagesStore implements IMessagesStore {
private long mChatroomParticipantIdleTime = 900000;
private boolean mChatroomRejoinWhenActive = true;
private boolean mChatroomCreateWhenNotExist = true;
private boolean mChatroomKickoffOtherPlatform = true;
private List<Integer> mForbiddenClientSendTypes = new ArrayList<>();
private List<Integer> mBlackListExceptionTypes = new ArrayList<>();
@@ -168,6 +182,8 @@ public class MemoryMessagesStore implements IMessagesStore {
private String mChannelInfoUpdateCallback;
private String mChatroomInfoUpdateCallback;
private String mChatroomMemberUpdateCallback;
private boolean mGroupAllowOwnerRecallSelfMsg = false;
private boolean mGroupAllowManagerRecallSelfMsg = false;
private boolean mGroupAllowClientCustomOperationNotification;
private boolean mGroupAllowRobotCustomOperationNotification;
private int mGroupVisibleQuitKickoffNotification;
@@ -265,6 +281,12 @@ public class MemoryMessagesStore implements IMessagesStore {
Utility.printExecption(LOG, e);
printMissConfigLog(FRIEND_Disable_NickName_Search, mDisableNicknameSearch + "");
}
try {
mDisableUserIdSearch = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.FRIEND_Disable_UserId_Search, "true"));
} catch (Exception e) {
}
try {
mDisableFriendRequest = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.FRIEND_Disable_Friend_Request));
} catch (Exception e) {
@@ -297,6 +319,18 @@ public class MemoryMessagesStore implements IMessagesStore {
printMissConfigLog(FRIEND_Request_Expiration_Duration, mFriendRequestExpiration + "");
}
try {
mFriendRobotAutoAccept = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.FRIEND_Request_Robot_Auto_Accept, "true"));
} catch (Exception e) {
}
try {
mPushExpiredTimes = Long.parseLong(m_Server.getConfig().getProperty(BrokerConstants.MESSAGE_Push_Expired_Days, "7")) * 86400000L;
if(mPushExpiredTimes == 0) mPushExpiredTimes = Long.MAX_VALUE;
} catch (Exception e) {
}
try {
mChatroomRejoinWhenActive = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.CHATROOM_Rejoin_When_Active));
} catch (Exception e) {
@@ -313,6 +347,12 @@ public class MemoryMessagesStore implements IMessagesStore {
printMissConfigLog(CHATROOM_Create_When_Not_Exist, mChatroomCreateWhenNotExist + "");
}
try {
mChatroomKickoffOtherPlatform = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.CHATROOM_Kickoff_Other_Platform, "true"));
} catch (Exception e) {
}
try {
mChatroomParticipantIdleTime = Long.parseLong(m_Server.getConfig().getProperty(CHATROOM_Participant_Idle_Time, "900000"));
} catch (Exception e) {
@@ -444,6 +484,17 @@ public class MemoryMessagesStore implements IMessagesStore {
}
try {
mGroupAllowOwnerRecallSelfMsg = Boolean.parseBoolean(server.getConfig().getProperty(GROUP_Allow_Owner_Recall_Self_Msg, "true"));
} catch (Exception e) {
}
try {
mGroupAllowManagerRecallSelfMsg = Boolean.parseBoolean(server.getConfig().getProperty(GROUP_Allow_Manager_Recall_Self_Msg, "false"));
} catch (Exception e) {
}
try {
mGroupAllowClientCustomOperationNotification = Boolean.parseBoolean(server.getConfig().getProperty(GROUP_Allow_Client_Custom_Operation_Notification));
} catch (Exception e) {
@@ -803,7 +854,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
if (bundle.getMessage().getContent().getExpireDuration() > 0) {
if (System.currentTimeMillis() > bundle.getMessage().getServerTimestamp() + bundle.getMessage().getContent().getExpireDuration()*1000) {
if (System.currentTimeMillis() > bundle.getMessage().getServerTimestamp() + bundle.getMessage().getContent().getExpireDuration()* 1000L) {
continue;
}
}
@@ -889,7 +940,29 @@ public class MemoryMessagesStore implements IMessagesStore {
Collection<UserClientEntry> members = chatroomMembers.get(chatroomId);
return members;
}
//Todo chatroom
@Override
public OutputUserChatroom getUserChatroom(String userId) {
String chatroomId = (String) m_Server.getHazelcastInstance().getMap(USER_CHATROOM).get(userId);
if(chatroomId != null) {
MultiMap<String, UserClientEntry> chatroomMembers = m_Server.getHazelcastInstance().getMultiMap(CHATROOM_MEMBER_IDS);
for (UserClientEntry userClientEntry : chatroomMembers.get(chatroomId)) {
if(userClientEntry.userId.equals(userId)) {
OutputUserChatroom outputUserChatroom = new OutputUserChatroom();
outputUserChatroom.userId = userId;
outputUserChatroom.chatroomId = chatroomId;
outputUserChatroom.clientId = userClientEntry.clientId;
MemorySessionStore.Session session = m_Server.getStore().sessionsStore().getSession(userClientEntry.clientId);
if(session != null) {
outputUserChatroom.platform = session.getPlatform();
}
return outputUserChatroom;
}
}
}
return null;
}
@Override
public WFCMessage.PullMessageResult fetchChatroomMessage(String fromUser, String chatroomId, String exceptClientId, long fromMessageId) {
WFCMessage.PullMessageResult.Builder builder = WFCMessage.PullMessageResult.newBuilder();
@@ -1920,6 +1993,11 @@ public class MemoryMessagesStore implements IMessagesStore {
return databaseStore.getUserGroupIds(userId);
}
@Override
public Set<String> getUserGroupIds(String userId, List<Integer> memberTypes) {
return databaseStore.getUserGroupIds(userId, memberTypes);
}
@Override
public Set<String> getCommonGroupIds(String userId1, String userId2) {
return databaseStore.getCommonGroupIds(userId1, userId2);
@@ -2065,6 +2143,10 @@ public class MemoryMessagesStore implements IMessagesStore {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
if(userList.contains(groupInfo.getOwner())) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
long updateDt = System.currentTimeMillis();
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
Collection<WFCMessage.GroupMember> members = groupMembers.get(groupId);
@@ -2170,7 +2252,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin) {
public ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin, ByteBuf ackPayload) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
IMap<Long, MessageBundle> mIMap = hzInstance.getMap(MESSAGES_MAP);
@@ -2199,7 +2281,28 @@ public class MemoryMessagesStore implements IMessagesStore {
return ErrorCode.ERROR_CODE_RECALL_TIME_EXPIRED;
}
if (operatorId.equals(groupInfo.getOwner())) {
canRecall = true;
if(operatorId.equals(message.getFromUser())) {
if(mGroupAllowOwnerRecallSelfMsg) {
canRecall = true;
}
} else {
canRecall = true;
}
} else {
if(message.getFromUser().equals(operatorId) && mGroupAllowManagerRecallSelfMsg) {
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
Collection<WFCMessage.GroupMember> members = groupMembers.get(message.getConversation().getTarget());
if (members == null || members.size() == 0) {
members = loadGroupMemberFromDB(hzInstance, message.getConversation().getTarget());
}
for (WFCMessage.GroupMember member : members) {
if (member.getMemberId().equals(operatorId)) {
if (member.getType() == GroupMemberType_Manager || member.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Owner) {
canRecall = true;
}
}
}
}
}
if(!canRecall && !message.getFromUser().equals(operatorId)) {
@@ -2265,7 +2368,7 @@ public class MemoryMessagesStore implements IMessagesStore {
json.put("c", message.getContent().getContent());
json.put("e", message.getContent().getExtra());
if (message.getContent().getData() != null && message.getContent().getData().size() > 0) {
json.put("b", Base64.getEncoder().encode(message.getContent().getData().toByteArray()));
json.put("b", Base64.getEncoder().encodeToString(message.getContent().getData().toByteArray()));
}
if (message.getContent().getMediaType() > 0) {
json.put("mt", message.getContent().getMediaType());
@@ -2296,6 +2399,7 @@ public class MemoryMessagesStore implements IMessagesStore {
databaseStore.deleteMessage(messageUid);
mIMap.put(messageUid, messageBundle, 7, TimeUnit.DAYS);
ackPayload.writeBytes(recalledContent.getBytes(StandardCharsets.UTF_8));
return ErrorCode.ERROR_CODE_SUCCESS;
} else {
return ErrorCode.ERROR_CODE_NOT_EXIST;
@@ -2510,6 +2614,28 @@ public class MemoryMessagesStore implements IMessagesStore {
}
}
private boolean isOnlineValueEqual(WFCMessage.UserSettingEntry pcentry, String newValue) {
if(pcentry == null) {
return StringUtil.isNullOrEmpty(newValue);
}
String oldValue = pcentry.getValue();
if(StringUtil.isNullOrEmpty(oldValue) && StringUtil.isNullOrEmpty(newValue)) {
return true;
}
if(StringUtil.isNullOrEmpty(oldValue) || StringUtil.isNullOrEmpty(newValue)) {
return false;
}
String[] ssOld = oldValue.split("\\|");
String[] ssNew = newValue.split("\\|");
if(ssOld.length != 4 || ssNew.length != 4 || !ssOld[1].equals(ssNew[1]) || !ssOld[2].equals(ssNew[2]) || !ssOld[3].equals(ssNew[3])) {
return false;
}
return true;
}
@Override
public void updateUserOnlineSetting(MemorySessionStore.Session session, boolean online) {
if(!mMultiPlatformNotification) {
@@ -2541,14 +2667,8 @@ public class MemoryMessagesStore implements IMessagesStore {
}
WFCMessage.UserSettingEntry pcentry = getUserSetting(session.getUsername(), kUserSettingPCOnline, "PC");
if (pcValue != null) {
if (pcentry == null || StringUtil.isNullOrEmpty(pcentry.getValue())) {
updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("PC").setValue(pcValue).build(), session.clientID);
}
} else {
if (pcentry != null && !StringUtil.isNullOrEmpty(pcentry.getValue())) {
updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("PC").setValue("").build(), session.clientID);
}
if (!isOnlineValueEqual(pcentry, pcValue)) {
updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("PC").setValue(pcValue==null?"":pcValue).build(), session.clientID);
}
}
@@ -2741,6 +2861,12 @@ public class MemoryMessagesStore implements IMessagesStore {
String userId = databaseStore.getUserIdByMobile(mobile);
return getUserInfo(userId);
}
@Override
public List<WFCMessage.User> getUserInfoList(int count, int offset) {
return databaseStore.getAllUsers(count, offset);
}
@Override
public List<WFCMessage.User> searchUser(String keyword, int searchType, int page) {
if (mDisableSearch) {
@@ -2748,6 +2874,10 @@ public class MemoryMessagesStore implements IMessagesStore {
}
if (mDisableNicknameSearch && searchType == ProtoConstants.SearchUserType.SearchUserType_General) {
searchType = ProtoConstants.SearchUserType.SearchUserType_Name_Mobile_UserId;
}
if(mDisableUserIdSearch && (searchType == ProtoConstants.SearchUserType.SearchUserType_General || searchType == ProtoConstants.SearchUserType.SearchUserType_Name_Mobile_UserId)) {
searchType = ProtoConstants.SearchUserType.SearchUserType_Name_Mobile;
}
@@ -2905,7 +3035,7 @@ public class MemoryMessagesStore implements IMessagesStore {
if (mDisableStrangerChat) {
//在禁止私聊时,是否是允许私聊的用户id
if(mAllowStrangerChatSet.contains(targetUser)) {
if(mAllowStrangerChatSet.contains(targetUser) || mAllowStrangerChatSet.contains(fromUser)) {
return ErrorCode.ERROR_CODE_SUCCESS;
}
@@ -3068,37 +3198,40 @@ public class MemoryMessagesStore implements IMessagesStore {
}
if (existRequest != null && existRequest.getStatus() != ProtoConstants.FriendRequestStatus.RequestStatus_Accepted && !isAdmin) {
if (mFriendRequestDuration > 0 && System.currentTimeMillis() - existRequest.getUpdateDt() > mFriendRequestDuration) {
if (existRequest.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Rejected
&& System.currentTimeMillis() - existRequest.getUpdateDt() < mFriendRejectDuration) {
return ErrorCode.ERROR_CODE_FRIEND_REQUEST_BLOCKED;
if (existRequest.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Rejected
&& System.currentTimeMillis() - existRequest.getUpdateDt() < mFriendRejectDuration) {
return ErrorCode.ERROR_CODE_FRIEND_REQUEST_BLOCKED;
}
if (!(mFriendRequestDuration > 0 && System.currentTimeMillis() - existRequest.getUpdateDt() > mFriendRequestDuration)) {
if(System.currentTimeMillis() - existRequest.getUpdateDt() > 5 * 60 * 1000) {
return ErrorCode.ERROR_CODE_FRIEND_ALREADY_REQUEST;
} else {
mWriteLock.lock();
try {
String repeatKey = userId + "-" + existRequest.getToUid();
Long lastTime = repeatFriendRequest.get(repeatKey);
if(lastTime != null && System.currentTimeMillis() - lastTime < 5 * 60 * 1000) {
return ErrorCode.ERROR_CODE_FRIEND_ALREADY_REQUEST;
}
repeatFriendRequest.put(repeatKey, System.currentTimeMillis());
} finally {
mWriteLock.unlock();
}
}
} else {
return ErrorCode.ERROR_CODE_FRIEND_ALREADY_REQUEST;
}
}
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS);
FriendData friendData1 = null;
Collection<FriendData> friendDatas = friendsMap.get(userId);
if (friendDatas == null || friendDatas.size() == 0) {
friendDatas = loadFriend(friendsMap, userId);
}
for (FriendData fd : friendDatas) {
if (fd.getFriendUid().equals(request.getTargetUid())) {
friendData1 = fd;
break;
}
}
if (friendData1 != null && friendData1.getBlacked() > 0 && !isAdmin) {
return ErrorCode.ERROR_CODE_IN_BLACK_LIST;
}
FriendData friendData1 = getFriendData(userId, request.getTargetUid());
if (friendData1 != null && friendData1.getState() == 0) {
return ErrorCode.ERROR_CODE_ALREADY_FRIENDS;
}
FriendData friendData2 = getFriendData(request.getTargetUid(), userId);
if (friendData2 != null && friendData2.getBlacked() > 0 && !isAdmin) {
return ErrorCode.ERROR_CODE_IN_BLACK_LIST;
}
WFCMessage.FriendRequest newRequest = WFCMessage.FriendRequest
.newBuilder()
.setFromUid(userId)
@@ -3437,9 +3570,25 @@ public class MemoryMessagesStore implements IMessagesStore {
}
}
MultiMap<String, UserClientEntry> chatroomMembers = m_Server.getHazelcastInstance().getMultiMap(CHATROOM_MEMBER_IDS);
String alreadyInChatroom = (String) m_Server.getHazelcastInstance().getMap(USER_CHATROOM).get(userId);
if(alreadyInChatroom != null) {
for (UserClientEntry userClientEntry : chatroomMembers.get(alreadyInChatroom)) {
if(userClientEntry.userId.equals(userId)) {
if(!chatroomId.equals(alreadyInChatroom) || !userClientEntry.clientId.equals(clientId)) {
if(mChatroomKickoffOtherPlatform) {
handleQuitChatroom(userId, userClientEntry.clientId, chatroomId);
} else {
return ErrorCode.ERROR_CODE_OTHER_CLIENT_ALREADY_IN_CHATROOM;
}
}
}
}
}
m_Server.getStore().sessionsStore().getSession(clientId).refreshLastChatroomActiveTime();
m_Server.getHazelcastInstance().getMap(USER_CHATROOM).put(userId, chatroomId);
m_Server.getHazelcastInstance().getMultiMap(CHATROOM_MEMBER_IDS).put(chatroomId, new UserClientEntry(userId, clientId));
chatroomMembers.put(chatroomId, new UserClientEntry(userId, clientId));
mWriteLock.lock();
chatroomMessages.put(userId, new TreeMap<>());
@@ -3476,7 +3625,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
private String ensureSecretLength(String secret) {
while ( secret.length() < 16) {
while ( secret.length() < AES.keyLen) {
secret += "w";
secret += secret;
}
@@ -4121,6 +4270,11 @@ public class MemoryMessagesStore implements IMessagesStore {
return databaseStore.searchChannelFromDB(keyword, buzzy, page);
}
@Override
public List<String> getListenedChannels(String userId) {
return databaseStore.getUserChannels(userId);
}
@Override
public ErrorCode listenChannel(String operator, String channelId, boolean listen) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
@@ -4290,6 +4444,16 @@ public class MemoryMessagesStore implements IMessagesStore {
return mChannelCallbackWithClientInfo;
}
@Override
public boolean isRobotAutoAcceptFriendRequest() {
return mFriendRobotAutoAccept;
}
@Override
public long getPushExpiredTimes() {
return mPushExpiredTimes;
}
@Override
public List<Integer> getClientForbiddenSendTypes() {
return mForbiddenClientSendTypes;
@@ -232,18 +232,6 @@ public class Server {
handlers = Collections.emptyList();
}
DBUtil.init(config);
String strKey = "0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F";
String[] strs = strKey.split(",");
if(strs.length != 16) {
LOG.error("Key error, it length should be 16");
}
byte[] keys = new byte[16];
for (int i = 0; i < 16; i++) {
keys[i] = (byte)(Integer.parseInt(strs[i].replace("0X", "").replace("0x", ""), 16));
}
AES.init(keys);
LOG.info("Starting Moquette Server. MQTT message interceptors={}", getInterceptorIds(handlers));
@@ -369,7 +357,11 @@ public class Server {
private String getServerIp(IConfig config) {
String serverIp = config.getProperty(BrokerConstants.SERVER_IP_PROPERTY_NAME);
if (serverIp == null || serverIp.equals("0.0.0.0")) {
serverIp = Utility.getLocalAddress().getHostAddress();
if(Utility.getLocalAddress() != null) {
serverIp = Utility.getLocalAddress().getHostAddress();
} else {
serverIp = "0.0.0.0";
}
}
return serverIp;
}
@@ -393,9 +385,13 @@ public class Server {
longPort = config.getProperty(BrokerConstants.PORT_PROPERTY_NAME);
shortPort = config.getProperty(BrokerConstants.HTTP_SERVER_PORT);
boolean aes256 = Boolean.parseBoolean(config.getProperty(ENCRYPT_AES256, "false"));
MessageShardingUtil.setNodeId(1);
Tokenor.setKey(config.getProperty(BrokerConstants.TOKEN_SECRET_KEY));
AES.useAes256(aes256);
String expirTimeStr = config.getProperty(TOKEN_EXPIRE_TIME);
if (!StringUtil.isNullOrEmpty(expirTimeStr)) {
try {
@@ -17,6 +17,7 @@
package io.moquette.spi;
import cn.wildfirechat.pojos.InputOutputUserInfo;
import cn.wildfirechat.pojos.OutputUserChatroom;
import cn.wildfirechat.pojos.SystemSettingPojo;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
@@ -119,6 +120,7 @@ public interface IMessagesStore {
List<WFCMessage.GroupInfo> getGroupInfos(List<WFCMessage.UserRequest> requests, String fromUser, boolean isAdmin);
WFCMessage.GroupInfo getGroupInfo(String groupId);
Set<String> getUserGroupIds(String userId);
Set<String> getUserGroupIds(String userId, List<Integer> types);
Set<String> getCommonGroupIds(String userId1, String userId2);
ErrorCode getGroupMembers(String fromUser, String groupId, long maxDt, List<WFCMessage.GroupMember> members);
WFCMessage.GroupMember getGroupMember(String groupId, String memberId);
@@ -128,7 +130,7 @@ public interface IMessagesStore {
ErrorCode canSendMessageInGroup(String member, String groupId);
Set<String> getGroupManagers(String groupId, boolean includeOwner);
ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin);
ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin, ByteBuf ackPayload);
ErrorCode recallCastMessage(long messageUid, String operatorId);
void clearUserMessages(String userId);
@@ -158,6 +160,8 @@ public interface IMessagesStore {
WFCMessage.User getUserInfoByMobile(String mobile);
List<WFCMessage.User> searchUser(String keyword, int searchType, int page);
List<WFCMessage.User> getUserInfoList(int count, int offset);
boolean updateSystemSetting(int id, String value, String desc);
SystemSettingPojo getSystemSetting(int id);
void createChatroom(String chatroomId, WFCMessage.ChatroomInfo chatroomInfo);
@@ -170,6 +174,7 @@ public interface IMessagesStore {
long insertChatroomMessages(String target, int line, long messageId);
Collection<UserClientEntry> getChatroomMembers(String chatroomId);
OutputUserChatroom getUserChatroom(String userId);
WFCMessage.PullMessageResult fetchChatroomMessage(String fromUser, String chatroomId, String exceptClientId, long fromMessageId);
ErrorCode verifyToken(String userId, String token, List<String> serverIPs, List<Integer> ports);
@@ -216,6 +221,7 @@ public interface IMessagesStore {
ErrorCode transferChannel(String operator, String channelId, String newOwner);
ErrorCode destroyChannel(String operator, String channelId, boolean isAdmin);
List<WFCMessage.ChannelInfo> searchChannel(String keyword, boolean buzzy, int page);
List<String> getListenedChannels(String userId);
ErrorCode listenChannel(String operator, String channelId, boolean listen);
WFCMessage.ChannelInfo getChannelInfo(String channelId);
boolean canSendMessageInChannel(String user, String channelId);
@@ -239,6 +245,10 @@ public interface IMessagesStore {
boolean isRobotCallbackWithClientInfo();
boolean isChannelCallbackWithClientInfo();
boolean isRobotAutoAcceptFriendRequest();
long getPushExpiredTimes();
List<Integer> getClientForbiddenSendTypes();
List<Integer> getBlackListExceptionTypes();
List<Integer> getGroupMuteExceptionTypes();
@@ -35,14 +35,11 @@ import io.moquette.spi.ISessionsStore;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.mqtt.*;
import win.liyufan.im.GsonUtil;
import win.liyufan.im.HttpUtils;
import win.liyufan.im.IMTopic;
import win.liyufan.im.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.Utility;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@@ -168,6 +165,9 @@ public class MessagesPublisher {
}
WFCMessage.Message message = null;
String senderName = null;
String senderPortrait = null;
boolean sendNameLoaded = false;
for (String user : receivers) {
if (!user.equals(sender)) {
WFCMessage.User userInfo = m_messagesStore.getUserInfo(user);
@@ -207,10 +207,10 @@ public class MessagesPublisher {
}
Collection<Session> sessions = m_sessionsStore.sessionForUser(user);
String senderName = null;
String targetName = null;
boolean nameLoaded = false;
String targetName = null;
String targetPortrait = null;
boolean targetNameLoaded = false;
Collection<String> targetClients = null;
if (pullType == ProtoConstants.PullType.Pull_ChatRoom) {
@@ -235,7 +235,7 @@ public class MessagesPublisher {
for (Session targetSession : sessions) {
//超过7天不活跃的用户忽略
if(System.currentTimeMillis() - targetSession.getLastActiveTime() > 7 * 24 * 60 * 60 * 1000) {
if(System.currentTimeMillis() - targetSession.getLastActiveTime() > m_messagesStore.getPushExpiredTimes()) {
continue;
}
@@ -386,10 +386,22 @@ public class MessagesPublisher {
boolean isHiddenDetail = m_messagesStore.getUserPushHiddenDetail(user);
if(!nameLoaded) {
senderName = getUserDisplayName(sender, conversationType == ProtoConstants.ConversationType.ConversationType_Group ? target : null);
targetName = getTargetName(target, conversationType);
nameLoaded = true;
if(!sendNameLoaded) {
List<String> list = new ArrayList<>();
senderName = getUserDisplayName(sender, conversationType == ProtoConstants.ConversationType.ConversationType_Group ? target : null, list);
if(!list.isEmpty()) {
senderPortrait = list.get(0);
}
sendNameLoaded = true;
}
if(!targetNameLoaded) {
List<String> list = new ArrayList<>();
targetName = getTargetName(target, conversationType, user, list);
if(!list.isEmpty()) {
targetPortrait = list.get(0);
}
targetNameLoaded = true;
}
String name = senderName;
@@ -399,7 +411,7 @@ public class MessagesPublisher {
name = fd.getAlias();
}
}
this.messageSender.sendPush(sender, conversationType, target, line, messageId, targetSession.getClientID(), pushContent, pushData, messageContentType, serverTime, name, targetName, targetSession.getUnReceivedMsgs(), curMentionType, isHiddenDetail, targetSession.getLanguage());
this.messageSender.sendPush(sender, conversationType, target, line, messageId, targetSession.getClientID(), pushContent, pushData, messageContentType, serverTime, name, senderPortrait, targetName, targetPortrait, targetSession.getUnReceivedMsgs(), curMentionType, isHiddenDetail, targetSession.getLanguage());
}
}
@@ -461,10 +473,13 @@ public class MessagesPublisher {
}
}
String getUserDisplayName(String userId, String groupId) {
String getUserDisplayName(String userId, String groupId, List<String> portraitList) {
WFCMessage.User user = m_messagesStore.getUserInfo(userId);
String userName = null;
if(user != null) {
if(portraitList != null && !StringUtil.isNullOrEmpty(user.getPortrait())) {
portraitList.add(user.getPortrait());
}
userName = user.getDisplayName();
}
if (!StringUtil.isNullOrEmpty(groupId)) {
@@ -476,17 +491,28 @@ public class MessagesPublisher {
return userName;
}
String getTargetName(String targetId, int cnvType) {
String getTargetName(String targetId, int cnvType, String fromUser, List<String> portraitList) {
if (cnvType == ProtoConstants.ConversationType.ConversationType_Private) {
return getUserDisplayName(targetId, null);
return getUserDisplayName(targetId, null, portraitList);
} else if(cnvType == ProtoConstants.ConversationType.ConversationType_Group) {
WFCMessage.GroupInfo group = m_messagesStore.getGroupInfo(targetId);
if(group != null) {
if(!StringUtil.isNullOrEmpty(group.getPortrait())) {
portraitList.add(group.getPortrait());
}
WFCMessage.UserSettingEntry entry = m_messagesStore.getUserSetting(fromUser, UserSettingScope.kUserSettingGroupRemark, targetId);
if(entry != null && !StringUtil.isNullOrEmpty(entry.getValue())) {
return entry.getValue();
}
return group.getName();
}
} else if(cnvType == ProtoConstants.ConversationType.ConversationType_Channel) {
WFCMessage.ChannelInfo channelInfo = m_messagesStore.getChannelInfo(targetId);
if (channelInfo != null) {
if(!StringUtil.isNullOrEmpty(channelInfo.getPortrait())) {
portraitList.add(channelInfo.getPortrait());
}
return channelInfo.getName();
}
}
@@ -37,9 +37,9 @@ class PersistentQueueMessageSender {
this.connectionDescriptorStore = connectionDescriptorStore;
}
void sendPush(String sender, int conversationType, String target, int line, long messageId, String deviceId, String pushContent, String pushData, int messageContentType, long serverTime, String senderName, String targetName, int unReceivedMsg, int mentionType, boolean isHiddenDetail, String language) {
void sendPush(String sender, int conversationType, String target, int line, long messageId, String deviceId, String pushContent, String pushData, int messageContentType, long serverTime, String senderName, String senderPortrait, String targetName, String targetPortrait, int unReceivedMsg, int mentionType, boolean isHiddenDetail, String language) {
LOG.info("Send push to {}, message from {}", deviceId, sender);
PushMessage pushMessage = new PushMessage(sender, conversationType, target, line, messageContentType, serverTime, senderName, targetName, unReceivedMsg, mentionType, isHiddenDetail, language);
PushMessage pushMessage = new PushMessage(sender, conversationType, target, line, messageContentType, serverTime, senderName, senderPortrait, targetName, targetPortrait, unReceivedMsg, mentionType, isHiddenDetail, language);
pushMessage.pushContent = pushContent;
pushMessage.pushData = pushData;
pushMessage.messageId = messageId;
@@ -243,20 +243,15 @@ public class Qos1PublishHandler extends QosPublishHandler {
String imtopic = topic.getTopic();
ByteBuf payload = msg.payload();
byte[] payloadContent = readBytesAndRewind(payload);
if(payloadContent.length == 0) {
ByteBuf ackPayload = Unpooled.buffer();
ackPayload.ensureWritable(1).writeByte(ERROR_CODE_INVALID_DATA.getCode());
sendPubAck(clientID, messageID, ackPayload, ERROR_CODE_INVALID_DATA);
return;
}
MemorySessionStore.Session session = m_sessionStore.getSession(clientID);
payloadContent = AES.AESDecrypt(payloadContent, session.getSecret(), true);
if(payloadContent == null) {
ByteBuf ackPayload = Unpooled.buffer();
ackPayload.ensureWritable(1).writeByte(ERROR_CODE_INVALID_DATA.getCode());
sendPubAck(clientID, messageID, ackPayload, ERROR_CODE_INVALID_DATA);
return;
if(payloadContent.length > 0) {
MemorySessionStore.Session session = m_sessionStore.getSession(clientID);
payloadContent = AES.AESDecrypt(payloadContent, session.getSecret(), true);
if(payloadContent == null) {
ByteBuf ackPayload = Unpooled.buffer();
ackPayload.ensureWritable(1).writeByte(ERROR_CODE_INVALID_DATA.getCode());
sendPubAck(clientID, messageID, ackPayload, ERROR_CODE_INVALID_DATA);
return;
}
}
imHandler(clientID, username, imtopic, payloadContent, (errorCode, ackPayload) -> sendPubAck(clientID, messageID, ackPayload, errorCode), ProtoConstants.RequestSourceType.Request_From_User);
@@ -77,6 +77,7 @@ public interface IMTopic {
String ChannelSearchTopic = "CHS";
String ChannelListenTopic = "CHL";
String ChannelPullTopic = "CHP";
String ListenedChannelListTopic = "CHLL";
String GetTokenTopic = "GETTOKEN";
String DestroyUserTopic = "DESTROYUSER";
@@ -14,5 +14,10 @@ public interface UserSettingScope {
int kUserSettingConversationDraft = 19;
int kUserSettingDisableSyncDraft = 20;
int kUserSettingVoipSilent = 21;
int kUserSettingPttReserved = 22;
int kUserSettingCustomState = 23;
int kUserSettingDisableSecretChat = 24;
int kUserSettingPttSilent = 25;
int kUserSettingGroupRemark = 26;
int kUserSettingPrivacySearchable = 27;
}
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>1.1.3</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -5,6 +5,7 @@ public interface APIPath {
String Chatroom_Destroy = "/admin/chatroom/del";
String Chatroom_Info = "/admin/chatroom/info";
String Chatroom_GetMembers = "/admin/chatroom/members";
String Chatroom_GetUserChatroom = "/admin/chatroom/user_chatroom";
String Chatroom_SetBlacklist = "/admin/chatroom/set_black_status";
String Chatroom_GetBlacklist = "/admin/chatroom/get_black_status";
String Chatroom_SetManager = "/admin/chatroom/set_manager";
@@ -26,6 +27,7 @@ public interface APIPath {
String User_Get_Token = "/admin/user/get_token";
String User_Update_Block_Status = "/admin/user/update_block_status";
String User_Get_Info = "/admin/user/get_info";
String User_Get_All = "/admin/user/all";
String User_Get_Robot_Info = "/admin/user/get_robot_info";
String User_Get_Blocked_List = "/admin/user/get_blocked_list";
String User_Check_Block_Status = "/admin/user/check_block_status";
@@ -68,6 +70,7 @@ public interface APIPath {
String Group_Get_Info = "/admin/group/get_info";
String Group_Modify_Info = "/admin/group/modify";
String Group_Member_List = "/admin/group/member/list";
String Group_Member_Get = "/admin/group/member/get";
String Group_Member_Add = "/admin/group/member/add";
String Group_Member_Kickoff = "/admin/group/member/del";
String Group_Member_Quit = "/admin/group/member/quit";
@@ -75,6 +78,7 @@ public interface APIPath {
String Group_Mute_Member = "/admin/group/manager/mute";
String Group_Allow_Member = "/admin/group/manager/allow";
String Get_User_Groups = "/admin/group/of_user";
String Get_User_Groups_By_Type = "/admin/group/of_user_by_type";
String Group_Set_Member_Alias = "/admin/group/member/set_alias";
String Group_Set_Member_Extra = "/admin/group/member/set_extra";
String Get_Common_Groups = "/admin/group/common_group";
@@ -122,6 +126,7 @@ public interface APIPath {
String Robot_Group_Dismiss = "/robot/group/del";
String Robot_Group_Get_Info = "/robot/group/get_info";
String Robot_Group_Member_List = "/robot/group/member/list";
String Robot_Group_Member_Get = "/robot/group/member/get";
String Robot_Group_Member_Kickoff = "/robot/group/member/del";
String Robot_Group_Modify_Info = "/robot/group/modify";
String Robot_Group_Set_Member_Alias = "/robot/group/member/set_alias";
@@ -48,9 +48,7 @@ public enum ErrorCode {
ERROR_CODE_NOT_YOUR_LOCKED(26, "unload failure, not your lock"),
ERROR_CODE_ROBOT_NO_TOKEN(27, "robot no token"),
ERROR_CODE_WS_NOT_CONFIGURED_CORRECTLY(28, "ws not configured correctly"),
ERROR_CODE_TIME_INCONSISTENT(30, "time inconsistent"),
ERROR_CODE_CONFERENCE_ROOM_NOT_EXIST(60, "conference room not exist"),
ERROR_CODE_CONFERENCE_SERVICE_NOT_AVAILABLE(61, "conference service not available"),
@@ -68,6 +66,8 @@ public enum ErrorCode {
ERROR_CODE_FUNCTION_DISABLED(220, "function disabled"),
ERROR_CODE_OTHER_CLIENT_ALREADY_IN_CHATROOM(225, "other client already in chatroom"),
ERROR_CODE_CHANNEL_NO_EXIST(236, "channel no exist"),
ERROR_CODE_CHANNEL_NO_SECRET(237, "channel no secret"),
ERROR_CODE_USER_NOT_PREPARED(238, "user not prepared"),
@@ -10,4 +10,9 @@ public class ConferenceCreateEvent {
public int bitrate;
public boolean advance;
public boolean recording;
public long timestamp;
public ConferenceCreateEvent() {
timestamp = System.currentTimeMillis();
}
}
@@ -3,4 +3,9 @@ package cn.wildfirechat.pojos;
public class ConferenceDestroyEvent {
public String userId;
public String roomId;
public long timestamp;
public ConferenceDestroyEvent() {
timestamp = System.currentTimeMillis();
}
}
@@ -4,4 +4,9 @@ public class ConferenceJoinEvent {
public String userId;
public String roomId;
public boolean screenSharing;
public long timestamp;
public ConferenceJoinEvent() {
timestamp = System.currentTimeMillis();
}
}
@@ -6,4 +6,9 @@ public class ConferenceLeaveEvent {
public boolean rejoin;
public boolean kicked;
public boolean screenSharing;
public long timestamp;
public ConferenceLeaveEvent() {
timestamp = System.currentTimeMillis();
}
}
@@ -5,4 +5,9 @@ public class ConferencePublishEvent {
public boolean video;
public String roomId;
public boolean screenSharing;
public long timestamp;
public ConferencePublishEvent() {
timestamp = System.currentTimeMillis();
}
}
@@ -4,4 +4,9 @@ public class ConferenceUnpublishEvent {
public String userId;
public String roomId;
public boolean screenSharing;
public long timestamp;
public ConferenceUnpublishEvent() {
timestamp = System.currentTimeMillis();
}
}
@@ -0,0 +1,30 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
public class InputGetGroupMember {
private String groupId;
private String memberId;
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
import java.util.List;
public class InputGetUserGroupByType {
private String userId;
private List<Integer> groupMemberTypes;
public InputGetUserGroupByType() {
}
public InputGetUserGroupByType(String userId, List<Integer> groupMemberTypes) {
this.userId = userId;
this.groupMemberTypes = groupMemberTypes;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public List<Integer> getGroupMemberTypes() {
return groupMemberTypes;
}
public void setGroupMemberTypes(List<Integer> groupMemberTypes) {
this.groupMemberTypes = groupMemberTypes;
}
}
@@ -0,0 +1,6 @@
package cn.wildfirechat.pojos;
public class InputGetUserList {
public int count;
public int offset;
}
@@ -0,0 +1,7 @@
package cn.wildfirechat.pojos;
import java.util.List;
public class OutputGetUserList {
public List<InputOutputUserInfo> userInfoList;
}
@@ -0,0 +1,16 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
public class OutputUserChatroom {
public String userId;
public String chatroomId;
public String clientId;
public int/*ProtoConstants.Platform*/ platform;
}
@@ -156,6 +156,8 @@ public class ProtoConstants {
int Modify_Group_History_Message = 7;
//仅专业版的server api支持
int Modify_Group_Max_Member_Count = 8;
//仅专业版的server api支持
int Modify_Group_Super_Group = 9;
}
//ModifyGroupInfoRequest -> type
@@ -216,6 +218,15 @@ public class ProtoConstants {
int SearchUserType_Name_Mobile = 1;
int SearchUserType_Name = 2;
int SearchUserType_Mobile = 3;
int SearchUserType_UserId = 4;
int SearchUserType_Name_Mobile_UserId = 5;
}
public interface DisableSearchMask {
int DisableSearchDisplayNameMask = 1;
int DisableSearchNameMask = 2;
int DisableSearchMobileMask = 4;
int DisableSearchUserIdMask = 8;
}
public interface UserStatus {
@@ -5,6 +5,7 @@ import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.BadPaddingException;
@@ -18,38 +19,46 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES {
private static byte[] aes_key= {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F};
public static void init(byte[] secret) {
if (secret != null && secret.length == 16) {
aes_key = new byte[16];
for (int i = 0; i < 16; i++) {
aes_key[i] = secret[i];
}
} else {
System.out.println("Error int key error, secret incorrect");
}
}
public static int keyLen = 16;
private final static int ivLen = 16;
private static byte[] aes_key= {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x3A,0x1F,0x28,0x39,0x4F,0x52,0x68,0x79,0x71,0x73,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F};
public static byte[] AESEncrypt(String sSrc, String userKey) {
return AESEncrypt(sSrc.getBytes(), userKey);
}
public static void useAes256(boolean aes256) {
if(aes256)
keyLen = 32;
else
keyLen = 16;
}
public static byte[] AESEncrypt(byte[] tobeencrypdata, byte[] aesKey) {
if (aesKey == null) {
System.out.print("Key为空null");
return null;
}
// 判断Key是否为16位
if (aesKey.length != 16) {
if (aesKey.length < keyLen) {
System.out.print("Key长度不是16位");
return null;
}
if(aesKey.length > keyLen) {
aesKey = Arrays.copyOfRange(aesKey, 0, keyLen);
}
byte[] ivKeys;
if(aesKey.length == ivLen) {
ivKeys = aesKey;
} else {
ivKeys = Arrays.copyOfRange(aesKey, 0, ivLen);
}
try {
SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式"
IvParameterSpec iv = new IvParameterSpec(aesKey);//使用CBC模式,需要一个向量iv,可增加加密算法的强度
IvParameterSpec iv = new IvParameterSpec(ivKeys);//使用CBC模式,需要一个向量iv,可增加加密算法的强度
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
//2018.1.1 0:0:0 以来的小时数
@@ -101,8 +110,8 @@ public class AES {
}
private static byte[] convertUserKey(String userKey) {
byte[] key = new byte[16];
for (int i = 0; i < 16; i++) {
byte[] key = new byte[keyLen];
for (int i = 0; i < keyLen; i++) {
key[i] = (byte) (userKey.charAt(i) & 0xFF);
}
return key;
@@ -128,14 +137,25 @@ public class AES {
aesKey = aes_key;
}
// 判断Key是否为16位
if (aesKey.length != 16) {
if (aesKey.length < keyLen) {
System.out.print("Key长度不是16位");
return null;
}
if(aesKey.length > keyLen) {
aesKey = Arrays.copyOfRange(aesKey, 0, keyLen);
}
byte[] ivKeys;
if(aesKey.length == ivLen) {
ivKeys = aesKey;
} else {
ivKeys = Arrays.copyOfRange(aesKey, 0, ivLen);
}
SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(aesKey);
IvParameterSpec iv = new IvParameterSpec(ivKeys);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
try {
byte[] original = cipher.doFinal(sSrc);
@@ -156,7 +176,7 @@ public class AES {
//2018.1.1 0:0:0 以来的小时数
int curhour = (int) ((System.currentTimeMillis()/1000 - 1514736000)/3600);
if (curhour - hours > 24 && checkTime) {
if (Math.abs(curhour - hours) > 24 && checkTime) {
if(invalidTime != null) {
invalidTime[0] = true;
}
+1 -1
View File
@@ -6,7 +6,7 @@
<!--<relativePath>../pom.xml</relativePath>-->
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>1.1.3</version>
<version>1.2.0</version>
</parent>
<artifactId>distribution</artifactId>
@@ -63,6 +63,9 @@ token.key testim
##是否拒绝空签名的android客户端, 默认为true。当有旧的客户端需要兼容时改成false,当所有都是新客户端时,改成true。
#connect.reject_empty_signature true
##是否使用AES256加密。默认客户端和服务器都是AES128加密,如果需要开启AES256,需要客户端和IM服务同时开通。
#encrypt.use_aes256 true
##首次登录,是否接收之前的历史消息。
##0 不接收历史消息,只接收${message.compensate_time_limit}毫秒以内的消息,由于服务器没有保存已经收取记录,所以如果有超过${message.compensate_time_limit}毫秒之前未收取的消息也不会收取下拉;
##1接收,会接收 message.max_queue 配置的条数的历史消息
@@ -118,6 +121,9 @@ message.group_mute_exception_types 401,402,403,404,405,407,408,410,411
## 用户被全局禁言时允许发送的消息类型
message.global_mute_exception_types 401,402,403,404,405,407,408,410,411
## 离线用户推送过期天数,0是永不过期,建议配置为7天。
message.push_expired_days 7
## 消息转发功能开启时,开关是否不转发server api接口消息。
## 当为true时,不转发server api发送的消息;当为false时,转发server api发送的消息。
message.no_forward_admin_message false
@@ -137,6 +143,9 @@ friend.disable_search false
##禁止按照昵称搜索用户。
friend.disable_nick_name_search false
##禁止按照用户id搜索用户,默认为true。
friend.disable_user_id_search true
##禁止发送好友邀请,通过server api添加好友不受此限制(force参数需要为true)
friend.disable_friend_request false
@@ -149,6 +158,9 @@ friend.reject_request_duration 2592000000
##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。
friend.request_expiration_duration 604800000
##请求添加机器人为好友时,机器人是否自动接受,默认为true
friend.robot_auto_accept true
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
chatroom.participant_idle_time 900000
@@ -158,6 +170,18 @@ chatroom.rejoin_when_active true
## 当一个聊天室不存在时,如果有用户加入就自动创建
chatroom.create_when_not_exist true
## 一个用户同一时刻只能加入一个聊天室。
## 当一个客户端加入一个聊天室时,如果这个客户端已经加入另外一个聊天室了,会自动退出之前的聊天室。
## 当一个客户端加入一个聊天室时,如果这个用户的其他端已经加入一个聊天室了,kickoff_other_platform为true时会自动退出之前的聊天室,为false时会返回225的错误码。
## 当自动退出聊天室时,客户端不会收到任何通知,只是不会再收到消息。
chatroom.kickoff_other_platform true
## 是否允许群主不受限制地撤回自己发送的消息。false可以${message.recall_time_limit}撤回自己的消息;true可以撤回任意时间自己的消息。默认为true。
group.allow_owner_recall_self_msg true
## 是否允许群管理员不受限制地撤回自己发送的消息。false可以${message.recall_time_limit}撤回自己的消息;true可以撤回任意时间自己的消息。默认为false。
group.allow_manager_recall_self_msg false
## 是否允许客户端发送操作群的自定义群通知消息
group.allow_client_custom_operation_notification true
@@ -182,6 +206,9 @@ group.visible_quit_or_kickoff_notification 0
# 因此需要分段多次同步,此开关定义了每次同步的数据的条数。此需要客户端支持,客户端SDK在2021.5.25日后支持此功能。如果确认所有客户端都在这个日志之后才可以打开此设置。
#sync.data_part_size 1000
## 是否关闭api/version接口。api/version方法可以用来检查IM服务版本,上线确认无问题后,可以关掉这个接口。
#http.close_api_version false
#*********************************************************************
# 限频配置
#*********************************************************************
@@ -359,10 +386,12 @@ push.ios.server.address http://localhost:8085/ios/push
#*********************************************************************
# Sensitive configuration
#*********************************************************************
## 内置文本敏感词过滤处理方法,0 发送失败;1 发送成功但消息被服务器直接丢弃;2 命中的敏感词被替换成***;3 记录并继续发送
## 内置文本敏感词过滤处理方法,当命中敏感词后,消息会被记录到t_sensitive_messages表中,然后根据type类型做不同的处理,处理方式如下:
## 0 发送失败;1 发送成功但消息被服务器直接丢弃;2 命中的敏感词被替换成***然后正常发送;3 正常发送。
## 如果开启 message.sensitive.forward.url 配置,命中敏感词的消息还会被回调到这个地址
sensitive.filter.type 0
## 如果内置敏感词库无法满足您的需求,可以自己开发部署敏感词审核服务。配置如下地址和消息类型,IM服务会把指定消息类型的消息回调到指定地址
## 如果内置敏感词库无法满足您的需求,可以开发部署独立敏感词审核服务。配置如下地址和消息类型,IM服务会把指定消息类型的消息回调到指定地址,内置的敏感词审核和敏感词转发功能就不再起作用了。
## 审核服务返回状态码200表示继续发送,如果需要替换内容,返回状态码200并且内容为替换后的内容。返回403表示不允许发送。其它错误继续发送。
## 独立审核服务地址,IM服务会post SendMessageData。如果需要修改消息内容,返回 MessagePayload。请参考应用服务中 "/message/censor" Mapping.
#sensitive.remote_server_url http://192.168.3.202:8888/message/censor
+1 -1
View File
@@ -9,7 +9,7 @@ fi
kill -15 $pid
for i in {1..15}
for i in {1..30}
do
pid=`ps -ef | grep wildfirechat.server.Server | grep -v grep | awk '{print $2}'`
if [ -z $pid ]; then
+2
View File
@@ -5,6 +5,8 @@ ADD distribution-*-bundle-tar.tar.gz /opt/im-server/
RUN sed -i 's/#JAVA_OPTS="$JAVA_OPTS -Xmx128M"/JAVA_OPTS="$JAVA_OPTS -Xmx$JVM_XMX"/g' /opt/im-server/bin/wildfirechat.sh
RUN sed -i 's/#JAVA_OPTS="$JAVA_OPTS -Xms128M"/JAVA_OPTS="$JAVA_OPTS -Xms$JVM_XMS"/g' /opt/im-server/bin/wildfirechat.sh
RUN chmod a+x /opt/im-server/bin/wildfirechat.sh
WORKDIR /opt/im-server
VOLUME /opt/im-server/config
+2 -2
View File
@@ -1,7 +1,7 @@
# 野火IM服务docker使用说明
## 编译镜像
首先需要先编译应用服务,在项目根目录下使用下面命令编译
首先需要先编译IM服务,在项目根目录下使用下面命令编译
```
mvn clean package
```
@@ -14,7 +14,7 @@ sudo docker build -t im-server .
## 运行
配置:
运行需要手动指定配置目录,手动指定配置目录的方法如下,其中$PATH_TO_CONFIG为im配置目录,需要为绝对路径,模版为```distribution/src/main/resources```目录。另外需要创建h2数据库目录(如果用mysql就不需要了)、日志目录、内置存储服务目录(如果使用其它对象存储服务就不需要了)。
运行需要手动指定配置目录,手动指定配置目录的方法如下,其中$PATH_TO_CONFIG为im配置目录,需要为绝对路径,模版为```distribution/src/main/resources```目录。另外需要创建h2数据库目录(如果用mysql就不需要了)、日志目录、内置存储服务目录(如果使用其它对象存储服务就不需要了)。h2数据库目录/日志目录/内置存储服务目录需要有写权限,因为IM服务会写入文件。
```
sudo docker run -it --name im-server -v $PATH_TO_CONFIG:/opt/im-server/config -v $PATH_TO_LOGS:/opt/im-server/logs -v $PATH_TO_H2DB:/opt/im-server/h2db -v $PATH_TO_MEDIA:/opt/im-server/media -e JVM_XMX=256M -e JVM_XMS=256M -p 80:80 -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 18080:18080 im-server
```
+1 -1
View File
@@ -12,7 +12,7 @@
<artifactId>wildfirechat-parent</artifactId>
<packaging>pom</packaging>
<version>1.1.3</version>
<version>1.2.0</version>
<name>Wildfire Chat</name>
<description>Wildfire Chat Server</description>
<inceptionYear>2019</inceptionYear>
+49
View File
@@ -12,6 +12,55 @@
# 更新记录
--------------
Release note 1.2.0:
1. 添加配置开关,可以关掉api/version检查接口。
2. Server SDK会议事件中添加时间戳。
3. 禁止私聊时,如果一方在允许私聊列表中,允许私聊。
4. 解决某些特殊情况下获取网卡信息失败导致启动失败的问题。
5. 支持按照用户ID来搜索用户。
6. 添加获取某个用户是否在聊天室的接口。
7. 优化多端加入聊天室的处理。
--------------
Release note 1.1.9:
1. 解决服务器时间误差太大引起的问题。
2. 添加推送过期配置。
3. 支持发送好友请求后5分钟之内再次发送。
4. Server API支持根据群成员类型获取用户群列表。
5. 添加配置,是否允许群主和群管理员无限制撤回自己的消息。
--------------
Release note 1.1.8:
1. 解决可以把群主设置为管理员的问题。
2. 发送好友请求之后5分钟内可以再次发送。
3. 解决撤回消息中原消息二进制内容格式错误问题。
--------------
Release note 1.1.7:
1. 优化用户搜索功能。
2. 推送消息中使用群备注。
3. 推送消息中添加发送者和目标头像。
4. 优化撤回消息流程。
--------------
Release note 1.1.6:
1. 支持用户设置查找自己的方法。
2. 解决获取用户信息返回type无效的问题。
3. 添加用户获取频道的功能。
--------------
Release note 1.1.5:
1. 添加获取所有用户的Server API。
2. 解决添加好友时没有处理黑名单的问题。
--------------
Release note 1.1.4:
1. 添加PC客户端多端登录互踢时没有更新pc在线状态问题。
2. 添加支持使用AES256加密。
3. Server API添加获取单个群成员的接口。
4. 添加配置,添加机器人为好友时是否自动接受。
--------------
Release note 1.1.3:
1. 添加服务器和客户端时间检查功能。
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>1.1.3</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+11 -5
View File
@@ -27,7 +27,7 @@
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
<version>1.15</version>
</dependency>
<dependency>
@@ -36,20 +36,26 @@
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>cn.wildfirechat</groupId>
<artifactId>sdk</artifactId>
<version>0.20</version>
<version>1.2.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/lib/sdk-0.20.jar</systemPath>
<systemPath>${project.basedir}/src/lib/sdk-1.1.9.jar</systemPath>
</dependency>
<dependency>
<groupId>cn.wildfirechat</groupId>
<artifactId>common</artifactId>
<version>0.20</version>
<version>1.2.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/lib/common-0.20.jar</systemPath>
<systemPath>${project.basedir}/src/lib/common-1.1.9.jar</systemPath>
</dependency>
</dependencies>
@@ -37,6 +37,12 @@ public class ChatroomAdmin {
return AdminHttpUtils.httpJsonPost(path, input, OutputStringList.class);
}
public static IMResult<OutputUserChatroom> getUserChatroom(String userId) throws Exception {
String path = APIPath.Chatroom_GetUserChatroom;
InputUserId input = new InputUserId(userId);
return AdminHttpUtils.httpJsonPost(path, input, OutputUserChatroom.class);
}
//仅专业版支持
//status:0,正常;1,禁言;2,禁止加入
public static IMResult<Void> setChatroomBlacklist(String chatroomId, String userId, int status) throws Exception {
@@ -2,6 +2,7 @@ package cn.wildfirechat.sdk;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.*;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.sdk.model.IMResult;
import cn.wildfirechat.sdk.utilities.AdminHttpUtils;
@@ -71,6 +72,14 @@ public class GroupAdmin {
return AdminHttpUtils.httpJsonPost(path, input, OutputGroupMemberList.class);
}
public static IMResult<PojoGroupMember> getGroupMember(String groupId, String memberId) throws Exception {
String path = APIPath.Group_Member_Get;
InputGetGroupMember input = new InputGetGroupMember();
input.setGroupId(groupId);
input.setMemberId(memberId);
return AdminHttpUtils.httpJsonPost(path, input, PojoGroupMember.class);
}
public static IMResult<Void> addGroupMembers(String operator, String groupId, List<PojoGroupMember> groupMembers, List<Integer> to_lines, MessagePayload notify_message) throws Exception {
String path = APIPath.Group_Member_Add;
InputAddGroupMember addGroupMember = new InputAddGroupMember();
@@ -170,6 +179,12 @@ public class GroupAdmin {
return AdminHttpUtils.httpJsonPost(path, inputUserId, OutputGroupIds.class);
}
public static IMResult<OutputGroupIds> getUserGroupsByType(String user, List</*ProtoConstants.GroupMemberType*/Integer> groupMemberType) throws Exception {
String path = APIPath.Get_User_Groups_By_Type;
InputGetUserGroupByType input = new InputGetUserGroupByType(user, groupMemberType);
return AdminHttpUtils.httpJsonPost(path, input, OutputGroupIds.class);
}
public static IMResult<OutputGroupIds> getCommonGroups(String user1, String user2) throws Exception {
String path = APIPath.Get_Common_Groups;
StringPairPojo intput = new StringPairPojo(user1, user2);
@@ -300,6 +300,14 @@ public class Main {
System.exit(-1);
}
IMResult<OutputGetUserList> getUserListIMResult = UserAdmin.getAllUsers(100, 0);
if (getUserListIMResult != null && getUserListIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("getUserListIMResult success");
} else {
System.out.println("getUserListIMResult failure");
System.exit(-1);
}
if (commercialServer) {
IMResult<GetOnlineUserCountResult> getOnlineUserCountResultIMResult = UserAdmin.getOnlineUserCount();
if (getOnlineUserCountResultIMResult != null && getOnlineUserCountResultIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
@@ -374,7 +382,6 @@ public class Main {
System.out.println("success");
} else {
System.out.println("send friend request success");
System.exit(-1);
}
IMResult<Void> updateFriendStatusResult = RelationAdmin.setUserFriend("ff1", "ff2", true, "{\"from\":1}");
@@ -572,6 +579,14 @@ public class Main {
System.exit(-1);
}
IMResult<PojoGroupMember> groupMemberIMResult = GroupAdmin.getGroupMember(groupInfo.getTarget_id(), "user1");
if (groupMemberIMResult != null && groupMemberIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get group member success");
} else {
System.out.println("get group member failure");
System.exit(-1);
}
voidIMResult = GroupAdmin.kickoffGroupMembers("user1", groupInfo.getTarget_id(), Arrays.asList("user3"), null, null);
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("kickoff group member success");
@@ -635,6 +650,14 @@ public class Main {
System.exit(-1);
}
groupIdsIMResult = GroupAdmin.getUserGroupsByType("user2", Arrays.asList(ProtoConstants.GroupMemberType.GroupMemberType_Manager, ProtoConstants.GroupMemberType.GroupMemberType_Owner));
if (groupIdsIMResult != null && groupIdsIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get user groups by type success");
} else {
System.out.println("get user groups by type failure");
System.exit(-1);
}
groupIdsIMResult = GroupAdmin.getCommonGroups("user1", "user2");
if (groupIdsIMResult != null && groupIdsIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get user common groups success");
@@ -725,8 +748,8 @@ public class Main {
System.exit(-1);
}
IMResult<Void> voidIMResult = MessageAdmin.recallMessage("user1", resultSendMessage.getResult().getMessageUid());
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
IMResult<String> stringIMResult = MessageAdmin.recallMessage("user1", resultSendMessage.getResult().getMessageUid());
if (stringIMResult != null && stringIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("recall message success");
} else {
System.out.println("recall message failure");
@@ -734,7 +757,7 @@ public class Main {
}
if (commercialServer) {
voidIMResult = MessageAdmin.deleteMessage(resultSendMessage.getResult().getMessageUid());
IMResult<Void> voidIMResult = MessageAdmin.deleteMessage(resultSendMessage.getResult().getMessageUid());
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("delete message success");
} else {
@@ -810,7 +833,7 @@ public class Main {
System.exit(-1);
}
voidIMResult = MessageAdmin.recallMultiCastMessage("user1", resultMulticastMessage.result.getMessageUid(), multicastReceivers);
IMResult<Void> voidIMResult = MessageAdmin.recallMultiCastMessage("user1", resultMulticastMessage.result.getMessageUid(), multicastReceivers);
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("Success");
} else {
@@ -951,6 +974,14 @@ public class Main {
System.exit(-1);
}
IMResult<OutputUserChatroom> userChatroomIMResult = ChatroomAdmin.getUserChatroom("hygqmws2k");
if(userChatroomIMResult != null && (userChatroomIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS || userChatroomIMResult.getErrorCode() == ErrorCode.ERROR_CODE_NOT_EXIST)) {
System.out.println("get user chatroom success");
} else {
System.out.println("get user chatroom failure");
System.exit(-1);
}
//下面仅专业版支持
if(commercialServer) {
//设置用户聊天室黑名单。0正常;1禁言;2禁止加入。
@@ -1215,7 +1246,7 @@ public class Main {
if (resultGetMembers != null && resultGetMembers.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get group member success");
} else {
System.out.println("create group failure");
System.out.println("get group member failure");
System.exit(-1);
}
@@ -1231,6 +1262,14 @@ public class Main {
System.exit(-1);
}
IMResult<PojoGroupMember> groupMemberIMResult = robotService.getGroupMember(groupInfo.getTarget_id(), "user0");
if (groupMemberIMResult != null && groupMemberIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get group member success");
} else {
System.out.println("get group member failure");
System.exit(-1);
}
voidIMResult = robotService.kickoffGroupMembers(groupInfo.getTarget_id(), Arrays.asList("user3"), null, null);
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("kickoff group member success");
@@ -25,12 +25,12 @@ public class MessageAdmin {
return AdminHttpUtils.httpJsonPost(path, messageData, SendMessageResult.class);
}
public static IMResult<Void> recallMessage(String operator, long messageUid) throws Exception {
public static IMResult<String> recallMessage(String operator, long messageUid) throws Exception {
String path = APIPath.Msg_Recall;
RecallMessageData messageData = new RecallMessageData();
messageData.setOperator(operator);
messageData.setMessageUid(messageUid);
return AdminHttpUtils.httpJsonPost(path, messageData, Void.class);
return AdminHttpUtils.httpJsonPost(path, messageData, String.class);
}
//仅专业版支持
@@ -134,6 +134,14 @@ public class RobotService {
return robotHttpUtils.httpJsonPost(path, input, OutputGroupMemberList.class);
}
public IMResult<PojoGroupMember> getGroupMember(String groupId, String memberId) throws Exception {
String path = APIPath.Robot_Group_Member_Get;
InputGetGroupMember input = new InputGetGroupMember();
input.setGroupId(groupId);
input.setMemberId(memberId);
return robotHttpUtils.httpJsonPost(path, input, PojoGroupMember.class);
}
public IMResult<Void> addGroupMembers(String groupId, List<PojoGroupMember> groupMembers, List<Integer> to_lines, MessagePayload notify_message) throws Exception {
String path = APIPath.Robot_Group_Member_Add;
InputAddGroupMember addGroupMember = new InputAddGroupMember();
@@ -24,6 +24,14 @@ public class UserAdmin {
return AdminHttpUtils.httpJsonPost(path, getUserInfo, InputOutputUserInfo.class);
}
public static IMResult<OutputGetUserList> getAllUsers(int count, int offset) throws Exception {
String path = APIPath.User_Get_All;
InputGetUserList input = new InputGetUserList();
input.count = count;
input.offset = offset;
return AdminHttpUtils.httpJsonPost(path, input, OutputGetUserList.class);
}
public static IMResult<OutputCreateUser> createUser(InputOutputUserInfo user) throws Exception {
String path = APIPath.Create_User;
return AdminHttpUtils.httpJsonPost(path, user, OutputCreateUser.class);
@@ -128,7 +128,7 @@ public class AdminHttpUtils extends JsonUtils {
if (object != null) {
jsonStr = gson.toJson(object);
}
LOG.info("http request:{} content: {}", path, jsonStr);
LOG.info("http request:{} content: {}", url, jsonStr);
StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));
entity.setContentEncoding("UTF-8");
@@ -78,7 +78,7 @@ public class ChannelHttpUtils extends JsonUtils {
if (object != null) {
jsonStr = gson.toJson(object);
}
LOG.info("http request:{} content: {}", path, jsonStr);
LOG.info("http request:{} content: {}", url, jsonStr);
StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));
entity.setContentEncoding("UTF-8");
@@ -79,7 +79,7 @@ public class RobotHttpUtils extends JsonUtils {
if (object != null) {
jsonStr = gson.toJson(object);
}
LOG.info("http request:{} content: {}", path, jsonStr);
LOG.info("http request:{} content: {}", url, jsonStr);
if(!StringUtil.isNullOrEmpty(jsonStr)) {
StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));