Commit 73638b67 authored by Murfey.Mou's avatar Murfey.Mou :poop:
Browse files

add rbac control

parent 5bee1dac
No related merge requests found
Showing with 205 additions and 52 deletions
+205 -52
......@@ -47,11 +47,11 @@ type (
)
type (
BoardcastReq struct {
BroadcastReq struct {
AnimalId int64 `json:"animal_id"`
AlertLevel string `json:"alert_level"`
}
BoardcastRsp struct {
BroadcastRsp struct {
Message string `json:"message"`
}
)
......@@ -64,7 +64,7 @@ service mtt-zoo-gateway {
@server (
jwt: JwtAuth
)
service mtt-zoo-gateway {
service mtt-zoo-gateway-service {
@handler VisitListHandler
get /mttzoo/visit/list() returns(VisitRsp)
@handler VisitGetHandler
......@@ -73,6 +73,6 @@ service mtt-zoo-gateway {
post /mttzoo/management/modify(AnimalManagementReq) returns(AnimalManagementRsp)
@handler ZooManagementRemoveHandler
post /mttzoo/management/remove(AnimalManagementReq) returns(AnimalManagementRsp)
@handler BoardcastHandler
post /mttzoo/boardcast/new(BoardcastReq) returns(BoardcastRsp)
@handler BroadcastHandler
post /mttzoo/broadcast/new(BroadcastReq) returns(BroadcastRsp)
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/golang/protobuf v1.4.2
github.com/tal-tech/go-zero v1.0.28
github.com/tidwall/gjson v1.6.3 // indirect
github.com/tidwall/gjson v1.6.3
google.golang.org/grpc v1.29.1
google.golang.org/protobuf v1.25.0
)
Name: mtt-zoo-gateway-service
Host: 0.0.0.0
Port: 8888
JwtAuth:
AccessSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AccessExpire: 604800
HumanService:
Etcd:
Hosts:
- localhost:2379
Key: mtt-zoo-human-service.rpc
AnimalService:
Etcd:
Hosts:
- localhost:2379
Key: mtt-zoo-animal-service.rpc
UseRBACControl: true
AccessControlService:
Etcd:
Hosts:
- localhost:2379
Key: mtt-zoo-access-control-service.rpc
......@@ -17,7 +17,7 @@ AnimalService:
- localhost:2379
Key: mtt-zoo-animal-service.rpc
UseRBACControl: false
UseRBACControl: true
AccessControlService:
Etcd:
Hosts:
......
......@@ -10,16 +10,16 @@ import (
"github.com/tal-tech/go-zero/rest/httpx"
)
func boardcastHandler(ctx *svc.ServiceContext) http.HandlerFunc {
func broadcastHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.BoardcastReq
var req types.BroadcastReq
if err := httpx.Parse(r, &req); err != nil {
httpx.Error(w, err)
return
}
l := logic.NewBoardcastLogic(r.Context(), ctx)
resp, err := l.Boardcast(req)
l := logic.NewBroadcastLogic(r.Context(), ctx)
resp, err := l.Broadcast(req, r.Header.Get("Authorization"))
if err != nil {
httpx.Error(w, err)
} else {
......
......@@ -44,8 +44,8 @@ func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {
},
{
Method: http.MethodPost,
Path: "/mttzoo/boardcast/new",
Handler: boardcastHandler(serverCtx),
Path: "/mttzoo/broadcast/new",
Handler: broadcastHandler(serverCtx),
},
},
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
......
......@@ -19,7 +19,7 @@ func visitGetHandler(ctx *svc.ServiceContext) http.HandlerFunc {
}
l := logic.NewVisitGetLogic(r.Context(), ctx)
resp, err := l.VisitGet(req)
resp, err := l.VisitGet(req, r.Header.Get("Authorization"))
if err != nil {
httpx.Error(w, err)
} else {
......
......@@ -12,7 +12,7 @@ func visitListHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := logic.NewVisitListLogic(r.Context(), ctx)
resp, err := l.VisitList()
resp, err := l.VisitList(r.Header.Get("Authorization"))
if err != nil {
httpx.Error(w, err)
} else {
......
......@@ -19,7 +19,7 @@ func zooManagementAddHandler(ctx *svc.ServiceContext) http.HandlerFunc {
}
l := logic.NewZooManagementAddLogic(r.Context(), ctx)
resp, err := l.ZooManagementAdd(req)
resp, err := l.ZooManagementAdd(req, r.Header.Get("Authorization"))
if err != nil {
httpx.Error(w, err)
} else {
......
......@@ -19,7 +19,7 @@ func zooManagementRemoveHandler(ctx *svc.ServiceContext) http.HandlerFunc {
}
l := logic.NewZooManagementRemoveLogic(r.Context(), ctx)
resp, err := l.ZooManagementRemove(req)
resp, err := l.ZooManagementRemove(req, r.Header.Get("Authorization"))
if err != nil {
httpx.Error(w, err)
} else {
......
......@@ -2,6 +2,8 @@ package logic
import (
"context"
"errors"
"go-zero-demo/mtt-zoo-access-control-service/accesscontrolservice"
"go-zero-demo/mtt-zoo-gateway-service/internal/svc"
"go-zero-demo/mtt-zoo-gateway-service/internal/types"
......@@ -9,22 +11,37 @@ import (
"github.com/tal-tech/go-zero/core/logx"
)
type BoardcastLogic struct {
type BroadcastLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewBoardcastLogic(ctx context.Context, svcCtx *svc.ServiceContext) BoardcastLogic {
return BoardcastLogic{
func NewBroadcastLogic(ctx context.Context, svcCtx *svc.ServiceContext) BroadcastLogic {
return BroadcastLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *BoardcastLogic) Boardcast(req types.BoardcastReq) (*types.BoardcastRsp, error) {
func (l *BroadcastLogic) Broadcast(req types.BroadcastReq, token string) (*types.BroadcastRsp, error) {
// todo: add your logic here and delete this line
if l.svcCtx.Config.UseRBACControl {
load, err := ParseToken(l.svcCtx.Config.JwtAuth.AccessSecret, token)
if err != nil {
return nil, err
}
if resp, err := l.svcCtx.AccessControlService.CheckAuth(l.ctx, &accesscontrolservice.CheckAuthRequest{
UserId: int64(load["user_id"].(float64)),
RequestResource: "Broadcast",
}); err != nil {
return nil, err
} else if !resp.Authorized {
// Unauthorized
return nil, errors.New("unauthorized request")
}
}
return &types.BoardcastRsp{}, nil
return &types.BroadcastRsp{}, nil
}
......@@ -33,7 +33,10 @@ func (l *LoginLogic) Login(req types.LoginReq) (*types.LoginRsp, error) {
if err != nil {
return nil, err
}
token, err := GenToken(time.Now().Unix(), l.svcCtx.Config.JwtAuth.AccessSecret, nil, l.svcCtx.Config.JwtAuth.AccessExpire)
payload := map[string]interface{}{
"user_id": resp.UserId,
}
token, err := GenToken(time.Now().Unix(), l.svcCtx.Config.JwtAuth.AccessSecret, payload, l.svcCtx.Config.JwtAuth.AccessExpire)
if err != nil {
return nil, err
}
......
package logic
import "github.com/dgrijalva/jwt-go"
import (
"errors"
"github.com/dgrijalva/jwt-go"
)
func GenToken(iat int64, secretKey string, payloads map[string]interface{}, seconds int64) (string, error) {
claims := make(jwt.MapClaims)
......@@ -15,3 +18,16 @@ func GenToken(iat int64, secretKey string, payloads map[string]interface{}, seco
return token.SignedString([]byte(secretKey))
}
func ParseToken(secretKey string, tokenString string) (map[string]interface{}, error) {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte(secretKey), nil
})
if err != nil {
return nil, err
}
if token.Valid {
return token.Claims.(jwt.MapClaims), nil
}
return nil, errors.New("invalid token")
}
......@@ -2,6 +2,8 @@ package logic
import (
"context"
"errors"
"go-zero-demo/mtt-zoo-access-control-service/accesscontrolservice"
"go-zero-demo/mtt-zoo-animal-service/animalservice"
"go-zero-demo/mtt-zoo-gateway-service/internal/svc"
......@@ -24,7 +26,22 @@ func NewVisitGetLogic(ctx context.Context, svcCtx *svc.ServiceContext) VisitGetL
}
}
func (l *VisitGetLogic) VisitGet(req types.VisitReq) (*types.Animal, error) {
func (l *VisitGetLogic) VisitGet(req types.VisitReq, token string) (*types.Animal, error) {
if l.svcCtx.Config.UseRBACControl {
load, err := ParseToken(l.svcCtx.Config.JwtAuth.AccessSecret, token)
if err != nil {
return nil, err
}
if resp, err := l.svcCtx.AccessControlService.CheckAuth(l.ctx, &accesscontrolservice.CheckAuthRequest{
UserId: int64(load["user_id"].(float64)),
RequestResource: "ZooVisit",
}); err != nil {
return nil, err
} else if !resp.Authorized {
// Unauthorized
return nil, errors.New("unauthorized request")
}
}
resp, err := l.svcCtx.AnimalService.Get(l.ctx, &animalservice.GetRequest{
AnimalId: req.AnimalId,
})
......
......@@ -2,6 +2,8 @@ package logic
import (
"context"
"errors"
"go-zero-demo/mtt-zoo-access-control-service/accesscontrolservice"
"go-zero-demo/mtt-zoo-animal-service/animalservice"
"go-zero-demo/mtt-zoo-gateway-service/internal/svc"
......@@ -24,7 +26,22 @@ func NewVisitListLogic(ctx context.Context, svcCtx *svc.ServiceContext) VisitLis
}
}
func (l *VisitListLogic) VisitList() (*types.VisitRsp, error) {
func (l *VisitListLogic) VisitList(token string) (*types.VisitRsp, error) {
if l.svcCtx.Config.UseRBACControl {
load, err := ParseToken(l.svcCtx.Config.JwtAuth.AccessSecret, token)
if err != nil {
return nil, err
}
if resp, err := l.svcCtx.AccessControlService.CheckAuth(l.ctx, &accesscontrolservice.CheckAuthRequest{
UserId: int64(load["user_id"].(float64)),
RequestResource: "ZooVisit",
}); err != nil {
return nil, err
} else if !resp.Authorized {
// Unauthorized
return nil, errors.New("unauthorized request")
}
}
resp, err := l.svcCtx.AnimalService.List(l.ctx, &animalservice.ListRequest{})
if err != nil {
return nil, err
......
......@@ -2,6 +2,7 @@ package logic
import (
"context"
"errors"
"go-zero-demo/mtt-zoo-access-control-service/accesscontrolservice"
"go-zero-demo/mtt-zoo-animal-service/animalservice"
......@@ -25,15 +26,20 @@ func NewZooManagementAddLogic(ctx context.Context, svcCtx *svc.ServiceContext) Z
}
}
func (l *ZooManagementAddLogic) ZooManagementAdd(req types.AnimalManagementReq) (*types.AnimalManagementRsp, error) {
func (l *ZooManagementAddLogic) ZooManagementAdd(req types.AnimalManagementReq, token string) (*types.AnimalManagementRsp, error) {
if l.svcCtx.Config.UseRBACControl {
load, err := ParseToken(l.svcCtx.Config.JwtAuth.AccessSecret, token)
if err != nil {
return nil, err
}
if resp, err := l.svcCtx.AccessControlService.CheckAuth(l.ctx, &accesscontrolservice.CheckAuthRequest{
UserId: 0,
RequestResource: "",
UserId: int64(load["user_id"].(float64)),
RequestResource: "ZooManagement",
}); err != nil {
return nil, err
} else if !resp.Authorized {
// Unauthorized
return nil, errors.New("unauthorized request")
}
}
resp, err := l.svcCtx.AnimalService.Modify(l.ctx, &animalservice.AnimalManagementRequest{
......
......@@ -2,6 +2,8 @@ package logic
import (
"context"
"errors"
"go-zero-demo/mtt-zoo-access-control-service/accesscontrolservice"
"go-zero-demo/mtt-zoo-animal-service/animalservice"
"go-zero-demo/mtt-zoo-gateway-service/internal/svc"
......@@ -24,12 +26,22 @@ func NewZooManagementRemoveLogic(ctx context.Context, svcCtx *svc.ServiceContext
}
}
func (l *ZooManagementRemoveLogic) ZooManagementRemove(req types.AnimalManagementReq) (*types.AnimalManagementRsp, error) {
// todo: rbac management control
func (l *ZooManagementRemoveLogic) ZooManagementRemove(req types.AnimalManagementReq, token string) (*types.AnimalManagementRsp, error) {
if l.svcCtx.Config.UseRBACControl {
logx.Info("Use RBAC Now")
load, err := ParseToken(l.svcCtx.Config.JwtAuth.AccessSecret, token)
if err != nil {
return nil, err
}
if resp, err := l.svcCtx.AccessControlService.CheckAuth(l.ctx, &accesscontrolservice.CheckAuthRequest{
UserId: int64(load["user_id"].(float64)),
RequestResource: "ZooManagement",
}); err != nil {
return nil, err
} else if !resp.Authorized {
// Unauthorized
return nil, errors.New("unauthorized request")
}
}
resp, err := l.svcCtx.AnimalService.Remove(l.ctx, &animalservice.AnimalManagementRequest{
AnimalId: req.AnimalId,
AnimalName: req.AnimalName,
......
......@@ -19,12 +19,12 @@ type AnimalManagementRsp struct {
AnimalId int64 `json:"animal_id"`
}
type BoardcastReq struct {
type BroadcastReq struct {
AnimalId int64 `json:"animal_id"`
AlertLevel string `json:"alert_level"`
}
type BoardcastRsp struct {
type BroadcastRsp struct {
Message string `json:"message"`
}
......
......@@ -92,6 +92,7 @@ type LoginResponse struct {
Token string `protobuf:"bytes,1,opt,name=Token,proto3" json:"Token,omitempty"`
Expire int64 `protobuf:"varint,2,opt,name=Expire,proto3" json:"Expire,omitempty"`
RoleType string `protobuf:"bytes,3,opt,name=RoleType,proto3" json:"RoleType,omitempty"`
UserId int64 `protobuf:"varint,4,opt,name=UserId,proto3" json:"UserId,omitempty"`
}
func (x *LoginResponse) Reset() {
......@@ -147,6 +148,13 @@ func (x *LoginResponse) GetRoleType() string {
return ""
}
func (x *LoginResponse) GetUserId() int64 {
if x != nil {
return x.UserId
}
return 0
}
type GetUserRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
......@@ -266,31 +274,33 @@ var file_login_proto_rawDesc = []byte{
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
0x6f, 0x72, 0x64, 0x22, 0x59, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x72, 0x64, 0x22, 0x71, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x45, 0x78,
0x70, 0x69, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x45, 0x78, 0x70, 0x69,
0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x28,
0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x61, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x55,
0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x55, 0x73, 0x65,
0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x1a, 0x0a, 0x08, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x32, 0x98, 0x01, 0x0a, 0x0c,
0x48, 0x75, 0x6d, 0x61, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x40, 0x0a, 0x05,
0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1a, 0x2e, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1b, 0x2e, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46,
0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x68, 0x75, 0x6d, 0x61,
0x6e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16,
0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x28, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65,
0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72,
0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64,
0x22, 0x61, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x55,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x55,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x6f, 0x6c, 0x65, 0x54,
0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x6f, 0x6c, 0x65, 0x54,
0x79, 0x70, 0x65, 0x32, 0x98, 0x01, 0x0a, 0x0c, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0x40, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1a, 0x2e,
0x68, 0x75, 0x6d, 0x61, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x6f, 0x67,
0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x68, 0x75, 0x6d, 0x61,
0x6e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65,
0x72, 0x12, 0x1c, 0x2e, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x1d, 0x2e, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47,
0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment