This commit is contained in:
hailong 2021-05-26 19:15:25 +08:00
parent b26bd4a707
commit dc698ec6a8
8 changed files with 557 additions and 0 deletions

26
src/api/Makefile Normal file
View File

@ -0,0 +1,26 @@
.PHONY: all build run gotool install clean help
BINARY_NAME=open_im_api
BIN_DIR=../../bin/
LAN_FILE=.go
GO_FILE:=${BINARY_NAME}${LAN_FILE}
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${BINARY_NAME} ${GO_FILE}
run:
@go run ./
gotool:
go fmt ./
go vet ./
install:
make build
mv ${BINARY_NAME} ${BIN_DIR}
clean:
@if [ -f ${BINARY_NAME} ] ; then rm ${BINARY_NAME} ; fi

View File

@ -0,0 +1,90 @@
package apiAuth
import (
"Open_IM/src/common/config"
"Open_IM/src/common/log"
pbAuth "Open_IM/src/proto/auth"
"context"
"github.com/gin-gonic/gin"
"github.com/skiffer-git/grpc-etcdv3/getcdv3"
"net/http"
"strings"
)
type paramsUserRegister struct {
Secret string `json:"secret" binding:"required,max=32"`
Platform int32 `json:"platform" binding:"required,min=1,max=7"`
UID string `json:"uid" binding:"required,min=1,max=64"`
Name string `json:"name" binding:"required,min=1,max=64"`
Icon string `json:"icon" binding:"omitempty,max=1024"`
Gender int32 `json:"gender" binding:"omitempty,oneof=0 1 2"`
Mobile string `json:"mobile" binding:"omitempty,max=32"`
Birth string `json:"birth" binding:"omitempty,max=16"`
Email string `json:"email" binding:"omitempty,max=64"`
Ex string `json:"ex" binding:"omitempty,max=1024"`
}
func newUserRegisterReq(params *paramsUserRegister) *pbAuth.UserRegisterReq {
pbData := pbAuth.UserRegisterReq{
UID: params.UID,
Name: params.Name,
Icon: params.Icon,
Gender: params.Gender,
Mobile: params.Mobile,
Birth: params.Birth,
Email: params.Email,
Ex: params.Ex,
}
return &pbData
}
func UserRegister(c *gin.Context) {
log.Info("", "", "api user_register init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.RpcGetTokenName)
client := pbAuth.NewAuthClient(etcdConn)
params := paramsUserRegister{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
pbData := newUserRegisterReq(&params)
log.Info("", "", "api user_register is server, [data: %s]", pbData.String())
reply, err := client.UserRegister(context.Background(), pbData)
if err != nil || !reply.Success {
log.Error("", "", "api user_register call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api user_register call rpc success, [data: %s] [reply: %s]", pbData.String(), reply.String())
pbDataToken := &pbAuth.UserTokenReq{
Platform: params.Platform,
UID: params.UID,
}
replyToken, err := client.UserToken(context.Background(), pbDataToken)
if err != nil {
log.Error("", "", "api user_register call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api user_register call success, [data: %s] [reply: %s]", pbData.String(), reply.String())
if replyToken.ErrCode == 0 {
c.JSON(http.StatusOK, gin.H{
"errCode": replyToken.ErrCode,
"errMsg": replyToken.ErrMsg,
"data": gin.H{
"uid": pbData.UID,
"token": replyToken.Token,
"expiredTime": replyToken.ExpiredTime,
},
})
} else {
c.JSON(http.StatusOK, gin.H{
"errCode": replyToken.ErrCode,
"errMsg": replyToken.ErrMsg,
})
}
}

View File

@ -0,0 +1,66 @@
package apiAuth
import (
"Open_IM/src/common/config"
"Open_IM/src/common/log"
pbAuth "Open_IM/src/proto/auth"
"context"
"github.com/gin-gonic/gin"
"github.com/skiffer-git/grpc-etcdv3/getcdv3"
"net/http"
"strings"
)
type paramsUserToken struct {
Secret string `json:"secret" binding:"required,max=32"`
Platform int32 `json:"platform" binding:"required,min=1,max=7"`
UID string `json:"uid" binding:"required,min=1,max=64"`
}
func newUserTokenReq(params *paramsUserToken) *pbAuth.UserTokenReq {
pbData := pbAuth.UserTokenReq{
Platform: params.Platform,
UID: params.UID,
}
return &pbData
}
func UserToken(c *gin.Context) {
log.Info("", "", "api user_token init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.RpcGetTokenName)
client := pbAuth.NewAuthClient(etcdConn)
params := paramsUserToken{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
pbData := newUserTokenReq(&params)
log.Info("", "", "api user_token is server, [data: %s]", pbData.String())
reply, err := client.UserToken(context.Background(), pbData)
if err != nil {
log.Error("", "", "api user_token call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api user_token call rpc success, [data: %s] [reply: %s]", pbData.String(), reply.String())
if reply.ErrCode == 0 {
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"data": gin.H{
"uid": pbData.UID,
"token": reply.Token,
"expiredTime": reply.ExpiredTime,
},
})
} else {
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
})
}
}

View File

@ -0,0 +1,59 @@
package apiChat
import (
"Open_IM/src/common/config"
"Open_IM/src/common/log"
pbMsg "Open_IM/src/proto/chat"
"Open_IM/src/utils"
"context"
"github.com/gin-gonic/gin"
"github.com/skiffer-git/grpc-etcdv3/getcdv3"
"net/http"
"strings"
)
type paramsUserNewestSeq struct {
ReqIdentifier int `json:"reqIdentifier" binding:"required"`
SendID string `json:"sendID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
MsgIncr int `json:"msgIncr" binding:"required"`
}
func UserNewestSeq(c *gin.Context) {
params := paramsUserNewestSeq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
token := c.Request.Header.Get("token")
if !utils.VerifyToken(token, params.SendID) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
}
pbData := pbMsg.GetNewSeqReq{}
pbData.UserID = params.SendID
pbData.OperationID = params.OperationID
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
if grpcConn == nil {
log.ErrorByKv("get grpcConn err", pbData.OperationID, "args", params)
}
msgClient := pbMsg.NewChatClient(grpcConn)
reply, err := msgClient.GetNewSeq(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("rpc call failed to getNewSeq", pbData.OperationID, "err", err, "pbData", pbData.String())
return
}
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"msgIncr": params.MsgIncr,
"reqIdentifier": params.ReqIdentifier,
"data": gin.H{
"seq": reply.Seq,
},
})
}

75
src/api/chat/pull_msg.go Normal file
View File

@ -0,0 +1,75 @@
package apiChat
import (
"Open_IM/src/common/config"
"Open_IM/src/common/log"
"Open_IM/src/proto/chat"
"Open_IM/src/utils"
"context"
"github.com/gin-gonic/gin"
"github.com/skiffer-git/grpc-etcdv3/getcdv3"
"net/http"
"strings"
)
type paramsUserPullMsg struct {
ReqIdentifier int `json:"reqIdentifier" binding:"required"`
SendID string `json:"sendID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
MsgIncr int `json:"msgIncr" binding:"required"`
Data struct {
SeqBegin int64 `json:"seqBegin" binding:"required"`
SeqEnd int64 `json:"seqEnd" binding:"required"`
}
}
func UserPullMsg(c *gin.Context) {
params := paramsUserPullMsg{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
token := c.Request.Header.Get("token")
if !utils.VerifyToken(token, params.SendID) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
}
pbData := pbChat.PullMessageReq{}
pbData.UserID = params.SendID
pbData.OperationID = params.OperationID
pbData.SeqBegin = params.Data.SeqBegin
pbData.SeqEnd = params.Data.SeqEnd
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessage(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("PullMessage error", pbData.OperationID, "err", err.Error())
return
}
log.InfoByKv("rpc call success to pullMsgRep", pbData.OperationID, "ReplyArgs", reply.String(), "maxSeq", reply.GetMaxSeq(),
"MinSeq", reply.GetMinSeq(), "singLen", len(reply.GetSingleUserMsg()), "groupLen", len(reply.GetGroupUserMsg()))
msg := make(map[string]interface{})
if v := reply.GetSingleUserMsg(); v != nil {
msg["single"] = v
} else {
msg["single"] = []pbChat.GatherFormat{}
}
if v := reply.GetGroupUserMsg(); v != nil {
msg["group"] = v
} else {
msg["group"] = []pbChat.GatherFormat{}
}
msg["maxSeq"] = reply.GetMaxSeq()
msg["minSeq"] = reply.GetMinSeq()
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"msgIncr": params.MsgIncr,
"reqIdentifier": params.ReqIdentifier,
"data": msg,
})
}

96
src/api/chat/send_msg.go Normal file
View File

@ -0,0 +1,96 @@
package apiChat
import (
"Open_IM/src/common/config"
"Open_IM/src/common/log"
pbChat "Open_IM/src/proto/chat"
"Open_IM/src/utils"
"context"
"github.com/gin-gonic/gin"
"github.com/skiffer-git/grpc-etcdv3/getcdv3"
"net/http"
"strings"
)
type paramsUserSendMsg struct {
ReqIdentifier int32 `json:"reqIdentifier" binding:"required"`
PlatformID int32 `json:"platformID" binding:"required"`
SendID string `json:"sendID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
MsgIncr int32 `json:"msgIncr" binding:"required"`
Data struct {
SessionType int32 `json:"sessionType" binding:"required"`
MsgFrom int32 `json:"msgFrom" binding:"required"`
ContentType int32 `json:"contentType" binding:"required"`
RecvID string `json:"recvID" binding:"required"`
ForceList []string `json:"forceList" binding:"required"`
Content string `json:"content" binding:"required"`
Options map[string]interface{} `json:"options" binding:"required"`
ClientMsgID string `json:"clientMsgID" binding:"required"`
OffLineInfo map[string]interface{} `json:"offlineInfo" binding:"required"`
Ex map[string]interface{} `json:"ext"`
}
}
func newUserSendMsgReq(token string, params *paramsUserSendMsg) *pbChat.UserSendMsgReq {
pbData := pbChat.UserSendMsgReq{
ReqIdentifier: params.ReqIdentifier,
Token: token,
SendID: params.SendID,
OperationID: params.OperationID,
MsgIncr: params.MsgIncr,
PlatformID: params.PlatformID,
SessionType: params.Data.SessionType,
MsgFrom: params.Data.MsgFrom,
ContentType: params.Data.ContentType,
RecvID: params.Data.RecvID,
ForceList: params.Data.ForceList,
Content: params.Data.Content,
Options: utils.MapToJsonString(params.Data.Options),
ClientMsgID: params.Data.ClientMsgID,
OffLineInfo: utils.MapToJsonString(params.Data.OffLineInfo),
Ex: utils.MapToJsonString(params.Data.Ex),
}
return &pbData
}
func UserSendMsg(c *gin.Context) {
params := paramsUserSendMsg{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
log.ErrorByKv("json unmarshal err", "", "err", err.Error(), "data", c.PostForm("data"))
return
}
token := c.Request.Header.Get("token")
if !utils.VerifyToken(token, params.SendID) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
}
log.InfoByKv("Ws call success to sendMsgReq", params.OperationID, "Parameters", params)
pbData := newUserSendMsgReq(token, &params)
log.Info("", "", "api UserSendMsg call start..., [data: %s]", pbData.String())
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
client := pbChat.NewChatClient(etcdConn)
log.Info("", "", "api UserSendMsg call, api call rpc...")
reply, _ := client.UserSendMsg(context.Background(), pbData)
log.Info("", "", "api UserSendMsg call end..., [data: %s] [reply: %s]", pbData.String(), reply.String())
c.JSON(http.StatusOK, gin.H{
"errCode": 0,
"errMsg": "",
"msgIncr": reply.MsgIncr,
"reqIdentifier": reply.ReqIdentifier,
"data": gin.H{
"clientMsgID": reply.ClientMsgID,
"serverMsgID": reply.ServerMsgID,
},
})
}

75
src/api/open_im_api.go Normal file
View File

@ -0,0 +1,75 @@
package main
import (
apiAuth "Open_IM/src/api/auth"
apiChat "Open_IM/src/api/chat"
"Open_IM/src/api/friend"
apiThird "Open_IM/src/api/third"
"Open_IM/src/api/user"
"Open_IM/src/common/log"
"Open_IM/src/utils"
"flag"
"github.com/gin-gonic/gin"
"strconv"
)
func main() {
log.Info("", "", "api server running...")
r := gin.Default()
r.Use(utils.CorsHandler())
// user routing group, which handles user registration and login services
userRouterGroup := r.Group("/user")
{
userRouterGroup.POST("/update_user_info", user.UpdateUserInfo)
userRouterGroup.POST("/get_user_info", user.GetUserInfo)
}
//friend routing group
friendRouterGroup := r.Group("/friend")
{
friendRouterGroup.POST("/search_friend", friend.SearchFriend)
friendRouterGroup.POST("/add_friend", friend.AddFriend)
friendRouterGroup.POST("/get_friend_apply_list", friend.GetFriendApplyList)
friendRouterGroup.POST("/get_friend_list", friend.GetFriendList)
friendRouterGroup.POST("/add_blacklist", friend.AddBlacklist)
friendRouterGroup.POST("/get_blacklist", friend.GetBlacklist)
friendRouterGroup.POST("/remove_blacklist", friend.RemoveBlacklist)
friendRouterGroup.POST("/delete_friend", friend.DeleteFriend)
friendRouterGroup.POST("/add_friend_response", friend.AddFriendResponse)
friendRouterGroup.POST("/set_friend_comment", friend.SetFriendComment)
}
//group related routing group
/*groupRouterGroup := r.Group("/group")
{
groupRouterGroup.POST("/create_group", group.CreateGroup)
groupRouterGroup.POST("/get_group_list", group.GetGroupList)
groupRouterGroup.POST("/get_group_info", group.GetGroupInfo)
groupRouterGroup.POST("/delete_group_member", group.DeleteGroupMember)
groupRouterGroup.POST("/set_group_name", group.SetGroupName)
groupRouterGroup.POST("/set_group_bulletin", group.SetGroupBulletin)
groupRouterGroup.POST("/set_owner_group_nickname", group.SetOwnerGroupNickname)
groupRouterGroup.POST("/set_group_head_image", group.SetGroupHeadImage)
groupRouterGroup.POST("/member_exit_group", group.MemberExitGroup)
}*/
//certificate
authRouterGroup := r.Group("/auth")
{
authRouterGroup.POST("/user_register", apiAuth.UserRegister)
authRouterGroup.POST("/user_token", apiAuth.UserToken)
}
//Third service
thirdGroup := r.Group("/third")
{
thirdGroup.POST("/tencent_cloud_storage_credential", apiThird.TencentCloudStorageCredential)
}
//Message
chatGroup := r.Group("/chat")
{
chatGroup.POST("/newest_seq", apiChat.UserNewestSeq)
chatGroup.POST("/pull_msg", apiChat.UserPullMsg)
chatGroup.POST("/send_msg", apiChat.UserSendMsg)
}
ginPort := flag.Int("port", 10000, "get ginServerPort from cmd,default 10000 as port")
flag.Parse()
r.Run(utils.ServerIP + ":" + strconv.Itoa(*ginPort))
}

View File

@ -0,0 +1,70 @@
package apiThird
import (
"Open_IM/src/common/config"
log2 "Open_IM/src/common/log"
"github.com/gin-gonic/gin"
sts "github.com/tencentyun/qcloud-cos-sts-sdk/go"
"net/http"
"time"
)
type paramsTencentCloudStorageCredential struct {
Token string `json:"token"`
OperationID string `json:"operationID"`
}
func TencentCloudStorageCredential(c *gin.Context) {
params := paramsTencentCloudStorageCredential{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "Parameter parsing errorplease check the parameters and request service again"})
return
}
log2.Info(params.Token, params.OperationID, "api TencentUpLoadCredential call start...")
cli := sts.NewClient(
config.Config.Credential.Tencent.SecretID,
config.Config.Credential.Tencent.SecretKey,
nil,
)
log2.Info(c.Request.Header.Get("token"), c.PostForm("optionID"), "api TencentUpLoadCredential sts.NewClient cli = %v", cli)
opt := &sts.CredentialOptions{
DurationSeconds: int64(time.Hour.Seconds()),
Region: config.Config.Credential.Tencent.Region,
Policy: &sts.CredentialPolicy{
Statement: []sts.CredentialPolicyStatement{
{
Action: []string{
"name/cos:PostObject",
"name/cos:PutObject",
},
Effect: "allow",
Resource: []string{
"qcs::cos:" + config.Config.Credential.Tencent.Region + ":uid/" + config.Config.Credential.Tencent.AppID + ":" + config.Config.Credential.Tencent.Bucket + "/*",
},
},
},
},
}
log2.Info(c.Request.Header.Get("token"), c.PostForm("optionID"), "api TencentUpLoadCredential sts.CredentialOptions opt = %v", opt)
res, err := cli.GetCredential(opt)
if err != nil {
log2.Error(c.Request.Header.Get("token"), c.PostForm("optionID"), "api TencentUpLoadCredential cli.GetCredential err = %s", err.Error())
c.JSON(http.StatusOK, gin.H{
"errCode": config.ErrTencentCredential.ErrCode,
"errMsg": err.Error(),
"data": res,
})
return
}
log2.Info(c.Request.Header.Get("token"), c.PostForm("optionID"), "api TencentUpLoadCredential cli.GetCredential success res = %v, res.Credentials = %v", res, res.Credentials)
c.JSON(http.StatusOK, gin.H{
"errCode": 0,
"errMsg": "",
"data": res,
})
}