From bb6462647a21b57aee4c1bad4a52d33063e95b25 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Mon, 11 Dec 2023 12:18:55 +0800 Subject: [PATCH 01/31] fix: fix docker compose scripts (#1546) * fix: fix docker compose scripts Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * fix: fix scripts and rea Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> --------- Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> --- .../{env_template.yaml => env-template.yaml} | 0 docs/contrib/bash-log.md | 2 +- install_guide.sh | 176 ------------------ internal/rpc/msg/as_read.go | 96 ++++++---- scripts/init-config.sh | 60 ++++-- scripts/install/openim-api.sh | 2 +- scripts/install/openim-rpc.sh | 2 +- scripts/lib/logging.sh | 2 +- 8 files changed, 108 insertions(+), 232 deletions(-) rename deployments/templates/{env_template.yaml => env-template.yaml} (100%) delete mode 100755 install_guide.sh diff --git a/deployments/templates/env_template.yaml b/deployments/templates/env-template.yaml similarity index 100% rename from deployments/templates/env_template.yaml rename to deployments/templates/env-template.yaml diff --git a/docs/contrib/bash-log.md b/docs/contrib/bash-log.md index 86acb1d33..7725d5589 100644 --- a/docs/contrib/bash-log.md +++ b/docs/contrib/bash-log.md @@ -11,7 +11,7 @@ OpenIM, an intricate project, requires a robust logging mechanism to diagnose is 1. **Initialization**: The system begins by determining the verbosity level through the `OPENIM_VERBOSE` variable. If it's not set, a default value of 5 is assigned. This verbosity level dictates the depth of the log details. 2. **Log File Setup**: Logs are stored in the directory specified by `OPENIM_OUTPUT`. If this variable isn't explicitly set, it defaults to the `_output` directory relative to the script location. Each log file is named based on the date to facilitate easy identification. 3. **Logging Function**: The `echo_log()` function plays a pivotal role by writing messages to both the console (stdout) and the log file. -4. **Logging to a file**: The `echo_log()` function writes to the log file by appending the message to the file. It also adds a timestamp to the message. path: `_output/logs/*`, Enable logging by default. Set to false to disable. If you wish to turn off output to log files set `ENABLE_LOGGING=flase`. +4. **Logging to a file**: The `echo_log()` function writes to the log file by appending the message to the file. It also adds a timestamp to the message. path: `_output/logs/*`, Enable logging by default. Set to false to disable. If you wish to turn off output to log files set `export ENABLE_LOGGING=flase`. ### Key Functions & Their Usages diff --git a/install_guide.sh b/install_guide.sh deleted file mode 100755 index c4323d6a8..000000000 --- a/install_guide.sh +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env bash - -echo "Welcome to the Open-IM-Server installation scripts." -echo "Please select an deploy option:" -echo "1. docker-compose install" -echo "2. exit" - -clear_openimlog() { - rm -rf ./logs/* -} - -is_path() { - if [ -e "$1" ]; then - return 1 - else - return 0 - fi -} - -is_empty() { - if [ -z "$1" ]; then - return 1 - else - return 0 - fi -} - -is_directory_exists() { - if [ -d "$1" ]; then - return 1 - else - return 0 - fi -} - -edit_config() { - echo "Is edit config.yaml?" - echo "1. vi edit config" - echo "2. do not edit config" - read choice - case $choice in - 1) - vi config/config.yaml - ;; - 2) - echo "do not edit config" - ;; - esac -} - -edit_enterprise_config() { - echo "Is edit enterprise config.yaml?" - echo "1. vi edit enterprise config" - echo "2. do not edit enterprise config" - read choice - case $choice in - 1) - vi ./.docker-compose_cfg/config.yaml - ;; - 2) - echo "Do not edit enterprise config" - ;; - esac -} - -install_docker_compose() { - echo "Please input the installation path, default is $(pwd)/Open-IM-Server, press enter to use default" - read install_path - is_empty $install_path - if [ $? -eq 1 ]; then - install_path="." - fi - echo "Installing Open-IM-Server to ${install_path}/Open-IM-Server..." - is_path $install_path - mkdir -p $install_path - cd $install_path - is_directory_exists "${install_path}/Open-IM-Server" - if [ $? -eq 1 ]; then - echo "WARNING: Directory $install_path/Open-IM-Server exist, please ensure your path" - echo "1. delete the directory and install" - echo "2. exit" - read choice - case $choice in - 1) - rm -rf "${install_path}/Open-IM-Server" - ;; - 2) - exit 1 - ;; - esac - fi - rm -rf ./Open-IM-Server - set -e - git clone https://github.com/openimsdk/open-im-server.git --recursive; - set +e - cd ./Open-IM-Server - git checkout errcode - echo "======== git clone success ========" - source .env - if [ $DATA_DIR = "./" ]; then - DATA_DIR=$(pwd)/components - fi - echo "Please input the components data directory, deault is ${DATA_DIR}, press enter to use default" - read NEW_DATA_DIR - is_empty $NEW_DATA_DIR - if [ $? -eq 0 ]; then - DATA_DIR=$NEW_DATA_DIR - fi - echo "Please input the user, deault is root, press enter to use default" - read NEW_USER - is_empty $NEW_USER - if [ $? -eq 0 ]; then - OPENIM_USER=$NEW_USER - fi - - echo "Please input the password, default is openIM123, press enter to use default" - read NEW_PASSWORD - is_empty $NEW_PASSWORD - if [ $? -eq 0 ]; then - PASSWORD=$NEW_PASSWORD - fi - - echo "Please input the minio_endpoint, default will detect auto, press enter to use default" - read NEW_MINIO_ENDPOINT - is_empty $NEW_MINIO_ENDPOINT - if [ $? -eq 1 ]; then - internet_ip=`curl ifconfig.me -s` - MINIO_ENDPOINT="http://${internet_ip}:10005" - else - MINIO_ENDPOINT=$NEW_MINIO_ENDPOINT - fi - set -e - export MINIO_ENDPOINT - export OPENIM_USER - export PASSWORD - export DATA_DIR - - cat < .env -OPENIM_USER=${OPENIM_USER} -PASSWORD=${PASSWORD} -MINIO_ENDPOINT=${MINIO_ENDPOINT} -DATA_DIR=${DATA_DIR} -EOF - - edit_config - edit_enterprise_config - - cd scripts; - chmod +x *.sh; - ./init-pwd.sh; - ./env_check.sh; - cd ..; - docker-compose up -d; - cd scripts; - ./docker-check-service.sh; -} - -read choice - -case $choice in - 1) - install_docker_compose - ;; - 2) - - ;; - 3) - ;; - 4) - echo "Exiting installation scripts..." - exit 0 - ;; - *) - echo "Invalid option, please try again." - ;; -esac diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index 49113aa0b..061498abb 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -16,14 +16,12 @@ package msg import ( "context" - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" - utils2 "github.com/OpenIMSDK/tools/utils" "github.com/redis/go-redis/v9" + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/OpenIMSDK/protocol/constant" - "github.com/OpenIMSDK/protocol/conversation" "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/errs" @@ -92,7 +90,10 @@ func (m *msgServer) SetConversationHasReadSeq( return &msg.SetConversationHasReadSeqResp{}, nil } -func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadReq) (resp *msg.MarkMsgsAsReadResp, err error) { +func (m *msgServer) MarkMsgsAsRead( + ctx context.Context, + req *msg.MarkMsgsAsReadReq, +) (resp *msg.MarkMsgsAsReadResp, err error) { if len(req.Seqs) < 1 { return nil, errs.ErrArgs.Wrap("seqs must not be empty") } @@ -111,6 +112,7 @@ func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadR if err = m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, req.Seqs); err != nil { return } + currentHasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID) if err != nil && errs.Unwrap(err) != redis.Nil { return @@ -128,7 +130,10 @@ func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadR return &msg.MarkMsgsAsReadResp{}, nil } -func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkConversationAsReadReq) (resp *msg.MarkConversationAsReadResp, err error) { +func (m *msgServer) MarkConversationAsRead( + ctx context.Context, + req *msg.MarkConversationAsReadReq, +) (resp *msg.MarkConversationAsReadResp, err error) { conversation, err := m.Conversation.GetConversation(ctx, req.UserID, req.ConversationID) if err != nil { return nil, err @@ -137,34 +142,54 @@ func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkCon if err != nil && errs.Unwrap(err) != redis.Nil { return nil, err } - seqs := generateSeqs(hasReadSeq, req) + var seqs []int64 - if len(seqs) > 0 || req.HasReadSeq > hasReadSeq { - err = m.updateReadStatus(ctx, req, conversation, seqs, hasReadSeq) - if err != nil { + log.ZDebug(ctx, "MarkConversationAsRead", "hasReadSeq", hasReadSeq, + "req.HasReadSeq", req.HasReadSeq) + if conversation.ConversationType == constant.SingleChatType { + for i := hasReadSeq + 1; i <= req.HasReadSeq; i++ { + seqs = append(seqs, i) + } + //avoid client missed call MarkConversationMessageAsRead by order + for _, val := range req.Seqs { + if !utils2.Contain(val, seqs...) { + seqs = append(seqs, val) + } + } + if len(seqs) > 0 { + log.ZDebug(ctx, "MarkConversationAsRead", "seqs", seqs, "conversationID", req.ConversationID) + if err = m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, seqs); err != nil { + return nil, err + } + } + if req.HasReadSeq > hasReadSeq { + err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq) + if err != nil { + return nil, err + } + hasReadSeq = req.HasReadSeq + } + if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID, + m.conversationAndGetRecvID(conversation, req.UserID), seqs, hasReadSeq); err != nil { return nil, err } - } - return &msg.MarkConversationAsReadResp{}, nil -} - -func generateSeqs(hasReadSeq int64, req *msg.MarkConversationAsReadReq) []int64 { - var seqs []int64 - for _, val := range req.Seqs { - if val > hasReadSeq && !utils2.Contain(val, seqs...) { - seqs = append(seqs, val) + + } else if conversation.ConversationType == constant.SuperGroupChatType || + conversation.ConversationType == constant.NotificationChatType { + if req.HasReadSeq > hasReadSeq { + err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq) + if err != nil { + return nil, err + } + hasReadSeq = req.HasReadSeq } - } - return seqs -} - -func (m *msgServer) updateReadStatus(ctx context.Context, req *msg.MarkConversationAsReadReq, conversation *conversation.Conversation, seqs []int64, hasReadSeq int64) error { - if conversation.ConversationType == constant.SingleChatType && len(seqs) > 0 { - log.ZDebug(ctx, "MarkConversationAsRead", "seqs", seqs, "conversationID", req.ConversationID) - if err := m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, seqs); err != nil { - return err + if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID, + req.UserID, seqs, hasReadSeq); err != nil { + return nil, err } + } + reqCall := &cbapi.CallbackGroupMsgReadReq{ SendID: conversation.OwnerUserID, ReceiveID: req.UserID, @@ -172,21 +197,10 @@ func (m *msgServer) updateReadStatus(ctx context.Context, req *msg.MarkConversat ContentType: int64(conversation.ConversationType), } if err := CallbackGroupMsgRead(ctx, reqCall); err != nil { - return err - } - - if req.HasReadSeq > hasReadSeq { - if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { - return err - } - } - - recvID := m.conversationAndGetRecvID(conversation, req.UserID) - if conversation.ConversationType == constant.SuperGroupChatType || conversation.ConversationType == constant.NotificationChatType { - recvID = req.UserID + return nil, err } - return m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID, recvID, seqs, req.HasReadSeq) + return &msg.MarkConversationAsReadResp{}, nil } func (m *msgServer) sendMarkAsReadNotification( @@ -208,4 +222,4 @@ func (m *msgServer) sendMarkAsReadNotification( log.ZWarn(ctx, "send has read Receipt err", err) } return nil -} +} \ No newline at end of file diff --git a/scripts/init-config.sh b/scripts/init-config.sh index f20fc7e73..380239d50 100755 --- a/scripts/init-config.sh +++ b/scripts/init-config.sh @@ -24,12 +24,10 @@ OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. source "${OPENIM_ROOT}/scripts/lib/init.sh" -# (en: Define a profile array that contains the name path of the profile to be generated.) readonly ENV_FILE=${ENV_FILE:-"${OPENIM_ROOT}/scripts/install/environment.sh"} -# (en: Defines an associative array where the keys are the template files and the values are the corresponding output files.) declare -A TEMPLATES=( - ["${OPENIM_ROOT}/deployments/templates/env_template.yaml"]="${OPENIM_ROOT}/.env" + ["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/.env" ["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/config.yaml" ["${OPENIM_ROOT}/deployments/templates/prometheus.yml"]="${OPENIM_ROOT}/config/prometheus.yml" ["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/alertmanager.yml" @@ -37,6 +35,42 @@ declare -A TEMPLATES=( openim::log::info "Read more configuration information: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md" +# New variables for argument handling +FORCE_OVERWRITE=false +SKIP_EXISTING=false + +# Function to display help +show_help() { + echo "Usage: $(basename "$0") [options]" + echo "Options:" + echo " -h, --help Show this help message" + echo " --force Overwrite existing files without prompt" + echo " --skip Skip generation if file exists" +} + +# Parse command-line options +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + show_help + exit 0 + ;; + --force) + FORCE_OVERWRITE=true + shift + ;; + --skip) + SKIP_EXISTING=true + shift + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + for template in "${!TEMPLATES[@]}"; do if [[ ! -f "${template}" ]]; then openim::log::error_exit "Template file ${template} does not exist..." @@ -48,14 +82,19 @@ for template in "${!TEMPLATES[@]}"; do IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}" for output_file in "${OUTPUT_FILES[@]}"; do if [[ -f "${output_file}" ]]; then - echo -n "File ${output_file} already exists. Overwrite? (Y/N): " - read -r -n 1 REPLY - echo # Adds a line to wrap after user input - if [[ $REPLY =~ ^[Yy]$ ]]; then - openim::log::info "Overwriting ${output_file}. Previous configuration will be lost." - else - openim::log::info "Skipping generation of ${output_file}." + if [[ "${FORCE_OVERWRITE}" == true ]]; then + openim::log::info "Force overwriting ${output_file}." + elif [[ "${SKIP_EXISTING}" == true ]]; then + openim::log::info "Skipping generation of ${output_file} as it already exists." continue + else + echo -n "File ${output_file} already exists. Overwrite? (Y/N): " + read -r -n 1 REPLY + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + openim::log::info "Skipping generation of ${output_file}." + continue + fi fi fi @@ -72,5 +111,4 @@ for template in "${!TEMPLATES[@]}"; do done done - openim::log::success "✨ All configuration files have been successfully generated!" diff --git a/scripts/install/openim-api.sh b/scripts/install/openim-api.sh index a40e23611..9f66d0ba0 100755 --- a/scripts/install/openim-api.sh +++ b/scripts/install/openim-api.sh @@ -66,7 +66,7 @@ function openim::api::start() { for ((j = 0; j < ${#OPENIM_API_SERVICE_PORTS[@]}; j++)); do openim::log::info "Starting ${OPENIM_API_SERVICE_LISTARIES[$i]} service, port: ${OPENIM_API_SERVICE_PORTS[j]}, binary root: ${OPENIM_OUTPUT_HOSTBIN}/${OPENIM_API_SERVICE_LISTARIES[$i]}" openim::api::start_service "${OPENIM_API_SERVICE_LISTARIES[$i]}" "${OPENIM_API_PORT_LISTARIES[j]}" - sleep 1 + sleep 2 done done diff --git a/scripts/install/openim-rpc.sh b/scripts/install/openim-rpc.sh index bd00ff9f2..b66004191 100755 --- a/scripts/install/openim-rpc.sh +++ b/scripts/install/openim-rpc.sh @@ -138,7 +138,7 @@ function openim::rpc::start() { done done - sleep 0.5 + sleep 1 openim::util::check_ports ${OPENIM_RPC_PORT_TARGETS[@]} # openim::util::check_ports ${OPENIM_RPC_PROM_PORT_TARGETS[@]} diff --git a/scripts/lib/logging.sh b/scripts/lib/logging.sh index 90f9d0c7f..9d28aa284 100755 --- a/scripts/lib/logging.sh +++ b/scripts/lib/logging.sh @@ -17,7 +17,7 @@ OPENIM_VERBOSE="${OPENIM_VERBOSE:-5}" # Enable logging by default. Set to false to disable. -ENABLE_LOGGING=true +ENABLE_LOGGING="${ENABLE_LOGGING:-true}" # If OPENIM_OUTPUT is not set, set it to the default value if [[ ! -v OPENIM_OUTPUT ]]; then From 6b55cfd0b8fea3645e0426d1f80b86d5220cbb13 Mon Sep 17 00:00:00 2001 From: chao <48119764+withchao@users.noreply.github.com> Date: Tue, 12 Dec 2023 10:03:40 +0800 Subject: [PATCH 02/31] feat: optimize tools up35 (#1552) * upgrade package and rtc convert * upgrade package and rtc convert * upgrade package and rtc convert --- go.mod | 4 +- go.sum | 4 +- internal/rpc/friend/friend.go | 1 - tools/up35/pkg/convert.go | 227 +++++++++++ .../pkg/internal/rtc/mongo/mgo/meeting.go | 86 +++++ .../rtc/mongo/mgo/meeting_invitation.go | 76 ++++ .../internal/rtc/mongo/mgo/meeting_record.go | 32 ++ .../up35/pkg/internal/rtc/mongo/mgo/signal.go | 89 +++++ .../rtc/mongo/mgo/signal_invitation.go | 78 ++++ .../pkg/internal/rtc/mongo/table/meeting.go | 51 +++ .../pkg/internal/rtc/mongo/table/signal.go | 73 ++++ tools/up35/pkg/internal/rtc/mysql/meeting.go | 40 ++ tools/up35/pkg/internal/rtc/mysql/signal.go | 43 +++ tools/up35/pkg/pkg.go | 206 ++++++++++ tools/up35/up35.go | 352 +----------------- 15 files changed, 1007 insertions(+), 355 deletions(-) create mode 100644 tools/up35/pkg/convert.go create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/signal.go create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go create mode 100644 tools/up35/pkg/internal/rtc/mongo/table/meeting.go create mode 100644 tools/up35/pkg/internal/rtc/mongo/table/signal.go create mode 100644 tools/up35/pkg/internal/rtc/mysql/meeting.go create mode 100644 tools/up35/pkg/internal/rtc/mysql/signal.go create mode 100644 tools/up35/pkg/pkg.go diff --git a/go.mod b/go.mod index 6cf2089de..11d374d08 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.19 require ( firebase.google.com/go v3.13.0+incompatible + github.com/OpenIMSDK/protocol v0.0.31 + github.com/OpenIMSDK/tools v0.0.20 github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/dtm-labs/rockscache v0.1.1 github.com/gin-gonic/gin v1.9.1 @@ -33,8 +35,6 @@ require github.com/google/uuid v1.3.1 require ( github.com/IBM/sarama v1.41.3 - github.com/OpenIMSDK/protocol v0.0.31 - github.com/OpenIMSDK/tools v0.0.18 github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible github.com/go-redis/redis v6.15.9+incompatible github.com/redis/go-redis/v9 v9.2.1 diff --git a/go.sum b/go.sum index 2f9198c9f..30e4b3cb4 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE= github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= -github.com/OpenIMSDK/tools v0.0.18 h1:h3CvKB90DNd2aIJcOQ99cqgeW6C0na0PzR1TNsfxwL0= -github.com/OpenIMSDK/tools v0.0.18/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= +github.com/OpenIMSDK/tools v0.0.20 h1:zBTjQZRJ5lR1FIzP9mtWyAvh5dKsmJXQugi4p8X/97k= +github.com/OpenIMSDK/tools v0.0.20/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index 7f22c9d0d..224efe3ed 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -16,7 +16,6 @@ package friend import ( "context" - "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/protocol/sdkws" diff --git a/tools/up35/pkg/convert.go b/tools/up35/pkg/convert.go new file mode 100644 index 000000000..91fdb474e --- /dev/null +++ b/tools/up35/pkg/convert.go @@ -0,0 +1,227 @@ +package pkg + +import ( + mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3" + mongoModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + mysqlModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mysql" + "time" +) + +type convert struct{} + +func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel { + return mongoModel.UserModel{ + UserID: v.UserID, + Nickname: v.Nickname, + FaceURL: v.FaceURL, + Ex: v.Ex, + AppMangerLevel: v.AppMangerLevel, + GlobalRecvMsgOpt: v.GlobalRecvMsgOpt, + CreateTime: v.CreateTime, + } +} + +func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel { + return mongoModel.FriendModel{ + OwnerUserID: v.OwnerUserID, + FriendUserID: v.FriendUserID, + Remark: v.Remark, + CreateTime: v.CreateTime, + AddSource: v.AddSource, + OperatorUserID: v.OperatorUserID, + Ex: v.Ex, + } +} + +func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel { + return mongoModel.FriendRequestModel{ + FromUserID: v.FromUserID, + ToUserID: v.ToUserID, + HandleResult: v.HandleResult, + ReqMsg: v.ReqMsg, + CreateTime: v.CreateTime, + HandlerUserID: v.HandlerUserID, + HandleMsg: v.HandleMsg, + HandleTime: v.HandleTime, + Ex: v.Ex, + } +} + +func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel { + return mongoModel.BlackModel{ + OwnerUserID: v.OwnerUserID, + BlockUserID: v.BlockUserID, + CreateTime: v.CreateTime, + AddSource: v.AddSource, + OperatorUserID: v.OperatorUserID, + Ex: v.Ex, + } +} + +func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel { + return mongoModel.GroupModel{ + GroupID: v.GroupID, + GroupName: v.GroupName, + Notification: v.Notification, + Introduction: v.Introduction, + FaceURL: v.FaceURL, + CreateTime: v.CreateTime, + Ex: v.Ex, + Status: v.Status, + CreatorUserID: v.CreatorUserID, + GroupType: v.GroupType, + NeedVerification: v.NeedVerification, + LookMemberInfo: v.LookMemberInfo, + ApplyMemberFriend: v.ApplyMemberFriend, + NotificationUpdateTime: v.NotificationUpdateTime, + NotificationUserID: v.NotificationUserID, + } +} + +func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel { + return mongoModel.GroupMemberModel{ + GroupID: v.GroupID, + UserID: v.UserID, + Nickname: v.Nickname, + FaceURL: v.FaceURL, + RoleLevel: v.RoleLevel, + JoinTime: v.JoinTime, + JoinSource: v.JoinSource, + InviterUserID: v.InviterUserID, + OperatorUserID: v.OperatorUserID, + MuteEndTime: v.MuteEndTime, + Ex: v.Ex, + } +} + +func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel { + return mongoModel.GroupRequestModel{ + UserID: v.UserID, + GroupID: v.GroupID, + HandleResult: v.HandleResult, + ReqMsg: v.ReqMsg, + HandledMsg: v.HandledMsg, + ReqTime: v.ReqTime, + HandleUserID: v.HandleUserID, + HandledTime: v.HandledTime, + JoinSource: v.JoinSource, + InviterUserID: v.InviterUserID, + Ex: v.Ex, + } +} + +func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel { + return mongoModel.ConversationModel{ + OwnerUserID: v.OwnerUserID, + ConversationID: v.ConversationID, + ConversationType: v.ConversationType, + UserID: v.UserID, + GroupID: v.GroupID, + RecvMsgOpt: v.RecvMsgOpt, + IsPinned: v.IsPinned, + IsPrivateChat: v.IsPrivateChat, + BurnDuration: v.BurnDuration, + GroupAtType: v.GroupAtType, + AttachedInfo: v.AttachedInfo, + Ex: v.Ex, + MaxSeq: v.MaxSeq, + MinSeq: v.MinSeq, + CreateTime: v.CreateTime, + IsMsgDestruct: v.IsMsgDestruct, + MsgDestructTime: v.MsgDestructTime, + LatestMsgDestructTime: v.LatestMsgDestructTime, + } +} + +func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel { + return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel { + return mongoModel.ObjectModel{ + Name: v.Name, + UserID: v.UserID, + Hash: v.Hash, + Engine: engine, + Key: v.Key, + Size: v.Size, + ContentType: v.ContentType, + Group: v.Cause, + CreateTime: v.CreateTime, + } + } +} + +func (convert) Log(v mysqlModel.Log) mongoModel.LogModel { + return mongoModel.LogModel{ + LogID: v.LogID, + Platform: v.Platform, + UserID: v.UserID, + CreateTime: v.CreateTime, + Url: v.Url, + FileName: v.FileName, + SystemType: v.SystemType, + Version: v.Version, + Ex: v.Ex, + } +} + +func (convert) SignalModel(v mysqlModelRtc.SignalModel) mongoModelRtc.SignalModel { + return mongoModelRtc.SignalModel{ + SID: v.SID, + InviterUserID: v.InviterUserID, + CustomData: v.CustomData, + GroupID: v.GroupID, + RoomID: v.RoomID, + Timeout: v.Timeout, + MediaType: v.MediaType, + PlatformID: v.PlatformID, + SessionType: v.SessionType, + InitiateTime: v.InitiateTime, + EndTime: v.EndTime, + FileURL: v.FileURL, + Title: v.Title, + Desc: v.Desc, + Ex: v.Ex, + IOSPushSound: v.IOSPushSound, + IOSBadgeCount: v.IOSBadgeCount, + SignalInfo: v.SignalInfo, + } +} + +func (convert) SignalInvitationModel(v mysqlModelRtc.SignalInvitationModel) mongoModelRtc.SignalInvitationModel { + return mongoModelRtc.SignalInvitationModel{ + SID: v.SID, + UserID: v.UserID, + Status: v.Status, + InitiateTime: v.InitiateTime, + HandleTime: v.HandleTime, + } +} + +func (convert) Meeting(v mysqlModelRtc.MeetingInfo) mongoModelRtc.MeetingInfo { + return mongoModelRtc.MeetingInfo{ + RoomID: v.RoomID, + MeetingName: v.MeetingName, + HostUserID: v.HostUserID, + Status: v.Status, + StartTime: time.Unix(v.StartTime, 0), + EndTime: time.Unix(v.EndTime, 0), + CreateTime: v.CreateTime, + Ex: v.Ex, + } +} + +func (convert) MeetingInvitationInfo(v mysqlModelRtc.MeetingInvitationInfo) mongoModelRtc.MeetingInvitationInfo { + return mongoModelRtc.MeetingInvitationInfo{ + RoomID: v.RoomID, + UserID: v.UserID, + CreateTime: v.CreateTime, + } +} + +func (convert) MeetingVideoRecord(v mysqlModelRtc.MeetingVideoRecord) mongoModelRtc.MeetingVideoRecord { + return mongoModelRtc.MeetingVideoRecord{ + RoomID: v.RoomID, + FileURL: v.FileURL, + CreateTime: v.CreateTime, + } +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go new file mode 100644 index 000000000..e3bab7af9 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go @@ -0,0 +1,86 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "time" +) + +func NewMeeting(db *mongo.Database) (table.MeetingInterface, error) { + coll := db.Collection("meeting") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "room_id", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "host_user_id", Value: 1}, + }, + }, + { + Keys: bson.D{ + {Key: "create_time", Value: -1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &meeting{coll: coll}, nil +} + +type meeting struct { + coll *mongo.Collection +} + +func (x *meeting) Find(ctx context.Context, roomIDs []string) ([]*table.MeetingInfo, error) { + return mgoutil.Find[*table.MeetingInfo](ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}}) +} + +func (x *meeting) CreateMeetingInfo(ctx context.Context, meetingInfo *table.MeetingInfo) error { + return mgoutil.InsertMany(ctx, x.coll, []*table.MeetingInfo{meetingInfo}) +} + +func (x *meeting) UpdateMeetingInfo(ctx context.Context, roomID string, update map[string]any) error { + if len(update) == 0 { + return nil + } + return mgoutil.UpdateOne(ctx, x.coll, bson.M{"room_id": roomID}, bson.M{"$set": update}, false) +} + +func (x *meeting) GetUnCompleteMeetingIDList(ctx context.Context, roomIDs []string) ([]string, error) { + if len(roomIDs) == 0 { + return nil, nil + } + return mgoutil.Find[string](ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}, "status": 0}, options.Find().SetProjection(bson.M{"_id": 0, "room_id": 1})) +} + +func (x *meeting) Delete(ctx context.Context, roomIDs []string) error { + return mgoutil.DeleteMany(ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}}) +} + +func (x *meeting) GetMeetingRecords(ctx context.Context, hostUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*table.MeetingInfo, error) { + var and []bson.M + if hostUserID != "" { + and = append(and, bson.M{"host_user_id": hostUserID}) + } + if !startTime.IsZero() { + and = append(and, bson.M{"create_time": bson.M{"$gte": startTime}}) + } + if !endTime.IsZero() { + and = append(and, bson.M{"create_time": bson.M{"$lte": endTime}}) + } + filter := bson.M{} + if len(and) > 0 { + filter["$and"] = and + } + return mgoutil.FindPage[*table.MeetingInfo](ctx, x.coll, filter, pagination, options.Find().SetSort(bson.M{"create_time": -1})) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go new file mode 100644 index 000000000..5286ffa95 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go @@ -0,0 +1,76 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/OpenIMSDK/tools/pagination" + "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "time" +) + +func NewMeetingInvitation(db *mongo.Database) (table.MeetingInvitationInterface, error) { + coll := db.Collection("meeting_invitation") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "room_id", Value: 1}, + {Key: "user_id", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "create_time", Value: -1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &meetingInvitation{coll: coll}, nil +} + +type meetingInvitation struct { + coll *mongo.Collection +} + +func (x *meetingInvitation) FindUserIDs(ctx context.Context, roomID string) ([]string, error) { + return mgoutil.Find[string](ctx, x.coll, bson.M{"room_id": roomID}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1})) +} + +func (x *meetingInvitation) CreateMeetingInvitationInfo(ctx context.Context, roomID string, inviteeUserIDs []string) error { + now := time.Now() + return mgoutil.InsertMany(ctx, x.coll, utils.Slice(inviteeUserIDs, func(userID string) *table.MeetingInvitationInfo { + return &table.MeetingInvitationInfo{ + RoomID: roomID, + UserID: userID, + CreateTime: now, + } + })) +} + +func (x *meetingInvitation) GetUserInvitedMeetingIDs(ctx context.Context, userID string) (meetingIDs []string, err error) { + fiveDaysAgo := time.Now().AddDate(0, 0, -5) + return mgoutil.Find[string](ctx, x.coll, bson.M{"user_id": userID, "create_time": bson.M{"$gte": fiveDaysAgo}}, options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1})) +} + +func (x *meetingInvitation) Delete(ctx context.Context, roomIDs []string) error { + return mgoutil.DeleteMany(ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}}) +} + +func (x *meetingInvitation) GetMeetingRecords(ctx context.Context, joinedUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) { + var and []bson.M + and = append(and, bson.M{"user_id": joinedUserID}) + if !startTime.IsZero() { + and = append(and, bson.M{"create_time": bson.M{"$gte": startTime}}) + } + if !endTime.IsZero() { + and = append(and, bson.M{"create_time": bson.M{"$lte": endTime}}) + } + opt := options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1}) + return mgoutil.FindPage[string](ctx, x.coll, bson.M{"$and": and}, pagination, opt) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go new file mode 100644 index 000000000..90fc9cdca --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go @@ -0,0 +1,32 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" +) + +func NewMeetingRecord(db *mongo.Database) (table.MeetingRecordInterface, error) { + coll := db.Collection("meeting_record") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "room_id", Value: 1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &meetingRecord{coll: coll}, nil +} + +type meetingRecord struct { + coll *mongo.Collection +} + +func (x *meetingRecord) CreateMeetingVideoRecord(ctx context.Context, meetingVideoRecord *table.MeetingVideoRecord) error { + return mgoutil.InsertMany(ctx, x.coll, []*table.MeetingVideoRecord{meetingVideoRecord}) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go new file mode 100644 index 000000000..0c1879007 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go @@ -0,0 +1,89 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "time" +) + +func NewSignal(db *mongo.Database) (table.SignalInterface, error) { + coll := db.Collection("signal") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "sid", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "inviter_user_id", Value: 1}, + }, + }, + { + Keys: bson.D{ + {Key: "initiate_time", Value: -1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &signal{coll: coll}, nil +} + +type signal struct { + coll *mongo.Collection +} + +func (x *signal) Find(ctx context.Context, sids []string) ([]*table.SignalModel, error) { + return mgoutil.Find[*table.SignalModel](ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}}) +} + +func (x *signal) CreateSignal(ctx context.Context, signalModel *table.SignalModel) error { + return mgoutil.InsertMany(ctx, x.coll, []*table.SignalModel{signalModel}) +} + +func (x *signal) Update(ctx context.Context, sid string, update map[string]any) error { + if len(update) == 0 { + return nil + } + return mgoutil.UpdateOne(ctx, x.coll, bson.M{"sid": sid}, bson.M{"$set": update}, false) +} + +func (x *signal) UpdateSignalFileURL(ctx context.Context, sID, fileURL string) error { + return x.Update(ctx, sID, map[string]any{"file_url": fileURL}) +} + +func (x *signal) UpdateSignalEndTime(ctx context.Context, sID string, endTime time.Time) error { + return x.Update(ctx, sID, map[string]any{"end_time": endTime}) +} + +func (x *signal) Delete(ctx context.Context, sids []string) error { + if len(sids) == 0 { + return nil + } + return mgoutil.DeleteMany(ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}}) +} + +func (x *signal) PageSignal(ctx context.Context, sesstionType int32, sendID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*table.SignalModel, error) { + var and []bson.M + if !startTime.IsZero() { + and = append(and, bson.M{"initiate_time": bson.M{"$gte": startTime}}) + } + if !endTime.IsZero() { + and = append(and, bson.M{"initiate_time": bson.M{"$lte": endTime}}) + } + if sesstionType != 0 { + and = append(and, bson.M{"sesstion_type": sesstionType}) + } + if sendID != "" { + and = append(and, bson.M{"inviter_user_id": sendID}) + } + return mgoutil.FindPage[*table.SignalModel](ctx, x.coll, bson.M{"$and": and}, pagination, options.Find().SetSort(bson.M{"initiate_time": -1})) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go new file mode 100644 index 000000000..274f2f11f --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go @@ -0,0 +1,78 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/OpenIMSDK/tools/pagination" + "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "time" +) + +func NewSignalInvitation(db *mongo.Database) (table.SignalInvitationInterface, error) { + coll := db.Collection("signal_invitation") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "sid", Value: 1}, + {Key: "user_id", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "initiate_time", Value: -1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &signalInvitation{coll: coll}, nil +} + +type signalInvitation struct { + coll *mongo.Collection +} + +func (x *signalInvitation) Find(ctx context.Context, sid string) ([]*table.SignalInvitationModel, error) { + return mgoutil.Find[*table.SignalInvitationModel](ctx, x.coll, bson.M{"sid": sid}) +} + +func (x *signalInvitation) CreateSignalInvitation(ctx context.Context, sid string, inviteeUserIDs []string) error { + now := time.Now() + return mgoutil.InsertMany(ctx, x.coll, utils.Slice(inviteeUserIDs, func(userID string) *table.SignalInvitationModel { + return &table.SignalInvitationModel{ + UserID: userID, + SID: sid, + InitiateTime: now, + HandleTime: time.Unix(0, 0), + } + })) +} + +func (x *signalInvitation) HandleSignalInvitation(ctx context.Context, sID, InviteeUserID string, status int32) error { + return mgoutil.UpdateOne(ctx, x.coll, bson.M{"sid": sID, "user_id": InviteeUserID}, bson.M{"$set": bson.M{"status": status, "handle_time": time.Now()}}, true) +} + +func (x *signalInvitation) PageSID(ctx context.Context, recvID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) { + var and []bson.M + and = append(and, bson.M{"user_id": recvID}) + if !startTime.IsZero() { + and = append(and, bson.M{"initiate_time": bson.M{"$gte": startTime}}) + } + if !endTime.IsZero() { + and = append(and, bson.M{"initiate_time": bson.M{"$lte": endTime}}) + } + return mgoutil.FindPage[string](ctx, x.coll, bson.M{"$and": and}, pagination, options.Find().SetProjection(bson.M{"_id": 0, "sid": 1}).SetSort(bson.M{"initiate_time": -1})) +} + +func (x *signalInvitation) Delete(ctx context.Context, sids []string) error { + if len(sids) == 0 { + return nil + } + return mgoutil.DeleteMany(ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}}) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/table/meeting.go b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go new file mode 100644 index 000000000..3b341cfb1 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go @@ -0,0 +1,51 @@ +package table + +import ( + "context" + "github.com/OpenIMSDK/tools/pagination" + "time" +) + +type MeetingInfo struct { + RoomID string `bson:"room_id"` + MeetingName string `bson:"meeting_name"` + HostUserID string `bson:"host_user_id"` + Status int64 `bson:"status"` + StartTime time.Time `bson:"start_time"` + EndTime time.Time `bson:"end_time"` + CreateTime time.Time `bson:"create_time"` + Ex string `bson:"ex"` +} + +type MeetingInterface interface { + Find(ctx context.Context, roomIDs []string) ([]*MeetingInfo, error) + CreateMeetingInfo(ctx context.Context, meetingInfo *MeetingInfo) error + UpdateMeetingInfo(ctx context.Context, roomID string, update map[string]any) error + GetUnCompleteMeetingIDList(ctx context.Context, roomIDs []string) ([]string, error) + Delete(ctx context.Context, roomIDs []string) error + GetMeetingRecords(ctx context.Context, hostUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*MeetingInfo, error) +} + +type MeetingInvitationInfo struct { + RoomID string `bson:"room_id"` + UserID string `bson:"user_id"` + CreateTime time.Time `bson:"create_time"` +} + +type MeetingInvitationInterface interface { + FindUserIDs(ctx context.Context, roomID string) ([]string, error) + CreateMeetingInvitationInfo(ctx context.Context, roomID string, inviteeUserIDs []string) error + GetUserInvitedMeetingIDs(ctx context.Context, userID string) (meetingIDs []string, err error) + Delete(ctx context.Context, roomIDs []string) error + GetMeetingRecords(ctx context.Context, joinedUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) +} + +type MeetingVideoRecord struct { + RoomID string `bson:"room_id"` + FileURL string `bson:"file_url"` + CreateTime time.Time `bson:"create_time"` +} + +type MeetingRecordInterface interface { + CreateMeetingVideoRecord(ctx context.Context, meetingVideoRecord *MeetingVideoRecord) error +} diff --git a/tools/up35/pkg/internal/rtc/mongo/table/signal.go b/tools/up35/pkg/internal/rtc/mongo/table/signal.go new file mode 100644 index 000000000..0cec050ff --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/table/signal.go @@ -0,0 +1,73 @@ +package table + +import ( + "context" + "github.com/OpenIMSDK/tools/errs" + "github.com/OpenIMSDK/tools/pagination" + "github.com/redis/go-redis/v9" + "go.mongodb.org/mongo-driver/mongo" + "time" +) + +type SignalModel struct { + SID string `bson:"sid"` + InviterUserID string `bson:"inviter_user_id"` + CustomData string `bson:"custom_data"` + GroupID string `bson:"group_id"` + RoomID string `bson:"room_id"` + Timeout int32 `bson:"timeout"` + MediaType string `bson:"media_type"` + PlatformID int32 `bson:"platform_id"` + SessionType int32 `bson:"session_type"` + InitiateTime time.Time `bson:"initiate_time"` + EndTime time.Time `bson:"end_time"` + FileURL string `bson:"file_url"` + + Title string `bson:"title"` + Desc string `bson:"desc"` + Ex string `bson:"ex"` + IOSPushSound string `bson:"ios_push_sound"` + IOSBadgeCount bool `bson:"ios_badge_count"` + SignalInfo string `bson:"signal_info"` +} + +type SignalInterface interface { + Find(ctx context.Context, sids []string) ([]*SignalModel, error) + CreateSignal(ctx context.Context, signalModel *SignalModel) error + Update(ctx context.Context, sid string, update map[string]any) error + UpdateSignalFileURL(ctx context.Context, sID, fileURL string) error + UpdateSignalEndTime(ctx context.Context, sID string, endTime time.Time) error + Delete(ctx context.Context, sids []string) error + PageSignal(ctx context.Context, sesstionType int32, sendID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*SignalModel, error) +} + +type SignalInvitationModel struct { + SID string `bson:"sid"` + UserID string `bson:"user_id"` + Status int32 `bson:"status"` + InitiateTime time.Time `bson:"initiate_time"` + HandleTime time.Time `bson:"handle_time"` +} + +type SignalInvitationInterface interface { + Find(ctx context.Context, sid string) ([]*SignalInvitationModel, error) + CreateSignalInvitation(ctx context.Context, sid string, inviteeUserIDs []string) error + HandleSignalInvitation(ctx context.Context, sID, InviteeUserID string, status int32) error + PageSID(ctx context.Context, recvID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) + Delete(ctx context.Context, sids []string) error +} + +func IsNotFound(err error) bool { + if err == nil { + return false + } + err = errs.Unwrap(err) + return err == mongo.ErrNoDocuments || err == redis.Nil +} + +func IsDuplicate(err error) bool { + if err == nil { + return false + } + return mongo.IsDuplicateKeyError(errs.Unwrap(err)) +} diff --git a/tools/up35/pkg/internal/rtc/mysql/meeting.go b/tools/up35/pkg/internal/rtc/mysql/meeting.go new file mode 100644 index 000000000..2c5bbed32 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mysql/meeting.go @@ -0,0 +1,40 @@ +package relation + +import ( + "time" +) + +type MeetingInfo struct { + RoomID string `gorm:"column:room_id;primary_key;size:128;index:room_id;index:status,priority:1"` + MeetingName string `gorm:"column:meeting_name;size:64"` + HostUserID string `gorm:"column:host_user_id;size:64;index:host_user_id"` + Status int64 `gorm:"column:status;index:status,priority:2"` + StartTime int64 `gorm:"column:start_time"` + EndTime int64 `gorm:"column:end_time"` + CreateTime time.Time `gorm:"column:create_time"` + Ex string `gorm:"column:ex;size:1024"` +} + +func (MeetingInfo) TableName() string { + return "meeting" +} + +type MeetingInvitationInfo struct { + RoomID string `gorm:"column:room_id;primary_key;size:128"` + UserID string `gorm:"column:user_id;primary_key;size:64;index:user_id"` + CreateTime time.Time `gorm:"column:create_time"` +} + +func (MeetingInvitationInfo) TableName() string { + return "meeting_invitation" +} + +type MeetingVideoRecord struct { + RoomID string `gorm:"column:room_id;size:128"` + FileURL string `gorm:"column:file_url"` + CreateTime time.Time `gorm:"column:create_time"` +} + +func (MeetingVideoRecord) TableName() string { + return "meeting_video_record" +} diff --git a/tools/up35/pkg/internal/rtc/mysql/signal.go b/tools/up35/pkg/internal/rtc/mysql/signal.go new file mode 100644 index 000000000..3a4d607d4 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mysql/signal.go @@ -0,0 +1,43 @@ +package relation + +import ( + "time" +) + +type SignalModel struct { + SID string `gorm:"column:sid;type:char(128);primary_key"` + InviterUserID string `gorm:"column:inviter_user_id;type:char(64);index:inviter_user_id_index"` + CustomData string `gorm:"column:custom_data;type:text"` + GroupID string `gorm:"column:group_id;type:char(64)"` + RoomID string `gorm:"column:room_id;primary_key;type:char(128)"` + Timeout int32 `gorm:"column:timeout"` + MediaType string `gorm:"column:media_type;type:char(64)"` + PlatformID int32 `gorm:"column:platform_id"` + SessionType int32 `gorm:"column:sesstion_type"` + InitiateTime time.Time `gorm:"column:initiate_time"` + EndTime time.Time `gorm:"column:end_time"` + FileURL string `gorm:"column:file_url" json:"-"` + + Title string `gorm:"column:title;size:128"` + Desc string `gorm:"column:desc;size:1024"` + Ex string `gorm:"column:ex;size:1024"` + IOSPushSound string `gorm:"column:ios_push_sound"` + IOSBadgeCount bool `gorm:"column:ios_badge_count"` + SignalInfo string `gorm:"column:signal_info;size:1024"` +} + +func (SignalModel) TableName() string { + return "signal" +} + +type SignalInvitationModel struct { + UserID string `gorm:"column:user_id;primary_key"` + SID string `gorm:"column:sid;type:char(128);primary_key"` + Status int32 `gorm:"column:status"` + InitiateTime time.Time `gorm:"column:initiate_time;primary_key"` + HandleTime time.Time `gorm:"column:handle_time"` +} + +func (SignalInvitationModel) TableName() string { + return "signal_invitation" +} diff --git a/tools/up35/pkg/pkg.go b/tools/up35/pkg/pkg.go new file mode 100644 index 000000000..d834b8492 --- /dev/null +++ b/tools/up35/pkg/pkg.go @@ -0,0 +1,206 @@ +package pkg + +import ( + "context" + "errors" + "fmt" + "gopkg.in/yaml.v3" + "log" + "os" + "reflect" + "strconv" + + "github.com/go-sql-driver/mysql" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + gormMysql "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" + + "github.com/openimsdk/open-im-server/v3/pkg/common/config" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" + rtcMgo "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/mgo" +) + +const ( + versionTable = "dataver" + versionKey = "data_version" + versionValue = 35 +) + +func InitConfig(path string) error { + data, err := os.ReadFile(path) + if err != nil { + return err + } + return yaml.Unmarshal(data, &config.Config) +} + +func GetMysql() (*gorm.DB, error) { + conf := config.Config.Mysql + mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database) + return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard}) +} + +func GetMongo() (*mongo.Database, error) { + mgo, err := unrelation.NewMongo() + if err != nil { + return nil, err + } + return mgo.GetDatabase(), nil +} + +func Main(path string) error { + if err := InitConfig(path); err != nil { + return err + } + if config.Config.Mysql == nil { + return nil + } + mongoDB, err := GetMongo() + if err != nil { + return err + } + var version struct { + Key string `bson:"key"` + Value string `bson:"value"` + } + switch mongoDB.Collection(versionTable).FindOne(context.Background(), bson.M{"key": versionKey}).Decode(&version) { + case nil: + if ver, _ := strconv.Atoi(version.Value); ver >= versionValue { + return nil + } + case mongo.ErrNoDocuments: + default: + return err + } + mysqlDB, err := GetMysql() + if err != nil { + if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1049 { + if err := SetMongoDataVersion(mongoDB, version.Value); err != nil { + return err + } + return nil // database not exist + } + return err + } + + var c convert + var tasks []func() error + tasks = append(tasks, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewUserMongo, c.User) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendMongo, c.Friend) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendRequestMongo, c.FriendRequest) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewBlackMongo, c.Black) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMongo, c.Group) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMember, c.GroupMember) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupRequestMgo, c.GroupRequest) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewConversationMongo, c.Conversation) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) }, + + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewSignal, c.SignalModel) }, + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewSignalInvitation, c.SignalInvitationModel) }, + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeeting, c.Meeting) }, + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeetingInvitation, c.MeetingInvitationInfo) }, + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeetingRecord, c.MeetingVideoRecord) }, + ) + + for _, task := range tasks { + if err := task(); err != nil { + return err + } + } + + if err := SetMongoDataVersion(mongoDB, version.Value); err != nil { + return err + } + return nil +} + +func SetMongoDataVersion(db *mongo.Database, curver string) error { + filter := bson.M{"key": versionKey, "value": curver} + update := bson.M{"$set": bson.M{"key": versionKey, "value": strconv.Itoa(versionValue)}} + _, err := db.Collection(versionTable).UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true)) + return err +} + +// NewTask A mysql table B mongodb model C mongodb table +func NewTask[A interface{ TableName() string }, B any, C any](gormDB *gorm.DB, mongoDB *mongo.Database, mongoDBInit func(db *mongo.Database) (B, error), convert func(v A) C) error { + obj, err := mongoDBInit(mongoDB) + if err != nil { + return err + } + var zero A + tableName := zero.TableName() + coll, err := getColl(obj) + if err != nil { + return fmt.Errorf("get mongo collection %s failed, err: %w", tableName, err) + } + var count int + defer func() { + log.Printf("completed convert %s total %d\n", tableName, count) + }() + const batch = 100 + for page := 0; ; page++ { + res := make([]A, 0, batch) + if err := gormDB.Limit(batch).Offset(page * batch).Find(&res).Error; err != nil { + if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1146 { + return nil // table not exist + } + return fmt.Errorf("find mysql table %s failed, err: %w", tableName, err) + } + if len(res) == 0 { + return nil + } + temp := make([]any, len(res)) + for i := range res { + temp[i] = convert(res[i]) + } + if err := insertMany(coll, temp); err != nil { + return fmt.Errorf("insert mongo table %s failed, err: %w", tableName, err) + } + count += len(res) + if len(res) < batch { + return nil + } + log.Printf("current convert %s completed %d\n", tableName, count) + } +} + +func insertMany(coll *mongo.Collection, objs []any) error { + if _, err := coll.InsertMany(context.Background(), objs); err != nil { + if !mongo.IsDuplicateKeyError(err) { + return err + } + } + for i := range objs { + _, err := coll.InsertOne(context.Background(), objs[i]) + switch { + case err == nil: + case mongo.IsDuplicateKeyError(err): + default: + return err + } + } + return nil +} + +func getColl(obj any) (_ *mongo.Collection, err error) { + defer func() { + if e := recover(); e != nil { + err = fmt.Errorf("not found %+v", e) + } + }() + stu := reflect.ValueOf(obj).Elem() + typ := reflect.TypeOf(&mongo.Collection{}).String() + for i := 0; i < stu.NumField(); i++ { + field := stu.Field(i) + if field.Type().String() == typ { + return (*mongo.Collection)(field.UnsafePointer()), nil + } + } + return nil, errors.New("not found") +} diff --git a/tools/up35/up35.go b/tools/up35/up35.go index 5d4740fca..0ce56ee13 100644 --- a/tools/up35/up35.go +++ b/tools/up35/up35.go @@ -1,367 +1,19 @@ package main import ( - "context" - "errors" "flag" - "fmt" - "github.com/go-sql-driver/mysql" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" - mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" - mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "gopkg.in/yaml.v3" - gormMysql "gorm.io/driver/mysql" - "gorm.io/gorm" - "gorm.io/gorm/logger" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg" "log" "os" - "reflect" - "strconv" -) - -const ( - versionTable = "dataver" - versionKey = "data_version" - versionValue = 35 ) func main() { var path string flag.StringVar(&path, "c", "", "path config file") flag.Parse() - if err := Main(path); err != nil { + if err := pkg.Main(path); err != nil { log.Fatal(err) return } os.Exit(0) } - -func InitConfig(path string) error { - data, err := os.ReadFile(path) - if err != nil { - return err - } - return yaml.Unmarshal(data, &config.Config) -} - -func GetMysql() (*gorm.DB, error) { - conf := config.Config.Mysql - mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database) - return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard}) -} - -func GetMongo() (*mongo.Database, error) { - mgo, err := unrelation.NewMongo() - if err != nil { - return nil, err - } - return mgo.GetDatabase(), nil -} - -func Main(path string) error { - if err := InitConfig(path); err != nil { - return err - } - if config.Config.Mysql == nil { - return nil - } - mongoDB, err := GetMongo() - if err != nil { - return err - } - var version struct { - Key string `bson:"key"` - Value string `bson:"value"` - } - switch mongoDB.Collection(versionTable).FindOne(context.Background(), bson.M{"key": versionKey}).Decode(&version) { - case nil: - if ver, _ := strconv.Atoi(version.Value); ver >= versionValue { - return nil - } - case mongo.ErrNoDocuments: - default: - return err - } - mysqlDB, err := GetMysql() - if err != nil { - if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1049 { - if err := SetMongoDataVersion(mongoDB, version.Value); err != nil { - return err - } - return nil // database not exist - } - return err - } - - var c convert - var tasks []func() error - tasks = append(tasks, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewUserMongo, c.User) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendMongo, c.Friend) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendRequestMongo, c.FriendRequest) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewBlackMongo, c.Black) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMongo, c.Group) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMember, c.GroupMember) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupRequestMgo, c.GroupRequest) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewConversationMongo, c.Conversation) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) }, - ) - - for _, task := range tasks { - if err := task(); err != nil { - return err - } - } - - if err := SetMongoDataVersion(mongoDB, version.Value); err != nil { - return err - } - return nil -} - -func SetMongoDataVersion(db *mongo.Database, curver string) error { - filter := bson.M{"key": versionKey, "value": curver} - update := bson.M{"$set": bson.M{"key": versionKey, "value": strconv.Itoa(versionValue)}} - _, err := db.Collection(versionTable).UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true)) - return err -} - -// NewTask A mysql table B mongodb model C mongodb table -func NewTask[A interface{ TableName() string }, B any, C any](gormDB *gorm.DB, mongoDB *mongo.Database, mongoDBInit func(db *mongo.Database) (B, error), convert func(v A) C) error { - obj, err := mongoDBInit(mongoDB) - if err != nil { - return err - } - var zero A - tableName := zero.TableName() - coll, err := getColl(obj) - if err != nil { - return fmt.Errorf("get mongo collection %s failed, err: %w", tableName, err) - } - var count int - defer func() { - log.Printf("completed convert %s total %d\n", tableName, count) - }() - const batch = 100 - for page := 0; ; page++ { - res := make([]A, 0, batch) - if err := gormDB.Limit(batch).Offset(page * batch).Find(&res).Error; err != nil { - if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1146 { - return nil // table not exist - } - return fmt.Errorf("find mysql table %s failed, err: %w", tableName, err) - } - if len(res) == 0 { - return nil - } - temp := make([]any, len(res)) - for i := range res { - temp[i] = convert(res[i]) - } - if err := insertMany(coll, temp); err != nil { - return fmt.Errorf("insert mongo table %s failed, err: %w", tableName, err) - } - count += len(res) - if len(res) < batch { - return nil - } - log.Printf("current convert %s completed %d\n", tableName, count) - } -} - -func insertMany(coll *mongo.Collection, objs []any) error { - if _, err := coll.InsertMany(context.Background(), objs); err != nil { - if !mongo.IsDuplicateKeyError(err) { - return err - } - } - for i := range objs { - _, err := coll.InsertOne(context.Background(), objs[i]) - switch { - case err == nil: - case mongo.IsDuplicateKeyError(err): - default: - return err - } - } - return nil -} - -func getColl(obj any) (_ *mongo.Collection, err error) { - defer func() { - if e := recover(); e != nil { - err = fmt.Errorf("not found %+v", e) - } - }() - stu := reflect.ValueOf(obj).Elem() - typ := reflect.TypeOf(&mongo.Collection{}).String() - for i := 0; i < stu.NumField(); i++ { - field := stu.Field(i) - if field.Type().String() == typ { - return (*mongo.Collection)(field.UnsafePointer()), nil - } - } - return nil, errors.New("not found") -} - -type convert struct{} - -func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel { - return mongoModel.UserModel{ - UserID: v.UserID, - Nickname: v.Nickname, - FaceURL: v.FaceURL, - Ex: v.Ex, - AppMangerLevel: v.AppMangerLevel, - GlobalRecvMsgOpt: v.GlobalRecvMsgOpt, - CreateTime: v.CreateTime, - } -} - -func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel { - return mongoModel.FriendModel{ - OwnerUserID: v.OwnerUserID, - FriendUserID: v.FriendUserID, - Remark: v.Remark, - CreateTime: v.CreateTime, - AddSource: v.AddSource, - OperatorUserID: v.OperatorUserID, - Ex: v.Ex, - } -} - -func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel { - return mongoModel.FriendRequestModel{ - FromUserID: v.FromUserID, - ToUserID: v.ToUserID, - HandleResult: v.HandleResult, - ReqMsg: v.ReqMsg, - CreateTime: v.CreateTime, - HandlerUserID: v.HandlerUserID, - HandleMsg: v.HandleMsg, - HandleTime: v.HandleTime, - Ex: v.Ex, - } -} - -func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel { - return mongoModel.BlackModel{ - OwnerUserID: v.OwnerUserID, - BlockUserID: v.BlockUserID, - CreateTime: v.CreateTime, - AddSource: v.AddSource, - OperatorUserID: v.OperatorUserID, - Ex: v.Ex, - } -} - -func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel { - return mongoModel.GroupModel{ - GroupID: v.GroupID, - GroupName: v.GroupName, - Notification: v.Notification, - Introduction: v.Introduction, - FaceURL: v.FaceURL, - CreateTime: v.CreateTime, - Ex: v.Ex, - Status: v.Status, - CreatorUserID: v.CreatorUserID, - GroupType: v.GroupType, - NeedVerification: v.NeedVerification, - LookMemberInfo: v.LookMemberInfo, - ApplyMemberFriend: v.ApplyMemberFriend, - NotificationUpdateTime: v.NotificationUpdateTime, - NotificationUserID: v.NotificationUserID, - } -} - -func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel { - return mongoModel.GroupMemberModel{ - GroupID: v.GroupID, - UserID: v.UserID, - Nickname: v.Nickname, - FaceURL: v.FaceURL, - RoleLevel: v.RoleLevel, - JoinTime: v.JoinTime, - JoinSource: v.JoinSource, - InviterUserID: v.InviterUserID, - OperatorUserID: v.OperatorUserID, - MuteEndTime: v.MuteEndTime, - Ex: v.Ex, - } -} - -func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel { - return mongoModel.GroupRequestModel{ - UserID: v.UserID, - GroupID: v.GroupID, - HandleResult: v.HandleResult, - ReqMsg: v.ReqMsg, - HandledMsg: v.HandledMsg, - ReqTime: v.ReqTime, - HandleUserID: v.HandleUserID, - HandledTime: v.HandledTime, - JoinSource: v.JoinSource, - InviterUserID: v.InviterUserID, - Ex: v.Ex, - } -} - -func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel { - return mongoModel.ConversationModel{ - OwnerUserID: v.OwnerUserID, - ConversationID: v.ConversationID, - ConversationType: v.ConversationType, - UserID: v.UserID, - GroupID: v.GroupID, - RecvMsgOpt: v.RecvMsgOpt, - IsPinned: v.IsPinned, - IsPrivateChat: v.IsPrivateChat, - BurnDuration: v.BurnDuration, - GroupAtType: v.GroupAtType, - AttachedInfo: v.AttachedInfo, - Ex: v.Ex, - MaxSeq: v.MaxSeq, - MinSeq: v.MinSeq, - CreateTime: v.CreateTime, - IsMsgDestruct: v.IsMsgDestruct, - MsgDestructTime: v.MsgDestructTime, - LatestMsgDestructTime: v.LatestMsgDestructTime, - } -} - -func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel { - return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel { - return mongoModel.ObjectModel{ - Name: v.Name, - UserID: v.UserID, - Hash: v.Hash, - Engine: engine, - Key: v.Key, - Size: v.Size, - ContentType: v.ContentType, - Group: v.Cause, - CreateTime: v.CreateTime, - } - } -} - -func (convert) Log(v mysqlModel.Log) mongoModel.LogModel { - return mongoModel.LogModel{ - LogID: v.LogID, - Platform: v.Platform, - UserID: v.UserID, - CreateTime: v.CreateTime, - Url: v.Url, - FileName: v.FileName, - SystemType: v.SystemType, - Version: v.Version, - Ex: v.Ex, - } -} From bb4463349e5ae3759cb96c3ac80b16597f1eae3a Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Tue, 12 Dec 2023 16:44:02 +0800 Subject: [PATCH 03/31] feat: add openim docker compose and env (#1550) * feat: add openim docker compose Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: add openim env Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: add openim env Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: add openim fix env Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> --------- Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> --- config/templates/README.md | 36 ++ config/templates/alertmanager.yml.template | 33 ++ config/templates/config.yaml.template | 506 +++++++++++++++++++++ config/templates/env.template | 249 ++++++++++ config/templates/prometheus.yml.template | 85 ++++ deployments/templates/env-template.yaml | 23 +- docker-compose.yml | 118 +++-- docs/contrib/util-makefile.md | 2 +- scripts/init-config.sh | 167 +++++-- 9 files changed, 1093 insertions(+), 126 deletions(-) create mode 100644 config/templates/README.md create mode 100644 config/templates/alertmanager.yml.template create mode 100644 config/templates/config.yaml.template create mode 100644 config/templates/env.template create mode 100644 config/templates/prometheus.yml.template diff --git a/config/templates/README.md b/config/templates/README.md new file mode 100644 index 000000000..6a979c6bb --- /dev/null +++ b/config/templates/README.md @@ -0,0 +1,36 @@ +# Examples Directory + +Welcome to the `examples` directory of our project! This directory contains a collection of example files that demonstrate various configurations and setups for our software. These examples are designed to provide you with templates that can be used as a starting point for your own configurations. + +## Overview + +In this directory, you'll find examples for a variety of use cases. Each file is a template with default values and configurations that illustrate best practices and typical scenarios. Whether you're just getting started or looking to implement a complex setup, these examples should help you get on the right track. + +## Structure + +Here's a quick overview of what you'll find in this directory: + ++ `env-example.yaml`: Demonstrates how to set up environment variables. ++ `openim-example.yaml`: A sample configuration file for the OpenIM application. ++ `prometheus-example.yml`: An example Prometheus configuration for monitoring. ++ `alertmanager-example.yml`: A template for setting up Alertmanager configurations. + +## How to Use These Examples + +To use these examples, simply copy the relevant file to your working directory and rename it as needed (e.g., removing the `-example` suffix). Then, modify the file according to your requirements. + +### Tips for Using Example Files: + +1. **Read the Comments**: Each file contains comments that explain various sections and settings. Make sure to read these comments for a better understanding of how to customize the file. +2. **Check for Required Changes**: Some examples might require mandatory changes (like setting specific environment variables) before they can be used effectively. +3. **Version Compatibility**: Ensure that the example files are compatible with the version of the software you are using. + +## Contributing + +If you have a configuration that you believe would be beneficial to others, please feel free to contribute by opening a pull request with your proposed changes. We appreciate contributions that expand our examples with new scenarios and use cases. + +## Support + +If you encounter any issues or have questions regarding the example files, please open an issue on our repository. Our community is here to help you navigate through any challenges you might face. + +Thank you for exploring our examples, and we hope they will be helpful in setting up and configuring your environment! diff --git a/config/templates/alertmanager.yml.template b/config/templates/alertmanager.yml.template new file mode 100644 index 000000000..da5f99b19 --- /dev/null +++ b/config/templates/alertmanager.yml.template @@ -0,0 +1,33 @@ +###################### AlertManager Configuration ###################### +# AlertManager configuration using environment variables +# +# Resolve timeout +# SMTP configuration for sending alerts +# Templates for email notifications +# Routing configurations for alerts +# Receiver configurations +global: + resolve_timeout: 5m + smtp_from: alert@openim.io + smtp_smarthost: smtp.163.com:465 + smtp_auth_username: alert@openim.io + smtp_auth_password: YOURAUTHPASSWORD + smtp_require_tls: false + smtp_hello: xxx监控告警 + +templates: + - /etc/alertmanager/email.tmpl + +route: + group_by: ['alertname'] + group_wait: 5s + group_interval: 5s + repeat_interval: 5m + receiver: email +receivers: + - name: email + email_configs: + - to: 'alert@example.com' + html: '{{ template "email.to.html" . }}' + headers: { Subject: "[OPENIM-SERVER]Alarm" } + send_resolved: true diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template new file mode 100644 index 000000000..a35d06c8c --- /dev/null +++ b/config/templates/config.yaml.template @@ -0,0 +1,506 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the License); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ----------------------------------------------------------------- +# TODO: This config file is the template file +# --| source: deployments/templates/openim.yaml +# --| env: scripts/install/environment +# --| target: config/config.yaml +# ----------------------------------------------------------------- + +envs: + discovery: zookeeper + +###################### Zookeeper ###################### +# Zookeeper configuration +# It's not recommended to modify the schema +# +# Zookeeper address +# Zookeeper username +# Zookeeper password +zookeeper: + schema: openim + address: [ 172.28.0.1:12181 ] + username: '' + password: '' + +###################### Mongo ###################### +# MongoDB configuration +# If uri is not empty, it will be used directly +# +# MongoDB address for standalone setup, Mongos address for sharded cluster setup +# Default MongoDB database name +# Maximum connection pool size +mongo: + uri: '' + address: [ 172.28.0.1:37017 ] + database: openIM_v3 + username: root + password: openIM123 + maxPoolSize: 100 + +###################### Redis configuration information ###################### +# Redis configuration +# +# Username is required only for Redis version 6.0+ +redis: + address: [ 172.28.0.1:16379 ] + username: '' + password: openIM123 + +###################### Kafka configuration information ###################### +# Kafka configuration +# +# Kafka username +# Kafka password +# It's not recommended to modify this topic name +# Consumer group ID, it's not recommended to modify +kafka: + username: '' + password: '' + addr: [ 172.28.0.1:19094 ] + latestMsgToRedis: + topic: "latestMsgToRedis" + offlineMsgToMongo: + topic: "offlineMsgToMongoMysql" + msgToPush: + topic: "msgToPush" + consumerGroupID: + msgToRedis: redis + msgToMongo: mongo + msgToMySql: mysql + msgToPush: push + +###################### RPC configuration information ###################### +# RPC configuration +# +# IP address to register with zookeeper when starting RPC, the IP and corresponding rpcPort should be accessible by api/gateway +# Default listen IP is 0.0.0.0 +rpc: + registerIP: '' + listenIP: 0.0.0.0 + +###################### API configuration information ###################### +# API configuration +# +# API service port +# Default listen IP is 0.0.0.0 +api: + openImApiPort: [ 10002 ] + listenIP: 0.0.0.0 + +###################### Object configuration information ###################### +# Object storage configuration +# +# Use minio for object storage +# API URL should be accessible by the app +# It's not recommended to modify the bucket name +# Endpoint should be accessible by the app +# Session token +# Configuration for Tencent COS +# Configuration for Aliyun OSS +# apiURL is the address of the api, the access address of the app, use s3 must be configured +# minio.endpoint can be configured as an intranet address, +# minio.signEndpoint is minio public network address +object: + enable: "minio" + apiURL: "http://172.28.0.1:10002" + minio: + bucket: "openim" + endpoint: "http://172.28.0.1:10005" + accessKeyID: "root" + secretAccessKey: "openIM123" + sessionToken: '' + signEndpoint: "http://172.28.0.1:10005" + publicRead: false + cos: + bucketURL: https://temp-1252357374.cos.ap-chengdu.myqcloud.com + secretID: '' + secretKey: '' + sessionToken: '' + publicRead: false + oss: + endpoint: "https://oss-cn-chengdu.aliyuncs.com" + bucket: "demo-9999999" + bucketURL: "https://demo-9999999.oss-cn-chengdu.aliyuncs.com" + accessKeyID: '' + accessKeySecret: '' + sessionToken: '' + publicRead: false + kodo: + endpoint: "http://s3.cn-east-1.qiniucs.com" + bucket: "demo-9999999" + bucketURL: "http://your.domain.com" + accessKeyID: '' + accessKeySecret: '' + sessionToken: '' + publicRead: false + +###################### RPC Port Configuration ###################### +# RPC service ports +# These ports are passed into the program by the script and are not recommended to modify +# For launching multiple programs, just fill in multiple ports separated by commas +# For example, [10110, 10111] +rpcPort: + openImUserPort: [ 10110 ] + openImFriendPort: [ 10120 ] + openImMessagePort: [ 10130 ] + openImGroupPort: [ 10150 ] + openImAuthPort: [ 10160 ] + openImPushPort: [ 10170 ] + openImConversationPort: [ 10180 ] + openImThirdPort: [ 10190 ] + +###################### RPC Register Name Configuration ###################### +# RPC service names for registration, it's not recommended to modify these +rpcRegisterName: + openImUserName: User + openImFriendName: Friend + openImMsgName: Msg + openImPushName: Push + openImMessageGatewayName: MessageGateway + openImGroupName: Group + openImAuthName: Auth + openImConversationName: Conversation + openImThirdName: Third + +###################### Log Configuration ###################### +# Log configuration +# +# Storage directory +# Log rotation time +# Maximum number of logs to retain +# Log level, 6 means all levels +# Whether to output to stdout +# Whether to output in json format +# Whether to include stack trace in logs +log: + storageLocation: ../logs/ + rotationTime: 24 + remainRotationCount: 2 + remainLogLevel: 6 + isStdout: false + isJson: false + withStack: false + +###################### Variables definition ###################### +# Long connection server configuration +# +# Websocket port for msg_gateway +# Maximum number of websocket connections +# Maximum length of websocket request package +# Websocket connection handshake timeout +longConnSvr: + openImWsPort: [ 10001 ] + websocketMaxConnNum: 100000 + openImMessageGatewayPort: [ 10140 ] + websocketMaxMsgLen: 4096 + websocketTimeout: 10 + +# Push notification service configuration +# +# Use GeTui for push notifications +# GeTui offline push configuration +# FCM offline push configuration +# Account file, place it in the config directory +# JPush configuration, modify these after applying in JPush backend +push: + enable: getui + geTui: + pushUrl: "https://restapi.getui.com/v2/$appId" + masterSecret: '' + appKey: '' + intent: '' + channelID: '' + channelName: '' + fcm: + serviceAccount: "x.json" + jpns: + appKey: '' + masterSecret: '' + pushUrl: '' + pushIntent: '' + +# App manager configuration +# +# Built-in app manager user IDs +# Built-in app manager nicknames +manager: + userID: [ "openIM123456", "openIM654321", "openIMAdmin" ] + nickname: [ "system1", "system2", "system3" ] + +# Multi-platform login policy +# For each platform(Android, iOS, Windows, Mac, web), only one can be online at a time +multiLoginPolicy: 1 + +# Whether to store messages in MySQL, messages in MySQL are only used for management background +chatPersistenceMysql: true + +# Message cache timeout in seconds, it's not recommended to modify +msgCacheTimeout: 86400 + +# Whether to enable read receipts for group chat +groupMessageHasReadReceiptEnable: true + +# Whether to enable read receipts for single chat +singleMessageHasReadReceiptEnable: true + +# MongoDB offline message retention period in days +retainChatRecords: 365 + +# Schedule to clear expired messages(older than retainChatRecords days) in MongoDB every Wednesday at 2am +# This deletion is just for cleaning up disk usage according to previous configuration retainChatRecords, no notification will be sent +chatRecordsClearTime: "0 2 * * 3" + +# Schedule to auto delete messages every day at 2am +# This deletion is for messages that have been retained for more than msg_destruct_time (seconds) in the conversation field +msgDestructTime: "0 2 * * *" + +# Secret key +secret: openIM123 + +# Token policy +# +# Token expiration period in days +tokenPolicy: + expire: 90 + +# Message verification policy +# +# Whether to verify friendship when sending messages +messageVerify: + friendVerify: false + +# iOS push notification configuration +# +# iOS push notification sound +# Whether to count badge +# Whether it's production environment +iosPush: + pushSound: "xxx" + badgeCount: true + production: false + +###################### Third-party service configuration ###################### +# Callback configuration +# +# Callback URL +# Whether to enable this callback event +# Timeout in seconds +# Whether to continue execution if callback fails +callback: + url: "" + beforeSendSingleMsg: + enable: false + timeout: 5 + failedContinue: true + afterSendSingleMsg: + enable: false + timeout: 5 + failedContinue: true + beforeSendGroupMsg: + enable: false + timeout: 5 + failedContinue: true + afterSendGroupMsg: + enable: false + timeout: 5 + failedContinue: true + msgModify: + enable: false + timeout: 5 + failedContinue: true + userOnline: + enable: false + timeout: 5 + failedContinue: true + userOffline: + enable: false + timeout: 5 + failedContinue: true + userKickOff: + enable: false + timeout: 5 + failedContinue: true + offlinePush: + enable: false + timeout: 5 + failedContinue: true + onlinePush: + enable: false + timeout: 5 + failedContinue: true + superGroupOnlinePush: + enable: false + timeout: 5 + failedContinue: true + beforeAddFriend: + enable: false + timeout: 5 + failedContinue: true + beforeUpdateUserInfo: + enable: false + timeout: 5 + failedContinue: true + beforeCreateGroup: + enable: false + timeout: 5 + failedContinue: true + afterCreateGroup: + enable: false + timeout: 5 + failedContinue: true + beforeMemberJoinGroup: + enable: false + timeout: 5 + failedContinue: true + beforeSetGroupMemberInfo: + enable: false + timeout: 5 + failedContinue: true + afterSetGroupMemberInfo: + enable: false + timeout: 5 + failedContinue: true + setMessageReactionExtensions: + enable: false + timeout: 5 + failedContinue: true + quitGroup: + enable: false + timeout: 5 + failedContinue: true + killGroupMember: + enable: false + timeout: 5 + failedContinue: true + dismissGroup: + enable: false + timeout: 5 + failedContinue: true + joinGroup: + enable: false + timeout: 5 + failedContinue: true + groupMsgRead: + enable: false + timeout: 5 + failedContinue: true + singleMsgRead: + enable: false + timeout: 5 + failedContinue: true + updateUserInfo: + enable: false + timeout: 5 + failedContinue: true + beforeUserRegister: + enable: false + timeout: 5 + failedContinue: true + afterUserRegister: + enable: false + timeout: 5 + failedContinue: true + transferGroupOwner: + enable: false + timeout: 5 + failedContinue: true + beforeSetFriendRemark: + enable: false + timeout: 5 + failedContinue: true + afterSetFriendRemark: + enable: false + timeout: 5 + failedContinue: true + afterGroupMsgRead: + enable: false + timeout: 5 + failedContinue: true + afterGroupMsgRevoke: + enable: false + timeout: 5 + failedContinue: true + afterJoinGroup: + enable: false + timeout: 5 + failedContinue: true + beforeInviteUserToGroup: + enable: false + timeout: 5 + failedContinue: true + joinGroupAfter: + enable: false + timeout: 5 + failedContinue: true + setGroupInfoAfter: + enable: false + timeout: 5 + failedContinue: true + setGroupInfoBefore: + enable: false + timeout: 5 + failedContinue: true + revokeMsgAfter: + enable: false + timeout: 5 + failedContinue: true + addBlackBefore: + enable: false + timeout: 5 + failedContinue: true + addFriendAfter: + enable: false + timeout: 5 + failedContinue: true + addFriendAgreeBefore: + enable: false + timeout: 5 + failedContinue: true + deleteFriendAfter: + enable: false + timeout: 5 + failedContinue: true + importFriendsBefore: + enable: false + timeout: 5 + failedContinue: true + importFriendsAfter: + enable: false + timeout: 5 + failedContinue: true + removeBlackAfter: + enable: false + timeout: 5 + failedContinue: true +###################### Prometheus ###################### +# Prometheus configuration for various services +# The number of Prometheus ports per service needs to correspond to rpcPort +# The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh +prometheus: + enable: false + prometheusUrl: 172.28.0.1:13000 + apiPrometheusPort: [20100] + userPrometheusPort: [ 20110 ] + friendPrometheusPort: [ 20120 ] + messagePrometheusPort: [ 20130 ] + messageGatewayPrometheusPort: [ 20140 ] + groupPrometheusPort: [ 20150 ] + authPrometheusPort: [ 20160 ] + pushPrometheusPort: [ 20170 ] + conversationPrometheusPort: [ 20230 ] + rtcPrometheusPort: [ 21300 ] + thirdPrometheusPort: [ 21301 ] + messageTransferPrometheusPort: [ 21400, 21401, 21402, 21403 ] # List of ports diff --git a/config/templates/env.template b/config/templates/env.template new file mode 100644 index 000000000..e47a9c073 --- /dev/null +++ b/config/templates/env.template @@ -0,0 +1,249 @@ +# ====================================== +# ========= Basic Configuration ======== +# ====================================== + +# The user for authentication or system operations. +# Default: OPENIM_USER=root +USER=root + +# Password associated with the specified user for authentication. +# Default: PASSWORD=openIM123 +PASSWORD=openIM123 + +# Endpoint for the MinIO object storage service. +# Default: MINIO_ENDPOINT=http://172.28.0.1:10005 +MINIO_ENDPOINT=http://172.28.0.1:10005 + +# Base URL for the application programming interface (API). +# Default: API_URL=http://172.28.0.1:10002 +API_URL=http://172.28.0.1:10002 + +# Directory path for storing data files or related information. +# Default: DATA_DIR=./ +DATA_DIR=./ + +# Choose the appropriate image address, the default is GITHUB image, +# you can choose docker hub, for Chinese users can choose Ali Cloud +# export IMAGE_REGISTRY="ghcr.io/openimsdk" +# export IMAGE_REGISTRY="openim" +# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk" +IMAGE_REGISTRY=ghcr.io/openimsdk + +# ====================================== +# ========= Network Configuration ====== +# ====================================== + +# Subnet for the Docker network. +# Default: DOCKER_BRIDGE_SUBNET=172.28.0.0/16 +DOCKER_BRIDGE_SUBNET=172.28.0.0/16 + +# Gateway for the Docker network. +# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1 +DOCKER_BRIDGE_GATEWAY=172.28.0.1 + +MONGO_NETWORK_ADDRESS=172.28.0.2 +REDIS_NETWORK_ADDRESS=172.28.0.3 +KAFKA_NETWORK_ADDRESS=172.28.0.4 +ZOOKEEPER_NETWORK_ADDRESS=172.28.0.5 +MINIO_NETWORK_ADDRESS=172.28.0.6 +OPENIM_WEB_NETWORK_ADDRESS=172.28.0.7 +OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.8 +OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.9 +PROMETHEUS_NETWORK_ADDRESS=172.28.0.10 +GRAFANA_NETWORK_ADDRESS=172.28.0.11 +NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.12 +OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=172.28.0.13 +ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14 + +# =============================================== +# = Component Extension Configuration = +# =============================================== + +# ============ Component Extension Configuration ========== +# ----- ZooKeeper Configuration ----- +# Address or hostname for the ZooKeeper service. +# Default: ZOOKEEPER_ADDRESS=172.28.0.1 +ZOOKEEPER_ADDRESS=172.28.0.5 + +# Port for ZooKeeper service. +# Default: ZOOKEEPER_PORT=12181 +ZOOKEEPER_PORT=12181 + +# ----- MongoDB Configuration ----- +# Address or hostname for the MongoDB service. +# Default: MONGO_ADDRESS=172.28.0.1 +MONGO_ADDRESS=172.28.0.2 + +# Port on which MongoDB service is running. +# Default: MONGO_PORT=37017 +# MONGO_PORT=37017 + +# Username to authenticate with the MongoDB service. +# Default: MONGO_USERNAME=root +# MONGO_USERNAME=root + +# Password to authenticate with the MongoDB service. +# Default: MONGO_PASSWORD=openIM123 +MONGO_PASSWORD=openIM123 + +# Name of the database in MongoDB to be used. +# Default: MONGO_DATABASE=openIM_v3 +MONGO_DATABASE=openIM_v3 + +# ----- Redis Configuration ----- +# Address or hostname for the Redis service. +# Default: REDIS_ADDRESS=172.28.0.1 +REDIS_ADDRESS=172.28.0.3 + +# Port on which Redis in-memory data structure store is running. +# Default: REDIS_PORT=16379 +REDIS_PORT=16379 + +# Password to authenticate with the Redis service. +# Default: REDIS_PASSWORD=openIM123 +REDIS_PASSWORD=openIM123 + +# ----- Kafka Configuration ----- +# Address or hostname for the Kafka service. +# Default: KAFKA_ADDRESS=172.28.0.1 +KAFKA_ADDRESS=172.28.0.4 + +# Kakfa username to authenticate with the Kafka service. +# KAFKA_USERNAME='' + +# Port on which Kafka distributed streaming platform is running. +# Default: KAFKA_PORT=19092 +KAFKA_PORT=19094 + +# Topic in Kafka for storing the latest messages in Redis. +# Default: KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis +KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis + +# Topic in Kafka for pushing messages (e.g. notifications or updates). +# Default: KAFKA_MSG_PUSH_TOPIC=msgToPush +KAFKA_MSG_PUSH_TOPIC=msgToPush + +# Topic in Kafka for storing offline messages in MongoDB. +# Default: KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql +KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql + +# ----- MinIO Configuration ---- +# Address or hostname for the MinIO object storage service. +# Default: MINIO_ADDRESS=172.28.0.1 +MINIO_ADDRESS=172.28.0.6 + +# Port on which MinIO object storage service is running. +# Default: MINIO_PORT=10005 +MINIO_PORT=10005 + +# Access key to authenticate with the MinIO service. +# Default: MINIO_ACCESS_KEY=root +# MINIO_ACCESS_KEY=root + +# Secret key corresponding to the access key for MinIO authentication. +# Default: MINIO_SECRET_KEY=openIM123 +MINIO_SECRET_KEY=openIM123 + +# ----- Prometheus Configuration ----- +# Address or hostname for the Prometheus service. +# Default: PROMETHEUS_ADDRESS=172.28.0.1 +PROMETHEUS_ADDRESS=172.28.0.10 + +# Port on which Prometheus service is running. +# Default: PROMETHEUS_PORT=19090 +PROMETHEUS_PORT=19090 + +# ----- Grafana Configuration ----- +# Address or hostname for the Grafana service. +# Default: GRAFANA_ADDRESS=172.28.0.1 +GRAFANA_ADDRESS=172.28.0.11 + +# Port on which Grafana service is running. +# Default: GRAFANA_PORT=13000 +GRAFANA_PORT=13000 + +# ====================================== +# ============ OpenIM Web =============== +# ====================================== + +# Path to the OpenIM web distribution. +# Default: OPENIM_WEB_DIST_PATH=/app/dist +OPENIM_WEB_DIST_PATH=/app/dist + +# Port on which OpenIM web service is running. +# Default: OPENIM_WEB_PORT=11001 +OPENIM_WEB_PORT=11001 + +# Address or hostname for the OpenIM web service. +# Default: OPENIM_WEB_ADDRESS=172.28.0.1 +OPENIM_WEB_ADDRESS=172.28.0.7 + +# ====================================== +# ========= OpenIM Server ============== +# ====================================== + +# Address or hostname for the OpenIM server. +# Default: OPENIM_SERVER_ADDRESS=172.28.0.1 +OPENIM_SERVER_ADDRESS=172.28.0.8 + +# Port for the OpenIM WebSockets. +# Default: OPENIM_WS_PORT=10001 +OPENIM_WS_PORT=10001 + +# Port for the OpenIM API. +# Default: API_OPENIM_PORT=10002 +API_OPENIM_PORT=10002 + + +# ====================================== +# ========== OpenIM Chat =============== +# ====================================== + +# Branch name for OpenIM chat. +# Default: CHAT_BRANCH=main +CHAT_BRANCH=main + +# Address or hostname for the OpenIM chat service. +# Default: OPENIM_CHAT_ADDRESS=172.28.0.1 +OPENIM_CHAT_ADDRESS=172.28.0.9 + +# Port for the OpenIM chat API. +# Default: OPENIM_CHAT_API_PORT=10008 +OPENIM_CHAT_API_PORT=10008 + +# Directory path for storing data files or related information for OpenIM chat. +# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main +OPENIM_CHAT_DATA_DIR=./openim-chat/main + + +# ====================================== +# ========== OpenIM Admin ============== +# ====================================== + +# Branch name for OpenIM server. +# Default: SERVER_BRANCH=main +SERVER_BRANCH=main + +# Port for the OpenIM admin API. +# Default: OPENIM_ADMIN_API_PORT=10009 +OPENIM_ADMIN_API_PORT=10009 + +# Port for the node exporter. +# Default: NODE_EXPORTER_PORT=19100 +NODE_EXPORTER_PORT=19100 + +# Port for the prometheus. +# Default: PROMETHEUS_PORT=19090 +PROMETHEUS_PORT=19090 + +# Port for the grafana. +# Default: GRAFANA_PORT=13000 +GRAFANA_PORT=13000 + +# Port for the admin front. +# Default: OPENIM_ADMIN_FRONT_PORT=11002 +OPENIM_ADMIN_FRONT_PORT=11002 + +# Port for the alertmanager. +# Default: ALERT_MANAGER_PORT=19093 +ALERT_MANAGER_PORT=19093 diff --git a/config/templates/prometheus.yml.template b/config/templates/prometheus.yml.template new file mode 100644 index 000000000..7950c5d33 --- /dev/null +++ b/config/templates/prometheus.yml.template @@ -0,0 +1,85 @@ +# my global config +global: + scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. + evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. + # scrape_timeout is set to the global default (10s). + +# Alertmanager configuration +alerting: + alertmanagers: + - static_configs: + - targets: ['172.28.0.1:19093'] + +# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. +rule_files: + - "instance-down-rules.yml" +# - "first_rules.yml" +# - "second_rules.yml" + +# A scrape configuration containing exactly one endpoint to scrape: +# Here it's Prometheus itself. +scrape_configs: + # The job name is added as a label "job='job_name'"" to any timeseries scraped from this config. + # Monitored information captured by prometheus + - job_name: 'node-exporter' + static_configs: + - targets: [ '172.28.0.1:19100' ] + labels: + namespace: 'default' + + # prometheus fetches application services + - job_name: 'openimserver-openim-api' + static_configs: + - targets: [ '172.28.0.1:20100' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-msggateway' + static_configs: + - targets: [ '172.28.0.1:20140' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-msgtransfer' + static_configs: + - targets: [ 172.28.0.1:21400, 172.28.0.1:21401, 172.28.0.1:21402, 172.28.0.1:21403 ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-push' + static_configs: + - targets: [ '172.28.0.1:20170' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-auth' + static_configs: + - targets: [ '172.28.0.1:20160' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-conversation' + static_configs: + - targets: [ '172.28.0.1:20230' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-friend' + static_configs: + - targets: [ '172.28.0.1:20120' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-group' + static_configs: + - targets: [ '172.28.0.1:20150' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-msg' + static_configs: + - targets: [ '172.28.0.1:20130' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-third' + static_configs: + - targets: [ '172.28.0.1:21301' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-user' + static_configs: + - targets: [ '172.28.0.1:20110' ] + labels: + namespace: 'default' diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml index 4db838c8e..b62543aba 100644 --- a/deployments/templates/env-template.yaml +++ b/deployments/templates/env-template.yaml @@ -1,17 +1,3 @@ -# Copyright © 2023 OpenIM. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # ====================================== # ========= Basic Configuration ======== # ====================================== @@ -90,11 +76,11 @@ MONGO_ADDRESS=${MONGO_NETWORK_ADDRESS} # Port on which MongoDB service is running. # Default: MONGO_PORT=37017 -MONGO_PORT=${MONGO_PORT} +# MONGO_PORT=${MONGO_PORT} # Username to authenticate with the MongoDB service. # Default: MONGO_USERNAME=root -MONGO_USERNAME=${MONGO_USERNAME} +# MONGO_USERNAME=${MONGO_USERNAME} # Password to authenticate with the MongoDB service. # Default: MONGO_PASSWORD=openIM123 @@ -122,6 +108,9 @@ REDIS_PASSWORD=${REDIS_PASSWORD} # Default: KAFKA_ADDRESS=172.28.0.1 KAFKA_ADDRESS=${KAFKA_NETWORK_ADDRESS} +# Kakfa username to authenticate with the Kafka service. +# KAFKA_USERNAME=${KAFKA_USERNAME} + # Port on which Kafka distributed streaming platform is running. # Default: KAFKA_PORT=19092 KAFKA_PORT=${KAFKA_PORT} @@ -149,7 +138,7 @@ MINIO_PORT=${MINIO_PORT} # Access key to authenticate with the MinIO service. # Default: MINIO_ACCESS_KEY=root -MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} +# MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} # Secret key corresponding to the access key for MinIO authentication. # Default: MINIO_SECRET_KEY=openIM123 diff --git a/docker-compose.yml b/docker-compose.yml index 233c8d492..22f57d329 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,55 +7,57 @@ networks: ipam: driver: default config: - - subnet: '${DOCKER_BRIDGE_SUBNET}' - gateway: '${DOCKER_BRIDGE_GATEWAY}' + - subnet: '${DOCKER_BRIDGE_SUBNET:-172.28.0.0/16}' + gateway: '${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}' services: mongodb: - image: mongo:6.0.2 + image: mongo:${MONGODB_IMAGE_VERSION-6.0.2} ports: - - "${MONGO_PORT}:27017" + - "${MONGO_PORT:-37017}:27017" container_name: mongo command: --wiredTigerCacheSizeGB 1 --auth volumes: - - "${DATA_DIR}/components/mongodb/data/db:/data/db" - - "${DATA_DIR}/components/mongodb/data/logs:/data/logs" - - "${DATA_DIR}/components/mongodb/data/conf:/etc/mongo" - - ./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro" + - "${DATA_DIR:-./}/components/mongodb/data/db:/data/db" + - "${DATA_DIR:-./}/components/mongodb/data/logs:/data/logs" + - "${DATA_DIR:-./}/components/mongodb/data/conf:/etc/mongo" + - ./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro environment: - TZ=Asia/Shanghai - wiredTigerCacheSizeGB=1 - - MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME} - - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD} - - MONGO_INITDB_DATABASE=${MONGO_DATABASE} + - MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME:-root} + - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD:-openIM123} + - MONGO_INITDB_DATABASE=${MONGO_DATABASE:-openIM_v3} restart: always networks: server: - ipv4_address: ${MONGO_NETWORK_ADDRESS} + ipv4_address: ${MONGO_NETWORK_ADDRESS:-172.28.0.2} redis: - image: redis:7.0.0 + # image: redis:7.0.0 + image: redis:${REDIS_IMAGE_VERSION:-7.0.0} container_name: redis ports: - - "${REDIS_PORT}:6379" + - "${REDIS_PORT:-16379}:6379" volumes: - - "${DATA_DIR}/components/redis/data:/data" - - "${DATA_DIR}/components/redis/config/redis.conf:/usr/local/redis/config/redis.conf" + - "${DATA_DIR:-./}/components/redis/data:/data" + - "${DATA_DIR:-./}/components/redis/config/redis.conf:/usr/local/redis/config/redis.conf" environment: TZ: Asia/Shanghai restart: always sysctls: net.core.somaxconn: 1024 - command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes + command: redis-server --requirepass ${REDIS_PASSWORD:-openIM123} --appendonly yes networks: server: - ipv4_address: ${REDIS_NETWORK_ADDRESS} + ipv4_address: ${REDIS_NETWORK_ADDRESS:-172.28.0.3} zookeeper: - image: bitnami/zookeeper:3.8 + # image: bitnami/zookeeper:3.8 + image: bitnami/zookeeper:${ZOOKEEPER_IMAGE_VERSION:-3.8} container_name: zookeeper ports: - - "${ZOOKEEPER_PORT}:2181" + - "${ZOOKEEPER_PORT:-12181}:2181" volumes: - "/etc/localtime:/etc/localtime" environment: @@ -64,81 +66,77 @@ services: restart: always networks: server: - ipv4_address: ${ZOOKEEPER_NETWORK_ADDRESS} + ipv4_address: ${ZOOKEEPER_NETWORK_ADDRESS:-172.28.0.5} kafka: - image: 'bitnami/kafka:3.5.1' + # image: 'bitnami/kafka:3.5.1' + image: 'bitnami/kafka:${KAFKA_IMAGE_VERSION:-3.5.1}' container_name: kafka - user: root restart: always + user: ${KAFKA_USER:-root} ports: - - "${KAFKA_PORT}:9094" + - "${KAFKA_PORT:-19094}:9094" volumes: - ./scripts/create-topic.sh:/opt/bitnami/kafka/create-topic.sh - - ${DATA_DIR}/components/kafka:/bitnami/kafka + - "${DATA_DIR:-./}/components/kafka:/bitnami/kafka" command: > - bash -c " - /opt/bitnami/scripts/kafka/run.sh & sleep 5; /opt/bitnami/kafka/create-topic.sh; wait - " + bash -c "/opt/bitnami/scripts/kafka/run.sh & sleep 5; /opt/bitnami/kafka/create-topic.sh; wait" environment: - TZ=Asia/Shanghai - KAFKA_CFG_NODE_ID=0 - KAFKA_CFG_PROCESS_ROLES=controller,broker - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@:9093 - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094 - - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://${DOCKER_BRIDGE_GATEWAY}:${KAFKA_PORT} + - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}:${KAFKA_PORT:-19094} - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER networks: server: - ipv4_address: ${KAFKA_NETWORK_ADDRESS} + ipv4_address: ${KAFKA_NETWORK_ADDRESS:-172.28.0.4} minio: - image: minio/minio + # image: minio/minio + image: minio/minio:${MINIO_IMAGE_VERSION:-latest} ports: - - "${MINIO_PORT}:9000" + - "${MINIO_PORT:-10005}:9000" - "9090:9090" container_name: minio volumes: - - "${DATA_DIR}/components/mnt/data:/data" - - "${DATA_DIR}/components/mnt/config:/root/.minio" + - "${DATA_DIR:-./}/components/mnt/data:/data" + - "${DATA_DIR:-./}/components/mnt/config:/root/.minio" environment: - MINIO_ROOT_USER: "${MINIO_ACCESS_KEY}" - MINIO_ROOT_PASSWORD: "${MINIO_SECRET_KEY}" + MINIO_ROOT_USER: "${MINIO_ACCESS_KEY:-root}" + MINIO_ROOT_PASSWORD: "${MINIO_SECRET_KEY:-openIM123}" restart: always command: minio server /data --console-address ':9090' networks: server: - ipv4_address: ${MINIO_NETWORK_ADDRESS} + ipv4_address: ${MINIO_NETWORK_ADDRESS:-172.28.0.6} openim-web: - # image: ghcr.io/openimsdk/openim-web:latest - # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web:latest - # image: openim/openim-web:latest - image: ${IMAGE_REGISTRY}/openim-web:latest + # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:latest + image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-latest} container_name: openim-web environment: - - OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH} - - OPENIM_WEB_PORT=${OPENIM_WEB_PORT} + - OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH:-/app/dist} + - OPENIM_WEB_PORT=${OPENIM_WEB_PORT:-11001} restart: always ports: - - "${OPENIM_WEB_PORT}:11001" + - "${OPENIM_WEB_PORT:-11001}:11001" networks: server: - ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS} + ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7} + # Uncomment and configure the following services as needed # openim-admin: - # image: ${IMAGE_REGISTRY}/openim-admin-front:v3.4.0 - # # image: ghcr.io/openimsdk/openim-admin-front:v3.4.0 - # # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:v3.4.0 - # # image: openim/openim-admin-front:v3.4.0 + # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0 # container_name: openim-admin # restart: always # ports: - # - "${OPENIM_ADMIN_FRONT_PORT}:80" + # - "${OPENIM_ADMIN_FRONT_PORT:-11002}:80" # networks: # server: - # ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS} + # ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS:-172.28.0.13} # prometheus: # image: prom/prometheus @@ -149,10 +147,10 @@ services: # - ./config/prometheus.yml:/etc/prometheus/prometheus.yml # - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml # ports: - # - "${PROMETHEUS_PORT}:9090" + # - "${PROMETHEUS_PORT:-19090}:9090" # networks: # server: - # ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS} + # ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS:-172.28.0.10} # alertmanager: # image: prom/alertmanager @@ -163,10 +161,10 @@ services: # - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml # - ./config/email.tmpl:/etc/alertmanager/email.tmpl # ports: - # - "${ALERT_MANAGER_PORT}:9093" + # - "${ALERT_MANAGER_PORT:-19093}:9093" # networks: # server: - # ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS} + # ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS:-172.28.0.14} # grafana: # image: grafana/grafana @@ -175,12 +173,12 @@ services: # user: root # restart: always # ports: - # - "${GRAFANA_PORT}:3000" + # - "${GRAFANA_PORT:-13000}:3000" # volumes: - # - ${DATA_DIR}/components/grafana:/var/lib/grafana + # - ${DATA_DIR:-./}/components/grafana:/var/lib/grafana # networks: # server: - # ipv4_address: ${GRAFANA_NETWORK_ADDRESS} + # ipv4_address: ${GRAFANA_NETWORK_ADDRESS:-172.28.0.11} # node-exporter: # image: quay.io/prometheus/node-exporter @@ -188,7 +186,7 @@ services: # hostname: node-exporter # restart: always # ports: - # - "${NODE_EXPORTER_PORT}:9100" + # - "${NODE_EXPORTER_PORT:-19100}:9100" # networks: # server: - # ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS} + # ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS:-172.28.0.12} diff --git a/docs/contrib/util-makefile.md b/docs/contrib/util-makefile.md index e0331f50e..8bde02874 100644 --- a/docs/contrib/util-makefile.md +++ b/docs/contrib/util-makefile.md @@ -30,7 +30,7 @@ Executing `make tools` ensures verification and installation of the default tool - go-junit-report - go-gitlint -The installation path is situated at `/root/workspaces/openim/Open-IM-Server/_output/tools/`. +The installation path is situated at `./_output/tools/`. ## Toolset Categories diff --git a/scripts/init-config.sh b/scripts/init-config.sh index 380239d50..631bd68d7 100755 --- a/scripts/init-config.sh +++ b/scripts/init-config.sh @@ -2,7 +2,7 @@ # Copyright © 2023 OpenIM. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. +# You may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 @@ -13,19 +13,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This script automatically initializes the various configuration files -# Read: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md +# This script automatically initializes various configuration files and can generate example files. set -o errexit set -o nounset set -o pipefail +# Root directory of the OpenIM project OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +# Source initialization script source "${OPENIM_ROOT}/scripts/lib/init.sh" +# Default environment file readonly ENV_FILE=${ENV_FILE:-"${OPENIM_ROOT}/scripts/install/environment.sh"} +# Templates for configuration files declare -A TEMPLATES=( ["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/.env" ["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/config.yaml" @@ -33,22 +36,107 @@ declare -A TEMPLATES=( ["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/alertmanager.yml" ) -openim::log::info "Read more configuration information: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md" +# Templates for example files +declare -A EXAMPLES=( + ["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/config/templates/env.template" + ["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/templates/config.yaml.template" + ["${OPENIM_ROOT}/deployments/templates/prometheus.yml"]="${OPENIM_ROOT}/config/templates/prometheus.yml.template" + ["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/templates/alertmanager.yml.template" +) -# New variables for argument handling +# Command-line options FORCE_OVERWRITE=false SKIP_EXISTING=false +GENERATE_EXAMPLES=false +CLEAN_ENV_EXAMPLES=false -# Function to display help +# Function to display help information show_help() { echo "Usage: $(basename "$0") [options]" echo "Options:" - echo " -h, --help Show this help message" - echo " --force Overwrite existing files without prompt" - echo " --skip Skip generation if file exists" + echo " -h, --help Show this help message" + echo " --force Overwrite existing files without prompt" + echo " --skip Skip generation if file exists" + echo " --examples Generate example files" + echo " --clean-env-examples Generate example files in a clean environment" +} + +# Function to generate configuration files +generate_config_files() { + # Loop through each template in TEMPLATES + for template in "${!TEMPLATES[@]}"; do + # Read the corresponding output files for the template + IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}" + for output_file in "${OUTPUT_FILES[@]}"; do + # Check if the output file already exists + if [[ -f "${output_file}" ]]; then + # Handle existing file based on command-line options + if [[ "${FORCE_OVERWRITE}" == true ]]; then + openim::log::info "Force overwriting ${output_file}." + elif [[ "${SKIP_EXISTING}" == true ]]; then + openim::log::info "Skipping generation of ${output_file} as it already exists." + continue + else + # Ask user for confirmation to overwrite + echo -n "File ${output_file} already exists. Overwrite? (Y/N): " + read -r -n 1 REPLY + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + openim::log::info "Skipping generation of ${output_file}." + continue + fi + fi + fi + + # Process the template file to generate the output file + openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..." + if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then + openim::log::error "genconfig.sh script not found" + exit 1 + fi + "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || { + openim::log::error "Error processing template file ${template}" + exit 1 + } + sleep 0.5 + done + done +} + +# Function to generate example files +generate_example_files() { + for template in "${!EXAMPLES[@]}"; do + local example_file="${EXAMPLES[$template]}" + if [[ ! -f "${example_file}" ]]; then + openim::log::info "Generating example file: ${example_file} from ${template}..." + cp "${template}" "${example_file}" + fi + done +} + +declare -A env_vars=( + ["OPENIM_IP"]="172.28.0.1" + ["DATA_DIR"]="./" + ["LOG_STORAGE_LOCATION"]="../logs/" +) + +generate_clean_environment_examples() { + env_cmd="env -i" + for var in "${!env_vars[@]}"; do + env_cmd+=" $var='${env_vars[$var]}'" + done + + for template in "${!EXAMPLES[@]}"; do + local example_file="${EXAMPLES[$template]}" + openim::log::info "Generating example file: ${example_file} from ${template}..." + + eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${example_file}'" || { + openim::log::error "Error processing template file ${template}" + exit 1 + } + done } -# Parse command-line options while [[ $# -gt 0 ]]; do case "$1" in -h|--help) @@ -63,6 +151,14 @@ while [[ $# -gt 0 ]]; do SKIP_EXISTING=true shift ;; + --examples) + GENERATE_EXAMPLES=true + shift + ;; + --clean-env-examples) + CLEAN_ENV_EXAMPLES=true + shift + ;; *) echo "Unknown option: $1" show_help @@ -71,44 +167,19 @@ while [[ $# -gt 0 ]]; do esac done -for template in "${!TEMPLATES[@]}"; do - if [[ ! -f "${template}" ]]; then - openim::log::error_exit "Template file ${template} does not exist..." - exit 1 - fi -done +# Generate configuration files if requested +if [[ "${FORCE_OVERWRITE}" == true || "${SKIP_EXISTING}" == false ]]; then + generate_config_files +fi -for template in "${!TEMPLATES[@]}"; do - IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}" - for output_file in "${OUTPUT_FILES[@]}"; do - if [[ -f "${output_file}" ]]; then - if [[ "${FORCE_OVERWRITE}" == true ]]; then - openim::log::info "Force overwriting ${output_file}." - elif [[ "${SKIP_EXISTING}" == true ]]; then - openim::log::info "Skipping generation of ${output_file} as it already exists." - continue - else - echo -n "File ${output_file} already exists. Overwrite? (Y/N): " - read -r -n 1 REPLY - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - openim::log::info "Skipping generation of ${output_file}." - continue - fi - fi - fi +# Generate example files if --examples option is provided +if [[ "${GENERATE_EXAMPLES}" == true ]]; then + generate_example_files +fi - openim::log::info "⌚ Working with template file: ${template} to ${output_file}..." - if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then - openim::log::error "genconfig.sh script not found" - exit 1 - fi - "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || { - openim::log::error "Error processing template file ${template}" - exit 1 - } - sleep 0.5 - done -done +# Generate example files in a clean environment if --clean-env-examples option is provided +if [[ "${CLEAN_ENV_EXAMPLES}" == true ]]; then + generate_clean_environment_examples +fi -openim::log::success "✨ All configuration files have been successfully generated!" +openim::log::success "Configuration and example files generation complete!" \ No newline at end of file From 01c3d4725ba22d21284a4111e2ae6989ecfa989f Mon Sep 17 00:00:00 2001 From: chao <48119764+withchao@users.noreply.github.com> Date: Tue, 12 Dec 2023 18:37:23 +0800 Subject: [PATCH 04/31] feat: optimize tools up35 (#1556) * upgrade package and rtc convert * upgrade package and rtc convert * upgrade package and rtc convert * upgrade package and rtc convert * friend user --- internal/rpc/friend/friend.go | 4 +++ internal/rpc/user/user.go | 16 +++++++++ tools/data-conversion/go.mod | 28 +++++++-------- tools/data-conversion/go.sum | 65 +++++++++++++++++------------------ tools/up35/go.mod | 48 -------------------------- 5 files changed, 65 insertions(+), 96 deletions(-) diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index 224efe3ed..21422fae3 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -52,6 +52,10 @@ type friendServer struct { RegisterCenter registry.SvcDiscoveryRegistry } +func (s *friendServer) PinFriends(ctx context.Context, req *pbfriend.PinFriendsReq) (*pbfriend.PinFriendsResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { // Initialize MongoDB mongo, err := unrelation.NewMongo() diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index 77da408aa..a2fa14c7a 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -56,6 +56,22 @@ type userServer struct { RegisterCenter registry.SvcDiscoveryRegistry } +func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + +func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + +func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + +func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { rdb, err := cache.NewRedis() if err != nil { diff --git a/tools/data-conversion/go.mod b/tools/data-conversion/go.mod index b0d7aea13..37d1776c2 100644 --- a/tools/data-conversion/go.mod +++ b/tools/data-conversion/go.mod @@ -3,16 +3,16 @@ module github.com/openimsdk/open-im-server/v3/tools/data-conversion go 1.19 require ( - github.com/IBM/sarama v1.41.2 - github.com/OpenIMSDK/protocol v0.0.23 - github.com/OpenIMSDK/tools v0.0.14 + github.com/IBM/sarama v1.42.1 + github.com/OpenIMSDK/protocol v0.0.33 + github.com/OpenIMSDK/tools v0.0.20 github.com/golang/protobuf v1.5.3 - github.com/openimsdk/open-im-server/v3 v3.3.2 - golang.org/x/net v0.17.0 - google.golang.org/grpc v1.57.0 + github.com/openimsdk/open-im-server/v3 v3.4.0 + golang.org/x/net v0.19.0 + google.golang.org/grpc v1.60.0 google.golang.org/protobuf v1.31.0 - gorm.io/driver/mysql v1.5.1 - gorm.io/gorm v1.25.4 + gorm.io/driver/mysql v1.5.2 + gorm.io/gorm v1.25.5 ) require ( @@ -28,7 +28,7 @@ require ( github.com/gin-gonic/gin v1.9.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.15.3 // indirect + github.com/go-playground/validator/v10 v10.15.5 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -63,10 +63,10 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/image v0.12.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/image v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tools/data-conversion/go.sum b/tools/data-conversion/go.sum index 9223f6e36..66f85785b 100644 --- a/tools/data-conversion/go.sum +++ b/tools/data-conversion/go.sum @@ -1,9 +1,9 @@ -github.com/IBM/sarama v1.41.2 h1:ZDBZfGPHAD4uuAtSv4U22fRZBgst0eEwGFzLj0fb85c= -github.com/IBM/sarama v1.41.2/go.mod h1:xdpu7sd6OE1uxNdjYTSKUfY8FaKkJES9/+EyjSgiGQk= -github.com/OpenIMSDK/protocol v0.0.23 h1:L545aRQez6Ro+AaJB1Z6Mz7ojnDtp41WqASxYveCkcE= -github.com/OpenIMSDK/protocol v0.0.23/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= -github.com/OpenIMSDK/tools v0.0.14 h1:WLof/+WxyPyRST+QkoTKubYCiV73uCLiL8pgnpH/yKQ= -github.com/OpenIMSDK/tools v0.0.14/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= +github.com/IBM/sarama v1.42.1 h1:wugyWa15TDEHh2kvq2gAy1IHLjEjuYOYgXz/ruC/OSQ= +github.com/IBM/sarama v1.42.1/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= +github.com/OpenIMSDK/protocol v0.0.33 h1:T07KWD0jt7IRlrYRujCa+eXmfgcSi8sRgLL8t2ZlHQA= +github.com/OpenIMSDK/protocol v0.0.33/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= +github.com/OpenIMSDK/tools v0.0.20 h1:zBTjQZRJ5lR1FIzP9mtWyAvh5dKsmJXQugi4p8X/97k= +github.com/OpenIMSDK/tools v0.0.20/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= @@ -34,8 +34,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW296KG4dL3X7xUZo= -github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= +github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= @@ -47,7 +47,7 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= @@ -103,8 +103,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/openimsdk/open-im-server/v3 v3.3.2 h1:uK6glaidrnWlYXFSwzOEq7fXS6jT1OyesUJENZJeptI= -github.com/openimsdk/open-im-server/v3 v3.3.2/go.mod h1:rqKiCkjav5P7tQmyqaixnMJcayWlM4XtXmwG+cZNw78= +github.com/openimsdk/open-im-server/v3 v3.4.0 h1:e7nslaWEHYc5xD1A3zHtnhbIWgfgtJSnPGHIqwjARaE= +github.com/openimsdk/open-im-server/v3 v3.4.0/go.mod h1:HKqjLZSMjD7ec59VV694Yfqnj9SIVotzDSPWgAei2Tg= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= @@ -146,24 +146,22 @@ golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= -golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= +golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -171,8 +169,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -180,18 +178,17 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= @@ -202,9 +199,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= -gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= -gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= -gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs= +gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8= +gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/tools/up35/go.mod b/tools/up35/go.mod index 5ae3907bf..23163a4dc 100644 --- a/tools/up35/go.mod +++ b/tools/up35/go.mod @@ -1,51 +1,3 @@ module github.com/openimsdk/open-im-server/v3/tools/up35 go 1.19 - -require ( - github.com/go-sql-driver/mysql v1.7.1 - github.com/openimsdk/open-im-server/v3 v3.5.0 - github.com/openimsdk/open-im-server/v3/tools/data-conversion v0.0.0-00010101000000-000000000000 - go.mongodb.org/mongo-driver v1.12.1 - gopkg.in/yaml.v3 v3.0.1 - gorm.io/driver/mysql v1.5.1 - gorm.io/gorm v1.25.4 -) - -require ( - github.com/OpenIMSDK/protocol v0.0.31 // indirect - github.com/OpenIMSDK/tools v0.0.18 // indirect - github.com/bwmarrin/snowflake v0.3.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/jinzhu/copier v0.4.0 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.16.7 // indirect - github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect - github.com/lestrrat-go/strftime v1.0.6 // indirect - github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect - github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/xdg-go/pbkdf2 v1.0.0 // indirect - github.com/xdg-go/scram v1.1.2 // indirect - github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/image v0.13.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect -) - -replace ( - github.com/openimsdk/open-im-server/v3 => ./../../../open-im-server - github.com/openimsdk/open-im-server/v3/tools/data-conversion => ./../data-conversion -) From 2cef0f62b38bcf12d5a42bbac7425b3aca5d7233 Mon Sep 17 00:00:00 2001 From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:14:43 +0800 Subject: [PATCH 05/31] fix group notification (#1557) --- internal/rpc/group/group.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index 5992ed031..b05b14b59 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -278,7 +278,6 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR break } } - s.Notification.GroupCreatedNotification(ctx, tips) if req.GroupInfo.GroupType == constant.SuperGroup { go func() { for _, userID := range userIDs { From c2dfc37b0bfc5bbf35273afd23896a8dc46e84f6 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Sat, 16 Dec 2023 23:01:15 +0800 Subject: [PATCH 06/31] feat: support mac deployment and optimization make check (#1570) * feat: add openim server code Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim env Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add openim scripts check and mac support ss comment Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: add mac os Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --------- Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --- .github/workflows/openimci.yml | 53 ++++++- config/templates/config.yaml.template | 6 +- config/templates/env.template | 13 +- deployments/templates/env-template.yaml | 8 +- docker-compose.yml | 5 - docs/contrib/environment.md | 10 +- scripts/check-all.sh | 6 +- scripts/docker-start-all.sh | 2 + scripts/init-config.sh | 176 +++++++++++++----------- scripts/install/environment.sh | 6 +- scripts/lib/logging.sh | 2 +- scripts/lib/util.sh | 23 +++- 12 files changed, 194 insertions(+), 116 deletions(-) diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml index 5f010db8a..d65c0dc89 100644 --- a/.github/workflows/openimci.yml +++ b/.github/workflows/openimci.yml @@ -130,14 +130,14 @@ jobs: sudo make install execute-scripts: - name: Execute OpenIM script on ${{ matrix.os }} + name: Execute OpenIM Script On ${{ matrix.os }} runs-on: ${{ matrix.os }} environment: name: openim strategy: matrix: go_version: ["1.20"] - os: ["ubuntu-latest"] + os: ["ubuntu-latest", "macos-latest"] steps: - name: Checkout code uses: actions/checkout@v4 @@ -154,18 +154,52 @@ jobs: version: '3.x' # If available, use the latest major version that's compatible repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Docker Operations + # - name: Install latest Bash (macOS only) + # if: runner.os == 'macOS' + # run: | + # /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + # brew update + + # brew install bash + # brew install gnu-sed + + # echo "/usr/local/bin" >> $GITHUB_PATH + # echo "$(brew --prefix)/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH + # continue-on-error: true + + - name: Set up Docker for Ubuntu + if: runner.os == 'Linux' run: | sudo make init sudo docker compose up -d sudo sleep 20 - - name: Module Operations + # - name: Set up Docker for macOS + # if: runner.os == 'macOS' + # run: | + # brew install --cask docker + # open /Applications/Docker.app + + # sleep 10 + # docker-compose --version || brew install docker-compose + + # docker-compose up -d + # sleep 20 + + - name: Module Operations for Ubuntu + if: runner.os == 'Linux' run: | sudo make tidy sudo make tools.verify.go-gitlint - - name: Build, Start, Check Services and Print Logs + # - name: Module Operations for macOS + # if: runner.os == 'macOS' + # run: | + # make tidy + # make tools.verify.go-gitlint + + - name: Build, Start, Check Services and Print Logs for Ubuntu + if: runner.os == 'Linux' run: | sudo make init && \ sudo make build && \ @@ -173,6 +207,15 @@ jobs: sudo make check || \ (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null) + # - name: Build, Start, Check Services and Print Logs for macOS + # if: runner.os == 'macOS' + # run: | + # make init && \ + # make build && \ + # make start && \ + # make check || \ + # (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null) + openim-test-build-image: name: Build OpenIM Docker Image runs-on: ubuntu-latest diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template index a35d06c8c..7eb082b24 100644 --- a/config/templates/config.yaml.template +++ b/config/templates/config.yaml.template @@ -115,14 +115,14 @@ api: # minio.signEndpoint is minio public network address object: enable: "minio" - apiURL: "http://172.28.0.1:10002" + apiURL: "http://14.155.64.202:10002" minio: bucket: "openim" endpoint: "http://172.28.0.1:10005" accessKeyID: "root" secretAccessKey: "openIM123" sessionToken: '' - signEndpoint: "http://172.28.0.1:10005" + signEndpoint: "http://14.155.64.202:10005" publicRead: false cos: bucketURL: https://temp-1252357374.cos.ap-chengdu.myqcloud.com @@ -186,7 +186,7 @@ rpcRegisterName: # Whether to output in json format # Whether to include stack trace in logs log: - storageLocation: ../logs/ + storageLocation: /data/workspaces/open-im-server/logs/ rotationTime: 24 remainRotationCount: 2 remainLogLevel: 6 diff --git a/config/templates/env.template b/config/templates/env.template index e47a9c073..54218c330 100644 --- a/config/templates/env.template +++ b/config/templates/env.template @@ -16,11 +16,11 @@ MINIO_ENDPOINT=http://172.28.0.1:10005 # Base URL for the application programming interface (API). # Default: API_URL=http://172.28.0.1:10002 -API_URL=http://172.28.0.1:10002 +API_URL=http://14.155.64.202:10002 # Directory path for storing data files or related information. # Default: DATA_DIR=./ -DATA_DIR=./ +DATA_DIR=/data/workspaces/open-im-server # Choose the appropriate image address, the default is GITHUB image, # you can choose docker hub, for Chinese users can choose Ali Cloud @@ -200,8 +200,9 @@ API_OPENIM_PORT=10002 # ====================================== # Branch name for OpenIM chat. -# Default: CHAT_BRANCH=main -CHAT_BRANCH=main +# Default: CHAT_IMAGE_VERSION=main +# https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md +CHAT_IMAGE_VERSION=main # Address or hostname for the OpenIM chat service. # Default: OPENIM_CHAT_ADDRESS=172.28.0.1 @@ -221,8 +222,8 @@ OPENIM_CHAT_DATA_DIR=./openim-chat/main # ====================================== # Branch name for OpenIM server. -# Default: SERVER_BRANCH=main -SERVER_BRANCH=main +# Default: SERVER_IMAGE_VERSION=main +SERVER_IMAGE_VERSION=main # Port for the OpenIM admin API. # Default: OPENIM_ADMIN_API_PORT=10009 diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml index b62543aba..b4118b9ce 100644 --- a/deployments/templates/env-template.yaml +++ b/deployments/templates/env-template.yaml @@ -200,8 +200,8 @@ API_OPENIM_PORT=${API_OPENIM_PORT} # ====================================== # Branch name for OpenIM chat. -# Default: CHAT_BRANCH=main -CHAT_BRANCH=${CHAT_BRANCH} +# Default: CHAT_IMAGE_VERSION=main +CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION} # Address or hostname for the OpenIM chat service. # Default: OPENIM_CHAT_ADDRESS=172.28.0.1 @@ -221,8 +221,8 @@ OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR} # ====================================== # Branch name for OpenIM server. -# Default: SERVER_BRANCH=main -SERVER_BRANCH=${SERVER_BRANCH} +# Default: SERVER_IMAGE_VERSION=main +SERVER_IMAGE_VERSION=${SERVER_IMAGE_VERSION} # Port for the OpenIM admin API. # Default: OPENIM_ADMIN_API_PORT=10009 diff --git a/docker-compose.yml b/docker-compose.yml index 22f57d329..de3deaaea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,6 @@ services: ipv4_address: ${MONGO_NETWORK_ADDRESS:-172.28.0.2} redis: - # image: redis:7.0.0 image: redis:${REDIS_IMAGE_VERSION:-7.0.0} container_name: redis ports: @@ -53,7 +52,6 @@ services: ipv4_address: ${REDIS_NETWORK_ADDRESS:-172.28.0.3} zookeeper: - # image: bitnami/zookeeper:3.8 image: bitnami/zookeeper:${ZOOKEEPER_IMAGE_VERSION:-3.8} container_name: zookeeper ports: @@ -69,7 +67,6 @@ services: ipv4_address: ${ZOOKEEPER_NETWORK_ADDRESS:-172.28.0.5} kafka: - # image: 'bitnami/kafka:3.5.1' image: 'bitnami/kafka:${KAFKA_IMAGE_VERSION:-3.5.1}' container_name: kafka restart: always @@ -95,7 +92,6 @@ services: ipv4_address: ${KAFKA_NETWORK_ADDRESS:-172.28.0.4} minio: - # image: minio/minio image: minio/minio:${MINIO_IMAGE_VERSION:-latest} ports: - "${MINIO_PORT:-10005}:9000" @@ -114,7 +110,6 @@ services: ipv4_address: ${MINIO_NETWORK_ADDRESS:-172.28.0.6} openim-web: - # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:latest image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-latest} container_name: openim-web environment: diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md index 3dd090dcc..310c2df6a 100644 --- a/docs/contrib/environment.md +++ b/docs/contrib/environment.md @@ -104,18 +104,18 @@ Docker deployment offers a slightly more intricate template. Within the [openim- Configuration file modifications can be made by specifying corresponding environment variables, for instance: ```bash -export CHAT_BRANCH="main" -export SERVER_BRANCH="main" +export CHAT_IMAGE_VERSION="main" +export SERVER_IMAGE_VERSION="main" ``` These variables are stored within the [`environment.sh`](https://github.com/OpenIMSDK/openim-docker/blob/main/scripts/install/environment.sh) configuration: ```bash -readonly CHAT_BRANCH=${CHAT_BRANCH:-'main'} -readonly SERVER_BRANCH=${SERVER_BRANCH:-'main'} +readonly CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION:-'main'} +readonly SERVER_IMAGE_VERSION=${SERVER_IMAGE_VERSION:-'main'} ``` -Setting a variable, e.g., `export CHAT_BRANCH="release-v1.3"`, will prioritize `CHAT_BRANCH="release-v1.3"` as the variable value. Ultimately, the chosen image version is determined, and rendering is achieved through `make init` (or `./scripts/init-config.sh`). +Setting a variable, e.g., `export CHAT_IMAGE_VERSION="release-v1.3"`, will prioritize `CHAT_IMAGE_VERSION="release-v1.3"` as the variable value. Ultimately, the chosen image version is determined, and rendering is achieved through `make init` (or `./scripts/init-config.sh`). > Note: Direct modifications to the `config.yaml` file are also permissible without utilizing `make init`. diff --git a/scripts/check-all.sh b/scripts/check-all.sh index 23e2119d4..5acae3498 100755 --- a/scripts/check-all.sh +++ b/scripts/check-all.sh @@ -33,9 +33,8 @@ openim::log::info "\n# Begin to check all openim service" # OpenIM status # Elegant printing function print_services_and_ports() { - # 获取数组 - declare -g service_names=("${!1}") - declare -g service_ports=("${!2}") + local -n service_names=$1 + local -n service_ports=$2 echo "+-------------------------+----------+" echo "| Service Name | Port |" @@ -48,7 +47,6 @@ print_services_and_ports() { echo "+-------------------------+----------+" } - # Print out services and their ports print_services_and_ports OPENIM_SERVER_NAME_TARGETS OPENIM_SERVER_PORT_TARGETS diff --git a/scripts/docker-start-all.sh b/scripts/docker-start-all.sh index 6ad277815..3c83b02bb 100755 --- a/scripts/docker-start-all.sh +++ b/scripts/docker-start-all.sh @@ -28,6 +28,8 @@ openim::log::info "\n# Use Docker to start all openim service" trap 'openim::util::onCtrlC' INT +"${OPENIM_ROOT}"/scripts/init-config.sh --skip + "${OPENIM_ROOT}"/scripts/start-all.sh sleep 5 diff --git a/scripts/init-config.sh b/scripts/init-config.sh index 631bd68d7..0b9c0e615 100755 --- a/scripts/init-config.sh +++ b/scripts/init-config.sh @@ -1,17 +1,4 @@ #!/usr/bin/env bash -# Copyright © 2023 OpenIM. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# You may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. # This script automatically initializes various configuration files and can generate example files. @@ -48,7 +35,8 @@ declare -A EXAMPLES=( FORCE_OVERWRITE=false SKIP_EXISTING=false GENERATE_EXAMPLES=false -CLEAN_ENV_EXAMPLES=false +CLEAN_CONFIG=false +CLEAN_EXAMPLES=false # Function to display help information show_help() { @@ -58,48 +46,45 @@ show_help() { echo " --force Overwrite existing files without prompt" echo " --skip Skip generation if file exists" echo " --examples Generate example files" - echo " --clean-env-examples Generate example files in a clean environment" + echo " --clean-config Clean all configuration files" + echo " --clean-examples Clean all example files" } # Function to generate configuration files generate_config_files() { - # Loop through each template in TEMPLATES for template in "${!TEMPLATES[@]}"; do - # Read the corresponding output files for the template - IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}" - for output_file in "${OUTPUT_FILES[@]}"; do - # Check if the output file already exists - if [[ -f "${output_file}" ]]; then - # Handle existing file based on command-line options - if [[ "${FORCE_OVERWRITE}" == true ]]; then - openim::log::info "Force overwriting ${output_file}." - elif [[ "${SKIP_EXISTING}" == true ]]; then - openim::log::info "Skipping generation of ${output_file} as it already exists." + local output_file="${TEMPLATES[$template]}" + if [[ -f "${output_file}" ]]; then + if [[ "${FORCE_OVERWRITE}" == true ]]; then + openim::log::info "Force overwriting ${output_file}." + elif [[ "${SKIP_EXISTING}" == true ]]; then + openim::log::info "Skipping generation of ${output_file} as it already exists." + continue + else + echo -n "File ${output_file} already exists. Overwrite? (Y/N): " + read -r -n 1 REPLY + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + openim::log::info "Skipping generation of ${output_file}." continue - else - # Ask user for confirmation to overwrite - echo -n "File ${output_file} already exists. Overwrite? (Y/N): " - read -r -n 1 REPLY - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - openim::log::info "Skipping generation of ${output_file}." - continue - fi fi fi - - # Process the template file to generate the output file - openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..." - if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then - openim::log::error "genconfig.sh script not found" - exit 1 + else + if [[ "${SKIP_EXISTING}" == true ]]; then + openim::log::info "Generating ${output_file} as it does not exist." fi - "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || { - openim::log::error "Error processing template file ${template}" - exit 1 - } - sleep 0.5 - done + fi + + openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..." + if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then + openim::log::error "genconfig.sh script not found" + exit 1 + fi + "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || { + openim::log::error "Error processing template file ${template}" + exit 1 + } + sleep 0.5 done } @@ -107,33 +92,56 @@ generate_config_files() { generate_example_files() { for template in "${!EXAMPLES[@]}"; do local example_file="${EXAMPLES[$template]}" - if [[ ! -f "${example_file}" ]]; then - openim::log::info "Generating example file: ${example_file} from ${template}..." - cp "${template}" "${example_file}" + if [[ -f "${example_file}" ]]; then + if [[ "${FORCE_OVERWRITE}" == true ]]; then + openim::log::info "Force overwriting example file: ${example_file}." + elif [[ "${SKIP_EXISTING}" == true ]]; then + openim::log::info "Skipping generation of example file: ${example_file} as it already exists." + continue + else + echo -n "Example file ${example_file} already exists. Overwrite? (Y/N): " + read -r -n 1 REPLY + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + openim::log::info "Skipping generation of example file: ${example_file}." + continue + fi + fi + elif [[ "${SKIP_EXISTING}" == true ]]; then + openim::log::info "Generating example file: ${example_file} as it does not exist." fi + + openim::log::info "⌚ Working with template file: ${template} to generate example file: ${example_file}..." + if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then + openim::log::error "genconfig.sh script not found" + exit 1 + fi + "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${example_file}" || { + openim::log::error "Error processing template file ${template}" + exit 1 + } + sleep 0.5 done } -declare -A env_vars=( - ["OPENIM_IP"]="172.28.0.1" - ["DATA_DIR"]="./" - ["LOG_STORAGE_LOCATION"]="../logs/" -) -generate_clean_environment_examples() { - env_cmd="env -i" - for var in "${!env_vars[@]}"; do - env_cmd+=" $var='${env_vars[$var]}'" +# Function to clean configuration files +clean_config_files() { + for output_file in "${TEMPLATES[@]}"; do + if [[ -f "${output_file}" ]]; then + rm -f "${output_file}" + openim::log::info "Removed configuration file: ${output_file}" + fi done +} - for template in "${!EXAMPLES[@]}"; do - local example_file="${EXAMPLES[$template]}" - openim::log::info "Generating example file: ${example_file} from ${template}..." - - eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${example_file}'" || { - openim::log::error "Error processing template file ${template}" - exit 1 - } +# Function to clean example files +clean_example_files() { + for example_file in "${EXAMPLES[@]}"; do + if [[ -f "${example_file}" ]]; then + rm -f "${example_file}" + openim::log::info "Removed example file: ${example_file}" + fi done } @@ -155,8 +163,12 @@ while [[ $# -gt 0 ]]; do GENERATE_EXAMPLES=true shift ;; - --clean-env-examples) - CLEAN_ENV_EXAMPLES=true + --clean-config) + CLEAN_CONFIG=true + shift + ;; + --clean-examples) + CLEAN_EXAMPLES=true shift ;; *) @@ -167,19 +179,29 @@ while [[ $# -gt 0 ]]; do esac done +# Clean configuration files if --clean-config option is provided +if [[ "${CLEAN_CONFIG}" == true ]]; then + clean_config_files +fi + +# Clean example files if --clean-examples option is provided +if [[ "${CLEAN_EXAMPLES}" == true ]]; then + clean_example_files +fi + # Generate configuration files if requested -if [[ "${FORCE_OVERWRITE}" == true || "${SKIP_EXISTING}" == false ]]; then +if [[ "${FORCE_OVERWRITE}" == true || "${SKIP_EXISTING}" == false ]] && [[ "${CLEAN_CONFIG}" == false ]]; then generate_config_files fi -# Generate example files if --examples option is provided -if [[ "${GENERATE_EXAMPLES}" == true ]]; then - generate_example_files +# Generate configuration files if requested +if [[ "${SKIP_EXISTING}" == true ]]; then + generate_config_files fi -# Generate example files in a clean environment if --clean-env-examples option is provided -if [[ "${CLEAN_ENV_EXAMPLES}" == true ]]; then - generate_clean_environment_examples +# Generate example files if --examples option is provided +if [[ "${GENERATE_EXAMPLES}" == true ]] && [[ "${CLEAN_EXAMPLES}" == false ]]; then + generate_example_files fi -openim::log::success "Configuration and example files generation complete!" \ No newline at end of file +openim::log::success "Configuration and example files operation complete!" diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh index 643f621b6..3dd062af6 100755 --- a/scripts/install/environment.sh +++ b/scripts/install/environment.sh @@ -66,8 +66,8 @@ def "ENV_FILE" ""${OPENIM_ROOT}"/scripts/install/environment.sh" ###################### Docker compose ################### # OPENIM AND CHAT -def "CHAT_BRANCH" "main" -def "SERVER_BRANCH" "main" +def "CHAT_IMAGE_VERSION" "main" +def "SERVER_IMAGE_VERSION" "main" # Choose the appropriate image address, the default is GITHUB image, # you can choose docker hub, for Chinese users can choose Ali Cloud @@ -139,7 +139,7 @@ readonly API_OPENIM_PORT=${API_OPENIM_PORT:-'10002'} def "API_LISTEN_IP" "0.0.0.0" # API的监听IP ###################### openim-chat 配置信息 ###################### -def "OPENIM_CHAT_DATA_DIR" "./openim-chat/${CHAT_BRANCH}" +def "OPENIM_CHAT_DATA_DIR" "./openim-chat/${CHAT_IMAGE_VERSION}" def "OPENIM_CHAT_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # OpenIM服务地址 def "OPENIM_CHAT_API_PORT" "10008" # OpenIM API端口 def "CHAT_API_LISTEN_IP" "" # OpenIM API的监听IP diff --git a/scripts/lib/logging.sh b/scripts/lib/logging.sh index 9d28aa284..8e7d5b09a 100755 --- a/scripts/lib/logging.sh +++ b/scripts/lib/logging.sh @@ -20,7 +20,7 @@ OPENIM_VERBOSE="${OPENIM_VERBOSE:-5}" ENABLE_LOGGING="${ENABLE_LOGGING:-true}" # If OPENIM_OUTPUT is not set, set it to the default value -if [[ ! -v OPENIM_OUTPUT ]]; then +if [ -z "${OPENIM_OUTPUT+x}" ]; then OPENIM_OUTPUT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../_output" && pwd -P)" fi diff --git a/scripts/lib/util.sh b/scripts/lib/util.sh index ad3baa6bf..b8d76edeb 100755 --- a/scripts/lib/util.sh +++ b/scripts/lib/util.sh @@ -302,8 +302,12 @@ openim::util::check_ports() { # Iterate over each given port. for port in "$@"; do # Use the `ss` command to find process information related to the given port. - local info=$(ss -ltnp | grep ":$port" || true) - + if command -v ss > /dev/null 2>&1; then + info=$(ss -ltnp | grep ":$port" || true) + else + info=$(netstat -ltnp | grep ":$port" || true) + fi + # If there's no process information, it means the process associated with the port is not running. if [[ -z $info ]]; then not_started+=($port) @@ -364,6 +368,18 @@ openim::util::check_ports() { # openim::util::check_process_names nginx mysql redis # The function returns a status of 1 if any of the processes is not running. openim::util::check_process_names() { + # Function to get the port of a process + get_port() { + local pid=$1 + if command -v ss > /dev/null 2>&1; then + # used ss comment + ss -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | cut -d ':' -f2 + else + # used netstat comment replace ss + netstat -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | sed 's/.*://' + fi + } + # Arrays to collect details of processes local not_started=() local started=() @@ -382,7 +398,7 @@ openim::util::check_process_names() { for pid in "${pids[@]}"; do local command=$(ps -p $pid -o cmd=) local start_time=$(ps -p $pid -o lstart=) - local port=$(ss -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | cut -d ':' -f2) + local port=$(get_port $pid) # Check if port information was found for the PID if [[ -z $port ]]; then @@ -419,6 +435,7 @@ openim::util::check_process_names() { return 0 fi } + # openim::util::check_process_names docker-pr # The `openim::util::stop_services_on_ports` function stops services running on specified ports. From c5c5b2fd8ea3a6cc5c73b7b5860d32285c0c29e5 Mon Sep 17 00:00:00 2001 From: xuexihuang <1339326187@qq.com> Date: Sun, 17 Dec 2023 17:40:04 +0800 Subject: [PATCH 07/31] support multipe msggateway services in k8s deployments (#1565) * feature:support multi msggateway * feature:support multi msggateway --------- Co-authored-by: lin.huang --- .../discoveryregister/discoveryregister.go | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/pkg/common/discoveryregister/discoveryregister.go b/pkg/common/discoveryregister/discoveryregister.go index c204184ff..62c1f4a31 100644 --- a/pkg/common/discoveryregister/discoveryregister.go +++ b/pkg/common/discoveryregister/discoveryregister.go @@ -4,6 +4,9 @@ import ( "context" "errors" "fmt" + "os" + "strconv" + "strings" "time" "github.com/OpenIMSDK/tools/discoveryregistry" @@ -43,7 +46,12 @@ func NewK8sDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) { } func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.DialOption) error { - cli.rpcRegisterAddr = serviceName + if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { + cli.rpcRegisterAddr = serviceName + } else { + cli.rpcRegisterAddr = cli.getSelfHost(context.Background()) + } + return nil } func (cli *K8sDR) UnRegister() error { @@ -63,10 +71,68 @@ func (cli *K8sDR) GetConfFromRegistry(key string) ([]byte, error) { return nil, nil } +func (cli *K8sDR) getSelfHost(ctx context.Context) string { + port := 88 + instance := "openimserver" + selfPodName := os.Getenv("MY_POD_NAME") + ns := os.Getenv("MY_POD_NAMESPACE") + statefuleIndex := 0 + gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":") + if len(gatewayEnds) != 2 { + log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error")) + } else { + port, _ = strconv.Atoi(gatewayEnds[1]) + } + podInfo := strings.Split(selfPodName, "-") + instance = podInfo[0] + count := len(podInfo) + statefuleIndex, _ = strconv.Atoi(podInfo[count-1]) + host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, statefuleIndex, instance, ns, port) + return host +} + +// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88 +func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string { + port := 88 + instance := "openimserver" + selfPodName := os.Getenv("MY_POD_NAME") + replicas := os.Getenv("MY_MSGGATEWAY_REPLICACOUNT") + ns := os.Getenv("MY_POD_NAMESPACE") + gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":") + if len(gatewayEnds) != 2 { + log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error")) + } else { + port, _ = strconv.Atoi(gatewayEnds[1]) + } + nReplicas, _ := strconv.Atoi(replicas) + podInfo := strings.Split(selfPodName, "-") + instance = podInfo[0] + var ret []string + for i := 0; i < nReplicas; i++ { + host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, i, instance, ns, port) + ret = append(ret, host) + } + log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret) + return ret +} func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { - conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) - return []*grpc.ClientConn{conn}, err + if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { + conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) + return []*grpc.ClientConn{conn}, err + } else { + var ret []*grpc.ClientConn + gatewayHosts := cli.getMsgGatewayHost(ctx) + for _, host := range gatewayHosts { + conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...) + if err != nil { + return nil, err + } else { + ret = append(ret, conn) + } + } + return ret, nil + } } func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { From f1c9686ada6d195449a5762e14c8312c48263ea3 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Mon, 18 Dec 2023 10:24:12 +0800 Subject: [PATCH 08/31] feat: Add OpenIM server, environment support for Docker Compose, and Kubernetes deployment. (#1559) * feat: add openim server code Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim env Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim mongo and redis env Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add zk and redis mongo env Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add kafka and redis mongo env Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim docker Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim docker Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim docker Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim copyright Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: docker compose Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: remove openim chat config file Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim config set Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim config set Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: fix Security vulnerability Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: fix Security vulnerability Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: docker compose Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * Update kubernetes.go * Update discoveryregister.go * fix: copyright-add Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --------- Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --- .github/workflows/build-docker-image.yml | 3 + .github/workflows/build-openim-web-image.yml | 139 ------ .gitignore | 15 +- config/Readme.md | 243 ++++++++++ config/templates/README.md | 36 -- config/templates/alertmanager.yml.template | 14 + config/templates/config.yaml.template | 17 +- .../email.tmpl.template} | 0 config/templates/env.template | 18 +- .../instance-down-rules.yml.template | 36 ++ config/templates/notification.yaml.template | 354 +++++++++++++++ .../{ => templates}/open-im-ng-example.conf | 0 .../{ => templates}/prometheus-dashboard.yaml | 14 + config/templates/prometheus.yml.template | 14 + deployments/{README.md => Readme.md} | 0 deployments/charts/helmfile.yaml | 14 + deployments/charts/openim-api/Chart.yaml | 14 + .../charts/openim-api/templates/app-cm.yaml | 14 + .../openim-api/templates/deployment.yaml | 14 + .../charts/openim-api/templates/hpa.yaml | 14 + .../charts/openim-api/templates/ingress.yaml | 14 + .../charts/openim-api/templates/service.yaml | 14 + .../openim-api/templates/serviceaccount.yaml | 14 + deployments/charts/openim-api/values.yaml | 14 + .../charts/openim-msggateway/Chart.yaml | 14 + .../openim-msggateway/templates/hpa.yaml | 14 + .../openim-msggateway/templates/ingress.yaml | 14 + .../openim-msggateway/templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + .../charts/openim-msggateway/values.yaml | 14 + .../charts/openim-msgtransfer/Chart.yaml | 14 + .../templates/deployment.yaml | 14 + .../openim-msgtransfer/templates/hpa.yaml | 14 + .../openim-msgtransfer/templates/ingress.yaml | 14 + .../openim-msgtransfer/templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + .../charts/openim-msgtransfer/values.yaml | 14 + deployments/charts/openim-push/Chart.yaml | 14 + .../openim-push/templates/deployment.yaml | 14 + .../charts/openim-push/templates/hpa.yaml | 14 + .../charts/openim-push/templates/ingress.yaml | 14 + .../charts/openim-push/templates/service.yaml | 14 + .../openim-push/templates/serviceaccount.yaml | 14 + deployments/charts/openim-push/values.yaml | 14 + deployments/charts/openim-rpc-auth/Chart.yaml | 14 + .../openim-rpc-auth/templates/deployment.yaml | 14 + .../charts/openim-rpc-auth/templates/hpa.yaml | 14 + .../openim-rpc-auth/templates/ingress.yaml | 14 + .../openim-rpc-auth/templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + .../charts/openim-rpc-auth/values.yaml | 14 + .../charts/openim-rpc-conversation/Chart.yaml | 14 + .../templates/deployment.yaml | 14 + .../templates/hpa.yaml | 14 + .../templates/ingress.yaml | 14 + .../templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + .../openim-rpc-conversation/values.yaml | 14 + .../charts/openim-rpc-friend/Chart.yaml | 14 + .../templates/deployment.yaml | 14 + .../openim-rpc-friend/templates/hpa.yaml | 14 + .../openim-rpc-friend/templates/ingress.yaml | 14 + .../openim-rpc-friend/templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + .../charts/openim-rpc-friend/values.yaml | 14 + .../charts/openim-rpc-group/Chart.yaml | 14 + .../templates/deployment.yaml | 14 + .../openim-rpc-group/templates/hpa.yaml | 14 + .../openim-rpc-group/templates/ingress.yaml | 14 + .../openim-rpc-group/templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + .../charts/openim-rpc-group/values.yaml | 14 + deployments/charts/openim-rpc-msg/Chart.yaml | 14 + .../openim-rpc-msg/templates/deployment.yaml | 14 + .../charts/openim-rpc-msg/templates/hpa.yaml | 14 + .../openim-rpc-msg/templates/ingress.yaml | 14 + .../openim-rpc-msg/templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + deployments/charts/openim-rpc-msg/values.yaml | 14 + .../charts/openim-rpc-third/Chart.yaml | 14 + .../templates/deployment.yaml | 14 + .../openim-rpc-third/templates/hpa.yaml | 14 + .../openim-rpc-third/templates/ingress.yaml | 14 + .../openim-rpc-third/templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + .../charts/openim-rpc-third/values.yaml | 14 + deployments/charts/openim-rpc-user/Chart.yaml | 14 + .../openim-rpc-user/templates/deployment.yaml | 14 + .../charts/openim-rpc-user/templates/hpa.yaml | 14 + .../openim-rpc-user/templates/ingress.yaml | 14 + .../openim-rpc-user/templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 14 + .../charts/openim-rpc-user/values.yaml | 14 + deployments/openim-charts.yaml | 14 + deployments/templates/alertmanager.yml | 14 + deployments/templates/charts-value.yaml | 14 + deployments/templates/chat.yaml | 118 ----- deployments/templates/email.tmpl | 16 + deployments/templates/env-template.yaml | 18 +- deployments/templates/helm-image.yaml | 14 + .../templates}/instance-down-rules.yml | 14 + .../templates}/notification.yaml | 33 +- deployments/templates/openim.yaml | 17 +- deployments/templates/prometheus.yml | 14 + internal/api/msg.go | 1 + internal/msggateway/compressor_test.go | 14 + internal/push/offlinepush/dummy/push.go | 14 + internal/push/push_rpc_server.go | 3 +- internal/rpc/friend/callback.go | 2 + internal/rpc/friend/friend.go | 1 + internal/rpc/group/callback.go | 3 +- internal/rpc/group/group.go | 3 +- internal/rpc/msg/as_read.go | 8 +- internal/rpc/msg/callback.go | 2 + internal/rpc/third/log.go | 14 + internal/rpc/user/callback.go | 1 + internal/tools/cron_task_test.go | 14 + pkg/apistruct/msg.go | 36 +- pkg/callbackstruct/constant.go | 14 + pkg/callbackstruct/revoke.go | 14 + pkg/common/cmd/constant.go | 14 + pkg/common/config/config.go | 1 + pkg/common/config/parse.go | 4 +- pkg/common/convert/user.go | 3 +- pkg/common/db/cache/group.go | 2 +- pkg/common/db/cache/init_redis.go | 24 +- pkg/common/db/cache/msg_test.go | 14 + pkg/common/db/cache/s3.go | 14 + pkg/common/db/mgo/black.go | 14 + pkg/common/db/mgo/conversation.go | 14 + pkg/common/db/mgo/friend.go | 14 + pkg/common/db/mgo/friend_request.go | 14 + pkg/common/db/mgo/group.go | 14 + pkg/common/db/mgo/group_member.go | 14 + pkg/common/db/mgo/group_request.go | 14 + pkg/common/db/mgo/log.go | 14 + pkg/common/db/mgo/object.go | 14 + pkg/common/db/mgo/user.go | 14 + pkg/common/db/s3/cos/internal.go | 14 + pkg/common/db/s3/minio/internal.go | 14 + pkg/common/db/s3/minio/thumbnail.go | 14 + pkg/common/db/table/relation/log.go | 14 + pkg/common/db/unrelation/mongo.go | 137 +++--- .../discoveryregister/discoveryregister.go | 169 ++----- .../discoveryregister_test.go | 428 ++---------------- .../kubernetes/kubernetes.go | 174 +++++++ .../discoveryregister/zookeeper/zookeeper.go | 61 +++ pkg/common/ginprometheus/ginprometheus.go | 14 + pkg/common/kafka/producer.go | 138 +++--- pkg/common/kafka/util.go | 11 + pkg/common/prommetrics/gin_api.go | 16 +- pkg/common/prommetrics/grpc_auth.go | 14 + pkg/common/prommetrics/grpc_msg.go | 14 + pkg/common/prommetrics/grpc_msggateway.go | 14 + pkg/common/prommetrics/grpc_push.go | 14 + pkg/common/prommetrics/prommetrics.go | 14 + pkg/common/prommetrics/prommetrics_test.go | 14 + pkg/common/prommetrics/transfer.go | 14 + pkg/common/startrpc/start_test.go | 14 + pkg/common/version/base.go | 16 +- pkg/common/version/types.go | 14 + pkg/common/version/version.go | 18 +- pkg/rpcclient/grouphash/grouphash.go | 14 + scripts/check-all.sh | 4 +- scripts/githooks/pre-push.sh | 2 +- scripts/init-config.sh | 159 ++++--- test/e2e/api/token/token.go | 28 +- test/e2e/api/user/curd.go | 24 +- test/e2e/api/user/user.go | 30 +- test/e2e/e2e.go | 14 + test/e2e/e2e_test.go | 14 + test/e2e/framework/config/config.go | 14 + test/e2e/framework/config/config_test.go | 14 + .../framework/ginkgowrapper/ginkgowrapper.go | 14 + .../ginkgowrapper/ginkgowrapper_test.go | 14 + test/e2e/framework/helpers/chat/chat.go | 22 +- tools/component/component.go | 320 +++++++------ .../chat/cmd/conversion-chat/chat.go | 14 + .../chat/conversion/conversion.go | 14 + tools/data-conversion/chat/v2/admin.go | 14 + tools/data-conversion/chat/v2/chat.go | 14 + .../cmd/conversion-msg/conversion-msg.go | 14 + tools/data-conversion/openim/mysql/cmd.go | 14 + .../openim/mysql/conversion/conversion.go | 14 + .../openim/mysql/v2/model_struct.go | 14 + tools/data-conversion/openim/mysql/v3/log.go | 14 + .../openim/proto/msg/msg.proto | 14 + .../openim/proto/sdk_ws/ws.proto | 14 + tools/data-conversion/utils/find_insert.go | 14 + tools/data-conversion/utils/time.go | 14 + tools/infra/infra.go | 14 + tools/up35/pkg/convert.go | 17 +- .../pkg/internal/rtc/mongo/mgo/meeting.go | 20 +- .../rtc/mongo/mgo/meeting_invitation.go | 27 +- .../internal/rtc/mongo/mgo/meeting_record.go | 18 +- .../up35/pkg/internal/rtc/mongo/mgo/signal.go | 20 +- .../rtc/mongo/mgo/signal_invitation.go | 20 +- .../pkg/internal/rtc/mongo/table/meeting.go | 17 +- .../pkg/internal/rtc/mongo/table/signal.go | 17 +- tools/up35/pkg/internal/rtc/mysql/meeting.go | 14 + tools/up35/pkg/internal/rtc/mysql/signal.go | 16 +- tools/up35/pkg/pkg.go | 17 +- tools/up35/up35.go | 17 +- tools/url2im/main.go | 14 + tools/url2im/pkg/api.go | 14 + tools/url2im/pkg/buffer.go | 14 + tools/url2im/pkg/config.go | 14 + tools/url2im/pkg/http.go | 14 + tools/url2im/pkg/manage.go | 14 + tools/url2im/pkg/md5.go | 14 + tools/url2im/pkg/progress.go | 14 + 211 files changed, 3985 insertions(+), 1235 deletions(-) delete mode 100644 .github/workflows/build-openim-web-image.yml create mode 100644 config/Readme.md delete mode 100644 config/templates/README.md rename config/{email.tmpl => templates/email.tmpl.template} (100%) create mode 100644 config/templates/instance-down-rules.yml.template create mode 100644 config/templates/notification.yaml.template rename config/{ => templates}/open-im-ng-example.conf (100%) rename config/{ => templates}/prometheus-dashboard.yaml (98%) rename deployments/{README.md => Readme.md} (100%) delete mode 100644 deployments/templates/chat.yaml create mode 100644 deployments/templates/email.tmpl rename {config => deployments/templates}/instance-down-rules.yml (61%) rename {config => deployments/templates}/notification.yaml (88%) create mode 100644 pkg/common/discoveryregister/kubernetes/kubernetes.go create mode 100644 pkg/common/discoveryregister/zookeeper/zookeeper.go diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index a8cb98a51..619744987 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -48,6 +48,7 @@ jobs: images: openim/openim-server # generate Docker tags based on the following events/attributes tags: | + type=ref,event=tag type=schedule type=ref,event=branch type=ref,event=pr @@ -90,6 +91,7 @@ jobs: images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server # generate Docker tags based on the following events/attributes tags: | + type=ref,event=tag type=schedule type=ref,event=branch type=ref,event=pr @@ -133,6 +135,7 @@ jobs: images: ghcr.io/openimsdk/openim-server # generate Docker tags based on the following events/attributes tags: | + type=ref,event=tag type=schedule type=ref,event=branch type=ref,event=pr diff --git a/.github/workflows/build-openim-web-image.yml b/.github/workflows/build-openim-web-image.yml deleted file mode 100644 index 999c2e1e3..000000000 --- a/.github/workflows/build-openim-web-image.yml +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright © 2023 OpenIM open source community. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -name: Build OpenIM Web Docker image - -on: -# schedule: -# - cron: '30 3 * * *' - push: - branches: - # - main - - release-* - tags: - - v* - workflow_dispatch: - -env: - # Common versions - GO_VERSION: "1.20" - -jobs: - build-openim-web-dockerhub: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - -# docker.io/openim/openim-web:latest - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5.0.0 - with: - images: openim/openim-web - # generate Docker tags based on the following events/attributes - tags: | - type=schedule - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - file: ./build/images/openim-tools/openim-web/Dockerfile - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - build-openim-web-aliyun: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 -# registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web:latest - - name: Extract metadata (tags, labels) for Docker - id: meta2 - uses: docker/metadata-action@v5.0.0 - with: - images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web - - - name: Log in to AliYun Docker Hub - uses: docker/login-action@v3 - with: - registry: registry.cn-hangzhou.aliyuncs.com - username: ${{ secrets.ALIREGISTRY_USERNAME }} - password: ${{ secrets.ALIREGISTRY_TOKEN }} - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - file: ./build/images/openim-tools/openim-web/Dockerfile - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta2.outputs.tags }} - labels: ${{ steps.meta2.outputs.labels }} - - build-openim-web-ghcr: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 -# ghcr.io/openimsdk/openim-web:latest - - name: Extract metadata (tags, labels) for Docker - id: meta2 - uses: docker/metadata-action@v5.0.0 - with: - images: ghcr.io/openimsdk/openim-web - - - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - file: ./build/images/openim-tools/openim-web/Dockerfile - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta2.outputs.tags }} - labels: ${{ steps.meta2.outputs.labels }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 675ce10c7..fb8d428d2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,10 +32,13 @@ _output/ deployments/charts/generated-configs/ ### OpenIM Config ### -config/config.yaml -./config/config.yaml .env -./.env +config/config.yaml +config/alertmanager.yml +config/prometheus.yml +config/email.tmpl +config/notification.yaml +config/instance-down-rules.yml ### OpenIM deploy ### deployments/openim-server/charts @@ -388,8 +391,4 @@ Sessionx.vim # End of https://www.toptal.com/developers/gitignore/api/go,git,vim,tags,test,emacs,backup,jetbrains .idea -dist/ -.env -config/config.yaml -config/alertmanager.yml -config/prometheus.yml \ No newline at end of file +dist/ \ No newline at end of file diff --git a/config/Readme.md b/config/Readme.md new file mode 100644 index 000000000..72f4577a5 --- /dev/null +++ b/config/Readme.md @@ -0,0 +1,243 @@ +# OpenIM Configuration Guide + + +* 1. [Directory Structure and File Descriptions](#DirectoryStructureandFileDescriptions) + * 1.1. [Directory Structure](#DirectoryStructure) + * 1.2. [Directory Structure Explanation](#DirectoryStructureExplanation) +* 2. [File Descriptions](#FileDescriptions) + * 2.1. [Files in the Root Directory](#FilesintheRootDirectory) + * 2.2. [Files in the `templates/` Directory](#FilesinthetemplatesDirectory) +* 3. [Configuration File Generation](#ConfigurationFileGeneration) + * 3.1. [How to Use `init-config.sh` Script](#HowtoUseinit-config.shScript) + * 3.2. [Examples of Operations](#ExamplesofOperations) + * 3.3. [Points to Note](#PointstoNote) +* 4. [Example Directory](#ExampleDirectory) + * 4.1. [Overview](#Overview) + * 4.2. [Structure](#Structure) + * 4.3. [How to Use These Examples](#HowtoUseTheseExamples) + * 4.4. [Tips for Using Example Files:](#TipsforUsingExampleFiles:) +* 5. [Configuration Item Descriptions](#ConfigurationItemDescriptions) +* 6. [Version Management and Upgrading](#VersionManagementandUpgrading) + * 6.1. [Pulling the Latest Code](#PullingtheLatestCode) + * 6.2. [Generating the Latest Example Configuration Files](#GeneratingtheLatestExampleConfigurationFiles) + * 6.3. [Comparing Configuration File Differences](#ComparingConfigurationFileDifferences) + * 6.4. [Updating Configuration Files](#UpdatingConfigurationFiles) + * 6.5. [Updating Binary Files and Restarting Services](#UpdatingBinaryFilesandRestartingServices) + * 6.6. [Best Practices for Version Management](#BestPracticesforVersionManagement) +* 7. [How to Contribute](#HowtoContribute) + * 7.1. [OpenIM Configuration Item Descriptions](#OpenIMConfigurationItemDescriptions) + * 7.2. [Modifying Template Files](#ModifyingTemplateFiles) + * 7.3. [Updating Configuration Center Scripts](#UpdatingConfigurationCenterScripts) + * 7.4. [Configuration File Generation Process](#ConfigurationFileGenerationProcess) + * 7.5. [Contribution Guidelines](#ContributionGuidelines) + * 7.6. [Submission and Review](#SubmissionandReview) + + + + + +## 1. Directory Structure and File Descriptions + +This document details the structure of the `config` directory, aiding users in understanding and managing configuration files. + +### 1.1. Directory Structure + +```bash +$ tree config +├── alertmanager.yml +├── config.yaml +├── email.tmpl +├── instance-down-rules.yml +├── notification.yaml +├── prometheus.yml +├── Readme.md +└── templates + ├── alertmanager.yml.template + ├── config.yaml.template + ├── email.tmpl.template + ├── env.template + ├── instance-down-rules.yml.template + ├── notification.yaml.template + ├── open-im-ng-example.conf + ├── prometheus-dashboard.yaml + └── prometheus.yml.template +``` + +### 1.2. Directory Structure Explanation + +- **Root Directory (`config/`)**: Contains actual configuration files and the `templates` subdirectory. +- **`templates/` Subdirectory**: Stores configuration templates for generating or updating configuration files in the root directory. + +## 2. File Descriptions + +### 2.1. Files in the Root Directory + +- **`alertmanager.yml`**: Configuration file for AlertManager, managing and setting up the alert system. +- **`config.yaml`**: The main application configuration file, covering service settings. +- **`email.tmpl`**: Template file for email notifications, defining email format and content. +- **`instance-down-rules.yml`**: Instance downtime rules configuration file for the monitoring system. +- **`notification.yaml`**: Configuration file for notification settings, defining different types of notifications. +- **`prometheus.yml`**: Configuration file for the Prometheus monitoring system, setting monitoring metrics and rules. + +### 2.2. Files in the `templates/` Directory + +- **`alertmanager.yml.template`**: Template for AlertManager configuration. +- **`config.yaml.template`**: Main configuration template for the application. +- **`email.tmpl.template`**: Template for email notifications. +- **`env.template`**: Template for environmental variable configurations, setting environment-related configurations. +- **`instance-down-rules.yml.template`**: Template for instance downtime rules. +- **`notification.yaml.template`**: Template for notification settings. +- **`open-im-ng-example.conf`**: Example configuration file for the application. +- **`prometheus-dashboard.yaml`**: Prometheus dashboard configuration file, specific to the OpenIM application. +- **`prometheus.yml.template`**: Template for Prometheus configuration. + +## 3. Configuration File Generation + +Configuration files can be automatically generated using the `make init` command or the `./scripts/init-config.sh` script. These scripts conveniently extract templates from the `templates` directory and generate or update actual configuration files in the root directory. + +### 3.1. How to Use `init-config.sh` Script + +```bash +$ ./scripts/init-config.sh --help +Usage: init-config.sh [options] +Options: + -h, --help Show this help message + --force Overwrite existing files without prompt + --skip Skip generation if file exists + --examples Generate example files + --clean-config Clean all configuration files + --clean-examples Clean all example files +``` + +### 3.2. Examples of Operations + +- Generate all template configuration files: + + ```bash + $ ./scripts/init-config.sh --examples + ``` + +- Force overwrite existing configuration files: + + ```bash + $ ./scripts/init-config.sh --force + ``` + +### 3.3. Points to Note + +- **Template files should not be directly modified**: Files in the `template` directory are templates included in source code management. Direct modification may lead to version conflicts or management issues. +- **Operations for Windows Users**: Windows users can use the `cp` command to copy files from the `template` directory to the `config/` directory and then modify the configuration items as needed. + +## 4. Example Directory + +Welcome to our project's `examples` directory! This directory contains a range of example files, showcasing various configurations and settings of our software. These examples are intended to provide you with templates that can serve as a starting point for your own configurations. + +### 4.1. Overview + +In this directory, you'll find examples suitable for a variety of use cases. Each file is a template with default values and configurations, demonstrating best practices and typical scenarios. Whether you're just getting started or looking to implement complex settings, these examples should help you get on the right track. + +### 4.2. Structure + +Here's a quick overview of the contents in this directory: + +- `env-example.yaml`: Demonstrates how to set up environmental variables. +- `openim-example.yaml`: Example configuration file for the OpenIM application. +- `prometheus-example.yml`: Example configuration for monitoring with Prometheus. +- `alertmanager-example.yml`: Template for setting up Alertmanager configuration. + +### 4.3. How to Use These Examples + +To use these examples, simply copy the relevant files to your working directory and rename them as needed (for example, removing the `-example` suffix). Then, modify the files according to your needs. + +### 4.4. Tips for Using Example Files: + +1. **Read Comments**: Each file contains comments explaining the various sections and settings. Make sure to read these comments for a better understanding of how to customize the file. +2. **Check Required Changes**: Some examples might require mandatory changes before they can be used effectively (such as setting specific environmental variables). +3. **Version Compatibility**: Ensure that the example files are compatible with the version of the software you are using. + +## 5. Configuration Item Descriptions + +## 6. Version Management and Upgrading + +When managing and upgrading the `config` directory's versions, it is crucial to ensure that the configuration files in both the local `config/` and `config/templates/` directories are kept in sync. This process can ensure that your configuration files are consistent with the latest standard templates, while also maintaining custom settings. + +### 6.1. Pulling the Latest Code + +First, ensure that your local repository is in sync with the remote repository. This can be achieved by pulling the latest code: + +```bash +$ git pull +``` + +### 6.2. Generating the Latest Example Configuration Files + +Next, generate the latest example configuration files. This can be done by running the `init-config.sh` script, using the `--examples` option to generate example files, and the `--skip` option to avoid overwriting existing configuration files: + +```bash +$ ./scripts/init-config.sh --examples --skip +``` + +### 6.3. Comparing Configuration File Differences + +Once the latest example configuration files are generated, you need to compare the configuration files in the `config/` and `config/templates/` directories to find any potential differences. This step ensures that you can identify and integrate any important updates or changes. Tools like `diff` can be helpful in completing this step: + +```bash +$ diff -ur config/ config/templates/ +``` + +### 6.4. Updating Configuration Files + +Based on the comparison results, manually update the configuration files in the `config/` directory to reflect the latest configurations in `config/templates/`. During this process, ensure to retain any custom configuration settings. + +### 6.5. Updating Binary Files and Restarting Services + +After updating the configuration files, the next step is to update any related binary files. This typically involves downloading and installing the latest version of the application or service. Depending on the specific application or service, this might involve running specific update scripts or directly downloading the latest version from official sources. + +Once the binary files are updated, the services need to be restarted to apply the new configurations. Make sure to conduct necessary checks before restarting to ensure the correctness of the configurations. + +### 6.6. Best Practices for Version Management + +- **Record Changes**: When committing changes to a version control system, ensure to log detailed change logs. +- **Stay Synced**: Regularly sync with the remote repository to ensure that your local configurations are in line with the latest developments. +- **Backup**: Backup your current configurations before making any significant changes, so that you can revert to a previous state if necessary. + +By following these steps and best practices, you can ensure effective management and smooth upgrading of your `config` directory. + +## 7. How to Contribute + +If you have an understanding of the logic behind OpenIM's configuration generation, then you will clearly know where to make modifications to contribute code. + +### 7.1. OpenIM Configuration Item Descriptions + +First, it is recommended to read the [OpenIM Configuration Items Document](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md). This will help you understand the roles of various configuration items and how they affect the operation of OpenIM. + +### 7.2. Modifying Template Files + +To contribute to OpenIM, focus on the `./deployments/templates` directory. This contains various configuration template files, which are the basis for generating the final configuration files. + +When making modifications, ensure that your changes align with OpenIM's configuration requirements and logic. This may involve adding new template files or modifying existing files to reflect new configuration options or structural changes. + +### 7.3. Updating Configuration Center Scripts + +In addition to modifying template files, pay attention to the `./scripts/install/environment.sh` script. In this script, you may need to add or modify environment variables. + +This script is responsible for defining environment variables that influence configuration generation. Therefore, any new configuration items or modifications to existing items need to be reflected here. + +### 7.4. Configuration File Generation Process + +The essence of the `make init` command is to use the environment variables defined in `/scripts/install/environment.sh` to render the template files in the `./deployments/templates` directory, thereby generating the final configuration files. + +When contributing code, ensure that your changes work smoothly in this process and do not cause errors during configuration file generation. + +### 7.5. Contribution Guidelines + +- **Code Review**: Ensure your changes have passed code review. This typically means that the code should be clear, easy to understand, and adhere to the project's coding style and best practices. +- **Testing**: Before submitting changes, conduct thorough tests to ensure new or modified configurations work as expected and do not negatively impact existing functionalities. +- **Documentation**: If you have added a new configuration option or made significant changes to an existing one, update the relevant documentation to assist other users and developers in understanding and utilizing these changes. + +### 7.6. Submission and Review + +After completing your changes, submit your code to the OpenIM repository in the form of a Pull Request (PR). The PR will be reviewed by the project maintainers and you may be asked to make further modifications or provide additional information. \ No newline at end of file diff --git a/config/templates/README.md b/config/templates/README.md deleted file mode 100644 index 6a979c6bb..000000000 --- a/config/templates/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Examples Directory - -Welcome to the `examples` directory of our project! This directory contains a collection of example files that demonstrate various configurations and setups for our software. These examples are designed to provide you with templates that can be used as a starting point for your own configurations. - -## Overview - -In this directory, you'll find examples for a variety of use cases. Each file is a template with default values and configurations that illustrate best practices and typical scenarios. Whether you're just getting started or looking to implement a complex setup, these examples should help you get on the right track. - -## Structure - -Here's a quick overview of what you'll find in this directory: - -+ `env-example.yaml`: Demonstrates how to set up environment variables. -+ `openim-example.yaml`: A sample configuration file for the OpenIM application. -+ `prometheus-example.yml`: An example Prometheus configuration for monitoring. -+ `alertmanager-example.yml`: A template for setting up Alertmanager configurations. - -## How to Use These Examples - -To use these examples, simply copy the relevant file to your working directory and rename it as needed (e.g., removing the `-example` suffix). Then, modify the file according to your requirements. - -### Tips for Using Example Files: - -1. **Read the Comments**: Each file contains comments that explain various sections and settings. Make sure to read these comments for a better understanding of how to customize the file. -2. **Check for Required Changes**: Some examples might require mandatory changes (like setting specific environment variables) before they can be used effectively. -3. **Version Compatibility**: Ensure that the example files are compatible with the version of the software you are using. - -## Contributing - -If you have a configuration that you believe would be beneficial to others, please feel free to contribute by opening a pull request with your proposed changes. We appreciate contributions that expand our examples with new scenarios and use cases. - -## Support - -If you encounter any issues or have questions regarding the example files, please open an issue on our repository. Our community is here to help you navigate through any challenges you might face. - -Thank you for exploring our examples, and we hope they will be helpful in setting up and configuring your environment! diff --git a/config/templates/alertmanager.yml.template b/config/templates/alertmanager.yml.template index da5f99b19..a0daadfbd 100644 --- a/config/templates/alertmanager.yml.template +++ b/config/templates/alertmanager.yml.template @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + ###################### AlertManager Configuration ###################### # AlertManager configuration using environment variables # diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template index 7eb082b24..fd51a2e31 100644 --- a/config/templates/config.yaml.template +++ b/config/templates/config.yaml.template @@ -37,13 +37,20 @@ zookeeper: ###################### Mongo ###################### # MongoDB configuration -# If uri is not empty, it will be used directly -# -# MongoDB address for standalone setup, Mongos address for sharded cluster setup -# Default MongoDB database name -# Maximum connection pool size + +# If uri is not empty, it will be used directly for the MongoDB connection. +# This is a complete MongoDB URI string. +# Example: mongodb://user:password@host1:port1,host2:port2/dbname?options mongo: uri: '' + +# List of MongoDB server addresses. +# Used for constructing the MongoDB URI if 'uri' above is empty. +# For a standalone setup, specify the address of the single server. +# For a sharded cluster, specify the addresses of the Mongos servers. +# Example: [ '172.28.0.1:37017', '172.28.0.2:37017' ] +# Default MongoDB database name +# Maximum connection pool size address: [ 172.28.0.1:37017 ] database: openIM_v3 username: root diff --git a/config/email.tmpl b/config/templates/email.tmpl.template similarity index 100% rename from config/email.tmpl rename to config/templates/email.tmpl.template diff --git a/config/templates/env.template b/config/templates/env.template index 54218c330..ffcec89e5 100644 --- a/config/templates/env.template +++ b/config/templates/env.template @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # ====================================== # ========= Basic Configuration ======== # ====================================== @@ -10,10 +24,6 @@ USER=root # Default: PASSWORD=openIM123 PASSWORD=openIM123 -# Endpoint for the MinIO object storage service. -# Default: MINIO_ENDPOINT=http://172.28.0.1:10005 -MINIO_ENDPOINT=http://172.28.0.1:10005 - # Base URL for the application programming interface (API). # Default: API_URL=http://172.28.0.1:10002 API_URL=http://14.155.64.202:10002 diff --git a/config/templates/instance-down-rules.yml.template b/config/templates/instance-down-rules.yml.template new file mode 100644 index 000000000..7a6e9fda9 --- /dev/null +++ b/config/templates/instance-down-rules.yml.template @@ -0,0 +1,36 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +groups: + - name: instance_down + rules: + - alert: InstanceDown + expr: up == 0 + for: 1m + labels: + severity: critical + annotations: + summary: "Instance {{ $labels.instance }} down" + description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minutes." + + - name: database_insert_failure_alerts + rules: + - alert: DatabaseInsertFailed + expr: (increase(msg_insert_redis_failed_total[5m]) > 0) or (increase(msg_insert_mongo_failed_total[5m]) > 0) + for: 1m + labels: + severity: critical + annotations: + summary: "Increase in MsgInsertRedisFailedCounter or MsgInsertMongoFailedCounter detected" + description: "Either MsgInsertRedisFailedCounter or MsgInsertMongoFailedCounter has increased in the last 5 minutes, indicating failures in message insert operations to Redis or MongoDB,maybe the redis or mongodb is crash." diff --git a/config/templates/notification.yaml.template b/config/templates/notification.yaml.template new file mode 100644 index 000000000..665c21261 --- /dev/null +++ b/config/templates/notification.yaml.template @@ -0,0 +1,354 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Determines if a message should be sent. If set to false, it triggers a silent sync without a message. If true, it requires triggering a conversation. +# For rpc notification, send twice: once as a message and once as a notification. +# The options field 'isNotification' indicates if it's a notification. +groupCreated: + isSendMsg: true + +# Reliability level of the message sending. +# Set to 1 to send only when online, 2 for guaranteed delivery. + reliabilityLevel: 1 + +# This setting is effective only when 'isSendMsg' is true. +# It controls whether to count unread messages. + unreadCount: false + +# Configuration for offline push notifications. + offlinePush: + # Enables or disables offline push notifications. + enable: false + + # Title for the notification when a group is created. + title: "create group title" + + # Description for the notification. + desc: "create group desc" + + # Additional information for the notification. + ext: "create group ext" + +# Content type is not added here. +# Content should use a JSON structure conforming to the protobuf format. + +groupInfoSet: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupInfoSet title" + desc: "groupInfoSet desc" + ext: "groupInfoSet ext" + + +joinGroupApplication: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "joinGroupApplication title" + desc: "joinGroupApplication desc" + ext: "joinGroupApplication ext" + +memberQuit: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "memberQuit title" + desc: "memberQuit desc" + ext: "memberQuit ext" + +groupApplicationAccepted: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupApplicationAccepted title" + desc: "groupApplicationAccepted desc" + ext: "groupApplicationAccepted ext" + +groupApplicationRejected: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: " title" + desc: " desc" + ext: " ext" + + +groupOwnerTransferred: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupOwnerTransferred title" + desc: "groupOwnerTransferred desc" + ext: "groupOwnerTransferred ext" + +memberKicked: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "memberKicked title" + desc: "memberKicked desc" + ext: "memberKicked ext" + +memberInvited: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "memberInvited title" + desc: "memberInvited desc" + ext: "memberInvited ext" + +memberEnter: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "memberEnter title" + desc: "memberEnter desc" + ext: "memberEnter ext" + +groupDismissed: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupDismissed title" + desc: "groupDismissed desc" + ext: "groupDismissed ext" + +groupMuted: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupMuted title" + desc: "groupMuted desc" + ext: "groupMuted ext" + +groupCancelMuted: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupCancelMuted title" + desc: "groupCancelMuted desc" + ext: "groupCancelMuted ext" + defaultTips: + tips: "group Cancel Muted" + + +groupMemberMuted: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupMemberMuted title" + desc: "groupMemberMuted desc" + ext: "groupMemberMuted ext" + +groupMemberCancelMuted: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupMemberCancelMuted title" + desc: "groupMemberCancelMuted desc" + ext: "groupMemberCancelMuted ext" + +groupMemberInfoSet: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupMemberInfoSet title" + desc: "groupMemberInfoSet desc" + ext: "groupMemberInfoSet ext" + +groupInfoSetAnnouncement: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupInfoSetAnnouncement title" + desc: "groupInfoSetAnnouncement desc" + ext: "groupInfoSetAnnouncement ext" + + +groupInfoSetName: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "groupInfoSetName title" + desc: "groupInfoSetName desc" + ext: "groupInfoSetName ext" + + +#############################friend################################# +friendApplicationAdded: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "Somebody applies to add you as a friend" + desc: "Somebody applies to add you as a friend" + ext: "Somebody applies to add you as a friend" + +friendApplicationApproved: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "Someone applies to add your friend application" + desc: "Someone applies to add your friend application" + ext: "Someone applies to add your friend application" + +friendApplicationRejected: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "Someone rejected your friend application" + desc: "Someone rejected your friend application" + ext: "Someone rejected your friend application" + +friendAdded: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "We have become friends" + desc: "We have become friends" + ext: "We have become friends" + +friendDeleted: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "deleted a friend" + desc: "deleted a friend" + ext: "deleted a friend" + +friendRemarkSet: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "Your friend's profile has been changed" + desc: "Your friend's profile has been changed" + ext: "Your friend's profile has been changed" + +blackAdded: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "blocked a user" + desc: "blocked a user" + ext: "blocked a user" + +blackDeleted: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "Remove a blocked user" + desc: "Remove a blocked user" + ext: "Remove a blocked user" + +friendInfoUpdated: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "friend info updated" + desc: "friend info updated" + ext: "friend info updated" + +#####################user######################### +userInfoUpdated: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "Remove a blocked user" + desc: "Remove a blocked user" + ext: "Remove a blocked user" + +userStatusChanged: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: false + title: "user status changed" + desc: "user status changed" + ext: "user status changed" + +#####################conversation######################### +conversationChanged: + isSendMsg: false + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "conversation changed" + desc: "conversation changed" + ext: "conversation changed" + +conversationSetPrivate: + isSendMsg: true + reliabilityLevel: 1 + unreadCount: false + offlinePush: + enable: true + title: "burn after reading" + desc: "burn after reading" + ext: "burn after reading" diff --git a/config/open-im-ng-example.conf b/config/templates/open-im-ng-example.conf similarity index 100% rename from config/open-im-ng-example.conf rename to config/templates/open-im-ng-example.conf diff --git a/config/prometheus-dashboard.yaml b/config/templates/prometheus-dashboard.yaml similarity index 98% rename from config/prometheus-dashboard.yaml rename to config/templates/prometheus-dashboard.yaml index 0e7823797..e1b569df3 100644 --- a/config/prometheus-dashboard.yaml +++ b/config/templates/prometheus-dashboard.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + { "annotations": { "list": [ diff --git a/config/templates/prometheus.yml.template b/config/templates/prometheus.yml.template index 7950c5d33..709fe9754 100644 --- a/config/templates/prometheus.yml.template +++ b/config/templates/prometheus.yml.template @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # my global config global: scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. diff --git a/deployments/README.md b/deployments/Readme.md similarity index 100% rename from deployments/README.md rename to deployments/Readme.md diff --git a/deployments/charts/helmfile.yaml b/deployments/charts/helmfile.yaml index a6a009257..eb064be9a 100644 --- a/deployments/charts/helmfile.yaml +++ b/deployments/charts/helmfile.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- define "defaultValues" -}} - ./generated-configs/helm-image.yaml - ./generated-configs/config.yaml diff --git a/deployments/charts/openim-api/Chart.yaml b/deployments/charts/openim-api/Chart.yaml index 74779b64a..e79d2a2c2 100644 --- a/deployments/charts/openim-api/Chart.yaml +++ b/deployments/charts/openim-api/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-api description: A OpenIM Api Helm chart for Kubernetes diff --git a/deployments/charts/openim-api/templates/app-cm.yaml b/deployments/charts/openim-api/templates/app-cm.yaml index 7a6f23314..9d4e96e8b 100644 --- a/deployments/charts/openim-api/templates/app-cm.yaml +++ b/deployments/charts/openim-api/templates/app-cm.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: ConfigMap metadata: diff --git a/deployments/charts/openim-api/templates/deployment.yaml b/deployments/charts/openim-api/templates/deployment.yaml index 27bfa1f13..3b4bf57a2 100644 --- a/deployments/charts/openim-api/templates/deployment.yaml +++ b/deployments/charts/openim-api/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-api/templates/hpa.yaml b/deployments/charts/openim-api/templates/hpa.yaml index 0e5848181..dc0742a25 100644 --- a/deployments/charts/openim-api/templates/hpa.yaml +++ b/deployments/charts/openim-api/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-api/templates/ingress.yaml b/deployments/charts/openim-api/templates/ingress.yaml index 62c66c135..55bc69710 100644 --- a/deployments/charts/openim-api/templates/ingress.yaml +++ b/deployments/charts/openim-api/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-api.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-api/templates/service.yaml b/deployments/charts/openim-api/templates/service.yaml index eb37fa56c..3704bf35c 100644 --- a/deployments/charts/openim-api/templates/service.yaml +++ b/deployments/charts/openim-api/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-api/templates/serviceaccount.yaml b/deployments/charts/openim-api/templates/serviceaccount.yaml index e3e7b2849..556a71e34 100644 --- a/deployments/charts/openim-api/templates/serviceaccount.yaml +++ b/deployments/charts/openim-api/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-api/values.yaml b/deployments/charts/openim-api/values.yaml index e41fb6e76..4208335de 100644 --- a/deployments/charts/openim-api/values.yaml +++ b/deployments/charts/openim-api/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-api. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-msggateway/Chart.yaml b/deployments/charts/openim-msggateway/Chart.yaml index c8c380bf9..fb6d0d153 100644 --- a/deployments/charts/openim-msggateway/Chart.yaml +++ b/deployments/charts/openim-msggateway/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-msggateway description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-msggateway/templates/hpa.yaml b/deployments/charts/openim-msggateway/templates/hpa.yaml index e1fbe50a6..99121afba 100644 --- a/deployments/charts/openim-msggateway/templates/hpa.yaml +++ b/deployments/charts/openim-msggateway/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-msggateway/templates/ingress.yaml b/deployments/charts/openim-msggateway/templates/ingress.yaml index 5c1c24078..0e22e1936 100644 --- a/deployments/charts/openim-msggateway/templates/ingress.yaml +++ b/deployments/charts/openim-msggateway/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-msggateway.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-msggateway/templates/service.yaml b/deployments/charts/openim-msggateway/templates/service.yaml index 2ed58a869..e33fce6db 100644 --- a/deployments/charts/openim-msggateway/templates/service.yaml +++ b/deployments/charts/openim-msggateway/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-msggateway/templates/serviceaccount.yaml b/deployments/charts/openim-msggateway/templates/serviceaccount.yaml index 6b47c12c5..718880d71 100644 --- a/deployments/charts/openim-msggateway/templates/serviceaccount.yaml +++ b/deployments/charts/openim-msggateway/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-msggateway/values.yaml b/deployments/charts/openim-msggateway/values.yaml index d82c674fc..059601807 100644 --- a/deployments/charts/openim-msggateway/values.yaml +++ b/deployments/charts/openim-msggateway/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-msggateway. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-msgtransfer/Chart.yaml b/deployments/charts/openim-msgtransfer/Chart.yaml index bba7a047f..37d897728 100644 --- a/deployments/charts/openim-msgtransfer/Chart.yaml +++ b/deployments/charts/openim-msgtransfer/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-msgtransfer description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-msgtransfer/templates/deployment.yaml b/deployments/charts/openim-msgtransfer/templates/deployment.yaml index adb8ae737..2c9e24bdd 100644 --- a/deployments/charts/openim-msgtransfer/templates/deployment.yaml +++ b/deployments/charts/openim-msgtransfer/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-msgtransfer/templates/hpa.yaml b/deployments/charts/openim-msgtransfer/templates/hpa.yaml index 75c7d4fef..89921bf30 100644 --- a/deployments/charts/openim-msgtransfer/templates/hpa.yaml +++ b/deployments/charts/openim-msgtransfer/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-msgtransfer/templates/ingress.yaml b/deployments/charts/openim-msgtransfer/templates/ingress.yaml index c9968a438..ab28a9e71 100644 --- a/deployments/charts/openim-msgtransfer/templates/ingress.yaml +++ b/deployments/charts/openim-msgtransfer/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-msgtransfer.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-msgtransfer/templates/service.yaml b/deployments/charts/openim-msgtransfer/templates/service.yaml index 839e520e5..e657f8c18 100644 --- a/deployments/charts/openim-msgtransfer/templates/service.yaml +++ b/deployments/charts/openim-msgtransfer/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-msgtransfer/templates/serviceaccount.yaml b/deployments/charts/openim-msgtransfer/templates/serviceaccount.yaml index 2e3ca4ee7..78816bd80 100644 --- a/deployments/charts/openim-msgtransfer/templates/serviceaccount.yaml +++ b/deployments/charts/openim-msgtransfer/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-msgtransfer/values.yaml b/deployments/charts/openim-msgtransfer/values.yaml index d4a792d17..6e26d72c8 100644 --- a/deployments/charts/openim-msgtransfer/values.yaml +++ b/deployments/charts/openim-msgtransfer/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-msgtransfer. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-push/Chart.yaml b/deployments/charts/openim-push/Chart.yaml index 93e134879..966769b00 100644 --- a/deployments/charts/openim-push/Chart.yaml +++ b/deployments/charts/openim-push/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-push description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-push/templates/deployment.yaml b/deployments/charts/openim-push/templates/deployment.yaml index 684e76e02..34de33e10 100644 --- a/deployments/charts/openim-push/templates/deployment.yaml +++ b/deployments/charts/openim-push/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-push/templates/hpa.yaml b/deployments/charts/openim-push/templates/hpa.yaml index 89c89c041..40c77b048 100644 --- a/deployments/charts/openim-push/templates/hpa.yaml +++ b/deployments/charts/openim-push/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-push/templates/ingress.yaml b/deployments/charts/openim-push/templates/ingress.yaml index b00fda3d3..6638f256d 100644 --- a/deployments/charts/openim-push/templates/ingress.yaml +++ b/deployments/charts/openim-push/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-push.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-push/templates/service.yaml b/deployments/charts/openim-push/templates/service.yaml index 4d8bb0457..b38c35375 100644 --- a/deployments/charts/openim-push/templates/service.yaml +++ b/deployments/charts/openim-push/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-push/templates/serviceaccount.yaml b/deployments/charts/openim-push/templates/serviceaccount.yaml index e22115724..66dfedfdf 100644 --- a/deployments/charts/openim-push/templates/serviceaccount.yaml +++ b/deployments/charts/openim-push/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-push/values.yaml b/deployments/charts/openim-push/values.yaml index dd6f0faf6..3348fe79d 100644 --- a/deployments/charts/openim-push/values.yaml +++ b/deployments/charts/openim-push/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-push. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-rpc-auth/Chart.yaml b/deployments/charts/openim-rpc-auth/Chart.yaml index 97848dbf2..8e8fb03b4 100644 --- a/deployments/charts/openim-rpc-auth/Chart.yaml +++ b/deployments/charts/openim-rpc-auth/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-rpc-auth description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-rpc-auth/templates/deployment.yaml b/deployments/charts/openim-rpc-auth/templates/deployment.yaml index 4dbc49731..202162775 100644 --- a/deployments/charts/openim-rpc-auth/templates/deployment.yaml +++ b/deployments/charts/openim-rpc-auth/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-rpc-auth/templates/hpa.yaml b/deployments/charts/openim-rpc-auth/templates/hpa.yaml index 20108afbf..e99536cf1 100644 --- a/deployments/charts/openim-rpc-auth/templates/hpa.yaml +++ b/deployments/charts/openim-rpc-auth/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-rpc-auth/templates/ingress.yaml b/deployments/charts/openim-rpc-auth/templates/ingress.yaml index f14458c52..ece395de7 100644 --- a/deployments/charts/openim-rpc-auth/templates/ingress.yaml +++ b/deployments/charts/openim-rpc-auth/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-rpc-auth.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-rpc-auth/templates/service.yaml b/deployments/charts/openim-rpc-auth/templates/service.yaml index ef7b00b86..3674da014 100644 --- a/deployments/charts/openim-rpc-auth/templates/service.yaml +++ b/deployments/charts/openim-rpc-auth/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-rpc-auth/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-auth/templates/serviceaccount.yaml index f13dcca81..555d4f6ff 100644 --- a/deployments/charts/openim-rpc-auth/templates/serviceaccount.yaml +++ b/deployments/charts/openim-rpc-auth/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-rpc-auth/values.yaml b/deployments/charts/openim-rpc-auth/values.yaml index a6db6716c..93fa68b87 100644 --- a/deployments/charts/openim-rpc-auth/values.yaml +++ b/deployments/charts/openim-rpc-auth/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-rpc-auth. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-rpc-conversation/Chart.yaml b/deployments/charts/openim-rpc-conversation/Chart.yaml index 090d63127..0ca8f5513 100644 --- a/deployments/charts/openim-rpc-conversation/Chart.yaml +++ b/deployments/charts/openim-rpc-conversation/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-rpc-conversation description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-rpc-conversation/templates/deployment.yaml b/deployments/charts/openim-rpc-conversation/templates/deployment.yaml index 13dd5c531..01721aa30 100644 --- a/deployments/charts/openim-rpc-conversation/templates/deployment.yaml +++ b/deployments/charts/openim-rpc-conversation/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-rpc-conversation/templates/hpa.yaml b/deployments/charts/openim-rpc-conversation/templates/hpa.yaml index a2378bfa0..524245562 100644 --- a/deployments/charts/openim-rpc-conversation/templates/hpa.yaml +++ b/deployments/charts/openim-rpc-conversation/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-rpc-conversation/templates/ingress.yaml b/deployments/charts/openim-rpc-conversation/templates/ingress.yaml index 224591f67..078c472b8 100644 --- a/deployments/charts/openim-rpc-conversation/templates/ingress.yaml +++ b/deployments/charts/openim-rpc-conversation/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-rpc-conversation.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-rpc-conversation/templates/service.yaml b/deployments/charts/openim-rpc-conversation/templates/service.yaml index be8355154..f90673584 100644 --- a/deployments/charts/openim-rpc-conversation/templates/service.yaml +++ b/deployments/charts/openim-rpc-conversation/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-rpc-conversation/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-conversation/templates/serviceaccount.yaml index 4e2d0e29f..14b1b2129 100644 --- a/deployments/charts/openim-rpc-conversation/templates/serviceaccount.yaml +++ b/deployments/charts/openim-rpc-conversation/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-rpc-conversation/values.yaml b/deployments/charts/openim-rpc-conversation/values.yaml index 1b3e1e3de..bb88ab613 100644 --- a/deployments/charts/openim-rpc-conversation/values.yaml +++ b/deployments/charts/openim-rpc-conversation/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-rpc-conversation. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-rpc-friend/Chart.yaml b/deployments/charts/openim-rpc-friend/Chart.yaml index d7e4a9fef..62e92db9b 100644 --- a/deployments/charts/openim-rpc-friend/Chart.yaml +++ b/deployments/charts/openim-rpc-friend/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-rpc-friend description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-rpc-friend/templates/deployment.yaml b/deployments/charts/openim-rpc-friend/templates/deployment.yaml index 227ef1144..a57188828 100644 --- a/deployments/charts/openim-rpc-friend/templates/deployment.yaml +++ b/deployments/charts/openim-rpc-friend/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-rpc-friend/templates/hpa.yaml b/deployments/charts/openim-rpc-friend/templates/hpa.yaml index 7c4f14b7c..ae88e2621 100644 --- a/deployments/charts/openim-rpc-friend/templates/hpa.yaml +++ b/deployments/charts/openim-rpc-friend/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-rpc-friend/templates/ingress.yaml b/deployments/charts/openim-rpc-friend/templates/ingress.yaml index b5d411743..0845aa783 100644 --- a/deployments/charts/openim-rpc-friend/templates/ingress.yaml +++ b/deployments/charts/openim-rpc-friend/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-rpc-friend.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-rpc-friend/templates/service.yaml b/deployments/charts/openim-rpc-friend/templates/service.yaml index 792592d87..e445d561f 100644 --- a/deployments/charts/openim-rpc-friend/templates/service.yaml +++ b/deployments/charts/openim-rpc-friend/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-rpc-friend/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-friend/templates/serviceaccount.yaml index c81343f6b..5146d6781 100644 --- a/deployments/charts/openim-rpc-friend/templates/serviceaccount.yaml +++ b/deployments/charts/openim-rpc-friend/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-rpc-friend/values.yaml b/deployments/charts/openim-rpc-friend/values.yaml index 041665a81..34dcda9da 100644 --- a/deployments/charts/openim-rpc-friend/values.yaml +++ b/deployments/charts/openim-rpc-friend/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-rpc-friend. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-rpc-group/Chart.yaml b/deployments/charts/openim-rpc-group/Chart.yaml index 8e037caea..c3f7e3bfa 100644 --- a/deployments/charts/openim-rpc-group/Chart.yaml +++ b/deployments/charts/openim-rpc-group/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-rpc-group description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-rpc-group/templates/deployment.yaml b/deployments/charts/openim-rpc-group/templates/deployment.yaml index 74ebe6c92..406d0b342 100644 --- a/deployments/charts/openim-rpc-group/templates/deployment.yaml +++ b/deployments/charts/openim-rpc-group/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-rpc-group/templates/hpa.yaml b/deployments/charts/openim-rpc-group/templates/hpa.yaml index 0ba0e8283..91f313abe 100644 --- a/deployments/charts/openim-rpc-group/templates/hpa.yaml +++ b/deployments/charts/openim-rpc-group/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-rpc-group/templates/ingress.yaml b/deployments/charts/openim-rpc-group/templates/ingress.yaml index 6a744f914..e3cad781a 100644 --- a/deployments/charts/openim-rpc-group/templates/ingress.yaml +++ b/deployments/charts/openim-rpc-group/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-rpc-group.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-rpc-group/templates/service.yaml b/deployments/charts/openim-rpc-group/templates/service.yaml index aa16f71b9..fc6f76060 100644 --- a/deployments/charts/openim-rpc-group/templates/service.yaml +++ b/deployments/charts/openim-rpc-group/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-rpc-group/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-group/templates/serviceaccount.yaml index b42dfb13b..304bbda56 100644 --- a/deployments/charts/openim-rpc-group/templates/serviceaccount.yaml +++ b/deployments/charts/openim-rpc-group/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-rpc-group/values.yaml b/deployments/charts/openim-rpc-group/values.yaml index ec36e256f..f04c64147 100644 --- a/deployments/charts/openim-rpc-group/values.yaml +++ b/deployments/charts/openim-rpc-group/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-rpc-group. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-rpc-msg/Chart.yaml b/deployments/charts/openim-rpc-msg/Chart.yaml index 659767484..c32fe64c1 100644 --- a/deployments/charts/openim-rpc-msg/Chart.yaml +++ b/deployments/charts/openim-rpc-msg/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-rpc-msg description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-rpc-msg/templates/deployment.yaml b/deployments/charts/openim-rpc-msg/templates/deployment.yaml index e0565710a..d764294ea 100644 --- a/deployments/charts/openim-rpc-msg/templates/deployment.yaml +++ b/deployments/charts/openim-rpc-msg/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-rpc-msg/templates/hpa.yaml b/deployments/charts/openim-rpc-msg/templates/hpa.yaml index c01e07294..0e6dde369 100644 --- a/deployments/charts/openim-rpc-msg/templates/hpa.yaml +++ b/deployments/charts/openim-rpc-msg/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-rpc-msg/templates/ingress.yaml b/deployments/charts/openim-rpc-msg/templates/ingress.yaml index 2f5ad9d15..2ba587338 100644 --- a/deployments/charts/openim-rpc-msg/templates/ingress.yaml +++ b/deployments/charts/openim-rpc-msg/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-rpc-msg.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-rpc-msg/templates/service.yaml b/deployments/charts/openim-rpc-msg/templates/service.yaml index 9afd55a8c..953b89d5d 100644 --- a/deployments/charts/openim-rpc-msg/templates/service.yaml +++ b/deployments/charts/openim-rpc-msg/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-rpc-msg/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-msg/templates/serviceaccount.yaml index da69e5ce8..70fd82069 100644 --- a/deployments/charts/openim-rpc-msg/templates/serviceaccount.yaml +++ b/deployments/charts/openim-rpc-msg/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-rpc-msg/values.yaml b/deployments/charts/openim-rpc-msg/values.yaml index 22cfd61f1..cf2f4e84d 100644 --- a/deployments/charts/openim-rpc-msg/values.yaml +++ b/deployments/charts/openim-rpc-msg/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-rpc-msg. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-rpc-third/Chart.yaml b/deployments/charts/openim-rpc-third/Chart.yaml index d7763d70a..ff624aa34 100644 --- a/deployments/charts/openim-rpc-third/Chart.yaml +++ b/deployments/charts/openim-rpc-third/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-rpc-third description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-rpc-third/templates/deployment.yaml b/deployments/charts/openim-rpc-third/templates/deployment.yaml index c14cce817..e4f47de57 100644 --- a/deployments/charts/openim-rpc-third/templates/deployment.yaml +++ b/deployments/charts/openim-rpc-third/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-rpc-third/templates/hpa.yaml b/deployments/charts/openim-rpc-third/templates/hpa.yaml index 2197e21a5..f20ecb973 100644 --- a/deployments/charts/openim-rpc-third/templates/hpa.yaml +++ b/deployments/charts/openim-rpc-third/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-rpc-third/templates/ingress.yaml b/deployments/charts/openim-rpc-third/templates/ingress.yaml index 3ba50cf33..1c64ac545 100644 --- a/deployments/charts/openim-rpc-third/templates/ingress.yaml +++ b/deployments/charts/openim-rpc-third/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-rpc-third.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-rpc-third/templates/service.yaml b/deployments/charts/openim-rpc-third/templates/service.yaml index 866b5cda2..f467992a2 100644 --- a/deployments/charts/openim-rpc-third/templates/service.yaml +++ b/deployments/charts/openim-rpc-third/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-rpc-third/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-third/templates/serviceaccount.yaml index 8a45872ce..27f2bf067 100644 --- a/deployments/charts/openim-rpc-third/templates/serviceaccount.yaml +++ b/deployments/charts/openim-rpc-third/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-rpc-third/values.yaml b/deployments/charts/openim-rpc-third/values.yaml index 8a92566a9..71d9a3ede 100644 --- a/deployments/charts/openim-rpc-third/values.yaml +++ b/deployments/charts/openim-rpc-third/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-rpc-third. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/charts/openim-rpc-user/Chart.yaml b/deployments/charts/openim-rpc-user/Chart.yaml index 7a2118e46..feb5a3195 100644 --- a/deployments/charts/openim-rpc-user/Chart.yaml +++ b/deployments/charts/openim-rpc-user/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v2 name: openim-rpc-user description: A Helm chart for Kubernetes diff --git a/deployments/charts/openim-rpc-user/templates/deployment.yaml b/deployments/charts/openim-rpc-user/templates/deployment.yaml index f6f679c2d..62106e5a2 100644 --- a/deployments/charts/openim-rpc-user/templates/deployment.yaml +++ b/deployments/charts/openim-rpc-user/templates/deployment.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: apps/v1 kind: Deployment metadata: diff --git a/deployments/charts/openim-rpc-user/templates/hpa.yaml b/deployments/charts/openim-rpc-user/templates/hpa.yaml index 7c00c9d64..012b15ae3 100644 --- a/deployments/charts/openim-rpc-user/templates/hpa.yaml +++ b/deployments/charts/openim-rpc-user/templates/hpa.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler diff --git a/deployments/charts/openim-rpc-user/templates/ingress.yaml b/deployments/charts/openim-rpc-user/templates/ingress.yaml index 7ed5a0328..38aa6fdff 100644 --- a/deployments/charts/openim-rpc-user/templates/ingress.yaml +++ b/deployments/charts/openim-rpc-user/templates/ingress.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.ingress.enabled -}} {{- $fullName := include "openim-rpc-user.fullname" . -}} {{- $svcPort := .Values.service.port -}} diff --git a/deployments/charts/openim-rpc-user/templates/service.yaml b/deployments/charts/openim-rpc-user/templates/service.yaml index 728c5de92..f89be1c44 100644 --- a/deployments/charts/openim-rpc-user/templates/service.yaml +++ b/deployments/charts/openim-rpc-user/templates/service.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + apiVersion: v1 kind: Service metadata: diff --git a/deployments/charts/openim-rpc-user/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-user/templates/serviceaccount.yaml index d3395f00d..ebe3e3d68 100644 --- a/deployments/charts/openim-rpc-user/templates/serviceaccount.yaml +++ b/deployments/charts/openim-rpc-user/templates/serviceaccount.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount diff --git a/deployments/charts/openim-rpc-user/values.yaml b/deployments/charts/openim-rpc-user/values.yaml index d137f0ad7..4f1ad7ede 100644 --- a/deployments/charts/openim-rpc-user/values.yaml +++ b/deployments/charts/openim-rpc-user/values.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Default values for openim-rpc-user. # This is a YAML-formatted file. # Declare variables to be passed into your templates. diff --git a/deployments/openim-charts.yaml b/deployments/openim-charts.yaml index 59815dbd5..2b468dad0 100644 --- a/deployments/openim-charts.yaml +++ b/deployments/openim-charts.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- # Source: openim-api/templates/app-cm.yaml apiVersion: v1 diff --git a/deployments/templates/alertmanager.yml b/deployments/templates/alertmanager.yml index ea99a9286..4e390b2bb 100644 --- a/deployments/templates/alertmanager.yml +++ b/deployments/templates/alertmanager.yml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + ###################### AlertManager Configuration ###################### # AlertManager configuration using environment variables # diff --git a/deployments/templates/charts-value.yaml b/deployments/templates/charts-value.yaml index 274d9b8d1..26bbe2926 100644 --- a/deployments/templates/charts-value.yaml +++ b/deployments/templates/charts-value.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + #This configuration file is used to override the use of the value.yaml variable. #Currently, only the configuration with ingressName as nginx is provided. #If it is another gateway such as istio or treafik, please modify the corresponding gateway requirements diff --git a/deployments/templates/chat.yaml b/deployments/templates/chat.yaml deleted file mode 100644 index 561d45d6e..000000000 --- a/deployments/templates/chat.yaml +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright © 2023 OpenIM. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Configuration for OpenIMServer - -# ----------------------------------------------------------------- -# TODO: This config file is the template file -# --| source: deployments/templates/chat.yaml -# --| env: scripts/install/environment -# --| target: config/config.yaml -# ----------------------------------------------------------------- - -###################### Zookeeper ###################### -# Zookeeper configuration -# It's not recommended to modify the schema -zookeeper: - schema: ${ZOOKEEPER_SCHEMA} - zkAddr: - - ${ZOOKEEPER_ADDRESS}:${ZOOKEEPER_PORT} - username: ${ZOOKEEPER_USERNAME} - password: ${ZOOKEEPER_PASSWORD} - -###################### Chat API ###################### -chatApi: - openImChatApiPort: [ ${OPENIM_CHAT_API_PORT} ] - listenIP: ${CHAT_API_LISTEN_IP} - -###################### Admin API ###################### -adminApi: - openImAdminApiPort: [ ${OPENIM_ADMIN_API_PORT} ] - listenIP: ${ADMIN_API_LISTEN_IP} - -###################### RPC ###################### -rpc: - registerIP: #作为rpc启动时,注册到zookeeper的IP,api/gateway能访问到此ip和对应的rpcPort中的端口 - listenIP: #默认为0.0.0.0 - -rpcPort: - openImAdminPort: [ ${OPENIM_ADMIN_PORT} ] - openImChatPort: [ ${OPENIM_CHAT_PORT} ] -rpcRegisterName: - openImAdminName: ${OPENIM_ADMIN_NAME} - openImChatName: ${OPENIM_CHAT_NAME} - -###################### Log ###################### -log: - storageLocation: ../logs/ #存放目录 -# rotationTime: 24 #日志旋转时间 -# remainRotationCount: 2 #日志数量 -# remainLogLevel: 6 #日志级别 6表示全都打印, -# isStdout: false -# isJson: false -# withStack: false - -###################### Secret & Token Policy ###################### -# secret: openIM123 -#tokenPolicy: -# expire: 86400 - -###################### Verify Code ###################### -verifyCode: - validTime: 300 # 验证码有效时间 - validCount: 5 # 验证码有效次数 - uintTime: 86400 # 单位时间间隔 - maxCount: 10 # 单位时间内最大获取次数 - superCode: "666666" # 超级验证码(只有use为空时使用) - len: 6 # 验证码长度 - use: "" # 使用的验证码服务(use: "ali") - ali: - endpoint: "dysmsapi.aliyuncs.com" - accessKeyId: "" - accessKeySecret: "" - signName: "" - verificationCodeTemplateCode: "" - mail: # 根据对应的发件邮箱更改 sendMail、senderAuthorizationCode、smtpAddr、smtpPort 即可 - title: "" - senderMail: "" # 发送者 - senderAuthorizationCode: "" # 授权码 - smtpAddr: "smtp.qq.com" # smtp 服务器地址 - smtpPort: 25 # smtp 服务器邮件发送端口 - testDepartMentID: 001 - imAPIURL: http://127.0.0.1:10002 - -###################### Proxy Header ###################### -# 获取ip的header,没有配置直接获取远程地址 -#proxyHeader: "X-Forwarded-For" - -###################### Admin List ###################### -adminList: - - adminID: admin1 - nickname: chat1 - imAdmin: openIM123456 - - adminID: admin2 - nickname: chat2 - imAdmin: openIM654321 - - adminID: admin3 - nickname: chat3 - imAdmin: openIMAdmin - -###################### OpenIM URL ###################### -openIMUrl: ${OPENIM_SERVER_ADDRESS}:${API_OPENIM_PORT} - -###################### Redis ###################### -redis: - # address: [ 127.0.0.1:16379 ] - # username: - # password: openIM123 diff --git a/deployments/templates/email.tmpl b/deployments/templates/email.tmpl new file mode 100644 index 000000000..0385601d0 --- /dev/null +++ b/deployments/templates/email.tmpl @@ -0,0 +1,16 @@ +{{ define "email.to.html" }} +{{ range .Alerts }} + +
+

OpenIM Alert

+

Alert Program: Prometheus Alert

+

Severity Level: {{ .Labels.severity }}

+

Alert Type: {{ .Labels.alertname }}

+

Affected Host: {{ .Labels.instance }}

+

Affected Service: {{ .Labels.job }}

+

Alert Subject: {{ .Annotations.summary }}

+

Trigger Time: {{ .StartsAt.Format "2006-01-02 15:04:05" }}

+
+ +{{ end }} +{{ end }} diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml index b4118b9ce..ab9c87c02 100644 --- a/deployments/templates/env-template.yaml +++ b/deployments/templates/env-template.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # ====================================== # ========= Basic Configuration ======== # ====================================== @@ -10,10 +24,6 @@ USER=${OPENIM_USER} # Default: PASSWORD=openIM123 PASSWORD=${PASSWORD} -# Endpoint for the MinIO object storage service. -# Default: MINIO_ENDPOINT=http://172.28.0.1:10005 -MINIO_ENDPOINT=${MINIO_ENDPOINT} - # Base URL for the application programming interface (API). # Default: API_URL=http://172.28.0.1:10002 API_URL=${API_URL} diff --git a/deployments/templates/helm-image.yaml b/deployments/templates/helm-image.yaml index 317bc34ac..ef64abf91 100644 --- a/deployments/templates/helm-image.yaml +++ b/deployments/templates/helm-image.yaml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + #This configuration file is used to override the use of the value.yaml variable. #Currently, only the configuration with ingressName as nginx is provided. #If it is another gateway such as istio or treafik, please modify the corresponding gateway requirements diff --git a/config/instance-down-rules.yml b/deployments/templates/instance-down-rules.yml similarity index 61% rename from config/instance-down-rules.yml rename to deployments/templates/instance-down-rules.yml index 5541d2c54..7a6e9fda9 100644 --- a/config/instance-down-rules.yml +++ b/deployments/templates/instance-down-rules.yml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + groups: - name: instance_down rules: diff --git a/config/notification.yaml b/deployments/templates/notification.yaml similarity index 88% rename from config/notification.yaml rename to deployments/templates/notification.yaml index 5e5223a00..665c21261 100644 --- a/config/notification.yaml +++ b/deployments/templates/notification.yaml @@ -12,18 +12,36 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Determines if a message should be sent. If set to false, it triggers a silent sync without a message. If true, it requires triggering a conversation. +# For rpc notification, send twice: once as a message and once as a notification. +# The options field 'isNotification' indicates if it's a notification. groupCreated: - isSendMsg: true #是否发送消息,false不发消息为无声的触发同步。true发消息需要触发会话,rpc notification直接发两次,一次消息一次通知, options字段isNotification是否为通知 - reliabilityLevel: 1 # 1为online才发送 2为必达 - unreadCount: false # 只在isSendMsg为true的情况下有作用 + isSendMsg: true + +# Reliability level of the message sending. +# Set to 1 to send only when online, 2 for guaranteed delivery. + reliabilityLevel: 1 + +# This setting is effective only when 'isSendMsg' is true. +# It controls whether to count unread messages. + unreadCount: false + +# Configuration for offline push notifications. offlinePush: - enable: false # 开启该开关 - title: "create group title" # xx create the group + # Enables or disables offline push notifications. + enable: false + + # Title for the notification when a group is created. + title: "create group title" + + # Description for the notification. desc: "create group desc" - ext: "create group ext" -# 不加消息contentType,content统一json 结构体使用pb的 + # Additional information for the notification. + ext: "create group ext" +# Content type is not added here. +# Content should use a JSON structure conforming to the protobuf format. groupInfoSet: isSendMsg: false @@ -334,4 +352,3 @@ conversationSetPrivate: title: "burn after reading" desc: "burn after reading" ext: "burn after reading" - diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml index d822fec13..ed5dc4fe1 100644 --- a/deployments/templates/openim.yaml +++ b/deployments/templates/openim.yaml @@ -37,13 +37,20 @@ zookeeper: ###################### Mongo ###################### # MongoDB configuration -# If uri is not empty, it will be used directly -# -# MongoDB address for standalone setup, Mongos address for sharded cluster setup -# Default MongoDB database name -# Maximum connection pool size + +# If uri is not empty, it will be used directly for the MongoDB connection. +# This is a complete MongoDB URI string. +# Example: mongodb://user:password@host1:port1,host2:port2/dbname?options mongo: uri: ${MONGO_URI} + +# List of MongoDB server addresses. +# Used for constructing the MongoDB URI if 'uri' above is empty. +# For a standalone setup, specify the address of the single server. +# For a sharded cluster, specify the addresses of the Mongos servers. +# Example: [ '172.28.0.1:37017', '172.28.0.2:37017' ] +# Default MongoDB database name +# Maximum connection pool size address: [ ${MONGO_ADDRESS}:${MONGO_PORT} ] database: ${MONGO_DATABASE} username: ${MONGO_USERNAME} diff --git a/deployments/templates/prometheus.yml b/deployments/templates/prometheus.yml index fb07a8129..5c3e0af66 100644 --- a/deployments/templates/prometheus.yml +++ b/deployments/templates/prometheus.yml @@ -1,3 +1,17 @@ +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # my global config global: scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. diff --git a/internal/api/msg.go b/internal/api/msg.go index 22182d985..664ee505a 100644 --- a/internal/api/msg.go +++ b/internal/api/msg.go @@ -27,6 +27,7 @@ import ( "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "github.com/mitchellh/mapstructure" + "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/config" diff --git a/internal/msggateway/compressor_test.go b/internal/msggateway/compressor_test.go index d41c57bf3..b1544f063 100644 --- a/internal/msggateway/compressor_test.go +++ b/internal/msggateway/compressor_test.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package msggateway import ( diff --git a/internal/push/offlinepush/dummy/push.go b/internal/push/offlinepush/dummy/push.go index 2b15bc05d..f147886d9 100644 --- a/internal/push/offlinepush/dummy/push.go +++ b/internal/push/offlinepush/dummy/push.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package dummy import ( diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go index 9e66f8f73..188ddc0e1 100644 --- a/internal/push/push_rpc_server.go +++ b/internal/push/push_rpc_server.go @@ -16,9 +16,10 @@ package push import ( "context" - "github.com/OpenIMSDK/tools/utils" "sync" + "github.com/OpenIMSDK/tools/utils" + "google.golang.org/grpc" "github.com/OpenIMSDK/protocol/constant" diff --git a/internal/rpc/friend/callback.go b/internal/rpc/friend/callback.go index d541071f5..e5054d9a9 100644 --- a/internal/rpc/friend/callback.go +++ b/internal/rpc/friend/callback.go @@ -16,8 +16,10 @@ package friend import ( "context" + pbfriend "github.com/OpenIMSDK/protocol/friend" "github.com/OpenIMSDK/tools/utils" + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/http" diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index 21422fae3..20c47ad8f 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -16,6 +16,7 @@ package friend import ( "context" + "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/protocol/sdkws" diff --git a/internal/rpc/group/callback.go b/internal/rpc/group/callback.go index 1599cc7b4..4a89a16fb 100644 --- a/internal/rpc/group/callback.go +++ b/internal/rpc/group/callback.go @@ -16,9 +16,10 @@ package group import ( "context" - "github.com/OpenIMSDK/tools/log" "time" + "github.com/OpenIMSDK/tools/log" + "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/group" "github.com/OpenIMSDK/protocol/wrapperspb" diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index b05b14b59..2c3c6fc43 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -17,13 +17,14 @@ package group import ( "context" "fmt" - "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "math/big" "math/rand" "strconv" "strings" "time" + "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" + pbconversation "github.com/OpenIMSDK/protocol/conversation" "github.com/OpenIMSDK/protocol/wrapperspb" "github.com/OpenIMSDK/tools/tx" diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index 061498abb..5324ccba8 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -16,16 +16,18 @@ package msg import ( "context" + utils2 "github.com/OpenIMSDK/tools/utils" "github.com/redis/go-redis/v9" - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" + + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" ) func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *msg.GetConversationsHasReadAndMaxSeqReq) (resp *msg.GetConversationsHasReadAndMaxSeqResp, err error) { @@ -173,7 +175,7 @@ func (m *msgServer) MarkConversationAsRead( m.conversationAndGetRecvID(conversation, req.UserID), seqs, hasReadSeq); err != nil { return nil, err } - + } else if conversation.ConversationType == constant.SuperGroupChatType || conversation.ConversationType == constant.NotificationChatType { if req.HasReadSeq > hasReadSeq { @@ -222,4 +224,4 @@ func (m *msgServer) sendMarkAsReadNotification( log.ZWarn(ctx, "send has read Receipt err", err) } return nil -} \ No newline at end of file +} diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go index 4ce5a5443..0bd71d9f7 100644 --- a/internal/rpc/msg/callback.go +++ b/internal/rpc/msg/callback.go @@ -16,6 +16,7 @@ package msg import ( "context" + "github.com/OpenIMSDK/protocol/sdkws" "google.golang.org/protobuf/proto" @@ -24,6 +25,7 @@ import ( "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/common/config" diff --git a/internal/rpc/third/log.go b/internal/rpc/third/log.go index 57d4f536e..11c7467b8 100644 --- a/internal/rpc/third/log.go +++ b/internal/rpc/third/log.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package third import ( diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go index e87b4674e..7d865af5f 100644 --- a/internal/rpc/user/callback.go +++ b/internal/rpc/user/callback.go @@ -16,6 +16,7 @@ package user import ( "context" + pbuser "github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/tools/utils" diff --git a/internal/tools/cron_task_test.go b/internal/tools/cron_task_test.go index 1f4f1f5c1..28bc2c945 100644 --- a/internal/tools/cron_task_test.go +++ b/internal/tools/cron_task_test.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package tools import ( diff --git a/pkg/apistruct/msg.go b/pkg/apistruct/msg.go index 61b4d832b..4b7bd1e6f 100644 --- a/pkg/apistruct/msg.go +++ b/pkg/apistruct/msg.go @@ -16,11 +16,11 @@ package apistruct type PictureBaseInfo struct { UUID string `mapstructure:"uuid"` - Type string `mapstructure:"type" validate:"required"` + Type string `mapstructure:"type" validate:"required"` Size int64 `mapstructure:"size"` - Width int32 `mapstructure:"width" validate:"required"` + Width int32 `mapstructure:"width" validate:"required"` Height int32 `mapstructure:"height" validate:"required"` - Url string `mapstructure:"url" validate:"required"` + Url string `mapstructure:"url" validate:"required"` } type PictureElem struct { @@ -34,28 +34,28 @@ type SoundElem struct { SoundPath string `mapstructure:"soundPath"` SourceURL string `mapstructure:"sourceUrl" validate:"required"` DataSize int64 `mapstructure:"dataSize"` - Duration int64 `mapstructure:"duration" validate:"required,min=1"` + Duration int64 `mapstructure:"duration" validate:"required,min=1"` } type VideoElem struct { - VideoPath string `mapstructure:"videoPath" ` + VideoPath string `mapstructure:"videoPath"` VideoUUID string `mapstructure:"videoUUID"` - VideoURL string `mapstructure:"videoUrl" validate:"required"` - VideoType string `mapstructure:"videoType" validate:"required"` - VideoSize int64 `mapstructure:"videoSize" validate:"required"` - Duration int64 `mapstructure:"duration" validate:"required"` + VideoURL string `mapstructure:"videoUrl" validate:"required"` + VideoType string `mapstructure:"videoType" validate:"required"` + VideoSize int64 `mapstructure:"videoSize" validate:"required"` + Duration int64 `mapstructure:"duration" validate:"required"` SnapshotPath string `mapstructure:"snapshotPath"` SnapshotUUID string `mapstructure:"snapshotUUID"` SnapshotSize int64 `mapstructure:"snapshotSize"` - SnapshotURL string `mapstructure:"snapshotUrl" validate:"required"` - SnapshotWidth int32 `mapstructure:"snapshotWidth" validate:"required"` + SnapshotURL string `mapstructure:"snapshotUrl" validate:"required"` + SnapshotWidth int32 `mapstructure:"snapshotWidth" validate:"required"` SnapshotHeight int32 `mapstructure:"snapshotHeight" validate:"required"` } type FileElem struct { - FilePath string `mapstructure:"filePath" ` + FilePath string `mapstructure:"filePath"` UUID string `mapstructure:"uuid"` SourceURL string `mapstructure:"sourceUrl" validate:"required"` - FileName string `mapstructure:"fileName" validate:"required"` - FileSize int64 `mapstructure:"fileSize" validate:"required"` + FileName string `mapstructure:"fileName" validate:"required"` + FileSize int64 `mapstructure:"fileSize" validate:"required"` } type AtElem struct { Text string `mapstructure:"text"` @@ -63,9 +63,9 @@ type AtElem struct { IsAtSelf bool `mapstructure:"isAtSelf"` } type LocationElem struct { - Description string `mapstructure:"description" ` - Longitude float64 `mapstructure:"longitude" validate:"required"` - Latitude float64 `mapstructure:"latitude" validate:"required"` + Description string `mapstructure:"description"` + Longitude float64 `mapstructure:"longitude" validate:"required"` + Latitude float64 `mapstructure:"latitude" validate:"required"` } type CustomElem struct { Data string `mapstructure:"data" validate:"required"` @@ -87,7 +87,7 @@ type OANotificationElem struct { NotificationType int32 `mapstructure:"notificationType" json:"notificationType" validate:"required"` Text string `mapstructure:"text" json:"text" validate:"required"` Url string `mapstructure:"url" json:"url"` - MixType int32 `mapstructure:"mixType" json:"mixType" validate:"required"` + MixType int32 `mapstructure:"mixType" json:"mixType" validate:"required"` PictureElem *PictureElem `mapstructure:"pictureElem" json:"pictureElem"` SoundElem *SoundElem `mapstructure:"soundElem" json:"soundElem"` VideoElem *VideoElem `mapstructure:"videoElem" json:"videoElem"` diff --git a/pkg/callbackstruct/constant.go b/pkg/callbackstruct/constant.go index 2af337ac6..0a03a1ef1 100644 --- a/pkg/callbackstruct/constant.go +++ b/pkg/callbackstruct/constant.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package callbackstruct const CallbackBeforeInviteJoinGroupCommand = "callbackBeforeInviteJoinGroupCommand" diff --git a/pkg/callbackstruct/revoke.go b/pkg/callbackstruct/revoke.go index 364c0162b..1f5e0b0c1 100644 --- a/pkg/callbackstruct/revoke.go +++ b/pkg/callbackstruct/revoke.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package callbackstruct type CallbackAfterRevokeMsgReq struct { diff --git a/pkg/common/cmd/constant.go b/pkg/common/cmd/constant.go index 835593bbe..c332ce3a6 100644 --- a/pkg/common/cmd/constant.go +++ b/pkg/common/cmd/constant.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cmd const ( diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 5fb8fe7e2..6da89fc8f 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -16,6 +16,7 @@ package config import ( "bytes" + "github.com/OpenIMSDK/tools/discoveryregistry" "gopkg.in/yaml.v3" ) diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go index 22e458e00..1410a5a4a 100644 --- a/pkg/common/config/parse.go +++ b/pkg/common/config/parse.go @@ -35,7 +35,7 @@ const ( DefaultFolderPath = "../config/" ) -// return absolude path join ../config/, this is k8s container config path +// return absolude path join ../config/, this is k8s container config path. func GetDefaultConfigPath() string { b, err := filepath.Abs(os.Args[0]) if err != nil { @@ -45,7 +45,7 @@ func GetDefaultConfigPath() string { return filepath.Join(filepath.Dir(b), "../config/") } -// getProjectRoot returns the absolute path of the project root directory +// getProjectRoot returns the absolute path of the project root directory. func GetProjectRoot() string { b, _ := filepath.Abs(os.Args[0]) diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go index 0c71aac22..8d960546a 100644 --- a/pkg/common/convert/user.go +++ b/pkg/common/convert/user.go @@ -15,9 +15,10 @@ package convert import ( - "github.com/OpenIMSDK/protocol/sdkws" "time" + "github.com/OpenIMSDK/protocol/sdkws" + relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) diff --git a/pkg/common/db/cache/group.go b/pkg/common/db/cache/group.go index 603d8e534..57fcf1a9b 100644 --- a/pkg/common/db/cache/group.go +++ b/pkg/common/db/cache/group.go @@ -39,7 +39,7 @@ const ( groupMemberIDsKey = "GROUP_MEMBER_IDS:" groupMembersHashKey = "GROUP_MEMBERS_HASH2:" groupMemberInfoKey = "GROUP_MEMBER_INFO:" - //groupOwnerInfoKey = "GROUP_OWNER_INFO:" + //groupOwnerInfoKey = "GROUP_OWNER_INFO:". joinedGroupsKey = "JOIN_GROUPS_KEY:" groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:" groupRoleLevelMemberIDsKey = "GROUP_ROLE_LEVEL_MEMBER_IDS:" diff --git a/pkg/common/db/cache/init_redis.go b/pkg/common/db/cache/init_redis.go index 77b38d9b7..63d2f5707 100644 --- a/pkg/common/db/cache/init_redis.go +++ b/pkg/common/db/cache/init_redis.go @@ -18,6 +18,8 @@ import ( "context" "errors" "fmt" + "os" + "strings" "time" "github.com/redis/go-redis/v9" @@ -43,6 +45,9 @@ func NewRedis() (redis.UniversalClient, error) { return redisClient, nil } + // Read configuration from environment variables + overrideConfigFromEnv() + if len(config.Config.Redis.Address) == 0 { return nil, errors.New("redis address is empty") } @@ -60,9 +65,9 @@ func NewRedis() (redis.UniversalClient, error) { rdb = redis.NewClient(&redis.Options{ Addr: config.Config.Redis.Address[0], Username: config.Config.Redis.Username, - Password: config.Config.Redis.Password, // no password set - DB: 0, // use default DB - PoolSize: 100, // connection pool size + Password: config.Config.Redis.Password, + DB: 0, // use default DB + PoolSize: 100, // connection pool size MaxRetries: maxRetry, }) } @@ -78,3 +83,16 @@ func NewRedis() (redis.UniversalClient, error) { redisClient = rdb return rdb, err } + +// overrideConfigFromEnv overrides configuration fields with environment variables if present. +func overrideConfigFromEnv() { + if envAddr := os.Getenv("REDIS_ADDRESS"); envAddr != "" { + config.Config.Redis.Address = strings.Split(envAddr, ",") // Assuming addresses are comma-separated + } + if envUser := os.Getenv("REDIS_USERNAME"); envUser != "" { + config.Config.Redis.Username = envUser + } + if envPass := os.Getenv("REDIS_PASSWORD"); envPass != "" { + config.Config.Redis.Password = envPass + } +} diff --git a/pkg/common/db/cache/msg_test.go b/pkg/common/db/cache/msg_test.go index 3fddf5965..65413199a 100644 --- a/pkg/common/db/cache/msg_test.go +++ b/pkg/common/db/cache/msg_test.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cache import ( diff --git a/pkg/common/db/cache/s3.go b/pkg/common/db/cache/s3.go index ba40ceacc..1e68cedf8 100644 --- a/pkg/common/db/cache/s3.go +++ b/pkg/common/db/cache/s3.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cache import ( diff --git a/pkg/common/db/mgo/black.go b/pkg/common/db/mgo/black.go index 6235639aa..1047e5c30 100644 --- a/pkg/common/db/mgo/black.go +++ b/pkg/common/db/mgo/black.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/conversation.go b/pkg/common/db/mgo/conversation.go index 72d04ebb3..bf5d1a145 100644 --- a/pkg/common/db/mgo/conversation.go +++ b/pkg/common/db/mgo/conversation.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go index aa9cb0301..8f3528d91 100644 --- a/pkg/common/db/mgo/friend.go +++ b/pkg/common/db/mgo/friend.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/friend_request.go b/pkg/common/db/mgo/friend_request.go index c1be87ca2..bfc101917 100644 --- a/pkg/common/db/mgo/friend_request.go +++ b/pkg/common/db/mgo/friend_request.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/group.go b/pkg/common/db/mgo/group.go index 3553b6b56..65dbbca59 100644 --- a/pkg/common/db/mgo/group.go +++ b/pkg/common/db/mgo/group.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/group_member.go b/pkg/common/db/mgo/group_member.go index ed09a028b..8c3041901 100644 --- a/pkg/common/db/mgo/group_member.go +++ b/pkg/common/db/mgo/group_member.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/group_request.go b/pkg/common/db/mgo/group_request.go index e88a39bf5..cb04d2308 100644 --- a/pkg/common/db/mgo/group_request.go +++ b/pkg/common/db/mgo/group_request.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/log.go b/pkg/common/db/mgo/log.go index aa280fcf2..09f002ee3 100644 --- a/pkg/common/db/mgo/log.go +++ b/pkg/common/db/mgo/log.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/object.go b/pkg/common/db/mgo/object.go index 5976b2d28..88bfde213 100644 --- a/pkg/common/db/mgo/object.go +++ b/pkg/common/db/mgo/object.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go index 4a53cb3c4..37e354cbb 100644 --- a/pkg/common/db/mgo/user.go +++ b/pkg/common/db/mgo/user.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( diff --git a/pkg/common/db/s3/cos/internal.go b/pkg/common/db/s3/cos/internal.go index 02afde684..064546953 100644 --- a/pkg/common/db/s3/cos/internal.go +++ b/pkg/common/db/s3/cos/internal.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cos import ( diff --git a/pkg/common/db/s3/minio/internal.go b/pkg/common/db/s3/minio/internal.go index 41129ce31..7e9dcd9e4 100644 --- a/pkg/common/db/s3/minio/internal.go +++ b/pkg/common/db/s3/minio/internal.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package minio import ( diff --git a/pkg/common/db/s3/minio/thumbnail.go b/pkg/common/db/s3/minio/thumbnail.go index 01b14541b..49c376c9f 100644 --- a/pkg/common/db/s3/minio/thumbnail.go +++ b/pkg/common/db/s3/minio/thumbnail.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package minio import ( diff --git a/pkg/common/db/table/relation/log.go b/pkg/common/db/table/relation/log.go index f690ff8aa..ba63c0c2b 100644 --- a/pkg/common/db/table/relation/log.go +++ b/pkg/common/db/table/relation/log.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package relation import ( diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go index 38a335567..2c1dc6f38 100644 --- a/pkg/common/db/unrelation/mongo.go +++ b/pkg/common/db/unrelation/mongo.go @@ -17,11 +17,11 @@ package unrelation import ( "context" "fmt" + "os" "strings" "time" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" @@ -34,7 +34,8 @@ import ( ) const ( - maxRetry = 10 // number of retries + maxRetry = 10 // number of retries + mongoConnTimeout = 10 * time.Second ) type Mongo struct { @@ -44,90 +45,122 @@ type Mongo struct { // NewMongo Initialize MongoDB connection. func NewMongo() (*Mongo, error) { specialerror.AddReplace(mongo.ErrNoDocuments, errs.ErrRecordNotFound) - uri := "mongodb://sample.host:27017/?maxPoolSize=20&w=majority" - if config.Config.Mongo.Uri != "" { - uri = config.Config.Mongo.Uri - } else { - mongodbHosts := "" - for i, v := range config.Config.Mongo.Address { - if i == len(config.Config.Mongo.Address)-1 { - mongodbHosts += v - } else { - mongodbHosts += v + "," - } - } - if config.Config.Mongo.Password != "" && config.Config.Mongo.Username != "" { - uri = fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d&authSource=admin", - config.Config.Mongo.Username, config.Config.Mongo.Password, mongodbHosts, - config.Config.Mongo.Database, config.Config.Mongo.MaxPoolSize) - } else { - uri = fmt.Sprintf("mongodb://%s/%s/?maxPoolSize=%d&authSource=admin", - mongodbHosts, config.Config.Mongo.Database, - config.Config.Mongo.MaxPoolSize) - } - } - fmt.Println("mongo:", uri) + uri := buildMongoURI() + var mongoClient *mongo.Client - var err error = nil + var err error + + // Retry connecting to MongoDB for i := 0; i <= maxRetry; i++ { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + ctx, cancel := context.WithTimeout(context.Background(), mongoConnTimeout) defer cancel() mongoClient, err = mongo.Connect(ctx, options.Client().ApplyURI(uri)) if err == nil { return &Mongo{db: mongoClient}, nil } - if cmdErr, ok := err.(mongo.CommandError); ok { - if cmdErr.Code == 13 || cmdErr.Code == 18 { - return nil, err - } else { - fmt.Printf("Failed to connect to MongoDB: %s\n", err) - } + if shouldRetry(err) { + fmt.Printf("Failed to connect to MongoDB, retrying: %s\n", err) + time.Sleep(time.Second) // exponential backoff could be implemented here + continue } + return nil, err } return nil, err } +func buildMongoURI() string { + uri := os.Getenv("MONGO_URI") + if uri != "" { + return uri + } + + username := os.Getenv("MONGO_USERNAME") + password := os.Getenv("MONGO_PASSWORD") + address := os.Getenv("MONGO_ADDRESS") + port := os.Getenv("MONGO_PORT") + database := os.Getenv("MONGO_DATABASE") + maxPoolSize := os.Getenv("MONGO_MAX_POOL_SIZE") + + if username == "" { + username = config.Config.Mongo.Username + } + if password == "" { + password = config.Config.Mongo.Password + } + if address == "" { + address = strings.Join(config.Config.Mongo.Address, ",") + } else if port != "" { + address = fmt.Sprintf("%s:%s", address, port) + } + if database == "" { + database = config.Config.Mongo.Database + } + if maxPoolSize == "" { + maxPoolSize = fmt.Sprint(config.Config.Mongo.MaxPoolSize) + } + + uriFormat := "mongodb://%s/%s?maxPoolSize=%s&authSource=admin" + if username != "" && password != "" { + uriFormat = "mongodb://%s:%s@%s/%s?maxPoolSize=%s&authSource=admin" + return fmt.Sprintf(uriFormat, username, password, address, database, maxPoolSize) + } + return fmt.Sprintf(uriFormat, address, database, maxPoolSize) +} + +func shouldRetry(err error) bool { + if cmdErr, ok := err.(mongo.CommandError); ok { + return cmdErr.Code != 13 && cmdErr.Code != 18 + } + return true +} + +// GetClient returns the MongoDB client. func (m *Mongo) GetClient() *mongo.Client { return m.db } +// GetDatabase returns the specific database from MongoDB. func (m *Mongo) GetDatabase() *mongo.Database { return m.db.Database(config.Config.Mongo.Database) } +// CreateMsgIndex creates an index for messages in MongoDB. func (m *Mongo) CreateMsgIndex() error { return m.createMongoIndex(unrelation.Msg, true, "doc_id") } +// createMongoIndex creates an index in a MongoDB collection. func (m *Mongo) createMongoIndex(collection string, isUnique bool, keys ...string) error { - db := m.db.Database(config.Config.Mongo.Database).Collection(collection) + db := m.GetDatabase().Collection(collection) opts := options.CreateIndexes().SetMaxTime(10 * time.Second) indexView := db.Indexes() - keysDoc := bson.D{} - // create composite indexes - for _, key := range keys { - if strings.HasPrefix(key, "-") { - keysDoc = append(keysDoc, bson.E{Key: strings.TrimLeft(key, "-"), Value: -1}) - // keysDoc = keysDoc.Append(strings.TrimLeft(key, "-"), bsonx.Int32(-1)) - } else { - keysDoc = append(keysDoc, bson.E{Key: key, Value: 1}) - // keysDoc = keysDoc.Append(key, bsonx.Int32(1)) - } - } - // create index + + keysDoc := buildIndexKeys(keys) + index := mongo.IndexModel{ Keys: keysDoc, } if isUnique { index.Options = options.Index().SetUnique(true) } - result, err := indexView.CreateOne( - context.Background(), - index, - opts, - ) + + _, err := indexView.CreateOne(context.Background(), index, opts) if err != nil { - return utils.Wrap(err, result) + return utils.Wrap(err, "CreateIndex") } return nil } + +// buildIndexKeys builds the BSON document for index keys. +func buildIndexKeys(keys []string) bson.D { + keysDoc := bson.D{} + for _, key := range keys { + direction := 1 // default direction is ascending + if strings.HasPrefix(key, "-") { + direction = -1 // descending order for prefixed with "-" + key = strings.TrimLeft(key, "-") + } + keysDoc = append(keysDoc, bson.E{Key: key, Value: direction}) + } + return keysDoc +} diff --git a/pkg/common/discoveryregister/discoveryregister.go b/pkg/common/discoveryregister/discoveryregister.go index 62c1f4a31..c14323027 100644 --- a/pkg/common/discoveryregister/discoveryregister.go +++ b/pkg/common/discoveryregister/discoveryregister.go @@ -1,159 +1,42 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package discoveryregister import ( - "context" "errors" - "fmt" "os" - "strconv" - "strings" - "time" - "github.com/OpenIMSDK/tools/discoveryregistry" - openkeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper" - "github.com/OpenIMSDK/tools/log" - "google.golang.org/grpc" + "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/kubernetes" + "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/zookeeper" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + "github.com/OpenIMSDK/tools/discoveryregistry" ) +// NewDiscoveryRegister creates a new service discovery and registry client based on the provided environment type. func NewDiscoveryRegister(envType string) (discoveryregistry.SvcDiscoveryRegistry, error) { - var client discoveryregistry.SvcDiscoveryRegistry - var err error + + if os.Getenv("ENVS_DISCOVERY") != "" { + envType = os.Getenv("ENVS_DISCOVERY") + } + switch envType { case "zookeeper": - client, err = openkeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, - openkeeper.WithFreq(time.Hour), openkeeper.WithUserNameAndPassword( - config.Config.Zookeeper.Username, - config.Config.Zookeeper.Password, - ), openkeeper.WithRoundRobin(), openkeeper.WithTimeout(10), openkeeper.WithLogger(log.NewZkLogger())) + return zookeeper.NewZookeeperDiscoveryRegister() case "k8s": - client, err = NewK8sDiscoveryRegister() + return kubernetes.NewK8sDiscoveryRegister() default: - client = nil - err = errors.New("envType not correct") + return nil, errors.New("envType not correct") } - return client, err -} - -type K8sDR struct { - options []grpc.DialOption - rpcRegisterAddr string -} - -func NewK8sDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) { - return &K8sDR{}, nil -} - -func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.DialOption) error { - if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { - cli.rpcRegisterAddr = serviceName - } else { - cli.rpcRegisterAddr = cli.getSelfHost(context.Background()) - } - - return nil -} -func (cli *K8sDR) UnRegister() error { - - return nil -} -func (cli *K8sDR) CreateRpcRootNodes(serviceNames []string) error { - - return nil -} -func (cli *K8sDR) RegisterConf2Registry(key string, conf []byte) error { - - return nil -} - -func (cli *K8sDR) GetConfFromRegistry(key string) ([]byte, error) { - - return nil, nil -} -func (cli *K8sDR) getSelfHost(ctx context.Context) string { - port := 88 - instance := "openimserver" - selfPodName := os.Getenv("MY_POD_NAME") - ns := os.Getenv("MY_POD_NAMESPACE") - statefuleIndex := 0 - gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":") - if len(gatewayEnds) != 2 { - log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error")) - } else { - port, _ = strconv.Atoi(gatewayEnds[1]) - } - podInfo := strings.Split(selfPodName, "-") - instance = podInfo[0] - count := len(podInfo) - statefuleIndex, _ = strconv.Atoi(podInfo[count-1]) - host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, statefuleIndex, instance, ns, port) - return host -} - -// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88 -func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string { - port := 88 - instance := "openimserver" - selfPodName := os.Getenv("MY_POD_NAME") - replicas := os.Getenv("MY_MSGGATEWAY_REPLICACOUNT") - ns := os.Getenv("MY_POD_NAMESPACE") - gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":") - if len(gatewayEnds) != 2 { - log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error")) - } else { - port, _ = strconv.Atoi(gatewayEnds[1]) - } - nReplicas, _ := strconv.Atoi(replicas) - podInfo := strings.Split(selfPodName, "-") - instance = podInfo[0] - var ret []string - for i := 0; i < nReplicas; i++ { - host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, i, instance, ns, port) - ret = append(ret, host) - } - log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret) - return ret -} -func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { - - if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { - conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) - return []*grpc.ClientConn{conn}, err - } else { - var ret []*grpc.ClientConn - gatewayHosts := cli.getMsgGatewayHost(ctx) - for _, host := range gatewayHosts { - conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...) - if err != nil { - return nil, err - } else { - ret = append(ret, conn) - } - } - return ret, nil - } -} -func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { - - return grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) -} -func (cli *K8sDR) GetSelfConnTarget() string { - - return cli.rpcRegisterAddr -} -func (cli *K8sDR) AddOption(opts ...grpc.DialOption) { - cli.options = append(cli.options, opts...) -} -func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) { - conn.Close() -} - -// do not use this method for call rpc -func (cli *K8sDR) GetClientLocalConns() map[string][]*grpc.ClientConn { - fmt.Println("should not call this function!!!!!!!!!!!!!!!!!!!!!!!!!") - return nil -} -func (cli *K8sDR) Close() { - return } diff --git a/pkg/common/discoveryregister/discoveryregister_test.go b/pkg/common/discoveryregister/discoveryregister_test.go index 8426598f9..d4a634b91 100644 --- a/pkg/common/discoveryregister/discoveryregister_test.go +++ b/pkg/common/discoveryregister/discoveryregister_test.go @@ -1,407 +1,59 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package discoveryregister import ( - "context" - "reflect" + "os" "testing" "github.com/OpenIMSDK/tools/discoveryregistry" - "google.golang.org/grpc" + "github.com/stretchr/testify/assert" ) -func TestNewDiscoveryRegister(t *testing.T) { - type args struct { - envType string - } - tests := []struct { - name string - args args - want discoveryregistry.SvcDiscoveryRegistry - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := NewDiscoveryRegister(tt.args.envType) - if (err != nil) != tt.wantErr { - t.Errorf("NewDiscoveryRegister() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("NewDiscoveryRegister() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestNewK8sDiscoveryRegister(t *testing.T) { - tests := []struct { - name string - want discoveryregistry.SvcDiscoveryRegistry - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := NewK8sDiscoveryRegister() - if (err != nil) != tt.wantErr { - t.Errorf("NewK8sDiscoveryRegister() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("NewK8sDiscoveryRegister() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestK8sDR_Register(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - type args struct { - serviceName string - host string - port int - opts []grpc.DialOption - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - if err := cli.Register(tt.args.serviceName, tt.args.host, tt.args.port, tt.args.opts...); (err != nil) != tt.wantErr { - t.Errorf("K8sDR.Register() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestK8sDR_UnRegister(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - tests := []struct { - name string - fields fields - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - if err := cli.UnRegister(); (err != nil) != tt.wantErr { - t.Errorf("K8sDR.UnRegister() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestK8sDR_CreateRpcRootNodes(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - type args struct { - serviceNames []string - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - if err := cli.CreateRpcRootNodes(tt.args.serviceNames); (err != nil) != tt.wantErr { - t.Errorf("K8sDR.CreateRpcRootNodes() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestK8sDR_RegisterConf2Registry(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - type args struct { - key string - conf []byte - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - if err := cli.RegisterConf2Registry(tt.args.key, tt.args.conf); (err != nil) != tt.wantErr { - t.Errorf("K8sDR.RegisterConf2Registry() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestK8sDR_GetConfFromRegistry(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - type args struct { - key string - } - tests := []struct { - name string - fields fields - args args - want []byte - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - got, err := cli.GetConfFromRegistry(tt.args.key) - if (err != nil) != tt.wantErr { - t.Errorf("K8sDR.GetConfFromRegistry() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("K8sDR.GetConfFromRegistry() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestK8sDR_GetConns(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - type args struct { - ctx context.Context - serviceName string - opts []grpc.DialOption - } - tests := []struct { - name string - fields fields - args args - want []*grpc.ClientConn - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - got, err := cli.GetConns(tt.args.ctx, tt.args.serviceName, tt.args.opts...) - if (err != nil) != tt.wantErr { - t.Errorf("K8sDR.GetConns() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("K8sDR.GetConns() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestK8sDR_GetConn(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - type args struct { - ctx context.Context - serviceName string - opts []grpc.DialOption - } - tests := []struct { - name string - fields fields - args args - want *grpc.ClientConn - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - got, err := cli.GetConn(tt.args.ctx, tt.args.serviceName, tt.args.opts...) - if (err != nil) != tt.wantErr { - t.Errorf("K8sDR.GetConn() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("K8sDR.GetConn() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestK8sDR_GetSelfConnTarget(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - tests := []struct { - name string - fields fields - want string - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - if got := cli.GetSelfConnTarget(); got != tt.want { - t.Errorf("K8sDR.GetSelfConnTarget() = %v, want %v", got, tt.want) - } - }) - } +func setupTestEnvironment() { + os.Setenv("ZOOKEEPER_SCHEMA", "openim") + os.Setenv("ZOOKEEPER_ADDRESS", "172.28.0.1:12181") + os.Setenv("ZOOKEEPER_USERNAME", "") + os.Setenv("ZOOKEEPER_PASSWORD", "") } -func TestK8sDR_AddOption(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - type args struct { - opts []grpc.DialOption - } - tests := []struct { - name string - fields fields - args args - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - cli.AddOption(tt.args.opts...) - }) - } -} +func TestNewDiscoveryRegister(t *testing.T) { + setupTestEnvironment() -func TestK8sDR_CloseConn(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - type args struct { - conn *grpc.ClientConn - } tests := []struct { - name string - fields fields - args args + envType string + expectedError bool + expectedResult bool }{ - // TODO: Add test cases. + {"zookeeper", false, true}, + {"k8s", false, true}, // 假设 k8s 配置也已正确设置 + {"invalid", true, false}, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - cli.CloseConn(tt.args.conn) - }) - } -} -func TestK8sDR_GetClientLocalConns(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - tests := []struct { - name string - fields fields - want map[string][]*grpc.ClientConn - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, - } - if got := cli.GetClientLocalConns(); !reflect.DeepEqual(got, tt.want) { - t.Errorf("K8sDR.GetClientLocalConns() = %v, want %v", got, tt.want) - } - }) - } -} + for _, test := range tests { + client, err := NewDiscoveryRegister(test.envType) -func TestK8sDR_Close(t *testing.T) { - type fields struct { - options []grpc.DialOption - rpcRegisterAddr string - } - tests := []struct { - name string - fields fields - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cli := &K8sDR{ - options: tt.fields.options, - rpcRegisterAddr: tt.fields.rpcRegisterAddr, + if test.expectedError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + if test.expectedResult { + assert.Implements(t, (*discoveryregistry.SvcDiscoveryRegistry)(nil), client) + } else { + assert.Nil(t, client) } - cli.Close() - }) + } } } diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go new file mode 100644 index 000000000..cd5fb0a36 --- /dev/null +++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go @@ -0,0 +1,174 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kubernetes + +import ( + "context" + "errors" + "fmt" + "os" + "strconv" + "strings" + + "google.golang.org/grpc" + + "github.com/OpenIMSDK/tools/discoveryregistry" + "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/open-im-server/v3/pkg/common/config" +) + +// K8sDR represents the Kubernetes service discovery and registration client. +type K8sDR struct { + options []grpc.DialOption + rpcRegisterAddr string +} + +// NewK8sDiscoveryRegister creates a new instance of K8sDR for Kubernetes service discovery and registration. +func NewK8sDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) { + + return &K8sDR{}, nil +} + +// Register registers a service with Kubernetes. +func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.DialOption) error { + if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { + cli.rpcRegisterAddr = serviceName + } else { + cli.rpcRegisterAddr = cli.getSelfHost(context.Background()) + } + + return nil +} + +// UnRegister removes a service registration from Kubernetes. +func (cli *K8sDR) UnRegister() error { + + return nil +} + +// CreateRpcRootNodes creates root nodes for RPC in Kubernetes. +func (cli *K8sDR) CreateRpcRootNodes(serviceNames []string) error { + + return nil +} + +// RegisterConf2Registry registers a configuration to the registry. +func (cli *K8sDR) RegisterConf2Registry(key string, conf []byte) error { + + return nil +} + +// GetConfFromRegistry retrieves a configuration from the registry. +func (cli *K8sDR) GetConfFromRegistry(key string) ([]byte, error) { + return nil, nil +} + +func (cli *K8sDR) getSelfHost(ctx context.Context) string { + port := 88 + instance := "openimserver" + selfPodName := os.Getenv("MY_POD_NAME") + ns := os.Getenv("MY_POD_NAMESPACE") + statefuleIndex := 0 + gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":") + if len(gatewayEnds) != 2 { + log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error")) + } else { + port, _ = strconv.Atoi(gatewayEnds[1]) + } + podInfo := strings.Split(selfPodName, "-") + instance = podInfo[0] + count := len(podInfo) + statefuleIndex, _ = strconv.Atoi(podInfo[count-1]) + host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, statefuleIndex, instance, ns, port) + return host +} + +// GetConns returns a list of gRPC client connections for a given service. +func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { + if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { + conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) + return []*grpc.ClientConn{conn}, err + } + var ret []*grpc.ClientConn + gatewayHosts := cli.getMsgGatewayHost(ctx) + for _, host := range gatewayHosts { + conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...) + if err != nil { + return nil, err + } + ret = append(ret, conn) + } + return ret, nil +} + +// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88 +func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string { + port := 88 + instance := "openimserver" + selfPodName := os.Getenv("MY_POD_NAME") + replicas := os.Getenv("MY_MSGGATEWAY_REPLICACOUNT") + ns := os.Getenv("MY_POD_NAMESPACE") + gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":") + if len(gatewayEnds) != 2 { + log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error")) + } else { + port, _ = strconv.Atoi(gatewayEnds[1]) + } + nReplicas, _ := strconv.Atoi(replicas) + podInfo := strings.Split(selfPodName, "-") + instance = podInfo[0] + var ret []string + for i := 0; i < nReplicas; i++ { + host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, i, instance, ns, port) + ret = append(ret, host) + } + log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret) + + return ret +} + +// GetConn returns a single gRPC client connection for a given service. +func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + return grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) +} + +// GetSelfConnTarget returns the connection target of the client itself. +func (cli *K8sDR) GetSelfConnTarget() string { + return cli.rpcRegisterAddr +} + +// AddOption adds gRPC dial options to the client. +func (cli *K8sDR) AddOption(opts ...grpc.DialOption) { + cli.options = append(cli.options, opts...) +} + +// CloseConn closes a given gRPC client connection. +func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) { + conn.Close() +} + +// do not use this method for call rpc. +func (cli *K8sDR) GetClientLocalConns() map[string][]*grpc.ClientConn { + fmt.Println("should not call this function!!!!!!!!!!!!!!!!!!!!!!!!!") + + return nil +} + +// Close closes the K8sDR client. +func (cli *K8sDR) Close() { + + // Close any open resources here (if applicable) + return +} diff --git a/pkg/common/discoveryregister/zookeeper/zookeeper.go b/pkg/common/discoveryregister/zookeeper/zookeeper.go new file mode 100644 index 000000000..a4edffc43 --- /dev/null +++ b/pkg/common/discoveryregister/zookeeper/zookeeper.go @@ -0,0 +1,61 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package zookeeper + +import ( + "os" + "strings" + "time" + + "github.com/OpenIMSDK/tools/discoveryregistry" + openkeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper" + "github.com/OpenIMSDK/tools/log" + + "github.com/openimsdk/open-im-server/v3/pkg/common/config" +) + +// NewZookeeperDiscoveryRegister creates a new instance of ZookeeperDR for Zookeeper service discovery and registration. +func NewZookeeperDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) { + schema := getEnv("ZOOKEEPER_SCHEMA", config.Config.Zookeeper.Schema) + zkAddr := getZkAddrFromEnv(config.Config.Zookeeper.ZkAddr) + username := getEnv("ZOOKEEPER_USERNAME", config.Config.Zookeeper.Username) + password := getEnv("ZOOKEEPER_PASSWORD", config.Config.Zookeeper.Password) + + return openkeeper.NewClient( + zkAddr, + schema, + openkeeper.WithFreq(time.Hour), + openkeeper.WithUserNameAndPassword(username, password), + openkeeper.WithRoundRobin(), + openkeeper.WithTimeout(10), + openkeeper.WithLogger(log.NewZkLogger()), + ) +} + +// getEnv returns the value of an environment variable if it exists, otherwise it returns the fallback value. +func getEnv(key, fallback string) string { + if value, exists := os.LookupEnv(key); exists { + return value + } + return fallback +} + +// getZkAddrFromEnv returns the value of an environment variable if it exists, otherwise it returns the fallback value. +func getZkAddrFromEnv(fallback []string) []string { + if value, exists := os.LookupEnv("ZOOKEEPER_ADDRESS"); exists { + return strings.Split(value, ",") + } + return fallback +} diff --git a/pkg/common/ginprometheus/ginprometheus.go b/pkg/common/ginprometheus/ginprometheus.go index a325595d6..f116fc23a 100644 --- a/pkg/common/ginprometheus/ginprometheus.go +++ b/pkg/common/ginprometheus/ginprometheus.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ginprometheus import ( diff --git a/pkg/common/kafka/producer.go b/pkg/common/kafka/producer.go index 1dad33f9c..9a06809b7 100644 --- a/pkg/common/kafka/producer.go +++ b/pkg/common/kafka/producer.go @@ -21,19 +21,18 @@ import ( "strings" "time" + "github.com/IBM/sarama" "github.com/OpenIMSDK/protocol/constant" - log "github.com/OpenIMSDK/tools/log" + "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" + "google.golang.org/protobuf/proto" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - - "github.com/IBM/sarama" - "google.golang.org/protobuf/proto" ) const ( - maxRetry = 10 // number of retries + maxRetry = 10 // Maximum number of retries for producer creation ) var errEmptyMsg = errors.New("binary msg is empty") @@ -45,62 +44,85 @@ type Producer struct { producer sarama.SyncProducer } -// NewKafkaProducer Initialize kafka producer. +// NewKafkaProducer initializes a new Kafka producer. func NewKafkaProducer(addr []string, topic string) *Producer { - p := Producer{} - p.config = sarama.NewConfig() // Instantiate a sarama Config - p.config.Producer.Return.Successes = true // Whether to enable the successes channel to be notified after the message is sent successfully + p := Producer{ + addr: addr, + topic: topic, + config: sarama.NewConfig(), + } + + // Set producer return flags + p.config.Producer.Return.Successes = true p.config.Producer.Return.Errors = true - p.config.Producer.Partitioner = sarama.NewHashPartitioner // Set the hash-key automatic hash partition. When sending a message, you must specify the key value of the message. If there is no key, the partition will be selected randomly - var producerAck = sarama.WaitForAll // default: WaitForAll - switch strings.ToLower(config.Config.Kafka.ProducerAck) { - case "no_response": - producerAck = sarama.NoResponse - case "wait_for_local": - producerAck = sarama.WaitForLocal - case "wait_for_all": - producerAck = sarama.WaitForAll - } - p.config.Producer.RequiredAcks = producerAck + // Set partitioner strategy + p.config.Producer.Partitioner = sarama.NewHashPartitioner - var compress = sarama.CompressionNone // default: no compress - _ = compress.UnmarshalText(bytes.ToLower([]byte(config.Config.Kafka.CompressType))) - p.config.Producer.Compression = compress + // Configure producer acknowledgement level + configureProducerAck(&p, config.Config.Kafka.ProducerAck) + + // Configure message compression + configureCompression(&p, config.Config.Kafka.CompressType) + + // Get Kafka configuration from environment variables or fallback to config file + kafkaUsername := getEnvOrConfig("KAFKA_USERNAME", config.Config.Kafka.Username) + kafkaPassword := getEnvOrConfig("KAFKA_PASSWORD", config.Config.Kafka.Password) + kafkaAddr := getEnvOrConfig("KAFKA_ADDRESS", addr[0]) // Assuming addr[0] contains address from config - if config.Config.Kafka.Username != "" && config.Config.Kafka.Password != "" { + // Configure SASL authentication if credentials are provided + if kafkaUsername != "" && kafkaPassword != "" { p.config.Net.SASL.Enable = true - p.config.Net.SASL.User = config.Config.Kafka.Username - p.config.Net.SASL.Password = config.Config.Kafka.Password + p.config.Net.SASL.User = kafkaUsername + p.config.Net.SASL.Password = kafkaPassword } - p.addr = addr - p.topic = topic + + // Set the Kafka address + p.addr = []string{kafkaAddr} + + // Set up TLS configuration (if required) SetupTLSConfig(p.config) - var producer sarama.SyncProducer + + // Create the producer with retries var err error for i := 0; i <= maxRetry; i++ { - producer, err = sarama.NewSyncProducer(p.addr, p.config) // Initialize the client + p.producer, err = sarama.NewSyncProducer(p.addr, p.config) if err == nil { - p.producer = producer return &p } - //TODO If the password is wrong, exit directly - //if packetErr, ok := err.(*sarama.PacketEncodingError); ok { - //if _, ok := packetErr.Err.(sarama.AuthenticationError); ok { - // fmt.Println("Kafka password is wrong.") - //} - //} else { - // fmt.Printf("Failed to create Kafka producer: %v\n", err) - //} - time.Sleep(time.Duration(1) * time.Second) + time.Sleep(1 * time.Second) // Wait before retrying } + + // Panic if unable to create producer after retries if err != nil { - panic(err.Error()) + panic("Failed to create Kafka producer: " + err.Error()) } - p.producer = producer + return &p } +// configureProducerAck configures the producer's acknowledgement level. +func configureProducerAck(p *Producer, ackConfig string) { + switch strings.ToLower(ackConfig) { + case "no_response": + p.config.Producer.RequiredAcks = sarama.NoResponse + case "wait_for_local": + p.config.Producer.RequiredAcks = sarama.WaitForLocal + case "wait_for_all": + p.config.Producer.RequiredAcks = sarama.WaitForAll + default: + p.config.Producer.RequiredAcks = sarama.WaitForAll + } +} + +// configureCompression configures the message compression type for the producer. +func configureCompression(p *Producer, compressType string) { + var compress sarama.CompressionCodec = sarama.CompressionNone + compress.UnmarshalText(bytes.ToLower([]byte(compressType))) + p.config.Producer.Compression = compress +} + +// GetMQHeaderWithContext extracts message queue headers from the context. func GetMQHeaderWithContext(ctx context.Context) ([]sarama.RecordHeader, error) { operationID, opUserID, platform, connID, err := mcontext.GetCtxInfos(ctx) if err != nil { @@ -111,22 +133,23 @@ func GetMQHeaderWithContext(ctx context.Context) ([]sarama.RecordHeader, error) {Key: []byte(constant.OpUserID), Value: []byte(opUserID)}, {Key: []byte(constant.OpUserPlatform), Value: []byte(platform)}, {Key: []byte(constant.ConnID), Value: []byte(connID)}, - }, err + }, nil } +// GetContextWithMQHeader creates a context from message queue headers. func GetContextWithMQHeader(header []*sarama.RecordHeader) context.Context { var values []string for _, recordHeader := range header { values = append(values, string(recordHeader.Value)) } - return mcontext.WithMustInfoCtx(values) // TODO + return mcontext.WithMustInfoCtx(values) // Attach extracted values to context } +// SendMessage sends a message to the Kafka topic configured in the Producer. func (p *Producer) SendMessage(ctx context.Context, key string, msg proto.Message) (int32, int64, error) { log.ZDebug(ctx, "SendMessage", "msg", msg, "topic", p.topic, "key", key) - kMsg := &sarama.ProducerMessage{} - kMsg.Topic = p.topic - kMsg.Key = sarama.StringEncoder(key) + + // Marshal the protobuf message bMsg, err := proto.Marshal(msg) if err != nil { return 0, 0, utils.Wrap(err, "kafka proto Marshal err") @@ -134,20 +157,33 @@ func (p *Producer) SendMessage(ctx context.Context, key string, msg proto.Messag if len(bMsg) == 0 { return 0, 0, utils.Wrap(errEmptyMsg, "") } - kMsg.Value = sarama.ByteEncoder(bMsg) + + // Prepare Kafka message + kMsg := &sarama.ProducerMessage{ + Topic: p.topic, + Key: sarama.StringEncoder(key), + Value: sarama.ByteEncoder(bMsg), + } + + // Validate message key and value if kMsg.Key.Length() == 0 || kMsg.Value.Length() == 0 { return 0, 0, utils.Wrap(errEmptyMsg, "") } - kMsg.Metadata = ctx + + // Attach context metadata as headers header, err := GetMQHeaderWithContext(ctx) if err != nil { return 0, 0, utils.Wrap(err, "") } kMsg.Headers = header + + // Send the message partition, offset, err := p.producer.SendMessage(kMsg) - log.ZDebug(ctx, "ByteEncoder SendMessage end", "key ", kMsg.Key, "key length", kMsg.Value.Length()) if err != nil { log.ZWarn(ctx, "p.producer.SendMessage error", err) + return 0, 0, utils.Wrap(err, "") } - return partition, offset, utils.Wrap(err, "") + + log.ZDebug(ctx, "ByteEncoder SendMessage end", "key", kMsg.Key, "key length", kMsg.Value.Length()) + return partition, offset, nil } diff --git a/pkg/common/kafka/util.go b/pkg/common/kafka/util.go index 722205865..da0c5349b 100644 --- a/pkg/common/kafka/util.go +++ b/pkg/common/kafka/util.go @@ -15,6 +15,8 @@ package kafka import ( + "os" + "github.com/IBM/sarama" "github.com/openimsdk/open-im-server/v3/pkg/common/config" @@ -33,3 +35,12 @@ func SetupTLSConfig(cfg *sarama.Config) { ) } } + +// getEnvOrConfig returns the value of the environment variable if it exists, +// otherwise, it returns the value from the configuration file. +func getEnvOrConfig(envName string, configValue string) string { + if value, exists := os.LookupEnv(envName); exists { + return value + } + return configValue +} diff --git a/pkg/common/prommetrics/gin_api.go b/pkg/common/prommetrics/gin_api.go index 7cd82dad2..c5ef612a2 100644 --- a/pkg/common/prommetrics/gin_api.go +++ b/pkg/common/prommetrics/gin_api.go @@ -1,10 +1,24 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package prommetrics import ginProm "github.com/openimsdk/open-im-server/v3/pkg/common/ginprometheus" /* labels := prometheus.Labels{"label_one": "any", "label_two": "value"} -ApiCustomCnt.MetricCollector.(*prometheus.CounterVec).With(labels).Inc() +ApiCustomCnt.MetricCollector.(*prometheus.CounterVec).With(labels).Inc(). */ var ( ApiCustomCnt = &ginProm.Metric{ diff --git a/pkg/common/prommetrics/grpc_auth.go b/pkg/common/prommetrics/grpc_auth.go index e44c146be..30dd5f1b1 100644 --- a/pkg/common/prommetrics/grpc_auth.go +++ b/pkg/common/prommetrics/grpc_auth.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package prommetrics import ( diff --git a/pkg/common/prommetrics/grpc_msg.go b/pkg/common/prommetrics/grpc_msg.go index 88d4ef3ce..758879b90 100644 --- a/pkg/common/prommetrics/grpc_msg.go +++ b/pkg/common/prommetrics/grpc_msg.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package prommetrics import ( diff --git a/pkg/common/prommetrics/grpc_msggateway.go b/pkg/common/prommetrics/grpc_msggateway.go index bb62426e1..98d5a3267 100644 --- a/pkg/common/prommetrics/grpc_msggateway.go +++ b/pkg/common/prommetrics/grpc_msggateway.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package prommetrics import ( diff --git a/pkg/common/prommetrics/grpc_push.go b/pkg/common/prommetrics/grpc_push.go index aa5085c2c..0b6c3e76f 100644 --- a/pkg/common/prommetrics/grpc_push.go +++ b/pkg/common/prommetrics/grpc_push.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package prommetrics import ( diff --git a/pkg/common/prommetrics/prommetrics.go b/pkg/common/prommetrics/prommetrics.go index 26b02b16f..41719dd2d 100644 --- a/pkg/common/prommetrics/prommetrics.go +++ b/pkg/common/prommetrics/prommetrics.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package prommetrics import ( diff --git a/pkg/common/prommetrics/prommetrics_test.go b/pkg/common/prommetrics/prommetrics_test.go index babc5e410..1e48c63ba 100644 --- a/pkg/common/prommetrics/prommetrics_test.go +++ b/pkg/common/prommetrics/prommetrics_test.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package prommetrics import ( diff --git a/pkg/common/prommetrics/transfer.go b/pkg/common/prommetrics/transfer.go index 6b03870b5..197b6f7fc 100644 --- a/pkg/common/prommetrics/transfer.go +++ b/pkg/common/prommetrics/transfer.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package prommetrics import ( diff --git a/pkg/common/startrpc/start_test.go b/pkg/common/startrpc/start_test.go index 171cdb1c2..481986e15 100644 --- a/pkg/common/startrpc/start_test.go +++ b/pkg/common/startrpc/start_test.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package startrpc import ( diff --git a/pkg/common/version/base.go b/pkg/common/version/base.go index ac214269f..9a656e03a 100644 --- a/pkg/common/version/base.go +++ b/pkg/common/version/base.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package version // Base version information. @@ -15,7 +29,7 @@ package version // When releasing a new Kubernetes version, this file is updated by // build/mark_new_version.sh to reflect the new version, and then a // git annotated tag (using format vX.Y where X == Major version and Y -// == Minor version) is created to point to the commit that updates +// == Minor version) is created to point to the commit that updates. var ( // TODO: Deprecate gitMajor and gitMinor, use only gitVersion // instead. First step in deprecation, keep the fields but make diff --git a/pkg/common/version/types.go b/pkg/common/version/types.go index ee4664149..da9c1ed90 100644 --- a/pkg/common/version/types.go +++ b/pkg/common/version/types.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package version // Info contains versioning information. diff --git a/pkg/common/version/version.go b/pkg/common/version/version.go index b8ccfaf81..3b271b3f6 100644 --- a/pkg/common/version/version.go +++ b/pkg/common/version/version.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package version import ( @@ -25,7 +39,7 @@ func Get() Info { } } -// GetClientVersion returns the git version of the OpenIM client repository +// GetClientVersion returns the git version of the OpenIM client repository. func GetClientVersion() (*OpenIMClientVersion, error) { clientVersion, err := getClientVersion() if err != nil { @@ -52,7 +66,7 @@ func getClientVersion() (string, error) { return ref.Hash().String(), nil } -// GetSingleVersion returns single version of sealer +// GetSingleVersion returns single version of sealer. func GetSingleVersion() string { return gitVersion } diff --git a/pkg/rpcclient/grouphash/grouphash.go b/pkg/rpcclient/grouphash/grouphash.go index b5570dccd..dee47ad44 100644 --- a/pkg/rpcclient/grouphash/grouphash.go +++ b/pkg/rpcclient/grouphash/grouphash.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package grouphash import ( diff --git a/scripts/check-all.sh b/scripts/check-all.sh index 5acae3498..30a4e422b 100755 --- a/scripts/check-all.sh +++ b/scripts/check-all.sh @@ -33,8 +33,8 @@ openim::log::info "\n# Begin to check all openim service" # OpenIM status # Elegant printing function print_services_and_ports() { - local -n service_names=$1 - local -n service_ports=$2 + declare -g service_names=("${!1}") + declare -g service_ports=("${!2}") echo "+-------------------------+----------+" echo "| Service Name | Port |" diff --git a/scripts/githooks/pre-push.sh b/scripts/githooks/pre-push.sh index 2985313b7..e341cf4f2 100644 --- a/scripts/githooks/pre-push.sh +++ b/scripts/githooks/pre-push.sh @@ -102,7 +102,7 @@ print_color "Deleted Files: ${deleted_files}" "${BACKGROUND_GREEN}" if [[ ! $local_branch =~ $valid_branch_regex ]] then printError "There is something wrong with your branch name. Branch names in this project must adhere to this contract: $valid_branch_regex. -Your commit will be rejected. You should rename your branch to a valid name(feat/name OR bug/name) and try again." +Your commit will be rejected. You should rename your branch to a valid name(feat/name OR fix/name) and try again." printError "For more on this, read on: https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694" exit 1 fi diff --git a/scripts/init-config.sh b/scripts/init-config.sh index 0b9c0e615..c75fc5502 100755 --- a/scripts/init-config.sh +++ b/scripts/init-config.sh @@ -1,4 +1,17 @@ #!/usr/bin/env bash +# Copyright © 2023 OpenIM. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # This script automatically initializes various configuration files and can generate example files. @@ -31,6 +44,20 @@ declare -A EXAMPLES=( ["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/templates/alertmanager.yml.template" ) +# Templates for config Copy file +declare -A COPY_TEMPLATES=( + ["${OPENIM_ROOT}/deployments/templates/email.tmpl"]="${OPENIM_ROOT}/config/email.tmpl" + ["${OPENIM_ROOT}/deployments/templates/instance-down-rules.yml"]="${OPENIM_ROOT}/config/instance-down-rules.yml" + ["${OPENIM_ROOT}/deployments/templates/notification.yaml"]="${OPENIM_ROOT}/config/notification.yaml" +) + +# Templates for config Copy file +declare -A COPY_EXAMPLES=( + ["${OPENIM_ROOT}/deployments/templates/email.tmpl"]="${OPENIM_ROOT}/config/templates/email.tmpl.template" + ["${OPENIM_ROOT}/deployments/templates/instance-down-rules.yml"]="${OPENIM_ROOT}/config/templates/instance-down-rules.yml.template" + ["${OPENIM_ROOT}/deployments/templates/notification.yaml"]="${OPENIM_ROOT}/config/templates/notification.yaml.template" +) + # Command-line options FORCE_OVERWRITE=false SKIP_EXISTING=false @@ -50,84 +77,101 @@ show_help() { echo " --clean-examples Clean all example files" } -# Function to generate configuration files +# Function to generate and copy configuration files generate_config_files() { + # Handle TEMPLATES array for template in "${!TEMPLATES[@]}"; do local output_file="${TEMPLATES[$template]}" - if [[ -f "${output_file}" ]]; then - if [[ "${FORCE_OVERWRITE}" == true ]]; then - openim::log::info "Force overwriting ${output_file}." - elif [[ "${SKIP_EXISTING}" == true ]]; then - openim::log::info "Skipping generation of ${output_file} as it already exists." - continue - else - echo -n "File ${output_file} already exists. Overwrite? (Y/N): " - read -r -n 1 REPLY - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - openim::log::info "Skipping generation of ${output_file}." - continue - fi - fi - else - if [[ "${SKIP_EXISTING}" == true ]]; then - openim::log::info "Generating ${output_file} as it does not exist." - fi - fi + process_file "$template" "$output_file" true + done - openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..." - if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then - openim::log::error "genconfig.sh script not found" - exit 1 - fi - "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || { - openim::log::error "Error processing template file ${template}" - exit 1 - } - sleep 0.5 + # Handle COPY_TEMPLATES array + for template in "${!COPY_TEMPLATES[@]}"; do + local output_file="${COPY_TEMPLATES[$template]}" + process_file "$template" "$output_file" false done } # Function to generate example files generate_example_files() { + env_cmd="env -i" + for var in "${!env_vars[@]}"; do + env_cmd+=" $var='${env_vars[$var]}'" + done + + # Processing EXAMPLES array for template in "${!EXAMPLES[@]}"; do local example_file="${EXAMPLES[$template]}" - if [[ -f "${example_file}" ]]; then - if [[ "${FORCE_OVERWRITE}" == true ]]; then - openim::log::info "Force overwriting example file: ${example_file}." - elif [[ "${SKIP_EXISTING}" == true ]]; then - openim::log::info "Skipping generation of example file: ${example_file} as it already exists." - continue - else - echo -n "Example file ${example_file} already exists. Overwrite? (Y/N): " - read -r -n 1 REPLY - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - openim::log::info "Skipping generation of example file: ${example_file}." - continue - fi - fi + process_file "$template" "$example_file" true + done + + # Processing COPY_EXAMPLES array + for template in "${!COPY_EXAMPLES[@]}"; do + local example_file="${COPY_EXAMPLES[$template]}" + process_file "$template" "$example_file" false + done + +} + +# Function to process a single file, either by generating or copying +process_file() { + local template=$1 + local output_file=$2 + local use_genconfig=$3 + + if [[ -f "${output_file}" ]]; then + if [[ "${FORCE_OVERWRITE}" == true ]]; then + openim::log::info "Force overwriting ${output_file}." elif [[ "${SKIP_EXISTING}" == true ]]; then - openim::log::info "Generating example file: ${example_file} as it does not exist." + openim::log::info "Skipping generation of ${output_file} as it already exists." + return + else + echo -n "File ${output_file} already exists. Overwrite? (Y/N): " + read -r -n 1 REPLY + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + openim::log::info "Skipping generation of ${output_file}." + return + fi + fi + else + if [[ "${SKIP_EXISTING}" == true ]]; then + openim::log::info "Generating ${output_file} as it does not exist." fi + fi - openim::log::info "⌚ Working with template file: ${template} to generate example file: ${example_file}..." + if [[ "$use_genconfig" == true ]]; then + openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..." if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then openim::log::error "genconfig.sh script not found" exit 1 fi - "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${example_file}" || { - openim::log::error "Error processing template file ${template}" + if [[ -n "${env_cmd}" ]]; then + eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${output_file}'" || { + openim::log::error "Error processing template file ${template}" + exit 1 + } + else + "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || { + openim::log::error "Error processing template file ${template}" + exit 1 + } + fi + else + openim::log::info "📋 Copying ${template} to ${output_file}..." + cp "${template}" "${output_file}" || { + openim::log::error "Error copying template file ${template}" exit 1 } - sleep 0.5 - done -} + fi + sleep 0.5 +} -# Function to clean configuration files clean_config_files() { - for output_file in "${TEMPLATES[@]}"; do + local all_templates=("${TEMPLATES[@]}" "${COPY_TEMPLATES[@]}") + + for output_file in "${all_templates[@]}"; do if [[ -f "${output_file}" ]]; then rm -f "${output_file}" openim::log::info "Removed configuration file: ${output_file}" @@ -137,7 +181,10 @@ clean_config_files() { # Function to clean example files clean_example_files() { - for example_file in "${EXAMPLES[@]}"; do + # 合并 EXAMPLES 和 COPY_EXAMPLES 数组 + local all_examples=("${EXAMPLES[@]}" "${COPY_EXAMPLES[@]}") + + for example_file in "${all_examples[@]}"; do if [[ -f "${example_file}" ]]; then rm -f "${example_file}" openim::log::info "Removed example file: ${example_file}" diff --git a/test/e2e/api/token/token.go b/test/e2e/api/token/token.go index 4c578e8f7..88af72058 100644 --- a/test/e2e/api/token/token.go +++ b/test/e2e/api/token/token.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package token import ( @@ -9,7 +23,7 @@ import ( "net/http" ) -// API endpoints and other constants +// API endpoints and other constants. const ( APIHost = "http://127.0.0.1:10002" UserTokenURL = APIHost + "/auth/user_token" @@ -18,27 +32,27 @@ const ( OperationID = "1646445464564" ) -// UserTokenRequest represents a request to get a user token +// UserTokenRequest represents a request to get a user token. type UserTokenRequest struct { Secret string `json:"secret"` PlatformID int `json:"platformID"` UserID string `json:"userID"` } -// UserTokenResponse represents a response containing a user token +// UserTokenResponse represents a response containing a user token. type UserTokenResponse struct { Token string `json:"token"` ErrCode int `json:"errCode"` } -// User represents user data for registration +// User represents user data for registration. type User struct { UserID string `json:"userID"` Nickname string `json:"nickname"` FaceURL string `json:"faceURL"` } -// UserRegisterRequest represents a request to register a user +// UserRegisterRequest represents a request to register a user. type UserRegisterRequest struct { Secret string `json:"secret"` Users []User `json:"users"` @@ -58,7 +72,7 @@ func main() { } } -// GetUserToken requests a user token from the API +// GetUserToken requests a user token from the API. func GetUserToken(userID string) (string, error) { reqBody := UserTokenRequest{ Secret: SecretKey, @@ -88,7 +102,7 @@ func GetUserToken(userID string) (string, error) { return tokenResp.Token, nil } -// RegisterUser registers a new user using the API +// RegisterUser registers a new user using the API. func RegisterUser(token, userID, nickname, faceURL string) error { user := User{ UserID: userID, diff --git a/test/e2e/api/user/curd.go b/test/e2e/api/user/curd.go index c0380b235..1b56492b3 100644 --- a/test/e2e/api/user/curd.go +++ b/test/e2e/api/user/curd.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package user import ( @@ -7,18 +21,18 @@ import ( "github.com/openimsdk/open-im-server/v3/test/e2e/framework/config" ) -// UserInfoRequest represents a request to get or update user information +// UserInfoRequest represents a request to get or update user information. type UserInfoRequest struct { UserIDs []string `json:"userIDs,omitempty"` UserInfo *gettoken.User `json:"userInfo,omitempty"` } -// GetUsersOnlineStatusRequest represents a request to get users' online status +// GetUsersOnlineStatusRequest represents a request to get users' online status. type GetUsersOnlineStatusRequest struct { UserIDs []string `json:"userIDs"` } -// GetUsersInfo retrieves detailed information for a list of user IDs +// GetUsersInfo retrieves detailed information for a list of user IDs. func GetUsersInfo(token string, userIDs []string) error { url := fmt.Sprintf("http://%s:%s/user/get_users_info", config.LoadConfig().APIHost, config.LoadConfig().APIPort) @@ -29,7 +43,7 @@ func GetUsersInfo(token string, userIDs []string) error { return sendPostRequestWithToken(url, token, requestBody) } -// UpdateUserInfo updates the information for a user +// UpdateUserInfo updates the information for a user. func UpdateUserInfo(token, userID, nickname, faceURL string) error { url := fmt.Sprintf("http://%s:%s/user/update_user_info", config.LoadConfig().APIHost, config.LoadConfig().APIPort) @@ -44,7 +58,7 @@ func UpdateUserInfo(token, userID, nickname, faceURL string) error { return sendPostRequestWithToken(url, token, requestBody) } -// GetUsersOnlineStatus retrieves the online status for a list of user IDs +// GetUsersOnlineStatus retrieves the online status for a list of user IDs. func GetUsersOnlineStatus(token string, userIDs []string) error { url := fmt.Sprintf("http://%s:%s/user/get_users_online_status", config.LoadConfig().APIHost, config.LoadConfig().APIPort) diff --git a/test/e2e/api/user/user.go b/test/e2e/api/user/user.go index 9facf76ac..fd8144acd 100644 --- a/test/e2e/api/user/user.go +++ b/test/e2e/api/user/user.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package user import ( @@ -11,29 +25,29 @@ import ( "github.com/openimsdk/open-im-server/v3/test/e2e/framework/config" ) -// ForceLogoutRequest represents a request to force a user logout +// ForceLogoutRequest represents a request to force a user logout. type ForceLogoutRequest struct { PlatformID int `json:"platformID"` UserID string `json:"userID"` } -// CheckUserAccountRequest represents a request to check a user account +// CheckUserAccountRequest represents a request to check a user account. type CheckUserAccountRequest struct { CheckUserIDs []string `json:"checkUserIDs"` } -// GetUsersRequest represents a request to get a list of users +// GetUsersRequest represents a request to get a list of users. type GetUsersRequest struct { Pagination Pagination `json:"pagination"` } -// Pagination specifies the page number and number of items per page +// Pagination specifies the page number and number of items per page. type Pagination struct { PageNumber int `json:"pageNumber"` ShowNumber int `json:"showNumber"` } -// ForceLogout forces a user to log out +// ForceLogout forces a user to log out. func ForceLogout(token, userID string, platformID int) error { url := fmt.Sprintf("http://%s:%s/auth/force_logout", config.LoadConfig().APIHost, config.LoadConfig().APIPort) @@ -45,7 +59,7 @@ func ForceLogout(token, userID string, platformID int) error { return sendPostRequestWithToken(url, token, requestBody) } -// CheckUserAccount checks if the user accounts exist +// CheckUserAccount checks if the user accounts exist. func CheckUserAccount(token string, userIDs []string) error { url := fmt.Sprintf("http://%s:%s/user/account_check", config.LoadConfig().APIHost, config.LoadConfig().APIPort) @@ -56,7 +70,7 @@ func CheckUserAccount(token string, userIDs []string) error { return sendPostRequestWithToken(url, token, requestBody) } -// GetUsers retrieves a list of users with pagination +// GetUsers retrieves a list of users with pagination. func GetUsers(token string, pageNumber, showNumber int) error { url := fmt.Sprintf("http://%s:%s/user/account_check", config.LoadConfig().APIHost, config.LoadConfig().APIPort) @@ -70,7 +84,7 @@ func GetUsers(token string, pageNumber, showNumber int) error { return sendPostRequestWithToken(url, token, requestBody) } -// sendPostRequestWithToken sends a POST request with a token in the header +// sendPostRequestWithToken sends a POST request with a token in the header. func sendPostRequestWithToken(url, token string, body any) error { reqBytes, err := json.Marshal(body) if err != nil { diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index d1d6c5509..a3d3b1bcf 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package e2e import ( diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 8fe810789..a6496679c 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package e2e import ( diff --git a/test/e2e/framework/config/config.go b/test/e2e/framework/config/config.go index ed3c6a258..14074fec1 100644 --- a/test/e2e/framework/config/config.go +++ b/test/e2e/framework/config/config.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package config import ( diff --git a/test/e2e/framework/config/config_test.go b/test/e2e/framework/config/config_test.go index c411df31e..b7259bf37 100644 --- a/test/e2e/framework/config/config_test.go +++ b/test/e2e/framework/config/config_test.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package config import ( diff --git a/test/e2e/framework/ginkgowrapper/ginkgowrapper.go b/test/e2e/framework/ginkgowrapper/ginkgowrapper.go index 16779440b..814d393bc 100644 --- a/test/e2e/framework/ginkgowrapper/ginkgowrapper.go +++ b/test/e2e/framework/ginkgowrapper/ginkgowrapper.go @@ -1 +1,15 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ginkgowrapper diff --git a/test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go b/test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go index 16779440b..814d393bc 100644 --- a/test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go +++ b/test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go @@ -1 +1,15 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ginkgowrapper diff --git a/test/e2e/framework/helpers/chat/chat.go b/test/e2e/framework/helpers/chat/chat.go index 4fca28f2a..a4ead528b 100644 --- a/test/e2e/framework/helpers/chat/chat.go +++ b/test/e2e/framework/helpers/chat/chat.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( @@ -10,7 +24,7 @@ import ( ) var ( - // The default template version + // The default template version. defaultTemplateVersion = "v1.3.0" ) @@ -84,7 +98,7 @@ func main() { select {} } -// getLatestVersion fetches the latest version number from a given URL +// getLatestVersion fetches the latest version number from a given URL. func getLatestVersion(url string) (string, error) { resp, err := http.Get(url) if err != nil { @@ -102,7 +116,7 @@ func getLatestVersion(url string) (string, error) { return latestVersion, nil } -// downloadAndExtract downloads a file from a URL and extracts it to a destination directory +// downloadAndExtract downloads a file from a URL and extracts it to a destination directory. func downloadAndExtract(url, destDir string) error { resp, err := http.Get(url) if err != nil { @@ -141,7 +155,7 @@ func downloadAndExtract(url, destDir string) error { return cmd.Run() } -// startProcess starts a process and prints any errors encountered +// startProcess starts a process and prints any errors encountered. func startProcess(cmdPath string) { cmd := exec.Command(cmdPath) cmd.Stdout = os.Stdout diff --git a/tools/component/component.go b/tools/component/component.go index 140313c30..7150c91af 100644 --- a/tools/component/component.go +++ b/tools/component/component.go @@ -16,7 +16,6 @@ package main import ( "context" - "database/sql" "flag" "fmt" "net" @@ -31,15 +30,11 @@ import ( "github.com/IBM/sarama" "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/utils" "github.com/go-zookeeper/zk" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - "gorm.io/driver/mysql" - "gorm.io/gorm" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - "github.com/openimsdk/open-im-server/v3/pkg/common/kafka" "github.com/minio/minio-go/v7/pkg/credentials" ) @@ -53,6 +48,12 @@ const ( configErrCode = 6001 ) +const ( + colorRed = 31 + colorGreen = 32 + colorYellow = 33 +) + var ( cfgPath = flag.String("c", defaultCfgPath, "Path to the configuration file") @@ -132,127 +133,131 @@ func exactIP(urll string) string { return host } -func checkMysql() error { - if config.Config.Mysql == nil { - return nil +// Helper function to get environment variable or default value +func getEnv(key, fallback string) string { + if value, exists := os.LookupEnv(key); exists { + return value } - var sqlDB *sql.DB - defer func() { - if sqlDB != nil { - sqlDB.Close() - } - }() - dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local", - config.Config.Mysql.Username, config.Config.Mysql.Password, config.Config.Mysql.Address[0], "mysql") - db, err := gorm.Open(mysql.Open(dsn), nil) + return fallback +} + +// checkMongo checks the MongoDB connection +func checkMongo() error { + // Use environment variables or fallback to config + uri := getEnv("MONGO_URI", buildMongoURI()) + + client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri)) if err != nil { return errs.Wrap(err) - } else { - sqlDB, err = db.DB() - err = sqlDB.Ping() - if err != nil { - return errs.Wrap(err) - } + } + defer client.Disconnect(context.TODO()) + + if err = client.Ping(context.TODO(), nil); err != nil { + return errs.Wrap(err) } return nil } -func checkMongo() error { - var client *mongo.Client - uri := "mongodb://sample.host:27017/?maxPoolSize=20&w=majority" - defer func() { - if client != nil { - client.Disconnect(context.TODO()) - } - }() - if config.Config.Mongo.Uri != "" { - uri = config.Config.Mongo.Uri - } else { - mongodbHosts := "" - for i, v := range config.Config.Mongo.Address { - if i == len(config.Config.Mongo.Address)-1 { - mongodbHosts += v - } else { - mongodbHosts += v + "," - } - } - if config.Config.Mongo.Password != "" && config.Config.Mongo.Username != "" { - uri = fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d&authSource=admin", - config.Config.Mongo.Username, config.Config.Mongo.Password, mongodbHosts, - config.Config.Mongo.Database, config.Config.Mongo.MaxPoolSize) - } else { - uri = fmt.Sprintf("mongodb://%s/%s/?maxPoolSize=%d&authSource=admin", - mongodbHosts, config.Config.Mongo.Database, - config.Config.Mongo.MaxPoolSize) - } +// buildMongoURI constructs the MongoDB URI using configuration settings +func buildMongoURI() string { + // Fallback to config if environment variables are not set + username := config.Config.Mongo.Username + password := config.Config.Mongo.Password + database := config.Config.Mongo.Database + maxPoolSize := config.Config.Mongo.MaxPoolSize + + mongodbHosts := strings.Join(config.Config.Mongo.Address, ",") + + if username != "" && password != "" { + return fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d&authSource=admin", + username, password, mongodbHosts, database, maxPoolSize) } - client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri)) + return fmt.Sprintf("mongodb://%s/%s?maxPoolSize=%d&authSource=admin", + mongodbHosts, database, maxPoolSize) +} + +// checkMinio checks the MinIO connection +func checkMinio() error { + // Check if MinIO is enabled + if config.Config.Object.Enable != "minio" { + return nil + } + + // Prioritize environment variables + endpoint := getEnv("MINIO_ENDPOINT", config.Config.Object.Minio.Endpoint) + accessKeyID := getEnv("MINIO_ACCESS_KEY_ID", config.Config.Object.Minio.AccessKeyID) + secretAccessKey := getEnv("MINIO_SECRET_ACCESS_KEY", config.Config.Object.Minio.SecretAccessKey) + useSSL := getEnv("MINIO_USE_SSL", "false") // Assuming SSL is not used by default + + if endpoint == "" || accessKeyID == "" || secretAccessKey == "" { + return ErrConfig.Wrap("MinIO configuration missing") + } + + // Parse endpoint URL to determine if SSL is enabled + u, err := url.Parse(endpoint) if err != nil { return errs.Wrap(err) - } else { - err = client.Ping(context.TODO(), nil) - if err != nil { - return errs.Wrap(err) - } } + secure := u.Scheme == "https" || useSSL == "true" - return nil -} + // Initialize MinIO client + minioClient, err := minio.New(u.Host, &minio.Options{ + Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""), + Secure: secure, + }) + if err != nil { + return errs.Wrap(err) + } -func checkMinio() error { - if config.Config.Object.Enable == "minio" { - conf := config.Config.Object.Minio - u, _ := url.Parse(conf.Endpoint) - minioClient, err := minio.New(u.Host, &minio.Options{ - Creds: credentials.NewStaticV4(conf.AccessKeyID, conf.SecretAccessKey, ""), - Secure: u.Scheme == "https", - }) - if err != nil { - return errs.Wrap(err) - } + // Perform health check + cancel, err := minioClient.HealthCheck(time.Duration(minioHealthCheckDuration) * time.Second) + if err != nil { + return errs.Wrap(err) + } + defer cancel() - cancel, err := minioClient.HealthCheck(time.Duration(minioHealthCheckDuration) * time.Second) - defer func() { - if cancel != nil { - cancel() - } - }() - if err != nil { - return errs.Wrap(err) - } else { - if minioClient.IsOffline() { - return ErrComponentStart.Wrap("Minio server is offline") - } - } - if exactIP(config.Config.Object.ApiURL) == "127.0.0.1" || exactIP(config.Config.Object.Minio.SignEndpoint) == "127.0.0.1" { - return ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1") - } + if minioClient.IsOffline() { + return ErrComponentStart.Wrap("Minio server is offline") + } + + // Check for localhost in API URL and Minio SignEndpoint + if exactIP(config.Config.Object.ApiURL) == "127.0.0.1" || exactIP(config.Config.Object.Minio.SignEndpoint) == "127.0.0.1" { + return ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1") } return nil } +// checkRedis checks the Redis connection func checkRedis() error { + // Prioritize environment variables + address := getEnv("REDIS_ADDRESS", strings.Join(config.Config.Redis.Address, ",")) + username := getEnv("REDIS_USERNAME", config.Config.Redis.Username) + password := getEnv("REDIS_PASSWORD", config.Config.Redis.Password) + + // Split address to handle multiple addresses for cluster setup + redisAddresses := strings.Split(address, ",") + var redisClient redis.UniversalClient - defer func() { - if redisClient != nil { - redisClient.Close() - } - }() - if len(config.Config.Redis.Address) > 1 { + if len(redisAddresses) > 1 { + // Use cluster client for multiple addresses redisClient = redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: config.Config.Redis.Address, - Username: config.Config.Redis.Username, - Password: config.Config.Redis.Password, + Addrs: redisAddresses, + Username: username, + Password: password, }) } else { + // Use regular client for single address redisClient = redis.NewClient(&redis.Options{ - Addr: config.Config.Redis.Address[0], - Username: config.Config.Redis.Username, - Password: config.Config.Redis.Password, + Addr: redisAddresses[0], + Username: username, + Password: password, }) } + defer redisClient.Close() + + // Ping Redis to check connectivity _, err := redisClient.Ping(context.Background()).Result() if err != nil { return errs.Wrap(err) @@ -261,75 +266,110 @@ func checkRedis() error { return nil } +// checkZookeeper checks the Zookeeper connection func checkZookeeper() error { - var c *zk.Conn - defer func() { - if c != nil { - c.Close() - } - }() - c, _, err := zk.Connect(config.Config.Zookeeper.ZkAddr, time.Second) + // Prioritize environment variables + schema := getEnv("ZOOKEEPER_SCHEMA", "digest") + address := getEnv("ZOOKEEPER_ADDRESS", strings.Join(config.Config.Zookeeper.ZkAddr, ",")) + username := getEnv("ZOOKEEPER_USERNAME", config.Config.Zookeeper.Username) + password := getEnv("ZOOKEEPER_PASSWORD", config.Config.Zookeeper.Password) + + // Split addresses to handle multiple Zookeeper nodes + zookeeperAddresses := strings.Split(address, ",") + + // Connect to Zookeeper + c, _, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary if err != nil { return errs.Wrap(err) - } else { - if config.Config.Zookeeper.Username != "" && config.Config.Zookeeper.Password != "" { - if err := c.AddAuth("digest", []byte(config.Config.Zookeeper.Username+":"+config.Config.Zookeeper.Password)); err != nil { - return errs.Wrap(err) - } - } - _, _, err = c.Get("/") - if err != nil { + } + defer c.Close() + + // Set authentication if username and password are provided + if username != "" && password != "" { + if err := c.AddAuth(schema, []byte(username+":"+password)); err != nil { return errs.Wrap(err) } } + // Check if Zookeeper is reachable + _, _, err = c.Get("/") + if err != nil { + return errs.Wrap(err) + } + return nil } +// checkKafka checks the Kafka connection func checkKafka() error { - var kafkaClient sarama.Client - defer func() { - if kafkaClient != nil { - kafkaClient.Close() - } - }() + // Prioritize environment variables + username := getEnv("KAFKA_USERNAME", config.Config.Kafka.Username) + password := getEnv("KAFKA_PASSWORD", config.Config.Kafka.Password) + address := getEnv("KAFKA_ADDRESS", strings.Join(config.Config.Kafka.Addr, ",")) + + // Split addresses to handle multiple Kafka brokers + kafkaAddresses := strings.Split(address, ",") + + // Configure Kafka client cfg := sarama.NewConfig() - if config.Config.Kafka.Username != "" && config.Config.Kafka.Password != "" { + if username != "" && password != "" { cfg.Net.SASL.Enable = true - cfg.Net.SASL.User = config.Config.Kafka.Username - cfg.Net.SASL.Password = config.Config.Kafka.Password + cfg.Net.SASL.User = username + cfg.Net.SASL.Password = password } - kafka.SetupTLSConfig(cfg) - kafkaClient, err := sarama.NewClient(config.Config.Kafka.Addr, cfg) + // Additional Kafka setup (e.g., TLS configuration) can be added here + // kafka.SetupTLSConfig(cfg) + + // Create Kafka client + kafkaClient, err := sarama.NewClient(kafkaAddresses, cfg) if err != nil { return errs.Wrap(err) - } else { - topics, err := kafkaClient.Topics() - if err != nil { - return err - } - if !utils.IsContain(config.Config.Kafka.MsgToMongo.Topic, topics) { - return ErrComponentStart.Wrap(fmt.Sprintf("kafka doesn't contain topic:%v", config.Config.Kafka.MsgToMongo.Topic)) - } - if !utils.IsContain(config.Config.Kafka.MsgToPush.Topic, topics) { - return ErrComponentStart.Wrap(fmt.Sprintf("kafka doesn't contain topic:%v", config.Config.Kafka.MsgToPush.Topic)) - } - if !utils.IsContain(config.Config.Kafka.LatestMsgToRedis.Topic, topics) { - return ErrComponentStart.Wrap(fmt.Sprintf("kafka doesn't contain topic:%v", config.Config.Kafka.LatestMsgToRedis.Topic)) + } + defer kafkaClient.Close() + + // Verify if necessary topics exist + topics, err := kafkaClient.Topics() + if err != nil { + return errs.Wrap(err) + } + + requiredTopics := []string{ + config.Config.Kafka.MsgToMongo.Topic, + config.Config.Kafka.MsgToPush.Topic, + config.Config.Kafka.LatestMsgToRedis.Topic, + } + + for _, requiredTopic := range requiredTopics { + if !isTopicPresent(requiredTopic, topics) { + return ErrComponentStart.Wrap(fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic)) } } return nil } +// isTopicPresent checks if a topic is present in the list of topics +func isTopicPresent(topic string, topics []string) bool { + for _, t := range topics { + if t == topic { + return true + } + } + return false +} + +func colorPrint(colorCode int, format string, a ...interface{}) { + fmt.Printf("\x1b[%dm%s\x1b[0m\n", colorCode, fmt.Sprintf(format, a...)) +} + func errorPrint(s string) { - fmt.Printf("\x1b[%dm%v\x1b[0m\n", 31, s) + colorPrint(colorRed, "%v", s) } func successPrint(s string) { - fmt.Printf("\x1b[%dm%v\x1b[0m\n", 32, s) + colorPrint(colorGreen, "%v", s) } func warningPrint(s string) { - fmt.Printf("\x1b[%dmWarning: But %v\x1b[0m\n", 33, s) + colorPrint(colorYellow, "Warning: But %v", s) } diff --git a/tools/data-conversion/chat/cmd/conversion-chat/chat.go b/tools/data-conversion/chat/cmd/conversion-chat/chat.go index 77c62ee1f..0fc49c782 100644 --- a/tools/data-conversion/chat/cmd/conversion-chat/chat.go +++ b/tools/data-conversion/chat/cmd/conversion-chat/chat.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( diff --git a/tools/data-conversion/chat/conversion/conversion.go b/tools/data-conversion/chat/conversion/conversion.go index 6032a4569..084fff59c 100644 --- a/tools/data-conversion/chat/conversion/conversion.go +++ b/tools/data-conversion/chat/conversion/conversion.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package conversion import ( diff --git a/tools/data-conversion/chat/v2/admin.go b/tools/data-conversion/chat/v2/admin.go index 7bc1b6c1b..fec11ff5b 100644 --- a/tools/data-conversion/chat/v2/admin.go +++ b/tools/data-conversion/chat/v2/admin.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package v2 import ( diff --git a/tools/data-conversion/chat/v2/chat.go b/tools/data-conversion/chat/v2/chat.go index 6690e110b..15cc4797f 100644 --- a/tools/data-conversion/chat/v2/chat.go +++ b/tools/data-conversion/chat/v2/chat.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package v2 import ( diff --git a/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go b/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go index 338fbf111..f2b9623a6 100644 --- a/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go +++ b/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( diff --git a/tools/data-conversion/openim/mysql/cmd.go b/tools/data-conversion/openim/mysql/cmd.go index 924b0a206..f5a23facb 100644 --- a/tools/data-conversion/openim/mysql/cmd.go +++ b/tools/data-conversion/openim/mysql/cmd.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mysql import ( diff --git a/tools/data-conversion/openim/mysql/conversion/conversion.go b/tools/data-conversion/openim/mysql/conversion/conversion.go index 54cf90edf..f371654df 100644 --- a/tools/data-conversion/openim/mysql/conversion/conversion.go +++ b/tools/data-conversion/openim/mysql/conversion/conversion.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package conversion import ( diff --git a/tools/data-conversion/openim/mysql/v2/model_struct.go b/tools/data-conversion/openim/mysql/v2/model_struct.go index 9da33f2a5..f05b84977 100644 --- a/tools/data-conversion/openim/mysql/v2/model_struct.go +++ b/tools/data-conversion/openim/mysql/v2/model_struct.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package db import "time" diff --git a/tools/data-conversion/openim/mysql/v3/log.go b/tools/data-conversion/openim/mysql/v3/log.go index 5904a790e..22198ca7c 100644 --- a/tools/data-conversion/openim/mysql/v3/log.go +++ b/tools/data-conversion/openim/mysql/v3/log.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package relation import ( diff --git a/tools/data-conversion/openim/proto/msg/msg.proto b/tools/data-conversion/openim/proto/msg/msg.proto index d2fe5337e..3149a7337 100644 --- a/tools/data-conversion/openim/proto/msg/msg.proto +++ b/tools/data-conversion/openim/proto/msg/msg.proto @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + syntax = "proto3"; import "Open-IM-Server/pkg/proto/sdk_ws/ws.proto"; import "Open-IM-Server/pkg/proto/sdk_ws/wrappers.proto"; diff --git a/tools/data-conversion/openim/proto/sdk_ws/ws.proto b/tools/data-conversion/openim/proto/sdk_ws/ws.proto index c8ef680c9..95b956b0e 100644 --- a/tools/data-conversion/openim/proto/sdk_ws/ws.proto +++ b/tools/data-conversion/openim/proto/sdk_ws/ws.proto @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + syntax = "proto3"; import "Open-IM-Server/pkg/proto/sdk_ws/wrappers.proto"; option go_package = "Open_IM/pkg/proto/sdk_ws;server_api_params"; diff --git a/tools/data-conversion/utils/find_insert.go b/tools/data-conversion/utils/find_insert.go index 4789cd554..150820fce 100644 --- a/tools/data-conversion/utils/find_insert.go +++ b/tools/data-conversion/utils/find_insert.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package utils import ( diff --git a/tools/data-conversion/utils/time.go b/tools/data-conversion/utils/time.go index e2dac4bb8..9077a3d88 100644 --- a/tools/data-conversion/utils/time.go +++ b/tools/data-conversion/utils/time.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package utils import "time" diff --git a/tools/infra/infra.go b/tools/infra/infra.go index f8d8c7522..c14b92fa3 100644 --- a/tools/infra/infra.go +++ b/tools/infra/infra.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( diff --git a/tools/up35/pkg/convert.go b/tools/up35/pkg/convert.go index 91fdb474e..24d3a2781 100644 --- a/tools/up35/pkg/convert.go +++ b/tools/up35/pkg/convert.go @@ -1,11 +1,26 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import ( + "time" + mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3" mongoModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" mysqlModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mysql" - "time" ) type convert struct{} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go index e3bab7af9..fd0f2818b 100644 --- a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go @@ -1,14 +1,30 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( "context" + "time" + "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" - "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - "time" + + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" ) func NewMeeting(db *mongo.Database) (table.MeetingInterface, error) { diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go index 5286ffa95..9926748bf 100644 --- a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go @@ -1,15 +1,31 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( "context" + "time" + "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - "time" + + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" ) func NewMeetingInvitation(db *mongo.Database) (table.MeetingInvitationInterface, error) { @@ -55,7 +71,12 @@ func (x *meetingInvitation) CreateMeetingInvitationInfo(ctx context.Context, roo func (x *meetingInvitation) GetUserInvitedMeetingIDs(ctx context.Context, userID string) (meetingIDs []string, err error) { fiveDaysAgo := time.Now().AddDate(0, 0, -5) - return mgoutil.Find[string](ctx, x.coll, bson.M{"user_id": userID, "create_time": bson.M{"$gte": fiveDaysAgo}}, options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1})) + return mgoutil.Find[string]( + ctx, + x.coll, + bson.M{"user_id": userID, "create_time": bson.M{"$gte": fiveDaysAgo}}, + options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1}), + ) } func (x *meetingInvitation) Delete(ctx context.Context, roomIDs []string) error { diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go index 90fc9cdca..4e9dc5e0f 100644 --- a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go @@ -1,11 +1,27 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( "context" + "github.com/OpenIMSDK/tools/mgoutil" - "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" + + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" ) func NewMeetingRecord(db *mongo.Database) (table.MeetingRecordInterface, error) { diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go index 0c1879007..47fd3fb02 100644 --- a/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go @@ -1,14 +1,30 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( "context" + "time" + "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" - "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - "time" + + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" ) func NewSignal(db *mongo.Database) (table.SignalInterface, error) { diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go index 274f2f11f..1f76381e9 100644 --- a/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go @@ -1,15 +1,31 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( "context" + "time" + "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - "time" + + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" ) func NewSignalInvitation(db *mongo.Database) (table.SignalInvitationInterface, error) { diff --git a/tools/up35/pkg/internal/rtc/mongo/table/meeting.go b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go index 3b341cfb1..6ff387bbb 100644 --- a/tools/up35/pkg/internal/rtc/mongo/table/meeting.go +++ b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go @@ -1,9 +1,24 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package table import ( "context" - "github.com/OpenIMSDK/tools/pagination" "time" + + "github.com/OpenIMSDK/tools/pagination" ) type MeetingInfo struct { diff --git a/tools/up35/pkg/internal/rtc/mongo/table/signal.go b/tools/up35/pkg/internal/rtc/mongo/table/signal.go index 0cec050ff..8d8aa96ed 100644 --- a/tools/up35/pkg/internal/rtc/mongo/table/signal.go +++ b/tools/up35/pkg/internal/rtc/mongo/table/signal.go @@ -1,12 +1,27 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package table import ( "context" + "time" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/pagination" "github.com/redis/go-redis/v9" "go.mongodb.org/mongo-driver/mongo" - "time" ) type SignalModel struct { diff --git a/tools/up35/pkg/internal/rtc/mysql/meeting.go b/tools/up35/pkg/internal/rtc/mysql/meeting.go index 2c5bbed32..71515c3b7 100644 --- a/tools/up35/pkg/internal/rtc/mysql/meeting.go +++ b/tools/up35/pkg/internal/rtc/mysql/meeting.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package relation import ( diff --git a/tools/up35/pkg/internal/rtc/mysql/signal.go b/tools/up35/pkg/internal/rtc/mysql/signal.go index 3a4d607d4..c546360a4 100644 --- a/tools/up35/pkg/internal/rtc/mysql/signal.go +++ b/tools/up35/pkg/internal/rtc/mysql/signal.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package relation import ( @@ -16,7 +30,7 @@ type SignalModel struct { SessionType int32 `gorm:"column:sesstion_type"` InitiateTime time.Time `gorm:"column:initiate_time"` EndTime time.Time `gorm:"column:end_time"` - FileURL string `gorm:"column:file_url" json:"-"` + FileURL string `gorm:"column:file_url" json:"-"` Title string `gorm:"column:title;size:128"` Desc string `gorm:"column:desc;size:1024"` diff --git a/tools/up35/pkg/pkg.go b/tools/up35/pkg/pkg.go index d834b8492..6d16817ec 100644 --- a/tools/up35/pkg/pkg.go +++ b/tools/up35/pkg/pkg.go @@ -1,15 +1,30 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import ( "context" "errors" "fmt" - "gopkg.in/yaml.v3" "log" "os" "reflect" "strconv" + "gopkg.in/yaml.v3" + "github.com/go-sql-driver/mysql" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" diff --git a/tools/up35/up35.go b/tools/up35/up35.go index 0ce56ee13..63b6ec2c2 100644 --- a/tools/up35/up35.go +++ b/tools/up35/up35.go @@ -1,10 +1,25 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( "flag" - "github.com/openimsdk/open-im-server/v3/tools/up35/pkg" "log" "os" + + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg" ) func main() { diff --git a/tools/url2im/main.go b/tools/url2im/main.go index ee159b5e8..8d6151b09 100644 --- a/tools/url2im/main.go +++ b/tools/url2im/main.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( diff --git a/tools/url2im/pkg/api.go b/tools/url2im/pkg/api.go index 1fc3813bb..7575b078a 100644 --- a/tools/url2im/pkg/api.go +++ b/tools/url2im/pkg/api.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import ( diff --git a/tools/url2im/pkg/buffer.go b/tools/url2im/pkg/buffer.go index 8ccc5c52f..b4c104652 100644 --- a/tools/url2im/pkg/buffer.go +++ b/tools/url2im/pkg/buffer.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import ( diff --git a/tools/url2im/pkg/config.go b/tools/url2im/pkg/config.go index 020395262..740e748cb 100644 --- a/tools/url2im/pkg/config.go +++ b/tools/url2im/pkg/config.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import "time" diff --git a/tools/url2im/pkg/http.go b/tools/url2im/pkg/http.go index 32e128524..50fb30c7b 100644 --- a/tools/url2im/pkg/http.go +++ b/tools/url2im/pkg/http.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import "net/http" diff --git a/tools/url2im/pkg/manage.go b/tools/url2im/pkg/manage.go index a68078f85..70c6713fc 100644 --- a/tools/url2im/pkg/manage.go +++ b/tools/url2im/pkg/manage.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import ( diff --git a/tools/url2im/pkg/md5.go b/tools/url2im/pkg/md5.go index 0db5ba000..26b8d47a2 100644 --- a/tools/url2im/pkg/md5.go +++ b/tools/url2im/pkg/md5.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import ( diff --git a/tools/url2im/pkg/progress.go b/tools/url2im/pkg/progress.go index 2d6ef3891..5f30495c6 100644 --- a/tools/url2im/pkg/progress.go +++ b/tools/url2im/pkg/progress.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pkg import ( From c8463a0a80ddd350c4e9e7f4070776c160a906a3 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Mon, 18 Dec 2023 12:30:38 +0800 Subject: [PATCH 09/31] Update check-all.sh (#1573) --- scripts/check-all.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/check-all.sh b/scripts/check-all.sh index 30a4e422b..a438ac26b 100755 --- a/scripts/check-all.sh +++ b/scripts/check-all.sh @@ -33,8 +33,8 @@ openim::log::info "\n# Begin to check all openim service" # OpenIM status # Elegant printing function print_services_and_ports() { - declare -g service_names=("${!1}") - declare -g service_ports=("${!2}") + local -n service_names=$1 + local -n service_ports=$2 echo "+-------------------------+----------+" echo "| Service Name | Port |" @@ -89,4 +89,4 @@ else echo "++++ Check all openim service ports successfully !" fi -set -e \ No newline at end of file +set -e From 87610568ae1189540a2e0b6ed5bd42c3540ba4ce Mon Sep 17 00:00:00 2001 From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:39:58 +0800 Subject: [PATCH 10/31] add crud for general function user process, add pinFriend (#1532) * update set pin friends * update set pin friends * update set pin friends * update set pin friends * update set pin friends * update set pin friends * fix bugs * fix bugs * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * Update go.mod * Update friend.go * debug * debug * debug * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * I cannot solve todo in test.sh * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * Update go.mod * fix group notification * fix group notification * update openimsdk tools * update openim server remove duplicate code * update openim server remove duplicate code * update user command get * update user command get * update response of callback response error * update black ex * update join group ex * update user pb2map * update go sum * update go sum --------- Co-authored-by: Xinwei Xiong <3293172751@qq.com> --- go.mod | 8 ++- internal/api/friend.go | 3 ++ internal/api/route.go | 6 +++ internal/api/user.go | 20 +++++++ internal/rpc/friend/black.go | 1 + internal/rpc/friend/friend.go | 38 ++++++++++++-- internal/rpc/group/callback.go | 8 +-- internal/rpc/group/group.go | 2 + internal/rpc/msg/callback.go | 1 - internal/rpc/third/third.go | 10 ++++ internal/rpc/user/user.go | 72 +++++++++++++++++++------ pkg/callbackstruct/group.go | 1 + pkg/common/convert/friend.go | 3 +- pkg/common/convert/user.go | 2 +- pkg/common/db/controller/friend.go | 7 +++ pkg/common/db/controller/user.go | 19 +++++++ pkg/common/db/mgo/friend.go | 19 ++++++- pkg/common/db/mgo/user.go | 73 ++++++++++++++++++++++++++ pkg/common/db/table/relation/friend.go | 3 ++ pkg/common/db/table/relation/user.go | 6 +++ pkg/common/http/http_client.go | 2 +- scripts/install/test.sh | 50 ++++++++++++++++-- 22 files changed, 320 insertions(+), 34 deletions(-) diff --git a/go.mod b/go.mod index 11d374d08..c8dd96689 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,6 @@ go 1.19 require ( firebase.google.com/go v3.13.0+incompatible - github.com/OpenIMSDK/protocol v0.0.31 - github.com/OpenIMSDK/tools v0.0.20 github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/dtm-labs/rockscache v0.1.1 github.com/gin-gonic/gin v1.9.1 @@ -35,6 +33,8 @@ require github.com/google/uuid v1.3.1 require ( github.com/IBM/sarama v1.41.3 + github.com/OpenIMSDK/protocol v0.0.36 + github.com/OpenIMSDK/tools v0.0.20 github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible github.com/go-redis/redis v6.15.9+incompatible github.com/redis/go-redis/v9 v9.2.1 @@ -154,3 +154,7 @@ require ( golang.org/x/crypto v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) +//replace ( +// github.com/OpenIMSDK/protocol v0.0.34 => github.com/AndrewZuo01/protocol v0.0.0-20231218034338-b8d838e0b182 +//) + diff --git a/internal/api/friend.go b/internal/api/friend.go index 23f337a9f..58e7398dd 100644 --- a/internal/api/friend.go +++ b/internal/api/friend.go @@ -92,3 +92,6 @@ func (o *FriendApi) GetFriendIDs(c *gin.Context) { func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) { a2r.Call(friend.FriendClient.GetSpecifiedFriendsInfo, o.Client, c) } +func (o *FriendApi) SetPinFriends(c *gin.Context) { + a2r.Call(friend.FriendClient.PinFriends, o.Client, c) +} diff --git a/internal/api/route.go b/internal/api/route.go index 7a331d643..8bfea5cca 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -77,6 +77,11 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive userRouterGroup.POST("/subscribe_users_status", ParseToken, u.SubscriberStatus) userRouterGroup.POST("/get_users_status", ParseToken, u.GetUserStatus) userRouterGroup.POST("/get_subscribe_users_status", ParseToken, u.GetSubscribeUsersStatus) + + userRouterGroup.POST("/process_user_command_add", ParseToken, u.ProcessUserCommandAdd) + userRouterGroup.POST("/process_user_command_delete", ParseToken, u.ProcessUserCommandDelete) + userRouterGroup.POST("/process_user_command_update", ParseToken, u.ProcessUserCommandUpdate) + userRouterGroup.POST("/process_user_command_get", ParseToken, u.ProcessUserCommandGet) } // friend routing group friendRouterGroup := r.Group("/friend", ParseToken) @@ -98,6 +103,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive friendRouterGroup.POST("/is_friend", f.IsFriend) friendRouterGroup.POST("/get_friend_id", f.GetFriendIDs) friendRouterGroup.POST("/get_specified_friends_info", f.GetSpecifiedFriendsInfo) + friendRouterGroup.POST("/set_pin_friend", f.SetPinFriends) } g := NewGroupApi(*groupRpc) groupRouterGroup := r.Group("/group", ParseToken) diff --git a/internal/api/user.go b/internal/api/user.go index 86b7c0b0b..8350d1711 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -199,3 +199,23 @@ func (u *UserApi) GetUserStatus(c *gin.Context) { func (u *UserApi) GetSubscribeUsersStatus(c *gin.Context) { a2r.Call(user.UserClient.GetSubscribeUsersStatus, u.Client, c) } + +// ProcessUserCommandAdd user general function add +func (u *UserApi) ProcessUserCommandAdd(c *gin.Context) { + a2r.Call(user.UserClient.ProcessUserCommandAdd, u.Client, c) +} + +// ProcessUserCommandDelete user general function delete +func (u *UserApi) ProcessUserCommandDelete(c *gin.Context) { + a2r.Call(user.UserClient.ProcessUserCommandDelete, u.Client, c) +} + +// ProcessUserCommandUpdate user general function update +func (u *UserApi) ProcessUserCommandUpdate(c *gin.Context) { + a2r.Call(user.UserClient.ProcessUserCommandUpdate, u.Client, c) +} + +// ProcessUserCommandGet user general function get +func (u *UserApi) ProcessUserCommandGet(c *gin.Context) { + a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c) +} diff --git a/internal/rpc/friend/black.go b/internal/rpc/friend/black.go index 54cdbb2cc..ed5791c38 100644 --- a/internal/rpc/friend/black.go +++ b/internal/rpc/friend/black.go @@ -79,6 +79,7 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq) BlockUserID: req.BlackUserID, OperatorUserID: mcontext.GetOpUserID(ctx), CreateTime: time.Now(), + Ex: req.Ex, } if err := s.blackDatabase.Create(ctx, []*relation.BlackModel{&black}); err != nil { return nil, err diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index 20c47ad8f..12203aa7e 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -53,10 +53,6 @@ type friendServer struct { RegisterCenter registry.SvcDiscoveryRegistry } -func (s *friendServer) PinFriends(ctx context.Context, req *pbfriend.PinFriendsReq) (*pbfriend.PinFriendsResp, error) { - return nil, errs.ErrInternalServer.Wrap("not implemented") -} - func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { // Initialize MongoDB mongo, err := unrelation.NewMongo() @@ -411,6 +407,7 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien } var friendInfo *sdkws.FriendInfo if friend := friendMap[userID]; friend != nil { + friendInfo = &sdkws.FriendInfo{ OwnerUserID: friend.OwnerUserID, Remark: friend.Remark, @@ -418,6 +415,7 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien AddSource: friend.AddSource, OperatorUserID: friend.OperatorUserID, Ex: friend.Ex, + IsPinned: friend.IsPinned, } } var blackInfo *sdkws.BlackInfo @@ -438,3 +436,35 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien } return resp, nil } +func (s *friendServer) PinFriends( + ctx context.Context, + req *pbfriend.PinFriendsReq, +) (*pbfriend.PinFriendsResp, error) { + if len(req.FriendUserIDs) == 0 { + return nil, errs.ErrArgs.Wrap("friendIDList is empty") + } + if utils.Duplicate(req.FriendUserIDs) { + return nil, errs.ErrArgs.Wrap("friendIDList repeated") + } + var isPinned bool + if req.IsPinned != nil { + isPinned = req.IsPinned.Value + } else { + return nil, errs.ErrArgs.Wrap("isPinned is nil") + } + //check whther in friend list + _, err := s.friendDatabase.FindFriendsWithError(ctx, req.OwnerUserID, req.FriendUserIDs) + if err != nil { + return nil, err + } + + //set friendslist friend pin status to isPinned + for _, friendID := range req.FriendUserIDs { + if err := s.friendDatabase.UpdateFriendPinStatus(ctx, req.OwnerUserID, friendID, isPinned); err != nil { + return nil, err + } + } + + resp := &pbfriend.PinFriendsResp{} + return resp, nil +} diff --git a/internal/rpc/group/callback.go b/internal/rpc/group/callback.go index 4a89a16fb..8779cb89b 100644 --- a/internal/rpc/group/callback.go +++ b/internal/rpc/group/callback.go @@ -327,8 +327,6 @@ func CallbackBeforeInviteUserToGroup(ctx context.Context, req *group.InviteUserT // Handle the scenario where certain members are refused // You might want to update the req.Members list or handle it as per your business logic } - utils.StructFieldNotNilReplace(req, resp) - return nil } @@ -395,7 +393,10 @@ func CallbackBeforeSetGroupInfo(ctx context.Context, req *group.SetGroupInfoReq) if resp.ApplyMemberFriend != nil { req.GroupInfoForSet.ApplyMemberFriend = wrapperspb.Int32(*resp.ApplyMemberFriend) } - utils.StructFieldNotNilReplace(req, resp) + utils.NotNilReplace(&req.GroupInfoForSet.GroupID, &resp.GroupID) + utils.NotNilReplace(&req.GroupInfoForSet.GroupName, &resp.GroupName) + utils.NotNilReplace(&req.GroupInfoForSet.FaceURL, &resp.FaceURL) + utils.NotNilReplace(&req.GroupInfoForSet.Introduction, &resp.Introduction) return nil } func CallbackAfterSetGroupInfo(ctx context.Context, req *group.SetGroupInfoReq) error { @@ -426,6 +427,5 @@ func CallbackAfterSetGroupInfo(ctx context.Context, req *group.SetGroupInfoReq) if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackAfterSetGroupInfo); err != nil { return err } - utils.StructFieldNotNilReplace(req, resp) return nil } diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index 2c3c6fc43..ba129d7e9 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -802,6 +802,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq) GroupType: string(group.GroupType), ApplyID: req.InviterUserID, ReqMessage: req.ReqMessage, + Ex: req.Ex, } if err = CallbackApplyJoinGroupBefore(ctx, reqCall); err != nil { @@ -848,6 +849,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq) JoinSource: req.JoinSource, ReqTime: time.Now(), HandledTime: time.Unix(0, 0), + Ex: req.Ex, } if err := s.db.CreateGroupRequest(ctx, []*relationtb.GroupRequestModel{&groupRequest}); err != nil { return nil, err diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go index 0bd71d9f7..3a8587ea3 100644 --- a/internal/rpc/msg/callback.go +++ b/internal/rpc/msg/callback.go @@ -202,6 +202,5 @@ func CallbackAfterRevokeMsg(ctx context.Context, req *pbchat.RevokeMsgReq) error if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackAfterRevokeMsg); err != nil { return err } - utils.StructFieldNotNilReplace(req, resp) return nil } diff --git a/internal/rpc/third/third.go b/internal/rpc/third/third.go index 7a63d3526..35df3f925 100644 --- a/internal/rpc/third/third.go +++ b/internal/rpc/third/third.go @@ -101,6 +101,16 @@ type thirdServer struct { defaultExpire time.Duration } +func (t *thirdServer) InitiateFormData(ctx context.Context, req *third.InitiateFormDataReq) (*third.InitiateFormDataResp, error) { + //TODO implement me + panic("implement me") +} + +func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.CompleteFormDataReq) (*third.CompleteFormDataResp, error) { + //TODO implement me + panic("implement me") +} + func (t *thirdServer) FcmUpdateToken(ctx context.Context, req *third.FcmUpdateTokenReq) (resp *third.FcmUpdateTokenResp, err error) { err = t.thirdDatabase.FcmUpdateToken(ctx, req.Account, int(req.PlatformID), req.FcmToken, req.ExpireTime) if err != nil { diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index a2fa14c7a..70e3aebe6 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -56,22 +56,6 @@ type userServer struct { RegisterCenter registry.SvcDiscoveryRegistry } -func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) { - return nil, errs.ErrInternalServer.Wrap("not implemented") -} - -func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) { - return nil, errs.ErrInternalServer.Wrap("not implemented") -} - -func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) { - return nil, errs.ErrInternalServer.Wrap("not implemented") -} - -func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) { - return nil, errs.ErrInternalServer.Wrap("not implemented") -} - func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { rdb, err := cache.NewRedis() if err != nil { @@ -350,3 +334,59 @@ func (s *userServer) GetSubscribeUsersStatus(ctx context.Context, } return &pbuser.GetSubscribeUsersStatusResp{StatusList: onlineStatusList}, nil } + +// ProcessUserCommandAdd user general function add +func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) { + // Assuming you have a method in s.UserDatabase to add a user command + err := s.UserDatabase.AddUserCommand(ctx, req.UserID, req.Type, req.Uuid, req.Value) + if err != nil { + return nil, err + } + + return &pbuser.ProcessUserCommandAddResp{}, nil +} + +// ProcessUserCommandDelete user general function delete +func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) { + // Assuming you have a method in s.UserDatabase to delete a user command + err := s.UserDatabase.DeleteUserCommand(ctx, req.UserID, req.Type, req.Uuid) + if err != nil { + return nil, err + } + + return &pbuser.ProcessUserCommandDeleteResp{}, nil +} + +// ProcessUserCommandUpdate user general function update +func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) { + // Assuming you have a method in s.UserDatabase to update a user command + err := s.UserDatabase.UpdateUserCommand(ctx, req.UserID, req.Type, req.Uuid, req.Value) + if err != nil { + return nil, err + } + + return &pbuser.ProcessUserCommandUpdateResp{}, nil +} + +func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) { + // Fetch user commands from the database + commands, err := s.UserDatabase.GetUserCommands(ctx, req.UserID, req.Type) + if err != nil { + return nil, err + } + + // Initialize commandInfoSlice as an empty slice + commandInfoSlice := make([]*pbuser.CommandInfoResp, 0, len(commands)) + + for _, command := range commands { + // No need to use index since command is already a pointer + commandInfoSlice = append(commandInfoSlice, &pbuser.CommandInfoResp{ + Uuid: command.Uuid, + Value: command.Value, + CreateTime: command.CreateTime, + }) + } + + // Return the response with the slice + return &pbuser.ProcessUserCommandGetResp{KVArray: commandInfoSlice}, nil +} diff --git a/pkg/callbackstruct/group.go b/pkg/callbackstruct/group.go index 899b4312f..5968f1e55 100644 --- a/pkg/callbackstruct/group.go +++ b/pkg/callbackstruct/group.go @@ -148,6 +148,7 @@ type CallbackJoinGroupReq struct { GroupType string `json:"groupType"` ApplyID string `json:"applyID"` ReqMessage string `json:"reqMessage"` + Ex string `json:"ex"` } type CallbackJoinGroupResp struct { diff --git a/pkg/common/convert/friend.go b/pkg/common/convert/friend.go index c81cd98d6..62ce6f95b 100644 --- a/pkg/common/convert/friend.go +++ b/pkg/common/convert/friend.go @@ -17,7 +17,6 @@ package convert import ( "context" "fmt" - "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/utils" @@ -62,6 +61,7 @@ func FriendsDB2Pb( for _, friendDB := range friendsDB { userID = append(userID, friendDB.FriendUserID) } + users, err := getUsers(ctx, userID) if err != nil { return nil, err @@ -74,6 +74,7 @@ func FriendsDB2Pb( friendPb.FriendUser.FaceURL = users[friend.FriendUserID].FaceURL friendPb.FriendUser.Ex = users[friend.FriendUserID].Ex friendPb.CreateTime = friend.CreateTime.Unix() + friendPb.IsPinned = friend.IsPinned friendsPb = append(friendsPb, friendPb) } return friendsPb, nil diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go index 8d960546a..72041a790 100644 --- a/pkg/common/convert/user.go +++ b/pkg/common/convert/user.go @@ -64,7 +64,7 @@ func UserPb2DBMap(user *sdkws.UserInfo) map[string]any { "global_recv_msg_opt": user.GlobalRecvMsgOpt, } for key, value := range fields { - if v, ok := value.(string); ok && v != "" { + if v, ok := value.(string); ok { val[key] = v } else if v, ok := value.(int32); ok && v != 0 { val[key] = v diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go index 29b2ef9b1..34ce22295 100644 --- a/pkg/common/db/controller/friend.go +++ b/pkg/common/db/controller/friend.go @@ -58,6 +58,7 @@ type FriendDatabase interface { FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error) FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) + UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) } type friendDatabase struct { @@ -298,3 +299,9 @@ func (f *friendDatabase) FindFriendUserIDs(ctx context.Context, ownerUserID stri func (f *friendDatabase) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) { return f.friendRequest.FindBothFriendRequests(ctx, fromUserID, toUserID) } +func (f *friendDatabase) UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) { + if err := f.friend.UpdatePinStatus(ctx, ownerUserID, friendUserID, isPinned); err != nil { + return err + } + return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx) +} diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go index ca703b729..433fb7ad3 100644 --- a/pkg/common/db/controller/user.go +++ b/pkg/common/db/controller/user.go @@ -68,6 +68,12 @@ type UserDatabase interface { GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error) // SetUserStatus Set the user status and store the user status in redis SetUserStatus(ctx context.Context, userID string, status, platformID int32) error + + //CRUD user command + AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error + DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error + UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error + GetUserCommands(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) } type userDatabase struct { @@ -227,3 +233,16 @@ func (u *userDatabase) GetUserStatus(ctx context.Context, userIDs []string) ([]* func (u *userDatabase) SetUserStatus(ctx context.Context, userID string, status, platformID int32) error { return u.cache.SetUserStatus(ctx, userID, status, platformID) } +func (u *userDatabase) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error { + return u.userDB.AddUserCommand(ctx, userID, Type, UUID, value) +} +func (u *userDatabase) DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error { + return u.userDB.DeleteUserCommand(ctx, userID, Type, UUID) +} +func (u *userDatabase) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error { + return u.userDB.UpdateUserCommand(ctx, userID, Type, UUID, value) +} +func (u *userDatabase) GetUserCommands(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) { + commands, err := u.userDB.GetUserCommand(ctx, userID, Type) + return commands, err +} diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go index 8f3528d91..667098819 100644 --- a/pkg/common/db/mgo/friend.go +++ b/pkg/common/db/mgo/friend.go @@ -16,7 +16,7 @@ package mgo import ( "context" - + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" "go.mongodb.org/mongo-driver/mongo/options" @@ -143,3 +143,20 @@ func (f *FriendMgo) FindFriendUserIDs(ctx context.Context, ownerUserID string) ( filter := bson.M{"owner_user_id": ownerUserID} return mgoutil.Find[string](ctx, f.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "friend_user_id": 1})) } + +// UpdatePinStatus update friend's pin status +func (f *FriendMgo) UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) { + + filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID} + // Create an update operation to set the "is_pinned" field to isPinned for all documents. + update := bson.M{"$set": bson.M{"is_pinned": isPinned}} + + // Perform the update operation for all documents in the collection. + _, err = f.coll.UpdateMany(ctx, filter, update) + + if err != nil { + return errs.Wrap(err, "update pin error") + } + + return nil +} diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go index 37e354cbb..268d69ce3 100644 --- a/pkg/common/db/mgo/user.go +++ b/pkg/common/db/mgo/user.go @@ -16,6 +16,7 @@ package mgo import ( "context" + "github.com/OpenIMSDK/protocol/user" "time" "github.com/OpenIMSDK/tools/mgoutil" @@ -87,6 +88,78 @@ func (u *UserMgo) CountTotal(ctx context.Context, before *time.Time) (count int6 return mgoutil.Count(ctx, u.coll, bson.M{"create_time": bson.M{"$lt": before}}) } +func (u *UserMgo) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error { + collection := u.coll.Database().Collection("userCommands") + + // Create a new document instead of updating an existing one + doc := bson.M{ + "userID": userID, + "type": Type, + "uuid": UUID, + "createTime": time.Now().Unix(), // assuming you want the creation time in Unix timestamp + "value": value, + } + + _, err := collection.InsertOne(ctx, doc) + return err +} +func (u *UserMgo) DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error { + collection := u.coll.Database().Collection("userCommands") + + filter := bson.M{"userID": userID, "type": Type, "uuid": UUID} + + _, err := collection.DeleteOne(ctx, filter) + return err +} +func (u *UserMgo) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error { + collection := u.coll.Database().Collection("userCommands") + + filter := bson.M{"userID": userID, "type": Type, "uuid": UUID} + update := bson.M{"$set": bson.M{"value": value}} + + _, err := collection.UpdateOne(ctx, filter, update) + return err +} +func (u *UserMgo) GetUserCommand(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) { + collection := u.coll.Database().Collection("userCommands") + filter := bson.M{"userID": userID, "type": Type} + + cursor, err := collection.Find(ctx, filter) + if err != nil { + return nil, err + } + defer cursor.Close(ctx) + + // Initialize commands as a slice of pointers + commands := []*user.CommandInfoResp{} + + for cursor.Next(ctx) { + var document struct { + UUID string `bson:"uuid"` + Value string `bson:"value"` + CreateTime int64 `bson:"createTime"` + } + + if err := cursor.Decode(&document); err != nil { + return nil, err + } + + commandInfo := &user.CommandInfoResp{ // Change here: use a pointer to the struct + Uuid: document.UUID, + Value: document.Value, + CreateTime: document.CreateTime, + } + + commands = append(commands, commandInfo) + } + + if err := cursor.Err(); err != nil { + return nil, err + } + + return commands, nil +} + func (u *UserMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) { pipeline := bson.A{ bson.M{ diff --git a/pkg/common/db/table/relation/friend.go b/pkg/common/db/table/relation/friend.go index 75dbea850..4f85998f4 100644 --- a/pkg/common/db/table/relation/friend.go +++ b/pkg/common/db/table/relation/friend.go @@ -30,6 +30,7 @@ type FriendModel struct { AddSource int32 `bson:"add_source"` OperatorUserID string `bson:"operator_user_id"` Ex string `bson:"ex"` + IsPinned bool `bson:"is_pinned"` } // FriendModelInterface defines the operations for managing friends in MongoDB. @@ -56,4 +57,6 @@ type FriendModelInterface interface { FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error) // FindFriendUserIDs retrieves a list of friend user IDs for a given owner. FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) + // UpdatePinStatus update friend's pin status + UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) } diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go index 1f26d751f..213a6b774 100644 --- a/pkg/common/db/table/relation/user.go +++ b/pkg/common/db/table/relation/user.go @@ -16,6 +16,7 @@ package relation import ( "context" + "github.com/OpenIMSDK/protocol/user" "time" "github.com/OpenIMSDK/tools/pagination" @@ -60,4 +61,9 @@ type UserModelInterface interface { CountTotal(ctx context.Context, before *time.Time) (count int64, err error) // 获取范围内用户增量 CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) + //CRUD user command + AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error + DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error + UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error + GetUserCommand(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) } diff --git a/pkg/common/http/http_client.go b/pkg/common/http/http_client.go index e1bc83d38..baad60459 100644 --- a/pkg/common/http/http_client.go +++ b/pkg/common/http/http_client.go @@ -127,7 +127,7 @@ func callBackPostReturn(ctx context.Context, url, command string, input interfac log.ZWarn(ctx, "callback failed but continue", err, "url", url) return nil } - return errs.ErrData.Wrap(err.Error()) + return errs.ErrData.WithDetail(err.Error() + "response format error") } return output.Parse() diff --git a/scripts/install/test.sh b/scripts/install/test.sh index 049dc19c8..93a39f298 100755 --- a/scripts/install/test.sh +++ b/scripts/install/test.sh @@ -70,14 +70,16 @@ function openim::test::auth() { #################################### Auth Module #################################### -# Define a function to get a token (Admin Token) +# Define a function to get a token for a specific user openim::test::get_token() { + local user_id="${1:-openIM123456}" # Default user ID if not provided token_response=$(${CCURL} "${OperationID}" "${Header}" ${INSECURE_OPENIMAPI}/auth/user_token \ - -d'{"secret": "'"$SECRET"'","platformID": 1,"userID": "openIM123456"}') + -d'{"secret": "'"$SECRET"'","platformID": 1,"userID": "'$user_id'"}') token=$(echo $token_response | grep -Po 'token[" :]+\K[^"]+') echo "$token" } + Header="-HContent-Type: application/json" OperationID="-HoperationID: 1646445464564" Token="-Htoken: $(openim::test::get_token)" @@ -530,6 +532,36 @@ EOF openim::test::check_error "$response" } +# Updates the pin status of multiple friends. +openim::test::update_pin_status() { + local ownerUserID="${1}" + shift # Shift the arguments to skip the first one (ownerUserID) + local isPinned="${1}" + shift # Shift the arguments to skip the isPinned argument + + # Constructing the list of friendUserIDs + local friendUserIDsArray=() + for friendUserID in "$@"; do + friendUserIDsArray+=("\"${friendUserID}\"") + done + local friendUserIDs=$(IFS=,; echo "${friendUserIDsArray[*]}") + + local request_body=$(cat < Date: Wed, 20 Dec 2023 10:22:55 +0800 Subject: [PATCH 11/31] fix: fix the output format (#1585) * fix: update the component output format * fix: fix the successful tiops * fix: update the error format --- tools/component/component.go | 72 +++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/tools/component/component.go b/tools/component/component.go index 7150c91af..28ea7a2fe 100644 --- a/tools/component/component.go +++ b/tools/component/component.go @@ -72,7 +72,7 @@ func initCfg() error { type checkFunc struct { name string - function func() error + function func() (string, error) } func main() { @@ -101,13 +101,13 @@ func main() { allSuccess := true for _, check := range checks { - err := check.function() + str, err := check.function() if err != nil { - errorPrint(fmt.Sprintf("Starting %s failed: %v", check.name, err)) + errorPrint(fmt.Sprintf("Starting %s failed, %v", check.name, err)) allSuccess = false break } else { - successPrint(fmt.Sprintf("%s starts successfully", check.name)) + successPrint(fmt.Sprintf("%s connected successfully, %s", check.name, str)) } } @@ -142,21 +142,22 @@ func getEnv(key, fallback string) string { } // checkMongo checks the MongoDB connection -func checkMongo() error { +func checkMongo() (string, error) { // Use environment variables or fallback to config uri := getEnv("MONGO_URI", buildMongoURI()) client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri)) + str := "ths addr is:" + strings.Join(config.Config.Mongo.Address, ",") if err != nil { - return errs.Wrap(err) + return "", errs.Wrap(errStr(err, str)) } defer client.Disconnect(context.TODO()) if err = client.Ping(context.TODO(), nil); err != nil { - return errs.Wrap(err) + return "", errs.Wrap(errStr(err, str)) } - return nil + return str, nil } // buildMongoURI constructs the MongoDB URI using configuration settings @@ -178,10 +179,10 @@ func buildMongoURI() string { } // checkMinio checks the MinIO connection -func checkMinio() error { +func checkMinio() (string, error) { // Check if MinIO is enabled if config.Config.Object.Enable != "minio" { - return nil + return "", nil } // Prioritize environment variables @@ -191,13 +192,14 @@ func checkMinio() error { useSSL := getEnv("MINIO_USE_SSL", "false") // Assuming SSL is not used by default if endpoint == "" || accessKeyID == "" || secretAccessKey == "" { - return ErrConfig.Wrap("MinIO configuration missing") + return "", ErrConfig.Wrap("MinIO configuration missing") } // Parse endpoint URL to determine if SSL is enabled u, err := url.Parse(endpoint) if err != nil { - return errs.Wrap(err) + str := "the endpoint is:" + endpoint + return "", errs.Wrap(errStr(err, str)) } secure := u.Scheme == "https" || useSSL == "true" @@ -206,31 +208,34 @@ func checkMinio() error { Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""), Secure: secure, }) + str := "ths addr is:" + u.Host if err != nil { - return errs.Wrap(err) + strs := fmt.Sprintf("%v;host:%s,accessKeyID:%s,secretAccessKey:%s,Secure:%v", err, u.Host, accessKeyID, secretAccessKey, secure) + return "", errs.Wrap(err, strs) } // Perform health check cancel, err := minioClient.HealthCheck(time.Duration(minioHealthCheckDuration) * time.Second) if err != nil { - return errs.Wrap(err) + return "", errs.Wrap(errStr(err, str)) } defer cancel() if minioClient.IsOffline() { - return ErrComponentStart.Wrap("Minio server is offline") + str := fmt.Sprintf("Minio server is offline;%s", str) + return "", ErrComponentStart.Wrap(str) } // Check for localhost in API URL and Minio SignEndpoint if exactIP(config.Config.Object.ApiURL) == "127.0.0.1" || exactIP(config.Config.Object.Minio.SignEndpoint) == "127.0.0.1" { - return ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1") + return "", ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1") } - return nil + return str, nil } // checkRedis checks the Redis connection -func checkRedis() error { +func checkRedis() (string, error) { // Prioritize environment variables address := getEnv("REDIS_ADDRESS", strings.Join(config.Config.Redis.Address, ",")) username := getEnv("REDIS_USERNAME", config.Config.Redis.Username) @@ -259,15 +264,16 @@ func checkRedis() error { // Ping Redis to check connectivity _, err := redisClient.Ping(context.Background()).Result() + str := "the addr is:" + strings.Join(redisAddresses, ",") if err != nil { - return errs.Wrap(err) + return "", errs.Wrap(errStr(err, str)) } - return nil + return str, nil } // checkZookeeper checks the Zookeeper connection -func checkZookeeper() error { +func checkZookeeper() (string, error) { // Prioritize environment variables schema := getEnv("ZOOKEEPER_SCHEMA", "digest") address := getEnv("ZOOKEEPER_ADDRESS", strings.Join(config.Config.Zookeeper.ZkAddr, ",")) @@ -278,30 +284,31 @@ func checkZookeeper() error { zookeeperAddresses := strings.Split(address, ",") // Connect to Zookeeper + str := "the addr is:" + address c, _, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary if err != nil { - return errs.Wrap(err) + return "", errs.Wrap(errStr(err, str)) } defer c.Close() // Set authentication if username and password are provided if username != "" && password != "" { if err := c.AddAuth(schema, []byte(username+":"+password)); err != nil { - return errs.Wrap(err) + return "", errs.Wrap(errStr(err, str)) } } // Check if Zookeeper is reachable _, _, err = c.Get("/") if err != nil { - return errs.Wrap(err) + return "", errs.Wrap(err, str) } - return nil + return str, nil } // checkKafka checks the Kafka connection -func checkKafka() error { +func checkKafka() (string, error) { // Prioritize environment variables username := getEnv("KAFKA_USERNAME", config.Config.Kafka.Username) password := getEnv("KAFKA_PASSWORD", config.Config.Kafka.Password) @@ -321,16 +328,17 @@ func checkKafka() error { // kafka.SetupTLSConfig(cfg) // Create Kafka client + str := "the addr is:" + address kafkaClient, err := sarama.NewClient(kafkaAddresses, cfg) if err != nil { - return errs.Wrap(err) + return "", errs.Wrap(errStr(err, str)) } defer kafkaClient.Close() // Verify if necessary topics exist topics, err := kafkaClient.Topics() if err != nil { - return errs.Wrap(err) + return "", errs.Wrap(err) } requiredTopics := []string{ @@ -341,11 +349,11 @@ func checkKafka() error { for _, requiredTopic := range requiredTopics { if !isTopicPresent(requiredTopic, topics) { - return ErrComponentStart.Wrap(fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic)) + return "", ErrComponentStart.Wrap(fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic)) } } - return nil + return str, nil } // isTopicPresent checks if a topic is present in the list of topics @@ -373,3 +381,7 @@ func successPrint(s string) { func warningPrint(s string) { colorPrint(colorYellow, "Warning: But %v", s) } + +func errStr(err error, str string) error { + return fmt.Errorf("%v;%s", err, str) +} From 34ed032af13e9743c8bf2b97695ba1d0d0692a54 Mon Sep 17 00:00:00 2001 From: xuexihuang <1339326187@qq.com> Date: Mon, 25 Dec 2023 15:32:07 +0800 Subject: [PATCH 12/31] K8s environment supports multiple msggateway by consistent hash (#1600) * feature:support multi msggateway * feature:support multi msggateway * feature:support multi msggateway by hash method * fix:fix log * change to consistent hash * change go.mod * fix:fix go routine values error * fix:fix push filter logic * fix:fix push filter logic --------- Co-authored-by: lin.huang --- go.mod | 8 +- go.sum | 12 +- internal/msggateway/n_ws_server.go | 13 +- internal/push/push_to_client.go | 139 +++++++++++++++--- .../kubernetes/kubernetes.go | 90 ++++++------ 5 files changed, 178 insertions(+), 84 deletions(-) diff --git a/go.mod b/go.mod index c8dd96689..9a9cde30e 100644 --- a/go.mod +++ b/go.mod @@ -34,10 +34,11 @@ require github.com/google/uuid v1.3.1 require ( github.com/IBM/sarama v1.41.3 github.com/OpenIMSDK/protocol v0.0.36 - github.com/OpenIMSDK/tools v0.0.20 + github.com/OpenIMSDK/tools v0.0.21 github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible github.com/go-redis/redis v6.15.9+incompatible github.com/redis/go-redis/v9 v9.2.1 + github.com/stathat/consistent v1.0.0 github.com/tencentyun/cos-go-sdk-v5 v0.7.45 go.uber.org/automaxprocs v1.5.3 golang.org/x/sync v0.4.0 @@ -141,6 +142,7 @@ require ( gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gorm.io/gorm v1.23.8 // indirect + stathat.com/c/consistent v1.0.0 // indirect ) require ( @@ -154,7 +156,3 @@ require ( golang.org/x/crypto v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) -//replace ( -// github.com/OpenIMSDK/protocol v0.0.34 => github.com/AndrewZuo01/protocol v0.0.0-20231218034338-b8d838e0b182 -//) - diff --git a/go.sum b/go.sum index 30e4b3cb4..61323c57b 100644 --- a/go.sum +++ b/go.sum @@ -18,10 +18,10 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= -github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE= -github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= -github.com/OpenIMSDK/tools v0.0.20 h1:zBTjQZRJ5lR1FIzP9mtWyAvh5dKsmJXQugi4p8X/97k= -github.com/OpenIMSDK/tools v0.0.20/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= +github.com/OpenIMSDK/protocol v0.0.36 h1:UJnFsr1A4RrNeHMNDVS/1nvXWFoGM43dcXpZeJiIZ+0= +github.com/OpenIMSDK/protocol v0.0.36/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= +github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48= +github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= @@ -308,6 +308,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/stathat/consistent v1.0.0 h1:ZFJ1QTRn8npNBKW065raSZ8xfOqhpb8vLOkfp4CcL/U= +github.com/stathat/consistent v1.0.0/go.mod h1:uajTPbgSygZBJ+V+0mY7meZ8i0XAcZs7AQ6V121XSxw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -536,3 +538,5 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +stathat.com/c/consistent v1.0.0 h1:ezyc51EGcRPJUxfHGSgJjWzJdj3NiMU9pNfLNGiXV0c= +stathat.com/c/consistent v1.0.0/go.mod h1:QkzMWzcbB+yQBL2AttO6sgsQS/JSTapcDISJalmCDS0= diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go index 737d5db14..70c2f8fe0 100644 --- a/internal/msggateway/n_ws_server.go +++ b/internal/msggateway/n_ws_server.go @@ -288,12 +288,13 @@ func (ws *WsServer) registerClient(client *Client) { } wg := sync.WaitGroup{} - wg.Add(1) - go func() { - defer wg.Done() - _ = ws.sendUserOnlineInfoToOtherNode(client.ctx, client) - }() - + if config.Config.Envs.Discovery == "zookeeper" { + wg.Add(1) + go func() { + defer wg.Done() + _ = ws.sendUserOnlineInfoToOtherNode(client.ctx, client) + }() + } wg.Add(1) go func() { defer wg.Done() diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go index 2ee8c457f..12b78ea2d 100644 --- a/internal/push/push_to_client.go +++ b/internal/push/push_to_client.go @@ -18,6 +18,7 @@ import ( "context" "encoding/json" "errors" + "google.golang.org/grpc" "sync" "golang.org/x/sync/errgroup" @@ -142,6 +143,47 @@ func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t any) error { return json.Unmarshal([]byte(notification.Detail), t) } +/* +k8s deployment,offline push group messages function +*/ +func (p *Pusher) k8sOfflinePush2SuperGroup(ctx context.Context, groupID string, msg *sdkws.MsgData, wsResults []*msggateway.SingleMsgToUserResults) error { + + var needOfflinePushUserIDs []string + for _, v := range wsResults { + if !v.OnlinePush { + needOfflinePushUserIDs = append(needOfflinePushUserIDs, v.UserID) + } + } + if len(needOfflinePushUserIDs) > 0 { + var offlinePushUserIDs []string + err := callbackOfflinePush(ctx, needOfflinePushUserIDs, msg, &offlinePushUserIDs) + if err != nil { + return err + } + + if len(offlinePushUserIDs) > 0 { + needOfflinePushUserIDs = offlinePushUserIDs + } + if msg.ContentType != constant.SignalingNotification { + resp, err := p.conversationRpcClient.Client.GetConversationOfflinePushUserIDs( + ctx, + &conversation.GetConversationOfflinePushUserIDsReq{ConversationID: utils.GenGroupConversationID(groupID), UserIDs: needOfflinePushUserIDs}, + ) + if err != nil { + return err + } + if len(resp.UserIDs) > 0 { + err = p.offlinePushMsg(ctx, groupID, msg, resp.UserIDs) + if err != nil { + log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg) + return err + } + } + } + + } + return nil +} func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws.MsgData) (err error) { log.ZDebug(ctx, "Get super group msg from msg_transfer and push msg", "msg", msg.String(), "groupID", groupID) var pushToUserIDs []string @@ -205,7 +247,10 @@ func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws log.ZDebug(ctx, "get conn and online push success", "result", wsResults, "msg", msg) isOfflinePush := utils.GetSwitchFromOptions(msg.Options, constant.IsOfflinePush) - if isOfflinePush { + if isOfflinePush && config.Config.Envs.Discovery == "k8s" { + return p.k8sOfflinePush2SuperGroup(ctx, groupID, msg, wsResults) + } + if isOfflinePush && config.Config.Envs.Discovery == "zookeeper" { var ( onlineSuccessUserIDs = []string{msg.SendID} webAndPcBackgroundUserIDs []string @@ -239,14 +284,7 @@ func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws } needOfflinePushUserIDs := utils.DifferenceString(onlineSuccessUserIDs, pushToUserIDs) - if msg.ContentType != constant.SignalingNotification { - notNotificationUserIDs, err := p.conversationLocalCache.GetRecvMsgNotNotifyUserIDs(ctx, groupID) - if err != nil { - return err - } - needOfflinePushUserIDs = utils.SliceSub(needOfflinePushUserIDs, notNotificationUserIDs) - } // Use offline push messaging if len(needOfflinePushUserIDs) > 0 { var offlinePushUserIDs []string @@ -258,30 +296,89 @@ func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws if len(offlinePushUserIDs) > 0 { needOfflinePushUserIDs = offlinePushUserIDs } - resp, err := p.conversationRpcClient.Client.GetConversationOfflinePushUserIDs( - ctx, - &conversation.GetConversationOfflinePushUserIDsReq{ConversationID: utils.GenGroupConversationID(groupID), UserIDs: needOfflinePushUserIDs}, - ) - if err != nil { - return err - } - if len(resp.UserIDs) > 0 { - err = p.offlinePushMsg(ctx, groupID, msg, resp.UserIDs) + if msg.ContentType != constant.SignalingNotification { + resp, err := p.conversationRpcClient.Client.GetConversationOfflinePushUserIDs( + ctx, + &conversation.GetConversationOfflinePushUserIDsReq{ConversationID: utils.GenGroupConversationID(groupID), UserIDs: needOfflinePushUserIDs}, + ) if err != nil { - log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg) return err } - if _, err := p.GetConnsAndOnlinePush(ctx, msg, utils.IntersectString(resp.UserIDs, webAndPcBackgroundUserIDs)); err != nil { - log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg, "userIDs", utils.IntersectString(needOfflinePushUserIDs, webAndPcBackgroundUserIDs)) - return err + if len(resp.UserIDs) > 0 { + err = p.offlinePushMsg(ctx, groupID, msg, resp.UserIDs) + if err != nil { + log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg) + return err + } + if _, err := p.GetConnsAndOnlinePush(ctx, msg, utils.IntersectString(resp.UserIDs, webAndPcBackgroundUserIDs)); err != nil { + log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg, "userIDs", utils.IntersectString(needOfflinePushUserIDs, webAndPcBackgroundUserIDs)) + return err + } } } + } } return nil } +func (p *Pusher) k8sOnlinePush(ctx context.Context, msg *sdkws.MsgData, pushToUserIDs []string) (wsResults []*msggateway.SingleMsgToUserResults, err error) { + var usersHost = make(map[string][]string) + for _, v := range pushToUserIDs { + tHost, err := p.discov.GetUserIdHashGatewayHost(ctx, v) + if err != nil { + log.ZError(ctx, "get msggateway hash error", err) + return nil, err + } + tUsers, tbl := usersHost[tHost] + if tbl { + tUsers = append(tUsers, v) + usersHost[tHost] = tUsers + } else { + usersHost[tHost] = []string{v} + } + } + log.ZDebug(ctx, "genUsers send hosts struct:", "usersHost", usersHost) + var usersConns = make(map[*grpc.ClientConn][]string) + for host, userIds := range usersHost { + tconn, _ := p.discov.GetConn(ctx, host) + usersConns[tconn] = userIds + } + var ( + mu sync.Mutex + wg = errgroup.Group{} + maxWorkers = config.Config.Push.MaxConcurrentWorkers + ) + if maxWorkers < 3 { + maxWorkers = 3 + } + wg.SetLimit(maxWorkers) + for conn, userIds := range usersConns { + tcon := conn + tuserIds := userIds + wg.Go(func() error { + input := &msggateway.OnlineBatchPushOneMsgReq{MsgData: msg, PushToUserIDs: tuserIds} + msgClient := msggateway.NewMsgGatewayClient(tcon) + reply, err := msgClient.SuperGroupOnlineBatchPushOneMsg(ctx, input) + if err != nil { + return nil + } + log.ZDebug(ctx, "push result", "reply", reply) + if reply != nil && reply.SinglePushResult != nil { + mu.Lock() + wsResults = append(wsResults, reply.SinglePushResult...) + mu.Unlock() + } + return nil + }) + } + _ = wg.Wait() + return wsResults, nil +} func (p *Pusher) GetConnsAndOnlinePush(ctx context.Context, msg *sdkws.MsgData, pushToUserIDs []string) (wsResults []*msggateway.SingleMsgToUserResults, err error) { + if config.Config.Envs.Discovery == "k8s" { + return p.k8sOnlinePush(ctx, msg, pushToUserIDs) + } conns, err := p.discov.GetConns(ctx, config.Config.RpcRegisterName.OpenImMessageGatewayName) log.ZDebug(ctx, "get gateway conn", "conn length", len(conns)) if err != nil { diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go index cd5fb0a36..2ff1539e6 100644 --- a/pkg/common/discoveryregister/kubernetes/kubernetes.go +++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go @@ -18,6 +18,7 @@ import ( "context" "errors" "fmt" + "github.com/stathat/consistent" "os" "strconv" "strings" @@ -31,51 +32,54 @@ import ( // K8sDR represents the Kubernetes service discovery and registration client. type K8sDR struct { - options []grpc.DialOption - rpcRegisterAddr string + options []grpc.DialOption + rpcRegisterAddr string + gatewayHostConsistent *consistent.Consistent } -// NewK8sDiscoveryRegister creates a new instance of K8sDR for Kubernetes service discovery and registration. func NewK8sDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) { - - return &K8sDR{}, nil + gatewayConsistent := consistent.New() + gatewayHosts := getMsgGatewayHost(context.Background()) + for _, v := range gatewayHosts { + gatewayConsistent.Add(v) + } + return &K8sDR{gatewayHostConsistent: gatewayConsistent}, nil } -// Register registers a service with Kubernetes. func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.DialOption) error { if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { cli.rpcRegisterAddr = serviceName } else { - cli.rpcRegisterAddr = cli.getSelfHost(context.Background()) + cli.rpcRegisterAddr = getSelfHost(context.Background()) } return nil } - -// UnRegister removes a service registration from Kubernetes. func (cli *K8sDR) UnRegister() error { return nil } - -// CreateRpcRootNodes creates root nodes for RPC in Kubernetes. func (cli *K8sDR) CreateRpcRootNodes(serviceNames []string) error { return nil } - -// RegisterConf2Registry registers a configuration to the registry. func (cli *K8sDR) RegisterConf2Registry(key string, conf []byte) error { return nil } -// GetConfFromRegistry retrieves a configuration from the registry. func (cli *K8sDR) GetConfFromRegistry(key string) ([]byte, error) { + return nil, nil } - -func (cli *K8sDR) getSelfHost(ctx context.Context) string { +func (cli *K8sDR) GetUserIdHashGatewayHost(ctx context.Context, userId string) (string, error) { + host, err := cli.gatewayHostConsistent.Get(userId) + if err != nil { + log.ZError(ctx, "GetUserIdHashGatewayHost error", err) + } + return host, err +} +func getSelfHost(ctx context.Context) string { port := 88 instance := "openimserver" selfPodName := os.Getenv("MY_POD_NAME") @@ -95,26 +99,8 @@ func (cli *K8sDR) getSelfHost(ctx context.Context) string { return host } -// GetConns returns a list of gRPC client connections for a given service. -func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { - if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { - conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) - return []*grpc.ClientConn{conn}, err - } - var ret []*grpc.ClientConn - gatewayHosts := cli.getMsgGatewayHost(ctx) - for _, host := range gatewayHosts { - conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...) - if err != nil { - return nil, err - } - ret = append(ret, conn) - } - return ret, nil -} - // like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88 -func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string { +func getMsgGatewayHost(ctx context.Context) []string { port := 88 instance := "openimserver" selfPodName := os.Getenv("MY_POD_NAME") @@ -135,40 +121,48 @@ func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string { ret = append(ret, host) } log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret) - return ret } +func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { -// GetConn returns a single gRPC client connection for a given service. + if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { + conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) + return []*grpc.ClientConn{conn}, err + } else { + var ret []*grpc.ClientConn + gatewayHosts := getMsgGatewayHost(ctx) + for _, host := range gatewayHosts { + conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...) + if err != nil { + return nil, err + } else { + ret = append(ret, conn) + } + } + return ret, nil + } +} func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + return grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) } -// GetSelfConnTarget returns the connection target of the client itself. func (cli *K8sDR) GetSelfConnTarget() string { + return cli.rpcRegisterAddr } - -// AddOption adds gRPC dial options to the client. func (cli *K8sDR) AddOption(opts ...grpc.DialOption) { cli.options = append(cli.options, opts...) } - -// CloseConn closes a given gRPC client connection. func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) { conn.Close() } -// do not use this method for call rpc. +// do not use this method for call rpc func (cli *K8sDR) GetClientLocalConns() map[string][]*grpc.ClientConn { fmt.Println("should not call this function!!!!!!!!!!!!!!!!!!!!!!!!!") - return nil } - -// Close closes the K8sDR client. func (cli *K8sDR) Close() { - - // Close any open resources here (if applicable) return } From f10528010b9bad2ac32f833a8abe93f2b33a8f07 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Mon, 25 Dec 2023 16:26:59 +0800 Subject: [PATCH 13/31] Update check-all.sh (#1591) --- scripts/check-all.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/check-all.sh b/scripts/check-all.sh index a438ac26b..efaa2ccb7 100755 --- a/scripts/check-all.sh +++ b/scripts/check-all.sh @@ -33,15 +33,15 @@ openim::log::info "\n# Begin to check all openim service" # OpenIM status # Elegant printing function print_services_and_ports() { - local -n service_names=$1 - local -n service_ports=$2 + service_names=("$1[@]") + service_ports=("$2[@]") echo "+-------------------------+----------+" echo "| Service Name | Port |" echo "+-------------------------+----------+" - for index in "${!service_names[@]}"; do - printf "| %-23s | %-8s |\n" "${service_names[$index]}" "${service_ports[$index]}" + for index in "${!service_names}"; do + printf "| %-23s | %-8s |\n" "${!service_names[$index]}" "${!service_ports[$index]}" done echo "+-------------------------+----------+" From 11a147792d7a8bd0e9d14933c64d60bcdb4da1da Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Mon, 25 Dec 2023 16:28:42 +0800 Subject: [PATCH 14/31] Update prometheus.yml (#1586) --- deployments/templates/prometheus.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/deployments/templates/prometheus.yml b/deployments/templates/prometheus.yml index 5c3e0af66..f1a551a62 100644 --- a/deployments/templates/prometheus.yml +++ b/deployments/templates/prometheus.yml @@ -44,12 +44,12 @@ scrape_configs: # prometheus fetches application services - job_name: 'openimserver-openim-api' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${API_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${API_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-msggateway' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${MSG_GATEWAY_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${MSG_GATEWAY_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-msgtransfer' @@ -59,41 +59,41 @@ scrape_configs: namespace: 'default' - job_name: 'openimserver-openim-push' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${PUSH_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${PUSH_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-rpc-auth' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${AUTH_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${AUTH_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-rpc-conversation' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${CONVERSATION_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${CONVERSATION_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-rpc-friend' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${FRIEND_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${FRIEND_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-rpc-group' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${GROUP_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${GROUP_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-rpc-msg' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${MESSAGE_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${MESSAGE_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-rpc-third' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${THIRD_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${THIRD_PROM_PORT}' ] labels: namespace: 'default' - job_name: 'openimserver-openim-rpc-user' static_configs: - - targets: [ '${OPENIM_SERVER_ADDRESS}:${USER_PROM_PORT}' ] + - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${USER_PROM_PORT}' ] labels: namespace: 'default' From de451d4cea1d961464318b7b2cd0ee657bd8b37d Mon Sep 17 00:00:00 2001 From: Gordon <46924906+FGadvancer@users.noreply.github.com> Date: Mon, 25 Dec 2023 16:30:18 +0800 Subject: [PATCH 15/31] fix: online notifications do not push to herself. (#1534) * fix: online notifications do not push to herself. * fix: online notifications do not push to herself. * fix: online notifications do not push to herself. --- internal/push/push_handler.go | 11 ++++++----- internal/push/push_rpc_server.go | 3 +-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/push/push_handler.go b/internal/push/push_handler.go index a1a9ff08e..c91206ecc 100644 --- a/internal/push/push_handler.go +++ b/internal/push/push_handler.go @@ -67,13 +67,14 @@ func (c *ConsumerHandler) handleMs2PsChat(ctx context.Context, msg []byte) { case constant.SuperGroupChatType: err = c.pusher.Push2SuperGroup(ctx, pbData.MsgData.GroupID, pbData.MsgData) default: - var pushUserIDs []string - if pbData.MsgData.SendID != pbData.MsgData.RecvID { - pushUserIDs = []string{pbData.MsgData.SendID, pbData.MsgData.RecvID} + var pushUserIDList []string + isSenderSync := utils.GetSwitchFromOptions(pbData.MsgData.Options, constant.IsSenderSync) + if !isSenderSync || pbData.MsgData.SendID == pbData.MsgData.RecvID { + pushUserIDList = append(pushUserIDList, pbData.MsgData.RecvID) } else { - pushUserIDs = []string{pbData.MsgData.SendID} + pushUserIDList = append(pushUserIDList, pbData.MsgData.RecvID, pbData.MsgData.SendID) } - err = c.pusher.Push2User(ctx, pushUserIDs, pbData.MsgData) + err = c.pusher.Push2User(ctx, pushUserIDList, pbData.MsgData) } if err != nil { if err == errNoOfflinePusher { diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go index 188ddc0e1..9e66f8f73 100644 --- a/internal/push/push_rpc_server.go +++ b/internal/push/push_rpc_server.go @@ -16,9 +16,8 @@ package push import ( "context" - "sync" - "github.com/OpenIMSDK/tools/utils" + "sync" "google.golang.org/grpc" From 7389639f174441ff66414e2e541e52aa138ba67f Mon Sep 17 00:00:00 2001 From: Brabem <69128477+luhaoling@users.noreply.github.com> Date: Tue, 26 Dec 2023 10:15:15 +0800 Subject: [PATCH 16/31] feat: add the notificationAccount (#1602) * feat: add notification API * fix: fix the script * fix: fix the error --- deployments/templates/openim.yaml | 8 ++ docs/contrib/environment.md | 74 ++++++++--------- go.mod | 2 + go.sum | 4 +- internal/api/friend.go | 3 - internal/api/msg.go | 5 +- internal/api/route.go | 6 +- internal/api/user.go | 15 +++- internal/rpc/friend/friend.go | 11 ++- internal/rpc/user/user.go | 128 ++++++++++++++++++++++++++++++ pkg/apistruct/msg.go | 2 +- pkg/authverify/token.go | 9 +++ pkg/common/config/config.go | 5 ++ pkg/common/db/controller/user.go | 6 ++ pkg/common/http/http_client.go | 2 +- pkg/rpcclient/user.go | 7 ++ scripts/check-all.sh | 2 +- scripts/install/environment.sh | 2 + 18 files changed, 238 insertions(+), 53 deletions(-) diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml index ed5dc4fe1..cbb4a8c6e 100644 --- a/deployments/templates/openim.yaml +++ b/deployments/templates/openim.yaml @@ -247,6 +247,14 @@ manager: userID: [ "${MANAGER_USERID_1}", "${MANAGER_USERID_2}", "${MANAGER_USERID_3}" ] nickname: [ "${NICKNAME_1}", "${NICKNAME_2}", "${NICKNAME_3}" ] +# chatAdmin, use for send notification +# +# Built-in app system notification account ID +# Built-in app system notification account nickname +im-admin: + userID: [ "${IM_ADMIN_USERID}" ] + nickname: [ "${IM_ADMIN_NAME}" ] + # Multi-platform login policy # For each platform(Android, iOS, Windows, Mac, web), only one can be online at a time multiLoginPolicy: ${MULTILOGIN_POLICY} diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md index 310c2df6a..e52d57235 100644 --- a/docs/contrib/environment.md +++ b/docs/contrib/environment.md @@ -453,43 +453,45 @@ This section involves configuring the log settings, including storage location, This section involves setting up additional configuration variables for Websocket, Push Notifications, and Chat. -| Parameter | Example Value | Description | -|-------------------------|-------------------|------------------------------------| -| WEBSOCKET_MAX_CONN_NUM | "100000" | Maximum Websocket connections | -| WEBSOCKET_MAX_MSG_LEN | "4096" | Maximum Websocket message length | -| WEBSOCKET_TIMEOUT | "10" | Websocket timeout | -| PUSH_ENABLE | "getui" | Push notification enable status | -| GETUI_PUSH_URL | [Generated URL] | GeTui Push Notification URL | -| GETUI_MASTER_SECRET | [User Defined] | GeTui Master Secret | -| GETUI_APP_KEY | [User Defined] | GeTui Application Key | -| GETUI_INTENT | [User Defined] | GeTui Push Intent | -| GETUI_CHANNEL_ID | [User Defined] | GeTui Channel ID | -| GETUI_CHANNEL_NAME | [User Defined] | GeTui Channel Name | -| FCM_SERVICE_ACCOUNT | "x.json" | FCM Service Account | -| JPNS_APP_KEY | [User Defined] | JPNS Application Key | -| JPNS_MASTER_SECRET | [User Defined] | JPNS Master Secret | -| JPNS_PUSH_URL | [User Defined] | JPNS Push Notification URL | -| JPNS_PUSH_INTENT | [User Defined] | JPNS Push Intent | -| MANAGER_USERID_1 | "openIM123456" | Administrator ID 1 | -| MANAGER_USERID_2 | "openIM654321" | Administrator ID 2 | -| MANAGER_USERID_3 | "openIMAdmin" | Administrator ID 3 | -| NICKNAME_1 | "system1" | Nickname 1 | -| NICKNAME_2 | "system2" | Nickname 2 | -| NICKNAME_3 | "system3" | Nickname 3 | -| MULTILOGIN_POLICY | "1" | Multi-login Policy | -| CHAT_PERSISTENCE_MYSQL | "true" | Chat Persistence in MySQL | -| MSG_CACHE_TIMEOUT | "86400" | Message Cache Timeout | -| GROUP_MSG_READ_RECEIPT | "true" | Group Message Read Receipt Enable | +| Parameter | Example Value | Description | +|-------------------------|-------------------|----------------------------------| +| WEBSOCKET_MAX_CONN_NUM | "100000" | Maximum Websocket connections | +| WEBSOCKET_MAX_MSG_LEN | "4096" | Maximum Websocket message length | +| WEBSOCKET_TIMEOUT | "10" | Websocket timeout | +| PUSH_ENABLE | "getui" | Push notification enable status | +| GETUI_PUSH_URL | [Generated URL] | GeTui Push Notification URL | +| GETUI_MASTER_SECRET | [User Defined] | GeTui Master Secret | +| GETUI_APP_KEY | [User Defined] | GeTui Application Key | +| GETUI_INTENT | [User Defined] | GeTui Push Intent | +| GETUI_CHANNEL_ID | [User Defined] | GeTui Channel ID | +| GETUI_CHANNEL_NAME | [User Defined] | GeTui Channel Name | +| FCM_SERVICE_ACCOUNT | "x.json" | FCM Service Account | +| JPNS_APP_KEY | [User Defined] | JPNS Application Key | +| JPNS_MASTER_SECRET | [User Defined] | JPNS Master Secret | +| JPNS_PUSH_URL | [User Defined] | JPNS Push Notification URL | +| JPNS_PUSH_INTENT | [User Defined] | JPNS Push Intent | +| MANAGER_USERID_1 | "openIM123456" | Administrator ID 1 | +| MANAGER_USERID_2 | "openIM654321" | Administrator ID 2 | +| MANAGER_USERID_3 | "openIMAdmin" | Administrator ID 3 | +| NICKNAME_1 | "system1" | Nickname 1 | +| NICKNAME_2 | "system2" | Nickname 2 | +| NICKNAME_3 | "system3" | Nickname 3 | +| IM_ADMIN_USERID | "imAdmin" | IM Administrator ID | +| IM_ADMIN_NAME | "imAdmin" | IM Administrator Nickname | +| MULTILOGIN_POLICY | "1" | Multi-login Policy | +| CHAT_PERSISTENCE_MYSQL | "true" | Chat Persistence in MySQL | +| MSG_CACHE_TIMEOUT | "86400" | Message Cache Timeout | +| GROUP_MSG_READ_RECEIPT | "true" | Group Message Read Receipt Enable | | SINGLE_MSG_READ_RECEIPT | "true" | Single Message Read Receipt Enable | -| RETAIN_CHAT_RECORDS | "365" | Retain Chat Records (in days) | -| CHAT_RECORDS_CLEAR_TIME | [Cron Expression] | Chat Records Clear Time | -| MSG_DESTRUCT_TIME | [Cron Expression] | Message Destruct Time | -| SECRET | "${PASSWORD}" | Secret Key | -| TOKEN_EXPIRE | "90" | Token Expiry Time | -| FRIEND_VERIFY | "false" | Friend Verification Enable | -| IOS_PUSH_SOUND | "xxx" | iOS | -| CALLBACK_ENABLE | "false" | Enable callback | -| CALLBACK_TIMEOUT | "5" | Maximum timeout for callback call | +| RETAIN_CHAT_RECORDS | "365" | Retain Chat Records (in days) | +| CHAT_RECORDS_CLEAR_TIME | [Cron Expression] | Chat Records Clear Time | +| MSG_DESTRUCT_TIME | [Cron Expression] | Message Destruct Time | +| SECRET | "${PASSWORD}" | Secret Key | +| TOKEN_EXPIRE | "90" | Token Expiry Time | +| FRIEND_VERIFY | "false" | Friend Verification Enable | +| IOS_PUSH_SOUND | "xxx" | iOS | +| CALLBACK_ENABLE | "false" | Enable callback | +| CALLBACK_TIMEOUT | "5" | Maximum timeout for callback call | | CALLBACK_FAILED_CONTINUE| "true" | fails to continue to the next step | ### 2.20. Prometheus Configuration diff --git a/go.mod b/go.mod index 9a9cde30e..fb5be5b90 100644 --- a/go.mod +++ b/go.mod @@ -156,3 +156,5 @@ require ( golang.org/x/crypto v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) + +replace github.com/OpenIMSDK/protocol v0.0.36 => github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5 diff --git a/go.sum b/go.sum index 61323c57b..cde33c7cd 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,6 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= -github.com/OpenIMSDK/protocol v0.0.36 h1:UJnFsr1A4RrNeHMNDVS/1nvXWFoGM43dcXpZeJiIZ+0= -github.com/OpenIMSDK/protocol v0.0.36/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48= github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= @@ -227,6 +225,8 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w= github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w= +github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5 h1:nmrJmAgQsCAxKgw109kaTcBV4rMWDRvqOson0ehw708= +github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= diff --git a/internal/api/friend.go b/internal/api/friend.go index 58e7398dd..23f337a9f 100644 --- a/internal/api/friend.go +++ b/internal/api/friend.go @@ -92,6 +92,3 @@ func (o *FriendApi) GetFriendIDs(c *gin.Context) { func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) { a2r.Call(friend.FriendClient.GetSpecifiedFriendsInfo, o.Client, c) } -func (o *FriendApi) SetPinFriends(c *gin.Context) { - a2r.Call(friend.FriendClient.PinFriends, o.Client, c) -} diff --git a/internal/api/msg.go b/internal/api/msg.go index 664ee505a..b6bfcebb6 100644 --- a/internal/api/msg.go +++ b/internal/api/msg.go @@ -169,9 +169,8 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM case constant.OANotification: data = apistruct.OANotificationElem{} req.SessionType = constant.NotificationChatType - if !authverify.IsManagerUserID(req.SendID) { - return nil, errs.ErrNoPermission. - Wrap("only app manager can as sender send OANotificationElem") + if err = m.userRpcClient.GetNotificationByID(c, req.SendID); err != nil { + return nil, err } default: return nil, errs.ErrArgs.WithDetail("not support err contentType") diff --git a/internal/api/route.go b/internal/api/route.go index 8bfea5cca..05aa6ac92 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -82,6 +82,10 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive userRouterGroup.POST("/process_user_command_delete", ParseToken, u.ProcessUserCommandDelete) userRouterGroup.POST("/process_user_command_update", ParseToken, u.ProcessUserCommandUpdate) userRouterGroup.POST("/process_user_command_get", ParseToken, u.ProcessUserCommandGet) + + userRouterGroup.POST("/add_notification_account", ParseToken, u.AddNotificationAccount) + userRouterGroup.POST("/update_notification_account", ParseToken, u.UpdateNotificationAccountInfo) + userRouterGroup.POST("/search_notification_account", ParseToken, u.SearchNotificationAccount) } // friend routing group friendRouterGroup := r.Group("/friend", ParseToken) @@ -103,7 +107,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive friendRouterGroup.POST("/is_friend", f.IsFriend) friendRouterGroup.POST("/get_friend_id", f.GetFriendIDs) friendRouterGroup.POST("/get_specified_friends_info", f.GetSpecifiedFriendsInfo) - friendRouterGroup.POST("/set_pin_friend", f.SetPinFriends) + //friendRouterGroup.POST("/set_pin_friend", f.SetPinFriends) } g := NewGroupApi(*groupRpc) groupRouterGroup := r.Group("/group", ParseToken) diff --git a/internal/api/user.go b/internal/api/user.go index 8350d1711..cf68fb422 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -15,8 +15,6 @@ package api import ( - "github.com/gin-gonic/gin" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/msggateway" "github.com/OpenIMSDK/protocol/user" @@ -24,6 +22,7 @@ import ( "github.com/OpenIMSDK/tools/apiresp" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" + "github.com/gin-gonic/gin" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" @@ -219,3 +218,15 @@ func (u *UserApi) ProcessUserCommandUpdate(c *gin.Context) { func (u *UserApi) ProcessUserCommandGet(c *gin.Context) { a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c) } + +func (u *UserApi) AddNotificationAccount(c *gin.Context) { + a2r.Call(user.UserClient.AddNotificationAccount, u.Client, c) +} + +func (u *UserApi) UpdateNotificationAccountInfo(c *gin.Context) { + a2r.Call(user.UserClient.UpdateNotificationAccountInfo, u.Client, c) +} + +func (u *UserApi) SearchNotificationAccount(c *gin.Context) { + a2r.Call(user.UserClient.SearchNotificationAccount, u.Client, c) +} diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index 12203aa7e..97e53d197 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -53,6 +53,11 @@ type friendServer struct { RegisterCenter registry.SvcDiscoveryRegistry } +func (s *friendServer) UpdateFriends(ctx context.Context, req *pbfriend.UpdateFriendsReq) (*pbfriend.UpdateFriendsResp, error) { + //TODO implement me + panic("implement me") +} + func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { // Initialize MongoDB mongo, err := unrelation.NewMongo() @@ -438,8 +443,8 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien } func (s *friendServer) PinFriends( ctx context.Context, - req *pbfriend.PinFriendsReq, -) (*pbfriend.PinFriendsResp, error) { + req *pbfriend.UpdateFriendsReq, +) (*pbfriend.UpdateFriendsResp, error) { if len(req.FriendUserIDs) == 0 { return nil, errs.ErrArgs.Wrap("friendIDList is empty") } @@ -465,6 +470,6 @@ func (s *friendServer) PinFriends( } } - resp := &pbfriend.PinFriendsResp{} + resp := &pbfriend.UpdateFriendsResp{} return resp, nil } diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index 70e3aebe6..9bc56298f 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -17,6 +17,7 @@ package user import ( "context" "errors" + "math/rand" "strings" "time" @@ -72,6 +73,12 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { for k, v := range config.Config.Manager.UserID { users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.Manager.Nickname[k], AppMangerLevel: constant.AppAdmin}) } + if len(config.Config.IMAdmin.UserID) != len(config.Config.IMAdmin.Nickname) { + return errors.New("len(config.Config.AppNotificationAdmin.AppManagerUid) != len(config.Config.AppNotificationAdmin.Nickname)") + } + for k, v := range config.Config.IMAdmin.UserID { + users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.IMAdmin.Nickname[k], AppMangerLevel: constant.AppNotificationAdmin}) + } userDB, err := mgo.NewUserMongo(mongo.GetDatabase()) if err != nil { return err @@ -390,3 +397,124 @@ func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.Proc // Return the response with the slice return &pbuser.ProcessUserCommandGetResp{KVArray: commandInfoSlice}, nil } + +func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.AddNotificationAccountReq) (*pbuser.AddNotificationAccountResp, error) { + if err := authverify.CheckIMAdmin(ctx); err != nil { + return nil, err + } + + var userID string + for i := 0; i < 20; i++ { + userId := s.genUserID() + _, err := s.UserDatabase.FindWithError(ctx, []string{userId}) + if err == nil { + continue + } + userID = userId + break + } + if userID == "" { + return nil, errs.ErrInternalServer.Wrap("gen user id failed") + } + + user := &tablerelation.UserModel{ + UserID: userID, + Nickname: req.NickName, + FaceURL: req.FaceURL, + CreateTime: time.Now(), + AppMangerLevel: constant.AppNotificationAdmin, + } + if err := s.UserDatabase.Create(ctx, []*tablerelation.UserModel{user}); err != nil { + return nil, err + } + + return &pbuser.AddNotificationAccountResp{}, nil +} + +func (s *userServer) UpdateNotificationAccountInfo(ctx context.Context, req *pbuser.UpdateNotificationAccountInfoReq) (*pbuser.UpdateNotificationAccountInfoResp, error) { + if err := authverify.CheckIMAdmin(ctx); err != nil { + return nil, err + } + + if _, err := s.UserDatabase.FindWithError(ctx, []string{req.UserID}); err != nil { + return nil, errs.ErrArgs.Wrap() + } + + user := map[string]interface{}{} + + if req.NickName != "" { + user["nickname"] = req.NickName + } + + if req.FaceURL != "" { + user["face_url"] = req.FaceURL + } + + if err := s.UserDatabase.UpdateByMap(ctx, req.UserID, user); err != nil { + return nil, err + } + + return &pbuser.UpdateNotificationAccountInfoResp{}, nil +} + +func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.SearchNotificationAccountReq) (*pbuser.SearchNotificationAccountResp, error) { + if err := authverify.CheckIMAdmin(ctx); err != nil { + return nil, err + } + + _, users, err := s.UserDatabase.Page(ctx, req.Pagination) + if err != nil { + return nil, err + } + + var total int64 + accounts := make([]*pbuser.NotificationAccountInfo, 0, len(users)) + for _, v := range users { + if v.AppMangerLevel != constant.AppNotificationAdmin { + continue + } + temp := &pbuser.NotificationAccountInfo{ + UserID: v.UserID, + FaceURL: v.FaceURL, + NickName: v.Nickname, + } + accounts = append(accounts, temp) + total += 1 + } + return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}, nil +} + +func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) { + //TODO implement me + panic("implement me") +} + +func (s *userServer) GetNotificationAccount(ctx context.Context, req *pbuser.GetNotificationAccountReq) (*pbuser.GetNotificationAccountResp, error) { + if req.UserID == "" { + return nil, errs.ErrArgs.Wrap("userID is empty") + } + user, err := s.UserDatabase.GetUserByID(ctx, req.UserID) + if err != nil { + return nil, errs.ErrUserIDNotFound.Wrap() + } + if user.AppMangerLevel == constant.AppAdmin || user.AppMangerLevel == constant.AppNotificationAdmin { + return &pbuser.GetNotificationAccountResp{}, nil + } + + return nil, errs.ErrNoPermission.Wrap("notification messages cannot be sent for this ID") +} + +func (s *userServer) genUserID() string { + const l = 10 + data := make([]byte, l) + rand.Read(data) + chars := []byte("0123456789") + for i := 0; i < len(data); i++ { + if i == 0 { + data[i] = chars[1:][data[i]%9] + } else { + data[i] = chars[data[i]%10] + } + } + return string(data) +} diff --git a/pkg/apistruct/msg.go b/pkg/apistruct/msg.go index 4b7bd1e6f..d23db9bf5 100644 --- a/pkg/apistruct/msg.go +++ b/pkg/apistruct/msg.go @@ -87,7 +87,7 @@ type OANotificationElem struct { NotificationType int32 `mapstructure:"notificationType" json:"notificationType" validate:"required"` Text string `mapstructure:"text" json:"text" validate:"required"` Url string `mapstructure:"url" json:"url"` - MixType int32 `mapstructure:"mixType" json:"mixType" validate:"required"` + MixType int32 `mapstructure:"mixType" json:"mixType"` PictureElem *PictureElem `mapstructure:"pictureElem" json:"pictureElem"` SoundElem *SoundElem `mapstructure:"soundElem" json:"soundElem"` VideoElem *VideoElem `mapstructure:"videoElem" json:"videoElem"` diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go index fd01e8c5a..d9aa0dbb1 100644 --- a/pkg/authverify/token.go +++ b/pkg/authverify/token.go @@ -54,6 +54,15 @@ func CheckAdmin(ctx context.Context) error { } return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx))) } +func CheckIMAdmin(ctx context.Context) error { + if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID) { + return nil + } + if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) { + return nil + } + return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not CheckIMAdmin userID", mcontext.GetOpUserID(ctx))) +} func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) { return tokenverify.GetClaimFromToken(string(redisToken.([]uint8)), Secret()) diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 6da89fc8f..707601234 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -236,6 +236,11 @@ type configStruct struct { Nickname []string `yaml:"nickname"` } `yaml:"manager"` + IMAdmin struct { + UserID []string `yaml:"userID"` + Nickname []string `yaml:"nickname"` + } `yaml:"im-admin"` + MultiLoginPolicy int `yaml:"multiLoginPolicy"` ChatPersistenceMysql bool `yaml:"chatPersistenceMysql"` MsgCacheTimeout int `yaml:"msgCacheTimeout"` diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go index 433fb7ad3..2fafcf266 100644 --- a/pkg/common/db/controller/user.go +++ b/pkg/common/db/controller/user.go @@ -50,6 +50,8 @@ type UserDatabase interface { IsExist(ctx context.Context, userIDs []string) (exist bool, err error) // GetAllUserID Get all user IDs GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error) + // Get user by userID + GetUserByID(ctx context.Context, userID string) (user *relation.UserModel, err error) // InitOnce Inside the function, first query whether it exists in the db, if it exists, do nothing; if it does not exist, insert it InitOnce(ctx context.Context, users []*relation.UserModel) (err error) // CountTotal Get the total number of users @@ -183,6 +185,10 @@ func (u *userDatabase) GetAllUserID(ctx context.Context, pagination pagination.P return u.userDB.GetAllUserID(ctx, pagination) } +func (u *userDatabase) GetUserByID(ctx context.Context, userID string) (user *relation.UserModel, err error) { + return u.userDB.Take(ctx, userID) +} + // CountTotal Get the total number of users. func (u *userDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) { return u.userDB.CountTotal(ctx, before) diff --git a/pkg/common/http/http_client.go b/pkg/common/http/http_client.go index baad60459..a80d1c9a4 100644 --- a/pkg/common/http/http_client.go +++ b/pkg/common/http/http_client.go @@ -112,7 +112,6 @@ func callBackPostReturn(ctx context.Context, url, command string, input interfac //v.Set(constant.CallbackCommand, command) //url = url + "/" + v.Encode() url = url + "/" + command - b, err := Post(ctx, url, nil, input, callbackConfig.CallbackTimeOut) if err != nil { if callbackConfig.CallbackFailedContinue != nil && *callbackConfig.CallbackFailedContinue { @@ -121,6 +120,7 @@ func callBackPostReturn(ctx context.Context, url, command string, input interfac } return errs.ErrNetwork.Wrap(err.Error()) } + defer log.ZDebug(ctx, "callback", "data", string(b)) if err = json.Unmarshal(b, output); err != nil { if callbackConfig.CallbackFailedContinue != nil && *callbackConfig.CallbackFailedContinue { diff --git a/pkg/rpcclient/user.go b/pkg/rpcclient/user.go index c40d95727..de633ee30 100644 --- a/pkg/rpcclient/user.go +++ b/pkg/rpcclient/user.go @@ -179,3 +179,10 @@ func (u *UserRpcClient) SetUserStatus(ctx context.Context, userID string, status }) return err } + +func (u *UserRpcClient) GetNotificationByID(ctx context.Context, userID string) error { + _, err := u.Client.GetNotificationAccount(ctx, &user.GetNotificationAccountReq{ + UserID: userID, + }) + return err +} diff --git a/scripts/check-all.sh b/scripts/check-all.sh index efaa2ccb7..e1e07bd65 100755 --- a/scripts/check-all.sh +++ b/scripts/check-all.sh @@ -89,4 +89,4 @@ else echo "++++ Check all openim service ports successfully !" fi -set -e +set -e \ No newline at end of file diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh index 3dd062af6..feb36c3c1 100755 --- a/scripts/install/environment.sh +++ b/scripts/install/environment.sh @@ -353,6 +353,8 @@ def "MANAGER_USERID_3" "openIMAdmin" # 管理员ID 3 def "NICKNAME_1" "system1" # 昵称1 def "NICKNAME_2" "system2" # 昵称2 def "NICKNAME_3" "system3" # 昵称3 +def "IM_ADMIN_USERID" "imAdmin" # IM管理员ID +def "IM_ADMIN_NAME" "imAdmin" # IM管理员昵称 def "MULTILOGIN_POLICY" "1" # 多登录策略 def "CHAT_PERSISTENCE_MYSQL" "true" # 聊天持久化MySQL def "MSG_CACHE_TIMEOUT" "86400" # 消息缓存超时 From 47dd6b17f61736686dabf3798888aaa7060d75a8 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Tue, 26 Dec 2023 12:16:55 +0800 Subject: [PATCH 17/31] Update openimci.yml (#1610) * Update openimci.yml * Update Makefile --- .github/workflows/openimci.yml | 8 +++++++- Makefile | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml index d65c0dc89..d8e988f0b 100644 --- a/.github/workflows/openimci.yml +++ b/.github/workflows/openimci.yml @@ -207,6 +207,12 @@ jobs: sudo make check || \ (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null) + - name: Restart Services and Print Logs for Ubuntu + if: runner.os == 'Linux' + run: | + sudo make restart + sudo make check + # - name: Build, Start, Check Services and Print Logs for macOS # if: runner.os == 'macOS' # run: | @@ -239,4 +245,4 @@ jobs: - name: Test Docker Build run: | sudo make init - sudo make image \ No newline at end of file + sudo make image diff --git a/Makefile b/Makefile index 1941bde6c..4faf1c21d 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ stop: ## restart: Restart openim (make init configuration file is initialized) ✨ .PHONY: restart -restart: clean stop build init start check +restart: clean stop build start check ## multiarch: Build binaries for multiple platforms. See option PLATFORMS. ✨ .PHONY: multiarch From cd1235fb32072af665808d3bffd6f782a6643dd3 Mon Sep 17 00:00:00 2001 From: chao <48119764+withchao@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:29:42 +0800 Subject: [PATCH 18/31] feat: s3 FormData upload (#1614) * upgrade package and rtc convert * upgrade package and rtc convert * upgrade package and rtc convert * upgrade package and rtc convert * friend user * s3 form data * s3 form data * s3 form data * s3 form data * s3 form data * s3 form data * s3 form data * s3 form data * s3 form data --- go.mod | 8 +- go.sum | 8 +- internal/api/route.go | 2 + internal/api/third.go | 8 ++ internal/rpc/friend/friend.go | 3 +- internal/rpc/third/s3.go | 113 ++++++++++++++++++++++ internal/rpc/third/third.go | 10 -- internal/rpc/third/tool.go | 3 + internal/rpc/user/user.go | 9 +- pkg/common/cmd/root.go | 2 +- pkg/common/db/controller/s3.go | 10 ++ pkg/common/db/s3/cont/consts.go | 1 + pkg/common/db/s3/cont/controller.go | 4 + pkg/common/db/s3/cos/cos.go | 69 +++++++++++++ pkg/common/db/s3/minio/minio.go | 50 ++++++++++ pkg/common/db/s3/oss/oss.go | 49 ++++++++++ pkg/common/db/s3/s3.go | 11 +++ pkg/common/ginprometheus/ginprometheus.go | 2 +- 18 files changed, 334 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index fb5be5b90..a753cae51 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.19 require ( firebase.google.com/go v3.13.0+incompatible + github.com/OpenIMSDK/protocol v0.0.39 + github.com/OpenIMSDK/tools v0.0.21 github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/dtm-labs/rockscache v0.1.1 github.com/gin-gonic/gin v1.9.1 @@ -33,8 +35,6 @@ require github.com/google/uuid v1.3.1 require ( github.com/IBM/sarama v1.41.3 - github.com/OpenIMSDK/protocol v0.0.36 - github.com/OpenIMSDK/tools v0.0.21 github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible github.com/go-redis/redis v6.15.9+incompatible github.com/redis/go-redis/v9 v9.2.1 @@ -133,7 +133,7 @@ require ( golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sys v0.14.0 // indirect golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.3.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect @@ -156,5 +156,3 @@ require ( golang.org/x/crypto v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) - -replace github.com/OpenIMSDK/protocol v0.0.36 => github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5 diff --git a/go.sum b/go.sum index cde33c7cd..a4609f6f2 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= +github.com/OpenIMSDK/protocol v0.0.39 h1:DfvFcNGBcfj2vtT7W3uw4U/ipnI7NecTzQdlSYGuQz8= +github.com/OpenIMSDK/protocol v0.0.39/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48= github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= @@ -225,8 +227,6 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w= github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w= -github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5 h1:nmrJmAgQsCAxKgw109kaTcBV4rMWDRvqOson0ehw708= -github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -453,8 +453,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/internal/api/route.go b/internal/api/route.go index 05aa6ac92..8fb372587 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -171,6 +171,8 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive objectGroup.POST("/auth_sign", t.AuthSign) objectGroup.POST("/complete_multipart_upload", t.CompleteMultipartUpload) objectGroup.POST("/access_url", t.AccessURL) + objectGroup.POST("/initiate_form_data", t.InitiateFormData) + objectGroup.POST("/complete_form_data", t.CompleteFormData) objectGroup.GET("/*name", t.ObjectRedirect) } // Message diff --git a/internal/api/third.go b/internal/api/third.go index 5191903da..37ec55098 100644 --- a/internal/api/third.go +++ b/internal/api/third.go @@ -71,6 +71,14 @@ func (o *ThirdApi) AccessURL(c *gin.Context) { a2r.Call(third.ThirdClient.AccessURL, o.Client, c) } +func (o *ThirdApi) InitiateFormData(c *gin.Context) { + a2r.Call(third.ThirdClient.InitiateFormData, o.Client, c) +} + +func (o *ThirdApi) CompleteFormData(c *gin.Context) { + a2r.Call(third.ThirdClient.CompleteFormData, o.Client, c) +} + func (o *ThirdApi) ObjectRedirect(c *gin.Context) { name := c.Param("name") if name == "" { diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index 97e53d197..c40b566f3 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -54,8 +54,7 @@ type friendServer struct { } func (s *friendServer) UpdateFriends(ctx context.Context, req *pbfriend.UpdateFriendsReq) (*pbfriend.UpdateFriendsResp, error) { - //TODO implement me - panic("implement me") + return nil, errs.ErrInternalServer.Wrap("not implemented") } func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { diff --git a/internal/rpc/third/s3.go b/internal/rpc/third/s3.go index ca826e805..2c230f258 100644 --- a/internal/rpc/third/s3.go +++ b/internal/rpc/third/s3.go @@ -16,6 +16,12 @@ package third import ( "context" + "encoding/base64" + "encoding/hex" + "encoding/json" + "github.com/google/uuid" + "github.com/openimsdk/open-im-server/v3/pkg/authverify" + "path" "strconv" "time" @@ -179,6 +185,113 @@ func (t *thirdServer) AccessURL(ctx context.Context, req *third.AccessURLReq) (* }, nil } +func (t *thirdServer) InitiateFormData(ctx context.Context, req *third.InitiateFormDataReq) (*third.InitiateFormDataResp, error) { + if req.Name == "" { + return nil, errs.ErrArgs.Wrap("name is empty") + } + if req.Size <= 0 { + return nil, errs.ErrArgs.Wrap("size must be greater than 0") + } + if err := checkUploadName(ctx, req.Name); err != nil { + return nil, err + } + var duration time.Duration + opUserID := mcontext.GetOpUserID(ctx) + var key string + if authverify.IsManagerUserID(opUserID) { + if req.Millisecond <= 0 { + duration = time.Minute * 10 + } else { + duration = time.Millisecond * time.Duration(req.Millisecond) + } + if req.Absolute { + key = req.Name + } + } else { + duration = time.Minute * 10 + } + uid, err := uuid.NewRandom() + if err != nil { + return nil, err + } + if key == "" { + date := time.Now().Format("20060102") + key = path.Join(cont.DirectPath, date, opUserID, hex.EncodeToString(uid[:])+path.Ext(req.Name)) + } + mate := FormDataMate{ + Name: req.Name, + Size: req.Size, + ContentType: req.ContentType, + Group: req.Group, + Key: key, + } + mateData, err := json.Marshal(&mate) + if err != nil { + return nil, err + } + resp, err := t.s3dataBase.FormData(ctx, key, req.Size, req.ContentType, duration) + if err != nil { + return nil, err + } + return &third.InitiateFormDataResp{ + Id: base64.RawStdEncoding.EncodeToString(mateData), + Url: resp.URL, + File: resp.File, + Header: toPbMapArray(resp.Header), + FormData: resp.FormData, + Expires: resp.Expires.UnixMilli(), + SuccessCodes: utils.Slice(resp.SuccessCodes, func(code int) int32 { + return int32(code) + }), + }, nil +} + +func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.CompleteFormDataReq) (*third.CompleteFormDataResp, error) { + if req.Id == "" { + return nil, errs.ErrArgs.Wrap("id is empty") + } + data, err := base64.RawStdEncoding.DecodeString(req.Id) + if err != nil { + return nil, errs.ErrArgs.Wrap("invalid id " + err.Error()) + } + var mate FormDataMate + if err := json.Unmarshal(data, &mate); err != nil { + return nil, errs.ErrArgs.Wrap("invalid id " + err.Error()) + } + if err := checkUploadName(ctx, mate.Name); err != nil { + return nil, err + } + info, err := t.s3dataBase.StatObject(ctx, mate.Key) + if err != nil { + return nil, err + } + if info.Size > 0 && info.Size != mate.Size { + return nil, errs.ErrData.Wrap("file size mismatch") + } + obj := &relation.ObjectModel{ + Name: mate.Name, + UserID: mcontext.GetOpUserID(ctx), + Hash: "etag_" + info.ETag, + Key: info.Key, + Size: info.Size, + ContentType: mate.ContentType, + Group: mate.Group, + CreateTime: time.Now(), + } + if err := t.s3dataBase.SetObject(ctx, obj); err != nil { + return nil, err + } + return &third.CompleteFormDataResp{Url: t.apiAddress(mate.Name)}, nil +} + func (t *thirdServer) apiAddress(name string) string { return t.apiURL + name } + +type FormDataMate struct { + Name string `json:"name"` + Size int64 `json:"size"` + ContentType string `json:"contentType"` + Group string `json:"group"` + Key string `json:"key"` +} diff --git a/internal/rpc/third/third.go b/internal/rpc/third/third.go index 35df3f925..7a63d3526 100644 --- a/internal/rpc/third/third.go +++ b/internal/rpc/third/third.go @@ -101,16 +101,6 @@ type thirdServer struct { defaultExpire time.Duration } -func (t *thirdServer) InitiateFormData(ctx context.Context, req *third.InitiateFormDataReq) (*third.InitiateFormDataResp, error) { - //TODO implement me - panic("implement me") -} - -func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.CompleteFormDataReq) (*third.CompleteFormDataResp, error) { - //TODO implement me - panic("implement me") -} - func (t *thirdServer) FcmUpdateToken(ctx context.Context, req *third.FcmUpdateTokenReq) (resp *third.FcmUpdateTokenResp, err error) { err = t.thirdDatabase.FcmUpdateToken(ctx, req.Account, int(req.PlatformID), req.FcmToken, req.ExpireTime) if err != nil { diff --git a/internal/rpc/third/tool.go b/internal/rpc/third/tool.go index a65d882dd..a6c16ff9d 100644 --- a/internal/rpc/third/tool.go +++ b/internal/rpc/third/tool.go @@ -29,6 +29,9 @@ import ( ) func toPbMapArray(m map[string][]string) []*third.KeyValues { + if len(m) == 0 { + return nil + } res := make([]*third.KeyValues, 0, len(m)) for key := range m { res = append(res, &third.KeyValues{ diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index 9bc56298f..b5ad186a5 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -57,6 +57,10 @@ type userServer struct { RegisterCenter registry.SvcDiscoveryRegistry } +func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { rdb, err := cache.NewRedis() if err != nil { @@ -484,11 +488,6 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser. return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}, nil } -func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) { - //TODO implement me - panic("implement me") -} - func (s *userServer) GetNotificationAccount(ctx context.Context, req *pbuser.GetNotificationAccountReq) (*pbuser.GetNotificationAccountResp, error) { if req.UserID == "" { return nil, errs.ErrArgs.Wrap("userID is empty") diff --git a/pkg/common/cmd/root.go b/pkg/common/cmd/root.go index 0bc308e07..66bec61a7 100644 --- a/pkg/common/cmd/root.go +++ b/pkg/common/cmd/root.go @@ -45,7 +45,7 @@ type CmdOpts struct { func WithCronTaskLogName() func(*CmdOpts) { return func(opts *CmdOpts) { - opts.loggerPrefixName = "OpenIM.CronTask.log.all" + opts.loggerPrefixName = "openim.crontask.log.all" } } diff --git a/pkg/common/db/controller/s3.go b/pkg/common/db/controller/s3.go index 6916a7d30..95505de41 100644 --- a/pkg/common/db/controller/s3.go +++ b/pkg/common/db/controller/s3.go @@ -35,6 +35,8 @@ type S3Database interface { CompleteMultipartUpload(ctx context.Context, uploadID string, parts []string) (*cont.UploadResult, error) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) SetObject(ctx context.Context, info *relation.ObjectModel) error + StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error) + FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) } func NewS3Database(rdb redis.UniversalClient, s3 s3.Interface, obj relation.ObjectInfoModelInterface) S3Database { @@ -100,3 +102,11 @@ func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Dur } return expireTime, rawURL, nil } + +func (s *s3Database) StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error) { + return s.s3.StatObject(ctx, name) +} + +func (s *s3Database) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) { + return s.s3.FormData(ctx, name, size, contentType, duration) +} diff --git a/pkg/common/db/s3/cont/consts.go b/pkg/common/db/s3/cont/consts.go index 1a0467ce5..a01a8312c 100644 --- a/pkg/common/db/s3/cont/consts.go +++ b/pkg/common/db/s3/cont/consts.go @@ -17,6 +17,7 @@ package cont const ( hashPath = "openim/data/hash/" tempPath = "openim/temp/" + DirectPath = "openim/direct" UploadTypeMultipart = 1 // 分片上传 UploadTypePresigned = 2 // 预签名上传 partSeparator = "," diff --git a/pkg/common/db/s3/cont/controller.go b/pkg/common/db/s3/cont/controller.go index 1bf1a4b12..82c27c1f2 100644 --- a/pkg/common/db/s3/cont/controller.go +++ b/pkg/common/db/s3/cont/controller.go @@ -279,3 +279,7 @@ func (c *Controller) AccessURL(ctx context.Context, name string, expire time.Dur } return c.impl.AccessURL(ctx, name, expire, opt) } + +func (c *Controller) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) { + return c.impl.FormData(ctx, name, size, contentType, duration) +} diff --git a/pkg/common/db/s3/cos/cos.go b/pkg/common/db/s3/cos/cos.go index 7add88487..7d2c0befe 100644 --- a/pkg/common/db/s3/cos/cos.go +++ b/pkg/common/db/s3/cos/cos.go @@ -16,6 +16,11 @@ package cos import ( "context" + "crypto/hmac" + "crypto/sha1" + "encoding/base64" + "encoding/hex" + "encoding/json" "errors" "fmt" "net/http" @@ -44,6 +49,8 @@ const ( imageWebp = "webp" ) +const successCode = http.StatusOK + const ( videoSnapshotImagePng = "png" videoSnapshotImageJpg = "jpg" @@ -326,3 +333,65 @@ func (c *Cos) getPresignedURL(ctx context.Context, name string, expire time.Dura } return c.client.Object.GetObjectURL(name), nil } + +func (c *Cos) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) { + // https://cloud.tencent.com/document/product/436/14690 + now := time.Now() + expiration := now.Add(duration) + keyTime := fmt.Sprintf("%d;%d", now.Unix(), expiration.Unix()) + conditions := []any{ + map[string]string{"q-sign-algorithm": "sha1"}, + map[string]string{"q-ak": c.credential.SecretID}, + map[string]string{"q-sign-time": keyTime}, + map[string]string{"key": name}, + } + if contentType != "" { + conditions = append(conditions, map[string]string{"Content-Type": contentType}) + } + policy := map[string]any{ + "expiration": expiration.Format("2006-01-02T15:04:05.000Z"), + "conditions": conditions, + } + policyJson, err := json.Marshal(policy) + if err != nil { + return nil, err + } + signKey := hmacSha1val(c.credential.SecretKey, keyTime) + strToSign := sha1val(string(policyJson)) + signature := hmacSha1val(signKey, strToSign) + + fd := &s3.FormData{ + URL: c.client.BaseURL.BucketURL.String(), + File: "file", + Expires: expiration, + FormData: map[string]string{ + "policy": base64.StdEncoding.EncodeToString(policyJson), + "q-sign-algorithm": "sha1", + "q-ak": c.credential.SecretID, + "q-key-time": keyTime, + "q-signature": signature, + "key": name, + "success_action_status": strconv.Itoa(successCode), + }, + SuccessCodes: []int{successCode}, + } + if contentType != "" { + fd.FormData["Content-Type"] = contentType + } + if c.credential.SessionToken != "" { + fd.FormData["x-cos-security-token"] = c.credential.SessionToken + } + return fd, nil +} + +func hmacSha1val(key, msg string) string { + v := hmac.New(sha1.New, []byte(key)) + v.Write([]byte(msg)) + return hex.EncodeToString(v.Sum(nil)) +} + +func sha1val(msg string) string { + sha1Hash := sha1.New() + sha1Hash.Write([]byte(msg)) + return hex.EncodeToString(sha1Hash.Sum(nil)) +} diff --git a/pkg/common/db/s3/minio/minio.go b/pkg/common/db/s3/minio/minio.go index be49e2faa..7dfe35b51 100644 --- a/pkg/common/db/s3/minio/minio.go +++ b/pkg/common/db/s3/minio/minio.go @@ -57,6 +57,8 @@ const ( imageThumbnailPath = "openim/thumbnail" ) +const successCode = http.StatusOK + func NewMinio(cache cache.MinioCache) (s3.Interface, error) { u, err := url.Parse(config.Config.Object.Minio.Endpoint) if err != nil { @@ -441,3 +443,51 @@ func (m *Minio) getObjectData(ctx context.Context, name string, limit int64) ([] } return io.ReadAll(io.LimitReader(object, limit)) } + +func (m *Minio) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) { + if err := m.initMinio(ctx); err != nil { + return nil, err + } + policy := minio.NewPostPolicy() + if err := policy.SetKey(name); err != nil { + return nil, err + } + expires := time.Now().Add(duration) + if err := policy.SetExpires(expires); err != nil { + return nil, err + } + if size > 0 { + if err := policy.SetContentLengthRange(0, size); err != nil { + return nil, err + } + } + if err := policy.SetSuccessStatusAction(strconv.Itoa(successCode)); err != nil { + return nil, err + } + if contentType != "" { + if err := policy.SetContentType(contentType); err != nil { + return nil, err + } + } + if err := policy.SetBucket(m.bucket); err != nil { + return nil, err + } + u, fd, err := m.core.PresignedPostPolicy(ctx, policy) + if err != nil { + return nil, err + } + sign, err := url.Parse(m.signEndpoint) + if err != nil { + return nil, err + } + u.Scheme = sign.Scheme + u.Host = sign.Host + return &s3.FormData{ + URL: u.String(), + File: "file", + Header: nil, + FormData: fd, + Expires: expires, + SuccessCodes: []int{successCode}, + }, nil +} diff --git a/pkg/common/db/s3/oss/oss.go b/pkg/common/db/s3/oss/oss.go index 6a728127b..8fa2a538e 100644 --- a/pkg/common/db/s3/oss/oss.go +++ b/pkg/common/db/s3/oss/oss.go @@ -16,8 +16,13 @@ package oss import ( "context" + "crypto/hmac" + "crypto/sha1" + "encoding/base64" + "encoding/json" "errors" "fmt" + "io" "net/http" "net/url" "reflect" @@ -45,6 +50,8 @@ const ( imageWebp = "webp" ) +const successCode = http.StatusOK + const ( videoSnapshotImagePng = "png" videoSnapshotImageJpg = "jpg" @@ -327,3 +334,45 @@ func (o *OSS) AccessURL(ctx context.Context, name string, expire time.Duration, params := getURLParams(*o.bucket.Client.Conn, rawParams) return getURL(o.um, o.bucket.BucketName, name, params).String(), nil } + +func (o *OSS) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) { + // https://help.aliyun.com/zh/oss/developer-reference/postobject?spm=a2c4g.11186623.0.0.1cb83cebkP55nn + expires := time.Now().Add(duration) + conditions := []any{ + map[string]string{"bucket": o.bucket.BucketName}, + map[string]string{"key": name}, + } + if size > 0 { + conditions = append(conditions, []any{"content-length-range", 0, size}) + } + policy := map[string]any{ + "expiration": expires.Format("2006-01-02T15:04:05.000Z"), + "conditions": conditions, + } + policyJson, err := json.Marshal(policy) + if err != nil { + return nil, err + } + policyStr := base64.StdEncoding.EncodeToString(policyJson) + h := hmac.New(sha1.New, []byte(o.credentials.GetAccessKeySecret())) + if _, err := io.WriteString(h, policyStr); err != nil { + return nil, err + } + fd := &s3.FormData{ + URL: o.bucketURL, + File: "file", + Expires: expires, + FormData: map[string]string{ + "key": name, + "policy": policyStr, + "OSSAccessKeyId": o.credentials.GetAccessKeyID(), + "success_action_status": strconv.Itoa(successCode), + "signature": base64.StdEncoding.EncodeToString(h.Sum(nil)), + }, + SuccessCodes: []int{successCode}, + } + if contentType != "" { + fd.FormData["x-oss-content-type"] = contentType + } + return fd, nil +} diff --git a/pkg/common/db/s3/s3.go b/pkg/common/db/s3/s3.go index afbe91955..0352004b5 100644 --- a/pkg/common/db/s3/s3.go +++ b/pkg/common/db/s3/s3.go @@ -74,6 +74,15 @@ type CopyObjectInfo struct { ETag string `json:"etag"` } +type FormData struct { + URL string `json:"url"` + File string `json:"file"` + Header http.Header `json:"header"` + FormData map[string]string `json:"form"` + Expires time.Time `json:"expires"` + SuccessCodes []int `json:"successActionStatus"` +} + type SignPart struct { PartNumber int `json:"partNumber"` URL string `json:"url"` @@ -152,4 +161,6 @@ type Interface interface { ListUploadedParts(ctx context.Context, uploadID string, name string, partNumberMarker int, maxParts int) (*ListUploadedPartsResult, error) AccessURL(ctx context.Context, name string, expire time.Duration, opt *AccessURLOption) (string, error) + + FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*FormData, error) } diff --git a/pkg/common/ginprometheus/ginprometheus.go b/pkg/common/ginprometheus/ginprometheus.go index f116fc23a..1ee8f8e34 100644 --- a/pkg/common/ginprometheus/ginprometheus.go +++ b/pkg/common/ginprometheus/ginprometheus.go @@ -432,7 +432,7 @@ func computeApproximateRequestSize(r *http.Request) int { } s += len(r.Host) - // r.Form and r.MultipartForm are assumed to be included in r.URL. + // r.FormData and r.MultipartForm are assumed to be included in r.URL. if r.ContentLength != -1 { s += int(r.ContentLength) From 222064542927b643ed00d6edd7cd0ec9114a84e9 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Tue, 26 Dec 2023 18:03:07 +0800 Subject: [PATCH 19/31] Update README.md (#1615) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index a2c5fc732..781db1217 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,10 @@ It's crafted in Golang and supports cross-platform deployment, ensuring a cohere ## :rocket: Quick Start +We support many platforms. Here are the addresses for quick experience on the web side: + +👉 **[OpenIM online web demo](https://web-enterprise.rentsoft.cn/)** + You can quickly learn OpenIM engineering solutions, all it takes is one simple command: ```bash From cff90a3099f8784c49f616fa1884e71505c305d5 Mon Sep 17 00:00:00 2001 From: Brabem <69128477+luhaoling@users.noreply.github.com> Date: Thu, 28 Dec 2023 00:29:44 +0800 Subject: [PATCH 20/31] fix: fix the searchNotificationAccout by userID or nickname (#1617) * feat: add notification API * fix: fix the script * fix: fix the error * fix: fix the searchNotificationAccount * fix: fix the protocol version * fix: fix the proto version --- go.mod | 4 +- go.sum | 4 +- internal/rpc/user/user.go | 62 +++++++++++++++++++--------- pkg/common/db/controller/user.go | 7 ++++ pkg/common/db/mgo/user.go | 4 ++ pkg/common/db/table/relation/user.go | 1 + 6 files changed, 60 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index a753cae51..1b80650c5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( firebase.google.com/go v3.13.0+incompatible - github.com/OpenIMSDK/protocol v0.0.39 + github.com/OpenIMSDK/protocol v0.0.40 github.com/OpenIMSDK/tools v0.0.21 github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/dtm-labs/rockscache v0.1.1 @@ -156,3 +156,5 @@ require ( golang.org/x/crypto v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) + +replace github.com/OpenIMSDK/protocol v0.0.40 => github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3 diff --git a/go.sum b/go.sum index a4609f6f2..09e4ce06b 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,6 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= -github.com/OpenIMSDK/protocol v0.0.39 h1:DfvFcNGBcfj2vtT7W3uw4U/ipnI7NecTzQdlSYGuQz8= -github.com/OpenIMSDK/protocol v0.0.39/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48= github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= @@ -227,6 +225,8 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w= github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w= +github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3 h1:HZz2U/M3T4x9SqPxWdrD9MZy7jxx7nS+nx/aRN9m3RQ= +github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index b5ad186a5..af9720590 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -17,6 +17,7 @@ package user import ( "context" "errors" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "math/rand" "strings" "time" @@ -57,10 +58,6 @@ type userServer struct { RegisterCenter registry.SvcDiscoveryRegistry } -func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) { - return nil, errs.ErrInternalServer.Wrap("not implemented") -} - func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { rdb, err := cache.NewRedis() if err != nil { @@ -466,26 +463,36 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser. return nil, err } + if req.NickName != "" { + users, err := s.UserDatabase.FindByNickname(ctx, req.NickName) + if err != nil { + return nil, err + } + resp := s.userModelToResp(users) + return resp, nil + } + + if req.UserID != "" { + users, err := s.UserDatabase.Find(ctx, []string{req.UserID}) + if err != nil { + return nil, err + } + resp := s.userModelToResp(users) + return resp, nil + } + _, users, err := s.UserDatabase.Page(ctx, req.Pagination) if err != nil { return nil, err } - var total int64 - accounts := make([]*pbuser.NotificationAccountInfo, 0, len(users)) - for _, v := range users { - if v.AppMangerLevel != constant.AppNotificationAdmin { - continue - } - temp := &pbuser.NotificationAccountInfo{ - UserID: v.UserID, - FaceURL: v.FaceURL, - NickName: v.Nickname, - } - accounts = append(accounts, temp) - total += 1 - } - return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}, nil + resp := s.userModelToResp(users) + return resp, nil +} + +func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) { + //TODO implement me + panic("implement me") } func (s *userServer) GetNotificationAccount(ctx context.Context, req *pbuser.GetNotificationAccountReq) (*pbuser.GetNotificationAccountResp, error) { @@ -517,3 +524,20 @@ func (s *userServer) genUserID() string { } return string(data) } + +func (s *userServer) userModelToResp(users []*relation.UserModel) *pbuser.SearchNotificationAccountResp { + accounts := make([]*pbuser.NotificationAccountInfo, 0) + var total int64 + for _, v := range users { + if v.AppMangerLevel == constant.AppNotificationAdmin || v.AppMangerLevel == constant.AppAdmin { + temp := &pbuser.NotificationAccountInfo{ + UserID: v.UserID, + FaceURL: v.FaceURL, + NickName: v.Nickname, + } + accounts = append(accounts, temp) + total += 1 + } + } + return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts} +} diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go index 2fafcf266..72bdf6b06 100644 --- a/pkg/common/db/controller/user.go +++ b/pkg/common/db/controller/user.go @@ -38,6 +38,8 @@ type UserDatabase interface { FindWithError(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) // Find Get the information of the specified user If the userID is not found, no error will be returned Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) + // Find userInfo By Nickname + FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error) // Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db Create(ctx context.Context, users []*relation.UserModel) (err error) // Update update (non-zero value) external guarantee userID exists @@ -133,6 +135,11 @@ func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*rel return u.cache.GetUsersInfo(ctx, userIDs) } +// Find userInfo By Nickname +func (u *userDatabase) FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error) { + return u.userDB.TakeByNickname(ctx, nickname) +} + // Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db. func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) { return u.tx.Transaction(ctx, func(ctx context.Context) error { diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go index 268d69ce3..0ca711ad8 100644 --- a/pkg/common/db/mgo/user.go +++ b/pkg/common/db/mgo/user.go @@ -65,6 +65,10 @@ func (u *UserMgo) Take(ctx context.Context, userID string) (user *relation.UserM return mgoutil.FindOne[*relation.UserModel](ctx, u.coll, bson.M{"user_id": userID}) } +func (u *UserMgo) TakeByNickname(ctx context.Context, nickname string) (user []*relation.UserModel, err error) { + return mgoutil.Find[*relation.UserModel](ctx, u.coll, bson.M{"nickname": nickname}) +} + func (u *UserMgo) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) { return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{}, pagination) } diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go index 213a6b774..8917ba55f 100644 --- a/pkg/common/db/table/relation/user.go +++ b/pkg/common/db/table/relation/user.go @@ -53,6 +53,7 @@ type UserModelInterface interface { UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) Find(ctx context.Context, userIDs []string) (users []*UserModel, err error) Take(ctx context.Context, userID string) (user *UserModel, err error) + TakeByNickname(ctx context.Context, nickname string) (user []*UserModel, err error) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error) Exist(ctx context.Context, userID string) (exist bool, err error) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error) From 53a3f475f382743e93c62e0473d3ef0affbbf215 Mon Sep 17 00:00:00 2001 From: Gordon <46924906+FGadvancer@users.noreply.github.com> Date: Thu, 28 Dec 2023 00:41:51 +0800 Subject: [PATCH 21/31] fix: add notifications for some notifications. (#1609) --- pkg/msgprocessor/options.go | 13 +------------ pkg/rpcclient/msg.go | 9 +++++++++ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pkg/msgprocessor/options.go b/pkg/msgprocessor/options.go index c17c7cb05..ea383a1af 100644 --- a/pkg/msgprocessor/options.go +++ b/pkg/msgprocessor/options.go @@ -30,10 +30,9 @@ func NewOptions(opts ...OptionsOpt) Options { options[constant.IsOfflinePush] = false options[constant.IsUnreadCount] = false options[constant.IsConversationUpdate] = false - options[constant.IsSenderSync] = false + options[constant.IsSenderSync] = true options[constant.IsNotPrivate] = false options[constant.IsSenderConversationUpdate] = false - options[constant.IsSenderNotificationPush] = false options[constant.IsReactionFromCache] = false for _, opt := range opts { opt(options) @@ -114,12 +113,6 @@ func WithSenderConversationUpdate() OptionsOpt { } } -func WithSenderNotificationPush() OptionsOpt { - return func(options Options) { - options[constant.IsSenderNotificationPush] = true - } -} - func WithReactionFromCache() OptionsOpt { return func(options Options) { options[constant.IsReactionFromCache] = true @@ -174,10 +167,6 @@ func (o Options) IsSenderConversationUpdate() bool { return o.Is(constant.IsSenderConversationUpdate) } -func (o Options) IsSenderNotificationPush() bool { - return o.Is(constant.IsSenderNotificationPush) -} - func (o Options) IsReactionFromCache() bool { return o.Is(constant.IsReactionFromCache) } diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go index 3b09b5062..50e1cd4a1 100644 --- a/pkg/rpcclient/msg.go +++ b/pkg/rpcclient/msg.go @@ -256,6 +256,7 @@ func (s *NotificationSender) NotificationWithSesstionType(ctx context.Context, s optionsConfig.ReliabilityLevel = constant.UnreliableNotification } options := config.GetOptionsByNotification(optionsConfig) + s.SetOptionsByContentType(ctx, options, contentType) msg.Options = options offlineInfo.Title = title offlineInfo.Desc = desc @@ -274,3 +275,11 @@ func (s *NotificationSender) NotificationWithSesstionType(ctx context.Context, s func (s *NotificationSender) Notification(ctx context.Context, sendID, recvID string, contentType int32, m proto.Message, opts ...NotificationOptions) error { return s.NotificationWithSesstionType(ctx, sendID, recvID, contentType, s.sessionTypeConf[contentType], m, opts...) } + +func (s *NotificationSender) SetOptionsByContentType(_ context.Context, options map[string]bool, contentType int32) { + switch contentType { + case constant.UserStatusChangeNotification: + options[constant.IsSenderSync] = false + default: + } +} From b90b8a1a558603107b65b51b1742c2ce944def0f Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Thu, 28 Dec 2023 14:17:27 +0800 Subject: [PATCH 22/31] fix: fix openim zk env set (#1623) * fix: fix openim zk env set Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: fix openim zk env set Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --------- Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --- pkg/common/db/cache/init_redis.go | 10 +++++++++- .../discoveryregister_test.go | 3 ++- .../discoveryregister/zookeeper/zookeeper.go | 14 +++++++++++--- pkg/common/kafka/producer.go | 13 ++++++------- pkg/common/kafka/util.go | 19 +++++++++++++++++++ tools/component/component_test.go | 12 ------------ 6 files changed, 47 insertions(+), 24 deletions(-) diff --git a/pkg/common/db/cache/init_redis.go b/pkg/common/db/cache/init_redis.go index 63d2f5707..1308e9649 100644 --- a/pkg/common/db/cache/init_redis.go +++ b/pkg/common/db/cache/init_redis.go @@ -87,7 +87,15 @@ func NewRedis() (redis.UniversalClient, error) { // overrideConfigFromEnv overrides configuration fields with environment variables if present. func overrideConfigFromEnv() { if envAddr := os.Getenv("REDIS_ADDRESS"); envAddr != "" { - config.Config.Redis.Address = strings.Split(envAddr, ",") // Assuming addresses are comma-separated + if envPort := os.Getenv("REDIS_PORT"); envPort != "" { + addresses := strings.Split(envAddr, ",") + for i, addr := range addresses { + addresses[i] = addr + ":" + envPort + } + config.Config.Redis.Address = addresses + } else { + config.Config.Redis.Address = strings.Split(envAddr, ",") + } } if envUser := os.Getenv("REDIS_USERNAME"); envUser != "" { config.Config.Redis.Username = envUser diff --git a/pkg/common/discoveryregister/discoveryregister_test.go b/pkg/common/discoveryregister/discoveryregister_test.go index d4a634b91..d83da1285 100644 --- a/pkg/common/discoveryregister/discoveryregister_test.go +++ b/pkg/common/discoveryregister/discoveryregister_test.go @@ -24,7 +24,8 @@ import ( func setupTestEnvironment() { os.Setenv("ZOOKEEPER_SCHEMA", "openim") - os.Setenv("ZOOKEEPER_ADDRESS", "172.28.0.1:12181") + os.Setenv("ZOOKEEPER_ADDRESS", "172.28.0.1") + os.Setenv("ZOOKEEPER_PORT", "12181") os.Setenv("ZOOKEEPER_USERNAME", "") os.Setenv("ZOOKEEPER_PASSWORD", "") } diff --git a/pkg/common/discoveryregister/zookeeper/zookeeper.go b/pkg/common/discoveryregister/zookeeper/zookeeper.go index a4edffc43..db1a5c6c4 100644 --- a/pkg/common/discoveryregister/zookeeper/zookeeper.go +++ b/pkg/common/discoveryregister/zookeeper/zookeeper.go @@ -52,10 +52,18 @@ func getEnv(key, fallback string) string { return fallback } -// getZkAddrFromEnv returns the value of an environment variable if it exists, otherwise it returns the fallback value. +// getZkAddrFromEnv returns the Zookeeper addresses combined from the ZOOKEEPER_ADDRESS and ZOOKEEPER_PORT environment variables. +// If the environment variables are not set, it returns the fallback value. func getZkAddrFromEnv(fallback []string) []string { - if value, exists := os.LookupEnv("ZOOKEEPER_ADDRESS"); exists { - return strings.Split(value, ",") + address, addrExists := os.LookupEnv("ZOOKEEPER_ADDRESS") + port, portExists := os.LookupEnv("ZOOKEEPER_PORT") + + if addrExists && portExists { + addresses := strings.Split(address, ",") + for i, addr := range addresses { + addresses[i] = addr + ":" + port + } + return addresses } return fallback } diff --git a/pkg/common/kafka/producer.go b/pkg/common/kafka/producer.go index 9a06809b7..06b1e2b4c 100644 --- a/pkg/common/kafka/producer.go +++ b/pkg/common/kafka/producer.go @@ -31,15 +31,14 @@ import ( "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) -const ( - maxRetry = 10 // Maximum number of retries for producer creation -) +const maxRetry = 10 // number of retries -var errEmptyMsg = errors.New("binary msg is empty") +var errEmptyMsg = errors.New("kafka binary msg is empty") +// Producer represents a Kafka producer. type Producer struct { - topic string addr []string + topic string config *sarama.Config producer sarama.SyncProducer } @@ -68,7 +67,7 @@ func NewKafkaProducer(addr []string, topic string) *Producer { // Get Kafka configuration from environment variables or fallback to config file kafkaUsername := getEnvOrConfig("KAFKA_USERNAME", config.Config.Kafka.Username) kafkaPassword := getEnvOrConfig("KAFKA_PASSWORD", config.Config.Kafka.Password) - kafkaAddr := getEnvOrConfig("KAFKA_ADDRESS", addr[0]) // Assuming addr[0] contains address from config + kafkaAddr := getKafkaAddrFromEnv(addr) // Updated to use the new function // Configure SASL authentication if credentials are provided if kafkaUsername != "" && kafkaPassword != "" { @@ -78,7 +77,7 @@ func NewKafkaProducer(addr []string, topic string) *Producer { } // Set the Kafka address - p.addr = []string{kafkaAddr} + p.addr = kafkaAddr // Set up TLS configuration (if required) SetupTLSConfig(p.config) diff --git a/pkg/common/kafka/util.go b/pkg/common/kafka/util.go index da0c5349b..f318ecf73 100644 --- a/pkg/common/kafka/util.go +++ b/pkg/common/kafka/util.go @@ -15,7 +15,9 @@ package kafka import ( + "fmt" "os" + "strings" "github.com/IBM/sarama" @@ -44,3 +46,20 @@ func getEnvOrConfig(envName string, configValue string) string { } return configValue } + +// getKafkaAddrFromEnv returns the Kafka addresses combined from the KAFKA_ADDRESS and KAFKA_PORT environment variables. +// If the environment variables are not set, it returns the fallback value. +func getKafkaAddrFromEnv(fallback []string) []string { + envAddr := os.Getenv("KAFKA_ADDRESS") + envPort := os.Getenv("KAFKA_PORT") + + if envAddr != "" && envPort != "" { + addresses := strings.Split(envAddr, ",") + for i, addr := range addresses { + addresses[i] = fmt.Sprintf("%s:%s", addr, envPort) + } + return addresses + } + + return fallback +} diff --git a/tools/component/component_test.go b/tools/component/component_test.go index 08ea0fda8..4488c029e 100644 --- a/tools/component/component_test.go +++ b/tools/component/component_test.go @@ -21,22 +21,10 @@ import ( "time" "github.com/redis/go-redis/v9" - "github.com/stretchr/testify/assert" "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) -func TestCheckMysql(t *testing.T) { - err := mockInitCfg() - assert.NoError(t, err, "Initialization should not produce errors") - - err = checkMysql() - if err != nil { - // You might expect an error if MySQL isn't running locally with the mock credentials. - t.Logf("Expected error due to mock configuration: %v", err) - } -} - // Mock for initCfg for testing purpose func mockInitCfg() error { config.Config.Mysql.Username = "root" From 998d4a3504fd30623e75ec6e9590050749104483 Mon Sep 17 00:00:00 2001 From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:45:27 +0800 Subject: [PATCH 23/31] Add updates friend, set user ex (#1592) * update set pin friends * update set pin friends * update set pin friends * update set pin friends * update set pin friends * update set pin friends * fix bugs * fix bugs * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * Update go.mod * Update friend.go * debug * debug * debug * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * I cannot solve todo in test.sh * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * Update go.mod * fix group notification * fix group notification * update openimsdk tools * update openim server remove duplicate code * update openim server remove duplicate code * update user command get * update user command get * update response of callback response error * update black ex * update join group ex * update user pb2map * update go sum * update go sum * update updateUserInfoEx * update updateUserInfoEx * update updateUserInfoEx add callback functions * fix dismiss group function * fix dismiss group function * fix dismiss group function * fix dismiss group function * update pin friend to update friend * fix go mod * fix err golangci-lint * fix UserPb2DBMap * update comments, update go.mod check for register username * update comments, update go.mod check for register username * update comments, update go.mod check for register username * update comments, update go.mod check for register username * fix callback * fix go.mod * fix debug * fix bugs * update notification * update notification * update notification * update notification * update notification * update notification * update notification * update notification --------- Co-authored-by: Xinwei Xiong <3293172751@qq.com> --- config/templates/config.yaml.template | 8 ++++ go.sum | 2 + internal/api/friend.go | 3 ++ internal/api/msg.go | 26 +++++++++++ internal/api/route.go | 3 +- internal/api/user.go | 4 +- internal/msggateway/client.go | 4 ++ internal/rpc/friend/friend.go | 36 +++++++++------- internal/rpc/msg/callback.go | 2 +- internal/rpc/user/callback.go | 36 +++++++++++++++- internal/rpc/user/user.go | 39 ++++++++++++++--- pkg/callbackstruct/constant.go | 2 + pkg/callbackstruct/user.go | 30 ++++++++++++- pkg/common/config/config.go | 2 + pkg/common/convert/user.go | 21 ++++++++- pkg/common/db/controller/friend.go | 60 ++++++++++++++++++++------ pkg/common/db/mgo/friend.go | 30 +++++++++++++ pkg/common/db/table/relation/friend.go | 4 ++ pkg/rpcclient/msg.go | 2 + pkg/rpcclient/notification/friend.go | 7 ++- tools/component/component.go | 22 +++++++--- 21 files changed, 297 insertions(+), 46 deletions(-) diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template index fd51a2e31..89f11f359 100644 --- a/config/templates/config.yaml.template +++ b/config/templates/config.yaml.template @@ -312,6 +312,14 @@ callback: enable: false timeout: 5 failedContinue: true + beforeUpdateUserInfoEx: + enable: false + timeout: 5 + failedContinue: true + afterUpdateUserInfoEx: + enable: false + timeout: 5 + failedContinue: true afterSendSingleMsg: enable: false timeout: 5 diff --git a/go.sum b/go.sum index 09e4ce06b..881000381 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= +github.com/OpenIMSDK/protocol v0.0.40 h1:1/Oij6RSAaePCPrWGwp9Cyz976/8Uxr94hM5M5FXzlg= +github.com/OpenIMSDK/protocol v0.0.40/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48= github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= diff --git a/internal/api/friend.go b/internal/api/friend.go index 23f337a9f..7dc898a02 100644 --- a/internal/api/friend.go +++ b/internal/api/friend.go @@ -92,3 +92,6 @@ func (o *FriendApi) GetFriendIDs(c *gin.Context) { func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) { a2r.Call(friend.FriendClient.GetSpecifiedFriendsInfo, o.Client, c) } +func (o *FriendApi) UpdateFriends(c *gin.Context) { + a2r.Call(friend.FriendClient.UpdateFriends, o.Client, c) +} diff --git a/internal/api/msg.go b/internal/api/msg.go index b6bfcebb6..8346ad860 100644 --- a/internal/api/msg.go +++ b/internal/api/msg.go @@ -172,6 +172,7 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM if err = m.userRpcClient.GetNotificationByID(c, req.SendID); err != nil { return nil, err } + default: return nil, errs.ErrArgs.WithDetail("not support err contentType") } @@ -185,38 +186,63 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM return m.newUserSendMsgReq(c, &req), nil } +// SendMessage handles the sending of a message. It's an HTTP handler function to be used with Gin framework. func (m *MessageApi) SendMessage(c *gin.Context) { + // Initialize a request struct for sending a message. req := apistruct.SendMsgReq{} + + // Bind the JSON request body to the request struct. if err := c.BindJSON(&req); err != nil { + // Respond with an error if request body binding fails. apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap()) return } + + // Check if the user has the app manager role. if !authverify.IsAppManagerUid(c) { + // Respond with a permission error if the user is not an app manager. apiresp.GinError(c, errs.ErrNoPermission.Wrap("only app manager can send message")) return } + + // Prepare the message request with additional required data. sendMsgReq, err := m.getSendMsgReq(c, req.SendMsg) if err != nil { + // Log and respond with an error if preparation fails. log.ZError(c, "decodeData failed", err) apiresp.GinError(c, err) return } + + // Set the receiver ID in the message data. sendMsgReq.MsgData.RecvID = req.RecvID + + // Declare a variable to store the message sending status. var status int + + // Attempt to send the message using the client. respPb, err := m.Client.SendMsg(c, sendMsgReq) if err != nil { + // Set the status to failed and respond with an error if sending fails. status = constant.MsgSendFailed log.ZError(c, "send message err", err) apiresp.GinError(c, err) return } + + // Set the status to successful if the message is sent. status = constant.MsgSendSuccessed + + // Attempt to update the message sending status in the system. _, err = m.Client.SetSendMsgStatus(c, &msg.SetSendMsgStatusReq{ Status: int32(status), }) if err != nil { + // Log the error if updating the status fails. log.ZError(c, "SetSendMsgStatus failed", err) } + + // Respond with a success message and the response payload. apiresp.GinSuccess(c, respPb) } diff --git a/internal/api/route.go b/internal/api/route.go index 8fb372587..766912d45 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -67,6 +67,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive { userRouterGroup.POST("/user_register", u.UserRegister) userRouterGroup.POST("/update_user_info", ParseToken, u.UpdateUserInfo) + userRouterGroup.POST("/update_user_info_ex", ParseToken, u.UpdateUserInfoEx) userRouterGroup.POST("/set_global_msg_recv_opt", ParseToken, u.SetGlobalRecvMessageOpt) userRouterGroup.POST("/get_users_info", ParseToken, u.GetUsersPublicInfo) userRouterGroup.POST("/get_all_users_uid", ParseToken, u.GetAllUsersID) @@ -107,7 +108,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive friendRouterGroup.POST("/is_friend", f.IsFriend) friendRouterGroup.POST("/get_friend_id", f.GetFriendIDs) friendRouterGroup.POST("/get_specified_friends_info", f.GetSpecifiedFriendsInfo) - //friendRouterGroup.POST("/set_pin_friend", f.SetPinFriends) + friendRouterGroup.POST("/update_friends", f.UpdateFriends) } g := NewGroupApi(*groupRpc) groupRouterGroup := r.Group("/group", ParseToken) diff --git a/internal/api/user.go b/internal/api/user.go index cf68fb422..5f0e23631 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -41,7 +41,9 @@ func (u *UserApi) UserRegister(c *gin.Context) { func (u *UserApi) UpdateUserInfo(c *gin.Context) { a2r.Call(user.UserClient.UpdateUserInfo, u.Client, c) } - +func (u *UserApi) UpdateUserInfoEx(c *gin.Context) { + a2r.Call(user.UserClient.UpdateUserInfoEx, u.Client, c) +} func (u *UserApi) SetGlobalRecvMessageOpt(c *gin.Context) { a2r.Call(user.UserClient.SetGlobalRecvMessageOpt, u.Client, c) } diff --git a/internal/msggateway/client.go b/internal/msggateway/client.go index 69b49d81a..43047fd73 100644 --- a/internal/msggateway/client.go +++ b/internal/msggateway/client.go @@ -87,6 +87,7 @@ func newClient(ctx *UserConnContext, conn LongConn, isCompress bool) *Client { } } +// ResetClient updates the client's state with new connection and context information. func (c *Client) ResetClient( ctx *UserConnContext, conn LongConn, @@ -108,11 +109,13 @@ func (c *Client) ResetClient( c.token = token } +// pingHandler handles ping messages and sends pong responses. func (c *Client) pingHandler(_ string) error { _ = c.conn.SetReadDeadline(pongWait) return c.writePongMsg() } +// readMessage continuously reads messages from the connection. func (c *Client) readMessage() { defer func() { if r := recover(); r != nil { @@ -164,6 +167,7 @@ func (c *Client) readMessage() { } } +// handleMessage processes a single message received by the client. func (c *Client) handleMessage(message []byte) error { if c.IsCompress { var err error diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index c40b566f3..c53cb88f5 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -53,10 +53,6 @@ type friendServer struct { RegisterCenter registry.SvcDiscoveryRegistry } -func (s *friendServer) UpdateFriends(ctx context.Context, req *pbfriend.UpdateFriendsReq) (*pbfriend.UpdateFriendsResp, error) { - return nil, errs.ErrInternalServer.Wrap("not implemented") -} - func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { // Initialize MongoDB mongo, err := unrelation.NewMongo() @@ -440,7 +436,7 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien } return resp, nil } -func (s *friendServer) PinFriends( +func (s *friendServer) UpdateFriends( ctx context.Context, req *pbfriend.UpdateFriendsReq, ) (*pbfriend.UpdateFriendsResp, error) { @@ -450,25 +446,35 @@ func (s *friendServer) PinFriends( if utils.Duplicate(req.FriendUserIDs) { return nil, errs.ErrArgs.Wrap("friendIDList repeated") } - var isPinned bool - if req.IsPinned != nil { - isPinned = req.IsPinned.Value - } else { - return nil, errs.ErrArgs.Wrap("isPinned is nil") - } - //check whther in friend list + _, err := s.friendDatabase.FindFriendsWithError(ctx, req.OwnerUserID, req.FriendUserIDs) if err != nil { return nil, err } - //set friendslist friend pin status to isPinned for _, friendID := range req.FriendUserIDs { - if err := s.friendDatabase.UpdateFriendPinStatus(ctx, req.OwnerUserID, friendID, isPinned); err != nil { - return nil, err + if req.IsPinned != nil { + if err = s.friendDatabase.UpdateFriendPinStatus(ctx, req.OwnerUserID, friendID, req.IsPinned.Value); err != nil { + return nil, err + } + } + if req.Remark != nil { + if err = s.friendDatabase.UpdateFriendRemark(ctx, req.OwnerUserID, friendID, req.Remark.Value); err != nil { + return nil, err + } + } + if req.Ex != nil { + if err = s.friendDatabase.UpdateFriendEx(ctx, req.OwnerUserID, friendID, req.Ex.Value); err != nil { + return nil, err + } } } resp := &pbfriend.UpdateFriendsResp{} + + err = s.notificationSender.FriendsInfoUpdateNotification(ctx, req.OwnerUserID, req.FriendUserIDs) + if err != nil { + return nil, errs.Wrap(err, "FriendsInfoUpdateNotification Error") + } return resp, nil } diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go index 3a8587ea3..5d192fb87 100644 --- a/internal/rpc/msg/callback.go +++ b/internal/rpc/msg/callback.go @@ -100,7 +100,7 @@ func callbackAfterSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) err } func callbackBeforeSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) error { - if !config.Config.Callback.CallbackBeforeSendSingleMsg.Enable { + if !config.Config.Callback.CallbackBeforeSendGroupMsg.Enable { return nil } req := &cbapi.CallbackBeforeSendGroupMsgReq{ diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go index 7d865af5f..9e02eb130 100644 --- a/internal/rpc/user/callback.go +++ b/internal/rpc/user/callback.go @@ -44,7 +44,6 @@ func CallbackBeforeUpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserInf utils.NotNilReplace(&req.UserInfo.Nickname, resp.Nickname) return nil } - func CallbackAfterUpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserInfoReq) error { if !config.Config.Callback.CallbackAfterUpdateUserInfo.Enable { return nil @@ -61,6 +60,41 @@ func CallbackAfterUpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserInfo } return nil } +func CallbackBeforeUpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) error { + if !config.Config.Callback.CallbackBeforeUpdateUserInfoEx.Enable { + return nil + } + cbReq := &cbapi.CallbackBeforeUpdateUserInfoExReq{ + CallbackCommand: cbapi.CallbackBeforeUpdateUserInfoExCommand, + UserID: req.UserInfo.UserID, + FaceURL: &req.UserInfo.FaceURL, + Nickname: &req.UserInfo.Nickname, + } + resp := &cbapi.CallbackBeforeUpdateUserInfoExResp{} + if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeUpdateUserInfoEx); err != nil { + return err + } + utils.NotNilReplace(&req.UserInfo.FaceURL, resp.FaceURL) + utils.NotNilReplace(req.UserInfo.Ex, resp.Ex) + utils.NotNilReplace(&req.UserInfo.Nickname, resp.Nickname) + return nil +} +func CallbackAfterUpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) error { + if !config.Config.Callback.CallbackAfterUpdateUserInfoEx.Enable { + return nil + } + cbReq := &cbapi.CallbackAfterUpdateUserInfoExReq{ + CallbackCommand: cbapi.CallbackAfterUpdateUserInfoExCommand, + UserID: req.UserInfo.UserID, + FaceURL: req.UserInfo.FaceURL, + Nickname: req.UserInfo.Nickname, + } + resp := &cbapi.CallbackAfterUpdateUserInfoExResp{} + if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeUpdateUserInfoEx); err != nil { + return err + } + return nil +} func CallbackBeforeUserRegister(ctx context.Context, req *pbuser.UserRegisterReq) error { if !config.Config.Callback.CallbackBeforeUserRegister.Enable { diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index af9720590..fdfd81ed2 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -149,7 +149,41 @@ func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserI } return resp, nil } +func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (resp *pbuser.UpdateUserInfoExResp, err error) { + resp = &pbuser.UpdateUserInfoExResp{} + err = authverify.CheckAccessV3(ctx, req.UserInfo.UserID) + if err != nil { + return nil, err + } + if err = CallbackBeforeUpdateUserInfoEx(ctx, req); err != nil { + return nil, err + } + data := convert.UserPb2DBMapEx(req.UserInfo) + if err = s.UpdateByMap(ctx, req.UserInfo.UserID, data); err != nil { + return nil, err + } + _ = s.friendNotificationSender.UserInfoUpdatedNotification(ctx, req.UserInfo.UserID) + friends, err := s.friendRpcClient.GetFriendIDs(ctx, req.UserInfo.UserID) + if err != nil { + return nil, err + } + if req.UserInfo.Nickname != "" || req.UserInfo.FaceURL != "" { + if err := s.groupRpcClient.NotificationUserInfoUpdate(ctx, req.UserInfo.UserID); err != nil { + log.ZError(ctx, "NotificationUserInfoUpdate", err) + } + } + for _, friendID := range friends { + s.friendNotificationSender.FriendInfoUpdatedNotification(ctx, req.UserInfo.UserID, friendID) + } + if err := CallbackAfterUpdateUserInfoEx(ctx, req); err != nil { + return nil, err + } + if err := s.groupRpcClient.NotificationUserInfoUpdate(ctx, req.UserInfo.UserID); err != nil { + log.ZError(ctx, "NotificationUserInfoUpdate", err, "userID", req.UserInfo.UserID) + } + return resp, nil +} func (s *userServer) SetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.SetGlobalRecvMessageOptReq) (resp *pbuser.SetGlobalRecvMessageOptResp, err error) { resp = &pbuser.SetGlobalRecvMessageOptResp{} if _, err := s.FindWithError(ctx, []string{req.UserID}); err != nil { @@ -490,11 +524,6 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser. return resp, nil } -func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) { - //TODO implement me - panic("implement me") -} - func (s *userServer) GetNotificationAccount(ctx context.Context, req *pbuser.GetNotificationAccountReq) (*pbuser.GetNotificationAccountResp, error) { if req.UserID == "" { return nil, errs.ErrArgs.Wrap("userID is empty") diff --git a/pkg/callbackstruct/constant.go b/pkg/callbackstruct/constant.go index 0a03a1ef1..cda98af16 100644 --- a/pkg/callbackstruct/constant.go +++ b/pkg/callbackstruct/constant.go @@ -37,6 +37,8 @@ const ( CallbackGroupMsgReadCommand = "callbackGroupMsgReadCommand" CallbackMsgModifyCommand = "callbackMsgModifyCommand" CallbackAfterUpdateUserInfoCommand = "callbackAfterUpdateUserInfoCommand" + CallbackAfterUpdateUserInfoExCommand = "callbackAfterUpdateUserInfoExCommand" + CallbackBeforeUpdateUserInfoExCommand = "callbackBeforeUpdateUserInfoExCommand" CallbackBeforeUserRegisterCommand = "callbackBeforeUserRegisterCommand" CallbackAfterUserRegisterCommand = "callbackAfterUserRegisterCommand" CallbackTransferGroupOwnerAfter = "callbackTransferGroupOwnerAfter" diff --git a/pkg/callbackstruct/user.go b/pkg/callbackstruct/user.go index f35cff554..bfb69bd38 100644 --- a/pkg/callbackstruct/user.go +++ b/pkg/callbackstruct/user.go @@ -14,7 +14,10 @@ package callbackstruct -import "github.com/OpenIMSDK/protocol/sdkws" +import ( + "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/protocol/wrapperspb" +) type CallbackBeforeUpdateUserInfoReq struct { CallbackCommand `json:"callbackCommand"` @@ -41,6 +44,31 @@ type CallbackAfterUpdateUserInfoResp struct { CommonCallbackResp } +type CallbackBeforeUpdateUserInfoExReq struct { + CallbackCommand `json:"callbackCommand"` + UserID string `json:"userID"` + Nickname *string `json:"nickName"` + FaceURL *string `json:"faceURL"` + Ex *wrapperspb.StringValue `json:"ex"` +} +type CallbackBeforeUpdateUserInfoExResp struct { + CommonCallbackResp + Nickname *string `json:"nickName"` + FaceURL *string `json:"faceURL"` + Ex *wrapperspb.StringValue `json:"ex"` +} + +type CallbackAfterUpdateUserInfoExReq struct { + CallbackCommand `json:"callbackCommand"` + UserID string `json:"userID"` + Nickname string `json:"nickName"` + FaceURL string `json:"faceURL"` + Ex *wrapperspb.StringValue `json:"ex"` +} +type CallbackAfterUpdateUserInfoExResp struct { + CommonCallbackResp +} + type CallbackBeforeUserRegisterReq struct { CallbackCommand `json:"callbackCommand"` Secret string `json:"secret"` diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 707601234..ea26ca677 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -282,6 +282,8 @@ type configStruct struct { CallbackBeforeSetFriendRemark CallBackConfig `yaml:"callbackBeforeSetFriendRemark"` CallbackAfterSetFriendRemark CallBackConfig `yaml:"callbackAfterSetFriendRemark"` CallbackBeforeUpdateUserInfo CallBackConfig `yaml:"beforeUpdateUserInfo"` + CallbackBeforeUpdateUserInfoEx CallBackConfig `yaml:"beforeUpdateUserInfoEx"` + CallbackAfterUpdateUserInfoEx CallBackConfig `yaml:"afterUpdateUserInfoEx"` CallbackBeforeUserRegister CallBackConfig `yaml:"beforeUserRegister"` CallbackAfterUpdateUserInfo CallBackConfig `yaml:"updateUserInfo"` CallbackAfterUserRegister CallBackConfig `yaml:"afterUserRegister"` diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go index 72041a790..6d43595bc 100644 --- a/pkg/common/convert/user.go +++ b/pkg/common/convert/user.go @@ -64,7 +64,7 @@ func UserPb2DBMap(user *sdkws.UserInfo) map[string]any { "global_recv_msg_opt": user.GlobalRecvMsgOpt, } for key, value := range fields { - if v, ok := value.(string); ok { + if v, ok := value.(string); ok && v != "" { val[key] = v } else if v, ok := value.(int32); ok && v != 0 { val[key] = v @@ -72,3 +72,22 @@ func UserPb2DBMap(user *sdkws.UserInfo) map[string]any { } return val } +func UserPb2DBMapEx(user *sdkws.UserInfoWithEx) map[string]any { + if user == nil { + return nil + } + val := make(map[string]any) + + // Map fields from UserInfoWithEx to val + val["nickname"] = user.Nickname + val["face_url"] = user.FaceURL + + if user.Ex != nil { + val["ex"] = user.Ex.Value + } + if user.GlobalRecvMsgOpt != 0 { + val["global_recv_msg_opt"] = user.GlobalRecvMsgOpt + } + + return val +} diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go index 34ce22295..924a179ba 100644 --- a/pkg/common/db/controller/friend.go +++ b/pkg/common/db/controller/friend.go @@ -32,33 +32,57 @@ import ( ) type FriendDatabase interface { - // 检查user2是否在user1的好友列表中(inUser1Friends==true) 检查user1是否在user2的好友列表中(inUser2Friends==true) + // CheckIn checks if user2 is in user1's friend list (inUser1Friends==true) and if user1 is in user2's friend list (inUser2Friends==true) CheckIn(ctx context.Context, user1, user2 string) (inUser1Friends bool, inUser2Friends bool, err error) - // 增加或者更新好友申请 + + // AddFriendRequest adds or updates a friend request AddFriendRequest(ctx context.Context, fromUserID, toUserID string, reqMsg string, ex string) (err error) - // 先判断是否在好友表,如果在则不插入 + + // BecomeFriends first checks if the users are already in the friends table; if not, it inserts them as friends BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error) - // 拒绝好友申请 + + // RefuseFriendRequest refuses a friend request RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) - // 同意好友申请 + + // AgreeFriendRequest accepts a friend request AgreeFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) - // 删除好友 + + // Delete removes a friend or friends from the owner's friend list Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error) - // 更新好友备注 + + // UpdateRemark updates the remark for a friend UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error) - // 获取ownerUserID的好友列表 + + // PageOwnerFriends retrieves the friend list of ownerUserID with pagination PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) - // friendUserID在哪些人的好友列表中 + + // PageInWhoseFriends finds the users who have friendUserID in their friend list with pagination PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) - // 获取我发出去的好友申请 + + // PageFriendRequestFromMe retrieves the friend requests sent by the user with pagination PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) - // 获取我收到的的好友申请 + + // PageFriendRequestToMe retrieves the friend requests received by the user with pagination PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) - // 获取某人指定好友的信息 + + // FindFriendsWithError fetches specified friends of a user and returns an error if any do not exist FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error) + + // FindFriendUserIDs retrieves the friend IDs of a user FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) + + // FindBothFriendRequests finds friend requests sent and received FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) + + // UpdateFriendPinStatus updates the pinned status of a friend UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) + + // UpdateFriendRemark updates the remark for a friend + UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) + + // UpdateFriendEx updates the 'ex' field for a friend + UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) + } type friendDatabase struct { @@ -305,3 +329,15 @@ func (f *friendDatabase) UpdateFriendPinStatus(ctx context.Context, ownerUserID } return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx) } +func (f *friendDatabase) UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) { + if err := f.friend.UpdateFriendRemark(ctx, ownerUserID, friendUserID, remark); err != nil { + return err + } + return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx) +} +func (f *friendDatabase) UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) { + if err := f.friend.UpdateFriendEx(ctx, ownerUserID, friendUserID, ex); err != nil { + return err + } + return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx) +} diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go index 667098819..72289181b 100644 --- a/pkg/common/db/mgo/friend.go +++ b/pkg/common/db/mgo/friend.go @@ -160,3 +160,33 @@ func (f *FriendMgo) UpdatePinStatus(ctx context.Context, ownerUserID string, fri return nil } +func (f *FriendMgo) UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) { + + filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID} + // Create an update operation to set the "is_pinned" field to isPinned for all documents. + update := bson.M{"$set": bson.M{"remark": remark}} + + // Perform the update operation for all documents in the collection. + _, err = f.coll.UpdateMany(ctx, filter, update) + + if err != nil { + return errs.Wrap(err, "update remark error") + } + + return nil +} +func (f *FriendMgo) UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) { + + filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID} + // Create an update operation to set the "is_pinned" field to isPinned for all documents. + update := bson.M{"$set": bson.M{"ex": ex}} + + // Perform the update operation for all documents in the collection. + _, err = f.coll.UpdateMany(ctx, filter, update) + + if err != nil { + return errs.Wrap(err, "update ex error") + } + + return nil +} diff --git a/pkg/common/db/table/relation/friend.go b/pkg/common/db/table/relation/friend.go index 4f85998f4..cc337701d 100644 --- a/pkg/common/db/table/relation/friend.go +++ b/pkg/common/db/table/relation/friend.go @@ -59,4 +59,8 @@ type FriendModelInterface interface { FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) // UpdatePinStatus update friend's pin status UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) + // UpdateFriendRemark update friend's remark + UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) + // UpdateFriendEx update friend's ex + UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) } diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go index 50e1cd4a1..03769dc74 100644 --- a/pkg/rpcclient/msg.go +++ b/pkg/rpcclient/msg.go @@ -68,6 +68,7 @@ func newContentTypeConf() map[int32]config.NotificationConf { constant.BlackAddedNotification: config.Config.Notification.BlackAdded, constant.BlackDeletedNotification: config.Config.Notification.BlackDeleted, constant.FriendInfoUpdatedNotification: config.Config.Notification.FriendInfoUpdated, + constant.FriendsInfoUpdateNotification: config.Config.Notification.FriendInfoUpdated, //use the same FriendInfoUpdated // conversation constant.ConversationChangeNotification: config.Config.Notification.ConversationChanged, constant.ConversationUnreadNotification: config.Config.Notification.ConversationChanged, @@ -115,6 +116,7 @@ func newSessionTypeConf() map[int32]int32 { constant.BlackAddedNotification: constant.SingleChatType, constant.BlackDeletedNotification: constant.SingleChatType, constant.FriendInfoUpdatedNotification: constant.SingleChatType, + constant.FriendsInfoUpdateNotification: constant.SingleChatType, // conversation constant.ConversationChangeNotification: constant.SingleChatType, constant.ConversationUnreadNotification: constant.SingleChatType, diff --git a/pkg/rpcclient/notification/friend.go b/pkg/rpcclient/notification/friend.go index b061a24ae..00759b1b2 100644 --- a/pkg/rpcclient/notification/friend.go +++ b/pkg/rpcclient/notification/friend.go @@ -196,7 +196,12 @@ func (f *FriendNotificationSender) FriendRemarkSetNotification(ctx context.Conte tips.FromToUserID.ToUserID = toUserID return f.Notification(ctx, fromUserID, toUserID, constant.FriendRemarkSetNotification, &tips) } - +func (f *FriendNotificationSender) FriendsInfoUpdateNotification(ctx context.Context, toUserID string, friendIDs []string) error { + tips := sdkws.FriendsInfoUpdateTips{} + tips.FromToUserID.ToUserID = toUserID + tips.FriendIDs = friendIDs + return f.Notification(ctx, toUserID, toUserID, constant.FriendsInfoUpdateNotification, &tips) +} func (f *FriendNotificationSender) BlackAddedNotification(ctx context.Context, req *pbfriend.AddBlackReq) error { tips := sdkws.BlackAddedTips{FromToUserID: &sdkws.FromToUserID{}} tips.FromToUserID.FromUserID = req.OwnerUserID diff --git a/tools/component/component.go b/tools/component/component.go index 28ea7a2fe..616ffec2d 100644 --- a/tools/component/component.go +++ b/tools/component/component.go @@ -16,6 +16,7 @@ package main import ( "context" + "errors" "flag" "fmt" "net" @@ -285,10 +286,23 @@ func checkZookeeper() (string, error) { // Connect to Zookeeper str := "the addr is:" + address - c, _, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary + c, eventChan, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary if err != nil { return "", errs.Wrap(errStr(err, str)) } + timeout := time.After(5 * time.Second) + for { + select { + case event := <-eventChan: + if event.State == zk.StateConnected { + fmt.Println("Connected to Zookeeper") + goto Connected + } + case <-timeout: + return "", errs.Wrap(errors.New("timeout waiting for Zookeeper connection"), "Zookeeper Addr: "+strings.Join(config.Config.Zookeeper.ZkAddr, " ")) + } + } +Connected: defer c.Close() // Set authentication if username and password are provided @@ -298,12 +312,6 @@ func checkZookeeper() (string, error) { } } - // Check if Zookeeper is reachable - _, _, err = c.Get("/") - if err != nil { - return "", errs.Wrap(err, str) - } - return str, nil } From cfde7bb0ff6d7441e3ae593016d6848b9e6af020 Mon Sep 17 00:00:00 2001 From: a3d21 <93191329+a3d21@users.noreply.github.com> Date: Fri, 29 Dec 2023 10:25:03 +0800 Subject: [PATCH 24/31] fix: mongo uri connect (#1611) --- pkg/common/db/unrelation/mongo.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go index 2c1dc6f38..8cfb97a98 100644 --- a/pkg/common/db/unrelation/mongo.go +++ b/pkg/common/db/unrelation/mongo.go @@ -74,6 +74,10 @@ func buildMongoURI() string { return uri } + if config.Config.Mongo.Uri != "" { + return config.Config.Mongo.Uri + } + username := os.Getenv("MONGO_USERNAME") password := os.Getenv("MONGO_PASSWORD") address := os.Getenv("MONGO_ADDRESS") From 7ddb84f7fcdab6fc2b67593691fbf741da0c56ff Mon Sep 17 00:00:00 2001 From: Brabem <69128477+luhaoling@users.noreply.github.com> Date: Fri, 29 Dec 2023 18:14:15 +0800 Subject: [PATCH 25/31] fix: add the GetconversationAPI 1542 (#1604) * feat: add GetConversationsUnreadSeqAndMaxSeq func * feat: add GetConversationsUnreadSeqAndMaxSeq func * feat: add GetConversationsUnreadSeqAndMaxSeq func * fix: fix the conflect * feat: add GetConversationList Api * fix: fix the error * fix: move the GetConversationList to conversation folder * fix: fix the go.mod * fix: add InitiateFormData and CompleteFormData * fix: fix the error * fix: find error * fix: test * feat: add notification API * fix: find error * fix: fix the error * fix: fix the PinFriend error * fix: fix the Ex error * fix: find the error * fix: fix the rpc error * fix: fix the error * fix: fix the log error * fix: fix the error1 * fix: fix the error * fix: fix the script * fix: fix the error * fix: fix the error * fix: fix the error of tag * fix: fix the protocol * fix: fix the error * fix: fix the error * fix: fix the err not wrap * fix: fix the error * fix: fix GetGroupMembers by nickname * fix: fix the error * fix: fix the FindOneByDocIDs * fix: fix the protocol version * fix: fit the protocol version --- go.mod | 4 +- go.sum | 6 +- internal/api/conversation.go | 4 + internal/api/msg.go | 5 +- internal/api/route.go | 1 + internal/rpc/conversation/conversaion.go | 173 +++++++++++++++++++++++ internal/rpc/msg/as_read.go | 3 +- internal/rpc/msg/seq.go | 25 +++- pkg/apistruct/manage.go | 24 ++++ pkg/common/db/controller/msg.go | 16 +++ pkg/rpcclient/msg.go | 25 +++- 11 files changed, 273 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 1b80650c5..2db34a8b1 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( firebase.google.com/go v3.13.0+incompatible - github.com/OpenIMSDK/protocol v0.0.40 + github.com/OpenIMSDK/protocol v0.0.41 github.com/OpenIMSDK/tools v0.0.21 github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/dtm-labs/rockscache v0.1.1 @@ -156,5 +156,3 @@ require ( golang.org/x/crypto v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) - -replace github.com/OpenIMSDK/protocol v0.0.40 => github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3 diff --git a/go.sum b/go.sum index 881000381..fc1d15242 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= -github.com/OpenIMSDK/protocol v0.0.40 h1:1/Oij6RSAaePCPrWGwp9Cyz976/8Uxr94hM5M5FXzlg= -github.com/OpenIMSDK/protocol v0.0.40/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= +github.com/OpenIMSDK/protocol v0.0.42 h1:vIWXqZJZZ1ddleJA25fxhjZ1GyEHATpYM3wVWh4/+PY= +github.com/OpenIMSDK/protocol v0.0.42/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48= github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= @@ -227,8 +227,6 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w= github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w= -github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3 h1:HZz2U/M3T4x9SqPxWdrD9MZy7jxx7nS+nx/aRN9m3RQ= -github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= diff --git a/internal/api/conversation.go b/internal/api/conversation.go index e422de677..6463cbde6 100644 --- a/internal/api/conversation.go +++ b/internal/api/conversation.go @@ -33,6 +33,10 @@ func (o *ConversationApi) GetAllConversations(c *gin.Context) { a2r.Call(conversation.ConversationClient.GetAllConversations, o.Client, c) } +func (o *ConversationApi) GetConversationsList(c *gin.Context) { + a2r.Call(conversation.ConversationClient.GetConversationList, o.Client, c) +} + func (o *ConversationApi) GetConversation(c *gin.Context) { a2r.Call(conversation.ConversationClient.GetConversation, o.Client, c) } diff --git a/internal/api/msg.go b/internal/api/msg.go index 8346ad860..548450534 100644 --- a/internal/api/msg.go +++ b/internal/api/msg.go @@ -250,13 +250,14 @@ func (m *MessageApi) SendBusinessNotification(c *gin.Context) { req := struct { Key string `json:"key"` Data string `json:"data"` - SendUserID string `json:"sendUserID"` - RecvUserID string `json:"recvUserID"` + SendUserID string `json:"sendUserID" binding:"required"` + RecvUserID string `json:"recvUserID" binding:"required"` }{} if err := c.BindJSON(&req); err != nil { apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap()) return } + if !authverify.IsAppManagerUid(c) { apiresp.GinError(c, errs.ErrNoPermission.Wrap("only app manager can send message")) return diff --git a/internal/api/route.go b/internal/api/route.go index 766912d45..1c91f4dde 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -204,6 +204,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive conversationGroup := r.Group("/conversation", ParseToken) { c := NewConversationApi(*conversationRpc) + conversationGroup.POST("/get_conversations_list", c.GetConversationsList) conversationGroup.POST("/get_all_conversations", c.GetAllConversations) conversationGroup.POST("/get_conversation", c.GetConversation) conversationGroup.POST("/get_conversations", c.GetConversations) diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index 88c9ff7ff..b80e32953 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -17,6 +17,8 @@ package conversation import ( "context" "errors" + "github.com/OpenIMSDK/protocol/sdkws" + "sort" "github.com/OpenIMSDK/tools/tx" @@ -41,6 +43,8 @@ import ( ) type conversationServer struct { + msgRpcClient *rpcclient.MessageRpcClient + user *rpcclient.UserRpcClient groupRpcClient *rpcclient.GroupRpcClient conversationDatabase controller.ConversationDatabase conversationNotificationSender *notification.ConversationNotificationSender @@ -61,7 +65,10 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e } groupRpcClient := rpcclient.NewGroupRpcClient(client) msgRpcClient := rpcclient.NewMessageRpcClient(client) + userRpcClient := rpcclient.NewUserRpcClient(client) pbconversation.RegisterConversationServer(server, &conversationServer{ + msgRpcClient: &msgRpcClient, + user: &userRpcClient, conversationNotificationSender: notification.NewConversationNotificationSender(&msgRpcClient), groupRpcClient: &groupRpcClient, conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx.NewMongo(mongo.GetClient())), @@ -82,6 +89,73 @@ func (c *conversationServer) GetConversation(ctx context.Context, req *pbconvers return resp, nil } +func (m *conversationServer) GetConversationList(ctx context.Context, req *pbconversation.GetConversationListReq) (resp *pbconversation.GetConversationListResp, err error) { + log.ZDebug(ctx, "GetConversationList", "seqs", req, "userID", req.UserID) + var conversationIDs []string + if len(req.ConversationIDs) == 0 { + conversationIDs, err = m.conversationDatabase.GetConversationIDs(ctx, req.UserID) + if err != nil { + return nil, err + } + } else { + conversationIDs = req.ConversationIDs + } + + conversations, err := m.conversationDatabase.FindConversations(ctx, req.UserID, conversationIDs) + if err != nil { + return nil, err + } + if len(conversations) == 0 { + return nil, errs.ErrRecordNotFound.Wrap() + } + + maxSeqs, err := m.msgRpcClient.GetMaxSeqs(ctx, conversationIDs) + if err != nil { + return nil, err + } + + chatLogs, err := m.msgRpcClient.GetMsgByConversationIDs(ctx, conversationIDs, maxSeqs) + if err != nil { + return nil, err + } + + conversationMsg, err := m.getConversationInfo(ctx, chatLogs, req.UserID) + if err != nil { + return nil, err + } + + hasReadSeqs, err := m.msgRpcClient.GetHasReadSeqs(ctx, req.UserID, conversationIDs) + if err != nil { + return nil, err + } + + conversation_unreadCount := make(map[string]int64) + for conversationID, maxSeq := range maxSeqs { + conversation_unreadCount[conversationID] = maxSeq - hasReadSeqs[conversationID] + } + + conversation_isPinkTime := make(map[int64]string) + conversation_notPinkTime := make(map[int64]string) + for _, v := range conversations { + conversationID := v.ConversationID + time := conversationMsg[conversationID].MsgInfo.LatestMsgRecvTime + conversationMsg[conversationID].RecvMsgOpt = v.RecvMsgOpt + if v.IsPinned { + conversationMsg[conversationID].IsPinned = v.IsPinned + conversation_isPinkTime[time] = conversationID + continue + } + conversation_notPinkTime[time] = conversationID + } + resp = &pbconversation.GetConversationListResp{ + ConversationElems: []*pbconversation.ConversationElem{}, + } + + m.conversationSort(conversation_isPinkTime, resp, conversation_unreadCount, conversationMsg) + m.conversationSort(conversation_notPinkTime, resp, conversation_unreadCount, conversationMsg) + return resp, nil +} + func (c *conversationServer) GetAllConversations(ctx context.Context, req *pbconversation.GetAllConversationsReq) (*pbconversation.GetAllConversationsResp, error) { conversations, err := c.conversationDatabase.GetUserAllConversation(ctx, req.OwnerUserID) if err != nil { @@ -348,3 +422,102 @@ func (c *conversationServer) GetConversationOfflinePushUserIDs( } return &pbconversation.GetConversationOfflinePushUserIDsResp{UserIDs: utils.Keys(userIDSet)}, nil } + +func (c *conversationServer) conversationSort( + conversations map[int64]string, + resp *pbconversation.GetConversationListResp, + conversation_unreadCount map[string]int64, + conversationMsg map[string]*pbconversation.ConversationElem, +) { + keys := []int64{} + for key := range conversations { + keys = append(keys, key) + } + + sort.Slice(keys[:], func(i, j int) bool { + return keys[i] > keys[j] + }) + index := 0 + + cons := make([]*pbconversation.ConversationElem, len(conversations)) + for _, v := range keys { + conversationID := conversations[v] + conversationElem := conversationMsg[conversationID] + conversationElem.UnreadCount = conversation_unreadCount[conversationID] + cons[index] = conversationElem + index++ + } + resp.ConversationElems = append(resp.ConversationElems, cons...) +} + +func (c *conversationServer) getConversationInfo( + ctx context.Context, + chatLogs map[string]*sdkws.MsgData, + userID string) (map[string]*pbconversation.ConversationElem, error) { + var ( + sendIDs []string + groupIDs []string + sendMap = make(map[string]*sdkws.UserInfo) + groupMap = make(map[string]*sdkws.GroupInfo) + conversationMsg = make(map[string]*pbconversation.ConversationElem) + ) + for _, chatLog := range chatLogs { + switch chatLog.SessionType { + case constant.SingleChatType: + if chatLog.SendID == userID { + sendIDs = append(sendIDs, chatLog.RecvID) + } + sendIDs = append(sendIDs, chatLog.SendID) + case constant.GroupChatType, constant.SuperGroupChatType: + groupIDs = append(groupIDs, chatLog.GroupID) + sendIDs = append(sendIDs, chatLog.SendID) + } + } + if len(sendIDs) != 0 { + sendInfos, err := c.user.GetUsersInfo(ctx, sendIDs) + if err != nil { + return nil, err + } + for _, sendInfo := range sendInfos { + sendMap[sendInfo.UserID] = sendInfo + } + } + if len(groupIDs) != 0 { + groupInfos, err := c.groupRpcClient.GetGroupInfos(ctx, groupIDs, false) + if err != nil { + return nil, err + } + for _, groupInfo := range groupInfos { + groupMap[groupInfo.GroupID] = groupInfo + } + } + for conversationID, chatLog := range chatLogs { + pbchatLog := &pbconversation.ConversationElem{} + msgInfo := &pbconversation.MsgInfo{} + if err := utils.CopyStructFields(msgInfo, chatLog); err != nil { + return nil, err + } + switch chatLog.SessionType { + case constant.SingleChatType: + if chatLog.SendID == userID { + msgInfo.FaceURL = sendMap[chatLog.RecvID].FaceURL + msgInfo.SenderName = sendMap[chatLog.RecvID].Nickname + break + } + msgInfo.FaceURL = sendMap[chatLog.SendID].FaceURL + msgInfo.SenderName = sendMap[chatLog.SendID].Nickname + case constant.GroupChatType, constant.SuperGroupChatType: + msgInfo.GroupName = groupMap[chatLog.GroupID].GroupName + msgInfo.GroupFaceURL = groupMap[chatLog.GroupID].FaceURL + msgInfo.GroupMemberCount = groupMap[chatLog.GroupID].MemberCount + msgInfo.GroupID = chatLog.GroupID + msgInfo.GroupType = groupMap[chatLog.GroupID].GroupType + msgInfo.SenderName = sendMap[chatLog.SendID].Nickname + } + pbchatLog.ConversationID = conversationID + msgInfo.LatestMsgRecvTime = chatLog.SendTime + pbchatLog.MsgInfo = msgInfo + conversationMsg[conversationID] = pbchatLog + } + return conversationMsg, nil +} diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index 5324ccba8..71e038b39 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -18,6 +18,7 @@ import ( "context" utils2 "github.com/OpenIMSDK/tools/utils" + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/redis/go-redis/v9" @@ -26,8 +27,6 @@ import ( "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" - - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" ) func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *msg.GetConversationsHasReadAndMaxSeqReq) (resp *msg.GetConversationsHasReadAndMaxSeqResp, err error) { diff --git a/internal/rpc/msg/seq.go b/internal/rpc/msg/seq.go index 4f6a01e8d..c12f258b7 100644 --- a/internal/rpc/msg/seq.go +++ b/internal/rpc/msg/seq.go @@ -16,7 +16,6 @@ package msg import ( "context" - pbmsg "github.com/OpenIMSDK/protocol/msg" ) @@ -30,3 +29,27 @@ func (m *msgServer) GetConversationMaxSeq( } return &pbmsg.GetConversationMaxSeqResp{MaxSeq: maxSeq}, nil } + +func (m *msgServer) GetMaxSeqs(ctx context.Context, req *pbmsg.GetMaxSeqsReq) (*pbmsg.SeqsInfoResp, error) { + maxSeqs, err := m.MsgDatabase.GetMaxSeqs(ctx, req.ConversationIDs) + if err != nil { + return nil, err + } + return &pbmsg.SeqsInfoResp{MaxSeqs: maxSeqs}, nil +} + +func (m *msgServer) GetHasReadSeqs(ctx context.Context, req *pbmsg.GetHasReadSeqsReq) (*pbmsg.SeqsInfoResp, error) { + hasReadSeqs, err := m.MsgDatabase.GetHasReadSeqs(ctx, req.UserID, req.ConversationIDs) + if err != nil { + return nil, err + } + return &pbmsg.SeqsInfoResp{MaxSeqs: hasReadSeqs}, nil +} + +func (m *msgServer) GetMsgByConversationIDs(ctx context.Context, req *pbmsg.GetMsgByConversationIDsReq) (*pbmsg.GetMsgByConversationIDsResp, error) { + Msgs, err := m.MsgDatabase.FindOneByDocIDs(ctx, req.ConversationIDs, req.MaxSeqs) + if err != nil { + return nil, err + } + return &pbmsg.GetMsgByConversationIDsResp{MsgDatas: Msgs}, nil +} diff --git a/pkg/apistruct/manage.go b/pkg/apistruct/manage.go index a48f5253c..f9f542835 100644 --- a/pkg/apistruct/manage.go +++ b/pkg/apistruct/manage.go @@ -64,6 +64,30 @@ type SendMsgReq struct { SendMsg } +type GetConversationListReq struct { + // userID uniquely identifies the user. + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty" binding:"required"` + + // ConversationIDs contains a list of unique identifiers for conversations. + ConversationIDs []string `protobuf:"bytes,2,rep,name=conversationIDs,proto3" json:"conversationIDs,omitempty"` +} + +type GetConversationListResp struct { + // ConversationElems is a map that associates conversation IDs with their respective details. + ConversationElems map[string]*ConversationElem `protobuf:"bytes,1,rep,name=conversationElems,proto3" json:"conversationElems,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +type ConversationElem struct { + // MaxSeq represents the maximum sequence number within the conversation. + MaxSeq int64 `protobuf:"varint,1,opt,name=maxSeq,proto3" json:"maxSeq,omitempty"` + + // UnreadSeq represents the number of unread messages in the conversation. + UnreadSeq int64 `protobuf:"varint,2,opt,name=unreadSeq,proto3" json:"unreadSeq,omitempty"` + + // LastSeqTime represents the timestamp of the last sequence in the conversation. + LastSeqTime int64 `protobuf:"varint,3,opt,name=LastSeqTime,proto3" json:"LastSeqTime,omitempty"` +} + // BatchSendMsgReq defines the structure for sending a message to multiple recipients. type BatchSendMsgReq struct { SendMsg diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go index fb0a9c702..dfff5c61d 100644 --- a/pkg/common/db/controller/msg.go +++ b/pkg/common/db/controller/msg.go @@ -98,6 +98,7 @@ type CommonMsgDatabase interface { SetSendMsgStatus(ctx context.Context, id string, status int32) error GetSendMsgStatus(ctx context.Context, id string) (int32, error) SearchMessage(ctx context.Context, req *pbmsg.SearchMessageReq) (total int32, msgData []*sdkws.MsgData, err error) + FindOneByDocIDs(ctx context.Context, docIDs []string, seqs map[string]int64) (map[string]*sdkws.MsgData, error) // to mq MsgToMQ(ctx context.Context, key string, msg2mq *sdkws.MsgData) error @@ -1051,6 +1052,21 @@ func (db *commonMsgDatabase) SearchMessage(ctx context.Context, req *pbmsg.Searc return total, totalMsgs, nil } +func (db *commonMsgDatabase) FindOneByDocIDs(ctx context.Context, conversationIDs []string, seqs map[string]int64) (map[string]*sdkws.MsgData, error) { + totalMsgs := make(map[string]*sdkws.MsgData) + for _, conversationID := range conversationIDs { + seq := seqs[conversationID] + docID := db.msg.GetDocID(conversationID, seq) + msgs, err := db.msgDocDatabase.FindOneByDocID(ctx, docID) + if err != nil { + return nil, err + } + index := db.msg.GetMsgIndex(seq) + totalMsgs[conversationID] = convert.MsgDB2Pb(msgs.Msg[index].Msg) + } + return totalMsgs, nil +} + func (db *commonMsgDatabase) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) { db.msgDocDatabase.ConvertMsgsDocLen(ctx, conversationIDs) } diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go index 03769dc74..abad0075a 100644 --- a/pkg/rpcclient/msg.go +++ b/pkg/rpcclient/msg.go @@ -17,7 +17,6 @@ package rpcclient import ( "context" "encoding/json" - "google.golang.org/grpc" "google.golang.org/protobuf/proto" @@ -157,6 +156,30 @@ func (m *MessageRpcClient) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqRe return resp, err } +func (m *MessageRpcClient) GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) { + log.ZDebug(ctx, "GetMaxSeqs", "conversationIDs", conversationIDs) + resp, err := m.Client.GetMaxSeqs(ctx, &msg.GetMaxSeqsReq{ + ConversationIDs: conversationIDs, + }) + return resp.MaxSeqs, err +} + +func (m *MessageRpcClient) GetHasReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error) { + resp, err := m.Client.GetHasReadSeqs(ctx, &msg.GetHasReadSeqsReq{ + UserID: userID, + ConversationIDs: conversationIDs, + }) + return resp.MaxSeqs, err +} + +func (m *MessageRpcClient) GetMsgByConversationIDs(ctx context.Context, docIDs []string, seqs map[string]int64) (map[string]*sdkws.MsgData, error) { + resp, err := m.Client.GetMsgByConversationIDs(ctx, &msg.GetMsgByConversationIDsReq{ + ConversationIDs: docIDs, + MaxSeqs: seqs, + }) + return resp.MsgDatas, err +} + func (m *MessageRpcClient) PullMessageBySeqList(ctx context.Context, req *sdkws.PullMessageBySeqsReq) (*sdkws.PullMessageBySeqsResp, error) { resp, err := m.Client.PullMessageBySeqs(ctx, req) return resp, err From c68a61d8c240143f1b4d58d5d82bb44e807fb5ad Mon Sep 17 00:00:00 2001 From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com> Date: Fri, 29 Dec 2023 20:38:43 +0800 Subject: [PATCH 26/31] fix setUserInfoEx (#1635) * update set pin friends * update set pin friends * update set pin friends * update set pin friends * update set pin friends * update set pin friends * fix bugs * fix bugs * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * Update go.mod * Update friend.go * debug * debug * debug * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * I cannot solve todo in test.sh * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * Update go.mod * fix group notification * fix group notification * update openimsdk tools * update openim server remove duplicate code * update openim server remove duplicate code * update user command get * update user command get * update response of callback response error * update black ex * update join group ex * update user pb2map * update go sum * update go sum * update updateUserInfoEx * update updateUserInfoEx * update updateUserInfoEx add callback functions * fix dismiss group function * fix dismiss group function * fix dismiss group function * fix dismiss group function * update pin friend to update friend * fix go mod * fix err golangci-lint * fix UserPb2DBMap * update comments, update go.mod check for register username * update comments, update go.mod check for register username * update comments, update go.mod check for register username * update comments, update go.mod check for register username * fix callback * fix go.mod * fix debug * fix bugs * update notification * update notification * update notification * update notification * update notification * update notification * update notification * update notification * fix updateUserInfoEx * fix updateUserInfoEx * modify go.mod * fix updateUserInfoEx * fix updateUserInfoEx --------- Co-authored-by: Xinwei Xiong <3293172751@qq.com> --- go.mod | 4 ++-- internal/rpc/user/callback.go | 9 ++++----- internal/rpc/user/user.go | 2 +- pkg/callbackstruct/user.go | 12 ++++++------ pkg/common/convert/user.go | 13 ++++++++----- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 2db34a8b1..393e742de 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( firebase.google.com/go v3.13.0+incompatible - github.com/OpenIMSDK/protocol v0.0.41 + github.com/OpenIMSDK/protocol v0.0.42 github.com/OpenIMSDK/tools v0.0.21 github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/dtm-labs/rockscache v0.1.1 @@ -155,4 +155,4 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/crypto v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect -) +) \ No newline at end of file diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go index 9e02eb130..092a66a07 100644 --- a/internal/rpc/user/callback.go +++ b/internal/rpc/user/callback.go @@ -16,7 +16,6 @@ package user import ( "context" - pbuser "github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/tools/utils" @@ -67,16 +66,16 @@ func CallbackBeforeUpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserI cbReq := &cbapi.CallbackBeforeUpdateUserInfoExReq{ CallbackCommand: cbapi.CallbackBeforeUpdateUserInfoExCommand, UserID: req.UserInfo.UserID, - FaceURL: &req.UserInfo.FaceURL, - Nickname: &req.UserInfo.Nickname, + FaceURL: req.UserInfo.FaceURL, + Nickname: req.UserInfo.Nickname, } resp := &cbapi.CallbackBeforeUpdateUserInfoExResp{} if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeUpdateUserInfoEx); err != nil { return err } - utils.NotNilReplace(&req.UserInfo.FaceURL, resp.FaceURL) + utils.NotNilReplace(req.UserInfo.FaceURL, resp.FaceURL) utils.NotNilReplace(req.UserInfo.Ex, resp.Ex) - utils.NotNilReplace(&req.UserInfo.Nickname, resp.Nickname) + utils.NotNilReplace(req.UserInfo.Nickname, resp.Nickname) return nil } func CallbackAfterUpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) error { diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index fdfd81ed2..5a79fbc91 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -168,7 +168,7 @@ func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUse if err != nil { return nil, err } - if req.UserInfo.Nickname != "" || req.UserInfo.FaceURL != "" { + if req.UserInfo.Nickname != nil || req.UserInfo.FaceURL != nil { if err := s.groupRpcClient.NotificationUserInfoUpdate(ctx, req.UserInfo.UserID); err != nil { log.ZError(ctx, "NotificationUserInfoUpdate", err) } diff --git a/pkg/callbackstruct/user.go b/pkg/callbackstruct/user.go index bfb69bd38..98536882d 100644 --- a/pkg/callbackstruct/user.go +++ b/pkg/callbackstruct/user.go @@ -47,22 +47,22 @@ type CallbackAfterUpdateUserInfoResp struct { type CallbackBeforeUpdateUserInfoExReq struct { CallbackCommand `json:"callbackCommand"` UserID string `json:"userID"` - Nickname *string `json:"nickName"` - FaceURL *string `json:"faceURL"` + Nickname *wrapperspb.StringValue `json:"nickName"` + FaceURL *wrapperspb.StringValue `json:"faceURL"` Ex *wrapperspb.StringValue `json:"ex"` } type CallbackBeforeUpdateUserInfoExResp struct { CommonCallbackResp - Nickname *string `json:"nickName"` - FaceURL *string `json:"faceURL"` + Nickname *wrapperspb.StringValue `json:"nickName"` + FaceURL *wrapperspb.StringValue `json:"faceURL"` Ex *wrapperspb.StringValue `json:"ex"` } type CallbackAfterUpdateUserInfoExReq struct { CallbackCommand `json:"callbackCommand"` UserID string `json:"userID"` - Nickname string `json:"nickName"` - FaceURL string `json:"faceURL"` + Nickname *wrapperspb.StringValue `json:"nickName"` + FaceURL *wrapperspb.StringValue `json:"faceURL"` Ex *wrapperspb.StringValue `json:"ex"` } type CallbackAfterUpdateUserInfoExResp struct { diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go index 6d43595bc..62f80e458 100644 --- a/pkg/common/convert/user.go +++ b/pkg/common/convert/user.go @@ -79,14 +79,17 @@ func UserPb2DBMapEx(user *sdkws.UserInfoWithEx) map[string]any { val := make(map[string]any) // Map fields from UserInfoWithEx to val - val["nickname"] = user.Nickname - val["face_url"] = user.FaceURL - + if user.Nickname != nil { + val["nickname"] = user.Nickname.Value + } + if user.FaceURL != nil { + val["face_url"] = user.FaceURL.Value + } if user.Ex != nil { val["ex"] = user.Ex.Value } - if user.GlobalRecvMsgOpt != 0 { - val["global_recv_msg_opt"] = user.GlobalRecvMsgOpt + if user.GlobalRecvMsgOpt != nil { + val["global_recv_msg_opt"] = user.GlobalRecvMsgOpt.Value } return val From 1e52376d7b6e8e10e0f0a01988faff1ad5a7b011 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Fri, 29 Dec 2023 20:43:58 +0800 Subject: [PATCH 27/31] fix: fix openim scripts and ci add openim check (#1632) * fix: fix openim zk env set Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: fix openim zk env set Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim docker prom Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --------- Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --- .github/workflows/openimci.yml | 1 - deployments/templates/env-template.yaml | 64 ++++++++----------------- docker-compose.yml | 2 +- scripts/check-all.sh | 12 +++-- scripts/install/environment.sh | 2 +- tools/component/component.go | 4 +- 6 files changed, 32 insertions(+), 53 deletions(-) diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml index d8e988f0b..d16e91ba4 100644 --- a/.github/workflows/openimci.yml +++ b/.github/workflows/openimci.yml @@ -201,7 +201,6 @@ jobs: - name: Build, Start, Check Services and Print Logs for Ubuntu if: runner.os == 'Linux' run: | - sudo make init && \ sudo make build && \ sudo make start && \ sudo make check || \ diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml index ab9c87c02..f98eda1c1 100644 --- a/deployments/templates/env-template.yaml +++ b/deployments/templates/env-template.yaml @@ -1,39 +1,20 @@ -# Copyright © 2023 OpenIM. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# ====================================== -# ========= Basic Configuration ======== -# ====================================== - -# The user for authentication or system operations. -# Default: OPENIM_USER=root -USER=${OPENIM_USER} - -# Password associated with the specified user for authentication. -# Default: PASSWORD=openIM123 -PASSWORD=${PASSWORD} - -# Base URL for the application programming interface (API). -# Default: API_URL=http://172.28.0.1:10002 -API_URL=${API_URL} - -# Directory path for storing data files or related information. -# Default: DATA_DIR=./ +# ----------------------------------------------------------------------------- +# General Configuration +# This section contains general configuration options for the entire environment. +# These options can be set via environment variables. If both environment variables +# and settings in this .env file exist, the environment variables take precedence. +# ----------------------------------------------------------------------------- + +# Local IP address for the service +# To modify, uncomment and replace with the actual IP address +OPENIM_IP=${OPENIM_IP} + +# Data storage directory DATA_DIR=${DATA_DIR} -# Choose the appropriate image address, the default is GITHUB image, -# you can choose docker hub, for Chinese users can choose Ali Cloud +# Choose the image address: GitHub (ghcr.io/openimsdk), Docker Hub (openim), +# or Ali Cloud (registry.cn-hangzhou.aliyuncs.com/openimsdk). +# Uncomment one of the following three options. Aliyun is recommended for users in China. # export IMAGE_REGISTRY="ghcr.io/openimsdk" # export IMAGE_REGISTRY="openim" # export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk" @@ -47,10 +28,9 @@ IMAGE_REGISTRY=${IMAGE_REGISTRY} # Default: DOCKER_BRIDGE_SUBNET=172.28.0.0/16 DOCKER_BRIDGE_SUBNET=${DOCKER_BRIDGE_SUBNET} -# Gateway for the Docker network. -# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1 +# Set and specify the IP addresses of some containers. Generally speaking, +# you do not need to modify these configurations to facilitate debugging DOCKER_BRIDGE_GATEWAY=${DOCKER_BRIDGE_GATEWAY} - MONGO_NETWORK_ADDRESS=${MONGO_NETWORK_ADDRESS} REDIS_NETWORK_ADDRESS=${REDIS_NETWORK_ADDRESS} KAFKA_NETWORK_ADDRESS=${KAFKA_NETWORK_ADDRESS} @@ -65,15 +45,13 @@ NODE_EXPORTER_NETWORK_ADDRESS=${NODE_EXPORTER_NETWORK_ADDRESS} OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS} ALERT_MANAGER_NETWORK_ADDRESS=${ALERT_MANAGER_NETWORK_ADDRESS} -# =============================================== -# = Component Extension Configuration = -# =============================================== +# ----------------------------------------------------------------------------- +# Database Configuration +# This section contains environment variable settings related to databases. +# ----------------------------------------------------------------------------- -# ============ Component Extension Configuration ========== # ----- ZooKeeper Configuration ----- # Address or hostname for the ZooKeeper service. -# Default: ZOOKEEPER_ADDRESS=172.28.0.1 -ZOOKEEPER_ADDRESS=${ZOOKEEPER_NETWORK_ADDRESS} # Port for ZooKeeper service. # Default: ZOOKEEPER_PORT=12181 diff --git a/docker-compose.yml b/docker-compose.yml index de3deaaea..bdfee3748 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -122,7 +122,7 @@ services: server: ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7} - # Uncomment and configure the following services as needed + ## Uncomment and configure the following services as needed # openim-admin: # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0 # container_name: openim-admin diff --git a/scripts/check-all.sh b/scripts/check-all.sh index e1e07bd65..48c38331d 100755 --- a/scripts/check-all.sh +++ b/scripts/check-all.sh @@ -30,23 +30,25 @@ OPENIM_VERBOSE=4 openim::log::info "\n# Begin to check all openim service" -# OpenIM status # Elegant printing function print_services_and_ports() { - service_names=("$1[@]") - service_ports=("$2[@]") + local -n service_names=$1 + local -n service_ports=$2 echo "+-------------------------+----------+" echo "| Service Name | Port |" echo "+-------------------------+----------+" - for index in "${!service_names}"; do - printf "| %-23s | %-8s |\n" "${!service_names[$index]}" "${!service_ports[$index]}" + for index in "${!service_names[@]}"; do + printf "| %-23s | %-8s |\n" "${service_names[$index]}" "${service_ports[$index]}" done echo "+-------------------------+----------+" } +# Assuming OPENIM_SERVER_NAME_TARGETS and OPENIM_SERVER_PORT_TARGETS are defined +# Similarly for OPENIM_DEPENDENCY_TARGETS and OPENIM_DEPENDENCY_PORT_TARGETS + # Print out services and their ports print_services_and_ports OPENIM_SERVER_NAME_TARGETS OPENIM_SERVER_PORT_TARGETS diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh index feb36c3c1..0e3a428e8 100755 --- a/scripts/install/environment.sh +++ b/scripts/install/environment.sh @@ -378,7 +378,7 @@ def "CALLBACK_TIMEOUT" "5" # 最长超时时间 def "CALLBACK_FAILED_CONTINUE" "true" # 失败后是否继续 ###################### Prometheus 配置信息 ###################### # 是否启用 Prometheus -readonly PROMETHEUS_ENABLE=${PROMETHEUS_ENABLE:-'false'} +readonly PROMETHEUS_ENABLE=${PROMETHEUS_ENABLE:-'true'} def "PROMETHEUS_URL" "${GRAFANA_ADDRESS}:${GRAFANA_PORT}" # Api 服务的 Prometheus 端口 readonly API_PROM_PORT=${API_PROM_PORT:-'20100'} diff --git a/tools/component/component.go b/tools/component/component.go index 616ffec2d..e09fa11e6 100644 --- a/tools/component/component.go +++ b/tools/component/component.go @@ -223,8 +223,8 @@ func checkMinio() (string, error) { defer cancel() if minioClient.IsOffline() { - str := fmt.Sprintf("Minio server is offline;%s", str) - return "", ErrComponentStart.Wrap(str) + // str := fmt.Sprintf("Minio server is offline;%s", str) + // return "", ErrComponentStart.Wrap(str) } // Check for localhost in API URL and Minio SignEndpoint From 959c5a7ae11186862743df1a2e3456341d3754c0 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Fri, 29 Dec 2023 22:29:52 +0800 Subject: [PATCH 28/31] feat: add openim scripts fix and optimize config about openim source code deployment for this PR? openim ci and scripts (#1641) * fix: fix openim zk env set Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * fix: fix openim zk env set Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim docker prom Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> * feat: add openim docker prom Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --------- Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --- deployments/templates/env-template.yaml | 124 +++++++++++------------- 1 file changed, 57 insertions(+), 67 deletions(-) diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml index f98eda1c1..e0fd7bc9f 100644 --- a/deployments/templates/env-template.yaml +++ b/deployments/templates/env-template.yaml @@ -4,20 +4,20 @@ # These options can be set via environment variables. If both environment variables # and settings in this .env file exist, the environment variables take precedence. # ----------------------------------------------------------------------------- +# ========================== +# General Configuration +# ========================== +# These settings apply to the overall environment. -# Local IP address for the service -# To modify, uncomment and replace with the actual IP address -OPENIM_IP=${OPENIM_IP} - -# Data storage directory +# Data storage directory for persistent data. +# Example: DATA_DIR=/path/to/data DATA_DIR=${DATA_DIR} -# Choose the image address: GitHub (ghcr.io/openimsdk), Docker Hub (openim), -# or Ali Cloud (registry.cn-hangzhou.aliyuncs.com/openimsdk). -# Uncomment one of the following three options. Aliyun is recommended for users in China. -# export IMAGE_REGISTRY="ghcr.io/openimsdk" -# export IMAGE_REGISTRY="openim" -# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk" +# Docker image registry. Uncomment the preferred one. +# Options: ghcr.io/openimsdk, openim, registry.cn-hangzhou.aliyuncs.com/openimsdk +# IMAGE_REGISTRY="ghcr.io/openimsdk" +# IMAGE_REGISTRY="openim" +# IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk" IMAGE_REGISTRY=${IMAGE_REGISTRY} # ====================================== @@ -45,23 +45,45 @@ NODE_EXPORTER_NETWORK_ADDRESS=${NODE_EXPORTER_NETWORK_ADDRESS} OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS} ALERT_MANAGER_NETWORK_ADDRESS=${ALERT_MANAGER_NETWORK_ADDRESS} -# ----------------------------------------------------------------------------- -# Database Configuration -# This section contains environment variable settings related to databases. -# ----------------------------------------------------------------------------- +# ============================================================================== +# Configuration Update Instructions +# ============================================================================== +# This header outlines the methods to update common variables in config.yaml and .env files. +# These instructions are vital for maintaining the OpenIM environment's configuration. +# +# METHOD 1: Regenerate All Configurations +# ---------------------------------------- +# Use this method to regenerate all configurations. +# Steps: +# 1. Delete existing config files: +# - openim-server/config/config.yaml +# - openim-chat/config/config.yaml +# 2. Modify the .env file as required. +# 3. Run 'docker compose up -d'. This will regenerate: +# - config/config.yaml +# +# METHOD 2: Modify Individual Configuration Files +# ----------------------------------------------- +# Use this method to update specific configuration files. +# Steps: +# 1. Modify the .env file as necessary. +# 2. Update the corresponding entries in: +# - config/config.yaml +# 3. Restart the services with 'docker compose up -d'. +# 4. Special Note: If you modify OPENIM_IP, API_OPENIM_PORT, or MINIO_PORT in .env, +# ensure to update the corresponding services and configurations accordingly. +# +# It is essential to follow these methods to ensure consistent and correct application behavior. +# ============================================================================== +# Local IP address of the service. Modify if necessary. +# Example: OPENIM_IP=172.28.0.1, +OPENIM_IP=${OPENIM_IP} # ----- ZooKeeper Configuration ----- -# Address or hostname for the ZooKeeper service. - # Port for ZooKeeper service. # Default: ZOOKEEPER_PORT=12181 ZOOKEEPER_PORT=${ZOOKEEPER_PORT} -# ----- MongoDB Configuration ----- -# Address or hostname for the MongoDB service. -# Default: MONGO_ADDRESS=172.28.0.1 -MONGO_ADDRESS=${MONGO_NETWORK_ADDRESS} - # Port on which MongoDB service is running. # Default: MONGO_PORT=37017 # MONGO_PORT=${MONGO_PORT} @@ -79,9 +101,6 @@ MONGO_PASSWORD=${MONGO_PASSWORD} MONGO_DATABASE=${MONGO_DATABASE} # ----- Redis Configuration ----- -# Address or hostname for the Redis service. -# Default: REDIS_ADDRESS=172.28.0.1 -REDIS_ADDRESS=${REDIS_NETWORK_ADDRESS} # Port on which Redis in-memory data structure store is running. # Default: REDIS_PORT=16379 @@ -91,11 +110,6 @@ REDIS_PORT=${REDIS_PORT} # Default: REDIS_PASSWORD=openIM123 REDIS_PASSWORD=${REDIS_PASSWORD} -# ----- Kafka Configuration ----- -# Address or hostname for the Kafka service. -# Default: KAFKA_ADDRESS=172.28.0.1 -KAFKA_ADDRESS=${KAFKA_NETWORK_ADDRESS} - # Kakfa username to authenticate with the Kafka service. # KAFKA_USERNAME=${KAFKA_USERNAME} @@ -107,20 +121,13 @@ KAFKA_PORT=${KAFKA_PORT} # Default: KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis KAFKA_LATESTMSG_REDIS_TOPIC=${KAFKA_LATESTMSG_REDIS_TOPIC} -# Topic in Kafka for pushing messages (e.g. notifications or updates). -# Default: KAFKA_MSG_PUSH_TOPIC=msgToPush -KAFKA_MSG_PUSH_TOPIC=${KAFKA_MSG_PUSH_TOPIC} - -# Topic in Kafka for storing offline messages in MongoDB. -# Default: KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql -KAFKA_OFFLINEMSG_MONGO_TOPIC=${KAFKA_OFFLINEMSG_MONGO_TOPIC} - -# ----- MinIO Configuration ---- -# Address or hostname for the MinIO object storage service. -# Default: MINIO_ADDRESS=172.28.0.1 -MINIO_ADDRESS=${MINIO_NETWORK_ADDRESS} - -# Port on which MinIO object storage service is running. +# MINIO_PORT +# ---------- +# MINIO_PORT sets the port for the MinIO object storage service. +# Upon changing this port, the MinIO endpoint URLs in the `config/config.yaml` file must be updated +# to reflect this change. The endpoints include both the 'endpoint' and 'signEndpoint' +# under the MinIO configuration. +# # Default: MINIO_PORT=10005 MINIO_PORT=${MINIO_PORT} @@ -133,19 +140,11 @@ MINIO_PORT=${MINIO_PORT} MINIO_SECRET_KEY=${MINIO_SECRET_KEY} # ----- Prometheus Configuration ----- -# Address or hostname for the Prometheus service. -# Default: PROMETHEUS_ADDRESS=172.28.0.1 -PROMETHEUS_ADDRESS=${PROMETHEUS_NETWORK_ADDRESS} - # Port on which Prometheus service is running. # Default: PROMETHEUS_PORT=19090 PROMETHEUS_PORT=${PROMETHEUS_PORT} # ----- Grafana Configuration ----- -# Address or hostname for the Grafana service. -# Default: GRAFANA_ADDRESS=172.28.0.1 -GRAFANA_ADDRESS=${GRAFANA_NETWORK_ADDRESS} - # Port on which Grafana service is running. # Default: GRAFANA_PORT=13000 GRAFANA_PORT=${GRAFANA_PORT} @@ -162,23 +161,19 @@ OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH} # Default: OPENIM_WEB_PORT=11001 OPENIM_WEB_PORT=${OPENIM_WEB_PORT} -# Address or hostname for the OpenIM web service. -# Default: OPENIM_WEB_ADDRESS=172.28.0.1 -OPENIM_WEB_ADDRESS=${OPENIM_WEB_NETWORK_ADDRESS} - # ====================================== # ========= OpenIM Server ============== # ====================================== - -# Address or hostname for the OpenIM server. -# Default: OPENIM_SERVER_ADDRESS=172.28.0.1 -OPENIM_SERVER_ADDRESS=${OPENIM_SERVER_NETWORK_ADDRESS} - # Port for the OpenIM WebSockets. # Default: OPENIM_WS_PORT=10001 OPENIM_WS_PORT=${OPENIM_WS_PORT} -# Port for the OpenIM API. +# API_OPENIM_PORT +# --------------- +# This variable defines the port on which the OpenIM API service will listen. +# When changing this port, it's essential to update the apiURL in the config.yaml file +# to ensure the API service is accessible at the new port. +# # Default: API_OPENIM_PORT=10002 API_OPENIM_PORT=${API_OPENIM_PORT} @@ -191,10 +186,6 @@ API_OPENIM_PORT=${API_OPENIM_PORT} # Default: CHAT_IMAGE_VERSION=main CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION} -# Address or hostname for the OpenIM chat service. -# Default: OPENIM_CHAT_ADDRESS=172.28.0.1 -OPENIM_CHAT_ADDRESS=${OPENIM_CHAT_NETWORK_ADDRESS} - # Port for the OpenIM chat API. # Default: OPENIM_CHAT_API_PORT=10008 OPENIM_CHAT_API_PORT=${OPENIM_CHAT_API_PORT} @@ -203,7 +194,6 @@ OPENIM_CHAT_API_PORT=${OPENIM_CHAT_API_PORT} # Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR} - # ====================================== # ========== OpenIM Admin ============== # ====================================== From a7138cb3b7d93f4c9462e8233a8fd9f52a5245bb Mon Sep 17 00:00:00 2001 From: xuexihuang <1339326187@qq.com> Date: Sat, 30 Dec 2023 10:40:42 +0800 Subject: [PATCH 29/31] feature:grafana web inside (#1636) * feature:grafana web inside * fix: using protocal v0.0.42 * fix: review values(but not use) --- config/templates/config.yaml.template | 2 +- deployments/templates/openim.yaml | 2 +- docker-compose.yml | 6 ++++++ internal/api/third.go | 2 +- pkg/common/config/config.go | 2 +- scripts/install/environment.sh | 3 +-- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template index 89f11f359..9954a8863 100644 --- a/config/templates/config.yaml.template +++ b/config/templates/config.yaml.template @@ -506,7 +506,7 @@ callback: # The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh prometheus: enable: false - prometheusUrl: 172.28.0.1:13000 + grafanaUrl: 172.28.0.1:13000 apiPrometheusPort: [20100] userPrometheusPort: [ 20110 ] friendPrometheusPort: [ 20120 ] diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml index cbb4a8c6e..96d867e10 100644 --- a/deployments/templates/openim.yaml +++ b/deployments/templates/openim.yaml @@ -506,7 +506,7 @@ callback: # The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh prometheus: enable: ${PROMETHEUS_ENABLE} - prometheusUrl: ${PROMETHEUS_URL} + grafanaUrl: ${GRAFANA_URL} apiPrometheusPort: [${API_PROM_PORT}] userPrometheusPort: [ ${USER_PROM_PORT} ] friendPrometheusPort: [ ${FRIEND_PROM_PORT} ] diff --git a/docker-compose.yml b/docker-compose.yml index bdfee3748..5b1e11d4e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -167,6 +167,12 @@ services: # hostname: grafana # user: root # restart: always + # environment: + # - GF_SECURITY_ALLOW_EMBEDDING=true + # - GF_SESSION_COOKIE_SAMESITE=none + # - GF_SESSION_COOKIE_SECURE=true + # - GF_AUTH_ANONYMOUS_ENABLED=true + # - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin # ports: # - "${GRAFANA_PORT:-13000}:3000" # volumes: diff --git a/internal/api/third.go b/internal/api/third.go index 37ec55098..0a1ef0fbe 100644 --- a/internal/api/third.go +++ b/internal/api/third.go @@ -130,5 +130,5 @@ func (o *ThirdApi) SearchLogs(c *gin.Context) { } func GetPrometheus(c *gin.Context) { - c.Redirect(http.StatusFound, config2.Config.Prometheus.PrometheusUrl) + c.Redirect(http.StatusFound, config2.Config.Prometheus.GrafanaUrl) } diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index ea26ca677..88e87e709 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -314,7 +314,7 @@ type configStruct struct { Prometheus struct { Enable bool `yaml:"enable"` - PrometheusUrl string `yaml:"prometheusUrl"` + GrafanaUrl string `yaml:"grafanaUrl"` ApiPrometheusPort []int `yaml:"apiPrometheusPort"` UserPrometheusPort []int `yaml:"userPrometheusPort"` FriendPrometheusPort []int `yaml:"friendPrometheusPort"` diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh index 0e3a428e8..22a0996fc 100755 --- a/scripts/install/environment.sh +++ b/scripts/install/environment.sh @@ -285,7 +285,6 @@ readonly ALERTMANAGER_SEND_RESOLVED=${ALERTMANAGER_SEND_RESOLVED:-"{SEND_RESOLVE ###################### Grafana 配置信息 ###################### def "GRAFANA_PORT" "13000" # Grafana的端口 def "GRAFANA_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # Grafana的地址 - ###################### RPC Port Configuration Variables ###################### # For launching multiple programs, just fill in multiple ports separated by commas # For example: @@ -379,7 +378,7 @@ def "CALLBACK_FAILED_CONTINUE" "true" # 失败后是否继续 ###################### Prometheus 配置信息 ###################### # 是否启用 Prometheus readonly PROMETHEUS_ENABLE=${PROMETHEUS_ENABLE:-'true'} -def "PROMETHEUS_URL" "${GRAFANA_ADDRESS}:${GRAFANA_PORT}" +readonly GRAFANA_URL=${GRAFANA_URL:-"http://${OPENIM_IP}:${GRAFANA_PORT}/"} # Api 服务的 Prometheus 端口 readonly API_PROM_PORT=${API_PROM_PORT:-'20100'} # User 服务的 Prometheus 端口 From bed112d037333c4a78ba8cf17f490aefbe3ec239 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Sat, 30 Dec 2023 11:12:19 +0800 Subject: [PATCH 30/31] Update check-all.sh (#1643) --- scripts/check-all.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/check-all.sh b/scripts/check-all.sh index 48c38331d..7b53e4a89 100755 --- a/scripts/check-all.sh +++ b/scripts/check-all.sh @@ -30,16 +30,18 @@ OPENIM_VERBOSE=4 openim::log::info "\n# Begin to check all openim service" +# Elegant printing function # Elegant printing function print_services_and_ports() { - local -n service_names=$1 - local -n service_ports=$2 + local service_names=("$@") + local half_length=$((${#service_names[@]} / 2)) + local service_ports=("${service_names[@]:half_length}") echo "+-------------------------+----------+" echo "| Service Name | Port |" echo "+-------------------------+----------+" - for index in "${!service_names[@]}"; do + for ((index=0; index < half_length; index++)); do printf "| %-23s | %-8s |\n" "${service_names[$index]}" "${service_ports[$index]}" done @@ -50,11 +52,10 @@ print_services_and_ports() { # Similarly for OPENIM_DEPENDENCY_TARGETS and OPENIM_DEPENDENCY_PORT_TARGETS # Print out services and their ports -print_services_and_ports OPENIM_SERVER_NAME_TARGETS OPENIM_SERVER_PORT_TARGETS +print_services_and_ports "${OPENIM_SERVER_NAME_TARGETS[@]}" "${OPENIM_SERVER_PORT_TARGETS[@]}" # Print out dependencies and their ports -print_services_and_ports OPENIM_DEPENDENCY_TARGETS OPENIM_DEPENDENCY_PORT_TARGETS - +print_services_and_ports "${OPENIM_DEPENDENCY_TARGETS[@]}" "${OPENIM_DEPENDENCY_PORT_TARGETS[@]}" # OpenIM check echo "++ The port being checked: ${OPENIM_SERVER_PORT_LISTARIES[@]}" @@ -91,4 +92,4 @@ else echo "++++ Check all openim service ports successfully !" fi -set -e \ No newline at end of file +set -e From 49f4e3f0deaa4c165d1f3d2bcc1d35368544401f Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Mon, 1 Jan 2024 21:11:57 +0800 Subject: [PATCH 31/31] fix: fix Security vulnerability (#1646) Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com> --- docker-compose.yml | 2 +- pkg/common/discoveryregister/kubernetes/kubernetes.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5b1e11d4e..fd71896a7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -124,7 +124,7 @@ services: ## Uncomment and configure the following services as needed # openim-admin: - # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0 + # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin:toc-base-open-docker.35 # container_name: openim-admin # restart: always # ports: diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go index 2ff1539e6..c10518056 100644 --- a/pkg/common/discoveryregister/kubernetes/kubernetes.go +++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go @@ -55,14 +55,17 @@ func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.Dial return nil } + func (cli *K8sDR) UnRegister() error { return nil } + func (cli *K8sDR) CreateRpcRootNodes(serviceNames []string) error { return nil } + func (cli *K8sDR) RegisterConf2Registry(key string, conf []byte) error { return nil @@ -123,6 +126,8 @@ func getMsgGatewayHost(ctx context.Context) []string { log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret) return ret } + +// GetConns returns the gRPC client connections to the specified service. func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName { @@ -142,6 +147,7 @@ func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc return ret, nil } } + func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { return grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...) @@ -151,9 +157,11 @@ func (cli *K8sDR) GetSelfConnTarget() string { return cli.rpcRegisterAddr } + func (cli *K8sDR) AddOption(opts ...grpc.DialOption) { cli.options = append(cli.options, opts...) } + func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) { conn.Close() }