From d3315ae3dd0d3527512a85e2876cc8198068c035 Mon Sep 17 00:00:00 2001 From: withchao <48119764+withchao@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:46:36 -0500 Subject: [PATCH 1/6] chore: add api timeout and im admin token cache #241 (#242) * fix: im api UserToken error non-responsive body * fix: set rand seed * fix: set rand seed * update version * fix: optimize error code * fix: optimize error code * fix: chat admin userID * fix: chat admin userID * fix: chat admin userID * feat: add SearchFriend * feat: add SearchFriend * feat: add SearchFriend * feat: add SearchFriend * feat: add SearchFriend * fix: admin char length * fix: phone already register code * feat: add api caller timeout * feat: add api caller timeout * feat: im admin token cache * feat: im admin token cache * feat: im admin token cache * chore: update pkg github.com/openimsdk/tools --- go.mod | 2 +- go.sum | 4 ++-- pkg/common/apicall/call.go | 10 +++++++++- pkg/common/apicall/caller.go | 26 ++++++++++++++++++++++---- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index c13e437a..26a3cd66 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( require ( github.com/OpenIMSDK/protocol v0.0.21 - github.com/OpenIMSDK/tools v0.0.14 + github.com/OpenIMSDK/tools v0.0.15 github.com/go-zookeeper/zk v1.0.3 github.com/redis/go-redis/v9 v9.1.0 ) diff --git a/go.sum b/go.sum index 4b7cc0b9..fb0e285e 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/OpenIMSDK/open_utils v1.0.8 h1:IopxWgJwEF5ZAPsRuiZZOfcxNOQOCt/p8VDENc github.com/OpenIMSDK/open_utils v1.0.8/go.mod h1:FLoaQblWUVKQgqt2LrNzfSZLT6D3DICBn1kcOMDLUOI= github.com/OpenIMSDK/protocol v0.0.21 h1:5H6H+hJ9d/VgRqttvxD/zfK9Asd+4M8Eknk5swSbUVY= github.com/OpenIMSDK/protocol v0.0.21/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/OpenIMSDK/tools v0.0.15 h1:FF3m0TQUG56pJC15a11jmBG6Y1EjXarEW4JV3CBF/Jc= +github.com/OpenIMSDK/tools v0.0.15/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 h1:iC9YFYKDGEy3n/FtqJnOkZsene9olVspKmkX5A2YBEo= github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc= github.com/alibabacloud-go/darabonba-openapi v0.1.18/go.mod h1:PB4HffMhJVmAgNKNq3wYbTUlFvPgxJpTzd1F5pTuUsc= diff --git a/pkg/common/apicall/call.go b/pkg/common/apicall/call.go index 3ee2bb08..870ef094 100644 --- a/pkg/common/apicall/call.go +++ b/pkg/common/apicall/call.go @@ -21,6 +21,7 @@ import ( "errors" "io" "net/http" + "time" "github.com/OpenIMSDK/chat/pkg/common/constant" constant2 "github.com/OpenIMSDK/protocol/constant" @@ -36,6 +37,10 @@ type baseApiResponse[T any] struct { Data *T `json:"data"` } +var client = &http.Client{ + Timeout: time.Second * 10, +} + type ApiCaller[Req, Resp any] interface { Call(ctx context.Context, req *Req) (*Resp, error) } @@ -64,6 +69,9 @@ func (a caller[Req, Resp]) Call(ctx context.Context, req *Req) (*Resp, error) { func (a caller[Req, Resp]) call(ctx context.Context, req *Req) (*Resp, error) { url := a.prefix() + a.api + defer func(start time.Time) { + log.ZDebug(ctx, "api call caller time", "api", a.api, "cost", time.Since(start).String()) + }(time.Now()) log.ZInfo(ctx, "caller req", "addr", url, "req", req) reqBody, err := json.Marshal(req) if err != nil { @@ -79,7 +87,7 @@ func (a caller[Req, Resp]) call(ctx context.Context, req *Req) (*Resp, error) { request.Header.Set(constant2.Token, token) log.ZDebug(ctx, "req token", "token", token) } - response, err := http.DefaultClient.Do(request) + response, err := client.Do(request) if err != nil { return nil, err } diff --git a/pkg/common/apicall/caller.go b/pkg/common/apicall/caller.go index 93cef4b3..f60fbb6d 100644 --- a/pkg/common/apicall/caller.go +++ b/pkg/common/apicall/caller.go @@ -16,7 +16,9 @@ package apicall import ( "context" - "fmt" + "github.com/OpenIMSDK/tools/log" + "sync" + "time" "github.com/OpenIMSDK/chat/pkg/common/config" "github.com/OpenIMSDK/protocol/auth" @@ -40,7 +42,11 @@ type CallerInterface interface { FriendUserIDs(ctx context.Context, userID string) ([]string, error) } -type Caller struct{} +type Caller struct { + token string + timeout time.Time + lock sync.Mutex +} func NewCallerInterface() CallerInterface { return &Caller{} @@ -58,11 +64,23 @@ func (c *Caller) ImportFriend(ctx context.Context, ownerUserID string, friendUse } func (c *Caller) ImAdminTokenWithDefaultAdmin(ctx context.Context) (string, error) { - return c.UserToken(ctx, config.GetDefaultIMAdmin(), constant.AdminPlatformID) + c.lock.Lock() + defer c.lock.Unlock() + if c.token == "" || c.timeout.Before(time.Now()) { + userID := config.GetDefaultIMAdmin() + token, err := c.UserToken(ctx, config.GetDefaultIMAdmin(), constant.AdminPlatformID) + if err != nil { + log.ZError(ctx, "get im admin token", err, "userID", userID) + return "", err + } + log.ZDebug(ctx, "get im admin token", "userID", userID) + c.token = token + c.timeout = time.Now().Add(time.Minute * 5) + } + return c.token, nil } func (c *Caller) UserToken(ctx context.Context, userID string, platformID int32) (string, error) { - fmt.Println(*config.Config.Secret) resp, err := userToken.Call(ctx, &auth.UserTokenReq{ Secret: *config.Config.Secret, PlatformID: platformID, From 8835023d9dd3d69f3e95d0f7a22b5ddc490c2e51 Mon Sep 17 00:00:00 2001 From: withchao <48119764+withchao@users.noreply.github.com> Date: Thu, 26 Oct 2023 01:50:06 -0500 Subject: [PATCH 2/6] chore: update tools pkg (#245) * fix: im api UserToken error non-responsive body * fix: set rand seed * fix: set rand seed * update version * fix: optimize error code * fix: optimize error code * fix: chat admin userID * fix: chat admin userID * fix: chat admin userID * feat: add SearchFriend * feat: add SearchFriend * feat: add SearchFriend * feat: add SearchFriend * feat: add SearchFriend * fix: admin char length * fix: phone already register code * feat: add api caller timeout * feat: add api caller timeout * feat: im admin token cache * feat: im admin token cache * feat: im admin token cache * chore: update pkg github.com/openimsdk/tools * chore: update pkg github.com/openimsdk/tools * chore: update pkg github.com/openimsdk/tools --- pkg/common/chatrpcstart/start.go | 2 +- pkg/common/config/parse.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/common/chatrpcstart/start.go b/pkg/common/chatrpcstart/start.go index 882487da..10785bc5 100644 --- a/pkg/common/chatrpcstart/start.go +++ b/pkg/common/chatrpcstart/start.go @@ -42,7 +42,7 @@ func Start(rpcPort int, rpcRegisterName string, prometheusPort int, rpcFn func(c if err != nil { return errs.Wrap(err) } - defer zkClient.CloseZK() + defer zkClient.Close() zkClient.AddOption(chatMw.AddUserType(), mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials())) registerIP, err := network.GetRpcRegisterIP(config.Config.Rpc.RegisterIP) if err != nil { diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go index a5f38e34..f6bd7fcd 100644 --- a/pkg/common/config/parse.go +++ b/pkg/common/config/parse.go @@ -72,7 +72,7 @@ func InitConfig(configFile string) error { if err != nil { return utils.Wrap(err, "conn zk error ") } - defer zk.CloseZK() + defer zk.Close() var openIMConfigData []byte for i := 0; i < 100; i++ { var err error From 31aff39821f30a915253861a431fb79ccbaad0c6 Mon Sep 17 00:00:00 2001 From: Brabem <69128477+luhaoling@users.noreply.github.com> Date: Thu, 2 Nov 2023 17:23:03 +0800 Subject: [PATCH 3/6] Support email registration (#230) --- cmd/api/chat-api/main.go | 4 +- config/config.yaml | 9 + go.mod | 2 + go.sum | 4 + internal/rpc/admin/admin.go | 5 +- internal/rpc/chat/chat.go | 7 + internal/rpc/chat/login.go | 62 +- pkg/common/config/config.go | 9 + pkg/common/db/database/chat.go | 5 + pkg/common/db/model/chat/attribute.go | 5 + pkg/common/db/table/chat/attribute.go | 1 + pkg/email/mail.go | 59 ++ pkg/proto/chat/chat.pb.go | 1074 +++++++++++++------------ pkg/proto/chat/chat.proto | 2 + 14 files changed, 703 insertions(+), 545 deletions(-) create mode 100644 pkg/email/mail.go diff --git a/cmd/api/chat-api/main.go b/cmd/api/chat-api/main.go index c26d5412..ef3632c7 100644 --- a/cmd/api/chat-api/main.go +++ b/cmd/api/chat-api/main.go @@ -17,12 +17,14 @@ package main import ( "flag" "fmt" - "github.com/OpenIMSDK/chat/tools/component" + "math/rand" "net" "strconv" "time" + "github.com/OpenIMSDK/chat/tools/component" + mw2 "github.com/OpenIMSDK/chat/pkg/common/mw" "github.com/OpenIMSDK/chat/internal/api" diff --git a/config/config.yaml b/config/config.yaml index 11698012..72950451 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -80,6 +80,15 @@ verifyCode: 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 + # 获取ip的header,没有配置直接获取远程地址 #proxyHeader: "X-Forwarded-For" diff --git a/go.mod b/go.mod index 26a3cd66..828403ef 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/OpenIMSDK/tools v0.0.15 github.com/go-zookeeper/zk v1.0.3 github.com/redis/go-redis/v9 v9.1.0 + gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df ) require ( @@ -87,6 +88,7 @@ require ( golang.org/x/sys v0.10.0 // indirect golang.org/x/text v0.11.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/go.sum b/go.sum index fb0e285e..5a4bc1f8 100644 --- a/go.sum +++ b/go.sum @@ -291,10 +291,14 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/internal/rpc/admin/admin.go b/internal/rpc/admin/admin.go index bf51d7c6..1486ec51 100644 --- a/internal/rpc/admin/admin.go +++ b/internal/rpc/admin/admin.go @@ -64,9 +64,8 @@ func Start(discov discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e panic(err) } - admin.RegisterAdminServer(server, &adminServer{ - Database: database.NewAdminDatabase(db, rdb), - Chat: chat.NewChatClient(discov), + admin.RegisterAdminServer(server, &adminServer{Database: database.NewAdminDatabase(db, rdb), + Chat: chat.NewChatClient(discov), }) return nil } diff --git a/internal/rpc/chat/chat.go b/internal/rpc/chat/chat.go index 2d202be7..2661f6ab 100644 --- a/internal/rpc/chat/chat.go +++ b/internal/rpc/chat/chat.go @@ -22,6 +22,7 @@ import ( "github.com/OpenIMSDK/chat/pkg/common/db/database" chat2 "github.com/OpenIMSDK/chat/pkg/common/db/table/chat" "github.com/OpenIMSDK/chat/pkg/common/dbconn" + "github.com/OpenIMSDK/chat/pkg/email" "github.com/OpenIMSDK/chat/pkg/proto/chat" chatClient "github.com/OpenIMSDK/chat/pkg/rpclient/chat" "github.com/OpenIMSDK/chat/pkg/sms" @@ -47,6 +48,10 @@ func Start(discov discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e if err != nil { return err } + email, err := email.NewMail() + if err != nil { + return err + } if err := discov.CreateRpcRootNodes([]string{config.Config.RpcRegisterName.OpenImAdminName, config.Config.RpcRegisterName.OpenImChatName}); err != nil { panic(err) } @@ -54,6 +59,7 @@ func Start(discov discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e Database: database.NewChatDatabase(db), Admin: chatClient.NewAdminClient(discov), SMS: s, + Mail: email, }) return nil } @@ -62,4 +68,5 @@ type chatSvr struct { Database database.ChatDatabaseInterface Admin *chatClient.AdminClient SMS sms.SMS + Mail email.Mail } diff --git a/internal/rpc/chat/login.go b/internal/rpc/chat/login.go index a70c125d..6cf70509 100644 --- a/internal/rpc/chat/login.go +++ b/internal/rpc/chat/login.go @@ -16,12 +16,13 @@ package chat import ( "context" - "github.com/OpenIMSDK/chat/pkg/common/mctx" "math/rand" "strconv" "strings" "time" + "github.com/OpenIMSDK/chat/pkg/common/mctx" + constant2 "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/tools/errs" @@ -57,14 +58,26 @@ func (o *chatSvr) SendVerifyCode(ctx context.Context, req *chat.SendVerifyCodeRe if _, err := strconv.ParseUint(req.AreaCode[1:], 10, 64); err != nil { return nil, errs.ErrArgs.Wrap("area code must be number") } - if _, err := strconv.ParseUint(req.PhoneNumber, 10, 64); err != nil { - return nil, errs.ErrArgs.Wrap("phone number must be number") - } - _, err := o.Database.TakeAttributeByPhone(ctx, req.AreaCode, req.PhoneNumber) - if err == nil { - return nil, eerrs.ErrPhoneAlreadyRegister.Wrap("phone already register") - } else if !o.Database.IsNotFound(err) { - return nil, err + if req.PhoneNumber != "" { + if _, err := strconv.ParseUint(req.PhoneNumber, 10, 64); err != nil { + return nil, errs.ErrArgs.Wrap("phone number must be number") + } + _, err := o.Database.TakeAttributeByPhone(ctx, req.AreaCode, req.PhoneNumber) + if err == nil { + return nil, eerrs.ErrPhoneAlreadyRegister.Wrap("phone already register") + } else if !o.Database.IsNotFound(err) { + return nil, err + } + } else { + if err := chat.EmailCheck(req.Email); err != nil { + return nil, errs.ErrArgs.Wrap("email must be right") + } + _, err := o.Database.TakeAttributeByEmail(ctx, req.Email) + if err == nil { + return nil, eerrs.ErrPhoneAlreadyRegister.Wrap("phone already register") + } else if !o.Database.IsNotFound(err) { + return nil, err + } } conf, err := o.Admin.GetConfig(ctx) if err != nil { @@ -106,15 +119,30 @@ func (o *chatSvr) SendVerifyCode(ctx context.Context, req *chat.SendVerifyCodeRe if verifyCode.MaxCount < int(count) { return nil, eerrs.ErrVerifyCodeSendFrequently.Wrap() } + var account string + var isEmail bool + if req.PhoneNumber != "" { + account = o.verifyCodeJoin(req.AreaCode, req.PhoneNumber) + } else { + isEmail = true + account = req.Email + } t := &chat2.VerifyCode{ - Account: o.verifyCodeJoin(req.AreaCode, req.PhoneNumber), + Account: account, Code: o.genVerifyCode(), Duration: uint(config.Config.VerifyCode.ValidTime), CreateTime: time.Now(), } - err = o.Database.AddVerifyCode(ctx, t, func() error { - return o.SMS.SendCode(ctx, req.AreaCode, req.PhoneNumber, t.Code) - }) + if !isEmail { + err = o.Database.AddVerifyCode(ctx, t, func() error { + return o.SMS.SendCode(ctx, req.AreaCode, req.PhoneNumber, t.Code) + }) + } else { + // 发送邮件验证码 + err = o.Database.AddVerifyCode(ctx, t, func() error { + return o.Mail.SendMail(ctx, req.Email, t.Code) + }) + } if err != nil { return nil, err } @@ -163,7 +191,13 @@ func (o *chatSvr) verifyCode(ctx context.Context, account string, verifyCode str func (o *chatSvr) VerifyCode(ctx context.Context, req *chat.VerifyCodeReq) (*chat.VerifyCodeResp, error) { defer log.ZDebug(ctx, "return") - if _, err := o.verifyCode(ctx, o.verifyCodeJoin(req.AreaCode, req.PhoneNumber), req.VerifyCode); err != nil { + var account string + if req.PhoneNumber != "" { + account = o.verifyCodeJoin(req.AreaCode, req.PhoneNumber) + } else { + account = req.Email + } + if _, err := o.verifyCode(ctx, account, req.VerifyCode); err != nil { return nil, err } return &chat.VerifyCodeResp{}, nil diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 74d41032..5a4b60cc 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -90,6 +90,15 @@ var Config struct { SignName string `yaml:"signName"` VerificationCodeTemplateCode string `yaml:"verificationCodeTemplateCode"` } `yaml:"ali"` + Mail struct { + Title string `yaml:"title"` + SenderMail string `yaml:"senderMail"` + SenderAuthorizationCode string `yaml:"senderAuthorizationCode"` + SmtpAddr string `yaml:"smtpAddr"` + SmtpPort int `yaml:"smtpPort"` + } `yaml:"mail"` + TestDepartMentID string `yaml:"testDepartMentID"` + ImAPIURL string `yaml:"imAPIURL"` } `yaml:"verifyCode"` ProxyHeader string `yaml:"proxyHeader"` AdminList []Admin `yaml:"adminList"` diff --git a/pkg/common/db/database/chat.go b/pkg/common/db/database/chat.go index d71db7d1..da3c1cd9 100644 --- a/pkg/common/db/database/chat.go +++ b/pkg/common/db/database/chat.go @@ -35,6 +35,7 @@ type ChatDatabaseInterface interface { FindAttribute(ctx context.Context, userIDs []string) ([]*table.Attribute, error) FindAttributeByAccount(ctx context.Context, accounts []string) ([]*table.Attribute, error) TakeAttributeByPhone(ctx context.Context, areaCode string, phoneNumber string) (*table.Attribute, error) + TakeAttributeByEmail(ctx context.Context, Email string) (*table.Attribute, error) TakeAttributeByAccount(ctx context.Context, account string) (*table.Attribute, error) TakeAttributeByUserID(ctx context.Context, userID string) (*table.Attribute, error) Search(ctx context.Context, normalUser int32, keyword string, gender int32, pageNumber int32, showNumber int32) (uint32, []*table.Attribute, error) @@ -132,6 +133,10 @@ func (o *ChatDatabase) TakeAttributeByPhone(ctx context.Context, areaCode string return o.attribute.TakePhone(ctx, areaCode, phoneNumber) } +func (o *ChatDatabase) TakeAttributeByEmail(ctx context.Context, email string) (*table.Attribute, error) { + return o.attribute.TakeEmail(ctx, email) +} + func (o *ChatDatabase) TakeAttributeByAccount(ctx context.Context, account string) (*table.Attribute, error) { return o.attribute.TakeAccount(ctx, account) } diff --git a/pkg/common/db/model/chat/attribute.go b/pkg/common/db/model/chat/attribute.go index 71e568dd..f4c9f085 100644 --- a/pkg/common/db/model/chat/attribute.go +++ b/pkg/common/db/model/chat/attribute.go @@ -67,6 +67,11 @@ func (o *Attribute) TakePhone(ctx context.Context, areaCode string, phoneNumber return &a, errs.Wrap(o.db.WithContext(ctx).Where("area_code = ? and phone_number = ?", areaCode, phoneNumber).First(&a).Error) } +func (o *Attribute) TakeEmail(ctx context.Context, email string) (*chat.Attribute, error) { + var a chat.Attribute + return &a, errs.Wrap(o.db.WithContext(ctx).Where("email = ?", email).First(&a).Error) +} + func (o *Attribute) TakeAccount(ctx context.Context, account string) (*chat.Attribute, error) { var a chat.Attribute return &a, errs.Wrap(o.db.WithContext(ctx).Where("account = ?", account).Take(&a).Error) diff --git a/pkg/common/db/table/chat/attribute.go b/pkg/common/db/table/chat/attribute.go index 3fd01a6e..e81e3185 100644 --- a/pkg/common/db/table/chat/attribute.go +++ b/pkg/common/db/table/chat/attribute.go @@ -51,6 +51,7 @@ type AttributeInterface interface { FindAccount(ctx context.Context, accounts []string) ([]*Attribute, error) Search(ctx context.Context, keyword string, genders []int32, page int32, size int32) (uint32, []*Attribute, error) TakePhone(ctx context.Context, areaCode string, phoneNumber string) (*Attribute, error) + TakeEmail(ctx context.Context, email string) (*Attribute, error) TakeAccount(ctx context.Context, account string) (*Attribute, error) Take(ctx context.Context, userID string) (*Attribute, error) SearchNormalUser(ctx context.Context, keyword string, forbiddenID []string, gender int32, page int32, size int32) (uint32, []*Attribute, error) diff --git a/pkg/email/mail.go b/pkg/email/mail.go new file mode 100644 index 00000000..b240c18e --- /dev/null +++ b/pkg/email/mail.go @@ -0,0 +1,59 @@ +// 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. + +package email + +import ( + "context" + "fmt" + + "github.com/OpenIMSDK/chat/pkg/common/config" + "github.com/OpenIMSDK/tools/errs" + + "gopkg.in/gomail.v2" +) + +func NewMail() (Mail, error) { + dail := gomail.NewDialer( + config.Config.VerifyCode.Mail.SmtpAddr, + config.Config.VerifyCode.Mail.SmtpPort, + config.Config.VerifyCode.Mail.SenderMail, + config.Config.VerifyCode.Mail.SenderAuthorizationCode) + return &mail{dail: dail}, nil +} + +type Mail interface { + Name() string + SendMail(ctx context.Context, mail string, verifyCode string) error +} + +type mail struct { + dail *gomail.Dialer +} + +func (a *mail) Name() string { + return "mail" +} + +func (a *mail) SendMail(ctx context.Context, mail string, verifyCode string) error { + m := gomail.NewMessage() + m.SetHeader(`From`, config.Config.VerifyCode.Mail.SenderMail) + m.SetHeader(`To`, []string{mail}...) + m.SetHeader(`Subject`, config.Config.VerifyCode.Mail.Title) + m.SetBody(`text/html`, fmt.Sprintf("您的验证码为:%s,该验证码5分钟内有效,请勿泄露于他人。", verifyCode)) + + // Send + err := a.dail.DialAndSend(m) + return errs.Wrap(err) +} diff --git a/pkg/proto/chat/chat.pb.go b/pkg/proto/chat/chat.pb.go index b0b82c0c..a0361582 100644 --- a/pkg/proto/chat/chat.pb.go +++ b/pkg/proto/chat/chat.pb.go @@ -14,14 +14,17 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.29.1 -// protoc v4.22.0 +// protoc-gen-go v1.31.0 +// protoc v3.21.6 // source: chat/chat.proto package chat import ( context "context" + reflect "reflect" + sync "sync" + common "github.com/OpenIMSDK/chat/pkg/proto/common" sdkws "github.com/OpenIMSDK/protocol/sdkws" wrapperspb "github.com/OpenIMSDK/protocol/wrapperspb" @@ -30,8 +33,6 @@ import ( status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( @@ -46,12 +47,12 @@ type UserIdentity struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email"` - AreaCode string `protobuf:"bytes,2,opt,name=areaCode,proto3" json:"areaCode"` - PhoneNumber string `protobuf:"bytes,3,opt,name=phoneNumber,proto3" json:"phoneNumber"` - DeviceID string `protobuf:"bytes,4,opt,name=deviceID,proto3" json:"deviceID"` - Platform int32 `protobuf:"varint,5,opt,name=platform,proto3" json:"platform"` - Account string `protobuf:"bytes,6,opt,name=account,proto3" json:"account"` + Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"` + AreaCode string `protobuf:"bytes,2,opt,name=areaCode,proto3" json:"areaCode,omitempty"` + PhoneNumber string `protobuf:"bytes,3,opt,name=phoneNumber,proto3" json:"phoneNumber,omitempty"` + DeviceID string `protobuf:"bytes,4,opt,name=deviceID,proto3" json:"deviceID,omitempty"` + Platform int32 `protobuf:"varint,5,opt,name=platform,proto3" json:"platform,omitempty"` + Account string `protobuf:"bytes,6,opt,name=account,proto3" json:"account,omitempty"` } func (x *UserIdentity) Reset() { @@ -133,20 +134,20 @@ type UpdateUserInfoReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID"` - Account *wrapperspb.StringValue `protobuf:"bytes,2,opt,name=account,proto3" json:"account"` - PhoneNumber *wrapperspb.StringValue `protobuf:"bytes,3,opt,name=phoneNumber,proto3" json:"phoneNumber"` - AreaCode *wrapperspb.StringValue `protobuf:"bytes,4,opt,name=areaCode,proto3" json:"areaCode"` - Email *wrapperspb.StringValue `protobuf:"bytes,5,opt,name=email,proto3" json:"email"` - Nickname *wrapperspb.StringValue `protobuf:"bytes,6,opt,name=nickname,proto3" json:"nickname"` - FaceURL *wrapperspb.StringValue `protobuf:"bytes,7,opt,name=faceURL,proto3" json:"faceURL"` - Gender *wrapperspb.Int32Value `protobuf:"bytes,8,opt,name=gender,proto3" json:"gender"` - Level *wrapperspb.Int32Value `protobuf:"bytes,9,opt,name=level,proto3" json:"level"` - Birth *wrapperspb.Int64Value `protobuf:"bytes,10,opt,name=birth,proto3" json:"birth"` - AllowAddFriend *wrapperspb.Int32Value `protobuf:"bytes,11,opt,name=allowAddFriend,proto3" json:"allowAddFriend"` - AllowBeep *wrapperspb.Int32Value `protobuf:"bytes,12,opt,name=allowBeep,proto3" json:"allowBeep"` - AllowVibration *wrapperspb.Int32Value `protobuf:"bytes,13,opt,name=allowVibration,proto3" json:"allowVibration"` - GlobalRecvMsgOpt *wrapperspb.Int32Value `protobuf:"bytes,14,opt,name=globalRecvMsgOpt,proto3" json:"globalRecvMsgOpt"` + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` + Account *wrapperspb.StringValue `protobuf:"bytes,2,opt,name=account,proto3" json:"account,omitempty"` + PhoneNumber *wrapperspb.StringValue `protobuf:"bytes,3,opt,name=phoneNumber,proto3" json:"phoneNumber,omitempty"` + AreaCode *wrapperspb.StringValue `protobuf:"bytes,4,opt,name=areaCode,proto3" json:"areaCode,omitempty"` + Email *wrapperspb.StringValue `protobuf:"bytes,5,opt,name=email,proto3" json:"email,omitempty"` + Nickname *wrapperspb.StringValue `protobuf:"bytes,6,opt,name=nickname,proto3" json:"nickname,omitempty"` + FaceURL *wrapperspb.StringValue `protobuf:"bytes,7,opt,name=faceURL,proto3" json:"faceURL,omitempty"` + Gender *wrapperspb.Int32Value `protobuf:"bytes,8,opt,name=gender,proto3" json:"gender,omitempty"` + Level *wrapperspb.Int32Value `protobuf:"bytes,9,opt,name=level,proto3" json:"level,omitempty"` + Birth *wrapperspb.Int64Value `protobuf:"bytes,10,opt,name=birth,proto3" json:"birth,omitempty"` + AllowAddFriend *wrapperspb.Int32Value `protobuf:"bytes,11,opt,name=allowAddFriend,proto3" json:"allowAddFriend,omitempty"` + AllowBeep *wrapperspb.Int32Value `protobuf:"bytes,12,opt,name=allowBeep,proto3" json:"allowBeep,omitempty"` + AllowVibration *wrapperspb.Int32Value `protobuf:"bytes,13,opt,name=allowVibration,proto3" json:"allowVibration,omitempty"` + GlobalRecvMsgOpt *wrapperspb.Int32Value `protobuf:"bytes,14,opt,name=globalRecvMsgOpt,proto3" json:"globalRecvMsgOpt,omitempty"` } func (x *UpdateUserInfoReq) Reset() { @@ -284,8 +285,8 @@ type UpdateUserInfoResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - FaceUrl string `protobuf:"bytes,1,opt,name=faceUrl,proto3" json:"faceUrl"` - NickName string `protobuf:"bytes,2,opt,name=nickName,proto3" json:"nickName"` + FaceUrl string `protobuf:"bytes,1,opt,name=faceUrl,proto3" json:"faceUrl,omitempty"` + NickName string `protobuf:"bytes,2,opt,name=nickName,proto3" json:"nickName,omitempty"` } func (x *UpdateUserInfoResp) Reset() { @@ -339,7 +340,7 @@ type FindUserPublicInfoReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UserIDs []string `protobuf:"bytes,1,rep,name=userIDs,proto3" json:"userIDs"` + UserIDs []string `protobuf:"bytes,1,rep,name=userIDs,proto3" json:"userIDs,omitempty"` } func (x *FindUserPublicInfoReq) Reset() { @@ -386,7 +387,7 @@ type FindUserPublicInfoResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Users []*common.UserPublicInfo `protobuf:"bytes,1,rep,name=users,proto3" json:"users"` + Users []*common.UserPublicInfo `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` } func (x *FindUserPublicInfoResp) Reset() { @@ -433,9 +434,9 @@ type SearchUserPublicInfoReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword"` - Pagination *sdkws.RequestPagination `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination"` - Genders int32 `protobuf:"varint,3,opt,name=genders,proto3" json:"genders"` + Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword,omitempty"` + Pagination *sdkws.RequestPagination `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` + Genders int32 `protobuf:"varint,3,opt,name=genders,proto3" json:"genders,omitempty"` } func (x *SearchUserPublicInfoReq) Reset() { @@ -496,8 +497,8 @@ type SearchUserPublicInfoResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total"` - Users []*common.UserPublicInfo `protobuf:"bytes,2,rep,name=users,proto3" json:"users"` + Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Users []*common.UserPublicInfo `protobuf:"bytes,2,rep,name=users,proto3" json:"users,omitempty"` } func (x *SearchUserPublicInfoResp) Reset() { @@ -551,7 +552,7 @@ type FindUserFullInfoReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UserIDs []string `protobuf:"bytes,1,rep,name=userIDs,proto3" json:"userIDs"` + UserIDs []string `protobuf:"bytes,1,rep,name=userIDs,proto3" json:"userIDs,omitempty"` } func (x *FindUserFullInfoReq) Reset() { @@ -598,7 +599,7 @@ type FindUserFullInfoResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Users []*common.UserFullInfo `protobuf:"bytes,1,rep,name=users,proto3" json:"users"` + Users []*common.UserFullInfo `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` } func (x *FindUserFullInfoResp) Reset() { @@ -645,13 +646,14 @@ type SendVerifyCodeReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UsedFor int32 `protobuf:"varint,1,opt,name=usedFor,proto3" json:"usedFor"` - Ip string `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip"` - InvitationCode string `protobuf:"bytes,3,opt,name=invitationCode,proto3" json:"invitationCode"` - DeviceID string `protobuf:"bytes,4,opt,name=deviceID,proto3" json:"deviceID"` - Platform int32 `protobuf:"varint,5,opt,name=platform,proto3" json:"platform"` - AreaCode string `protobuf:"bytes,6,opt,name=areaCode,proto3" json:"areaCode"` - PhoneNumber string `protobuf:"bytes,7,opt,name=phoneNumber,proto3" json:"phoneNumber"` + UsedFor int32 `protobuf:"varint,1,opt,name=usedFor,proto3" json:"usedFor,omitempty"` + Ip string `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip,omitempty"` + InvitationCode string `protobuf:"bytes,3,opt,name=invitationCode,proto3" json:"invitationCode,omitempty"` + DeviceID string `protobuf:"bytes,4,opt,name=deviceID,proto3" json:"deviceID,omitempty"` + Platform int32 `protobuf:"varint,5,opt,name=platform,proto3" json:"platform,omitempty"` + AreaCode string `protobuf:"bytes,6,opt,name=areaCode,proto3" json:"areaCode,omitempty"` + PhoneNumber string `protobuf:"bytes,7,opt,name=phoneNumber,proto3" json:"phoneNumber,omitempty"` + Email string `protobuf:"bytes,8,opt,name=email,proto3" json:"email,omitempty"` } func (x *SendVerifyCodeReq) Reset() { @@ -735,6 +737,13 @@ func (x *SendVerifyCodeReq) GetPhoneNumber() string { return "" } +func (x *SendVerifyCodeReq) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + type SendVerifyCodeResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -778,9 +787,10 @@ type VerifyCodeReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AreaCode string `protobuf:"bytes,1,opt,name=areaCode,proto3" json:"areaCode"` - PhoneNumber string `protobuf:"bytes,2,opt,name=phoneNumber,proto3" json:"phoneNumber"` - VerifyCode string `protobuf:"bytes,3,opt,name=verifyCode,proto3" json:"verifyCode"` + AreaCode string `protobuf:"bytes,1,opt,name=areaCode,proto3" json:"areaCode,omitempty"` + PhoneNumber string `protobuf:"bytes,2,opt,name=phoneNumber,proto3" json:"phoneNumber,omitempty"` + VerifyCode string `protobuf:"bytes,3,opt,name=verifyCode,proto3" json:"verifyCode,omitempty"` + Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"` } func (x *VerifyCodeReq) Reset() { @@ -836,6 +846,13 @@ func (x *VerifyCodeReq) GetVerifyCode() string { return "" } +func (x *VerifyCodeReq) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + type VerifyCodeResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -879,16 +896,16 @@ type RegisterUserInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID"` - Nickname string `protobuf:"bytes,2,opt,name=nickname,proto3" json:"nickname"` - FaceURL string `protobuf:"bytes,3,opt,name=faceURL,proto3" json:"faceURL"` - Birth int64 `protobuf:"varint,4,opt,name=birth,proto3" json:"birth"` - Gender int32 `protobuf:"varint,5,opt,name=gender,proto3" json:"gender"` - AreaCode string `protobuf:"bytes,6,opt,name=areaCode,proto3" json:"areaCode"` - PhoneNumber string `protobuf:"bytes,7,opt,name=phoneNumber,proto3" json:"phoneNumber"` - Email string `protobuf:"bytes,8,opt,name=email,proto3" json:"email"` - Account string `protobuf:"bytes,9,opt,name=account,proto3" json:"account"` - Password string `protobuf:"bytes,10,opt,name=password,proto3" json:"password"` + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` + Nickname string `protobuf:"bytes,2,opt,name=nickname,proto3" json:"nickname,omitempty"` + FaceURL string `protobuf:"bytes,3,opt,name=faceURL,proto3" json:"faceURL,omitempty"` + Birth int64 `protobuf:"varint,4,opt,name=birth,proto3" json:"birth,omitempty"` + Gender int32 `protobuf:"varint,5,opt,name=gender,proto3" json:"gender,omitempty"` + AreaCode string `protobuf:"bytes,6,opt,name=areaCode,proto3" json:"areaCode,omitempty"` + PhoneNumber string `protobuf:"bytes,7,opt,name=phoneNumber,proto3" json:"phoneNumber,omitempty"` + Email string `protobuf:"bytes,8,opt,name=email,proto3" json:"email,omitempty"` + Account string `protobuf:"bytes,9,opt,name=account,proto3" json:"account,omitempty"` + Password string `protobuf:"bytes,10,opt,name=password,proto3" json:"password,omitempty"` } func (x *RegisterUserInfo) Reset() { @@ -998,13 +1015,13 @@ type RegisterUserReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - InvitationCode string `protobuf:"bytes,1,opt,name=invitationCode,proto3" json:"invitationCode"` - VerifyCode string `protobuf:"bytes,2,opt,name=verifyCode,proto3" json:"verifyCode"` - Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip"` - DeviceID string `protobuf:"bytes,4,opt,name=deviceID,proto3" json:"deviceID"` - Platform int32 `protobuf:"varint,5,opt,name=platform,proto3" json:"platform"` - AutoLogin bool `protobuf:"varint,6,opt,name=autoLogin,proto3" json:"autoLogin"` - User *RegisterUserInfo `protobuf:"bytes,7,opt,name=user,proto3" json:"user"` + InvitationCode string `protobuf:"bytes,1,opt,name=invitationCode,proto3" json:"invitationCode,omitempty"` + VerifyCode string `protobuf:"bytes,2,opt,name=verifyCode,proto3" json:"verifyCode,omitempty"` + Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"` + DeviceID string `protobuf:"bytes,4,opt,name=deviceID,proto3" json:"deviceID,omitempty"` + Platform int32 `protobuf:"varint,5,opt,name=platform,proto3" json:"platform,omitempty"` + AutoLogin bool `protobuf:"varint,6,opt,name=autoLogin,proto3" json:"autoLogin,omitempty"` + User *RegisterUserInfo `protobuf:"bytes,7,opt,name=user,proto3" json:"user,omitempty"` } func (x *RegisterUserReq) Reset() { @@ -1093,8 +1110,8 @@ type RegisterUserResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID"` - ChatToken string `protobuf:"bytes,3,opt,name=chatToken,proto3" json:"chatToken"` + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` + ChatToken string `protobuf:"bytes,3,opt,name=chatToken,proto3" json:"chatToken,omitempty"` } func (x *RegisterUserResp) Reset() { @@ -1148,14 +1165,14 @@ type LoginReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AreaCode string `protobuf:"bytes,1,opt,name=areaCode,proto3" json:"areaCode"` - PhoneNumber string `protobuf:"bytes,2,opt,name=phoneNumber,proto3" json:"phoneNumber"` - VerifyCode string `protobuf:"bytes,3,opt,name=verifyCode,proto3" json:"verifyCode"` - Account string `protobuf:"bytes,4,opt,name=account,proto3" json:"account"` - Password string `protobuf:"bytes,5,opt,name=password,proto3" json:"password"` - Platform int32 `protobuf:"varint,6,opt,name=platform,proto3" json:"platform"` - DeviceID string `protobuf:"bytes,7,opt,name=deviceID,proto3" json:"deviceID"` - Ip string `protobuf:"bytes,8,opt,name=ip,proto3" json:"ip"` + AreaCode string `protobuf:"bytes,1,opt,name=areaCode,proto3" json:"areaCode,omitempty"` + PhoneNumber string `protobuf:"bytes,2,opt,name=phoneNumber,proto3" json:"phoneNumber,omitempty"` + VerifyCode string `protobuf:"bytes,3,opt,name=verifyCode,proto3" json:"verifyCode,omitempty"` + Account string `protobuf:"bytes,4,opt,name=account,proto3" json:"account,omitempty"` + Password string `protobuf:"bytes,5,opt,name=password,proto3" json:"password,omitempty"` + Platform int32 `protobuf:"varint,6,opt,name=platform,proto3" json:"platform,omitempty"` + DeviceID string `protobuf:"bytes,7,opt,name=deviceID,proto3" json:"deviceID,omitempty"` + Ip string `protobuf:"bytes,8,opt,name=ip,proto3" json:"ip,omitempty"` } func (x *LoginReq) Reset() { @@ -1251,8 +1268,8 @@ type LoginResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ChatToken string `protobuf:"bytes,2,opt,name=chatToken,proto3" json:"chatToken"` - UserID string `protobuf:"bytes,3,opt,name=userID,proto3" json:"userID"` + ChatToken string `protobuf:"bytes,2,opt,name=chatToken,proto3" json:"chatToken,omitempty"` + UserID string `protobuf:"bytes,3,opt,name=userID,proto3" json:"userID,omitempty"` } func (x *LoginResp) Reset() { @@ -1306,10 +1323,10 @@ type ResetPasswordReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AreaCode string `protobuf:"bytes,1,opt,name=areaCode,proto3" json:"areaCode"` - PhoneNumber string `protobuf:"bytes,2,opt,name=phoneNumber,proto3" json:"phoneNumber"` - VerifyCode string `protobuf:"bytes,3,opt,name=verifyCode,proto3" json:"verifyCode"` - Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password"` + AreaCode string `protobuf:"bytes,1,opt,name=areaCode,proto3" json:"areaCode,omitempty"` + PhoneNumber string `protobuf:"bytes,2,opt,name=phoneNumber,proto3" json:"phoneNumber,omitempty"` + VerifyCode string `protobuf:"bytes,3,opt,name=verifyCode,proto3" json:"verifyCode,omitempty"` + Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"` } func (x *ResetPasswordReq) Reset() { @@ -1415,9 +1432,9 @@ type ChangePasswordReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID"` - CurrentPassword string `protobuf:"bytes,2,opt,name=currentPassword,proto3" json:"currentPassword"` - NewPassword string `protobuf:"bytes,3,opt,name=newPassword,proto3" json:"newPassword"` + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` + CurrentPassword string `protobuf:"bytes,2,opt,name=currentPassword,proto3" json:"currentPassword,omitempty"` + NewPassword string `protobuf:"bytes,3,opt,name=newPassword,proto3" json:"newPassword,omitempty"` } func (x *ChangePasswordReq) Reset() { @@ -1516,7 +1533,7 @@ type FindUserAccountReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UserIDs []string `protobuf:"bytes,1,rep,name=userIDs,proto3" json:"userIDs"` + UserIDs []string `protobuf:"bytes,1,rep,name=userIDs,proto3" json:"userIDs,omitempty"` } func (x *FindUserAccountReq) Reset() { @@ -1563,7 +1580,7 @@ type FindUserAccountResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UserAccountMap map[string]string `protobuf:"bytes,1,rep,name=userAccountMap,proto3" json:"userAccountMap" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // userID account + UserAccountMap map[string]string `protobuf:"bytes,1,rep,name=userAccountMap,proto3" json:"userAccountMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // userID account } func (x *FindUserAccountResp) Reset() { @@ -1610,7 +1627,7 @@ type FindAccountUserReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Accounts []string `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts"` + Accounts []string `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts,omitempty"` } func (x *FindAccountUserReq) Reset() { @@ -1657,7 +1674,7 @@ type FindAccountUserResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AccountUserMap map[string]string `protobuf:"bytes,1,rep,name=accountUserMap,proto3" json:"accountUserMap" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // account userID + AccountUserMap map[string]string `protobuf:"bytes,1,rep,name=accountUserMap,proto3" json:"accountUserMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // account userID } func (x *FindAccountUserResp) Reset() { @@ -1704,20 +1721,20 @@ type SignalRecord struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName"` - MediaType string `protobuf:"bytes,2,opt,name=mediaType,proto3" json:"mediaType"` - RoomType string `protobuf:"bytes,3,opt,name=roomType,proto3" json:"roomType"` - SenderID string `protobuf:"bytes,4,opt,name=senderID,proto3" json:"senderID"` - SenderNickname string `protobuf:"bytes,5,opt,name=senderNickname,proto3" json:"senderNickname"` - RecvID string `protobuf:"bytes,6,opt,name=recvID,proto3" json:"recvID"` - RecvNickname string `protobuf:"bytes,7,opt,name=recvNickname,proto3" json:"recvNickname"` - GroupID string `protobuf:"bytes,8,opt,name=groupID,proto3" json:"groupID"` - GroupName string `protobuf:"bytes,9,opt,name=groupName,proto3" json:"groupName"` - InviterUserList []*common.UserPublicInfo `protobuf:"bytes,10,rep,name=inviterUserList,proto3" json:"inviterUserList"` - Duration int32 `protobuf:"varint,11,opt,name=duration,proto3" json:"duration"` - CreateTime int64 `protobuf:"varint,12,opt,name=createTime,proto3" json:"createTime"` - Size string `protobuf:"bytes,13,opt,name=size,proto3" json:"size"` - DownloadURL string `protobuf:"bytes,14,opt,name=downloadURL,proto3" json:"downloadURL"` + FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"` + MediaType string `protobuf:"bytes,2,opt,name=mediaType,proto3" json:"mediaType,omitempty"` + RoomType string `protobuf:"bytes,3,opt,name=roomType,proto3" json:"roomType,omitempty"` + SenderID string `protobuf:"bytes,4,opt,name=senderID,proto3" json:"senderID,omitempty"` + SenderNickname string `protobuf:"bytes,5,opt,name=senderNickname,proto3" json:"senderNickname,omitempty"` + RecvID string `protobuf:"bytes,6,opt,name=recvID,proto3" json:"recvID,omitempty"` + RecvNickname string `protobuf:"bytes,7,opt,name=recvNickname,proto3" json:"recvNickname,omitempty"` + GroupID string `protobuf:"bytes,8,opt,name=groupID,proto3" json:"groupID,omitempty"` + GroupName string `protobuf:"bytes,9,opt,name=groupName,proto3" json:"groupName,omitempty"` + InviterUserList []*common.UserPublicInfo `protobuf:"bytes,10,rep,name=inviterUserList,proto3" json:"inviterUserList,omitempty"` + Duration int32 `protobuf:"varint,11,opt,name=duration,proto3" json:"duration,omitempty"` + CreateTime int64 `protobuf:"varint,12,opt,name=createTime,proto3" json:"createTime,omitempty"` + Size string `protobuf:"bytes,13,opt,name=size,proto3" json:"size,omitempty"` + DownloadURL string `protobuf:"bytes,14,opt,name=downloadURL,proto3" json:"downloadURL,omitempty"` } func (x *SignalRecord) Reset() { @@ -1855,8 +1872,8 @@ type AddSignalRecordReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SignalRecord *SignalRecord `protobuf:"bytes,1,opt,name=signalRecord,proto3" json:"signalRecord"` - OperationID string `protobuf:"bytes,2,opt,name=operationID,proto3" json:"operationID"` + SignalRecord *SignalRecord `protobuf:"bytes,1,opt,name=signalRecord,proto3" json:"signalRecord,omitempty"` + OperationID string `protobuf:"bytes,2,opt,name=operationID,proto3" json:"operationID,omitempty"` } func (x *AddSignalRecordReq) Reset() { @@ -1948,12 +1965,12 @@ type GetSignalRecordsReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Pagination *sdkws.RequestPagination `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination"` - SenderID string `protobuf:"bytes,2,opt,name=senderID,proto3" json:"senderID"` - RecvID string `protobuf:"bytes,3,opt,name=recvID,proto3" json:"recvID"` - MediaType string `protobuf:"bytes,4,opt,name=mediaType,proto3" json:"mediaType"` - CreateTime int64 `protobuf:"varint,5,opt,name=createTime,proto3" json:"createTime"` - OperationID string `protobuf:"bytes,6,opt,name=operationID,proto3" json:"operationID"` + Pagination *sdkws.RequestPagination `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` + SenderID string `protobuf:"bytes,2,opt,name=senderID,proto3" json:"senderID,omitempty"` + RecvID string `protobuf:"bytes,3,opt,name=recvID,proto3" json:"recvID,omitempty"` + MediaType string `protobuf:"bytes,4,opt,name=mediaType,proto3" json:"mediaType,omitempty"` + CreateTime int64 `protobuf:"varint,5,opt,name=createTime,proto3" json:"createTime,omitempty"` + OperationID string `protobuf:"bytes,6,opt,name=operationID,proto3" json:"operationID,omitempty"` } func (x *GetSignalRecordsReq) Reset() { @@ -2035,8 +2052,8 @@ type GetSignalRecordsResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - TotalNumber uint32 `protobuf:"varint,1,opt,name=totalNumber,proto3" json:"totalNumber"` - SignalRecords []*SignalRecord `protobuf:"bytes,2,rep,name=signalRecords,proto3" json:"signalRecords"` + TotalNumber uint32 `protobuf:"varint,1,opt,name=totalNumber,proto3" json:"totalNumber,omitempty"` + SignalRecords []*SignalRecord `protobuf:"bytes,2,rep,name=signalRecords,proto3" json:"signalRecords,omitempty"` } func (x *GetSignalRecordsResp) Reset() { @@ -2090,8 +2107,8 @@ type OpenIMCallbackReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Command string `protobuf:"bytes,1,opt,name=command,proto3" json:"command"` - Body string `protobuf:"bytes,2,opt,name=body,proto3" json:"body"` + Command string `protobuf:"bytes,1,opt,name=command,proto3" json:"command,omitempty"` + Body string `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` } func (x *OpenIMCallbackReq) Reset() { @@ -2183,10 +2200,10 @@ type SearchUserFullInfoReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword"` - Pagination *sdkws.RequestPagination `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination"` - Genders int32 `protobuf:"varint,3,opt,name=genders,proto3" json:"genders"` - Normal int32 `protobuf:"varint,4,opt,name=normal,proto3" json:"normal"` + Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword,omitempty"` + Pagination *sdkws.RequestPagination `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` + Genders int32 `protobuf:"varint,3,opt,name=genders,proto3" json:"genders,omitempty"` + Normal int32 `protobuf:"varint,4,opt,name=normal,proto3" json:"normal,omitempty"` } func (x *SearchUserFullInfoReq) Reset() { @@ -2254,8 +2271,8 @@ type SearchUserFullInfoResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total"` - Users []*common.UserFullInfo `protobuf:"bytes,2,rep,name=users,proto3" json:"users"` + Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Users []*common.UserFullInfo `protobuf:"bytes,2,rep,name=users,proto3" json:"users,omitempty"` } func (x *SearchUserFullInfoResp) Reset() { @@ -2309,8 +2326,8 @@ type UserLoginCountReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Start int64 `protobuf:"varint,1,opt,name=start,proto3" json:"start"` - End int64 `protobuf:"varint,2,opt,name=end,proto3" json:"end"` + Start int64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` + End int64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` } func (x *UserLoginCountReq) Reset() { @@ -2364,9 +2381,9 @@ type UserLoginCountResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - LoginCount int64 `protobuf:"varint,1,opt,name=loginCount,proto3" json:"loginCount"` - UnloginCount int64 `protobuf:"varint,2,opt,name=unloginCount,proto3" json:"unloginCount"` - Count map[string]int64 `protobuf:"bytes,3,rep,name=Count,proto3" json:"Count" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + LoginCount int64 `protobuf:"varint,1,opt,name=loginCount,proto3" json:"loginCount,omitempty"` + UnloginCount int64 `protobuf:"varint,2,opt,name=unloginCount,proto3" json:"unloginCount,omitempty"` + Count map[string]int64 `protobuf:"bytes,3,rep,name=Count,proto3" json:"Count,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` } func (x *UserLoginCountResp) Reset() { @@ -2427,8 +2444,8 @@ type FileURL struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename"` - URL string `protobuf:"bytes,2,opt,name=URL,proto3" json:"URL"` + Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"` + URL string `protobuf:"bytes,2,opt,name=URL,proto3" json:"URL,omitempty"` } func (x *FileURL) Reset() { @@ -2482,11 +2499,11 @@ type UploadLogsReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Platform int32 `protobuf:"varint,1,opt,name=platform,proto3" json:"platform"` - FileURLs []*FileURL `protobuf:"bytes,2,rep,name=fileURLs,proto3" json:"fileURLs"` - SystemType string `protobuf:"bytes,3,opt,name=systemType,proto3" json:"systemType"` - Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version"` - Ex string `protobuf:"bytes,4,opt,name=ex,proto3" json:"ex"` + Platform int32 `protobuf:"varint,1,opt,name=platform,proto3" json:"platform,omitempty"` + FileURLs []*FileURL `protobuf:"bytes,2,rep,name=fileURLs,proto3" json:"fileURLs,omitempty"` + SystemType string `protobuf:"bytes,3,opt,name=systemType,proto3" json:"systemType,omitempty"` + Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"` + Ex string `protobuf:"bytes,4,opt,name=ex,proto3" json:"ex,omitempty"` } func (x *UploadLogsReq) Reset() { @@ -2599,7 +2616,7 @@ type DeleteLogsReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - LogIDs []string `protobuf:"bytes,1,rep,name=logIDs,proto3" json:"logIDs"` + LogIDs []string `protobuf:"bytes,1,rep,name=logIDs,proto3" json:"logIDs,omitempty"` } func (x *DeleteLogsReq) Reset() { @@ -2684,10 +2701,10 @@ type SearchLogsReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword"` - StartTime int64 `protobuf:"varint,2,opt,name=startTime,proto3" json:"startTime"` - EndTime int64 `protobuf:"varint,3,opt,name=endTime,proto3" json:"endTime"` - Pagination *sdkws.RequestPagination `protobuf:"bytes,4,opt,name=pagination,proto3" json:"pagination"` + Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword,omitempty"` + StartTime int64 `protobuf:"varint,2,opt,name=startTime,proto3" json:"startTime,omitempty"` + EndTime int64 `protobuf:"varint,3,opt,name=endTime,proto3" json:"endTime,omitempty"` + Pagination *sdkws.RequestPagination `protobuf:"bytes,4,opt,name=pagination,proto3" json:"pagination,omitempty"` } func (x *SearchLogsReq) Reset() { @@ -2755,8 +2772,8 @@ type SearchLogsResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - LogsInfos []*common.LogInfo `protobuf:"bytes,1,rep,name=LogsInfos,proto3" json:"LogsInfos"` - Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total"` + LogsInfos []*common.LogInfo `protobuf:"bytes,1,rep,name=LogsInfos,proto3" json:"LogsInfos,omitempty"` + Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *SearchLogsResp) Reset() { @@ -2810,10 +2827,10 @@ type SearchUserInfoReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword"` - Pagination *sdkws.RequestPagination `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination"` - Genders []int32 `protobuf:"varint,3,rep,packed,name=genders,proto3" json:"genders"` - UserIDs []string `protobuf:"bytes,4,rep,name=userIDs,proto3" json:"userIDs"` + Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword,omitempty"` + Pagination *sdkws.RequestPagination `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` + Genders []int32 `protobuf:"varint,3,rep,packed,name=genders,proto3" json:"genders,omitempty"` + UserIDs []string `protobuf:"bytes,4,rep,name=userIDs,proto3" json:"userIDs,omitempty"` } func (x *SearchUserInfoReq) Reset() { @@ -2881,8 +2898,8 @@ type SearchUserInfoResp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total"` - Users []*common.UserFullInfo `protobuf:"bytes,2,rep,name=users,proto3" json:"users"` + Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Users []*common.UserFullInfo `protobuf:"bytes,2,rep,name=users,proto3" json:"users,omitempty"` } func (x *SearchUserInfoResp) Reset() { @@ -3044,7 +3061,7 @@ var file_chat_chat_proto_rawDesc = []byte{ 0x35, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x56, + 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0xf1, 0x01, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x75, 0x73, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, @@ -3058,399 +3075,402 @@ var file_chat_chat_proto_rawDesc = []byte{ 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x22, 0x14, 0x0a, 0x12, 0x53, 0x65, 0x6e, 0x64, 0x56, 0x65, 0x72, 0x69, - 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x6d, 0x0a, 0x0d, 0x56, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x61, - 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, - 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, - 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, - 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x56, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x98, 0x02, 0x0a, 0x10, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, + 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x14, 0x0a, 0x12, 0x53, 0x65, + 0x6e, 0x64, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x22, 0x83, 0x01, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x10, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x98, 0x02, 0x0a, 0x10, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x61, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x66, 0x61, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x12, 0x14, 0x0a, 0x05, 0x62, + 0x69, 0x72, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x69, 0x72, 0x74, + 0x68, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x65, + 0x61, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x65, + 0x61, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, 0x6e, + 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x18, 0x0a, + 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x22, 0xf6, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x76, 0x69, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x1e, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, + 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, + 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x35, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, + 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x48, 0x0a, 0x10, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x61, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66, 0x61, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x12, 0x14, - 0x0a, 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, - 0x69, 0x72, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, - 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, - 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, - 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, - 0x61, 0x69, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, - 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, - 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, - 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0xf6, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x75, - 0x74, 0x6f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, - 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x35, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, - 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, - 0x48, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x63, - 0x68, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x63, 0x68, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xe6, 0x01, 0x0a, 0x08, 0x4c, 0x6f, - 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, - 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, - 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, - 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, - 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x49, 0x44, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x70, 0x22, 0x41, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x0a, - 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, - 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x8c, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, - 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, - 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, - 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, - 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x69, - 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x77, 0x0a, 0x11, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x12, 0x16, - 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x2e, 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, - 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x18, - 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x13, 0x46, 0x69, 0x6e, - 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x60, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, - 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, - 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, - 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, - 0x61, 0x70, 0x1a, 0x41, 0x0a, 0x13, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x30, 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x13, 0x46, 0x69, 0x6e, 0x64, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x60, 0x0a, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x61, - 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, - 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x61, - 0x70, 0x1a, 0x41, 0x0a, 0x13, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdb, 0x03, 0x0a, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, - 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x72, 0x6f, 0x6f, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x72, 0x6f, 0x6f, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x44, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x72, 0x65, 0x63, 0x76, 0x49, 0x44, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x72, 0x65, 0x63, 0x76, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x63, 0x76, 0x4e, - 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, - 0x65, 0x63, 0x76, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x49, 0x44, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, - 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x4f, + 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x74, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, + 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xe6, 0x01, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, + 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x20, 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, + 0x6f, 0x72, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, + 0x6f, 0x72, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x22, + 0x41, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1c, 0x0a, 0x09, + 0x63, 0x68, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x63, 0x68, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, + 0x65, 0x72, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, + 0x49, 0x44, 0x22, 0x8c, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, + 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, + 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x22, 0x13, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x77, 0x0a, 0x11, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x44, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, + 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, + 0x14, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x2e, 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, + 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x49, 0x44, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x13, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x60, 0x0a, + 0x0e, 0x75, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, + 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x0e, 0x75, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x1a, + 0x41, 0x0a, 0x13, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x61, + 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0x30, 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x13, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x60, 0x0a, 0x0e, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, + 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x1a, 0x41, + 0x0a, 0x13, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x61, 0x70, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0xdb, 0x03, 0x0a, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, + 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x6f, 0x6f, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x72, 0x6f, 0x6f, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6e, 0x64, + 0x65, 0x72, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, + 0x65, 0x72, 0x49, 0x44, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4e, 0x69, + 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x72, 0x65, 0x63, 0x76, 0x49, 0x44, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, + 0x63, 0x76, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x63, 0x76, 0x4e, 0x69, 0x63, 0x6b, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x63, 0x76, + 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x49, 0x44, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x4b, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4c, + 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x4f, 0x70, 0x65, 0x6e, + 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x69, 0x6e, + 0x76, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1a, 0x0a, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x20, 0x0a, + 0x0b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x22, + 0x79, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, + 0x72, 0x64, 0x52, 0x65, 0x71, 0x12, 0x41, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x4f, 0x70, + 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x0c, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x64, + 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x22, 0xf0, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x61, 0x67, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x73, 0x64, 0x6b, + 0x77, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, + 0x72, 0x65, 0x63, 0x76, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, + 0x63, 0x76, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, + 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x44, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x7d, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x20, 0x0a, 0x0b, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x43, + 0x0a, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, + 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, + 0x72, 0x64, 0x73, 0x22, 0x41, 0x0a, 0x11, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x61, 0x6c, + 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x14, 0x0a, 0x12, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x22, 0xaa, 0x01, 0x0a, + 0x15, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, + 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x73, 0x64, 0x6b, 0x77, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x67, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x64, 0x65, + 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x06, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x22, 0x65, 0x0a, 0x16, 0x53, 0x65, 0x61, + 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x35, 0x0a, 0x05, 0x75, 0x73, 0x65, + 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, + 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, + 0x22, 0x3b, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, + 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0xd8, 0x01, + 0x0a, 0x12, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x75, 0x6e, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x75, 0x6e, 0x6c, 0x6f, + 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x05, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x38, + 0x0a, 0x0a, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x37, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x65, + 0x55, 0x52, 0x4c, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x55, 0x52, 0x4c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, + 0x4c, 0x22, 0xab, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x73, + 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, + 0x34, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x52, 0x4c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x18, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, + 0x68, 0x61, 0x74, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x52, 0x4c, 0x52, 0x08, 0x66, 0x69, 0x6c, + 0x65, 0x55, 0x52, 0x4c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x0e, 0x0a, 0x02, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x65, 0x78, 0x22, + 0x10, 0x0a, 0x0e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x22, 0x27, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, + 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x49, 0x44, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x67, 0x49, 0x44, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0xa8, 0x01, 0x0a, + 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x12, 0x18, + 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x73, 0x64, 0x6b, 0x77, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x67, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x60, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x38, 0x0a, 0x09, 0x4c, 0x6f, 0x67, + 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x18, - 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, - 0x52, 0x4c, 0x22, 0x79, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, - 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x12, 0x41, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, + 0x2e, 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x4c, 0x6f, 0x67, 0x73, 0x49, 0x6e, + 0x66, 0x6f, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0xa8, 0x01, 0x0a, 0x11, 0x53, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x12, + 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x61, 0x67, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x73, 0x64, 0x6b, + 0x77, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x18, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x05, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x49, 0x44, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x44, 0x73, 0x22, 0x61, 0x0a, 0x12, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x12, 0x35, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x32, 0xe8, 0x0e, 0x0a, 0x04, 0x63, 0x68, 0x61, 0x74, + 0x12, 0x59, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, + 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, + 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x6b, 0x0a, 0x14, 0x53, + 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, + 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x29, 0x2e, + 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, + 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x65, 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, + 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x26, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x0c, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x6f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x15, 0x0a, - 0x13, 0x41, 0x64, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x22, 0xf0, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x12, 0x45, 0x0a, 0x0a, - 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, - 0x73, 0x64, 0x6b, 0x77, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x44, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x44, 0x12, - 0x16, 0x0a, 0x06, 0x72, 0x65, 0x63, 0x76, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x72, 0x65, 0x63, 0x76, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, - 0x54, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x64, 0x69, - 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, - 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x7d, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x20, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x12, 0x43, 0x0a, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, - 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, - 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x22, 0x41, 0x0a, 0x11, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, - 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x14, 0x0a, 0x12, 0x4f, 0x70, 0x65, - 0x6e, 0x49, 0x4d, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x22, - 0xaa, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, - 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, - 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, - 0x6f, 0x72, 0x64, 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x73, 0x64, 0x6b, 0x77, 0x73, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, - 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x67, 0x65, 0x6e, - 0x64, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x22, 0x65, 0x0a, 0x16, - 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x35, 0x0a, 0x05, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x4f, 0x70, - 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x75, 0x73, - 0x65, 0x72, 0x73, 0x22, 0x3b, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, - 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, - 0x22, 0xd8, 0x01, 0x0a, 0x12, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6c, 0x6f, 0x67, - 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x75, 0x6e, 0x6c, 0x6f, 0x67, - 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x75, - 0x6e, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x05, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x4f, 0x70, 0x65, - 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x2e, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x1a, 0x38, 0x0a, 0x0a, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x37, 0x0a, 0x07, 0x66, - 0x69, 0x6c, 0x65, 0x55, 0x52, 0x4c, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x52, 0x4c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x55, 0x52, 0x4c, 0x22, 0xab, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4c, - 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x12, 0x34, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x52, 0x4c, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, - 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x52, 0x4c, 0x52, 0x08, - 0x66, 0x69, 0x6c, 0x65, 0x55, 0x52, 0x4c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x79, 0x73, 0x74, - 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x65, 0x78, 0x22, 0x10, 0x0a, 0x0e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x22, 0x27, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4c, 0x6f, - 0x67, 0x73, 0x52, 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x49, 0x44, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x67, 0x49, 0x44, 0x73, 0x22, 0x10, 0x0a, - 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, - 0xa8, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, - 0x71, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x64, - 0x54, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x73, 0x64, 0x6b, 0x77, 0x73, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, - 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x60, 0x0a, 0x0e, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x38, 0x0a, 0x09, - 0x4c, 0x6f, 0x67, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x4c, 0x6f, 0x67, - 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0xa8, 0x01, 0x0a, - 0x11, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x45, 0x0a, 0x0a, - 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, - 0x73, 0x64, 0x6b, 0x77, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x05, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, - 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, 0x22, 0x61, 0x0a, 0x12, 0x53, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x14, 0x0a, - 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x12, 0x35, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x32, 0xe8, 0x0e, 0x0a, 0x04, 0x63, - 0x68, 0x61, 0x74, 0x12, 0x59, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, - 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x6b, - 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, - 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, - 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, - 0x1a, 0x29, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, - 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x65, 0x0a, 0x12, 0x46, - 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x26, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, - 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x27, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, - 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, - 0x73, 0x70, 0x12, 0x65, 0x0a, 0x12, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, - 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x26, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, - 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, - 0x1a, 0x27, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, - 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, - 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5f, 0x0a, 0x10, 0x46, 0x69, 0x6e, - 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x24, 0x2e, + 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x27, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, + 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, + 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x65, 0x0a, 0x12, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, + 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x26, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, + 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, + 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x27, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, - 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x71, 0x1a, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, - 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, - 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x59, 0x0a, 0x0e, 0x53, 0x65, - 0x6e, 0x64, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x2e, 0x4f, - 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, - 0x65, 0x6e, 0x64, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, - 0x61, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x0a, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, - 0x6f, 0x64, 0x65, 0x12, 0x1e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, - 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, - 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x12, 0x53, 0x0a, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x55, 0x73, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, - 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x21, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, - 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, 0x05, 0x4c, 0x6f, 0x67, - 0x69, 0x6e, 0x12, 0x19, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, - 0x63, 0x68, 0x61, 0x74, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, + 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5f, 0x0a, 0x10, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x24, 0x2e, 0x4f, 0x70, 0x65, + 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, + 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, + 0x1a, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, + 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x75, 0x6c, 0x6c, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x59, 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, + 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, + 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, - 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x56, 0x0a, 0x0d, 0x52, 0x65, 0x73, - 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x2e, 0x4f, 0x70, 0x65, + 0x53, 0x65, 0x6e, 0x64, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x0a, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x1e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, + 0x61, 0x74, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x1a, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, + 0x61, 0x74, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x53, 0x0a, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x12, 0x20, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, + 0x68, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x1a, 0x21, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, + 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, + 0x19, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, + 0x74, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, 0x4f, 0x70, 0x65, + 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x56, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x73, - 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x22, 0x2e, + 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x59, + 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, + 0x61, 0x74, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, + 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5c, 0x0a, 0x0f, 0x46, 0x69, 0x6e, + 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x4f, + 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, + 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x1a, 0x24, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, + 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5c, 0x0a, 0x0f, 0x46, 0x69, 0x6e, 0x64, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x23, 0x2e, 0x4f, 0x70, 0x65, + 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, + 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, + 0x24, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, + 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5c, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, + 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x24, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, - 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x59, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, - 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, - 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5c, 0x0a, 0x0f, - 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, - 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x52, 0x65, 0x71, 0x1a, 0x24, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, - 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5c, 0x0a, 0x0f, 0x46, 0x69, - 0x6e, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x23, 0x2e, + 0x41, 0x64, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x5f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, + 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x24, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, - 0x46, 0x69, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x1a, 0x24, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, - 0x63, 0x68, 0x61, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5c, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x23, 0x2e, 0x4f, 0x70, - 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x41, 0x64, - 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, - 0x1a, 0x24, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, - 0x61, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, - 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x24, 0x2e, 0x4f, 0x70, 0x65, - 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x1a, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, - 0x61, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, - 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x59, 0x0a, 0x0e, 0x4f, 0x70, 0x65, 0x6e, 0x49, - 0x4d, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x49, 0x4d, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, - 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, - 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x12, 0x59, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, - 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, - 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, - 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, - 0x0a, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x4f, 0x70, - 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x4f, 0x70, - 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x0a, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x4f, 0x70, 0x65, - 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x4f, 0x70, 0x65, - 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x0a, 0x53, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, + 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x59, 0x0a, 0x0e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x61, + 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, + 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, + 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, + 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x4f, 0x70, 0x65, + 0x6e, 0x49, 0x4d, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x59, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, + 0x68, 0x61, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, + 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x0a, 0x55, 0x70, + 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, + 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, + 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x0a, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x0a, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, + 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, + 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, + 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, + 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x59, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x59, 0x0a, 0x0e, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x4f, - 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x53, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, - 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, - 0x61, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x44, 0x4b, 0x2f, 0x63, 0x68, - 0x61, 0x74, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x68, 0x61, - 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, + 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x43, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, + 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x73, 0x70, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x44, 0x4b, 0x2f, 0x63, 0x68, 0x61, 0x74, 0x2f, + 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x68, 0x61, 0x74, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/proto/chat/chat.proto b/pkg/proto/chat/chat.proto index 97f6f0cd..b90ea09e 100644 --- a/pkg/proto/chat/chat.proto +++ b/pkg/proto/chat/chat.proto @@ -86,6 +86,7 @@ message SendVerifyCodeReq { int32 platform = 5; string areaCode = 6; string phoneNumber = 7; + string email= 8; } message SendVerifyCodeResp { @@ -95,6 +96,7 @@ message VerifyCodeReq { string areaCode = 1; string phoneNumber = 2; string verifyCode = 3; + string email = 4; } message VerifyCodeResp { From 595d5f3d95991751c2a42fa2b844d34d51ec53db Mon Sep 17 00:00:00 2001 From: Brabem <69128477+luhaoling@users.noreply.github.com> Date: Fri, 3 Nov 2023 10:56:24 +0800 Subject: [PATCH 4/6] feat: add send email test (#254) * Support email registration * add the email test * send email test * send email test * add the email test --- pkg/email/mail.go | 1 + pkg/email/mail_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 pkg/email/mail_test.go diff --git a/pkg/email/mail.go b/pkg/email/mail.go index b240c18e..73178a41 100644 --- a/pkg/email/mail.go +++ b/pkg/email/mail.go @@ -30,6 +30,7 @@ func NewMail() (Mail, error) { config.Config.VerifyCode.Mail.SmtpPort, config.Config.VerifyCode.Mail.SenderMail, config.Config.VerifyCode.Mail.SenderAuthorizationCode) + return &mail{dail: dail}, nil } diff --git a/pkg/email/mail_test.go b/pkg/email/mail_test.go new file mode 100644 index 00000000..daf40c67 --- /dev/null +++ b/pkg/email/mail_test.go @@ -0,0 +1,62 @@ +package email + +import ( + "context" + "errors" + "github.com/OpenIMSDK/chat/pkg/common/config" + "gopkg.in/yaml.v3" + "io/ioutil" + "testing" +) + +func TestEmail(T *testing.T) { + if err := InitConfig(); err != nil { + panic(err) + } + tests := []struct { + name string + ctx context.Context + mail string + code string + want error + }{ + { + name: "success send email", + ctx: context.Background(), + mail: "test@gmail.com", + code: "5555", + want: errors.New("nil"), + }, + { + name: "fail send email", + ctx: context.Background(), + mail: "", + code: "5555", + want: errors.New("dial tcp :0: connectex: The requested address is not valid in its context."), + }, + } + mail, err := NewMail() + if err != nil { + T.Errorf("Init mail failed,%v", err) + } + + for _, tt := range tests { + T.Run(tt.name, func(t *testing.T) { + if got := mail.SendMail(tt.ctx, tt.mail, tt.code); errors.Is(got, tt.want) { + t.Errorf("%v have a err,%v", tt.name, tt.want) + } + }) + } +} + +func InitConfig() error { + yam, err := ioutil.ReadFile("../../config/config.yaml") + if err != nil { + return err + } + err = yaml.Unmarshal(yam, &config.Config) + if err != nil { + return err + } + return nil +} From 9d432479723cb00a008418f0491b133062ac8d8b Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Tue, 7 Nov 2023 18:34:53 +0800 Subject: [PATCH 5/6] feat: super openim chat k8s deployment and code remould (#240) * Adapting to k8s environment: modify service discovery and service registration logic,modify config file reading logic * Submit initial chart script * change chat script * fix bug:if env.descovery==k8s,not check zk * fix bug:Implement option interface * fix bug:change K8sDR.Register * change config.yaml * docs: add openim chat options Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * docs: add openim flag Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * docs: add openim version Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * docs: add openim version Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * docs: add openim version Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * docs: add openim version Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * update the config code * update the config code * fix:solve the conflict * fix: fix the flag parse error * fix:slove the script error * fix:alter the config.yaml * fix:alter the comfig.yaml * fix:alter a scripts-test.yml --------- Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> Co-authored-by: lin.huang Co-authored-by: xuexihuang <1339326187@qq.com> Co-authored-by: luhaoling <2198702716@qq.com> --- .github/workflows/chatci.yml | 2 +- .github/workflows/docker-buildx.yml | 8 +- .github/workflows/scripts-test.yml | 8 +- .goreleaser.yaml | 8 +- Makefile | 76 +++++- build/README.md | 65 +++++ build/images/Dockerfile | 10 + build/{docker => images}/api-admin/Dockerfile | 14 +- build/{docker => images}/api-chat/Dockerfile | 17 +- build/{docker => images}/rpc-admin/Dockerfile | 20 +- build/{docker => images}/rpc-chat/Dockerfile | 17 +- cmd/api/admin-api/Makefile | 24 -- cmd/api/admin-api/main.go | 45 ++-- cmd/api/chat-api/Makefile | 24 -- cmd/api/chat-api/main.go | 48 ++-- cmd/rpc/admin-rpc/Makefile | 23 -- cmd/rpc/admin-rpc/main.go | 34 ++- cmd/rpc/chat-rpc/Makefile | 23 -- cmd/rpc/chat-rpc/main.go | 51 ++-- config/config.yaml | 5 +- deployment/helm-charts/.helmignore | 23 ++ deployment/helm-charts/Chart.yaml | 24 ++ .../helm-charts/charts/admin-rpc/.helmignore | 23 ++ .../helm-charts/charts/admin-rpc/Chart.yaml | 24 ++ .../charts/admin-rpc/templates/NOTES.txt | 22 ++ .../charts/admin-rpc/templates/_helpers.tpl | 62 +++++ .../admin-rpc/templates/deployment.yaml | 69 ++++++ .../charts/admin-rpc/templates/hpa.yaml | 28 +++ .../charts/admin-rpc/templates/ingress.yaml | 61 +++++ .../charts/admin-rpc/templates/service.yaml | 15 ++ .../admin-rpc/templates/serviceaccount.yaml | 12 + .../helm-charts/charts/admin-rpc/values.yaml | 82 +++++++ .../helm-charts/charts/chat-api/.helmignore | 23 ++ .../helm-charts/charts/chat-api/Chart.yaml | 24 ++ .../charts/chat-api/templates/NOTES.txt | 22 ++ .../charts/chat-api/templates/_helpers.tpl | 62 +++++ .../charts/chat-api/templates/deployment.yaml | 69 ++++++ .../charts/chat-api/templates/hpa.yaml | 28 +++ .../charts/chat-api/templates/ingress.yaml | 61 +++++ .../charts/chat-api/templates/service.yaml | 15 ++ .../chat-api/templates/serviceaccount.yaml | 12 + .../helm-charts/charts/chat-api/values.yaml | 84 +++++++ .../helm-charts/charts/chat-rpc/.helmignore | 23 ++ .../helm-charts/charts/chat-rpc/Chart.yaml | 24 ++ .../charts/chat-rpc/templates/NOTES.txt | 22 ++ .../charts/chat-rpc/templates/_helpers.tpl | 62 +++++ .../charts/chat-rpc/templates/deployment.yaml | 69 ++++++ .../charts/chat-rpc/templates/hpa.yaml | 28 +++ .../charts/chat-rpc/templates/ingress.yaml | 61 +++++ .../charts/chat-rpc/templates/service.yaml | 15 ++ .../chat-rpc/templates/serviceaccount.yaml | 12 + .../helm-charts/charts/chat-rpc/values.yaml | 82 +++++++ deployment/helm-charts/config.yaml | 112 +++++++++ deployment/helm-charts/templates/NOTES.txt | 22 ++ deployment/helm-charts/templates/_helpers.tpl | 62 +++++ deployment/helm-charts/templates/app-cm.yaml | 9 + .../helm-charts/templates/deployment.yaml | 69 ++++++ deployment/helm-charts/templates/hpa.yaml | 28 +++ deployment/helm-charts/templates/ingress.yaml | 61 +++++ deployment/helm-charts/templates/service.yaml | 15 ++ .../helm-charts/templates/serviceaccount.yaml | 12 + deployment/helm-charts/values.yaml | 84 +++++++ go.mod | 8 +- go.sum | 14 ++ internal/rpc/admin/register_add_group.go | 4 +- internal/rpc/chat/log.go | 5 +- internal/rpc/chat/statistic.go | 3 +- pkg/common/chatrpcstart/start.go | 15 +- pkg/common/config/config.go | 3 + pkg/common/config/parse.go | 228 +++++++++++++----- pkg/common/config/version | 2 +- pkg/common/constant/constant.go | 61 +++-- pkg/common/db/model/admin/admin.go | 4 +- pkg/common/db/model/chat/log.go | 4 +- pkg/common/db/model/chat/user_login_record.go | 3 +- pkg/common/version/base.go | 47 ++++ pkg/common/version/types.go | 20 ++ pkg/common/version/version.go | 38 +++ .../k8s_discovery_register.go | 94 ++++++++ pkg/proto/chat/chat.go | 4 +- pkg/sms/sms.go | 2 +- scripts/check_all.sh | 43 +++- scripts/start_all.sh | 2 +- tools/component/component.go | 26 +- 84 files changed, 2508 insertions(+), 361 deletions(-) create mode 100644 build/README.md create mode 100644 build/images/Dockerfile rename build/{docker => images}/api-admin/Dockerfile (73%) rename build/{docker => images}/api-chat/Dockerfile (72%) rename build/{docker => images}/rpc-admin/Dockerfile (65%) rename build/{docker => images}/rpc-chat/Dockerfile (68%) delete mode 100644 cmd/api/admin-api/Makefile delete mode 100644 cmd/api/chat-api/Makefile delete mode 100644 cmd/rpc/admin-rpc/Makefile delete mode 100644 cmd/rpc/chat-rpc/Makefile create mode 100644 deployment/helm-charts/.helmignore create mode 100644 deployment/helm-charts/Chart.yaml create mode 100644 deployment/helm-charts/charts/admin-rpc/.helmignore create mode 100644 deployment/helm-charts/charts/admin-rpc/Chart.yaml create mode 100644 deployment/helm-charts/charts/admin-rpc/templates/NOTES.txt create mode 100644 deployment/helm-charts/charts/admin-rpc/templates/_helpers.tpl create mode 100644 deployment/helm-charts/charts/admin-rpc/templates/deployment.yaml create mode 100644 deployment/helm-charts/charts/admin-rpc/templates/hpa.yaml create mode 100644 deployment/helm-charts/charts/admin-rpc/templates/ingress.yaml create mode 100644 deployment/helm-charts/charts/admin-rpc/templates/service.yaml create mode 100644 deployment/helm-charts/charts/admin-rpc/templates/serviceaccount.yaml create mode 100644 deployment/helm-charts/charts/admin-rpc/values.yaml create mode 100644 deployment/helm-charts/charts/chat-api/.helmignore create mode 100644 deployment/helm-charts/charts/chat-api/Chart.yaml create mode 100644 deployment/helm-charts/charts/chat-api/templates/NOTES.txt create mode 100644 deployment/helm-charts/charts/chat-api/templates/_helpers.tpl create mode 100644 deployment/helm-charts/charts/chat-api/templates/deployment.yaml create mode 100644 deployment/helm-charts/charts/chat-api/templates/hpa.yaml create mode 100644 deployment/helm-charts/charts/chat-api/templates/ingress.yaml create mode 100644 deployment/helm-charts/charts/chat-api/templates/service.yaml create mode 100644 deployment/helm-charts/charts/chat-api/templates/serviceaccount.yaml create mode 100644 deployment/helm-charts/charts/chat-api/values.yaml create mode 100644 deployment/helm-charts/charts/chat-rpc/.helmignore create mode 100644 deployment/helm-charts/charts/chat-rpc/Chart.yaml create mode 100644 deployment/helm-charts/charts/chat-rpc/templates/NOTES.txt create mode 100644 deployment/helm-charts/charts/chat-rpc/templates/_helpers.tpl create mode 100644 deployment/helm-charts/charts/chat-rpc/templates/deployment.yaml create mode 100644 deployment/helm-charts/charts/chat-rpc/templates/hpa.yaml create mode 100644 deployment/helm-charts/charts/chat-rpc/templates/ingress.yaml create mode 100644 deployment/helm-charts/charts/chat-rpc/templates/service.yaml create mode 100644 deployment/helm-charts/charts/chat-rpc/templates/serviceaccount.yaml create mode 100644 deployment/helm-charts/charts/chat-rpc/values.yaml create mode 100644 deployment/helm-charts/config.yaml create mode 100644 deployment/helm-charts/templates/NOTES.txt create mode 100644 deployment/helm-charts/templates/_helpers.tpl create mode 100644 deployment/helm-charts/templates/app-cm.yaml create mode 100644 deployment/helm-charts/templates/deployment.yaml create mode 100644 deployment/helm-charts/templates/hpa.yaml create mode 100644 deployment/helm-charts/templates/ingress.yaml create mode 100644 deployment/helm-charts/templates/service.yaml create mode 100644 deployment/helm-charts/templates/serviceaccount.yaml create mode 100644 deployment/helm-charts/values.yaml create mode 100644 pkg/common/version/base.go create mode 100644 pkg/common/version/types.go create mode 100644 pkg/common/version/version.go create mode 100644 pkg/discovery_register/k8s_discovery_register.go diff --git a/.github/workflows/chatci.yml b/.github/workflows/chatci.yml index 0d124f69..7f707246 100644 --- a/.github/workflows/chatci.yml +++ b/.github/workflows/chatci.yml @@ -47,7 +47,7 @@ jobs: strategy: matrix: - go_version: ["1.18","1.19","1.20"] + go_version: ["1.19","1.20","1.21"] os: [ubuntu-latest] steps: diff --git a/.github/workflows/docker-buildx.yml b/.github/workflows/docker-buildx.yml index d2543f30..224df06b 100644 --- a/.github/workflows/docker-buildx.yml +++ b/.github/workflows/docker-buildx.yml @@ -54,7 +54,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./build/docker/api-admin/Dockerfile + file: ./build/images/api-admin/Dockerfile platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta1.outputs.tags }} @@ -70,7 +70,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./build/docker/api-chat/Dockerfile + file: ./build/images/api-chat/Dockerfile platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta2.outputs.tags }} @@ -86,7 +86,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./build/docker/rpc-admin/Dockerfile + file: ./build/images/rpc-admin/Dockerfile platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta3.outputs.tags }} @@ -102,7 +102,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./build/docker/rpc-chat/Dockerfile + file: ./build/images/rpc-chat/Dockerfile platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta4.outputs.tags }} diff --git a/.github/workflows/scripts-test.yml b/.github/workflows/scripts-test.yml index edde4240..8ac23e69 100644 --- a/.github/workflows/scripts-test.yml +++ b/.github/workflows/scripts-test.yml @@ -49,10 +49,10 @@ jobs: - name: deploy all services run: | - git clone -b release-v3.1 https://github.com/OpenIMSDK/Open-IM-Server.git openim && export openim=$(pwd)/openim && cd $openim + git clone -b release-v3.3 https://github.com/OpenIMSDK/Open-IM-Server.git openim && export openim=$(pwd)/openim && cd $openim curl -o docker-compose.yaml https://gist.githubusercontent.com/cubxxw/b1d5cbd2edfa23fee911118aa3e8249e/raw/openim-chat.sh sudo docker compose up -d - sudo sleep 60 + sudo sleep 30 sudo chmod +x ./scripts/stop_all.sh sudo ./scripts/stop_all.sh @@ -82,10 +82,8 @@ jobs: - name: Check all services run: | - sudo ./scripts/check_all.sh - sudo cat ../logs/openIM.log 2>/dev/null + sudo sleep 15; ports=(10008 10009 30200 30300); for port in "${ports[@]}"; do if ! lsof -i :$port > /dev/null; then echo "The service is not started on port $port."; exit 1; else echo "The service is started normally on port $port."; fi; done; echo "All port services have been started normally." shell: bash - continue-on-error: true - name: Print openIM.log run: | diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 74558265..010f7140 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -232,7 +232,7 @@ changelog: # - "--platform=linux/amd64" # goos: linux # goarch: amd64 -# dockerfile: ./build/docker/api-chat/Dockerfile +# dockerfile: ./build/images/api-chat/Dockerfile # use: buildx # - image_templates: @@ -254,7 +254,7 @@ changelog: # - "--platform=linux/arm64" # goos: linux # goarch: arm64 -# dockerfile: ./build/docker/api-chat/Dockerfile +# dockerfile: ./build/images/api-chat/Dockerfile # use: buildx # - image_templates: @@ -276,7 +276,7 @@ changelog: # - "--platform=linux/amd64" # goos: linux # goarch: amd64 -# dockerfile: ./build/docker/api-admin/Dockerfile +# dockerfile: ./build/images/api-admin/Dockerfile # use: buildx # - image_templates: @@ -298,7 +298,7 @@ changelog: # - "--platform=linux/arm64" # goos: linux # goarch: arm64 -# dockerfile: ./build/docker/api-admin/Dockerfile +# dockerfile: ./build/images/api-admin/Dockerfile # use: buildx # docker_manifests: diff --git a/Makefile b/Makefile index 3e1a0fa0..a4924343 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,10 @@ # get the repo root and output path ROOT_PACKAGE=github.com/OpenIM/chat OUT_DIR=$(REPO_ROOT)/_output +VERSION_PACKAGE=github.com/OpenIMSDK/chat/pkg/common/version # ============================================================================== + # define the default goal # @@ -114,16 +116,17 @@ SPACE += # ============================================================================== # Build definition -GO_SUPPORTED_VERSIONS ?= 1.18|1.19|1.20|1.21 -GO_LDFLAGS += -X $(VERSION_PACKAGE).GitVersion=$(VERSION) \ - -X $(VERSION_PACKAGE).GitCommit=$(GIT_COMMIT) \ - -X $(VERSION_PACKAGE).GitTreeState=$(GIT_TREE_STATE) \ - -X $(VERSION_PACKAGE).BuildDate=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') -ifneq ($(DLV),) +GO_SUPPORTED_VERSIONS ?= 1.19|1.20|1.21|1.22 +GO_LDFLAGS += -X $(VERSION_PACKAGE).gitVersion=$(VERSION) \ + -X $(VERSION_PACKAGE).gitCommit=$(GIT_COMMIT) \ + -X $(VERSION_PACKAGE).gitTreeState=$(GIT_TREE_STATE) \ + -X $(VERSION_PACKAGE).buildDate=$(shell date +%FT%T%z) \ + -s -w +ifneq ($(DEBUG),) GO_BUILD_FLAGS += -gcflags "all=-N -l" LDFLAGS = "" endif -GO_BUILD_FLAGS += -ldflags "$(GO_LDFLAGS)" +GO_BUILD_FLAGS += -tags "containers_image_openpgp netgo exclude_graphdriver_devicemapper static osusergo exclude_graphdriver_btrfs" -trimpath -ldflags "$(GO_LDFLAGS)" ifeq ($(GOOS),windows) GO_OUT_EXT := .exe @@ -150,6 +153,39 @@ endif EXCLUDE_TESTS=github.com/OpenIMSDK/chat/test +# ============================================================================== +# Docker build definition +# Image and Deployment +# +DOCKER := docker + +# read: https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/images.md +REGISTRY_PREFIX ?= registry.cn-hangzhou.aliyuncs.com/openimsdk #ghcr.io/openimsdk + +BASE_IMAGE ?= ghcr.io/openim-sigs/openim-bash-image + +IMAGE_PLAT ?= $(subst $(SPACE),$(COMMA),$(subst _,/,$(PLATFORMS))) + +EXTRA_ARGS ?= --no-cache +_DOCKER_BUILD_EXTRA_ARGS := + +ifdef HTTP_PROXY +_DOCKER_BUILD_EXTRA_ARGS += --build-arg HTTP_PROXY=${HTTP_PROXY} +endif + +ifneq ($(EXTRA_ARGS), ) +_DOCKER_BUILD_EXTRA_ARGS += $(EXTRA_ARGS) +endif + +# Determine image files by looking into build/images/*/Dockerfile +IMAGES_DIR ?= $(wildcard ${ROOT_DIR}/build/images/*) +# Determine images names by stripping out the dir names, and filter out the undesired directories +IMAGES ?= $(filter-out Dockerfile, $(foreach image,${IMAGES_DIR},$(notdir ${image}))) + +ifeq (${IMAGES},) + $(error Could not determine IMAGES, set ROOT_DIR or run in source dir) +endif + # ============================================================================== # Build @@ -188,7 +224,6 @@ go.build.%: @cd $(ROOT_DIR)/cmd/*/$(COMMAND) && CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) $(GO) build $(GO_BUILD_FLAGS) -o \ $(BIN_DIR)/platforms/$(OS)/$(ARCH)/$(COMMAND)$(GO_OUT_EXT) . - ## build-multiarch: Build binaries for multiple platforms. .PHONY: build-multiarch build-multiarch: go.build.verify $(foreach p,$(PLATFORMS),$(addprefix go.build., $(addprefix $(p)., $(BINS)))) @@ -267,6 +302,31 @@ stop: @echo "===========> Stopping the service" @$(ROOT_DIR)/scripts/stop_all.sh +## restart: Restart openim chat +.PHONY: restart +restart: clean stop build start check + +## image.build.%: Build docker image for a specific platform +.PHONY: image.build.% +image.build.%: go.build.% + $(eval IMAGE := $(COMMAND)) + $(eval IMAGE_PLAT := $(subst _,/,$(PLATFORM))) + $(eval ARCH := $(word 2,$(subst _, ,$(PLATFORM)))) + @echo "===========> Building docker image $(IMAGE) $(VERSION) for $(IMAGE_PLAT)" + @mkdir -p $(TMP_DIR)/$(IMAGE)/$(PLATFORM) + @cat $(ROOT_DIR)/build/images/Dockerfile\ + | sed "s#BASE_IMAGE#$(BASE_IMAGE)#g" \ + | sed "s#BINARY_NAME#$(IMAGE)#g" >$(TMP_DIR)/$(IMAGE)/Dockerfile + @cp $(BIN_DIR)/platforms/$(IMAGE_PLAT)/$(IMAGE) $(TMP_DIR)/$(IMAGE) + $(eval BUILD_SUFFIX := $(_DOCKER_BUILD_EXTRA_ARGS) --pull -t $(REGISTRY_PREFIX)/$(IMAGE)-$(ARCH):$(VERSION) $(TMP_DIR)/$(IMAGE)) + @if [ $(shell $(GO) env GOARCH) != $(ARCH) ] ; then \ + $(MAKE) image.daemon.verify ;\ + $(DOCKER) build --platform $(IMAGE_PLAT) $(BUILD_SUFFIX) ; \ + else \ + $(DOCKER) build $(BUILD_SUFFIX) ; \ + fi + @rm -rf $(TMP_DIR)/$(IMAGE) + ## docker-build: Build docker image with the manager. .PHONY: docker-build docker-build: diff --git a/build/README.md b/build/README.md new file mode 100644 index 00000000..edd419ae --- /dev/null +++ b/build/README.md @@ -0,0 +1,65 @@ +# Building OpenIM + +Building OpenIM is easy if you take advantage of the containerized build environment. This document will help guide you through understanding this build process. + +## Requirements + +1. Docker, using one of the following configurations: + * **macOS** Install Docker for Mac. See installation instructions [here](https://docs.docker.com/docker-for-mac/). + **Note**: You will want to set the Docker VM to have at least 4GB of initial memory or building will likely fail. + * **Linux with local Docker** Install Docker according to the [instructions](https://docs.docker.com/installation/#installation) for your OS. + * **Windows with Docker Desktop WSL2 backend** Install Docker according to the [instructions](https://docs.docker.com/docker-for-windows/wsl-tech-preview/). Be sure to store your sources in the local Linux file system, not the Windows remote mount at `/mnt/c`. + + **Note**: You will need to check if Docker CLI plugin buildx is properly installed (`docker-buildx` file should be present in `~/.docker/cli-plugins`). You can install buildx according to the [instructions](https://github.com/docker/buildx/blob/master/README.md#installing). + +2. **Optional** [Google Cloud SDK](https://developers.google.com/cloud/sdk/) + +You must install and configure Google Cloud SDK if you want to upload your release to Google Cloud Storage and may safely omit this otherwise. + +## Actions + +About [Images packages](https://github.com/orgs/OpenIMSDK/packages?repo_name=Open-IM-Server) + +All files in the `build/images` directory are not templated and are instead rendered by Github Actions, which is an automated process. + +Trigger condition: +1. create a new tag with the format `vX.Y.Z` (e.g. `v1.0.0`) +2. push the tag to the remote repository +3. wait for the build to finish +4. download the artifacts from the release page + +## Make images + +**help info:** + +```bash +$ make image.help +``` + +**build images:** + +```bash +$ make image +``` + +## Overview + +While it is possible to build OpenIM using a local golang installation, we have a build process that runs in a Docker container. This simplifies initial set up and provides for a very consistent build and test environment. + + +## Basic Flow + +The scripts directly under [`build/`](.) are used to build and test. They will ensure that the `openim-build` Docker image is built (based on [`build/build-image/Dockerfile`](../Dockerfile) and after base image's `OPENIM_BUILD_IMAGE_CROSS_TAG` from Dockerfile is replaced with one of those actual tags of the base image, like `v1.13.9-2`) and then execute the appropriate command in that container. These scripts will both ensure that the right data is cached from run to run for incremental builds and will copy the results back out of the container. You can specify a different registry/name and version for `openim-cross` by setting `OPENIM_CROSS_IMAGE` and `OPENIM_CROSS_VERSION`, see [`common.sh`](common.sh) for more details. + +The `openim-build` container image is built by first creating a "context" directory in `_output/images/build-image`. It is done there instead of at the root of the OpenIM repo to minimize the amount of data we need to package up when building the image. + +There are 3 different containers instances that are run from this image. The first is a "data" container to store all data that needs to persist across to support incremental builds. Next there is an "rsync" container that is used to transfer data in and out to the data container. Lastly there is a "build" container that is used for actually doing build actions. The data container persists across runs while the rsync and build containers are deleted after each use. + +`rsync` is used transparently behind the scenes to efficiently move data in and out of the container. This will use an ephemeral port picked by Docker. You can modify this by setting the `OPENIM_RSYNC_PORT` env variable. + +All Docker names are suffixed with a hash derived from the file path (to allow concurrent usage on things like CI machines) and a version number. When the version number changes all state is cleared and clean build is started. This allows the build infrastructure to be changed and signal to CI systems that old artifacts need to be deleted. + +## Build artifacts +The build system output all its products to a top level directory in the source repository named `_output`. +These include the binary compiled packages (e.g. imctl, openim-api etc.) and archived Docker images. +If you intend to run a component with a docker image you will need to import it from this directory with diff --git a/build/images/Dockerfile b/build/images/Dockerfile new file mode 100644 index 00000000..518de78b --- /dev/null +++ b/build/images/Dockerfile @@ -0,0 +1,10 @@ +FROM BASE_IMAGE + +WORKDIR ${SERVER_WORKDIR} + +# Set HTTP proxy +ARG BINARY_NAME + +COPY BINARY_NAME ./bin/BINARY_NAME + +ENTRYPOINT ["./bin/BINARY_NAME"] \ No newline at end of file diff --git a/build/docker/api-admin/Dockerfile b/build/images/api-admin/Dockerfile similarity index 73% rename from build/docker/api-admin/Dockerfile rename to build/images/api-admin/Dockerfile index a1aeaf1f..6d7b713d 100644 --- a/build/docker/api-admin/Dockerfile +++ b/build/images/api-admin/Dockerfile @@ -34,19 +34,15 @@ RUN go mod download COPY . . -RUN make clean RUN make build BINS=admin-api -FROM ghcr.io/openim-sigs/openim-bash-image:latest +RUN cp /openim/openim-chat/_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/admin-api /usr/bin/admin-api -WORKDIR ${CHAT_WORKDIR} -COPY --from=builder ${OPENIM_CHAT_BINDIR}/platforms /openim/openim-chat/_output/bin/platforms -COPY --from=builder ${OPENIM_CHAT_CONFIG_NAME} /openim/openim-chat/config/config.yaml +FROM ghcr.io/openim-sigs/openim-bash-image:latest -ENV PORT=10009 -EXPOSE 10009 +WORKDIR ${CHAT_WORKDIR} -RUN mv ${OPENIM_CHAT_BINDIR}/platforms/$(get_os)/$(get_arch)/admin-api /usr/bin/admin-api +COPY --from=builder /usr/bin/admin-api ./bin/admin-api -ENTRYPOINT ["bash", "-c", "admin-api --port $PORT -c $OPENIM_CHAT_CONFIG_NAME"] +ENTRYPOINT ["./bin/admin-api"] \ No newline at end of file diff --git a/build/docker/api-chat/Dockerfile b/build/images/api-chat/Dockerfile similarity index 72% rename from build/docker/api-chat/Dockerfile rename to build/images/api-chat/Dockerfile index 1b5225fd..3a06d51e 100644 --- a/build/docker/api-chat/Dockerfile +++ b/build/images/api-chat/Dockerfile @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# OpenIM base image: https://github.com/openim-sigs/openim-base-image + # Set go mod installation source and proxy + ARG GOARCH ARG GOOS @@ -31,19 +34,15 @@ RUN go mod download COPY . . -RUN make clean RUN make build BINS=chat-api -FROM ghcr.io/openim-sigs/openim-bash-image:latest +RUN cp /openim/openim-chat/_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/chat-api /usr/bin/chat-api -WORKDIR ${CHAT_WORKDIR} -COPY --from=builder ${OPENIM_CHAT_BINDIR}/platforms /openim/openim-chat/_output/bin/platforms -COPY --from=builder ${OPENIM_CHAT_CONFIG_NAME} /openim/openim-chat/config/config.yaml +FROM ghcr.io/openim-sigs/openim-bash-image:latest -ENV PORT=10008 -EXPOSE 10008 +WORKDIR ${CHAT_WORKDIR} -RUN mv ${OPENIM_CHAT_BINDIR}/platforms/$(get_os)/$(get_arch)/chat-api /usr/bin/chat-api +COPY --from=builder /usr/bin/chat-api ./bin/chat-api -ENTRYPOINT ["bash", "-c", "chat-api --port $PORT -c $OPENIM_CHAT_CONFIG_NAME"] +ENTRYPOINT ["./bin/chat-api"] \ No newline at end of file diff --git a/build/docker/rpc-admin/Dockerfile b/build/images/rpc-admin/Dockerfile similarity index 65% rename from build/docker/rpc-admin/Dockerfile rename to build/images/rpc-admin/Dockerfile index b77cf611..736e2122 100644 --- a/build/docker/rpc-admin/Dockerfile +++ b/build/images/rpc-admin/Dockerfile @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# OpenIM base image: https://github.com/openim-sigs/openim-base-image + # Set go mod installation source and proxy + ARG GOARCH ARG GOOS @@ -31,22 +34,15 @@ RUN go mod download COPY . . -RUN make clean RUN make build BINS=admin-rpc -FROM ghcr.io/openim-sigs/openim-bash-image:latest - -WORKDIR ${CHAT_WORKDIR} - -COPY --from=builder ${OPENIM_CHAT_BINDIR}/platforms /openim/openim-chat/_output/bin/platforms -COPY --from=builder ${OPENIM_CHAT_CONFIG_NAME} /openim/openim-chat/config/config.yaml +RUN cp /openim/openim-chat/_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/admin-rpc /usr/bin/admin-rpc -CMD ["bash", "-c", "${OPENIM_CHAT_BINDIR}/platforms/$(get_os)/$(get_arch)/admin-rpc --port ${PORT} --config_folder_path ${OPENIM_CHAT_CONFIG_NAME}"] +FROM ghcr.io/openim-sigs/openim-bash-image:latest -ENV PORT=30200 -EXPOSE 30200 +WORKDIR ${CHAT_WORKDIR} -RUN mv ${OPENIM_CHAT_BINDIR}/platforms/$(get_os)/$(get_arch)/admin-rpc /usr/bin/admin-rpc +COPY --from=builder /usr/bin/admin-rpc ./bin/admin-rpc -ENTRYPOINT ["bash", "-c", "admin-rpc --port $PORT -c $OPENIM_CHAT_CONFIG_NAME"] +ENTRYPOINT ["./bin/admin-rpc"] \ No newline at end of file diff --git a/build/docker/rpc-chat/Dockerfile b/build/images/rpc-chat/Dockerfile similarity index 68% rename from build/docker/rpc-chat/Dockerfile rename to build/images/rpc-chat/Dockerfile index 436254ba..e9ffa383 100644 --- a/build/docker/rpc-chat/Dockerfile +++ b/build/images/rpc-chat/Dockerfile @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# OpenIM base image: https://github.com/openim-sigs/openim-base-image + # Set go mod installation source and proxy + ARG GOARCH ARG GOOS @@ -31,21 +34,15 @@ RUN go mod download COPY . . -RUN make clean RUN make build BINS=chat-rpc -RUN rm -rf ./_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/admin-rpc +RUN cp /openim/openim-chat/_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/chat-rpc /usr/bin/chat-rpc + FROM ghcr.io/openim-sigs/openim-bash-image:latest WORKDIR ${CHAT_WORKDIR} -COPY --from=builder ${OPENIM_CHAT_BINDIR}/platforms /openim/openim-chat/_output/bin/platforms -COPY --from=builder ${OPENIM_CHAT_CONFIG_NAME} /openim/openim-chat/config/config.yaml - -ENV PORT=30300 -EXPOSE 30300 - -RUN mv ${OPENIM_CHAT_BINDIR}/platforms/$(get_os)/$(get_arch)/chat-rpc /usr/bin/chat-rpc +COPY --from=builder /usr/bin/chat-rpc ./bin/chat-rpc -ENTRYPOINT ["bash", "-c", "chat-rpc --port $PORT -c $OPENIM_CHAT_CONFIG_NAME"] +ENTRYPOINT ["./bin/chat-rpc"] \ No newline at end of file diff --git a/cmd/api/admin-api/Makefile b/cmd/api/admin-api/Makefile deleted file mode 100644 index 3b8b11dd..00000000 --- a/cmd/api/admin-api/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -.PHONY: all build run gotool install clean help - -BINARY_NAME=admin-api -BIN_DIR=../../../bin/ - - -all: gotool build - -build: - CGO_ENABLED=0 GOOS=linux GOARCH=amd64; go build -ldflags="-w -s" -o ${BINARY_NAME} - -run: - @go run ./ - -gotool: - go fmt ./ - go vet ./ - -install: - make build - mv ${BINARY_NAME} ${BIN_DIR} - -clean: - @if [ -f ${BINARY_NAME} ] ; then rm ${BINARY_NAME} ; fi diff --git a/cmd/api/admin-api/main.go b/cmd/api/admin-api/main.go index e9cb6bab..07c66de6 100644 --- a/cmd/api/admin-api/main.go +++ b/cmd/api/admin-api/main.go @@ -15,18 +15,21 @@ package main import ( - "flag" - "github.com/OpenIMSDK/chat/tools/component" + "fmt" + "github.com/OpenIMSDK/chat/pkg/discovery_register" "math/rand" "net" "strconv" "time" + "github.com/OpenIMSDK/chat/tools/component" + "github.com/OpenIMSDK/tools/discoveryregistry" + mw2 "github.com/OpenIMSDK/chat/pkg/common/mw" + "github.com/OpenIMSDK/chat/pkg/common/version" "github.com/OpenIMSDK/chat/internal/api" "github.com/OpenIMSDK/chat/pkg/common/config" - openKeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mw" "google.golang.org/grpc" @@ -37,18 +40,24 @@ import ( func main() { rand.Seed(time.Now().UnixNano()) - var configFile string - flag.StringVar(&configFile, "config_folder_path", "../config/config.yaml", "Config full path") - - var ginPort int - - flag.IntVar(&ginPort, "port", 10009, "get ginServerPort from cmd") + configFile, ginPort, hide, showVersion, err := config.FlagParse() + if err != nil { + panic(err) + } - var hide bool - flag.BoolVar(&hide, "hide", false, "hide the ComponentCheck result") + // Check if the version flag was set + if showVersion { + ver := version.Get() + fmt.Println("Version:", ver.GitVersion) + fmt.Println("Git Commit:", ver.GitCommit) + fmt.Println("Build Date:", ver.BuildDate) + fmt.Println("Go Version:", ver.GoVersion) + fmt.Println("Compiler:", ver.Compiler) + fmt.Println("Platform:", ver.Platform) + return + } - flag.Parse() - err := component.ComponentCheck(configFile, hide) + err = component.ComponentCheck(configFile, hide) if err != nil { return } @@ -58,9 +67,13 @@ func main() { if err := log.InitFromConfig("chat.log", "admin-api", *config.Config.Log.RemainLogLevel, *config.Config.Log.IsStdout, *config.Config.Log.IsJson, *config.Config.Log.StorageLocation, *config.Config.Log.RemainRotationCount, *config.Config.Log.RotationTime); err != nil { panic(err) } - zk, 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())) + if config.Config.Envs.Discovery == "k8s" { + ginPort = 80 + } + var zk discoveryregistry.SvcDiscoveryRegistry + zk, err = discovery_register.NewDiscoveryRegister(config.Config.Envs.Discovery) + //zk, 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())) if err != nil { panic(err) } diff --git a/cmd/api/chat-api/Makefile b/cmd/api/chat-api/Makefile deleted file mode 100644 index 7252c8b4..00000000 --- a/cmd/api/chat-api/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -.PHONY: all build run gotool install clean help - -BINARY_NAME=chat-api -BIN_DIR=../../../bin/ - - -all: gotool build - -build: - CGO_ENABLED=0 GOOS=linux GOARCH=amd64; go build -ldflags="-w -s" -o ${BINARY_NAME} - -run: - @go run ./ - -gotool: - go fmt ./ - go vet ./ - -install: - make build - mv ${BINARY_NAME} ${BIN_DIR} - -clean: - @if [ -f ${BINARY_NAME} ] ; then rm ${BINARY_NAME} ; fi diff --git a/cmd/api/chat-api/main.go b/cmd/api/chat-api/main.go index ef3632c7..0c0a907f 100644 --- a/cmd/api/chat-api/main.go +++ b/cmd/api/chat-api/main.go @@ -17,19 +17,21 @@ package main import ( "flag" "fmt" - "math/rand" "net" "strconv" "time" + "github.com/OpenIMSDK/chat/pkg/discovery_register" + "github.com/OpenIMSDK/tools/discoveryregistry" + "github.com/OpenIMSDK/chat/tools/component" mw2 "github.com/OpenIMSDK/chat/pkg/common/mw" + "github.com/OpenIMSDK/chat/pkg/common/version" "github.com/OpenIMSDK/chat/internal/api" "github.com/OpenIMSDK/chat/pkg/common/config" - openKeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mw" "google.golang.org/grpc" @@ -38,21 +40,34 @@ import ( "github.com/gin-gonic/gin" ) +var rng *rand.Rand + +func init() { + rng = rand.New(rand.NewSource(time.Now().UnixNano())) +} + func main() { - rand.Seed(time.Now().UnixNano()) - var configFile string - flag.StringVar(&configFile, "config_folder_path", "../config/config.yaml", "Config full path:") - // defaultPorts := config.Config.ChatApi.GinPort - var ginPort int - flag.IntVar(&ginPort, "port", 10008, "get ginServerPort from cmd") + configFile, ginPort, hide, showVersion, err := config.FlagParse() + if err != nil { + panic(err) + } - var hide bool - flag.BoolVar(&hide, "hide", true, "hide the ComponentCheck result") + // Check if the version flag was set + if showVersion { + ver := version.Get() + fmt.Println("Version:", ver.GitVersion) + fmt.Println("Git Commit:", ver.GitCommit) + fmt.Println("Build Date:", ver.BuildDate) + fmt.Println("Go Version:", ver.GoVersion) + fmt.Println("Compiler:", ver.Compiler) + fmt.Println("Platform:", ver.Platform) + return + } flag.Parse() - err := component.ComponentCheck(configFile, hide) + err = component.ComponentCheck(configFile, hide) if err != nil { return } @@ -64,9 +79,14 @@ func main() { if err := log.InitFromConfig("chat.log", "chat-api", *config.Config.Log.RemainLogLevel, *config.Config.Log.IsStdout, *config.Config.Log.IsJson, *config.Config.Log.StorageLocation, *config.Config.Log.RemainRotationCount, *config.Config.Log.RotationTime); err != nil { panic(err) } - zk, 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())) + if config.Config.Envs.Discovery == "k8s" { + ginPort = 80 + } + var zk discoveryregistry.SvcDiscoveryRegistry + zk, err = discovery_register.NewDiscoveryRegister(config.Config.Envs.Discovery) + /*zk, 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()))*/ if err != nil { panic(err) } diff --git a/cmd/rpc/admin-rpc/Makefile b/cmd/rpc/admin-rpc/Makefile deleted file mode 100644 index f4ff0f59..00000000 --- a/cmd/rpc/admin-rpc/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -.PHONY: all build run gotool install clean help - -BINARY_NAME=admin-rpc -BIN_DIR=../../../bin/ - -all: gotool build - -build: - CGO_ENABLED=0 GOOS=linux GOARCH=amd64; go build -ldflags="-w -s" -o ${BINARY_NAME} - -run: - @go run ./ - -gotool: - go fmt ./ - go vet ./ - -install: - make build - mv ${BINARY_NAME} ${BIN_DIR} - -clean: - @if [ -f ${BINARY_NAME} ] ; then rm ${BINARY_NAME} ; fi diff --git a/cmd/rpc/admin-rpc/main.go b/cmd/rpc/admin-rpc/main.go index 32391f3e..872f8c5b 100644 --- a/cmd/rpc/admin-rpc/main.go +++ b/cmd/rpc/admin-rpc/main.go @@ -16,11 +16,14 @@ package main import ( "flag" + "fmt" + "math/rand" + "time" + "github.com/OpenIMSDK/chat/pkg/common/chatrpcstart" + "github.com/OpenIMSDK/chat/pkg/common/version" "github.com/OpenIMSDK/chat/tools/component" "github.com/OpenIMSDK/tools/log" - "math/rand" - "time" "github.com/OpenIMSDK/chat/internal/rpc/admin" "github.com/OpenIMSDK/chat/pkg/common/config" @@ -28,24 +31,35 @@ import ( func main() { rand.Seed(time.Now().UnixNano()) - var configFile string - flag.StringVar(&configFile, "config_folder_path", "../config/config.yaml", "Config full path") - - var rpcPort int - flag.IntVar(&rpcPort, "port", 30200, "get rpc ServerPort from cmd") + configFile, rpcPort, hide, showVersion, err := config.FlagParse() + if err != nil { + panic(err) + } - var hide bool - flag.BoolVar(&hide, "hide", true, "hide the ComponentCheck result") + // Check if the version flag was set + if showVersion { + ver := version.Get() + fmt.Println("Version:", ver.GitVersion) + fmt.Println("Git Commit:", ver.GitCommit) + fmt.Println("Build Date:", ver.BuildDate) + fmt.Println("Go Version:", ver.GoVersion) + fmt.Println("Compiler:", ver.Compiler) + fmt.Println("Platform:", ver.Platform) + return + } flag.Parse() - err := component.ComponentCheck(configFile, hide) + err = component.ComponentCheck(configFile, hide) if err != nil { return } if err := config.InitConfig(configFile); err != nil { panic(err) } + if config.Config.Envs.Discovery == "k8s" { + rpcPort = 80 + } if err := log.InitFromConfig("chat.log", "admin-rpc", *config.Config.Log.RemainLogLevel, *config.Config.Log.IsStdout, *config.Config.Log.IsJson, *config.Config.Log.StorageLocation, *config.Config.Log.RemainRotationCount, *config.Config.Log.RotationTime); err != nil { panic(err) } diff --git a/cmd/rpc/chat-rpc/Makefile b/cmd/rpc/chat-rpc/Makefile deleted file mode 100644 index 9368c60a..00000000 --- a/cmd/rpc/chat-rpc/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -.PHONY: all build run gotool install clean help - -BINARY_NAME=chat-rpc -BIN_DIR=../../../bin/ - -all: gotool build - -build: - CGO_ENABLED=0 GOOS=linux GOARCH=amd64; go build -ldflags="-w -s" -o ${BINARY_NAME} - -run: - @go run ./ - -gotool: - go fmt ./ - go vet ./ - -install: - make build - mv ${BINARY_NAME} ${BIN_DIR} - -clean: - @if [ -f ${BINARY_NAME} ] ; then rm ${BINARY_NAME} ; fi diff --git a/cmd/rpc/chat-rpc/main.go b/cmd/rpc/chat-rpc/main.go index 50de20a6..5b00c9f8 100644 --- a/cmd/rpc/chat-rpc/main.go +++ b/cmd/rpc/chat-rpc/main.go @@ -1,51 +1,48 @@ -// 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. - package main import ( - "flag" + "fmt" + "math/rand" + "time" + "github.com/OpenIMSDK/chat/pkg/common/chatrpcstart" "github.com/OpenIMSDK/chat/tools/component" "github.com/OpenIMSDK/tools/log" - "math/rand" - "time" "github.com/OpenIMSDK/chat/internal/rpc/chat" "github.com/OpenIMSDK/chat/pkg/common/config" + "github.com/OpenIMSDK/chat/pkg/common/version" ) func main() { rand.Seed(time.Now().UnixNano()) - var configFile string - flag.StringVar(&configFile, "config_folder_path", "../config/config.yaml", "Config full path") - - var rpcPort int - - flag.IntVar(&rpcPort, "port", 30300, "get rpc ServerPort from cmd") + configFile, rpcPort, hide, showVersion, err := config.FlagParse() + if err != nil { + panic(err) + } - var hide bool - flag.BoolVar(&hide, "hide", true, "hide the ComponentCheck result") + // Check if the version flag was set + if showVersion { + ver := version.Get() + fmt.Println("Version:", ver.GitVersion) + fmt.Println("Git Commit:", ver.GitCommit) + fmt.Println("Build Date:", ver.BuildDate) + fmt.Println("Go Version:", ver.GoVersion) + fmt.Println("Compiler:", ver.Compiler) + fmt.Println("Platform:", ver.Platform) + return + } - flag.Parse() - err := component.ComponentCheck(configFile, hide) + err = component.ComponentCheck(configFile, hide) if err != nil { return } if err := config.InitConfig(configFile); err != nil { panic(err) } + if config.Config.Envs.Discovery == "k8s" { + rpcPort = 80 + } if err := log.InitFromConfig("chat.log", "chat-rpc", *config.Config.Log.RemainLogLevel, *config.Config.Log.IsStdout, *config.Config.Log.IsJson, *config.Config.Log.StorageLocation, *config.Config.Log.RemainRotationCount, *config.Config.Log.RotationTime); err != nil { panic(err) } diff --git a/config/config.yaml b/config/config.yaml index 72950451..5c6a5270 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -13,6 +13,9 @@ # limitations under the License. # 需要先启动OpenIMServer +envs: + discovery: "zookeeper" + zookeeper: schema: openim zkAddr: @@ -50,7 +53,7 @@ mysql: # maxLifeTime: 60 #连接可以重复使用的最长时间(秒) # logLevel: 4 #日志级别 1=slient 2=error 3=warn 4=info # slowThreshold: 500 #慢语句阈值 (毫秒) - database: openim_enterprise + # database: openim_enterprise # 没有配置表示和OpenIM一致 log: diff --git a/deployment/helm-charts/.helmignore b/deployment/helm-charts/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/deployment/helm-charts/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deployment/helm-charts/Chart.yaml b/deployment/helm-charts/Chart.yaml new file mode 100644 index 00000000..14197079 --- /dev/null +++ b/deployment/helm-charts/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: admin-api +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/deployment/helm-charts/charts/admin-rpc/.helmignore b/deployment/helm-charts/charts/admin-rpc/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deployment/helm-charts/charts/admin-rpc/Chart.yaml b/deployment/helm-charts/charts/admin-rpc/Chart.yaml new file mode 100644 index 00000000..81a2aadb --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: admin-rpc +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/deployment/helm-charts/charts/admin-rpc/templates/NOTES.txt b/deployment/helm-charts/charts/admin-rpc/templates/NOTES.txt new file mode 100644 index 00000000..cb5db3d5 --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "admin-rpc.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "admin-rpc.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "admin-rpc.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "admin-rpc.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/deployment/helm-charts/charts/admin-rpc/templates/_helpers.tpl b/deployment/helm-charts/charts/admin-rpc/templates/_helpers.tpl new file mode 100644 index 00000000..b6da9576 --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "admin-rpc.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "admin-rpc.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "admin-rpc.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "admin-rpc.labels" -}} +helm.sh/chart: {{ include "admin-rpc.chart" . }} +{{ include "admin-rpc.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "admin-rpc.selectorLabels" -}} +app.kubernetes.io/name: {{ include "admin-rpc.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "admin-rpc.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "admin-rpc.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/admin-rpc/templates/deployment.yaml b/deployment/helm-charts/charts/admin-rpc/templates/deployment.yaml new file mode 100644 index 00000000..b8c92167 --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/templates/deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "admin-rpc.fullname" . }} + labels: + {{- include "admin-rpc.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "admin-rpc.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "admin-rpc.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "admin-rpc.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + #livenessProbe: + # httpGet: + # path: / + # port: http + #readinessProbe: + # httpGet: + # path: / + # port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - mountPath: /app/config/config.yaml + name: config + subPath: config.yaml + volumes: + - name: config + configMap: + name: imchat-cm + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deployment/helm-charts/charts/admin-rpc/templates/hpa.yaml b/deployment/helm-charts/charts/admin-rpc/templates/hpa.yaml new file mode 100644 index 00000000..ea6966c6 --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "admin-rpc.fullname" . }} + labels: + {{- include "admin-rpc.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "admin-rpc.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/admin-rpc/templates/ingress.yaml b/deployment/helm-charts/charts/admin-rpc/templates/ingress.yaml new file mode 100644 index 00000000..1c1ba0e9 --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "admin-rpc.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "admin-rpc.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/admin-rpc/templates/service.yaml b/deployment/helm-charts/charts/admin-rpc/templates/service.yaml new file mode 100644 index 00000000..5104079a --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "admin-rpc.fullname" . }} + labels: + {{- include "admin-rpc.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "admin-rpc.selectorLabels" . | nindent 4 }} diff --git a/deployment/helm-charts/charts/admin-rpc/templates/serviceaccount.yaml b/deployment/helm-charts/charts/admin-rpc/templates/serviceaccount.yaml new file mode 100644 index 00000000..d79d94a6 --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "admin-rpc.serviceAccountName" . }} + labels: + {{- include "admin-rpc.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/admin-rpc/values.yaml b/deployment/helm-charts/charts/admin-rpc/values.yaml new file mode 100644 index 00000000..c4a4ae9b --- /dev/null +++ b/deployment/helm-charts/charts/admin-rpc/values.yaml @@ -0,0 +1,82 @@ +# Default values for admin-rpc. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/deployment/helm-charts/charts/chat-api/.helmignore b/deployment/helm-charts/charts/chat-api/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deployment/helm-charts/charts/chat-api/Chart.yaml b/deployment/helm-charts/charts/chat-api/Chart.yaml new file mode 100644 index 00000000..f885ada6 --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: chat-api +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/deployment/helm-charts/charts/chat-api/templates/NOTES.txt b/deployment/helm-charts/charts/chat-api/templates/NOTES.txt new file mode 100644 index 00000000..01227086 --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "chat-api.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "chat-api.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "chat-api.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "chat-api.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/deployment/helm-charts/charts/chat-api/templates/_helpers.tpl b/deployment/helm-charts/charts/chat-api/templates/_helpers.tpl new file mode 100644 index 00000000..a7a4c2c2 --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "chat-api.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "chat-api.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chat-api.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "chat-api.labels" -}} +helm.sh/chart: {{ include "chat-api.chart" . }} +{{ include "chat-api.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chat-api.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chat-api.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "chat-api.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "chat-api.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/chat-api/templates/deployment.yaml b/deployment/helm-charts/charts/chat-api/templates/deployment.yaml new file mode 100644 index 00000000..f5518d00 --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/templates/deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "chat-api.fullname" . }} + labels: + {{- include "chat-api.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "chat-api.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "chat-api.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "chat-api.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + #livenessProbe: + # httpGet: + # path: / + # port: http + #readinessProbe: + # httpGet: + # path: / + # port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - mountPath: /app/config/config.yaml + name: config + subPath: config.yaml + volumes: + - name: config + configMap: + name: imchat-cm + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deployment/helm-charts/charts/chat-api/templates/hpa.yaml b/deployment/helm-charts/charts/chat-api/templates/hpa.yaml new file mode 100644 index 00000000..454cd0ed --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "chat-api.fullname" . }} + labels: + {{- include "chat-api.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "chat-api.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/chat-api/templates/ingress.yaml b/deployment/helm-charts/charts/chat-api/templates/ingress.yaml new file mode 100644 index 00000000..f9a7ab0e --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "chat-api.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "chat-api.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/chat-api/templates/service.yaml b/deployment/helm-charts/charts/chat-api/templates/service.yaml new file mode 100644 index 00000000..7761dccc --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "chat-api.fullname" . }} + labels: + {{- include "chat-api.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "chat-api.selectorLabels" . | nindent 4 }} diff --git a/deployment/helm-charts/charts/chat-api/templates/serviceaccount.yaml b/deployment/helm-charts/charts/chat-api/templates/serviceaccount.yaml new file mode 100644 index 00000000..ab59c1af --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "chat-api.serviceAccountName" . }} + labels: + {{- include "chat-api.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/chat-api/values.yaml b/deployment/helm-charts/charts/chat-api/values.yaml new file mode 100644 index 00000000..bd8b8b39 --- /dev/null +++ b/deployment/helm-charts/charts/chat-api/values.yaml @@ -0,0 +1,84 @@ +# Default values for chat-api. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: true + className: "nginx" + annotations: + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/rewrite-target: /$2 + hosts: + - host: openim1.nsddd.top + paths: + - path: /chat(/|$)(.*) + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/deployment/helm-charts/charts/chat-rpc/.helmignore b/deployment/helm-charts/charts/chat-rpc/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deployment/helm-charts/charts/chat-rpc/Chart.yaml b/deployment/helm-charts/charts/chat-rpc/Chart.yaml new file mode 100644 index 00000000..32af6b4e --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: chat-rpc +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/deployment/helm-charts/charts/chat-rpc/templates/NOTES.txt b/deployment/helm-charts/charts/chat-rpc/templates/NOTES.txt new file mode 100644 index 00000000..2f1beaee --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "chat-rpc.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "chat-rpc.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "chat-rpc.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "chat-rpc.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/deployment/helm-charts/charts/chat-rpc/templates/_helpers.tpl b/deployment/helm-charts/charts/chat-rpc/templates/_helpers.tpl new file mode 100644 index 00000000..9edc1981 --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "chat-rpc.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "chat-rpc.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chat-rpc.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "chat-rpc.labels" -}} +helm.sh/chart: {{ include "chat-rpc.chart" . }} +{{ include "chat-rpc.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chat-rpc.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chat-rpc.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "chat-rpc.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "chat-rpc.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/chat-rpc/templates/deployment.yaml b/deployment/helm-charts/charts/chat-rpc/templates/deployment.yaml new file mode 100644 index 00000000..d73eb945 --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/templates/deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "chat-rpc.fullname" . }} + labels: + {{- include "chat-rpc.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "chat-rpc.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "chat-rpc.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "chat-rpc.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + #livenessProbe: + # httpGet: + # path: / + # port: http + #readinessProbe: + # httpGet: + # path: / + # port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - mountPath: /app/config/config.yaml + name: config + subPath: config.yaml + volumes: + - name: config + configMap: + name: imchat-cm + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deployment/helm-charts/charts/chat-rpc/templates/hpa.yaml b/deployment/helm-charts/charts/chat-rpc/templates/hpa.yaml new file mode 100644 index 00000000..4ff77848 --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "chat-rpc.fullname" . }} + labels: + {{- include "chat-rpc.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "chat-rpc.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/chat-rpc/templates/ingress.yaml b/deployment/helm-charts/charts/chat-rpc/templates/ingress.yaml new file mode 100644 index 00000000..8b742fe7 --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "chat-rpc.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "chat-rpc.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/chat-rpc/templates/service.yaml b/deployment/helm-charts/charts/chat-rpc/templates/service.yaml new file mode 100644 index 00000000..5056fc7f --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "chat-rpc.fullname" . }} + labels: + {{- include "chat-rpc.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "chat-rpc.selectorLabels" . | nindent 4 }} diff --git a/deployment/helm-charts/charts/chat-rpc/templates/serviceaccount.yaml b/deployment/helm-charts/charts/chat-rpc/templates/serviceaccount.yaml new file mode 100644 index 00000000..085101f9 --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "chat-rpc.serviceAccountName" . }} + labels: + {{- include "chat-rpc.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/charts/chat-rpc/values.yaml b/deployment/helm-charts/charts/chat-rpc/values.yaml new file mode 100644 index 00000000..1da19de4 --- /dev/null +++ b/deployment/helm-charts/charts/chat-rpc/values.yaml @@ -0,0 +1,82 @@ +# Default values for chat-rpc. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/deployment/helm-charts/config.yaml b/deployment/helm-charts/config.yaml new file mode 100644 index 00000000..b6dc0e3e --- /dev/null +++ b/deployment/helm-charts/config.yaml @@ -0,0 +1,112 @@ +image: + repository: registry.cn-shenzhen.aliyuncs.com/huanglin_hub/admin-api + pullPolicy: Always + tag: "dev" +admin-rpc: + image: + repository: registry.cn-shenzhen.aliyuncs.com/huanglin_hub/admin-rpc + pullPolicy: Always + tag: "dev" +chat-api: + image: + repository: registry.cn-shenzhen.aliyuncs.com/huanglin_hub/chat-api + pullPolicy: Always + tag: "dev" +chat-rpc: + image: + repository: registry.cn-shenzhen.aliyuncs.com/huanglin_hub/chat-rpc + pullPolicy: Always + tag: "dev" + +config: + envs: + discovery: k8s + zookeeper: + schema: openim + zkAddr: + - 127.0.0.1:12181 + username: "" + password: "" + + chatApi: + openImChatApiPort: [ 80 ] + listenIP: + + adminApi: + openImAdminApiPort: [ 80 ] + listenIP: + + rpc: + registerIP: #作为rpc启动时,注册到zookeeper的IP,api/gateway能访问到此ip和对应的rpcPort中的端口 + listenIP: #默认为0.0.0.0 + + rpcPort: + openImAdminPort: [ 80 ] + openImChatPort: [ 80 ] + rpcRegisterName: + openImAdminName: openimchat-admin-rpc:80 + openImChatName: openimchat-chat-rpc:80 + + # 没有配置表示和OpenIM一致 + mysql: + address: [ im-mysql:3306 ] #目前仅支持单机 + username: root #用户名 + password: openIM123 #密码 + #database: openIM_v2 #不建议修改 + maxOpenConn: 1000 #最大连接数 + maxIdleConn: 100 #最大空闲连接数 + maxLifeTime: 60 #连接可以重复使用的最长时间(秒) + logLevel: 4 #日志级别 1=slient 2=error 3=warn 4=info + slowThreshold: 500 #慢语句阈值 (毫秒) + database: openim_enterprise + + # 没有配置表示和OpenIM一致 + log: + storageLocation: ../logs/ #存放目录 + rotationTime: 24 #日志旋转时间 + remainRotationCount: 2 #日志数量 + remainLogLevel: 6 #日志级别 6表示全都打印, + isStdout: true + isJson: false + withStack: false + + secret: openIM123 + tokenPolicy: + expire: 86400 + + 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: "" + + # 获取ip的header,没有配置直接获取远程地址 + #proxyHeader: "X-Forwarded-For" + + adminList: + - adminID: admin1 + nickname: chat1 + imAdmin: openIM123456 + - adminID: admin2 + nickname: chat2 + imAdmin: openIM654321 + - adminID: admin3 + nickname: chat3 + imAdmin: openIMAdmin + + + openIMUrl: "http://openimserver-openim-api" + + redis: + address: [ im-redis-master:6379 ] + username: '' + password: openIM123 diff --git a/deployment/helm-charts/templates/NOTES.txt b/deployment/helm-charts/templates/NOTES.txt new file mode 100644 index 00000000..9cbe5775 --- /dev/null +++ b/deployment/helm-charts/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "admin-api.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "admin-api.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "admin-api.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "admin-api.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/deployment/helm-charts/templates/_helpers.tpl b/deployment/helm-charts/templates/_helpers.tpl new file mode 100644 index 00000000..10ad4b5e --- /dev/null +++ b/deployment/helm-charts/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "admin-api.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "admin-api.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "admin-api.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "admin-api.labels" -}} +helm.sh/chart: {{ include "admin-api.chart" . }} +{{ include "admin-api.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "admin-api.selectorLabels" -}} +app.kubernetes.io/name: {{ include "admin-api.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "admin-api.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "admin-api.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/deployment/helm-charts/templates/app-cm.yaml b/deployment/helm-charts/templates/app-cm.yaml new file mode 100644 index 00000000..0d03ce71 --- /dev/null +++ b/deployment/helm-charts/templates/app-cm.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: imchat-cm +data: + config.yaml: |+ + {{- with .Values.config }} + {{- toYaml . | nindent 4 }} + {{- end }} diff --git a/deployment/helm-charts/templates/deployment.yaml b/deployment/helm-charts/templates/deployment.yaml new file mode 100644 index 00000000..361ac165 --- /dev/null +++ b/deployment/helm-charts/templates/deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "admin-api.fullname" . }} + labels: + {{- include "admin-api.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "admin-api.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "admin-api.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "admin-api.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + #livenessProbe: + # httpGet: + # path: / + # port: http + #readinessProbe: + # httpGet: + # path: / + # port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - mountPath: /app/config/config.yaml + name: config + subPath: config.yaml + volumes: + - name: config + configMap: + name: imchat-cm + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deployment/helm-charts/templates/hpa.yaml b/deployment/helm-charts/templates/hpa.yaml new file mode 100644 index 00000000..60d7bd20 --- /dev/null +++ b/deployment/helm-charts/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "admin-api.fullname" . }} + labels: + {{- include "admin-api.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "admin-api.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/templates/ingress.yaml b/deployment/helm-charts/templates/ingress.yaml new file mode 100644 index 00000000..2ea7af21 --- /dev/null +++ b/deployment/helm-charts/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "admin-api.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "admin-api.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/templates/service.yaml b/deployment/helm-charts/templates/service.yaml new file mode 100644 index 00000000..f4e3506b --- /dev/null +++ b/deployment/helm-charts/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "admin-api.fullname" . }} + labels: + {{- include "admin-api.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "admin-api.selectorLabels" . | nindent 4 }} diff --git a/deployment/helm-charts/templates/serviceaccount.yaml b/deployment/helm-charts/templates/serviceaccount.yaml new file mode 100644 index 00000000..04801cd7 --- /dev/null +++ b/deployment/helm-charts/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "admin-api.serviceAccountName" . }} + labels: + {{- include "admin-api.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/deployment/helm-charts/values.yaml b/deployment/helm-charts/values.yaml new file mode 100644 index 00000000..e483907b --- /dev/null +++ b/deployment/helm-charts/values.yaml @@ -0,0 +1,84 @@ +# Default values for admin-api. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: true + className: "nginx" + annotations: + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/rewrite-target: /$2 + hosts: + - host: openim1.nsddd.top + paths: + - path: /complete_admin(/|$)(.*) + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/go.mod b/go.mod index 828403ef..b8422f13 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/OpenIMSDK/chat -go 1.18 +go 1.19 require ( github.com/OpenIMSDK/open_utils v1.0.8 @@ -30,7 +30,9 @@ require ( github.com/OpenIMSDK/protocol v0.0.21 github.com/OpenIMSDK/tools v0.0.15 github.com/go-zookeeper/zk v1.0.3 + github.com/gosuri/uitable v0.0.4 github.com/redis/go-redis/v9 v9.1.0 + github.com/spf13/pflag v1.0.5 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df ) @@ -48,6 +50,7 @@ require ( github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/clbanning/mxj/v2 v2.5.6 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.15.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -63,12 +66,15 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lestrrat-go/strftime v1.0.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/tjfoc/gmsm v1.3.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect diff --git a/go.sum b/go.sum index 5a4bc1f8..ca8eba71 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -94,6 +96,8 @@ github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -128,8 +132,13 @@ github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkL github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -151,11 +160,15 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY= github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +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/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= @@ -249,6 +262,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/rpc/admin/register_add_group.go b/internal/rpc/admin/register_add_group.go index ce998d99..32dc3c54 100644 --- a/internal/rpc/admin/register_add_group.go +++ b/internal/rpc/admin/register_add_group.go @@ -19,10 +19,8 @@ import ( "strings" "time" - "github.com/OpenIMSDK/tools/log" - - "github.com/OpenIMSDK/tools/errs" + "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/utils" admin2 "github.com/OpenIMSDK/chat/pkg/common/db/table/admin" diff --git a/internal/rpc/chat/log.go b/internal/rpc/chat/log.go index e48135d7..34d476cd 100644 --- a/internal/rpc/chat/log.go +++ b/internal/rpc/chat/log.go @@ -3,6 +3,9 @@ package chat import ( "context" "fmt" + "math/rand" + "time" + "github.com/OpenIMSDK/chat/pkg/common/constant" table "github.com/OpenIMSDK/chat/pkg/common/db/table/chat" "github.com/OpenIMSDK/chat/pkg/common/mctx" @@ -11,8 +14,6 @@ import ( "github.com/OpenIMSDK/tools/mw/specialerror" utils2 "github.com/OpenIMSDK/tools/utils" "gorm.io/gorm/utils" - "math/rand" - "time" ) func (o *chatSvr) genLogID() string { diff --git a/internal/rpc/chat/statistic.go b/internal/rpc/chat/statistic.go index 74b979bb..9651ef04 100644 --- a/internal/rpc/chat/statistic.go +++ b/internal/rpc/chat/statistic.go @@ -16,9 +16,10 @@ package chat import ( "context" + "time" + "github.com/OpenIMSDK/chat/pkg/proto/chat" "github.com/OpenIMSDK/tools/errs" - "time" ) func (o *chatSvr) UserLoginCount(ctx context.Context, req *chat.UserLoginCountReq) (*chat.UserLoginCountResp, error) { diff --git a/pkg/common/chatrpcstart/start.go b/pkg/common/chatrpcstart/start.go index 10785bc5..f06cf120 100644 --- a/pkg/common/chatrpcstart/start.go +++ b/pkg/common/chatrpcstart/start.go @@ -18,14 +18,12 @@ import ( "fmt" "net" "strconv" - "time" "github.com/OpenIMSDK/chat/pkg/common/config" chatMw "github.com/OpenIMSDK/chat/pkg/common/mw" + "github.com/OpenIMSDK/chat/pkg/discovery_register" "github.com/OpenIMSDK/tools/discoveryregistry" - openKeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper" "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mw" "github.com/OpenIMSDK/tools/network" "github.com/OpenIMSDK/tools/utils" @@ -36,12 +34,15 @@ import ( func Start(rpcPort int, rpcRegisterName string, prometheusPort int, rpcFn func(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error, options ...grpc.ServerOption) error { fmt.Println("start", rpcRegisterName, "server, port: ", rpcPort, "prometheusPort:", prometheusPort, ", OpenIM version: ", config.Version) - zkClient, 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())) - if err != nil { + var zkClient discoveryregistry.SvcDiscoveryRegistry + zkClient, err := discovery_register.NewDiscoveryRegister(config.Config.Envs.Discovery) + /* + zkClient, 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()))*/if err != nil { return errs.Wrap(err) } + // defer zkClient.CloseZK() defer zkClient.Close() zkClient.AddOption(chatMw.AddUserType(), mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials())) registerIP, err := network.GetRpcRegisterIP(config.Config.Rpc.RegisterIP) diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 5a4b60cc..8e450d61 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -20,6 +20,9 @@ import _ "embed" var Version string var Config struct { + Envs struct { + Discovery string `yaml:"discovery"` + } `yaml:"envs"` Zookeeper struct { Schema string `yaml:"schema"` ZkAddr []string `yaml:"zkAddr"` diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go index f6bd7fcd..561fe28e 100644 --- a/pkg/common/config/parse.go +++ b/pkg/common/config/parse.go @@ -17,14 +17,17 @@ package config import ( "bytes" "errors" + "flag" "fmt" "os" "path/filepath" "runtime" "time" + Constant "github.com/OpenIMSDK/chat/pkg/common/constant" "github.com/OpenIMSDK/protocol/constant" openKeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper" + "github.com/OpenIMSDK/tools/utils" "gopkg.in/yaml.v3" ) @@ -32,30 +35,42 @@ import ( var ( _, b, _, _ = runtime.Caller(0) // Root folder of this project. - Root = filepath.Join(filepath.Dir(b), "../../..") + Root = filepath.Join(filepath.Dir(b), "../..") ) func readConfig(configFile string) ([]byte, error) { b, err := os.ReadFile(configFile) - if err != nil { + if err != nil { // File exists and was read successfully return nil, utils.Wrap(err, configFile) } return b, nil - // cfgName := os.Getenv("CONFIG_NAME") - // if len(cfgName) != 0 { - // data, err := os.ReadFile(filepath.Join(cfgName, "config", "config.yaml")) - // if err != nil { - // data, err = os.ReadFile(filepath.Join(Root, "config", "config.yaml")) - // if err != nil { - // return nil, err - // } - // } else { - // Root = cfgName - // } - // return data, nil - // } else { - // return os.ReadFile(fmt.Sprintf("../config/%s", "config.yaml")) - // } + + // //First, check the configFile argument + // if configFile != "" { + // b, err := os.ReadFile(configFile) + // if err == nil { // File exists and was read successfully + // fmt.Println("这里aaaaaaaa") + // return b, nil + // } + // } + // + // // Second, check for OPENIMCHATCONFIG environment variable + // envConfigPath := os.Getenv("OPENIMCHATCONFIG") + // if envConfigPath != "" { + // b, err := os.ReadFile(envConfigPath) + // if err == nil { // File exists and was read successfully + // return b, nil + // } + // // Again, if there was an error, you can either log it or ignore. + // } + // + // // If neither configFile nor environment variable provided a valid path, use default path + // defaultConfigPath := filepath.Join(Root, "config", "config.yaml") + // b, err := os.ReadFile(defaultConfigPath) + // if err != nil { + // return nil, utils.Wrap(err, defaultConfigPath) + // } + // return b, nil } func InitConfig(configFile string) error { @@ -66,60 +81,63 @@ func InitConfig(configFile string) error { if err := yaml.NewDecoder(bytes.NewReader(data)).Decode(&Config); err != nil { return fmt.Errorf("parse loacl openIMConfig file error: %w", err) } - zk, err := openKeeper.NewClient(Config.Zookeeper.ZkAddr, Config.Zookeeper.Schema, - openKeeper.WithFreq(time.Hour), openKeeper.WithUserNameAndPassword(Config.Zookeeper.Username, - Config.Zookeeper.Password), openKeeper.WithRoundRobin(), openKeeper.WithTimeout(10), openKeeper.WithLogger(&zkLogger{})) - if err != nil { - return utils.Wrap(err, "conn zk error ") - } - defer zk.Close() - var openIMConfigData []byte - for i := 0; i < 100; i++ { - var err error - configData, err := zk.GetConfFromRegistry(constant.OpenIMCommonConfigKey) + if Config.Envs.Discovery != "k8s" { + zk, err := openKeeper.NewClient(Config.Zookeeper.ZkAddr, Config.Zookeeper.Schema, + openKeeper.WithFreq(time.Hour), openKeeper.WithUserNameAndPassword(Config.Zookeeper.Username, + Config.Zookeeper.Password), openKeeper.WithRoundRobin(), openKeeper.WithTimeout(10), openKeeper.WithLogger(&zkLogger{})) if err != nil { - fmt.Printf("get zk config [%d] error: %v\n", i, err) - time.Sleep(time.Second) - continue + return utils.Wrap(err, "conn zk error ") } - if len(configData) == 0 { - fmt.Printf("get zk config [%d] data is empty\n", i) - time.Sleep(time.Second) - continue + defer zk.Close() + var openIMConfigData []byte + for i := 0; i < 100; i++ { + var err error + configData, err := zk.GetConfFromRegistry(constant.OpenIMCommonConfigKey) + if err != nil { + fmt.Printf("get zk config [%d] error: %v\n;envs.descoery=%s", i, err, Config.Envs.Discovery) + time.Sleep(time.Second) + continue + } + if len(configData) == 0 { + fmt.Printf("get zk config [%d] data is empty\n", i) + time.Sleep(time.Second) + continue + } + openIMConfigData = configData } - openIMConfigData = configData - } - if len(openIMConfigData) == 0 { - return errors.New("get zk config data failed") - } - if err := yaml.NewDecoder(bytes.NewReader(openIMConfigData)).Decode(&imConfig); err != nil { - return fmt.Errorf("parse zk openIMConfig: %w", err) + if len(openIMConfigData) == 0 { + return errors.New("get zk config data failed") + } + if err := yaml.NewDecoder(bytes.NewReader(openIMConfigData)).Decode(&imConfig); err != nil { + return fmt.Errorf("parse zk openIMConfig: %w", err) + } + // 这里可以优化,可将其优化为结构体层面的赋值 + configFieldCopy(&Config.Mysql.Address, imConfig.Mysql.Address) + configFieldCopy(&Config.Mysql.Username, imConfig.Mysql.Username) + configFieldCopy(&Config.Mysql.Password, imConfig.Mysql.Password) + configFieldCopy(&Config.Mysql.Database, imConfig.Mysql.Database) + configFieldCopy(&Config.Mysql.MaxOpenConn, imConfig.Mysql.MaxOpenConn) + configFieldCopy(&Config.Mysql.MaxIdleConn, imConfig.Mysql.MaxIdleConn) + configFieldCopy(&Config.Mysql.MaxLifeTime, imConfig.Mysql.MaxLifeTime) + configFieldCopy(&Config.Mysql.LogLevel, imConfig.Mysql.LogLevel) + configFieldCopy(&Config.Mysql.SlowThreshold, imConfig.Mysql.SlowThreshold) + + configFieldCopy(&Config.Log.StorageLocation, imConfig.Log.StorageLocation) + configFieldCopy(&Config.Log.RotationTime, imConfig.Log.RotationTime) + configFieldCopy(&Config.Log.RemainRotationCount, imConfig.Log.RemainRotationCount) + configFieldCopy(&Config.Log.RemainLogLevel, imConfig.Log.RemainLogLevel) + configFieldCopy(&Config.Log.IsStdout, imConfig.Log.IsStdout) + configFieldCopy(&Config.Log.WithStack, imConfig.Log.WithStack) + configFieldCopy(&Config.Log.IsJson, imConfig.Log.IsJson) + + configFieldCopy(&Config.Secret, imConfig.Secret) + configFieldCopy(&Config.TokenPolicy.Expire, imConfig.TokenPolicy.Expire) + + // Redis + configFieldCopy(&Config.Redis.Address, imConfig.Redis.Address) + configFieldCopy(&Config.Redis.Password, imConfig.Redis.Password) + configFieldCopy(&Config.Redis.Username, imConfig.Redis.Username) } - configFieldCopy(&Config.Mysql.Address, imConfig.Mysql.Address) - configFieldCopy(&Config.Mysql.Username, imConfig.Mysql.Username) - configFieldCopy(&Config.Mysql.Password, imConfig.Mysql.Password) - configFieldCopy(&Config.Mysql.Database, imConfig.Mysql.Database) - configFieldCopy(&Config.Mysql.MaxOpenConn, imConfig.Mysql.MaxOpenConn) - configFieldCopy(&Config.Mysql.MaxIdleConn, imConfig.Mysql.MaxIdleConn) - configFieldCopy(&Config.Mysql.MaxLifeTime, imConfig.Mysql.MaxLifeTime) - configFieldCopy(&Config.Mysql.LogLevel, imConfig.Mysql.LogLevel) - configFieldCopy(&Config.Mysql.SlowThreshold, imConfig.Mysql.SlowThreshold) - - configFieldCopy(&Config.Log.StorageLocation, imConfig.Log.StorageLocation) - configFieldCopy(&Config.Log.RotationTime, imConfig.Log.RotationTime) - configFieldCopy(&Config.Log.RemainRotationCount, imConfig.Log.RemainRotationCount) - configFieldCopy(&Config.Log.RemainLogLevel, imConfig.Log.RemainLogLevel) - configFieldCopy(&Config.Log.IsStdout, imConfig.Log.IsStdout) - configFieldCopy(&Config.Log.WithStack, imConfig.Log.WithStack) - configFieldCopy(&Config.Log.IsJson, imConfig.Log.IsJson) - - configFieldCopy(&Config.Secret, imConfig.Secret) - configFieldCopy(&Config.TokenPolicy.Expire, imConfig.TokenPolicy.Expire) - - // Redis - configFieldCopy(&Config.Redis.Address, imConfig.Redis.Address) - configFieldCopy(&Config.Redis.Password, imConfig.Redis.Password) - configFieldCopy(&Config.Redis.Username, imConfig.Redis.Username) configData, err := yaml.Marshal(&Config) fmt.Printf("debug: %s\nconfig:\n%s\n", time.Now(), string(configData)) @@ -160,3 +178,79 @@ type zkLogger struct{} func (l *zkLogger) Printf(format string, a ...interface{}) { fmt.Printf("zk get config %s\n", fmt.Sprintf(format, a...)) } + +func checkFileExists(filePath string) bool { + info, err := os.Stat(filePath) + if os.IsNotExist(err) { + return false + } + return !info.IsDir() +} + +func findConfigFile(paths []string) (string, error) { + for _, path := range paths { + if checkFileExists(path) { + return path, nil + } + } + return "", fmt.Errorf("configPath not found") +} + +func CreateCatalogPath() []string { + + return []string{Constant.ConfigPath1, Constant.ConfigPath2} +} + +func findConfigPath(configFile string) (string, error) { + path := make([]string, 10) + + // First, check the configFile argument + if configFile != "" { + if _, err := findConfigFile([]string{configFile}); err != nil { + return "", errors.New("the configFile argument path is error") + } + return configFile, nil + } + + // Second, check for OPENIMCONFIG environment variable + envConfigPath := os.Getenv(Constant.OpenIMConfig) + if envConfigPath != "" { + if _, err := findConfigFile([]string{envConfigPath}); err != nil { + return "", errors.New("the environment path config path is error") + } + return envConfigPath, nil + } + + // Third, check the catalog to find the config.yaml + path = CreateCatalogPath() + pathFind, err := findConfigFile(path) + if err == nil { + return pathFind, nil + } + + // Forth, use the Default path. + return Constant.Default, nil +} + +func FlagParse() (string, int, bool, bool, error) { + var configFile string + flag.StringVar(&configFile, "config_folder_path", "", "Config full path") + + var ginPort int + flag.IntVar(&ginPort, "port", 10009, "get ginServerPort from cmd") + + var hide bool + flag.BoolVar(&hide, "hide", false, "hide the ComponentCheck result") + + // Version flag + var showVersion bool + flag.BoolVar(&showVersion, "version", false, "show version and exit") + + flag.Parse() + + configFile, err := findConfigPath(configFile) + if err != nil { + return "", 0, false, false, err + } + return configFile, ginPort, hide, showVersion, nil +} diff --git a/pkg/common/config/version b/pkg/common/config/version index 70cdc089..56e50151 100644 --- a/pkg/common/config/version +++ b/pkg/common/config/version @@ -1 +1 @@ -v3.1.1 \ No newline at end of file +v3.3.1 \ No newline at end of file diff --git a/pkg/common/constant/constant.go b/pkg/common/constant/constant.go index 2a0b92c2..ca53f574 100644 --- a/pkg/common/constant/constant.go +++ b/pkg/common/constant/constant.go @@ -16,11 +16,20 @@ package constant import "github.com/OpenIMSDK/protocol/constant" +// config path +const ( + ConfigPath1 = "../config/config.yaml" + ConfigPath2 = "../../../../../config/config.yaml" + + OpenIMConfig = "OpenIMConfig" // environment variables + Default = "../../../config/config.yaml" +) + const ( // verificationCode used for. - VerificationCodeForRegister = 1 // 注册 - VerificationCodeForResetPassword = 2 // 重置密码 - VerificationCodeForLogin = 3 // 登录 + VerificationCodeForRegister = 1 // Register + VerificationCodeForResetPassword = 2 // Reset password + VerificationCodeForLogin = 3 // Login VerificationCodeForRegisterSuffix = "_forRegister" VerificationCodeForResetSuffix = "_forReset" @@ -56,8 +65,8 @@ const ( // AddFriendCtrl. const ( - OrdinaryUserAddFriendEnable = 1 // 允许普通用户添加好友 - OrdinaryUserAddFriendDisable = -1 // 不允许普通用户添加好友 + OrdinaryUserAddFriendEnable = 1 // Allow ordinary users to add friends + OrdinaryUserAddFriendDisable = -1 // Do not allow ordinary users to add friends ) // minioUpload. @@ -74,15 +83,15 @@ const ( ) const ( - ScreenInvitationRegisterAll = 0 // 全部 - ScreenInvitationRegisterUsed = 1 // 已使用 - ScreenInvitationRegisterNotUsed = 2 // 未使用 + ScreenInvitationRegisterAll = 0 // All + ScreenInvitationRegisterUsed = 1 // Used + ScreenInvitationRegisterNotUsed = 2 // Unused ) // 1 block; 2 unblock. const ( - UserBlock = 1 // 封号 - UserUnblock = 2 // 解封 + UserBlock = 1 // Account ban + UserUnblock = 2 // Unban ) const ( @@ -116,14 +125,14 @@ const ( ) const ( - NotNeedInvitationCodeRegister = 0 // 不需要邀请码 - NeedInvitationCodeRegister = 1 // 需要邀请码 + NotNeedInvitationCodeRegister = 0 // No invitation code required + NeedInvitationCodeRegister = 1 // Invitation code required ) -// 小程序. +// mini-app const ( - StatusOnShelf = 1 // 上架 - StatusUnShelf = 2 // 下架 + StatusOnShelf = 1 // OnShelf + StatusUnShelf = 2 // UnShelf ) const ( @@ -132,22 +141,22 @@ const ( ) const ( - LimitNil = 0 // 无 - LimitEmpty = 1 // 都不限制 - LimitOnlyLoginIP = 2 // 仅限制登录 - LimitOnlyRegisterIP = 3 // 仅限制注册 - LimitLoginIP = 4 // 限制登录 - LimitRegisterIP = 5 // 限制注册 - LimitLoginRegisterIP = 6 // 限制登录注册 + LimitNil = 0 // None + LimitEmpty = 1 // Neither are restricted + LimitOnlyLoginIP = 2 // Only login is restricted + LimitOnlyRegisterIP = 3 // Only registration is restricted + LimitLoginIP = 4 // Restrict login + LimitRegisterIP = 5 // Restrict registration + LimitLoginRegisterIP = 6 // Restrict both login and registration ) const ( - InvitationCodeAll = 0 // 全部 - InvitationCodeUsed = 1 // 已使用 - InvitationCodeUnused = 2 // 未使用 + InvitationCodeAll = 0 // All + InvitationCodeUsed = 1 // Used + InvitationCodeUnused = 2 // Unused ) -// 默认发现页面. +// Default discovery page const DefaultDiscoverPageURL = "https://doc.rentsoft.cn/#/" // const OperationID = "operationID" diff --git a/pkg/common/db/model/admin/admin.go b/pkg/common/db/model/admin/admin.go index f4e8d04a..befd2659 100644 --- a/pkg/common/db/model/admin/admin.go +++ b/pkg/common/db/model/admin/admin.go @@ -18,9 +18,11 @@ import ( "context" "crypto/md5" "encoding/hex" - "github.com/OpenIMSDK/tools/log" "time" + + "github.com/OpenIMSDK/tools/log" + "github.com/OpenIMSDK/chat/pkg/common/config" "github.com/OpenIMSDK/chat/pkg/common/db/table/admin" "github.com/OpenIMSDK/tools/errs" diff --git a/pkg/common/db/model/chat/log.go b/pkg/common/db/model/chat/log.go index 5cb15119..df138f5f 100644 --- a/pkg/common/db/model/chat/log.go +++ b/pkg/common/db/model/chat/log.go @@ -2,11 +2,12 @@ package chat import ( "context" + "time" + "github.com/OpenIMSDK/chat/pkg/common/db/table/chat" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/ormutil" "gorm.io/gorm" - "time" ) type Logs struct { @@ -39,6 +40,7 @@ func (l *Logs) Get(ctx context.Context, logIDs []string, userID string) ([]*chat } return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Find(&logs).Error) } + func NewLogs(db *gorm.DB) chat.LogInterface { return &Logs{db: db} } diff --git a/pkg/common/db/model/chat/user_login_record.go b/pkg/common/db/model/chat/user_login_record.go index 54fe1756..cb3b1f6e 100644 --- a/pkg/common/db/model/chat/user_login_record.go +++ b/pkg/common/db/model/chat/user_login_record.go @@ -16,9 +16,10 @@ package chat import ( "context" + "time" + "github.com/OpenIMSDK/tools/errs" - "time" "gorm.io/gorm" diff --git a/pkg/common/version/base.go b/pkg/common/version/base.go new file mode 100644 index 00000000..6d2c2dc8 --- /dev/null +++ b/pkg/common/version/base.go @@ -0,0 +1,47 @@ +package version + +// Base version information. +// +// This is the fallback data used when version information from git is not +// provided via go ldflags. It provides an approximation of the Kubernetes +// version for ad-hoc builds (e.g. `go build`) that cannot get the version +// information from git. +// +// If you are looking at these fields in the git tree, they look +// strange. They are modified on the fly by the build process. The +// in-tree values are dummy values used for "git archive", which also +// works for GitHub tar downloads. +// +// 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 +var ( + // TODO: Deprecate gitMajor and gitMinor, use only gitVersion + // instead. First step in deprecation, keep the fields but make + // them irrelevant. (Next we'll take it out, which may muck with + // scripts consuming the kubectl version output - but most of + // these should be looking at gitVersion already anyways.) + gitMajor string = "" // major version, always numeric + gitMinor string = "" // minor version, numeric possibly followed by "+" + + // semantic version, derived by build scripts (see + // https://github.com/kubernetes/sig-release/blob/master/release-engineering/versioning.md#kubernetes-release-versioning + // https://kubernetes.io/releases/version-skew-policy/ + // for a detailed discussion of this field) + // + // TODO: This field is still called "gitVersion" for legacy + // reasons. For prerelease versions, the build metadata on the + // semantic version is a git hash, but the version itself is no + // longer the direct output of "git describe", but a slight + // translation to be semver compliant. + + // NOTE: The $Format strings are replaced during 'git archive' thanks to the + // companion .gitattributes file containing 'export-subst' in this same + // directory. See also https://git-scm.com/docs/gitattributes + gitVersion string = "latest" + gitCommit string = "" // sha1 from git, output of $(git rev-parse HEAD) + gitTreeState string = "" // state of git tree, either "clean" or "dirty" + + buildDate string = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') +) \ No newline at end of file diff --git a/pkg/common/version/types.go b/pkg/common/version/types.go new file mode 100644 index 00000000..3778220b --- /dev/null +++ b/pkg/common/version/types.go @@ -0,0 +1,20 @@ +package version + +// Info contains versioning information. +// TODO: Add []string of api versions supported? It's still unclear +// how we'll want to distribute that information. +type Info struct { + Major string `json:"major,omitempty"` + Minor string `json:"minor,omitempty"` + GitVersion string `json:"gitVersion"` + GitCommit string `json:"gitCommit,omitempty"` + BuildDate string `json:"buildDate"` + GoVersion string `json:"goVersion"` + Compiler string `json:"compiler"` + Platform string `json:"platform"` +} + +// String returns info as a human-friendly version string. +func (info Info) String() string { + return info.GitVersion +} \ No newline at end of file diff --git a/pkg/common/version/version.go b/pkg/common/version/version.go new file mode 100644 index 00000000..f2fb64d9 --- /dev/null +++ b/pkg/common/version/version.go @@ -0,0 +1,38 @@ +package version + +import ( + "fmt" + "runtime" +) + +// Get returns the overall codebase version. It's for detecting +// what code a binary was built from. +func Get() Info { + // These variables typically come from -ldflags settings and in + // their absence fallback to the settings in ./base.go + return Info{ + Major: gitMajor, + Minor: gitMinor, + GitVersion: gitVersion, + GitCommit: gitCommit, + BuildDate: buildDate, + GoVersion: runtime.Version(), + Compiler: runtime.Compiler, + Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), + } +} + +// GetSingleVersion returns single version of sealer +func GetSingleVersion() string { + return gitVersion +} + +type Output struct { + OpenIMChatVersion Info `json:"OpenIMChatVersion,omitempty" yaml:"OpenIMChatVersion,omitempty"` + OpenIMServerVersion *OpenIMServerVersion `json:"OpenIMServerVersion,omitempty" yaml:"OpenIMServerVersion,omitempty"` +} + +type OpenIMServerVersion struct { + ServerVersion string `json:"serverVersion,omitempty" yaml:"serverVersion,omitempty"` + ClientVersion string `json:"clientVersion,omitempty" yaml:"clientVersion,omitempty"` //sdk core version +} \ No newline at end of file diff --git a/pkg/discovery_register/k8s_discovery_register.go b/pkg/discovery_register/k8s_discovery_register.go new file mode 100644 index 00000000..a8ee5fff --- /dev/null +++ b/pkg/discovery_register/k8s_discovery_register.go @@ -0,0 +1,94 @@ +package discovery_register + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/OpenIMSDK/chat/pkg/common/config" + "github.com/OpenIMSDK/tools/discoveryregistry" + openkeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper" + "github.com/OpenIMSDK/tools/log" + "google.golang.org/grpc" +) + +func NewDiscoveryRegister(envType string) (discoveryregistry.SvcDiscoveryRegistry, error) { + var client discoveryregistry.SvcDiscoveryRegistry + var err error + 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())) + case "k8s": + client, err = NewK8sDiscoveryRegister() + default: + client = nil + err = 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 { + cli.rpcRegisterAddr = serviceName + 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) 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 +} + +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/proto/chat/chat.go b/pkg/proto/chat/chat.go index 61cc24b1..d6e8cd05 100644 --- a/pkg/proto/chat/chat.go +++ b/pkg/proto/chat/chat.go @@ -15,10 +15,11 @@ package chat import ( - "github.com/OpenIMSDK/tools/utils" "regexp" "strconv" + "github.com/OpenIMSDK/tools/utils" + "github.com/OpenIMSDK/chat/pkg/common/constant" constant2 "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/tools/errs" @@ -221,6 +222,7 @@ func (x *UploadLogsReq) Check() error { } return nil } + func (x *SearchLogsReq) Check() error { if x.Pagination == nil { return errs.ErrArgs.Wrap("Pagination is empty") diff --git a/pkg/sms/sms.go b/pkg/sms/sms.go index 7a6f4a3e..8966822d 100644 --- a/pkg/sms/sms.go +++ b/pkg/sms/sms.go @@ -17,9 +17,9 @@ package sms import ( "context" "fmt" - "github.com/OpenIMSDK/chat/pkg/common/config" "strings" + "github.com/OpenIMSDK/chat/pkg/common/config" ) func New() (SMS, error) { diff --git a/scripts/check_all.sh b/scripts/check_all.sh index 3e28955f..a087f5e6 100755 --- a/scripts/check_all.sh +++ b/scripts/check_all.sh @@ -47,16 +47,35 @@ service_port_name=( switch=$(cat $config_path | grep demoswitch |awk -F '[:]' '{print $NF}') for i in ${service_port_name[*]}; do - list=$(cat $config_path | grep -w ${i} | awk -F '[:]' '{print $NF}') - list_to_string $list - for j in ${ports_array}; do - port=$(ps -ef |grep -E 'api|rpc|open_im' |awk '{print $10}'| grep -w ${j}) - if [[ ${port} -ne ${j} ]]; then - echo -e ${YELLOW_PREFIX}${i}${COLOR_SUFFIX}${RED_PREFIX}" service does not start normally,not initiated port is "${COLOR_SUFFIX}${YELLOW_PREFIX}${j}${COLOR_SUFFIX} - echo -e ${RED_PREFIX}"please check ../logs/openIM.log "${COLOR_SUFFIX} + case $i in + "openImChatApiPort") + new_service_name="chat-api" + new_service_port="10008" + ;; + "openImAdminApiPort") + new_service_name="admin-rpc" + new_service_port="30200" + ;; + "openImAdminPort") + new_service_name="chat-rpc" + new_service_port="30300" + ;; + "openImChatPort") + new_service_name="admin-api" + new_service_port="10009" + ;; + *) + echo "Invalid service name: $i" exit -1 - else - echo -e ${j}${GREEN_PREFIX}" port has been listening,belongs service is "${i}${COLOR_SUFFIX} - fi - done -done + ;; + esac + + port=$(ss -tunlp | grep "$new_service_name" | awk '{print $5}' | awk -F '[:]' '{print $NF}') + if [[ "$port" != "$new_service_port" ]]; then + echo -e "${YELLOW_PREFIX}${i}${COLOR_SUFFIX}${RED_PREFIX} service does not start normally, not initiated port is ${COLOR_SUFFIX}${YELLOW_PREFIX}${new_service_port}${COLOR_SUFFIX}" + echo -e "${RED_PREFIX}please check ${SCRIPTS_ROOT}/../logs/openIM.log ${COLOR_SUFFIX}" + exit -1 + else + echo -e "${new_service_port}${GREEN_PREFIX} port has been listening, belongs service is ${i}${COLOR_SUFFIX}" + fi +done \ No newline at end of file diff --git a/scripts/start_all.sh b/scripts/start_all.sh index c0616ebf..4c6c14ab 100755 --- a/scripts/start_all.sh +++ b/scripts/start_all.sh @@ -108,4 +108,4 @@ for ((i = 0; i < ${#service_filename[*]}; i++)); do # pid="netstat -ntlp|grep $j |awk '{printf \$7}'|cut -d/ -f1" # echo -e "${GREEN_PREFIX}${service_filename[$i]} start success,port number:${service_ports[$j]} pid:$(eval $pid)$COLOR_SUFFIX" done -done +done \ No newline at end of file diff --git a/tools/component/component.go b/tools/component/component.go index 3f28862f..a6edfe13 100644 --- a/tools/component/component.go +++ b/tools/component/component.go @@ -2,15 +2,16 @@ package component import ( "fmt" - "github.com/OpenIMSDK/chat/pkg/common/config" "github.com/OpenIMSDK/protocol/constant" + "os" + "time" + + "github.com/OpenIMSDK/chat/pkg/common/config" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/go-zookeeper/zk" "github.com/pkg/errors" "gopkg.in/yaml.v3" - "os" - "time" ) func initCfg(cfgPath string) error { @@ -31,15 +32,18 @@ func ComponentCheck(cfgPath string, hide bool) error { errorPrint(errs.Wrap(err).Error(), hide) return err } - var zkConn *zk.Conn - if zkConn, err = checkNewZkClient(hide); err != nil { - errorPrint(fmt.Sprintf("%v.Please check if your openIM server has started", err.Error()), hide) - return err - } - if err = checkGetCfg(zkConn, hide); err != nil { - errorPrint(fmt.Sprintf("%v.Please check if your openIM server has started", err.Error()), hide) - return err + if config.Config.Envs.Discovery != "k8s" { + var zkConn *zk.Conn + if zkConn, err = checkNewZkClient(hide); err != nil { + errorPrint(fmt.Sprintf("%v.Please check if your openIM server has started", err.Error()), hide) + return err + } + if err = checkGetCfg(zkConn, hide); err != nil { + errorPrint(fmt.Sprintf("%v.Please check if your openIM server has started", err.Error()), hide) + return err + } } + return nil } From dc74d650208f58f635f7db9c329385919ef4727d Mon Sep 17 00:00:00 2001 From: Brabem <69128477+luhaoling@users.noreply.github.com> Date: Wed, 8 Nov 2023 21:46:57 +0800 Subject: [PATCH 6/6] fix: fix the flag parse (#260) * fix:alter the config.yaml path * fix:fix the const error * fix:update the config.yaml path * fix:update parse.go * Update parse.go add default path * Update parse.go * Update parse.go * Update parse.go --- pkg/common/config/parse.go | 32 +++++++++++++++++++++++++++----- pkg/common/constant/constant.go | 4 +--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go index 561fe28e..c5e38b4a 100644 --- a/pkg/common/config/parse.go +++ b/pkg/common/config/parse.go @@ -196,9 +196,24 @@ func findConfigFile(paths []string) (string, error) { return "", fmt.Errorf("configPath not found") } -func CreateCatalogPath() []string { +func CreateCatalogPath(path string) []string { + + path1 := filepath.Dir(path) + path1 = filepath.Dir(path1) + // the parent of binary file + pa1 := filepath.Join(path1, Constant.ConfigPath) + path2 := filepath.Dir(path1) + path2 = filepath.Dir(path2) + path2 = filepath.Dir(path2) + // the parent is _output + pa2 := filepath.Join(path2, Constant.ConfigPath) + path3 := filepath.Dir(path2) + // the parent is project(default) + pa3 := filepath.Join(path3, Constant.ConfigPath) + + return []string{pa1, pa2,pa3} + - return []string{Constant.ConfigPath1, Constant.ConfigPath2} } func findConfigPath(configFile string) (string, error) { @@ -209,10 +224,12 @@ func findConfigPath(configFile string) (string, error) { if _, err := findConfigFile([]string{configFile}); err != nil { return "", errors.New("the configFile argument path is error") } + fmt.Println("configfile:", configFile) return configFile, nil } // Second, check for OPENIMCONFIG environment variable + //envConfigPath := os.Getenv(Constant.OpenIMConfig) envConfigPath := os.Getenv(Constant.OpenIMConfig) if envConfigPath != "" { if _, err := findConfigFile([]string{envConfigPath}); err != nil { @@ -220,16 +237,21 @@ func findConfigPath(configFile string) (string, error) { } return envConfigPath, nil } - // Third, check the catalog to find the config.yaml - path = CreateCatalogPath() + + p1, err := os.Executable() + if err != nil { + return "", err + } + + path = CreateCatalogPath(p1) pathFind, err := findConfigFile(path) if err == nil { return pathFind, nil } // Forth, use the Default path. - return Constant.Default, nil + return "", errors.New("the config.yaml path not found") } func FlagParse() (string, int, bool, bool, error) { diff --git a/pkg/common/constant/constant.go b/pkg/common/constant/constant.go index ca53f574..5468507b 100644 --- a/pkg/common/constant/constant.go +++ b/pkg/common/constant/constant.go @@ -18,11 +18,9 @@ import "github.com/OpenIMSDK/protocol/constant" // config path const ( - ConfigPath1 = "../config/config.yaml" - ConfigPath2 = "../../../../../config/config.yaml" + ConfigPath = "/config/config.yaml" OpenIMConfig = "OpenIMConfig" // environment variables - Default = "../../../config/config.yaml" ) const (