From 260ea04d960bc4b5c25e62104e2ab12be713279b Mon Sep 17 00:00:00 2001 From: piupuer Date: Sat, 12 Oct 2024 17:25:04 +0800 Subject: [PATCH] [feat]add hotspot --- cmd/auth/wire_gen.go | 8 +- configs/task.yml | 18 +- docs/auth-proto/auth.openapi.yaml | 114 ++-- internal/biz/hotspot.go | 1 + internal/biz/permission.go | 50 +- internal/biz/user.go | 16 +- internal/biz/user_group.go | 1 - internal/biz/whitelist.go | 5 +- internal/conf/conf.pb.go | 510 ++++++++++++------ internal/conf/conf.proto | 15 +- internal/data/hotspot.go | 22 +- internal/data/permission.go | 41 +- internal/data/user.go | 17 +- internal/data/user_group.go | 24 - .../db/migrations/2023060217-default-data.sql | 6 +- internal/pkg/task/task.go | 25 +- internal/server/middleware/jwt.go | 4 +- internal/server/middleware/whitelist.go | 12 +- internal/service/action.go | 13 +- internal/service/auth.go | 40 +- internal/service/hotspot.go | 22 + internal/service/role.go | 5 +- internal/service/service.go | 8 +- internal/service/user.go | 13 +- internal/service/user_group.go | 9 +- internal/service/whitelist.go | 11 +- 26 files changed, 591 insertions(+), 419 deletions(-) create mode 100644 internal/service/hotspot.go diff --git a/cmd/auth/wire_gen.go b/cmd/auth/wire_gen.go index d435920..b790339 100644 --- a/cmd/auth/wire_gen.go +++ b/cmd/auth/wire_gen.go @@ -49,7 +49,7 @@ func wireApp(c *conf.Bootstrap) (*kratos.App, func(), error) { dataData, cleanup := data.NewData(universalClient, tenant, sonyflake, tracerProvider) hotspotRepo := data.NewHotspotRepo(c, dataData) actionRepo := data.NewActionRepo(c, dataData, hotspotRepo) - userRepo := data.NewUserRepo(dataData, actionRepo, hotspotRepo) + userRepo := data.NewUserRepo(dataData, actionRepo) transaction := data.NewTransaction(dataData) cache := data.NewCache(c, universalClient) userUseCase := biz.NewUserUseCase(c, userRepo, hotspotRepo, transaction, cache) @@ -64,11 +64,11 @@ func wireApp(c *conf.Bootstrap) (*kratos.App, func(), error) { roleUseCase := biz.NewRoleUseCase(c, roleRepo, transaction, cache) userGroupRepo := data.NewUserGroupRepo(dataData, actionRepo, userRepo) userGroupUseCase := biz.NewUserGroupUseCase(c, userGroupRepo, transaction, cache) - permissionRepo := data.NewPermissionRepo(dataData, actionRepo, userRepo, userGroupRepo, hotspotRepo) - permissionUseCase := biz.NewPermissionUseCase(c, permissionRepo, cache) + permissionRepo := data.NewPermissionRepo(dataData, actionRepo, hotspotRepo) + permissionUseCase := biz.NewPermissionUseCase(c, permissionRepo) whitelistRepo := data.NewWhitelistRepo(dataData, actionRepo, hotspotRepo) whitelistUseCase := biz.NewWhitelistUseCase(c, whitelistRepo, transaction, cache) - authService := service.NewAuthService(worker, idempotentIdempotent, userUseCase, actionUseCase, roleUseCase, userGroupUseCase, permissionUseCase, whitelistUseCase) + authService := service.NewAuthService(c, worker, idempotentIdempotent, userUseCase, actionUseCase, roleUseCase, userGroupUseCase, permissionUseCase, whitelistUseCase) grpcServer := server.NewGRPCServer(c, universalClient, idempotentIdempotent, authService, whitelistUseCase) httpServer := server.NewHTTPServer(c, universalClient, idempotentIdempotent, authService, whitelistUseCase) app := newApp(grpcServer, httpServer) diff --git a/configs/task.yml b/configs/task.yml index fb3041c..0ea1f73 100644 --- a/configs/task.yml +++ b/configs/task.yml @@ -1,4 +1,16 @@ task: - refresh.hotspot: - name: 'refresh.hotspot' - expr: '0 0/5 * * * * *' \ No newline at end of file + # cron task list + cron: + refresh.hotspot: + name: 'refresh.hotspot' + expr: '0 0/5 * * * * *' + # all group name list(cron or once) + group: + # login failed will delay to update wrong count(once) + loginFailed: 'login.failed' + # login success will delay to update last login time(once) + loginLast: 'login.last' + # refresh hotspot(cron) + refreshHotspot: 'refresh.hotspot' + # refresh hotspot manual(once) + refreshHotspotManual: 'refresh.hotspot.manual' diff --git a/docs/auth-proto/auth.openapi.yaml b/docs/auth-proto/auth.openapi.yaml index 866866c..89e93c6 100644 --- a/docs/auth-proto/auth.openapi.yaml +++ b/docs/auth-proto/auth.openapi.yaml @@ -122,43 +122,78 @@ paths: "200": description: OK content: {} - /captcha: + /idempotent: get: tags: - Auth - operationId: Auth_Captcha + operationId: Auth_Idempotent responses: "200": description: OK content: application/json: schema: - $ref: '#/components/schemas/auth.v1.CaptchaReply' - /idempotent: + $ref: '#/components/schemas/auth.v1.IdempotentReply' + /info: get: tags: - Auth - operationId: Auth_Idempotent + operationId: Auth_Info responses: "200": description: OK content: application/json: schema: - $ref: '#/components/schemas/auth.v1.IdempotentReply' - /info: + $ref: '#/components/schemas/auth.v1.InfoReply' + /logout: + post: + tags: + - Auth + operationId: Auth_Logout + requestBody: + content: + application/json: {} + required: true + responses: + "200": + description: OK + content: {} + /permission: get: tags: - Auth - operationId: Auth_Info + operationId: Auth_Permission + parameters: + - name: resource + in: query + schema: + type: string + - name: method + in: query + schema: + type: string + - name: uri + in: query + schema: + type: string + responses: + "200": + description: OK + content: {} + /pub/captcha: + get: + tags: + - Auth + operationId: Auth_Captcha responses: "200": description: OK content: application/json: schema: - $ref: '#/components/schemas/auth.v1.InfoReply' - /login: + $ref: '#/components/schemas/auth.v1.CaptchaReply' + /pub/login: post: tags: - Auth @@ -176,41 +211,38 @@ paths: application/json: schema: $ref: '#/components/schemas/auth.v1.LoginReply' - /logout: + /pub/register: post: tags: - Auth - operationId: Auth_Logout + operationId: Auth_Register requestBody: content: - application/json: {} + application/json: + schema: + $ref: '#/components/schemas/auth.v1.RegisterRequest' required: true responses: "200": description: OK content: {} - /permission: + /pub/status: get: tags: - Auth - operationId: Auth_Permission + operationId: Auth_Status parameters: - - name: resource - in: query - schema: - type: string - - name: method - in: query - schema: - type: string - - name: uri + - name: username in: query schema: type: string responses: "200": description: OK - content: {} + content: + application/json: + schema: + $ref: '#/components/schemas/auth.v1.StatusReply' /pwd: post: tags: @@ -244,21 +276,6 @@ paths: application/json: schema: $ref: '#/components/schemas/auth.v1.LoginReply' - /register: - post: - tags: - - Auth - operationId: Auth_Register - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/auth.v1.RegisterRequest' - required: true - responses: - "200": - description: OK - content: {} /role: get: tags: @@ -370,23 +387,6 @@ paths: "200": description: OK content: {} - /status: - get: - tags: - - Auth - operationId: Auth_Status - parameters: - - name: username - in: query - schema: - type: string - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/auth.v1.StatusReply' /user: get: tags: diff --git a/internal/biz/hotspot.go b/internal/biz/hotspot.go index 930cfc9..a529ddf 100644 --- a/internal/biz/hotspot.go +++ b/internal/biz/hotspot.go @@ -13,6 +13,7 @@ type HotspotRepo interface { GetRoleByID(ctx context.Context, id uint64) *Role GetActionByWord(ctx context.Context, word string) *Action GetActionByCode(ctx context.Context, code string) *Action + FindActionByCode(ctx context.Context, codes ...string) []Action FindWhitelistResourceByCategory(ctx context.Context, category uint32) []string FindUserGroupByUserCode(ctx context.Context, code string) []UserGroup } diff --git a/internal/biz/permission.go b/internal/biz/permission.go index a02e820..f37c606 100644 --- a/internal/biz/permission.go +++ b/internal/biz/permission.go @@ -2,12 +2,8 @@ package biz import ( "context" - "errors" - "strings" "auth/internal/conf" - "github.com/go-cinch/common/copierx" - "github.com/go-cinch/common/utils" ) type Permission struct { @@ -25,20 +21,18 @@ type CheckPermission struct { type PermissionRepo interface { Check(ctx context.Context, item CheckPermission) bool - GetByUserCode(ctx context.Context, code string) (*Permission, error) + GetByUserCode(ctx context.Context, code string) *Permission } type PermissionUseCase struct { - c *conf.Bootstrap - repo PermissionRepo - cache Cache + c *conf.Bootstrap + repo PermissionRepo } -func NewPermissionUseCase(c *conf.Bootstrap, repo PermissionRepo, cache Cache) *PermissionUseCase { +func NewPermissionUseCase(c *conf.Bootstrap, repo PermissionRepo) *PermissionUseCase { return &PermissionUseCase{ - c: c, - repo: repo, - cache: cache.WithPrefix("permission"), + c: c, + repo: repo, } } @@ -47,35 +41,7 @@ func (uc *PermissionUseCase) Check(ctx context.Context, item CheckPermission) (r return } -func (uc *PermissionUseCase) GetByUserCode(ctx context.Context, code string) (rp *Permission, err error) { - rp = &Permission{} - action := strings.Join([]string{"get_by_user_code", code}, "_") - str, err := uc.cache.Get(ctx, action, func(ctx context.Context) (string, error) { - return uc.getByUserCode(ctx, action, code) - }) - if err != nil { - return - } - utils.Json2Struct(&rp, str) +func (uc *PermissionUseCase) GetByUserCode(ctx context.Context, code string) (rp *Permission) { + rp = uc.repo.GetByUserCode(ctx, code) return } - -func (uc *PermissionUseCase) getByUserCode(ctx context.Context, action string, code string) (res string, err error) { - // read data from db and write to cache - rp := &Permission{} - permission, err := uc.repo.GetByUserCode(ctx, code) - notFound := errors.Is(err, ErrRecordNotFound(ctx)) - if err != nil && !notFound { - return - } - copierx.Copy(&rp, permission) - res = utils.Struct2Json(rp) - uc.cache.Set(ctx, action, res, notFound) - return -} - -func (uc *PermissionUseCase) FlushCache(ctx context.Context) { - uc.cache.Flush(ctx, func(ctx context.Context) (err error) { - return - }) -} diff --git a/internal/biz/user.go b/internal/biz/user.go index dd13a21..3106530 100644 --- a/internal/biz/user.go +++ b/internal/biz/user.go @@ -127,7 +127,6 @@ type UserRepo interface { WrongPwd(ctx context.Context, req LoginTime) error UpdatePassword(ctx context.Context, item *User) error IdExists(ctx context.Context, id uint64) error - GetByCode(ctx context.Context, code string) (*User, error) } type UserUseCase struct { @@ -173,10 +172,7 @@ func (uc *UserUseCase) Update(ctx context.Context, item *UpdateUser) error { func (uc *UserUseCase) Delete(ctx context.Context, ids ...uint64) error { return uc.tx.Tx(ctx, func(ctx context.Context) error { return uc.cache.Flush(ctx, func(ctx context.Context) (err error) { - info, err := uc.InfoFromCtx(ctx) - if err != nil { - return - } + info := uc.InfoFromCtx(ctx) if funk.ContainsUInt64(ids, info.Id) { err = ErrDeleteYourself(ctx) return @@ -187,8 +183,8 @@ func (uc *UserUseCase) Delete(ctx context.Context, ids ...uint64) error { }) } -func (uc *UserUseCase) GetUserByCode(ctx context.Context, code string) (rp *User, err error) { - return uc.repo.GetByCode(ctx, code) +func (uc *UserUseCase) GetUserByCode(ctx context.Context, code string) (rp *User) { + return uc.hotspot.GetUserByCode(ctx, code) } func (uc *UserUseCase) Find(ctx context.Context, condition *FindUser) (rp []User, err error) { @@ -217,14 +213,14 @@ func (uc *UserUseCase) find(ctx context.Context, action string, condition *FindU return } -func (uc *UserUseCase) InfoFromCtx(ctx context.Context) (rp *UserInfo, err error) { +func (uc *UserUseCase) InfoFromCtx(ctx context.Context) (rp *UserInfo) { user := jwt.FromServerContext(ctx) return uc.Info(ctx, user.Code) } -func (uc *UserUseCase) Info(ctx context.Context, code string) (rp *UserInfo, err error) { +func (uc *UserUseCase) Info(ctx context.Context, code string) (rp *UserInfo) { rp = &UserInfo{} - user, err := uc.GetUserByCode(ctx, code) + user := uc.hotspot.GetUserByCode(ctx, code) utils.Struct2StructByJson(rp, user) return } diff --git a/internal/biz/user_group.go b/internal/biz/user_group.go index 3a1de30..76bb982 100644 --- a/internal/biz/user_group.go +++ b/internal/biz/user_group.go @@ -43,7 +43,6 @@ type UserGroupRepo interface { Find(ctx context.Context, condition *FindUserGroup) []UserGroup Update(ctx context.Context, item *UpdateUserGroup) error Delete(ctx context.Context, ids ...uint64) error - FindGroupByUserCode(ctx context.Context, code string) []UserGroup } type UserGroupUseCase struct { diff --git a/internal/biz/whitelist.go b/internal/biz/whitelist.go index dc9e9ac..2d3afe1 100644 --- a/internal/biz/whitelist.go +++ b/internal/biz/whitelist.go @@ -106,9 +106,8 @@ func (uc *WhitelistUseCase) find(ctx context.Context, action string, condition * return } -func (uc *WhitelistUseCase) Has(ctx context.Context, condition *HasWhitelist) (rp bool, err error) { - rp = uc.repo.Has(ctx, condition) - return +func (uc *WhitelistUseCase) Has(ctx context.Context, condition *HasWhitelist) (rp bool) { + return uc.repo.Has(ctx, condition) } func (uc *WhitelistUseCase) Update(ctx context.Context, item *UpdateWhitelist) error { diff --git a/internal/conf/conf.pb.go b/internal/conf/conf.pb.go index 4d2869f..d840922 100644 --- a/internal/conf/conf.pb.go +++ b/internal/conf/conf.pb.go @@ -26,15 +26,15 @@ type Bootstrap struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - Server *Server `protobuf:"bytes,3,opt,name=server,proto3" json:"server,omitempty"` - Data *Data `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` - Tracer *Tracer `protobuf:"bytes,5,opt,name=tracer,proto3" json:"tracer,omitempty"` - Task map[string]*Task `protobuf:"bytes,6,rep,name=task,proto3" json:"task,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Client *Client `protobuf:"bytes,7,opt,name=client,proto3" json:"client,omitempty"` - Log *Log `protobuf:"bytes,8,opt,name=log,proto3" json:"log,omitempty"` - Hotspot *Hotspot `protobuf:"bytes,9,opt,name=hotspot,proto3" json:"hotspot,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + Server *Server `protobuf:"bytes,3,opt,name=server,proto3" json:"server,omitempty"` + Data *Data `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + Tracer *Tracer `protobuf:"bytes,5,opt,name=tracer,proto3" json:"tracer,omitempty"` + Task *Task `protobuf:"bytes,6,opt,name=task,proto3" json:"task,omitempty"` + Client *Client `protobuf:"bytes,7,opt,name=client,proto3" json:"client,omitempty"` + Log *Log `protobuf:"bytes,8,opt,name=log,proto3" json:"log,omitempty"` + Hotspot *Hotspot `protobuf:"bytes,9,opt,name=hotspot,proto3" json:"hotspot,omitempty"` } func (x *Bootstrap) Reset() { @@ -104,7 +104,7 @@ func (x *Bootstrap) GetTracer() *Tracer { return nil } -func (x *Bootstrap) GetTask() map[string]*Task { +func (x *Bootstrap) GetTask() *Task { if x != nil { return x.Task } @@ -503,7 +503,7 @@ func (x *Client) GetAuth() string { return "" } -type Task struct { +type CronTask struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -514,8 +514,8 @@ type Task struct { Retry int64 `protobuf:"varint,4,opt,name=retry,proto3" json:"retry,omitempty"` } -func (x *Task) Reset() { - *x = Task{} +func (x *CronTask) Reset() { + *x = CronTask{} if protoimpl.UnsafeEnabled { mi := &file_conf_conf_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -523,13 +523,13 @@ func (x *Task) Reset() { } } -func (x *Task) String() string { +func (x *CronTask) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Task) ProtoMessage() {} +func (*CronTask) ProtoMessage() {} -func (x *Task) ProtoReflect() protoreflect.Message { +func (x *CronTask) ProtoReflect() protoreflect.Message { mi := &file_conf_conf_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -541,39 +541,94 @@ func (x *Task) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Task.ProtoReflect.Descriptor instead. -func (*Task) Descriptor() ([]byte, []int) { +// Deprecated: Use CronTask.ProtoReflect.Descriptor instead. +func (*CronTask) Descriptor() ([]byte, []int) { return file_conf_conf_proto_rawDescGZIP(), []int{6} } -func (x *Task) GetName() string { +func (x *CronTask) GetName() string { if x != nil { return x.Name } return "" } -func (x *Task) GetExpr() string { +func (x *CronTask) GetExpr() string { if x != nil { return x.Expr } return "" } -func (x *Task) GetTimeout() int64 { +func (x *CronTask) GetTimeout() int64 { if x != nil { return x.Timeout } return 0 } -func (x *Task) GetRetry() int64 { +func (x *CronTask) GetRetry() int64 { if x != nil { return x.Retry } return 0 } +type Task struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cron map[string]*CronTask `protobuf:"bytes,1,rep,name=cron,proto3" json:"cron,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Group *Task_Group `protobuf:"bytes,2,opt,name=group,proto3" json:"group,omitempty"` +} + +func (x *Task) Reset() { + *x = Task{} + if protoimpl.UnsafeEnabled { + mi := &file_conf_conf_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Task) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Task) ProtoMessage() {} + +func (x *Task) ProtoReflect() protoreflect.Message { + mi := &file_conf_conf_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Task.ProtoReflect.Descriptor instead. +func (*Task) Descriptor() ([]byte, []int) { + return file_conf_conf_proto_rawDescGZIP(), []int{7} +} + +func (x *Task) GetCron() map[string]*CronTask { + if x != nil { + return x.Cron + } + return nil +} + +func (x *Task) GetGroup() *Task_Group { + if x != nil { + return x.Group + } + return nil +} + type Hotspot struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -586,7 +641,7 @@ type Hotspot struct { func (x *Hotspot) Reset() { *x = Hotspot{} if protoimpl.UnsafeEnabled { - mi := &file_conf_conf_proto_msgTypes[7] + mi := &file_conf_conf_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -599,7 +654,7 @@ func (x *Hotspot) String() string { func (*Hotspot) ProtoMessage() {} func (x *Hotspot) ProtoReflect() protoreflect.Message { - mi := &file_conf_conf_proto_msgTypes[7] + mi := &file_conf_conf_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -612,7 +667,7 @@ func (x *Hotspot) ProtoReflect() protoreflect.Message { // Deprecated: Use Hotspot.ProtoReflect.Descriptor instead. func (*Hotspot) Descriptor() ([]byte, []int) { - return file_conf_conf_proto_rawDescGZIP(), []int{7} + return file_conf_conf_proto_rawDescGZIP(), []int{8} } func (x *Hotspot) GetName() string { @@ -1070,13 +1125,84 @@ func (x *Tracer_Stdout) GetPrettyPrint() bool { return false } +type Task_Group struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LoginFailed string `protobuf:"bytes,1,opt,name=loginFailed,proto3" json:"loginFailed,omitempty"` + LoginLast string `protobuf:"bytes,2,opt,name=loginLast,proto3" json:"loginLast,omitempty"` + RefreshHotspot string `protobuf:"bytes,3,opt,name=refreshHotspot,proto3" json:"refreshHotspot,omitempty"` + RefreshHotspotManual string `protobuf:"bytes,4,opt,name=refreshHotspotManual,proto3" json:"refreshHotspotManual,omitempty"` +} + +func (x *Task_Group) Reset() { + *x = Task_Group{} + if protoimpl.UnsafeEnabled { + mi := &file_conf_conf_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Task_Group) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Task_Group) ProtoMessage() {} + +func (x *Task_Group) ProtoReflect() protoreflect.Message { + mi := &file_conf_conf_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Task_Group.ProtoReflect.Descriptor instead. +func (*Task_Group) Descriptor() ([]byte, []int) { + return file_conf_conf_proto_rawDescGZIP(), []int{7, 1} +} + +func (x *Task_Group) GetLoginFailed() string { + if x != nil { + return x.LoginFailed + } + return "" +} + +func (x *Task_Group) GetLoginLast() string { + if x != nil { + return x.LoginLast + } + return "" +} + +func (x *Task_Group) GetRefreshHotspot() string { + if x != nil { + return x.RefreshHotspot + } + return "" +} + +func (x *Task_Group) GetRefreshHotspotManual() string { + if x != nil { + return x.RefreshHotspotManual + } + return "" +} + var File_conf_conf_proto protoreflect.FileDescriptor var file_conf_conf_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb5, 0x03, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdb, 0x02, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, @@ -1088,131 +1214,147 @@ var file_conf_conf_proto_rawDesc = []byte{ 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x72, 0x52, - 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x61, 0x73, 0x6b, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x2e, 0x54, 0x61, 0x73, - 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x2a, 0x0a, 0x06, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x52, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x2d, 0x0a, 0x07, 0x68, - 0x6f, 0x74, 0x73, 0x70, 0x6f, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, - 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x48, 0x6f, 0x74, 0x73, 0x70, 0x6f, - 0x74, 0x52, 0x07, 0x68, 0x6f, 0x74, 0x73, 0x70, 0x6f, 0x74, 0x1a, 0x49, 0x0a, 0x09, 0x54, 0x61, - 0x73, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf1, 0x04, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x72, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, - 0x70, 0x72, 0x6f, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, - 0x2b, 0x0a, 0x04, 0x67, 0x72, 0x70, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x04, 0x67, 0x72, 0x70, 0x63, 0x12, 0x1a, 0x0a, 0x08, - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x03, 0x6a, 0x77, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x03, 0x6a, - 0x77, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, - 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x6e, 0x6f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x6e, 0x6f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x1a, 0x69, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, - 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, - 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x33, - 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x1a, 0x69, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x18, 0x0a, 0x07, 0x6e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x1a, 0x49, - 0x0a, 0x03, 0x4a, 0x77, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x22, 0xbd, 0x03, 0x0a, 0x04, 0x44, 0x61, - 0x74, 0x61, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, - 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x72, 0x65, 0x64, - 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, - 0x52, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x1a, 0xb4, 0x02, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, - 0x62, 0x61, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x64, 0x73, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, 0x1a, - 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x12, 0x40, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x54, 0x65, 0x6e, - 0x61, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, - 0x74, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, + 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x04, 0x74, 0x61, 0x73, 0x6b, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x04, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x2a, 0x0a, + 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x52, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6c, 0x6f, 0x67, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x2d, 0x0a, 0x07, + 0x68, 0x6f, 0x74, 0x73, 0x70, 0x6f, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x48, 0x6f, 0x74, 0x73, 0x70, + 0x6f, 0x74, 0x52, 0x07, 0x68, 0x6f, 0x74, 0x73, 0x70, 0x6f, 0x74, 0x22, 0xf1, 0x04, 0x0a, 0x06, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x72, 0x6f, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x70, 0x72, 0x6f, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, + 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, 0x2b, 0x0a, 0x04, 0x67, 0x72, 0x70, 0x63, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x04, 0x67, 0x72, + 0x70, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x28, + 0x0a, 0x03, 0x6a, 0x77, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x69, + 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, + 0x4a, 0x77, 0x74, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6d, + 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x64, + 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x6f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6e, 0x6f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x1a, 0x69, + 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x61, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x1a, 0x69, 0x0a, 0x04, 0x47, 0x52, 0x50, + 0x43, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, + 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, + 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x1a, 0x49, 0x0a, 0x03, 0x4a, 0x77, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x22, + 0xbd, 0x03, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, + 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x69, 0x6e, + 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, + 0x2c, 0x0a, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, + 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, 0x52, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x1a, 0xb4, 0x02, + 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x73, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x73, 0x6e, 0x12, 0x16, 0x0a, 0x06, + 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, + 0x69, 0x76, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x40, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, + 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, + 0x73, 0x65, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x54, 0x65, 0x6e, 0x61, + 0x6e, 0x74, 0x73, 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, 0x1a, 0x19, 0x0a, 0x05, 0x52, 0x65, 0x64, 0x69, 0x73, 0x12, 0x10, 0x0a, + 0x03, 0x64, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x73, 0x6e, 0x22, + 0x49, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, + 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x4a, 0x53, 0x4f, 0x4e, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x68, 0x6f, 0x77, 0x53, 0x51, 0x4c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x73, 0x68, 0x6f, 0x77, 0x53, 0x51, 0x4c, 0x22, 0x82, 0x02, 0x0a, 0x06, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x12, 0x2b, 0x0a, 0x04, 0x6f, 0x74, 0x6c, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x72, 0x2e, 0x4f, 0x74, 0x6c, 0x70, 0x52, 0x04, 0x6f, 0x74, 0x6c, 0x70, + 0x12, 0x31, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x54, 0x72, + 0x61, 0x63, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x52, 0x06, 0x73, 0x74, 0x64, + 0x6f, 0x75, 0x74, 0x1a, 0x3e, 0x0a, 0x04, 0x4f, 0x74, 0x6c, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x1a, 0x2a, 0x0a, 0x06, 0x53, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x20, 0x0a, + 0x0b, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x22, + 0x69, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x22, 0x62, 0x0a, 0x08, 0x43, 0x72, + 0x6f, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, + 0x70, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x18, + 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x74, 0x72, + 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x22, 0xd9, + 0x02, 0x0a, 0x04, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x2e, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x1a, 0x4d, 0x0a, 0x09, 0x43, 0x72, 0x6f, 0x6e, 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, 0x1a, 0x19, - 0x0a, 0x05, 0x52, 0x65, 0x64, 0x69, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x73, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x73, 0x6e, 0x22, 0x49, 0x0a, 0x03, 0x4c, 0x6f, 0x67, - 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x68, - 0x6f, 0x77, 0x53, 0x51, 0x4c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x68, 0x6f, - 0x77, 0x53, 0x51, 0x4c, 0x22, 0x82, 0x02, 0x0a, 0x06, 0x54, 0x72, 0x61, 0x63, 0x65, 0x72, 0x12, - 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x2b, 0x0a, - 0x04, 0x6f, 0x74, 0x6c, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x69, - 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x72, 0x2e, - 0x4f, 0x74, 0x6c, 0x70, 0x52, 0x04, 0x6f, 0x74, 0x6c, 0x70, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x74, - 0x64, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x69, 0x6e, - 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x72, 0x2e, 0x53, - 0x74, 0x64, 0x6f, 0x75, 0x74, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x1a, 0x3e, 0x0a, - 0x04, 0x4f, 0x74, 0x6c, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x1a, 0x2a, 0x0a, - 0x06, 0x53, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x72, - 0x65, 0x74, 0x74, 0x79, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x69, 0x0a, 0x06, 0x43, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x33, 0x0a, 0x07, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x61, 0x75, 0x74, 0x68, 0x22, 0x5e, 0x0a, 0x04, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x65, 0x78, 0x70, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x72, - 0x65, 0x74, 0x72, 0x79, 0x22, 0x50, 0x0a, 0x07, 0x48, 0x6f, 0x74, 0x73, 0x70, 0x6f, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, - 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x42, 0x19, 0x5a, 0x17, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, - 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x69, 0x6e, 0x63, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xa3, 0x01, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x20, + 0x0a, 0x0b, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x73, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x73, 0x74, 0x12, 0x26, + 0x0a, 0x0e, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x48, 0x6f, 0x74, 0x73, 0x70, 0x6f, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x48, + 0x6f, 0x74, 0x73, 0x70, 0x6f, 0x74, 0x12, 0x32, 0x0a, 0x14, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, + 0x68, 0x48, 0x6f, 0x74, 0x73, 0x70, 0x6f, 0x74, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x48, 0x6f, 0x74, + 0x73, 0x70, 0x6f, 0x74, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x22, 0x50, 0x0a, 0x07, 0x48, 0x6f, + 0x74, 0x73, 0x70, 0x6f, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x65, 0x78, 0x70, + 0x69, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x42, 0x19, 0x5a, 0x17, + 0x61, 0x75, 0x74, 0x68, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6f, + 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1227,7 +1369,7 @@ func file_conf_conf_proto_rawDescGZIP() []byte { return file_conf_conf_proto_rawDescData } -var file_conf_conf_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_conf_conf_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_conf_conf_proto_goTypes = []interface{}{ (*Bootstrap)(nil), // 0: cinch.conf.Bootstrap (*Server)(nil), // 1: cinch.conf.Server @@ -1235,9 +1377,9 @@ var file_conf_conf_proto_goTypes = []interface{}{ (*Log)(nil), // 3: cinch.conf.Log (*Tracer)(nil), // 4: cinch.conf.Tracer (*Client)(nil), // 5: cinch.conf.Client - (*Task)(nil), // 6: cinch.conf.Task - (*Hotspot)(nil), // 7: cinch.conf.Hotspot - nil, // 8: cinch.conf.Bootstrap.TaskEntry + (*CronTask)(nil), // 6: cinch.conf.CronTask + (*Task)(nil), // 7: cinch.conf.Task + (*Hotspot)(nil), // 8: cinch.conf.Hotspot (*Server_HTTP)(nil), // 9: cinch.conf.Server.HTTP (*Server_GRPC)(nil), // 10: cinch.conf.Server.GRPC (*Server_Jwt)(nil), // 11: cinch.conf.Server.Jwt @@ -1246,16 +1388,18 @@ var file_conf_conf_proto_goTypes = []interface{}{ nil, // 14: cinch.conf.Data.Database.TenantsEntry (*Tracer_Otlp)(nil), // 15: cinch.conf.Tracer.Otlp (*Tracer_Stdout)(nil), // 16: cinch.conf.Tracer.Stdout - (*durationpb.Duration)(nil), // 17: google.protobuf.Duration + nil, // 17: cinch.conf.Task.CronEntry + (*Task_Group)(nil), // 18: cinch.conf.Task.Group + (*durationpb.Duration)(nil), // 19: google.protobuf.Duration } var file_conf_conf_proto_depIdxs = []int32{ 1, // 0: cinch.conf.Bootstrap.server:type_name -> cinch.conf.Server 2, // 1: cinch.conf.Bootstrap.data:type_name -> cinch.conf.Data 4, // 2: cinch.conf.Bootstrap.tracer:type_name -> cinch.conf.Tracer - 8, // 3: cinch.conf.Bootstrap.task:type_name -> cinch.conf.Bootstrap.TaskEntry + 7, // 3: cinch.conf.Bootstrap.task:type_name -> cinch.conf.Task 5, // 4: cinch.conf.Bootstrap.client:type_name -> cinch.conf.Client 3, // 5: cinch.conf.Bootstrap.log:type_name -> cinch.conf.Log - 7, // 6: cinch.conf.Bootstrap.hotspot:type_name -> cinch.conf.Hotspot + 8, // 6: cinch.conf.Bootstrap.hotspot:type_name -> cinch.conf.Hotspot 9, // 7: cinch.conf.Server.http:type_name -> cinch.conf.Server.HTTP 10, // 8: cinch.conf.Server.grpc:type_name -> cinch.conf.Server.GRPC 11, // 9: cinch.conf.Server.jwt:type_name -> cinch.conf.Server.Jwt @@ -1263,17 +1407,19 @@ var file_conf_conf_proto_depIdxs = []int32{ 13, // 11: cinch.conf.Data.redis:type_name -> cinch.conf.Data.Redis 15, // 12: cinch.conf.Tracer.otlp:type_name -> cinch.conf.Tracer.Otlp 16, // 13: cinch.conf.Tracer.stdout:type_name -> cinch.conf.Tracer.Stdout - 17, // 14: cinch.conf.Client.timeout:type_name -> google.protobuf.Duration - 17, // 15: cinch.conf.Hotspot.expire:type_name -> google.protobuf.Duration - 6, // 16: cinch.conf.Bootstrap.TaskEntry.value:type_name -> cinch.conf.Task - 17, // 17: cinch.conf.Server.HTTP.timeout:type_name -> google.protobuf.Duration - 17, // 18: cinch.conf.Server.GRPC.timeout:type_name -> google.protobuf.Duration - 14, // 19: cinch.conf.Data.Database.tenants:type_name -> cinch.conf.Data.Database.TenantsEntry - 20, // [20:20] is the sub-list for method output_type - 20, // [20:20] is the sub-list for method input_type - 20, // [20:20] is the sub-list for extension type_name - 20, // [20:20] is the sub-list for extension extendee - 0, // [0:20] is the sub-list for field type_name + 19, // 14: cinch.conf.Client.timeout:type_name -> google.protobuf.Duration + 17, // 15: cinch.conf.Task.cron:type_name -> cinch.conf.Task.CronEntry + 18, // 16: cinch.conf.Task.group:type_name -> cinch.conf.Task.Group + 19, // 17: cinch.conf.Hotspot.expire:type_name -> google.protobuf.Duration + 19, // 18: cinch.conf.Server.HTTP.timeout:type_name -> google.protobuf.Duration + 19, // 19: cinch.conf.Server.GRPC.timeout:type_name -> google.protobuf.Duration + 14, // 20: cinch.conf.Data.Database.tenants:type_name -> cinch.conf.Data.Database.TenantsEntry + 6, // 21: cinch.conf.Task.CronEntry.value:type_name -> cinch.conf.CronTask + 22, // [22:22] is the sub-list for method output_type + 22, // [22:22] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name } func init() { file_conf_conf_proto_init() } @@ -1355,7 +1501,7 @@ func file_conf_conf_proto_init() { } } file_conf_conf_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Task); i { + switch v := v.(*CronTask); i { case 0: return &v.state case 1: @@ -1367,6 +1513,18 @@ func file_conf_conf_proto_init() { } } file_conf_conf_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Task); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_conf_conf_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Hotspot); i { case 0: return &v.state @@ -1462,6 +1620,18 @@ func file_conf_conf_proto_init() { return nil } } + file_conf_conf_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Task_Group); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1469,7 +1639,7 @@ func file_conf_conf_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_conf_conf_proto_rawDesc, NumEnums: 0, - NumMessages: 17, + NumMessages: 19, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/conf/conf.proto b/internal/conf/conf.proto index da695b8..9947f6b 100644 --- a/internal/conf/conf.proto +++ b/internal/conf/conf.proto @@ -11,7 +11,7 @@ message Bootstrap { Server server = 3; Data data = 4; Tracer tracer = 5; - map task = 6; + Task task = 6; Client client = 7; Log log = 8; Hotspot hotspot = 9; @@ -89,13 +89,24 @@ message Client { string auth = 3; } -message Task { +message CronTask { string name = 1; string expr = 2; int64 timeout = 3; int64 retry = 4; } +message Task { + map cron = 1; + message Group { + string loginFailed = 1; + string loginLast = 2; + string refreshHotspot = 3; + string refreshHotspotManual = 4; + } + Group group = 2; +} + message Hotspot { string name = 1; google.protobuf.Duration expire = 2; diff --git a/internal/data/hotspot.go b/internal/data/hotspot.go index 9e8e0d8..17d78a4 100644 --- a/internal/data/hotspot.go +++ b/internal/data/hotspot.go @@ -64,8 +64,16 @@ func (ro hotspotRepo) GetUserByCode(ctx context.Context, code string) *biz.User code, }, ".") res, _ := rds.HGetAll(ctx, key).Result() + m := make(map[string]interface{}, len(res)) + copierx.Copy(&m, res) + if v, ok := m[utils.CamelCase(p.Locked.ColumnName().String())]; ok { + m[utils.CamelCase(p.Locked.ColumnName().String())], _ = strconv.ParseBool(v.(string)) + } + if v, ok := m[utils.CamelCase(p.Wrong.ColumnName().String())]; ok { + m[utils.CamelCase(p.Wrong.ColumnName().String())], _ = strconv.ParseUint(v.(string), 10, 64) + } var item biz.User - utils.Struct2StructByJson(&item, res) + utils.Struct2StructByJson(&item, m) if item.RoleId > constant.UI0 { item.Role = *ro.GetRoleByID(ctx, item.RoleId) } @@ -176,6 +184,16 @@ func (ro hotspotRepo) GetActionByCode(ctx context.Context, code string) *biz.Act return &item } +func (ro hotspotRepo) FindActionByCode(ctx context.Context, codes ...string) (list []biz.Action) { + tr := otel.Tracer("data") + ctx, span := tr.Start(ctx, "FindActionByCode") + defer span.End() + for _, code := range codes { + list = append(list, *ro.GetActionByCode(ctx, code)) + } + return +} + func (ro hotspotRepo) FindUserGroupByUserCode(ctx context.Context, code string) (list []biz.UserGroup) { tr := otel.Tracer("data") ctx, span := tr.Start(ctx, "FindUserGroupByUserCode") @@ -325,6 +343,7 @@ func (ro hotspotRepo) refreshUserUserGroupRelation(ctx context.Context, pipe red p.UserID.ColumnName().String(), strconv.FormatUint(userID, 10), }, ".") + pipe.Del(ctx, userIDKey) for _, id := range groupIDs { pipe.HSet( ctx, userIDKey, @@ -480,6 +499,7 @@ func (ro hotspotRepo) refreshWhitelist(ctx context.Context, pipe redis.Pipeliner p.Category.ColumnName().String(), strconv.FormatUint(uint64(category), 10), }, ".") + pipe.Del(ctx, categoryKey) for _, resource := range resources { pipe.HSet( ctx, categoryKey, diff --git a/internal/data/permission.go b/internal/data/permission.go index e5d660b..43e662a 100644 --- a/internal/data/permission.go +++ b/internal/data/permission.go @@ -5,25 +5,21 @@ import ( "strings" "auth/internal/biz" - "github.com/go-cinch/common/utils" + "github.com/samber/lo" ) type permissionRepo struct { - data *Data - action biz.ActionRepo - user biz.UserRepo - userGroup biz.UserGroupRepo - hotspot biz.HotspotRepo + data *Data + action biz.ActionRepo + hotspot biz.HotspotRepo } // NewPermissionRepo . -func NewPermissionRepo(data *Data, action biz.ActionRepo, user biz.UserRepo, userGroup biz.UserGroupRepo, hotspot biz.HotspotRepo) biz.PermissionRepo { +func NewPermissionRepo(data *Data, action biz.ActionRepo, hotspot biz.HotspotRepo) biz.PermissionRepo { return &permissionRepo{ - data: data, - action: action, - user: user, - userGroup: userGroup, - hotspot: hotspot, + data: data, + action: action, + hotspot: hotspot, } } @@ -56,15 +52,14 @@ func (ro permissionRepo) Check(ctx context.Context, item biz.CheckPermission) (p return } -func (ro permissionRepo) GetByUserCode(ctx context.Context, code string) (rp *biz.Permission, err error) { +func (ro permissionRepo) GetByUserCode(ctx context.Context, code string) (rp *biz.Permission) { rp = &biz.Permission{} rp.Resources = make([]string, 0) - user, err := ro.user.GetByCode(ctx, code) - if err != nil { - return - } + user := ro.hotspot.GetUserByCode(ctx, code) // 1. user action actions := make([]string, 0) + defaultAction := ro.hotspot.GetActionByWord(ctx, "default") + actions = append(actions, defaultAction.Code) if user.Action != "" { arr := strings.Split(user.Action, ",") actions = append(actions, arr...) @@ -75,16 +70,16 @@ func (ro permissionRepo) GetByUserCode(ctx context.Context, code string) (rp *bi actions = append(actions, arr...) } // 3. user group action - groups := ro.userGroup.FindGroupByUserCode(ctx, user.Code) + groups := ro.hotspot.FindUserGroupByUserCode(ctx, user.Code) for _, group := range groups { if group.Action != "" { arr := strings.Split(group.Action, ",") actions = append(actions, arr...) } } - actions = utils.RemoveRepeat(actions) + actions = lo.Uniq(actions) if len(actions) > 0 { - list := ro.action.FindByCode(ctx, strings.Join(actions, ",")) + list := ro.hotspot.FindActionByCode(ctx, actions...) for _, item := range list { if item.Resource != "" { rp.Resources = append(rp.Resources, strings.Split(item.Resource, "\n")...) @@ -97,8 +92,8 @@ func (ro permissionRepo) GetByUserCode(ctx context.Context, code string) (rp *bi } } } - rp.Resources = utils.RemoveRepeat(rp.Resources) - rp.Menus = utils.RemoveRepeat(rp.Menus) - rp.Btns = utils.RemoveRepeat(rp.Btns) + rp.Resources = lo.Uniq(rp.Resources) + rp.Menus = lo.Uniq(rp.Menus) + rp.Btns = lo.Uniq(rp.Btns) return } diff --git a/internal/data/user.go b/internal/data/user.go index 6aab34d..05c82c4 100644 --- a/internal/data/user.go +++ b/internal/data/user.go @@ -19,17 +19,15 @@ import ( ) type userRepo struct { - data *Data - action biz.ActionRepo - hotspot biz.HotspotRepo + data *Data + action biz.ActionRepo } // NewUserRepo . -func NewUserRepo(data *Data, action biz.ActionRepo, hotspot biz.HotspotRepo) biz.UserRepo { +func NewUserRepo(data *Data, action biz.ActionRepo) biz.UserRepo { return &userRepo{ - data: data, - action: action, - hotspot: hotspot, + data: data, + action: action, } } @@ -303,8 +301,3 @@ func (ro userRepo) IdExists(ctx context.Context, id uint64) (err error) { } return } - -func (ro userRepo) GetByCode(ctx context.Context, code string) (item *biz.User, err error) { - item = ro.hotspot.GetUserByCode(ctx, code) - return -} diff --git a/internal/data/user_group.go b/internal/data/user_group.go index ffb236e..6a46d92 100644 --- a/internal/data/user_group.go +++ b/internal/data/user_group.go @@ -65,30 +65,6 @@ func (ro userGroupRepo) Create(ctx context.Context, item *biz.UserGroup) (err er return } -func (ro userGroupRepo) FindGroupByUserCode(ctx context.Context, code string) (list []biz.UserGroup) { - list = make([]biz.UserGroup, 0) - user, err := ro.user.GetByCode(ctx, code) - if err != nil { - return - } - p := query.Use(ro.data.DB(ctx)).UserUserGroupRelation - db := p.WithContext(ctx) - groupIds := make([]uint64, 0) - db. - Where(p.UserID.Eq(user.Id)). - Pluck(p.UserGroupID, &groupIds) - if len(groupIds) == 0 { - return - } - pUserGroup := query.Use(ro.data.DB(ctx)).UserGroup - dbUserGroup := pUserGroup.WithContext(ctx) - groups, _ := dbUserGroup. - Where(pUserGroup.ID.In(groupIds...)). - Find() - copierx.Copy(&list, groups) - return -} - func (ro userGroupRepo) Find(ctx context.Context, condition *biz.FindUserGroup) (rp []biz.UserGroup) { p := query.Use(ro.data.DB(ctx)).UserGroup db := p.WithContext(ctx) diff --git a/internal/db/migrations/2023060217-default-data.sql b/internal/db/migrations/2023060217-default-data.sql index 13bf2d1..8b98252 100644 --- a/internal/db/migrations/2023060217-default-data.sql +++ b/internal/db/migrations/2023060217-default-data.sql @@ -2,7 +2,7 @@ -- SQL in section 'Up' is executed when this migration is applied INSERT INTO `action` (`id`, `name`, `code`, `word`, `resource`, `menu`, `btn`) VALUES (8926844486248562689,'全部权限','SN2837AY','*','*','*','*'), -(8926844486248579238,'默认权限','KHXK5JVL','default','POST|/auth/pwd|/auth.v1.Auth/Pwd\nGET|/auth/idempotent|/auth.v1.Auth/Idempotent\n/auth.v1.Auth/CheckIdempotent','',''), +(8926844486248579238,'默认权限','KHXK5JVL','default','POST|/auth/pwd|/auth.v1.Auth/Pwd\nGET|/auth/idempotent|/auth.v1.Auth/Idempotent\n/auth.v1.Auth/CheckIdempotent','/dashboard/base\n/user/index',''), (8929298412088590337,'首页','2QKHTYEE','dashboard','','/dashboard/base',''), (8929306305215070209,'用户查询','GRNA3NPV','user.read','GET|/auth/user|/auth.v1.Auth/FindUser','/system/user','system.user.read'), (8929306391416406017,'用户新增','2LV9MDWB','user.create','POST|/auth/register|/auth.v1.Auth/Register','/system/user','system.user.create'), @@ -47,8 +47,8 @@ INSERT INTO `user_user_group_relation` (`user_id`, `user_group_id`) VALUES (8929717570412478465,8929717758803836929); INSERT INTO `whitelist` (`id`, `category`, `resource`) VALUES -(8946576552976449537, 0, 'POST|/auth/login|/auth.v1.Auth/Login\nGET|/auth/status|/auth.v1.Auth/Status\nPOST|/auth/logout|/auth.v1.Auth/Logout\nGET|/auth/captcha|/auth.v1.Auth/Captcha\nPOST|/auth/register|/auth.v1.Auth/Register\nGET|/auth/info|/auth.v1.Auth/Info\n/grpc.health.v1.Health/Check\n/grpc.health.v1.Health/Watch'), -(8946576560039657473, 1, 'POST|/auth/login|/auth.v1.Auth/Login\nGET|/auth/status|/auth.v1.Auth/Status\nPOST|/auth/logout|/auth.v1.Auth/Logout\nGET|/auth/captcha|/auth.v1.Auth/Captcha\nPOST|/auth/register|/auth.v1.Auth/Register\n/auth.v1.Auth/GetUserByCode\n/auth.v1.Auth/CheckIdempotent\n/grpc.health.v1.Health/Check\n/grpc.health.v1.Health/Watch'), +(8946576552976449537, 0, 'POST|/auth/logout|/auth.v1.Auth/Logout\nGET|/auth/info|/auth.v1.Auth/Info\n/grpc.health.v1.Health/Check\n/grpc.health.v1.Health/Watch'), +(8946576560039657473, 1, 'POST|/auth/login|/auth.v1.Auth/Login\n/auth.v1.Auth/GetUserByCode\n/auth.v1.Auth/CheckIdempotent\n/grpc.health.v1.Health/Check\n/grpc.health.v1.Health/Watch'), (8946576567690067969, 2, 'POST|/auth/action|/auth.v1.Auth/CreateAction\nPOST|/auth/role|/auth.v1.Auth/CreateRole\nPOST|/auth/user/group|/auth.v1.Auth/CreateUserGroup'); -- +migrate Down diff --git a/internal/pkg/task/task.go b/internal/pkg/task/task.go index 74fb6fe..f138ecf 100644 --- a/internal/pkg/task/task.go +++ b/internal/pkg/task/task.go @@ -2,6 +2,8 @@ package task import ( "context" + "strings" + "time" "auth/internal/biz" "auth/internal/conf" @@ -21,9 +23,11 @@ func New(c *conf.Bootstrap, user *biz.UserUseCase, hotspot *biz.HotspotUseCase) w = worker.New( worker.WithRedisURI(c.Data.Redis.Dsn), worker.WithGroup(c.Name), - worker.WithHandler(func(ctx context.Context, p worker.Payload) error { + worker.WithHandlerNeedWorker(func(ctx context.Context, w worker.Worker, p worker.Payload) error { return process(task{ ctx: ctx, + c: c, + w: w, payload: p, user: user, hotspot: hotspot, @@ -36,7 +40,7 @@ func New(c *conf.Bootstrap, user *biz.UserUseCase, hotspot *biz.HotspotUseCase) return } - for id, item := range c.Task { + for id, item := range c.Task.Cron { err = w.Cron( worker.WithRunUUID(id), worker.WithRunGroup(item.Name), @@ -52,11 +56,20 @@ func New(c *conf.Bootstrap, user *biz.UserUseCase, hotspot *biz.HotspotUseCase) } log.Info("initialize worker success") + // when app restart, clear hotspot + _ = w.Once( + worker.WithRunUUID(strings.Join([]string{c.Task.Group.RefreshHotspotManual}, ".")), + worker.WithRunGroup(c.Task.Group.RefreshHotspotManual), + worker.WithRunIn(10*time.Second), + worker.WithRunReplace(true), + ) return } type task struct { ctx context.Context + c *conf.Bootstrap + w worker.Worker payload worker.Payload user *biz.UserUseCase hotspot *biz.HotspotUseCase @@ -67,15 +80,17 @@ func process(t task) (err error) { ctx, span := tr.Start(t.ctx, "Task") defer span.End() switch t.payload.Group { - case "login.failed": + case t.c.Task.Group.LoginFailed: var req biz.LoginTime utils.Json2Struct(&req, t.payload.Payload) err = t.user.WrongPwd(ctx, req) - case "login.last": + case t.c.Task.Group.LoginLast: var req biz.LoginTime utils.Json2Struct(&req, t.payload.Payload) err = t.user.LastLogin(ctx, req.Username) - case "refresh.hotspot": + case t.c.Task.Group.RefreshHotspot: + err = t.hotspot.Refresh(ctx) + case t.c.Task.Group.RefreshHotspotManual: err = t.hotspot.Refresh(ctx) } return diff --git a/internal/server/middleware/jwt.go b/internal/server/middleware/jwt.go index 7ca73e4..a0524ae 100644 --- a/internal/server/middleware/jwt.go +++ b/internal/server/middleware/jwt.go @@ -2,6 +2,7 @@ package middleware import ( "context" + "errors" "strings" "time" @@ -65,7 +66,8 @@ func parseToken(ctx context.Context, key, jwtToken string) (info *jwtV4.Token, e return }) if err != nil { - ve, ok := err.(*jwtV4.ValidationError) + var ve *jwtV4.ValidationError + ok := errors.As(err, &ve) if !ok { return } diff --git a/internal/server/middleware/whitelist.go b/internal/server/middleware/whitelist.go index ca26c8b..8b82c71 100644 --- a/internal/server/middleware/whitelist.go +++ b/internal/server/middleware/whitelist.go @@ -3,6 +3,7 @@ package middleware import ( "context" "net/http" + "strings" "auth/api/auth" "auth/internal/biz" @@ -39,6 +40,11 @@ func Whitelist(whitelist *biz.WhitelistUseCase) middleware.Middleware { if v.Uri == nil && uri != "" { v.Uri = &uri } + // public api no need check + if v.Uri != nil && strings.Contains(*v.Uri, "/pub/") { + rp = &emptypb.Empty{} + return + } // check whitelist pass, err = hasPermissionWhitelist(ctx, whitelist, v) if err != nil { @@ -76,7 +82,7 @@ func hasPermissionWhitelist(ctx context.Context, whitelist *biz.WhitelistUseCase return } // check if it is on the whitelist - ok, err = whitelist.Has(ctx, &biz.HasWhitelist{ + ok = whitelist.Has(ctx, &biz.HasWhitelist{ Category: biz.WhitelistPermissionCategory, Permission: r, }) @@ -85,7 +91,7 @@ func hasPermissionWhitelist(ctx context.Context, whitelist *biz.WhitelistUseCase func jwtWhitelist(whitelist *biz.WhitelistUseCase) selector.MatchFunc { return func(ctx context.Context, operation string) bool { - pass, _ := whitelist.Has(ctx, &biz.HasWhitelist{ + pass := whitelist.Has(ctx, &biz.HasWhitelist{ Category: biz.WhitelistJwtCategory, Permission: biz.CheckPermission{ Resource: operation, @@ -98,7 +104,7 @@ func jwtWhitelist(whitelist *biz.WhitelistUseCase) selector.MatchFunc { func idempotentBlacklist(whitelist *biz.WhitelistUseCase) selector.MatchFunc { return func(ctx context.Context, operation string) bool { - pass, _ := whitelist.Has(ctx, &biz.HasWhitelist{ + pass := whitelist.Has(ctx, &biz.HasWhitelist{ Category: biz.WhitelistIdempotentCategory, Permission: biz.CheckPermission{ Resource: operation, diff --git a/internal/service/action.go b/internal/service/action.go index 96f2b7d..7a446a7 100644 --- a/internal/service/action.go +++ b/internal/service/action.go @@ -21,7 +21,7 @@ func (s *AuthService) CreateAction(ctx context.Context, req *auth.CreateActionRe r := &biz.Action{} copierx.Copy(&r, req) err = s.action.Create(ctx, r) - s.flushUserAndPermissionCache(ctx) + s.flushCache(ctx) return } @@ -52,7 +52,7 @@ func (s *AuthService) UpdateAction(ctx context.Context, req *auth.UpdateActionRe r := &biz.UpdateAction{} copierx.Copy(&r, req) err = s.action.Update(ctx, r) - s.flushUserAndPermissionCache(ctx) + s.flushCache(ctx) return } @@ -62,13 +62,6 @@ func (s *AuthService) DeleteAction(ctx context.Context, req *params.IdsRequest) defer span.End() rp = &emptypb.Empty{} err = s.action.Delete(ctx, utils.Str2Uint64Arr(req.Ids)...) - s.flushUserAndPermissionCache(ctx) + s.flushCache(ctx) return } - -func (s *AuthService) flushUserAndPermissionCache(ctx context.Context) { - // clear user info cache - s.user.FlushCache(ctx) - // clear permission cache - s.permission.FlushCache(ctx) -} diff --git a/internal/service/auth.go b/internal/service/auth.go index ee54bf8..71c66af 100644 --- a/internal/service/auth.go +++ b/internal/service/auth.go @@ -29,6 +29,7 @@ func (s *AuthService) Register(ctx context.Context, req *auth.RegisterRequest) ( return } err = s.user.Create(ctx, r) + s.flushCache(ctx) return } @@ -40,6 +41,7 @@ func (s *AuthService) Pwd(ctx context.Context, req *auth.PwdRequest) (rp *emptyp r := &biz.User{} copierx.Copy(&r, req) err = s.user.Pwd(ctx, r) + s.flushCache(ctx) return } @@ -57,10 +59,10 @@ func (s *AuthService) Login(ctx context.Context, req *auth.LoginRequest) (rp *au ctx, _ = context.WithTimeout(ctx, time.Second) if err != nil { if loginFailed { - s.task.Once( + _ = s.task.Once( worker.WithRunCtx(ctx), - worker.WithRunUUID(strings.Join([]string{"login.failed", req.Username}, ".")), - worker.WithRunGroup("login.failed"), + worker.WithRunUUID(strings.Join([]string{s.c.Task.Group.LoginFailed, req.Username}, ".")), + worker.WithRunGroup(s.c.Task.Group.LoginFailed), worker.WithRunNow(true), worker.WithRunTimeout(10), worker.WithRunReplace(true), @@ -72,6 +74,8 @@ func (s *AuthService) Login(ctx context.Context, req *auth.LoginRequest) (rp *au Wrong: res.Wrong, })), ) + // need refresh hotspot + s.flushCache(ctx) return } if notFound { @@ -82,10 +86,10 @@ func (s *AuthService) Login(ctx context.Context, req *auth.LoginRequest) (rp *au return } copierx.Copy(&rp, res) - s.task.Once( + _ = s.task.Once( worker.WithRunCtx(ctx), - worker.WithRunUUID(strings.Join([]string{"login.last", req.Username}, ".")), - worker.WithRunGroup("login.last"), + worker.WithRunUUID(strings.Join([]string{s.c.Task.Group.LoginLast, req.Username}, ".")), + worker.WithRunGroup(s.c.Task.Group.LoginLast), worker.WithRunIn(time.Duration(10)*time.Second), worker.WithRunTimeout(10), worker.WithRunReplace(true), @@ -93,6 +97,15 @@ func (s *AuthService) Login(ctx context.Context, req *auth.LoginRequest) (rp *au Username: req.Username, })), ) + s.flushCache(ctx) + return +} + +func (*AuthService) Logout(ctx context.Context, _ *emptypb.Empty) (rp *emptypb.Empty, err error) { + tr := otel.Tracer("api") + ctx, span := tr.Start(ctx, "Logout") + defer span.End() + rp = &emptypb.Empty{} return } @@ -143,10 +156,7 @@ func (s *AuthService) Permission(ctx context.Context, req *auth.PermissionReques err = biz.ErrNoPermission(ctx) return } - info, err := s.user.Info(ctx, user.Code) - if err != nil { - return - } + info := s.user.Info(ctx, user.Code) jwt.AppendToReplyHeader(ctx, jwt.User{ Code: info.Code, Platform: info.Platform, @@ -161,14 +171,8 @@ func (s *AuthService) Info(ctx context.Context, _ *emptypb.Empty) (rp *auth.Info rp = &auth.InfoReply{} rp.Permission = &auth.Permission{} user := jwt.FromServerContext(ctx) - res, err := s.user.Info(ctx, user.Code) - if err != nil { - return - } - permission, err := s.permission.GetByUserCode(ctx, user.Code) - if err != nil { - return - } + res := s.user.Info(ctx, user.Code) + permission := s.permission.GetByUserCode(ctx, user.Code) copierx.Copy(&rp.Permission, permission) copierx.Copy(&rp, res) return diff --git a/internal/service/hotspot.go b/internal/service/hotspot.go new file mode 100644 index 0000000..ad6a39d --- /dev/null +++ b/internal/service/hotspot.go @@ -0,0 +1,22 @@ +package service + +import ( + "context" + "strings" + + "github.com/go-cinch/common/worker" +) + +func (s *AuthService) flushCache(ctx context.Context) { + // clear user info cache + s.user.FlushCache(ctx) + + // delay clear hotspot cache + _ = s.task.Once( + worker.WithRunCtx(ctx), + worker.WithRunUUID(strings.Join([]string{s.c.Task.Group.RefreshHotspotManual}, ".")), + worker.WithRunGroup(s.c.Task.Group.RefreshHotspotManual), + worker.WithRunNow(true), + worker.WithRunReplace(true), + ) +} diff --git a/internal/service/role.go b/internal/service/role.go index 83bd20f..79ef8cd 100644 --- a/internal/service/role.go +++ b/internal/service/role.go @@ -21,6 +21,7 @@ func (s *AuthService) CreateRole(ctx context.Context, req *auth.CreateRoleReques r := &biz.Role{} copierx.Copy(&r, req) err = s.role.Create(ctx, r) + s.flushCache(ctx) return } @@ -54,7 +55,7 @@ func (s *AuthService) UpdateRole(ctx context.Context, req *auth.UpdateRoleReques if err != nil { return } - s.permission.FlushCache(ctx) + s.flushCache(ctx) return } @@ -67,6 +68,6 @@ func (s *AuthService) DeleteRole(ctx context.Context, req *params.IdsRequest) (r if err != nil { return } - s.permission.FlushCache(ctx) + s.flushCache(ctx) return } diff --git a/internal/service/service.go b/internal/service/service.go index 14f95fb..084fa70 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -3,6 +3,7 @@ package service import ( "auth/api/auth" "auth/internal/biz" + "auth/internal/conf" "auth/internal/pkg/idempotent" "github.com/go-cinch/common/worker" "github.com/google/wire" @@ -15,7 +16,8 @@ var ProviderSet = wire.NewSet(NewAuthService) type AuthService struct { auth.UnimplementedAuthServer - task *worker.Worker + c *conf.Bootstrap + task *worker.Worker idempotent *idempotent.Idempotent user *biz.UserUseCase action *biz.ActionUseCase @@ -27,7 +29,8 @@ type AuthService struct { // NewAuthService new an auth service. func NewAuthService( - task *worker.Worker, + c *conf.Bootstrap, + task *worker.Worker, idempotent *idempotent.Idempotent, user *biz.UserUseCase, action *biz.ActionUseCase, @@ -37,6 +40,7 @@ func NewAuthService( whitelist *biz.WhitelistUseCase, ) *AuthService { return &AuthService{ + c: c, task: task, idempotent: idempotent, user: user, diff --git a/internal/service/user.go b/internal/service/user.go index 8a2cc25..4201e5e 100644 --- a/internal/service/user.go +++ b/internal/service/user.go @@ -19,10 +19,7 @@ func (s *AuthService) GetUserByCode(ctx context.Context, req *auth.GetUserByCode ctx, span := tr.Start(ctx, "GetUserByCode") defer span.End() rp = &auth.GetUserByCodeReply{} - user, err := s.user.GetUserByCode(ctx, req.Code) - if err != nil { - return - } + user := s.user.GetUserByCode(ctx, req.Code) rp.User = &auth.User{} copierx.Copy(&rp.User, user) return @@ -59,9 +56,7 @@ func (s *AuthService) UpdateUser(ctx context.Context, req *auth.UpdateUserReques r.LockExpire = &lockExpire } err = s.user.Update(ctx, r) - if err == nil { - s.permission.FlushCache(ctx) - } + s.flushCache(ctx) return } @@ -71,8 +66,6 @@ func (s *AuthService) DeleteUser(ctx context.Context, req *params.IdsRequest) (r defer span.End() rp = &emptypb.Empty{} err = s.user.Delete(ctx, utils.Str2Uint64Arr(req.Ids)...) - if err == nil { - s.permission.FlushCache(ctx) - } + s.flushCache(ctx) return } diff --git a/internal/service/user_group.go b/internal/service/user_group.go index 1655f2f..8970384 100644 --- a/internal/service/user_group.go +++ b/internal/service/user_group.go @@ -21,6 +21,7 @@ func (s *AuthService) CreateUserGroup(ctx context.Context, req *auth.CreateUserG r := &biz.UserGroup{} copierx.Copy(&r, req) err = s.userGroup.Create(ctx, r) + s.flushCache(ctx) return } @@ -51,9 +52,7 @@ func (s *AuthService) UpdateUserGroup(ctx context.Context, req *auth.UpdateUserG r := &biz.UpdateUserGroup{} copierx.Copy(&r, req) err = s.userGroup.Update(ctx, r) - if err == nil { - s.permission.FlushCache(ctx) - } + s.flushCache(ctx) return } @@ -63,8 +62,6 @@ func (s *AuthService) DeleteUserGroup(ctx context.Context, req *params.IdsReques defer span.End() rp = &emptypb.Empty{} err = s.userGroup.Delete(ctx, utils.Str2Uint64Arr(req.Ids)...) - if err == nil { - s.permission.FlushCache(ctx) - } + s.flushCache(ctx) return } diff --git a/internal/service/whitelist.go b/internal/service/whitelist.go index c833448..b1e21a9 100644 --- a/internal/service/whitelist.go +++ b/internal/service/whitelist.go @@ -21,7 +21,7 @@ func (s *AuthService) CreateWhitelist(ctx context.Context, req *auth.CreateWhite r := &biz.Whitelist{} copierx.Copy(&r, req) err = s.whitelist.Create(ctx, r) - s.flushUserAndPermissionCache(ctx) + s.flushCache(ctx) return } @@ -32,10 +32,7 @@ func (s *AuthService) HasWhitelist(ctx context.Context, req *auth.HasWhitelistRe rp = &auth.HasWhitelistReply{} r := &biz.HasWhitelist{} copierx.Copy(&r, req) - res, err := s.whitelist.Has(ctx, r) - if err != nil { - return - } + res := s.whitelist.Has(ctx, r) rp.Ok = res return } @@ -64,7 +61,7 @@ func (s *AuthService) UpdateWhitelist(ctx context.Context, req *auth.UpdateWhite r := &biz.UpdateWhitelist{} copierx.Copy(&r, req) err = s.whitelist.Update(ctx, r) - s.flushUserAndPermissionCache(ctx) + s.flushCache(ctx) return } @@ -74,6 +71,6 @@ func (s *AuthService) DeleteWhitelist(ctx context.Context, req *params.IdsReques defer span.End() rp = &emptypb.Empty{} err = s.whitelist.Delete(ctx, utils.Str2Uint64Arr(req.Ids)...) - s.flushUserAndPermissionCache(ctx) + s.flushCache(ctx) return }