增加白名单userid

This commit is contained in:
zhx 2026-06-30 10:47:21 +08:00
parent e71194ad25
commit 9717929231
19 changed files with 1047 additions and 275 deletions

View File

@ -1448,6 +1448,122 @@ func (x *CheckLoginRiskIPWhitelistResponse) GetWhitelisted() bool {
return false
}
// RefreshLoginRiskWhitelistCacheRequest 要求 user-service 从 MySQL 重建登录风控白名单缓存。
type RefreshLoginRiskWhitelistCacheRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
}
func (x *RefreshLoginRiskWhitelistCacheRequest) Reset() {
*x = RefreshLoginRiskWhitelistCacheRequest{}
mi := &file_proto_user_v1_auth_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RefreshLoginRiskWhitelistCacheRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RefreshLoginRiskWhitelistCacheRequest) ProtoMessage() {}
func (x *RefreshLoginRiskWhitelistCacheRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[18]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RefreshLoginRiskWhitelistCacheRequest.ProtoReflect.Descriptor instead.
func (*RefreshLoginRiskWhitelistCacheRequest) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{18}
}
func (x *RefreshLoginRiskWhitelistCacheRequest) GetMeta() *RequestMeta {
if x != nil {
return x.Meta
}
return nil
}
// RefreshLoginRiskWhitelistCacheResponse 返回本次刷新后的白名单规模,便于后台保存后确认缓存已更新。
type RefreshLoginRiskWhitelistCacheResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Refreshed bool `protobuf:"varint,1,opt,name=refreshed,proto3" json:"refreshed,omitempty"`
IpWhitelistCount int32 `protobuf:"varint,2,opt,name=ip_whitelist_count,json=ipWhitelistCount,proto3" json:"ip_whitelist_count,omitempty"`
UserWhitelistCount int32 `protobuf:"varint,3,opt,name=user_whitelist_count,json=userWhitelistCount,proto3" json:"user_whitelist_count,omitempty"`
UserCacheExpiresAtMs int64 `protobuf:"varint,4,opt,name=user_cache_expires_at_ms,json=userCacheExpiresAtMs,proto3" json:"user_cache_expires_at_ms,omitempty"`
}
func (x *RefreshLoginRiskWhitelistCacheResponse) Reset() {
*x = RefreshLoginRiskWhitelistCacheResponse{}
mi := &file_proto_user_v1_auth_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RefreshLoginRiskWhitelistCacheResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RefreshLoginRiskWhitelistCacheResponse) ProtoMessage() {}
func (x *RefreshLoginRiskWhitelistCacheResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[19]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RefreshLoginRiskWhitelistCacheResponse.ProtoReflect.Descriptor instead.
func (*RefreshLoginRiskWhitelistCacheResponse) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{19}
}
func (x *RefreshLoginRiskWhitelistCacheResponse) GetRefreshed() bool {
if x != nil {
return x.Refreshed
}
return false
}
func (x *RefreshLoginRiskWhitelistCacheResponse) GetIpWhitelistCount() int32 {
if x != nil {
return x.IpWhitelistCount
}
return 0
}
func (x *RefreshLoginRiskWhitelistCacheResponse) GetUserWhitelistCount() int32 {
if x != nil {
return x.UserWhitelistCount
}
return 0
}
func (x *RefreshLoginRiskWhitelistCacheResponse) GetUserCacheExpiresAtMs() int64 {
if x != nil {
return x.UserCacheExpiresAtMs
}
return 0
}
// RegisterRiskConfig 是注册链路读取的风控配置。
type RegisterRiskConfig struct {
state protoimpl.MessageState
@ -1462,7 +1578,7 @@ type RegisterRiskConfig struct {
func (x *RegisterRiskConfig) Reset() {
*x = RegisterRiskConfig{}
mi := &file_proto_user_v1_auth_proto_msgTypes[18]
mi := &file_proto_user_v1_auth_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1474,7 +1590,7 @@ func (x *RegisterRiskConfig) String() string {
func (*RegisterRiskConfig) ProtoMessage() {}
func (x *RegisterRiskConfig) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[18]
mi := &file_proto_user_v1_auth_proto_msgTypes[20]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1487,7 +1603,7 @@ func (x *RegisterRiskConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use RegisterRiskConfig.ProtoReflect.Descriptor instead.
func (*RegisterRiskConfig) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{18}
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{20}
}
func (x *RegisterRiskConfig) GetAppCode() string {
@ -1529,7 +1645,7 @@ type GetRegisterRiskConfigRequest struct {
func (x *GetRegisterRiskConfigRequest) Reset() {
*x = GetRegisterRiskConfigRequest{}
mi := &file_proto_user_v1_auth_proto_msgTypes[19]
mi := &file_proto_user_v1_auth_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1541,7 +1657,7 @@ func (x *GetRegisterRiskConfigRequest) String() string {
func (*GetRegisterRiskConfigRequest) ProtoMessage() {}
func (x *GetRegisterRiskConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[19]
mi := &file_proto_user_v1_auth_proto_msgTypes[21]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1554,7 +1670,7 @@ func (x *GetRegisterRiskConfigRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetRegisterRiskConfigRequest.ProtoReflect.Descriptor instead.
func (*GetRegisterRiskConfigRequest) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{19}
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{21}
}
func (x *GetRegisterRiskConfigRequest) GetMeta() *RequestMeta {
@ -1574,7 +1690,7 @@ type GetRegisterRiskConfigResponse struct {
func (x *GetRegisterRiskConfigResponse) Reset() {
*x = GetRegisterRiskConfigResponse{}
mi := &file_proto_user_v1_auth_proto_msgTypes[20]
mi := &file_proto_user_v1_auth_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1586,7 +1702,7 @@ func (x *GetRegisterRiskConfigResponse) String() string {
func (*GetRegisterRiskConfigResponse) ProtoMessage() {}
func (x *GetRegisterRiskConfigResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[20]
mi := &file_proto_user_v1_auth_proto_msgTypes[22]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1599,7 +1715,7 @@ func (x *GetRegisterRiskConfigResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetRegisterRiskConfigResponse.ProtoReflect.Descriptor instead.
func (*GetRegisterRiskConfigResponse) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{20}
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{22}
}
func (x *GetRegisterRiskConfigResponse) GetConfig() *RegisterRiskConfig {
@ -1622,7 +1738,7 @@ type UpdateRegisterRiskConfigRequest struct {
func (x *UpdateRegisterRiskConfigRequest) Reset() {
*x = UpdateRegisterRiskConfigRequest{}
mi := &file_proto_user_v1_auth_proto_msgTypes[21]
mi := &file_proto_user_v1_auth_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1634,7 +1750,7 @@ func (x *UpdateRegisterRiskConfigRequest) String() string {
func (*UpdateRegisterRiskConfigRequest) ProtoMessage() {}
func (x *UpdateRegisterRiskConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[21]
mi := &file_proto_user_v1_auth_proto_msgTypes[23]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1647,7 +1763,7 @@ func (x *UpdateRegisterRiskConfigRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdateRegisterRiskConfigRequest.ProtoReflect.Descriptor instead.
func (*UpdateRegisterRiskConfigRequest) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{21}
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{23}
}
func (x *UpdateRegisterRiskConfigRequest) GetMeta() *RequestMeta {
@ -1681,7 +1797,7 @@ type UpdateRegisterRiskConfigResponse struct {
func (x *UpdateRegisterRiskConfigResponse) Reset() {
*x = UpdateRegisterRiskConfigResponse{}
mi := &file_proto_user_v1_auth_proto_msgTypes[22]
mi := &file_proto_user_v1_auth_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1693,7 +1809,7 @@ func (x *UpdateRegisterRiskConfigResponse) String() string {
func (*UpdateRegisterRiskConfigResponse) ProtoMessage() {}
func (x *UpdateRegisterRiskConfigResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[22]
mi := &file_proto_user_v1_auth_proto_msgTypes[24]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1706,7 +1822,7 @@ func (x *UpdateRegisterRiskConfigResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdateRegisterRiskConfigResponse.ProtoReflect.Descriptor instead.
func (*UpdateRegisterRiskConfigResponse) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{22}
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{24}
}
func (x *UpdateRegisterRiskConfigResponse) GetConfig() *RegisterRiskConfig {
@ -1729,7 +1845,7 @@ type AppHeartbeatRequest struct {
func (x *AppHeartbeatRequest) Reset() {
*x = AppHeartbeatRequest{}
mi := &file_proto_user_v1_auth_proto_msgTypes[23]
mi := &file_proto_user_v1_auth_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1741,7 +1857,7 @@ func (x *AppHeartbeatRequest) String() string {
func (*AppHeartbeatRequest) ProtoMessage() {}
func (x *AppHeartbeatRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[23]
mi := &file_proto_user_v1_auth_proto_msgTypes[25]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1754,7 +1870,7 @@ func (x *AppHeartbeatRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use AppHeartbeatRequest.ProtoReflect.Descriptor instead.
func (*AppHeartbeatRequest) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{23}
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{25}
}
func (x *AppHeartbeatRequest) GetMeta() *RequestMeta {
@ -1792,7 +1908,7 @@ type AppHeartbeatResponse struct {
func (x *AppHeartbeatResponse) Reset() {
*x = AppHeartbeatResponse{}
mi := &file_proto_user_v1_auth_proto_msgTypes[24]
mi := &file_proto_user_v1_auth_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1804,7 +1920,7 @@ func (x *AppHeartbeatResponse) String() string {
func (*AppHeartbeatResponse) ProtoMessage() {}
func (x *AppHeartbeatResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_v1_auth_proto_msgTypes[24]
mi := &file_proto_user_v1_auth_proto_msgTypes[26]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1817,7 +1933,7 @@ func (x *AppHeartbeatResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use AppHeartbeatResponse.ProtoReflect.Descriptor instead.
func (*AppHeartbeatResponse) Descriptor() ([]byte, []int) {
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{24}
return file_proto_user_v1_auth_proto_rawDescGZIP(), []int{26}
}
func (x *AppHeartbeatResponse) GetAccepted() bool {
@ -2073,152 +2189,181 @@ var file_proto_user_v1_auth_proto_rawDesc = []byte{
0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x49, 0x50, 0x57, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73,
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x77, 0x68, 0x69,
0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b,
0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, 0xb9, 0x01, 0x0a, 0x12,
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x35, 0x0a,
0x17, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65,
0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14,
0x6d, 0x61, 0x78, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x44, 0x65,
0x76, 0x69, 0x63, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f,
0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18,
0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79,
0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x4e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x52, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74,
0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x5a, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x52, 0x65,
0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, 0x57, 0x0a, 0x25, 0x52,
0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x57,
0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04,
0x6d, 0x65, 0x74, 0x61, 0x22, 0xde, 0x01, 0x0a, 0x26, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68,
0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x57, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69,
0x73, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x65, 0x64, 0x12, 0x2c, 0x0a,
0x12, 0x69, 0x70, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x70, 0x57, 0x68, 0x69,
0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x75,
0x73, 0x65, 0x72, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x57,
0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x36, 0x0a,
0x18, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x69,
0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
0x14, 0x75, 0x73, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65,
0x73, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xb9, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08,
0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x61,
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x41, 0x63, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x22,
0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18,
0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
0x4d, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79,
0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49,
0x64, 0x22, 0x4e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74,
0x61, 0x22, 0x5a, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb4, 0x01,
0x0a, 0x1f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74,
0x61, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x05, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x50,
0x65, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72,
0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x6d,
0x69, 0x6e, 0x49, 0x64, 0x22, 0x5d, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x22, 0xb4, 0x01, 0x0a, 0x1f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74,
0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x61,
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x41, 0x63, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2a,
0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e,
0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61,
0x74, 0x6f, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x5d, 0x0a, 0x20, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39,
0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x7d, 0x0a, 0x13, 0x41, 0x70, 0x70,
0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61,
0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73,
0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73,
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x14, 0x41, 0x70, 0x70,
0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x26, 0x0a,
0x0f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73,
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61,
0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x74,
0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61,
0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x54,
0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xaa, 0x0a, 0x0a, 0x0b,
0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x0d, 0x4c,
0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x23, 0x2e, 0x68,
0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67,
0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76,
0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55,
0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74,
0x79, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76,
0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74,
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x12, 0x28, 0x2e, 0x68, 0x79,
0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69,
0x73, 0x74, 0x65, 0x72, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x7e, 0x0a, 0x19, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x69, 0x72, 0x64,
0x50, 0x61, 0x72, 0x74, 0x79, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12,
0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x66, 0x69, 0x67, 0x22, 0x7d, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62,
0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65,
0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73,
0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65,
0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69,
0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62,
0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61,
0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61,
0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x68, 0x65, 0x61, 0x72, 0x74,
0x62, 0x65, 0x61, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
0x52, 0x0d, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12,
0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d,
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54,
0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65,
0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x05,
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xba, 0x0b, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61,
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75,
0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x68, 0x79,
0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69,
0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x12, 0x25, 0x2e, 0x68, 0x79,
0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69,
0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x5b, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x68, 0x69, 0x72, 0x64,
0x50, 0x61, 0x72, 0x74, 0x79, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x68,
0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x19,
0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31,
0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79,
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
0x64, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65,
0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x51, 0x75, 0x69, 0x63,
0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28,
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51,
0x75, 0x69, 0x63, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70,
0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54,
0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61,
0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b,
0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b,
0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x2e, 0x68, 0x79,
0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50,
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22,
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53,
0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f,
0x6b, 0x65, 0x6e, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72,
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e,
0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54,
0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x06,
0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75,
0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65,
0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x6f, 0x67,
0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70,
0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72,
0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
0x76, 0x31, 0x2e, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a,
0x0c, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x22, 0x2e,
0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76,
0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x06, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74,
0x12, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31,
0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d,
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a,
0x12, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x65, 0x64, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72,
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e,
0x0a, 0x19, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b,
0x49, 0x50, 0x57, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x2e, 0x68, 0x79,
0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63,
0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e,
0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
0x63, 0x6f, 0x72, 0x64, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x19, 0x43, 0x68, 0x65, 0x63,
0x6b, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x49, 0x50, 0x57, 0x68, 0x69, 0x74,
0x65, 0x6c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68,
0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65,
0x63, 0x6b, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x49, 0x50, 0x57, 0x68, 0x69,
0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72,
0x0a, 0x15, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73,
0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e,
0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73,
0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65,
0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x7b, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69,
0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e,
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73,
0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f,
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73,
0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x57, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12,
0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72,
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x26, 0x5a, 0x24, 0x68, 0x79, 0x61, 0x70,
0x70, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x75, 0x73, 0x65, 0x72, 0x76, 0x31,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4c, 0x6f, 0x67, 0x69, 0x6e,
0x52, 0x69, 0x73, 0x6b, 0x49, 0x50, 0x57, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75,
0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4c, 0x6f, 0x67, 0x69,
0x6e, 0x52, 0x69, 0x73, 0x6b, 0x49, 0x50, 0x57, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x66,
0x72, 0x65, 0x73, 0x68, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x57, 0x68, 0x69,
0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x34, 0x2e, 0x68, 0x79,
0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72,
0x65, 0x73, 0x68, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x57, 0x68, 0x69, 0x74,
0x65, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76,
0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69,
0x73, 0x6b, 0x57, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76,
0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73,
0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c,
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47,
0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x18,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69,
0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x69, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x41, 0x70, 0x70,
0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70,
0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61,
0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e,
0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70,
0x70, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x42, 0x26, 0x5a, 0x24, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72,
0x2f, 0x76, 0x31, 0x3b, 0x75, 0x73, 0x65, 0x72, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
@ -2233,87 +2378,92 @@ func file_proto_user_v1_auth_proto_rawDescGZIP() []byte {
return file_proto_user_v1_auth_proto_rawDescData
}
var file_proto_user_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
var file_proto_user_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
var file_proto_user_v1_auth_proto_goTypes = []any{
(*LoginPasswordRequest)(nil), // 0: hyapp.user.v1.LoginPasswordRequest
(*LoginThirdPartyRequest)(nil), // 1: hyapp.user.v1.LoginThirdPartyRequest
(*RegisterThirdPartyRequest)(nil), // 2: hyapp.user.v1.RegisterThirdPartyRequest
(*CheckThirdPartyRegisteredRequest)(nil), // 3: hyapp.user.v1.CheckThirdPartyRegisteredRequest
(*CheckThirdPartyRegisteredResponse)(nil), // 4: hyapp.user.v1.CheckThirdPartyRegisteredResponse
(*AuthResponse)(nil), // 5: hyapp.user.v1.AuthResponse
(*SetPasswordRequest)(nil), // 6: hyapp.user.v1.SetPasswordRequest
(*SetPasswordResponse)(nil), // 7: hyapp.user.v1.SetPasswordResponse
(*QuickCreateAccountRequest)(nil), // 8: hyapp.user.v1.QuickCreateAccountRequest
(*QuickCreateAccountResponse)(nil), // 9: hyapp.user.v1.QuickCreateAccountResponse
(*RefreshTokenRequest)(nil), // 10: hyapp.user.v1.RefreshTokenRequest
(*RefreshTokenResponse)(nil), // 11: hyapp.user.v1.RefreshTokenResponse
(*LogoutRequest)(nil), // 12: hyapp.user.v1.LogoutRequest
(*LogoutResponse)(nil), // 13: hyapp.user.v1.LogoutResponse
(*RecordLoginBlockedRequest)(nil), // 14: hyapp.user.v1.RecordLoginBlockedRequest
(*RecordLoginBlockedResponse)(nil), // 15: hyapp.user.v1.RecordLoginBlockedResponse
(*CheckLoginRiskIPWhitelistRequest)(nil), // 16: hyapp.user.v1.CheckLoginRiskIPWhitelistRequest
(*CheckLoginRiskIPWhitelistResponse)(nil), // 17: hyapp.user.v1.CheckLoginRiskIPWhitelistResponse
(*RegisterRiskConfig)(nil), // 18: hyapp.user.v1.RegisterRiskConfig
(*GetRegisterRiskConfigRequest)(nil), // 19: hyapp.user.v1.GetRegisterRiskConfigRequest
(*GetRegisterRiskConfigResponse)(nil), // 20: hyapp.user.v1.GetRegisterRiskConfigResponse
(*UpdateRegisterRiskConfigRequest)(nil), // 21: hyapp.user.v1.UpdateRegisterRiskConfigRequest
(*UpdateRegisterRiskConfigResponse)(nil), // 22: hyapp.user.v1.UpdateRegisterRiskConfigResponse
(*AppHeartbeatRequest)(nil), // 23: hyapp.user.v1.AppHeartbeatRequest
(*AppHeartbeatResponse)(nil), // 24: hyapp.user.v1.AppHeartbeatResponse
(*RequestMeta)(nil), // 25: hyapp.user.v1.RequestMeta
(*AuthToken)(nil), // 26: hyapp.user.v1.AuthToken
(*LoginPasswordRequest)(nil), // 0: hyapp.user.v1.LoginPasswordRequest
(*LoginThirdPartyRequest)(nil), // 1: hyapp.user.v1.LoginThirdPartyRequest
(*RegisterThirdPartyRequest)(nil), // 2: hyapp.user.v1.RegisterThirdPartyRequest
(*CheckThirdPartyRegisteredRequest)(nil), // 3: hyapp.user.v1.CheckThirdPartyRegisteredRequest
(*CheckThirdPartyRegisteredResponse)(nil), // 4: hyapp.user.v1.CheckThirdPartyRegisteredResponse
(*AuthResponse)(nil), // 5: hyapp.user.v1.AuthResponse
(*SetPasswordRequest)(nil), // 6: hyapp.user.v1.SetPasswordRequest
(*SetPasswordResponse)(nil), // 7: hyapp.user.v1.SetPasswordResponse
(*QuickCreateAccountRequest)(nil), // 8: hyapp.user.v1.QuickCreateAccountRequest
(*QuickCreateAccountResponse)(nil), // 9: hyapp.user.v1.QuickCreateAccountResponse
(*RefreshTokenRequest)(nil), // 10: hyapp.user.v1.RefreshTokenRequest
(*RefreshTokenResponse)(nil), // 11: hyapp.user.v1.RefreshTokenResponse
(*LogoutRequest)(nil), // 12: hyapp.user.v1.LogoutRequest
(*LogoutResponse)(nil), // 13: hyapp.user.v1.LogoutResponse
(*RecordLoginBlockedRequest)(nil), // 14: hyapp.user.v1.RecordLoginBlockedRequest
(*RecordLoginBlockedResponse)(nil), // 15: hyapp.user.v1.RecordLoginBlockedResponse
(*CheckLoginRiskIPWhitelistRequest)(nil), // 16: hyapp.user.v1.CheckLoginRiskIPWhitelistRequest
(*CheckLoginRiskIPWhitelistResponse)(nil), // 17: hyapp.user.v1.CheckLoginRiskIPWhitelistResponse
(*RefreshLoginRiskWhitelistCacheRequest)(nil), // 18: hyapp.user.v1.RefreshLoginRiskWhitelistCacheRequest
(*RefreshLoginRiskWhitelistCacheResponse)(nil), // 19: hyapp.user.v1.RefreshLoginRiskWhitelistCacheResponse
(*RegisterRiskConfig)(nil), // 20: hyapp.user.v1.RegisterRiskConfig
(*GetRegisterRiskConfigRequest)(nil), // 21: hyapp.user.v1.GetRegisterRiskConfigRequest
(*GetRegisterRiskConfigResponse)(nil), // 22: hyapp.user.v1.GetRegisterRiskConfigResponse
(*UpdateRegisterRiskConfigRequest)(nil), // 23: hyapp.user.v1.UpdateRegisterRiskConfigRequest
(*UpdateRegisterRiskConfigResponse)(nil), // 24: hyapp.user.v1.UpdateRegisterRiskConfigResponse
(*AppHeartbeatRequest)(nil), // 25: hyapp.user.v1.AppHeartbeatRequest
(*AppHeartbeatResponse)(nil), // 26: hyapp.user.v1.AppHeartbeatResponse
(*RequestMeta)(nil), // 27: hyapp.user.v1.RequestMeta
(*AuthToken)(nil), // 28: hyapp.user.v1.AuthToken
}
var file_proto_user_v1_auth_proto_depIdxs = []int32{
25, // 0: hyapp.user.v1.LoginPasswordRequest.meta:type_name -> hyapp.user.v1.RequestMeta
25, // 1: hyapp.user.v1.LoginThirdPartyRequest.meta:type_name -> hyapp.user.v1.RequestMeta
25, // 2: hyapp.user.v1.RegisterThirdPartyRequest.meta:type_name -> hyapp.user.v1.RequestMeta
25, // 3: hyapp.user.v1.CheckThirdPartyRegisteredRequest.meta:type_name -> hyapp.user.v1.RequestMeta
26, // 4: hyapp.user.v1.AuthResponse.token:type_name -> hyapp.user.v1.AuthToken
25, // 5: hyapp.user.v1.SetPasswordRequest.meta:type_name -> hyapp.user.v1.RequestMeta
25, // 6: hyapp.user.v1.QuickCreateAccountRequest.meta:type_name -> hyapp.user.v1.RequestMeta
26, // 7: hyapp.user.v1.QuickCreateAccountResponse.token:type_name -> hyapp.user.v1.AuthToken
25, // 8: hyapp.user.v1.RefreshTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta
26, // 9: hyapp.user.v1.RefreshTokenResponse.token:type_name -> hyapp.user.v1.AuthToken
25, // 10: hyapp.user.v1.LogoutRequest.meta:type_name -> hyapp.user.v1.RequestMeta
25, // 11: hyapp.user.v1.RecordLoginBlockedRequest.meta:type_name -> hyapp.user.v1.RequestMeta
25, // 12: hyapp.user.v1.CheckLoginRiskIPWhitelistRequest.meta:type_name -> hyapp.user.v1.RequestMeta
25, // 13: hyapp.user.v1.GetRegisterRiskConfigRequest.meta:type_name -> hyapp.user.v1.RequestMeta
18, // 14: hyapp.user.v1.GetRegisterRiskConfigResponse.config:type_name -> hyapp.user.v1.RegisterRiskConfig
25, // 15: hyapp.user.v1.UpdateRegisterRiskConfigRequest.meta:type_name -> hyapp.user.v1.RequestMeta
18, // 16: hyapp.user.v1.UpdateRegisterRiskConfigResponse.config:type_name -> hyapp.user.v1.RegisterRiskConfig
25, // 17: hyapp.user.v1.AppHeartbeatRequest.meta:type_name -> hyapp.user.v1.RequestMeta
26, // 18: hyapp.user.v1.AppHeartbeatResponse.token:type_name -> hyapp.user.v1.AuthToken
0, // 19: hyapp.user.v1.AuthService.LoginPassword:input_type -> hyapp.user.v1.LoginPasswordRequest
1, // 20: hyapp.user.v1.AuthService.LoginThirdParty:input_type -> hyapp.user.v1.LoginThirdPartyRequest
2, // 21: hyapp.user.v1.AuthService.RegisterThirdParty:input_type -> hyapp.user.v1.RegisterThirdPartyRequest
3, // 22: hyapp.user.v1.AuthService.CheckThirdPartyRegistered:input_type -> hyapp.user.v1.CheckThirdPartyRegisteredRequest
6, // 23: hyapp.user.v1.AuthService.SetPassword:input_type -> hyapp.user.v1.SetPasswordRequest
8, // 24: hyapp.user.v1.AuthService.QuickCreateAccount:input_type -> hyapp.user.v1.QuickCreateAccountRequest
10, // 25: hyapp.user.v1.AuthService.RefreshToken:input_type -> hyapp.user.v1.RefreshTokenRequest
12, // 26: hyapp.user.v1.AuthService.Logout:input_type -> hyapp.user.v1.LogoutRequest
14, // 27: hyapp.user.v1.AuthService.RecordLoginBlocked:input_type -> hyapp.user.v1.RecordLoginBlockedRequest
16, // 28: hyapp.user.v1.AuthService.CheckLoginRiskIPWhitelist:input_type -> hyapp.user.v1.CheckLoginRiskIPWhitelistRequest
19, // 29: hyapp.user.v1.AuthService.GetRegisterRiskConfig:input_type -> hyapp.user.v1.GetRegisterRiskConfigRequest
21, // 30: hyapp.user.v1.AuthService.UpdateRegisterRiskConfig:input_type -> hyapp.user.v1.UpdateRegisterRiskConfigRequest
23, // 31: hyapp.user.v1.AuthService.AppHeartbeat:input_type -> hyapp.user.v1.AppHeartbeatRequest
5, // 32: hyapp.user.v1.AuthService.LoginPassword:output_type -> hyapp.user.v1.AuthResponse
5, // 33: hyapp.user.v1.AuthService.LoginThirdParty:output_type -> hyapp.user.v1.AuthResponse
5, // 34: hyapp.user.v1.AuthService.RegisterThirdParty:output_type -> hyapp.user.v1.AuthResponse
4, // 35: hyapp.user.v1.AuthService.CheckThirdPartyRegistered:output_type -> hyapp.user.v1.CheckThirdPartyRegisteredResponse
7, // 36: hyapp.user.v1.AuthService.SetPassword:output_type -> hyapp.user.v1.SetPasswordResponse
9, // 37: hyapp.user.v1.AuthService.QuickCreateAccount:output_type -> hyapp.user.v1.QuickCreateAccountResponse
11, // 38: hyapp.user.v1.AuthService.RefreshToken:output_type -> hyapp.user.v1.RefreshTokenResponse
13, // 39: hyapp.user.v1.AuthService.Logout:output_type -> hyapp.user.v1.LogoutResponse
15, // 40: hyapp.user.v1.AuthService.RecordLoginBlocked:output_type -> hyapp.user.v1.RecordLoginBlockedResponse
17, // 41: hyapp.user.v1.AuthService.CheckLoginRiskIPWhitelist:output_type -> hyapp.user.v1.CheckLoginRiskIPWhitelistResponse
20, // 42: hyapp.user.v1.AuthService.GetRegisterRiskConfig:output_type -> hyapp.user.v1.GetRegisterRiskConfigResponse
22, // 43: hyapp.user.v1.AuthService.UpdateRegisterRiskConfig:output_type -> hyapp.user.v1.UpdateRegisterRiskConfigResponse
24, // 44: hyapp.user.v1.AuthService.AppHeartbeat:output_type -> hyapp.user.v1.AppHeartbeatResponse
32, // [32:45] is the sub-list for method output_type
19, // [19:32] is the sub-list for method input_type
19, // [19:19] is the sub-list for extension type_name
19, // [19:19] is the sub-list for extension extendee
0, // [0:19] is the sub-list for field type_name
27, // 0: hyapp.user.v1.LoginPasswordRequest.meta:type_name -> hyapp.user.v1.RequestMeta
27, // 1: hyapp.user.v1.LoginThirdPartyRequest.meta:type_name -> hyapp.user.v1.RequestMeta
27, // 2: hyapp.user.v1.RegisterThirdPartyRequest.meta:type_name -> hyapp.user.v1.RequestMeta
27, // 3: hyapp.user.v1.CheckThirdPartyRegisteredRequest.meta:type_name -> hyapp.user.v1.RequestMeta
28, // 4: hyapp.user.v1.AuthResponse.token:type_name -> hyapp.user.v1.AuthToken
27, // 5: hyapp.user.v1.SetPasswordRequest.meta:type_name -> hyapp.user.v1.RequestMeta
27, // 6: hyapp.user.v1.QuickCreateAccountRequest.meta:type_name -> hyapp.user.v1.RequestMeta
28, // 7: hyapp.user.v1.QuickCreateAccountResponse.token:type_name -> hyapp.user.v1.AuthToken
27, // 8: hyapp.user.v1.RefreshTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta
28, // 9: hyapp.user.v1.RefreshTokenResponse.token:type_name -> hyapp.user.v1.AuthToken
27, // 10: hyapp.user.v1.LogoutRequest.meta:type_name -> hyapp.user.v1.RequestMeta
27, // 11: hyapp.user.v1.RecordLoginBlockedRequest.meta:type_name -> hyapp.user.v1.RequestMeta
27, // 12: hyapp.user.v1.CheckLoginRiskIPWhitelistRequest.meta:type_name -> hyapp.user.v1.RequestMeta
27, // 13: hyapp.user.v1.RefreshLoginRiskWhitelistCacheRequest.meta:type_name -> hyapp.user.v1.RequestMeta
27, // 14: hyapp.user.v1.GetRegisterRiskConfigRequest.meta:type_name -> hyapp.user.v1.RequestMeta
20, // 15: hyapp.user.v1.GetRegisterRiskConfigResponse.config:type_name -> hyapp.user.v1.RegisterRiskConfig
27, // 16: hyapp.user.v1.UpdateRegisterRiskConfigRequest.meta:type_name -> hyapp.user.v1.RequestMeta
20, // 17: hyapp.user.v1.UpdateRegisterRiskConfigResponse.config:type_name -> hyapp.user.v1.RegisterRiskConfig
27, // 18: hyapp.user.v1.AppHeartbeatRequest.meta:type_name -> hyapp.user.v1.RequestMeta
28, // 19: hyapp.user.v1.AppHeartbeatResponse.token:type_name -> hyapp.user.v1.AuthToken
0, // 20: hyapp.user.v1.AuthService.LoginPassword:input_type -> hyapp.user.v1.LoginPasswordRequest
1, // 21: hyapp.user.v1.AuthService.LoginThirdParty:input_type -> hyapp.user.v1.LoginThirdPartyRequest
2, // 22: hyapp.user.v1.AuthService.RegisterThirdParty:input_type -> hyapp.user.v1.RegisterThirdPartyRequest
3, // 23: hyapp.user.v1.AuthService.CheckThirdPartyRegistered:input_type -> hyapp.user.v1.CheckThirdPartyRegisteredRequest
6, // 24: hyapp.user.v1.AuthService.SetPassword:input_type -> hyapp.user.v1.SetPasswordRequest
8, // 25: hyapp.user.v1.AuthService.QuickCreateAccount:input_type -> hyapp.user.v1.QuickCreateAccountRequest
10, // 26: hyapp.user.v1.AuthService.RefreshToken:input_type -> hyapp.user.v1.RefreshTokenRequest
12, // 27: hyapp.user.v1.AuthService.Logout:input_type -> hyapp.user.v1.LogoutRequest
14, // 28: hyapp.user.v1.AuthService.RecordLoginBlocked:input_type -> hyapp.user.v1.RecordLoginBlockedRequest
16, // 29: hyapp.user.v1.AuthService.CheckLoginRiskIPWhitelist:input_type -> hyapp.user.v1.CheckLoginRiskIPWhitelistRequest
18, // 30: hyapp.user.v1.AuthService.RefreshLoginRiskWhitelistCache:input_type -> hyapp.user.v1.RefreshLoginRiskWhitelistCacheRequest
21, // 31: hyapp.user.v1.AuthService.GetRegisterRiskConfig:input_type -> hyapp.user.v1.GetRegisterRiskConfigRequest
23, // 32: hyapp.user.v1.AuthService.UpdateRegisterRiskConfig:input_type -> hyapp.user.v1.UpdateRegisterRiskConfigRequest
25, // 33: hyapp.user.v1.AuthService.AppHeartbeat:input_type -> hyapp.user.v1.AppHeartbeatRequest
5, // 34: hyapp.user.v1.AuthService.LoginPassword:output_type -> hyapp.user.v1.AuthResponse
5, // 35: hyapp.user.v1.AuthService.LoginThirdParty:output_type -> hyapp.user.v1.AuthResponse
5, // 36: hyapp.user.v1.AuthService.RegisterThirdParty:output_type -> hyapp.user.v1.AuthResponse
4, // 37: hyapp.user.v1.AuthService.CheckThirdPartyRegistered:output_type -> hyapp.user.v1.CheckThirdPartyRegisteredResponse
7, // 38: hyapp.user.v1.AuthService.SetPassword:output_type -> hyapp.user.v1.SetPasswordResponse
9, // 39: hyapp.user.v1.AuthService.QuickCreateAccount:output_type -> hyapp.user.v1.QuickCreateAccountResponse
11, // 40: hyapp.user.v1.AuthService.RefreshToken:output_type -> hyapp.user.v1.RefreshTokenResponse
13, // 41: hyapp.user.v1.AuthService.Logout:output_type -> hyapp.user.v1.LogoutResponse
15, // 42: hyapp.user.v1.AuthService.RecordLoginBlocked:output_type -> hyapp.user.v1.RecordLoginBlockedResponse
17, // 43: hyapp.user.v1.AuthService.CheckLoginRiskIPWhitelist:output_type -> hyapp.user.v1.CheckLoginRiskIPWhitelistResponse
19, // 44: hyapp.user.v1.AuthService.RefreshLoginRiskWhitelistCache:output_type -> hyapp.user.v1.RefreshLoginRiskWhitelistCacheResponse
22, // 45: hyapp.user.v1.AuthService.GetRegisterRiskConfig:output_type -> hyapp.user.v1.GetRegisterRiskConfigResponse
24, // 46: hyapp.user.v1.AuthService.UpdateRegisterRiskConfig:output_type -> hyapp.user.v1.UpdateRegisterRiskConfigResponse
26, // 47: hyapp.user.v1.AuthService.AppHeartbeat:output_type -> hyapp.user.v1.AppHeartbeatResponse
34, // [34:48] is the sub-list for method output_type
20, // [20:34] 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
}
func init() { file_proto_user_v1_auth_proto_init() }
@ -2328,7 +2478,7 @@ func file_proto_user_v1_auth_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_user_v1_auth_proto_rawDesc,
NumEnums: 0,
NumMessages: 25,
NumMessages: 27,
NumExtensions: 0,
NumServices: 1,
},

View File

@ -171,6 +171,19 @@ message CheckLoginRiskIPWhitelistResponse {
bool whitelisted = 1;
}
// RefreshLoginRiskWhitelistCacheRequest user-service MySQL
message RefreshLoginRiskWhitelistCacheRequest {
RequestMeta meta = 1;
}
// RefreshLoginRiskWhitelistCacheResponse 便
message RefreshLoginRiskWhitelistCacheResponse {
bool refreshed = 1;
int32 ip_whitelist_count = 2;
int32 user_whitelist_count = 3;
int64 user_cache_expires_at_ms = 4;
}
// RegisterRiskConfig
message RegisterRiskConfig {
string app_code = 1;
@ -226,6 +239,7 @@ service AuthService {
rpc Logout(LogoutRequest) returns (LogoutResponse);
rpc RecordLoginBlocked(RecordLoginBlockedRequest) returns (RecordLoginBlockedResponse);
rpc CheckLoginRiskIPWhitelist(CheckLoginRiskIPWhitelistRequest) returns (CheckLoginRiskIPWhitelistResponse);
rpc RefreshLoginRiskWhitelistCache(RefreshLoginRiskWhitelistCacheRequest) returns (RefreshLoginRiskWhitelistCacheResponse);
rpc GetRegisterRiskConfig(GetRegisterRiskConfigRequest) returns (GetRegisterRiskConfigResponse);
rpc UpdateRegisterRiskConfig(UpdateRegisterRiskConfigRequest) returns (UpdateRegisterRiskConfigResponse);
rpc AppHeartbeat(AppHeartbeatRequest) returns (AppHeartbeatResponse);

View File

@ -19,19 +19,20 @@ import (
const _ = grpc.SupportPackageIsVersion9
const (
AuthService_LoginPassword_FullMethodName = "/hyapp.user.v1.AuthService/LoginPassword"
AuthService_LoginThirdParty_FullMethodName = "/hyapp.user.v1.AuthService/LoginThirdParty"
AuthService_RegisterThirdParty_FullMethodName = "/hyapp.user.v1.AuthService/RegisterThirdParty"
AuthService_CheckThirdPartyRegistered_FullMethodName = "/hyapp.user.v1.AuthService/CheckThirdPartyRegistered"
AuthService_SetPassword_FullMethodName = "/hyapp.user.v1.AuthService/SetPassword"
AuthService_QuickCreateAccount_FullMethodName = "/hyapp.user.v1.AuthService/QuickCreateAccount"
AuthService_RefreshToken_FullMethodName = "/hyapp.user.v1.AuthService/RefreshToken"
AuthService_Logout_FullMethodName = "/hyapp.user.v1.AuthService/Logout"
AuthService_RecordLoginBlocked_FullMethodName = "/hyapp.user.v1.AuthService/RecordLoginBlocked"
AuthService_CheckLoginRiskIPWhitelist_FullMethodName = "/hyapp.user.v1.AuthService/CheckLoginRiskIPWhitelist"
AuthService_GetRegisterRiskConfig_FullMethodName = "/hyapp.user.v1.AuthService/GetRegisterRiskConfig"
AuthService_UpdateRegisterRiskConfig_FullMethodName = "/hyapp.user.v1.AuthService/UpdateRegisterRiskConfig"
AuthService_AppHeartbeat_FullMethodName = "/hyapp.user.v1.AuthService/AppHeartbeat"
AuthService_LoginPassword_FullMethodName = "/hyapp.user.v1.AuthService/LoginPassword"
AuthService_LoginThirdParty_FullMethodName = "/hyapp.user.v1.AuthService/LoginThirdParty"
AuthService_RegisterThirdParty_FullMethodName = "/hyapp.user.v1.AuthService/RegisterThirdParty"
AuthService_CheckThirdPartyRegistered_FullMethodName = "/hyapp.user.v1.AuthService/CheckThirdPartyRegistered"
AuthService_SetPassword_FullMethodName = "/hyapp.user.v1.AuthService/SetPassword"
AuthService_QuickCreateAccount_FullMethodName = "/hyapp.user.v1.AuthService/QuickCreateAccount"
AuthService_RefreshToken_FullMethodName = "/hyapp.user.v1.AuthService/RefreshToken"
AuthService_Logout_FullMethodName = "/hyapp.user.v1.AuthService/Logout"
AuthService_RecordLoginBlocked_FullMethodName = "/hyapp.user.v1.AuthService/RecordLoginBlocked"
AuthService_CheckLoginRiskIPWhitelist_FullMethodName = "/hyapp.user.v1.AuthService/CheckLoginRiskIPWhitelist"
AuthService_RefreshLoginRiskWhitelistCache_FullMethodName = "/hyapp.user.v1.AuthService/RefreshLoginRiskWhitelistCache"
AuthService_GetRegisterRiskConfig_FullMethodName = "/hyapp.user.v1.AuthService/GetRegisterRiskConfig"
AuthService_UpdateRegisterRiskConfig_FullMethodName = "/hyapp.user.v1.AuthService/UpdateRegisterRiskConfig"
AuthService_AppHeartbeat_FullMethodName = "/hyapp.user.v1.AuthService/AppHeartbeat"
)
// AuthServiceClient is the client API for AuthService service.
@ -50,6 +51,7 @@ type AuthServiceClient interface {
Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error)
RecordLoginBlocked(ctx context.Context, in *RecordLoginBlockedRequest, opts ...grpc.CallOption) (*RecordLoginBlockedResponse, error)
CheckLoginRiskIPWhitelist(ctx context.Context, in *CheckLoginRiskIPWhitelistRequest, opts ...grpc.CallOption) (*CheckLoginRiskIPWhitelistResponse, error)
RefreshLoginRiskWhitelistCache(ctx context.Context, in *RefreshLoginRiskWhitelistCacheRequest, opts ...grpc.CallOption) (*RefreshLoginRiskWhitelistCacheResponse, error)
GetRegisterRiskConfig(ctx context.Context, in *GetRegisterRiskConfigRequest, opts ...grpc.CallOption) (*GetRegisterRiskConfigResponse, error)
UpdateRegisterRiskConfig(ctx context.Context, in *UpdateRegisterRiskConfigRequest, opts ...grpc.CallOption) (*UpdateRegisterRiskConfigResponse, error)
AppHeartbeat(ctx context.Context, in *AppHeartbeatRequest, opts ...grpc.CallOption) (*AppHeartbeatResponse, error)
@ -163,6 +165,16 @@ func (c *authServiceClient) CheckLoginRiskIPWhitelist(ctx context.Context, in *C
return out, nil
}
func (c *authServiceClient) RefreshLoginRiskWhitelistCache(ctx context.Context, in *RefreshLoginRiskWhitelistCacheRequest, opts ...grpc.CallOption) (*RefreshLoginRiskWhitelistCacheResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RefreshLoginRiskWhitelistCacheResponse)
err := c.cc.Invoke(ctx, AuthService_RefreshLoginRiskWhitelistCache_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) GetRegisterRiskConfig(ctx context.Context, in *GetRegisterRiskConfigRequest, opts ...grpc.CallOption) (*GetRegisterRiskConfigResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetRegisterRiskConfigResponse)
@ -209,6 +221,7 @@ type AuthServiceServer interface {
Logout(context.Context, *LogoutRequest) (*LogoutResponse, error)
RecordLoginBlocked(context.Context, *RecordLoginBlockedRequest) (*RecordLoginBlockedResponse, error)
CheckLoginRiskIPWhitelist(context.Context, *CheckLoginRiskIPWhitelistRequest) (*CheckLoginRiskIPWhitelistResponse, error)
RefreshLoginRiskWhitelistCache(context.Context, *RefreshLoginRiskWhitelistCacheRequest) (*RefreshLoginRiskWhitelistCacheResponse, error)
GetRegisterRiskConfig(context.Context, *GetRegisterRiskConfigRequest) (*GetRegisterRiskConfigResponse, error)
UpdateRegisterRiskConfig(context.Context, *UpdateRegisterRiskConfigRequest) (*UpdateRegisterRiskConfigResponse, error)
AppHeartbeat(context.Context, *AppHeartbeatRequest) (*AppHeartbeatResponse, error)
@ -252,6 +265,9 @@ func (UnimplementedAuthServiceServer) RecordLoginBlocked(context.Context, *Recor
func (UnimplementedAuthServiceServer) CheckLoginRiskIPWhitelist(context.Context, *CheckLoginRiskIPWhitelistRequest) (*CheckLoginRiskIPWhitelistResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CheckLoginRiskIPWhitelist not implemented")
}
func (UnimplementedAuthServiceServer) RefreshLoginRiskWhitelistCache(context.Context, *RefreshLoginRiskWhitelistCacheRequest) (*RefreshLoginRiskWhitelistCacheResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RefreshLoginRiskWhitelistCache not implemented")
}
func (UnimplementedAuthServiceServer) GetRegisterRiskConfig(context.Context, *GetRegisterRiskConfigRequest) (*GetRegisterRiskConfigResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRegisterRiskConfig not implemented")
}
@ -462,6 +478,24 @@ func _AuthService_CheckLoginRiskIPWhitelist_Handler(srv interface{}, ctx context
return interceptor(ctx, in, info, handler)
}
func _AuthService_RefreshLoginRiskWhitelistCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RefreshLoginRiskWhitelistCacheRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).RefreshLoginRiskWhitelistCache(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_RefreshLoginRiskWhitelistCache_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).RefreshLoginRiskWhitelistCache(ctx, req.(*RefreshLoginRiskWhitelistCacheRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_GetRegisterRiskConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetRegisterRiskConfigRequest)
if err := dec(in); err != nil {
@ -563,6 +597,10 @@ var AuthService_ServiceDesc = grpc.ServiceDesc{
MethodName: "CheckLoginRiskIPWhitelist",
Handler: _AuthService_CheckLoginRiskIPWhitelist_Handler,
},
{
MethodName: "RefreshLoginRiskWhitelistCache",
Handler: _AuthService_RefreshLoginRiskWhitelistCache_Handler,
},
{
MethodName: "GetRegisterRiskConfig",
Handler: _AuthService_GetRegisterRiskConfig_Handler,

View File

@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS login_risk_user_whitelist (
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
whitelist_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '白名单 ID',
user_id BIGINT NOT NULL COMMENT '允许跳过登录地区屏蔽复核的用户 ID',
enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '启用',
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
updated_by_user_id BIGINT NULL COMMENT '更新人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (whitelist_id),
UNIQUE KEY uk_login_risk_user_whitelist_user (app_code, user_id),
KEY idx_login_risk_user_whitelist_enabled (app_code, enabled, user_id),
KEY idx_login_risk_user_whitelist_updated (app_code, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录风险用户白名单表';

View File

@ -294,7 +294,7 @@ func main() {
RedPacket: redpacketmodule.New(walletclient.NewGRPC(walletConn), auditHandler),
Report: reportmodule.New(userDB, roomClient),
RegistrationReward: registrationrewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler),
RegionBlock: regionblockmodule.New(userDB, auditHandler),
RegionBlock: regionblockmodule.New(userDB, userclient.NewGRPC(userConn), auditHandler),
Resource: resourcemodule.New(walletclient.NewGRPC(walletConn), store, userDB, cfg.WalletService.RequestTimeout, auditHandler),
RiskConfig: riskconfigmodule.New(userclient.NewGRPC(userConn), auditHandler),
RoomAdmin: roomadminmodule.New(userDB, store, roomClient, robotClient, auditHandler),

View File

@ -17,6 +17,7 @@ type Client interface {
SetUserStatus(ctx context.Context, req SetUserStatusRequest) (*SetUserStatusResult, error)
GetRegisterRiskConfig(ctx context.Context, req GetRegisterRiskConfigRequest) (*RegisterRiskConfig, error)
UpdateRegisterRiskConfig(ctx context.Context, req UpdateRegisterRiskConfigRequest) (*RegisterRiskConfig, error)
RefreshLoginRiskWhitelistCache(ctx context.Context, req RefreshLoginRiskWhitelistCacheRequest) (*LoginRiskWhitelistCacheSnapshot, error)
ResolveDisplayUserID(ctx context.Context, req ResolveDisplayUserIDRequest) (*UserIdentity, error)
ListPrettyDisplayIDPools(ctx context.Context, req ListPrettyDisplayIDPoolsRequest) ([]*PrettyDisplayIDPool, int64, error)
CreatePrettyDisplayIDPool(ctx context.Context, req PrettyDisplayIDPoolRequest) (*PrettyDisplayIDPool, error)
@ -139,6 +140,18 @@ type RegisterRiskConfig struct {
UpdatedByAdminID int64 `json:"updatedByAdminId"`
}
type RefreshLoginRiskWhitelistCacheRequest struct {
RequestID string
Caller string
}
type LoginRiskWhitelistCacheSnapshot struct {
Refreshed bool `json:"refreshed"`
IPWhitelistCount int32 `json:"ipWhitelistCount"`
UserWhitelistCount int32 `json:"userWhitelistCount"`
UserCacheExpiresAtMs int64 `json:"userCacheExpiresAtMs"`
}
type ResolveDisplayUserIDRequest struct {
RequestID string
Caller string
@ -285,6 +298,21 @@ func (c *GRPCClient) UpdateRegisterRiskConfig(ctx context.Context, req UpdateReg
return fromProtoRegisterRiskConfig(resp.GetConfig()), nil
}
func (c *GRPCClient) RefreshLoginRiskWhitelistCache(ctx context.Context, req RefreshLoginRiskWhitelistCacheRequest) (*LoginRiskWhitelistCacheSnapshot, error) {
resp, err := c.authClient.RefreshLoginRiskWhitelistCache(ctx, &userv1.RefreshLoginRiskWhitelistCacheRequest{
Meta: requestMeta(ctx, req.RequestID, req.Caller),
})
if err != nil {
return nil, err
}
return &LoginRiskWhitelistCacheSnapshot{
Refreshed: resp.GetRefreshed(),
IPWhitelistCount: resp.GetIpWhitelistCount(),
UserWhitelistCount: resp.GetUserWhitelistCount(),
UserCacheExpiresAtMs: resp.GetUserCacheExpiresAtMs(),
}, nil
}
// BatchGetUsers 复用 user-service 主数据 RPC让后台列表只做展示聚合不复制用户资料到游戏库。
func (c *GRPCClient) BatchGetUsers(ctx context.Context, req BatchGetUsersRequest) (map[int64]*User, error) {
resp, err := c.client.BatchGetUsers(ctx, &userv1.BatchGetUsersRequest{

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"hyapp-admin-server/internal/integration/userclient"
"hyapp-admin-server/internal/middleware"
"hyapp-admin-server/internal/modules/shared"
"hyapp-admin-server/internal/response"
@ -18,12 +19,13 @@ type Handler struct {
}
type replaceRequest struct {
Keywords *[]string `json:"keywords"`
WhitelistIPs *[]string `json:"whitelist_ips"`
Keywords *[]string `json:"keywords"`
WhitelistIPs *[]string `json:"whitelist_ips"`
WhitelistUserIDs *[]string `json:"whitelist_user_ids"`
}
func New(userDB *sql.DB, audit shared.OperationLogger) *Handler {
return &Handler{service: NewService(userDB), audit: audit}
func New(userDB *sql.DB, user userclient.Client, audit shared.OperationLogger) *Handler {
return &Handler{service: NewService(userDB, user), audit: audit}
}
// ListRegionBlocks 返回用户管理 > 地区屏蔽页面需要的当前屏蔽词列表。
@ -43,15 +45,19 @@ func (h *Handler) ReplaceRegionBlocks(c *gin.Context) {
response.BadRequest(c, "地区屏蔽词参数不正确")
return
}
items, err := h.service.Replace(c.Request.Context(), int64(shared.ActorFromContext(c).UserID), *req.Keywords, req.WhitelistIPs)
items, err := h.service.Replace(c.Request.Context(), middleware.CurrentRequestID(c), int64(shared.ActorFromContext(c).UserID), *req.Keywords, req.WhitelistIPs, req.WhitelistUserIDs)
if err != nil {
if errors.Is(err, errInvalidPayload) {
response.BadRequest(c, "地区屏蔽词参数不正确")
return
}
if errors.Is(err, errWhitelistCacheRefresh) {
response.ServerError(c, "保存成功但刷新登录风控缓存失败")
return
}
response.ServerError(c, "保存地区屏蔽配置失败")
return
}
shared.OperationLogWithResourceID(c, h.audit, "replace-region-blocks", "login_risk_country_blocks", middleware.CurrentRequestID(c), "success", fmt.Sprintf("keywords=%d whitelist_ips=%d", len(items.Items), len(items.WhitelistItems)))
shared.OperationLogWithResourceID(c, h.audit, "replace-region-blocks", "login_risk_country_blocks", middleware.CurrentRequestID(c), "success", fmt.Sprintf("keywords=%d whitelist_ips=%d whitelist_users=%d", len(items.Items), len(items.WhitelistItems), len(items.WhitelistUserItems)))
response.OK(c, items)
}

View File

@ -6,26 +6,31 @@ import (
"errors"
"net/netip"
"regexp"
"strconv"
"strings"
"time"
"unicode/utf8"
"hyapp-admin-server/internal/appctx"
"hyapp-admin-server/internal/integration/userclient"
)
const (
maxRegionBlockKeywords = 200
maxRegionBlockKeywordLength = 128
maxIPWhitelistItems = 500
maxUserWhitelistItems = 500
)
var (
countryCodePattern = regexp.MustCompile(`^[A-Za-z]{2,3}$`)
errInvalidPayload = errors.New("region block payload invalid")
countryCodePattern = regexp.MustCompile(`^[A-Za-z]{2,3}$`)
errInvalidPayload = errors.New("region block payload invalid")
errWhitelistCacheRefresh = errors.New("login risk whitelist cache refresh failed")
)
type Service struct {
userDB *sql.DB
user userclient.Client
}
type RegionBlock struct {
@ -45,11 +50,21 @@ type IPWhitelistItem struct {
UpdatedAtMS int64 `json:"updated_at_ms"`
}
type UserWhitelistItem struct {
WhitelistID int64 `json:"whitelist_id"`
UserID int64 `json:"user_id,string"`
Enabled bool `json:"enabled"`
CreatedAtMS int64 `json:"created_at_ms"`
UpdatedAtMS int64 `json:"updated_at_ms"`
}
type Config struct {
Items []RegionBlock `json:"items"`
Total int `json:"total"`
WhitelistItems []IPWhitelistItem `json:"whitelist_items"`
WhitelistTotal int `json:"whitelist_total"`
Items []RegionBlock `json:"items"`
Total int `json:"total"`
WhitelistItems []IPWhitelistItem `json:"whitelist_items"`
WhitelistTotal int `json:"whitelist_total"`
WhitelistUserItems []UserWhitelistItem `json:"whitelist_user_items"`
WhitelistUserTotal int `json:"whitelist_user_total"`
}
type normalizedKeyword struct {
@ -61,11 +76,11 @@ type countryCodeQuerier interface {
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}
func NewService(userDB *sql.DB) *Service {
return &Service{userDB: userDB}
func NewService(userDB *sql.DB, user userclient.Client) *Service {
return &Service{userDB: userDB, user: user}
}
// List 返回当前 App 已启用的登录地区屏蔽词和 IP 白名单。
// List 返回当前 App 已启用的登录地区屏蔽词、IP 白名单和用户白名单。
// 表属于 user-service 登录风控事实admin-server 只作为后台维护入口直接写 user DB。
func (s *Service) List(ctx context.Context) (Config, error) {
if s.userDB == nil {
@ -80,12 +95,16 @@ func (s *Service) List(ctx context.Context) (Config, error) {
if err != nil {
return Config{}, err
}
return Config{Items: blocks, Total: len(blocks), WhitelistItems: whitelist, WhitelistTotal: len(whitelist)}, nil
userWhitelist, err := queryEnabledUserWhitelist(ctx, s.userDB, appCode)
if err != nil {
return Config{}, err
}
return Config{Items: blocks, Total: len(blocks), WhitelistItems: whitelist, WhitelistTotal: len(whitelist), WhitelistUserItems: userWhitelist, WhitelistUserTotal: len(userWhitelist)}, nil
}
// Replace 用页面提交的词表整体替换当前 App 的生效配置。
// 整体替换比逐条增删更适合配置页保存语义,也能避免客户端和服务端出现半旧半新的屏蔽词集合。
func (s *Service) Replace(ctx context.Context, actorID int64, keywords []string, whitelistIPs *[]string) (Config, error) {
func (s *Service) Replace(ctx context.Context, requestID string, actorID int64, keywords []string, whitelistIPs *[]string, whitelistUserIDs *[]string) (Config, error) {
if s.userDB == nil {
return Config{}, errors.New("user db is not configured")
}
@ -100,6 +119,13 @@ func (s *Service) Replace(ctx context.Context, actorID int64, keywords []string,
return Config{}, err
}
}
var normalizedUserIDs []int64
if whitelistUserIDs != nil {
normalizedUserIDs, err = normalizeUserIDWhitelist(*whitelistUserIDs)
if err != nil {
return Config{}, err
}
}
tx, err := s.userDB.BeginTx(ctx, nil)
if err != nil {
return Config{}, err
@ -155,9 +181,38 @@ func (s *Service) Replace(ctx context.Context, actorID int64, keywords []string,
}
}
}
if whitelistUserIDs != nil {
if _, err := tx.ExecContext(ctx, `
UPDATE login_risk_user_whitelist
SET enabled = 0, updated_by_user_id = ?, updated_at_ms = ?
WHERE app_code = ? AND enabled = 1
`, nullableActor(actorID), nowMS, appCode); err != nil {
return Config{}, err
}
for _, userID := range normalizedUserIDs {
if _, err := tx.ExecContext(ctx, `
INSERT INTO login_risk_user_whitelist (
app_code, user_id, enabled,
created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms
)
VALUES (?, ?, 1, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
enabled = 1,
updated_by_user_id = VALUES(updated_by_user_id),
updated_at_ms = VALUES(updated_at_ms)
`, appCode, userID, nullableActor(actorID), nullableActor(actorID), nowMS, nowMS); err != nil {
return Config{}, err
}
}
}
if err := tx.Commit(); err != nil {
return Config{}, err
}
if whitelistIPs != nil || whitelistUserIDs != nil {
if err := s.refreshWhitelistCache(ctx, requestID); err != nil {
return Config{}, err
}
}
return s.List(ctx)
}
@ -210,6 +265,44 @@ func normalizeIPWhitelist(raw []string) ([]string, error) {
return result, nil
}
func normalizeUserIDWhitelist(raw []string) ([]int64, error) {
if len(raw) > maxUserWhitelistItems {
return nil, errInvalidPayload
}
result := make([]int64, 0, len(raw))
seen := map[int64]struct{}{}
for _, item := range raw {
value := strings.TrimSpace(item)
if value == "" {
return nil, errInvalidPayload
}
userID, err := strconv.ParseInt(value, 10, 64)
if err != nil || userID <= 0 {
return nil, errInvalidPayload
}
if _, ok := seen[userID]; ok {
continue
}
seen[userID] = struct{}{}
result = append(result, userID)
}
return result, nil
}
func (s *Service) refreshWhitelistCache(ctx context.Context, requestID string) error {
if s.user == nil {
return nil
}
_, err := s.user.RefreshLoginRiskWhitelistCache(ctx, userclient.RefreshLoginRiskWhitelistCacheRequest{
RequestID: requestID,
Caller: "admin-server",
})
if err != nil {
return errWhitelistCacheRefresh
}
return nil
}
func resolveCountryCode(ctx context.Context, querier countryCodeQuerier, appCode string, keyword string) (string, error) {
if countryCodePattern.MatchString(keyword) {
return strings.ToUpper(keyword), nil
@ -290,6 +383,34 @@ func queryEnabledIPWhitelist(ctx context.Context, db *sql.DB, appCode string) ([
return items, nil
}
func queryEnabledUserWhitelist(ctx context.Context, db *sql.DB, appCode string) ([]UserWhitelistItem, error) {
rows, err := db.QueryContext(ctx, `
SELECT whitelist_id, user_id, enabled, created_at_ms, updated_at_ms
FROM login_risk_user_whitelist
WHERE app_code = ? AND enabled = 1
ORDER BY user_id ASC, whitelist_id ASC
`, appCode)
if err != nil {
return nil, err
}
defer rows.Close()
items := make([]UserWhitelistItem, 0)
for rows.Next() {
var item UserWhitelistItem
if err := rows.Scan(&item.WhitelistID, &item.UserID, &item.Enabled, &item.CreatedAtMS, &item.UpdatedAtMS); err != nil {
return nil, err
}
if item.UserID > 0 {
items = append(items, item)
}
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
func nullableActor(actorID int64) any {
if actorID <= 0 {
return nil

View File

@ -0,0 +1,59 @@
package regionblock
import (
"context"
"errors"
"reflect"
"testing"
"hyapp-admin-server/internal/integration/userclient"
)
type fakeWhitelistCacheUserClient struct {
userclient.Client
called bool
err error
}
func (f *fakeWhitelistCacheUserClient) RefreshLoginRiskWhitelistCache(_ context.Context, req userclient.RefreshLoginRiskWhitelistCacheRequest) (*userclient.LoginRiskWhitelistCacheSnapshot, error) {
f.called = true
if req.RequestID != "req-refresh" || req.Caller != "admin-server" {
return nil, errors.New("unexpected refresh request")
}
if f.err != nil {
return nil, f.err
}
return &userclient.LoginRiskWhitelistCacheSnapshot{Refreshed: true, UserWhitelistCount: 2}, nil
}
func TestNormalizeUserIDWhitelistDeduplicatesPositiveIDs(t *testing.T) {
got, err := normalizeUserIDWhitelist([]string{" 900025 ", "900026", "900025"})
if err != nil {
t.Fatalf("normalize user whitelist failed: %v", err)
}
want := []int64{900025, 900026}
if !reflect.DeepEqual(got, want) {
t.Fatalf("normalized user whitelist = %+v, want %+v", got, want)
}
}
func TestNormalizeUserIDWhitelistRejectsInvalidID(t *testing.T) {
for _, raw := range [][]string{{""}, {"0"}, {"-1"}, {"abc"}} {
if _, err := normalizeUserIDWhitelist(raw); !errors.Is(err, errInvalidPayload) {
t.Fatalf("normalize %v error = %v, want errInvalidPayload", raw, err)
}
}
}
func TestRefreshWhitelistCacheMapsUserServiceError(t *testing.T) {
client := &fakeWhitelistCacheUserClient{err: errors.New("rpc down")}
service := NewService(nil, client)
err := service.refreshWhitelistCache(context.Background(), "req-refresh")
if !client.called {
t.Fatal("expected refresh rpc to be called")
}
if !errors.Is(err, errWhitelistCacheRefresh) {
t.Fatalf("refresh error = %v, want errWhitelistCacheRefresh", err)
}
}

View File

@ -1268,3 +1268,18 @@ CREATE TABLE IF NOT EXISTS login_risk_ip_whitelist (
KEY idx_login_risk_ip_whitelist_enabled (app_code, enabled, ip_address),
KEY idx_login_risk_ip_whitelist_updated (app_code, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录风险 IP 白名单表';
CREATE TABLE IF NOT EXISTS login_risk_user_whitelist (
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
whitelist_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '白名单 ID',
user_id BIGINT NOT NULL COMMENT '允许跳过登录地区屏蔽复核的用户 ID',
enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '启用',
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
updated_by_user_id BIGINT NULL COMMENT '更新人用户 ID',
created_at_ms BIGINT NOT NULL COMMENT '创建时间UTC epoch ms',
updated_at_ms BIGINT NOT NULL COMMENT '更新时间UTC epoch ms',
PRIMARY KEY (whitelist_id),
UNIQUE KEY uk_login_risk_user_whitelist_user (app_code, user_id),
KEY idx_login_risk_user_whitelist_enabled (app_code, enabled, user_id),
KEY idx_login_risk_user_whitelist_updated (app_code, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录风险用户白名单表';

View File

@ -83,6 +83,17 @@ type LoginRiskIPWhitelist struct {
UpdatedAtMs int64
}
// LoginRiskUserWhitelist 是后台维护的登录地区屏蔽用户白名单事实。
// 用户 ID 命中后只跳过登录后的地区/IP 复核,不改变账号状态、注册设备限制或登录前 gateway 快拦语义。
type LoginRiskUserWhitelist struct {
AppCode string
WhitelistID int64
UserID int64
Enabled bool
CreatedAtMs int64
UpdatedAtMs int64
}
// RegisterRiskConfig 是注册链路的风控开关集合。
// 当前只包含单设备最大账号数,后续增加注册频率或设备指纹策略时仍可复用同一行 App 配置。
type RegisterRiskConfig struct {

View File

@ -83,6 +83,29 @@ func (c *RedisIPDecisionCache) SetIPWhitelist(ctx context.Context, appCode strin
return c.client.Set(ctx, loginRiskIPWhitelistKey(appCode), raw, ttl).Err()
}
func (c *RedisIPDecisionCache) GetUserWhitelist(ctx context.Context, appCode string) ([]int64, bool, error) {
raw, err := c.client.Get(ctx, loginRiskUserWhitelistKey(appCode)).Result()
if errors.Is(err, redis.Nil) {
return nil, false, nil
}
if err != nil {
return nil, false, err
}
var userIDs []int64
if err := json.Unmarshal([]byte(raw), &userIDs); err != nil {
return nil, false, err
}
return userIDs, true, nil
}
func (c *RedisIPDecisionCache) SetUserWhitelist(ctx context.Context, appCode string, userIDs []int64, ttl time.Duration) error {
raw, err := json.Marshal(userIDs)
if err != nil {
return err
}
return c.client.Set(ctx, loginRiskUserWhitelistKey(appCode), raw, ttl).Err()
}
func (c *RedisIPDecisionCache) GetRegisterRiskConfig(ctx context.Context, appCode string) (authdomain.RegisterRiskConfig, bool, error) {
raw, err := c.client.Get(ctx, registerRiskConfigKey(appCode)).Result()
if errors.Is(err, redis.Nil) {
@ -114,6 +137,10 @@ func loginRiskIPWhitelistKey(appCode string) string {
return "login_risk:ip_whitelist:" + appcode.Normalize(appCode)
}
func loginRiskUserWhitelistKey(appCode string) string {
return "login_risk:user_whitelist:" + appcode.Normalize(appCode)
}
func revokedSessionKey(appCode string, sessionID string) string {
return "auth:revoked_session:" + appcode.Normalize(appCode) + ":" + strings.TrimSpace(sessionID)
}

View File

@ -11,7 +11,19 @@ import (
authdomain "hyapp/services/user-service/internal/domain/auth"
)
const loginRiskIPWhitelistCacheTTL = 30 * time.Second
const (
loginRiskIPWhitelistCacheTTL = 30 * time.Second
loginRiskUserWhitelistCacheTTL = 5 * time.Minute
)
// LoginRiskWhitelistCacheSnapshot 是后台保存配置后主动刷新缓存的结果。
// IP 白名单仍沿用原短 TTL用户白名单按运营要求缓存 5 分钟,避免每个风控任务回源 MySQL。
type LoginRiskWhitelistCacheSnapshot struct {
Refreshed bool
IPWhitelistCount int
UserWhitelistCount int
UserCacheExpiresAtMs int64
}
// ListLoginRiskBlockedCountries 返回当前 App 实际生效的登录地区风控词表。
// 静态配置和后台动态配置都下发给 AppApp 可异步做本地风险提示,最终封禁仍以服务端 worker 为准。
@ -79,6 +91,57 @@ func (s *Service) CheckLoginRiskIPWhitelisted(ctx context.Context, clientIP stri
return false, nil
}
// CheckLoginRiskUserWhitelisted 判断登录用户是否命中后台白名单。
// 该白名单只在 user-service 登录后风控 worker 中使用gateway 登录前没有可信 user_id不能用它跳过入口快拦。
func (s *Service) CheckLoginRiskUserWhitelisted(ctx context.Context, userID int64) (bool, error) {
if userID <= 0 {
return false, nil
}
userIDs, err := s.listLoginRiskUserWhitelist(ctx)
if err != nil {
return false, err
}
for _, item := range userIDs {
if item == userID {
return true, nil
}
}
return false, nil
}
// RefreshLoginRiskWhitelistCache 从 MySQL 读取当前 App 白名单并立即写入 Redis。
// 后台保存直接调用该方法,避免新增白名单后仍等 5 分钟 TTL 自然过期才生效。
func (s *Service) RefreshLoginRiskWhitelistCache(ctx context.Context) (LoginRiskWhitelistCacheSnapshot, error) {
if s.authRepository == nil {
return LoginRiskWhitelistCacheSnapshot{}, nil
}
ips, err := s.loadLoginRiskIPWhitelist(ctx)
if err != nil {
return LoginRiskWhitelistCacheSnapshot{}, err
}
userIDs, err := s.loadLoginRiskUserWhitelist(ctx)
if err != nil {
return LoginRiskWhitelistCacheSnapshot{}, err
}
snapshot := LoginRiskWhitelistCacheSnapshot{
IPWhitelistCount: len(ips),
UserWhitelistCount: len(userIDs),
UserCacheExpiresAtMs: s.now().Add(loginRiskUserWhitelistCacheTTL).UnixMilli(),
}
if s.ipDecisionCache == nil {
return snapshot, nil
}
// IP 和用户白名单共用一次刷新入口;任一缓存写失败都返回错误,让后台保存页能提示重试刷新。
if err := s.ipDecisionCache.SetIPWhitelist(ctx, appcode.FromContext(ctx), ips, loginRiskIPWhitelistCacheTTL); err != nil {
return LoginRiskWhitelistCacheSnapshot{}, err
}
if err := s.ipDecisionCache.SetUserWhitelist(ctx, appcode.FromContext(ctx), userIDs, loginRiskUserWhitelistCacheTTL); err != nil {
return LoginRiskWhitelistCacheSnapshot{}, err
}
snapshot.Refreshed = true
return snapshot, nil
}
func (s *Service) listLoginRiskIPWhitelist(ctx context.Context) ([]string, error) {
appCode := appcode.FromContext(ctx)
if s.ipDecisionCache != nil {
@ -87,6 +150,37 @@ func (s *Service) listLoginRiskIPWhitelist(ctx context.Context) ([]string, error
return normalizeLoginRiskIPList(ips), nil
}
}
ips, err := s.loadLoginRiskIPWhitelist(ctx)
if err != nil {
return nil, err
}
if s.ipDecisionCache != nil {
// 白名单读取结果按 App 整体缓存 30 秒;空列表也缓存,避免无配置时每次登录都回源 DB。
_ = s.ipDecisionCache.SetIPWhitelist(ctx, appCode, ips, loginRiskIPWhitelistCacheTTL)
}
return ips, nil
}
func (s *Service) listLoginRiskUserWhitelist(ctx context.Context) ([]int64, error) {
appCode := appcode.FromContext(ctx)
if s.ipDecisionCache != nil {
userIDs, ok, err := s.ipDecisionCache.GetUserWhitelist(ctx, appCode)
if err == nil && ok {
return normalizeLoginRiskUserIDList(userIDs), nil
}
}
userIDs, err := s.loadLoginRiskUserWhitelist(ctx)
if err != nil {
return nil, err
}
if s.ipDecisionCache != nil {
// 用户白名单按运营要求缓存 5 分钟;空列表也缓存,减少无配置时的任务回源。
_ = s.ipDecisionCache.SetUserWhitelist(ctx, appCode, userIDs, loginRiskUserWhitelistCacheTTL)
}
return userIDs, nil
}
func (s *Service) loadLoginRiskIPWhitelist(ctx context.Context) ([]string, error) {
if s.authRepository == nil {
return nil, nil
}
@ -100,12 +194,24 @@ func (s *Service) listLoginRiskIPWhitelist(ctx context.Context) ([]string, error
ips = append(ips, ip)
}
}
ips = normalizeLoginRiskIPList(ips)
if s.ipDecisionCache != nil {
// 白名单读取结果按 App 整体缓存 30 秒;空列表也缓存,避免无配置时每次登录都回源 DB。
_ = s.ipDecisionCache.SetIPWhitelist(ctx, appCode, ips, loginRiskIPWhitelistCacheTTL)
return normalizeLoginRiskIPList(ips), nil
}
func (s *Service) loadLoginRiskUserWhitelist(ctx context.Context) ([]int64, error) {
if s.authRepository == nil {
return nil, nil
}
return ips, nil
items, err := s.authRepository.ListEnabledLoginRiskUserWhitelist(ctx)
if err != nil {
return nil, err
}
userIDs := make([]int64, 0, len(items))
for _, item := range items {
if item.UserID > 0 {
userIDs = append(userIDs, item.UserID)
}
}
return normalizeLoginRiskUserIDList(userIDs), nil
}
func appendUniqueCountryBlock(blocks []authdomain.LoginRiskCountryBlock, seen map[string]struct{}, block authdomain.LoginRiskCountryBlock) []authdomain.LoginRiskCountryBlock {
@ -167,3 +273,22 @@ func normalizeLoginRiskIPList(raw []string) []string {
sort.Strings(ips)
return ips
}
func normalizeLoginRiskUserIDList(raw []int64) []int64 {
seen := make(map[int64]struct{}, len(raw))
userIDs := make([]int64, 0, len(raw))
for _, userID := range raw {
if userID <= 0 {
continue
}
if _, ok := seen[userID]; ok {
continue
}
seen[userID] = struct{}{}
userIDs = append(userIDs, userID)
}
sort.Slice(userIDs, func(i, j int) bool {
return userIDs[i] < userIDs[j]
})
return userIDs
}

View File

@ -71,6 +71,19 @@ func normalizeLoginIPRiskWorkerOptions(options LoginIPRiskWorkerOptions) LoginIP
func (s *Service) processLoginIPRiskJob(ctx context.Context, job authdomain.LoginIPRiskJob) error {
policy := s.loginRiskPolicy
nowMs := s.now().UnixMilli()
userWhitelisted, err := s.CheckLoginRiskUserWhitelisted(ctx, job.UserID)
if err != nil {
logx.Warn(ctx, "login_user_whitelist_read_failed", slog.String("component", "user_auth_risk"), slog.String("job_id", job.JobID), slog.Int64("user_id", job.UserID), slog.String("error", err.Error()))
}
if userWhitelisted {
// 用户白名单是运营按真实 user_id 做的例外;命中后不再访问 GeoIP也不写 IP 决策缓存,避免把用户级放行扩散到同 IP 其他账号。
return s.applyLoginIPRiskDecision(ctx, job, IPDecision{
Decision: authdomain.LoginIPRiskDecisionAllowed,
Source: "user_whitelist",
CheckedAtMs: nowMs,
ExpiresAtMs: nowMs + loginRiskUserWhitelistCacheTTL.Milliseconds(),
}, nil, authdomain.LoginIPRiskStatusCompleted)
}
whitelisted, err := s.CheckLoginRiskIPWhitelisted(ctx, job.ClientIP)
if err != nil {
logx.Warn(ctx, "login_ip_whitelist_read_failed", slog.String("component", "user_auth_risk"), slog.String("job_id", job.JobID), slog.String("client_ip_hash", job.ClientIPHash), slog.String("error", err.Error()))

View File

@ -88,6 +88,8 @@ type AuthRepository interface {
ListEnabledLoginRiskCountryBlocks(ctx context.Context) ([]authdomain.LoginRiskCountryBlock, error)
// ListEnabledLoginRiskIPWhitelist 返回当前 App 的登录地区屏蔽 IP 白名单。
ListEnabledLoginRiskIPWhitelist(ctx context.Context) ([]authdomain.LoginRiskIPWhitelist, error)
// ListEnabledLoginRiskUserWhitelist 返回当前 App 的登录地区屏蔽用户白名单。
ListEnabledLoginRiskUserWhitelist(ctx context.Context) ([]authdomain.LoginRiskUserWhitelist, error)
// MarkLoginAuditBlocked 把登录成功后被异步风控撤销的审计行更新成阻断态。
MarkLoginAuditBlocked(ctx context.Context, requestID string, userID int64, countryCode string, blockReason string) error
}
@ -177,6 +179,8 @@ type IPDecisionCache interface {
SetRevokedSession(ctx context.Context, appCode string, sessionID string, reason string, ttl time.Duration) error
GetIPWhitelist(ctx context.Context, appCode string) ([]string, bool, error)
SetIPWhitelist(ctx context.Context, appCode string, ips []string, ttl time.Duration) error
GetUserWhitelist(ctx context.Context, appCode string) ([]int64, bool, error)
SetUserWhitelist(ctx context.Context, appCode string, userIDs []int64, ttl time.Duration) error
}
// RegisterRiskConfigCache 是注册风控配置的 Redis 快取边界。

View File

@ -24,10 +24,18 @@ type memoryDecisionCache struct {
ip map[string]authservice.IPDecision
revoked map[string]string
ips map[string][]string
users map[string][]int64
userTTL map[string]time.Duration
}
func newMemoryDecisionCache() *memoryDecisionCache {
return &memoryDecisionCache{ip: make(map[string]authservice.IPDecision), revoked: make(map[string]string), ips: make(map[string][]string)}
return &memoryDecisionCache{
ip: make(map[string]authservice.IPDecision),
revoked: make(map[string]string),
ips: make(map[string][]string),
users: make(map[string][]int64),
userTTL: make(map[string]time.Duration),
}
}
func (c *memoryDecisionCache) GetIPDecision(_ context.Context, appCode string, clientIPHash string) (authservice.IPDecision, bool, error) {
@ -65,6 +73,21 @@ func (c *memoryDecisionCache) SetIPWhitelist(_ context.Context, appCode string,
return nil
}
func (c *memoryDecisionCache) GetUserWhitelist(_ context.Context, appCode string) ([]int64, bool, error) {
c.mu.Lock()
defer c.mu.Unlock()
userIDs, ok := c.users[appCode]
return append([]int64(nil), userIDs...), ok, nil
}
func (c *memoryDecisionCache) SetUserWhitelist(_ context.Context, appCode string, userIDs []int64, ttl time.Duration) error {
c.mu.Lock()
defer c.mu.Unlock()
c.users[appCode] = append([]int64(nil), userIDs...)
c.userTTL[appCode] = ttl
return nil
}
type sequenceIDGenerator struct {
// values 是测试预设 user_id 序列。
values []int64
@ -671,6 +694,81 @@ func TestLoginIPRiskIPWhitelistBypassesBlockedCountry(t *testing.T) {
}
}
func TestLoginIPRiskUserWhitelistBypassesBlockedCountryWithFiveMinuteCache(t *testing.T) {
ctx := context.Background()
repository := mysqltest.NewRepository(t)
seedCountry(t, repository, "CN")
now := time.UnixMilli(1000)
if _, err := repository.RawDB().ExecContext(ctx, `
INSERT INTO login_risk_user_whitelist (
app_code, user_id, enabled, created_at_ms, updated_at_ms
)
VALUES ('lalu', 900025, 1, 1000, 1000)
`); err != nil {
t.Fatalf("seed user whitelist failed: %v", err)
}
cache := newMemoryDecisionCache()
authSvc := newAuthService(repository, &now, []int64{900025}, []string{"100025"},
authservice.WithLoginRiskPolicy(authservice.LoginRiskPolicy{
Enabled: true,
UnsupportedCountries: []string{"CN"},
BlockedTTL: time.Hour,
AllowedTTL: time.Hour,
UnknownTTL: time.Minute,
ProviderTimeout: 50 * time.Millisecond,
ProviderNames: []string{"edge_country"},
DenylistTTL: time.Hour,
}),
authservice.WithIPDecisionCache(cache),
authservice.WithIPGeoProviders(authservice.BuildIPGeoProviders([]string{"edge_country"})),
)
snapshot, err := authSvc.RefreshLoginRiskWhitelistCache(ctx)
if err != nil {
t.Fatalf("refresh whitelist cache failed: %v", err)
}
if !snapshot.Refreshed || snapshot.UserWhitelistCount != 1 || snapshot.UserCacheExpiresAtMs != now.Add(5*time.Minute).UnixMilli() {
t.Fatalf("user whitelist refresh snapshot mismatch: %+v", snapshot)
}
if got := cache.userTTL["lalu"]; got != 5*time.Minute {
t.Fatalf("user whitelist cache ttl = %v, want 5m", got)
}
token, _, err := authSvc.LoginThirdParty(ctx, "wechat", "openid-risk-user-whitelist", thirdPartyRegistration("ios"), authservice.Meta{
AppCode: "lalu",
RequestID: "req-risk-user-whitelist",
ClientIP: "203.0.113.81",
CountryByIP: "CN",
Platform: "ios",
})
if err != nil {
t.Fatalf("LoginThirdParty failed: %v", err)
}
now = time.UnixMilli(2000)
processed, err := authSvc.ProcessLoginIPRiskBatch(ctx, authservice.LoginIPRiskWorkerOptions{WorkerID: "risk-user-whitelist-test", LockTTL: time.Second, BatchSize: 10})
if err != nil || processed != 1 {
t.Fatalf("risk worker mismatch: processed=%d err=%v", processed, err)
}
if _, err := authSvc.RefreshToken(ctx, token.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RequestID: "req-refresh-user-whitelist"}); err != nil {
t.Fatalf("whitelisted user must keep refresh session active: %v", err)
}
if _, ok := cache.ip["lalu:"+authservice.HashLoginRiskIP("203.0.113.81")]; ok {
t.Fatalf("user whitelist must not write ordinary IP decision cache")
}
var decision string
if err := repository.RawDB().QueryRowContext(ctx, `
SELECT decision
FROM login_ip_risk_jobs
WHERE app_code = 'lalu' AND request_id = 'req-risk-user-whitelist'
`).Scan(&decision); err != nil {
t.Fatalf("query risk job failed: %v", err)
}
if decision != "allowed" {
t.Fatalf("whitelisted user risk job decision mismatch: %s", decision)
}
}
func TestLoginIPRiskWorkerRevokesRotatedSameDeviceSessions(t *testing.T) {
// 复现线上竞态:登录后风控任务尚未完成,客户端连续 refresh 轮换 session。
// blocked 决策落地时必须沿源 session 的同设备登录链路清掉后续 session否则最新 access/refresh 仍能继续使用。

View File

@ -161,6 +161,35 @@ func (r *Repository) ListEnabledLoginRiskIPWhitelist(ctx context.Context) ([]aut
return items, nil
}
func (r *Repository) ListEnabledLoginRiskUserWhitelist(ctx context.Context) ([]authdomain.LoginRiskUserWhitelist, error) {
rows, err := r.db.QueryContext(ctx, `
SELECT app_code, whitelist_id, user_id, enabled, created_at_ms, updated_at_ms
FROM login_risk_user_whitelist
WHERE app_code = ? AND enabled = 1
ORDER BY user_id ASC, whitelist_id ASC
`, appcode.FromContext(ctx))
if err != nil {
return nil, err
}
defer rows.Close()
items := make([]authdomain.LoginRiskUserWhitelist, 0)
for rows.Next() {
var item authdomain.LoginRiskUserWhitelist
if err := rows.Scan(&item.AppCode, &item.WhitelistID, &item.UserID, &item.Enabled, &item.CreatedAtMs, &item.UpdatedAtMs); err != nil {
return nil, err
}
if item.UserID <= 0 {
continue
}
items = append(items, item)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
type loginIPRiskJobScanner interface {
Scan(dest ...any) error
}

View File

@ -434,6 +434,11 @@ func (r *Repository) ListEnabledLoginRiskIPWhitelist(ctx context.Context) ([]aut
return r.Repository.AuthRepository().ListEnabledLoginRiskIPWhitelist(ctx)
}
// ListEnabledLoginRiskUserWhitelist 让测试 wrapper 继续满足认证风控接口。
func (r *Repository) ListEnabledLoginRiskUserWhitelist(ctx context.Context) ([]authdomain.LoginRiskUserWhitelist, error) {
return r.Repository.AuthRepository().ListEnabledLoginRiskUserWhitelist(ctx)
}
// MarkLoginAuditBlocked 让测试 wrapper 继续满足认证接口。
func (r *Repository) MarkLoginAuditBlocked(ctx context.Context, requestID string, userID int64, countryCode string, blockReason string) error {
return r.Repository.AuthRepository().MarkLoginAuditBlocked(ctx, requestID, userID, countryCode, blockReason)

View File

@ -264,6 +264,21 @@ func (s *Server) CheckLoginRiskIPWhitelist(ctx context.Context, req *userv1.Chec
return &userv1.CheckLoginRiskIPWhitelistResponse{Whitelisted: whitelisted}, nil
}
// RefreshLoginRiskWhitelistCache 让后台保存白名单后立刻重建 Redis 缓存,避免等待 TTL 自然过期。
func (s *Server) RefreshLoginRiskWhitelistCache(ctx context.Context, req *userv1.RefreshLoginRiskWhitelistCacheRequest) (*userv1.RefreshLoginRiskWhitelistCacheResponse, error) {
ctx = contextWithApp(ctx, req.GetMeta())
snapshot, err := s.authSvc.RefreshLoginRiskWhitelistCache(ctx)
if err != nil {
return nil, xerr.ToGRPCError(err)
}
return &userv1.RefreshLoginRiskWhitelistCacheResponse{
Refreshed: snapshot.Refreshed,
IpWhitelistCount: int32(snapshot.IPWhitelistCount),
UserWhitelistCount: int32(snapshot.UserWhitelistCount),
UserCacheExpiresAtMs: snapshot.UserCacheExpiresAtMs,
}, nil
}
// GetRegisterRiskConfig 返回后台配置页和注册链路共用的设备注册上限。
func (s *Server) GetRegisterRiskConfig(ctx context.Context, req *userv1.GetRegisterRiskConfigRequest) (*userv1.GetRegisterRiskConfigResponse, error) {
ctx = contextWithApp(ctx, req.GetMeta())