diff --git a/api/proto/user/v1/host.pb.go b/api/proto/user/v1/host.pb.go index 00179ab0..c8fe851e 100644 --- a/api/proto/user/v1/host.pb.go +++ b/api/proto/user/v1/host.pb.go @@ -4852,6 +4852,136 @@ func (x *DeleteAgencyResponse) GetAgency() *Agency { return nil } +type SetAgencyStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AdminUserId int64 `protobuf:"varint,3,opt,name=admin_user_id,json=adminUserId,proto3" json:"admin_user_id,omitempty"` + AgencyId int64 `protobuf:"varint,4,opt,name=agency_id,json=agencyId,proto3" json:"agency_id,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` +} + +func (x *SetAgencyStatusRequest) Reset() { + *x = SetAgencyStatusRequest{} + mi := &file_proto_user_v1_host_proto_msgTypes[71] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetAgencyStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetAgencyStatusRequest) ProtoMessage() {} + +func (x *SetAgencyStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[71] + 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 SetAgencyStatusRequest.ProtoReflect.Descriptor instead. +func (*SetAgencyStatusRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{71} +} + +func (x *SetAgencyStatusRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *SetAgencyStatusRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *SetAgencyStatusRequest) GetAdminUserId() int64 { + if x != nil { + return x.AdminUserId + } + return 0 +} + +func (x *SetAgencyStatusRequest) GetAgencyId() int64 { + if x != nil { + return x.AgencyId + } + return 0 +} + +func (x *SetAgencyStatusRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *SetAgencyStatusRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type SetAgencyStatusResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Agency *Agency `protobuf:"bytes,1,opt,name=agency,proto3" json:"agency,omitempty"` +} + +func (x *SetAgencyStatusResponse) Reset() { + *x = SetAgencyStatusResponse{} + mi := &file_proto_user_v1_host_proto_msgTypes[72] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetAgencyStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetAgencyStatusResponse) ProtoMessage() {} + +func (x *SetAgencyStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[72] + 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 SetAgencyStatusResponse.ProtoReflect.Descriptor instead. +func (*SetAgencyStatusResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{72} +} + +func (x *SetAgencyStatusResponse) GetAgency() *Agency { + if x != nil { + return x.Agency + } + return nil +} + type SetAgencyJoinEnabledRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4867,7 +4997,7 @@ type SetAgencyJoinEnabledRequest struct { func (x *SetAgencyJoinEnabledRequest) Reset() { *x = SetAgencyJoinEnabledRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[71] + mi := &file_proto_user_v1_host_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4879,7 +5009,7 @@ func (x *SetAgencyJoinEnabledRequest) String() string { func (*SetAgencyJoinEnabledRequest) ProtoMessage() {} func (x *SetAgencyJoinEnabledRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[71] + mi := &file_proto_user_v1_host_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4892,7 +5022,7 @@ func (x *SetAgencyJoinEnabledRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetAgencyJoinEnabledRequest.ProtoReflect.Descriptor instead. func (*SetAgencyJoinEnabledRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{71} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{73} } func (x *SetAgencyJoinEnabledRequest) GetMeta() *RequestMeta { @@ -4947,7 +5077,7 @@ type SetAgencyJoinEnabledResponse struct { func (x *SetAgencyJoinEnabledResponse) Reset() { *x = SetAgencyJoinEnabledResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[72] + mi := &file_proto_user_v1_host_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4959,7 +5089,7 @@ func (x *SetAgencyJoinEnabledResponse) String() string { func (*SetAgencyJoinEnabledResponse) ProtoMessage() {} func (x *SetAgencyJoinEnabledResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[72] + mi := &file_proto_user_v1_host_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4972,7 +5102,7 @@ func (x *SetAgencyJoinEnabledResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetAgencyJoinEnabledResponse.ProtoReflect.Descriptor instead. func (*SetAgencyJoinEnabledResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{72} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{74} } func (x *SetAgencyJoinEnabledResponse) GetAgency() *Agency { @@ -5776,233 +5906,258 @@ var file_proto_user_v1_host_proto_rawDesc = []byte{ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, - 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xe8, 0x01, 0x0a, 0x1b, 0x53, 0x65, 0x74, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6a, - 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, + 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xd8, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, + 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, + 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, - 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, - 0x79, 0x32, 0xd5, 0x12, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x78, 0x0a, 0x17, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, - 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x4b, 0x69, - 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x24, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, - 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x6f, 0x6e, 0x22, 0x48, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, + 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xe8, 0x01, 0x0a, + 0x1b, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 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, 0x1d, 0x0a, 0x0a, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, + 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x6a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, + 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x32, 0xd5, 0x12, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x53, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, + 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x49, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x12, 0x1e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x5d, 0x0a, 0x0e, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, + 0x74, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, + 0x0a, 0x0c, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x51, 0x0a, 0x0a, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x20, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x42, 0x44, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x42, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x49, 0x6e, 0x76, 0x69, 0x74, + 0x65, 0x42, 0x44, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, + 0x73, 0x74, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x42, + 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, + 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, + 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x4c, 0x69, + 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, - 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x50, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, - 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, - 0x14, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, - 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x22, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, - 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x90, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, - 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, - 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, - 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x63, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x52, 0x6f, + 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 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, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x06, 0x0a, 0x14, 0x55, 0x73, - 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x12, 0x1e, 0x2e, + 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x72, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, + 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, + 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, + 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x90, 0x01, + 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, + 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x69, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, + 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x47, + 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, + 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, + 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x47, 0x65, + 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc6, + 0x07, 0x0a, 0x14, 0x55, 0x73, 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x42, 0x44, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x10, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, - 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, - 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x53, 0x65, 0x74, - 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, + 0x0a, 0x13, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, + 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x43, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x54, 0x0a, 0x0b, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, - 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x6f, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, - 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, - 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, - 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 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, + 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2a, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 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 ( @@ -6017,7 +6172,7 @@ func file_proto_user_v1_host_proto_rawDescGZIP() []byte { return file_proto_user_v1_host_proto_rawDescData } -var file_proto_user_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 74) +var file_proto_user_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 76) var file_proto_user_v1_host_proto_goTypes = []any{ (*HostProfile)(nil), // 0: hyapp.user.v1.HostProfile (*Agency)(nil), // 1: hyapp.user.v1.Agency @@ -6090,154 +6245,160 @@ var file_proto_user_v1_host_proto_goTypes = []any{ (*CloseAgencyResponse)(nil), // 68: hyapp.user.v1.CloseAgencyResponse (*DeleteAgencyRequest)(nil), // 69: hyapp.user.v1.DeleteAgencyRequest (*DeleteAgencyResponse)(nil), // 70: hyapp.user.v1.DeleteAgencyResponse - (*SetAgencyJoinEnabledRequest)(nil), // 71: hyapp.user.v1.SetAgencyJoinEnabledRequest - (*SetAgencyJoinEnabledResponse)(nil), // 72: hyapp.user.v1.SetAgencyJoinEnabledResponse - nil, // 73: hyapp.user.v1.BatchGetHostProfilesResponse.HostProfilesEntry - (*RequestMeta)(nil), // 74: hyapp.user.v1.RequestMeta + (*SetAgencyStatusRequest)(nil), // 71: hyapp.user.v1.SetAgencyStatusRequest + (*SetAgencyStatusResponse)(nil), // 72: hyapp.user.v1.SetAgencyStatusResponse + (*SetAgencyJoinEnabledRequest)(nil), // 73: hyapp.user.v1.SetAgencyJoinEnabledRequest + (*SetAgencyJoinEnabledResponse)(nil), // 74: hyapp.user.v1.SetAgencyJoinEnabledResponse + nil, // 75: hyapp.user.v1.BatchGetHostProfilesResponse.HostProfilesEntry + (*RequestMeta)(nil), // 76: hyapp.user.v1.RequestMeta } var file_proto_user_v1_host_proto_depIdxs = []int32{ - 74, // 0: hyapp.user.v1.SearchAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 0: hyapp.user.v1.SearchAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 1: hyapp.user.v1.SearchAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 74, // 2: hyapp.user.v1.ApplyToAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 2: hyapp.user.v1.ApplyToAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 3: hyapp.user.v1.ApplyToAgencyResponse.application:type_name -> hyapp.user.v1.AgencyApplication - 74, // 4: hyapp.user.v1.ReviewAgencyApplicationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 4: hyapp.user.v1.ReviewAgencyApplicationRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 5: hyapp.user.v1.ReviewAgencyApplicationResponse.application:type_name -> hyapp.user.v1.AgencyApplication 0, // 6: hyapp.user.v1.ReviewAgencyApplicationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile 6, // 7: hyapp.user.v1.ReviewAgencyApplicationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 74, // 8: hyapp.user.v1.KickAgencyHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 8: hyapp.user.v1.KickAgencyHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta 6, // 9: hyapp.user.v1.KickAgencyHostResponse.membership:type_name -> hyapp.user.v1.AgencyMembership 0, // 10: hyapp.user.v1.KickAgencyHostResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 74, // 11: hyapp.user.v1.InviteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 11: hyapp.user.v1.InviteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 12: hyapp.user.v1.InviteAgencyResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 74, // 13: hyapp.user.v1.InviteBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 13: hyapp.user.v1.InviteBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 14: hyapp.user.v1.InviteBDResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 74, // 15: hyapp.user.v1.InviteHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 15: hyapp.user.v1.InviteHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 16: hyapp.user.v1.InviteHostResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 74, // 17: hyapp.user.v1.ListBDLeaderBDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 17: hyapp.user.v1.ListBDLeaderBDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 18: hyapp.user.v1.ListBDLeaderBDsResponse.bd_profiles:type_name -> hyapp.user.v1.BDProfile - 74, // 19: hyapp.user.v1.ListBDLeaderAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 19: hyapp.user.v1.ListBDLeaderAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 20: hyapp.user.v1.ListBDLeaderAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 74, // 21: hyapp.user.v1.ListBDAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 21: hyapp.user.v1.ListBDAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 22: hyapp.user.v1.ListBDAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 74, // 23: hyapp.user.v1.ListRoleInvitationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 23: hyapp.user.v1.ListRoleInvitationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 24: hyapp.user.v1.ListRoleInvitationsResponse.invitations:type_name -> hyapp.user.v1.RoleInvitation - 74, // 25: hyapp.user.v1.GetRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 25: hyapp.user.v1.GetRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 26: hyapp.user.v1.GetRoleInvitationResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 74, // 27: hyapp.user.v1.ProcessRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 27: hyapp.user.v1.ProcessRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 28: hyapp.user.v1.ProcessRoleInvitationResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation 0, // 29: hyapp.user.v1.ProcessRoleInvitationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile 1, // 30: hyapp.user.v1.ProcessRoleInvitationResponse.agency:type_name -> hyapp.user.v1.Agency 6, // 31: hyapp.user.v1.ProcessRoleInvitationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership 2, // 32: hyapp.user.v1.ProcessRoleInvitationResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 74, // 33: hyapp.user.v1.GetHostProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 33: hyapp.user.v1.GetHostProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta 0, // 34: hyapp.user.v1.GetHostProfileResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 74, // 35: hyapp.user.v1.BatchGetHostProfilesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 73, // 36: hyapp.user.v1.BatchGetHostProfilesResponse.host_profiles:type_name -> hyapp.user.v1.BatchGetHostProfilesResponse.HostProfilesEntry - 74, // 37: hyapp.user.v1.GetBDProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 35: hyapp.user.v1.BatchGetHostProfilesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 75, // 36: hyapp.user.v1.BatchGetHostProfilesResponse.host_profiles:type_name -> hyapp.user.v1.BatchGetHostProfilesResponse.HostProfilesEntry + 76, // 37: hyapp.user.v1.GetBDProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 38: hyapp.user.v1.GetBDProfileResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 74, // 39: hyapp.user.v1.GetCoinSellerProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 39: hyapp.user.v1.GetCoinSellerProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta 3, // 40: hyapp.user.v1.GetCoinSellerProfileResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 74, // 41: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 41: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta 4, // 42: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse.coin_sellers:type_name -> hyapp.user.v1.CoinSellerListItem - 74, // 43: hyapp.user.v1.GetUserRoleSummaryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 43: hyapp.user.v1.GetUserRoleSummaryRequest.meta:type_name -> hyapp.user.v1.RequestMeta 5, // 44: hyapp.user.v1.GetUserRoleSummaryResponse.summary:type_name -> hyapp.user.v1.UserRoleSummary - 74, // 45: hyapp.user.v1.GetAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 45: hyapp.user.v1.GetAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 46: hyapp.user.v1.GetAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 74, // 47: hyapp.user.v1.CheckBusinessCapabilityRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 74, // 48: hyapp.user.v1.GetAgencyMembersRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 47: hyapp.user.v1.CheckBusinessCapabilityRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 48: hyapp.user.v1.GetAgencyMembersRequest.meta:type_name -> hyapp.user.v1.RequestMeta 6, // 49: hyapp.user.v1.GetAgencyMembersResponse.memberships:type_name -> hyapp.user.v1.AgencyMembership - 74, // 50: hyapp.user.v1.GetAgencyApplicationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 50: hyapp.user.v1.GetAgencyApplicationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 51: hyapp.user.v1.GetAgencyApplicationsResponse.applications:type_name -> hyapp.user.v1.AgencyApplication - 74, // 52: hyapp.user.v1.CreateBDLeaderRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 52: hyapp.user.v1.CreateBDLeaderRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 53: hyapp.user.v1.CreateBDLeaderResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 74, // 54: hyapp.user.v1.CreateBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 54: hyapp.user.v1.CreateBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 55: hyapp.user.v1.CreateBDResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 74, // 56: hyapp.user.v1.SetBDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 56: hyapp.user.v1.SetBDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 57: hyapp.user.v1.SetBDStatusResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 74, // 58: hyapp.user.v1.CreateCoinSellerRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 58: hyapp.user.v1.CreateCoinSellerRequest.meta:type_name -> hyapp.user.v1.RequestMeta 3, // 59: hyapp.user.v1.CreateCoinSellerResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 74, // 60: hyapp.user.v1.SetCoinSellerStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 60: hyapp.user.v1.SetCoinSellerStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta 3, // 61: hyapp.user.v1.SetCoinSellerStatusResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 74, // 62: hyapp.user.v1.CreateAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 62: hyapp.user.v1.CreateAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 63: hyapp.user.v1.CreateAgencyResponse.agency:type_name -> hyapp.user.v1.Agency 0, // 64: hyapp.user.v1.CreateAgencyResponse.host_profile:type_name -> hyapp.user.v1.HostProfile 6, // 65: hyapp.user.v1.CreateAgencyResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 74, // 66: hyapp.user.v1.CloseAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 66: hyapp.user.v1.CloseAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 67: hyapp.user.v1.CloseAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 74, // 68: hyapp.user.v1.DeleteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 76, // 68: hyapp.user.v1.DeleteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 69: hyapp.user.v1.DeleteAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 74, // 70: hyapp.user.v1.SetAgencyJoinEnabledRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 71: hyapp.user.v1.SetAgencyJoinEnabledResponse.agency:type_name -> hyapp.user.v1.Agency - 0, // 72: hyapp.user.v1.BatchGetHostProfilesResponse.HostProfilesEntry.value:type_name -> hyapp.user.v1.HostProfile - 9, // 73: hyapp.user.v1.UserHostService.SearchAgencies:input_type -> hyapp.user.v1.SearchAgenciesRequest - 11, // 74: hyapp.user.v1.UserHostService.ApplyToAgency:input_type -> hyapp.user.v1.ApplyToAgencyRequest - 13, // 75: hyapp.user.v1.UserHostService.ReviewAgencyApplication:input_type -> hyapp.user.v1.ReviewAgencyApplicationRequest - 15, // 76: hyapp.user.v1.UserHostService.KickAgencyHost:input_type -> hyapp.user.v1.KickAgencyHostRequest - 17, // 77: hyapp.user.v1.UserHostService.InviteAgency:input_type -> hyapp.user.v1.InviteAgencyRequest - 19, // 78: hyapp.user.v1.UserHostService.InviteBD:input_type -> hyapp.user.v1.InviteBDRequest - 21, // 79: hyapp.user.v1.UserHostService.InviteHost:input_type -> hyapp.user.v1.InviteHostRequest - 23, // 80: hyapp.user.v1.UserHostService.ListBDLeaderBDs:input_type -> hyapp.user.v1.ListBDLeaderBDsRequest - 25, // 81: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:input_type -> hyapp.user.v1.ListBDLeaderAgenciesRequest - 27, // 82: hyapp.user.v1.UserHostService.ListBDAgencies:input_type -> hyapp.user.v1.ListBDAgenciesRequest - 29, // 83: hyapp.user.v1.UserHostService.ListRoleInvitations:input_type -> hyapp.user.v1.ListRoleInvitationsRequest - 31, // 84: hyapp.user.v1.UserHostService.GetRoleInvitation:input_type -> hyapp.user.v1.GetRoleInvitationRequest - 33, // 85: hyapp.user.v1.UserHostService.ProcessRoleInvitation:input_type -> hyapp.user.v1.ProcessRoleInvitationRequest - 35, // 86: hyapp.user.v1.UserHostService.GetHostProfile:input_type -> hyapp.user.v1.GetHostProfileRequest - 37, // 87: hyapp.user.v1.UserHostService.BatchGetHostProfiles:input_type -> hyapp.user.v1.BatchGetHostProfilesRequest - 39, // 88: hyapp.user.v1.UserHostService.GetBDProfile:input_type -> hyapp.user.v1.GetBDProfileRequest - 41, // 89: hyapp.user.v1.UserHostService.GetCoinSellerProfile:input_type -> hyapp.user.v1.GetCoinSellerProfileRequest - 43, // 90: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:input_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest - 45, // 91: hyapp.user.v1.UserHostService.GetUserRoleSummary:input_type -> hyapp.user.v1.GetUserRoleSummaryRequest - 47, // 92: hyapp.user.v1.UserHostService.GetAgency:input_type -> hyapp.user.v1.GetAgencyRequest - 49, // 93: hyapp.user.v1.UserHostService.CheckBusinessCapability:input_type -> hyapp.user.v1.CheckBusinessCapabilityRequest - 51, // 94: hyapp.user.v1.UserHostService.GetAgencyMembers:input_type -> hyapp.user.v1.GetAgencyMembersRequest - 53, // 95: hyapp.user.v1.UserHostService.GetAgencyApplications:input_type -> hyapp.user.v1.GetAgencyApplicationsRequest - 55, // 96: hyapp.user.v1.UserHostAdminService.CreateBDLeader:input_type -> hyapp.user.v1.CreateBDLeaderRequest - 57, // 97: hyapp.user.v1.UserHostAdminService.CreateBD:input_type -> hyapp.user.v1.CreateBDRequest - 59, // 98: hyapp.user.v1.UserHostAdminService.SetBDStatus:input_type -> hyapp.user.v1.SetBDStatusRequest - 61, // 99: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:input_type -> hyapp.user.v1.CreateCoinSellerRequest - 63, // 100: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:input_type -> hyapp.user.v1.SetCoinSellerStatusRequest - 65, // 101: hyapp.user.v1.UserHostAdminService.CreateAgency:input_type -> hyapp.user.v1.CreateAgencyRequest - 67, // 102: hyapp.user.v1.UserHostAdminService.CloseAgency:input_type -> hyapp.user.v1.CloseAgencyRequest - 69, // 103: hyapp.user.v1.UserHostAdminService.DeleteAgency:input_type -> hyapp.user.v1.DeleteAgencyRequest - 71, // 104: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:input_type -> hyapp.user.v1.SetAgencyJoinEnabledRequest - 10, // 105: hyapp.user.v1.UserHostService.SearchAgencies:output_type -> hyapp.user.v1.SearchAgenciesResponse - 12, // 106: hyapp.user.v1.UserHostService.ApplyToAgency:output_type -> hyapp.user.v1.ApplyToAgencyResponse - 14, // 107: hyapp.user.v1.UserHostService.ReviewAgencyApplication:output_type -> hyapp.user.v1.ReviewAgencyApplicationResponse - 16, // 108: hyapp.user.v1.UserHostService.KickAgencyHost:output_type -> hyapp.user.v1.KickAgencyHostResponse - 18, // 109: hyapp.user.v1.UserHostService.InviteAgency:output_type -> hyapp.user.v1.InviteAgencyResponse - 20, // 110: hyapp.user.v1.UserHostService.InviteBD:output_type -> hyapp.user.v1.InviteBDResponse - 22, // 111: hyapp.user.v1.UserHostService.InviteHost:output_type -> hyapp.user.v1.InviteHostResponse - 24, // 112: hyapp.user.v1.UserHostService.ListBDLeaderBDs:output_type -> hyapp.user.v1.ListBDLeaderBDsResponse - 26, // 113: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:output_type -> hyapp.user.v1.ListBDLeaderAgenciesResponse - 28, // 114: hyapp.user.v1.UserHostService.ListBDAgencies:output_type -> hyapp.user.v1.ListBDAgenciesResponse - 30, // 115: hyapp.user.v1.UserHostService.ListRoleInvitations:output_type -> hyapp.user.v1.ListRoleInvitationsResponse - 32, // 116: hyapp.user.v1.UserHostService.GetRoleInvitation:output_type -> hyapp.user.v1.GetRoleInvitationResponse - 34, // 117: hyapp.user.v1.UserHostService.ProcessRoleInvitation:output_type -> hyapp.user.v1.ProcessRoleInvitationResponse - 36, // 118: hyapp.user.v1.UserHostService.GetHostProfile:output_type -> hyapp.user.v1.GetHostProfileResponse - 38, // 119: hyapp.user.v1.UserHostService.BatchGetHostProfiles:output_type -> hyapp.user.v1.BatchGetHostProfilesResponse - 40, // 120: hyapp.user.v1.UserHostService.GetBDProfile:output_type -> hyapp.user.v1.GetBDProfileResponse - 42, // 121: hyapp.user.v1.UserHostService.GetCoinSellerProfile:output_type -> hyapp.user.v1.GetCoinSellerProfileResponse - 44, // 122: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:output_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse - 46, // 123: hyapp.user.v1.UserHostService.GetUserRoleSummary:output_type -> hyapp.user.v1.GetUserRoleSummaryResponse - 48, // 124: hyapp.user.v1.UserHostService.GetAgency:output_type -> hyapp.user.v1.GetAgencyResponse - 50, // 125: hyapp.user.v1.UserHostService.CheckBusinessCapability:output_type -> hyapp.user.v1.CheckBusinessCapabilityResponse - 52, // 126: hyapp.user.v1.UserHostService.GetAgencyMembers:output_type -> hyapp.user.v1.GetAgencyMembersResponse - 54, // 127: hyapp.user.v1.UserHostService.GetAgencyApplications:output_type -> hyapp.user.v1.GetAgencyApplicationsResponse - 56, // 128: hyapp.user.v1.UserHostAdminService.CreateBDLeader:output_type -> hyapp.user.v1.CreateBDLeaderResponse - 58, // 129: hyapp.user.v1.UserHostAdminService.CreateBD:output_type -> hyapp.user.v1.CreateBDResponse - 60, // 130: hyapp.user.v1.UserHostAdminService.SetBDStatus:output_type -> hyapp.user.v1.SetBDStatusResponse - 62, // 131: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:output_type -> hyapp.user.v1.CreateCoinSellerResponse - 64, // 132: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:output_type -> hyapp.user.v1.SetCoinSellerStatusResponse - 66, // 133: hyapp.user.v1.UserHostAdminService.CreateAgency:output_type -> hyapp.user.v1.CreateAgencyResponse - 68, // 134: hyapp.user.v1.UserHostAdminService.CloseAgency:output_type -> hyapp.user.v1.CloseAgencyResponse - 70, // 135: hyapp.user.v1.UserHostAdminService.DeleteAgency:output_type -> hyapp.user.v1.DeleteAgencyResponse - 72, // 136: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:output_type -> hyapp.user.v1.SetAgencyJoinEnabledResponse - 105, // [105:137] is the sub-list for method output_type - 73, // [73:105] is the sub-list for method input_type - 73, // [73:73] is the sub-list for extension type_name - 73, // [73:73] is the sub-list for extension extendee - 0, // [0:73] is the sub-list for field type_name + 76, // 70: hyapp.user.v1.SetAgencyStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 71: hyapp.user.v1.SetAgencyStatusResponse.agency:type_name -> hyapp.user.v1.Agency + 76, // 72: hyapp.user.v1.SetAgencyJoinEnabledRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 73: hyapp.user.v1.SetAgencyJoinEnabledResponse.agency:type_name -> hyapp.user.v1.Agency + 0, // 74: hyapp.user.v1.BatchGetHostProfilesResponse.HostProfilesEntry.value:type_name -> hyapp.user.v1.HostProfile + 9, // 75: hyapp.user.v1.UserHostService.SearchAgencies:input_type -> hyapp.user.v1.SearchAgenciesRequest + 11, // 76: hyapp.user.v1.UserHostService.ApplyToAgency:input_type -> hyapp.user.v1.ApplyToAgencyRequest + 13, // 77: hyapp.user.v1.UserHostService.ReviewAgencyApplication:input_type -> hyapp.user.v1.ReviewAgencyApplicationRequest + 15, // 78: hyapp.user.v1.UserHostService.KickAgencyHost:input_type -> hyapp.user.v1.KickAgencyHostRequest + 17, // 79: hyapp.user.v1.UserHostService.InviteAgency:input_type -> hyapp.user.v1.InviteAgencyRequest + 19, // 80: hyapp.user.v1.UserHostService.InviteBD:input_type -> hyapp.user.v1.InviteBDRequest + 21, // 81: hyapp.user.v1.UserHostService.InviteHost:input_type -> hyapp.user.v1.InviteHostRequest + 23, // 82: hyapp.user.v1.UserHostService.ListBDLeaderBDs:input_type -> hyapp.user.v1.ListBDLeaderBDsRequest + 25, // 83: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:input_type -> hyapp.user.v1.ListBDLeaderAgenciesRequest + 27, // 84: hyapp.user.v1.UserHostService.ListBDAgencies:input_type -> hyapp.user.v1.ListBDAgenciesRequest + 29, // 85: hyapp.user.v1.UserHostService.ListRoleInvitations:input_type -> hyapp.user.v1.ListRoleInvitationsRequest + 31, // 86: hyapp.user.v1.UserHostService.GetRoleInvitation:input_type -> hyapp.user.v1.GetRoleInvitationRequest + 33, // 87: hyapp.user.v1.UserHostService.ProcessRoleInvitation:input_type -> hyapp.user.v1.ProcessRoleInvitationRequest + 35, // 88: hyapp.user.v1.UserHostService.GetHostProfile:input_type -> hyapp.user.v1.GetHostProfileRequest + 37, // 89: hyapp.user.v1.UserHostService.BatchGetHostProfiles:input_type -> hyapp.user.v1.BatchGetHostProfilesRequest + 39, // 90: hyapp.user.v1.UserHostService.GetBDProfile:input_type -> hyapp.user.v1.GetBDProfileRequest + 41, // 91: hyapp.user.v1.UserHostService.GetCoinSellerProfile:input_type -> hyapp.user.v1.GetCoinSellerProfileRequest + 43, // 92: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:input_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest + 45, // 93: hyapp.user.v1.UserHostService.GetUserRoleSummary:input_type -> hyapp.user.v1.GetUserRoleSummaryRequest + 47, // 94: hyapp.user.v1.UserHostService.GetAgency:input_type -> hyapp.user.v1.GetAgencyRequest + 49, // 95: hyapp.user.v1.UserHostService.CheckBusinessCapability:input_type -> hyapp.user.v1.CheckBusinessCapabilityRequest + 51, // 96: hyapp.user.v1.UserHostService.GetAgencyMembers:input_type -> hyapp.user.v1.GetAgencyMembersRequest + 53, // 97: hyapp.user.v1.UserHostService.GetAgencyApplications:input_type -> hyapp.user.v1.GetAgencyApplicationsRequest + 55, // 98: hyapp.user.v1.UserHostAdminService.CreateBDLeader:input_type -> hyapp.user.v1.CreateBDLeaderRequest + 57, // 99: hyapp.user.v1.UserHostAdminService.CreateBD:input_type -> hyapp.user.v1.CreateBDRequest + 59, // 100: hyapp.user.v1.UserHostAdminService.SetBDStatus:input_type -> hyapp.user.v1.SetBDStatusRequest + 61, // 101: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:input_type -> hyapp.user.v1.CreateCoinSellerRequest + 63, // 102: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:input_type -> hyapp.user.v1.SetCoinSellerStatusRequest + 65, // 103: hyapp.user.v1.UserHostAdminService.CreateAgency:input_type -> hyapp.user.v1.CreateAgencyRequest + 67, // 104: hyapp.user.v1.UserHostAdminService.CloseAgency:input_type -> hyapp.user.v1.CloseAgencyRequest + 69, // 105: hyapp.user.v1.UserHostAdminService.DeleteAgency:input_type -> hyapp.user.v1.DeleteAgencyRequest + 71, // 106: hyapp.user.v1.UserHostAdminService.SetAgencyStatus:input_type -> hyapp.user.v1.SetAgencyStatusRequest + 73, // 107: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:input_type -> hyapp.user.v1.SetAgencyJoinEnabledRequest + 10, // 108: hyapp.user.v1.UserHostService.SearchAgencies:output_type -> hyapp.user.v1.SearchAgenciesResponse + 12, // 109: hyapp.user.v1.UserHostService.ApplyToAgency:output_type -> hyapp.user.v1.ApplyToAgencyResponse + 14, // 110: hyapp.user.v1.UserHostService.ReviewAgencyApplication:output_type -> hyapp.user.v1.ReviewAgencyApplicationResponse + 16, // 111: hyapp.user.v1.UserHostService.KickAgencyHost:output_type -> hyapp.user.v1.KickAgencyHostResponse + 18, // 112: hyapp.user.v1.UserHostService.InviteAgency:output_type -> hyapp.user.v1.InviteAgencyResponse + 20, // 113: hyapp.user.v1.UserHostService.InviteBD:output_type -> hyapp.user.v1.InviteBDResponse + 22, // 114: hyapp.user.v1.UserHostService.InviteHost:output_type -> hyapp.user.v1.InviteHostResponse + 24, // 115: hyapp.user.v1.UserHostService.ListBDLeaderBDs:output_type -> hyapp.user.v1.ListBDLeaderBDsResponse + 26, // 116: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:output_type -> hyapp.user.v1.ListBDLeaderAgenciesResponse + 28, // 117: hyapp.user.v1.UserHostService.ListBDAgencies:output_type -> hyapp.user.v1.ListBDAgenciesResponse + 30, // 118: hyapp.user.v1.UserHostService.ListRoleInvitations:output_type -> hyapp.user.v1.ListRoleInvitationsResponse + 32, // 119: hyapp.user.v1.UserHostService.GetRoleInvitation:output_type -> hyapp.user.v1.GetRoleInvitationResponse + 34, // 120: hyapp.user.v1.UserHostService.ProcessRoleInvitation:output_type -> hyapp.user.v1.ProcessRoleInvitationResponse + 36, // 121: hyapp.user.v1.UserHostService.GetHostProfile:output_type -> hyapp.user.v1.GetHostProfileResponse + 38, // 122: hyapp.user.v1.UserHostService.BatchGetHostProfiles:output_type -> hyapp.user.v1.BatchGetHostProfilesResponse + 40, // 123: hyapp.user.v1.UserHostService.GetBDProfile:output_type -> hyapp.user.v1.GetBDProfileResponse + 42, // 124: hyapp.user.v1.UserHostService.GetCoinSellerProfile:output_type -> hyapp.user.v1.GetCoinSellerProfileResponse + 44, // 125: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:output_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse + 46, // 126: hyapp.user.v1.UserHostService.GetUserRoleSummary:output_type -> hyapp.user.v1.GetUserRoleSummaryResponse + 48, // 127: hyapp.user.v1.UserHostService.GetAgency:output_type -> hyapp.user.v1.GetAgencyResponse + 50, // 128: hyapp.user.v1.UserHostService.CheckBusinessCapability:output_type -> hyapp.user.v1.CheckBusinessCapabilityResponse + 52, // 129: hyapp.user.v1.UserHostService.GetAgencyMembers:output_type -> hyapp.user.v1.GetAgencyMembersResponse + 54, // 130: hyapp.user.v1.UserHostService.GetAgencyApplications:output_type -> hyapp.user.v1.GetAgencyApplicationsResponse + 56, // 131: hyapp.user.v1.UserHostAdminService.CreateBDLeader:output_type -> hyapp.user.v1.CreateBDLeaderResponse + 58, // 132: hyapp.user.v1.UserHostAdminService.CreateBD:output_type -> hyapp.user.v1.CreateBDResponse + 60, // 133: hyapp.user.v1.UserHostAdminService.SetBDStatus:output_type -> hyapp.user.v1.SetBDStatusResponse + 62, // 134: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:output_type -> hyapp.user.v1.CreateCoinSellerResponse + 64, // 135: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:output_type -> hyapp.user.v1.SetCoinSellerStatusResponse + 66, // 136: hyapp.user.v1.UserHostAdminService.CreateAgency:output_type -> hyapp.user.v1.CreateAgencyResponse + 68, // 137: hyapp.user.v1.UserHostAdminService.CloseAgency:output_type -> hyapp.user.v1.CloseAgencyResponse + 70, // 138: hyapp.user.v1.UserHostAdminService.DeleteAgency:output_type -> hyapp.user.v1.DeleteAgencyResponse + 72, // 139: hyapp.user.v1.UserHostAdminService.SetAgencyStatus:output_type -> hyapp.user.v1.SetAgencyStatusResponse + 74, // 140: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:output_type -> hyapp.user.v1.SetAgencyJoinEnabledResponse + 108, // [108:141] is the sub-list for method output_type + 75, // [75:108] is the sub-list for method input_type + 75, // [75:75] is the sub-list for extension type_name + 75, // [75:75] is the sub-list for extension extendee + 0, // [0:75] is the sub-list for field type_name } func init() { file_proto_user_v1_host_proto_init() } @@ -6252,7 +6413,7 @@ func file_proto_user_v1_host_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_user_v1_host_proto_rawDesc, NumEnums: 0, - NumMessages: 74, + NumMessages: 76, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/user/v1/host.proto b/api/proto/user/v1/host.proto index 00313fbe..690e7d7b 100644 --- a/api/proto/user/v1/host.proto +++ b/api/proto/user/v1/host.proto @@ -506,6 +506,19 @@ message DeleteAgencyResponse { Agency agency = 1; } +message SetAgencyStatusRequest { + RequestMeta meta = 1; + string command_id = 2; + int64 admin_user_id = 3; + int64 agency_id = 4; + string status = 5; + string reason = 6; +} + +message SetAgencyStatusResponse { + Agency agency = 1; +} + message SetAgencyJoinEnabledRequest { RequestMeta meta = 1; string command_id = 2; @@ -556,5 +569,6 @@ service UserHostAdminService { rpc CreateAgency(CreateAgencyRequest) returns (CreateAgencyResponse); rpc CloseAgency(CloseAgencyRequest) returns (CloseAgencyResponse); rpc DeleteAgency(DeleteAgencyRequest) returns (DeleteAgencyResponse); + rpc SetAgencyStatus(SetAgencyStatusRequest) returns (SetAgencyStatusResponse); rpc SetAgencyJoinEnabled(SetAgencyJoinEnabledRequest) returns (SetAgencyJoinEnabledResponse); } diff --git a/api/proto/user/v1/host_grpc.pb.go b/api/proto/user/v1/host_grpc.pb.go index 083ec670..042f4830 100644 --- a/api/proto/user/v1/host_grpc.pb.go +++ b/api/proto/user/v1/host_grpc.pb.go @@ -969,6 +969,7 @@ const ( UserHostAdminService_CreateAgency_FullMethodName = "/hyapp.user.v1.UserHostAdminService/CreateAgency" UserHostAdminService_CloseAgency_FullMethodName = "/hyapp.user.v1.UserHostAdminService/CloseAgency" UserHostAdminService_DeleteAgency_FullMethodName = "/hyapp.user.v1.UserHostAdminService/DeleteAgency" + UserHostAdminService_SetAgencyStatus_FullMethodName = "/hyapp.user.v1.UserHostAdminService/SetAgencyStatus" UserHostAdminService_SetAgencyJoinEnabled_FullMethodName = "/hyapp.user.v1.UserHostAdminService/SetAgencyJoinEnabled" ) @@ -986,6 +987,7 @@ type UserHostAdminServiceClient interface { CreateAgency(ctx context.Context, in *CreateAgencyRequest, opts ...grpc.CallOption) (*CreateAgencyResponse, error) CloseAgency(ctx context.Context, in *CloseAgencyRequest, opts ...grpc.CallOption) (*CloseAgencyResponse, error) DeleteAgency(ctx context.Context, in *DeleteAgencyRequest, opts ...grpc.CallOption) (*DeleteAgencyResponse, error) + SetAgencyStatus(ctx context.Context, in *SetAgencyStatusRequest, opts ...grpc.CallOption) (*SetAgencyStatusResponse, error) SetAgencyJoinEnabled(ctx context.Context, in *SetAgencyJoinEnabledRequest, opts ...grpc.CallOption) (*SetAgencyJoinEnabledResponse, error) } @@ -1077,6 +1079,16 @@ func (c *userHostAdminServiceClient) DeleteAgency(ctx context.Context, in *Delet return out, nil } +func (c *userHostAdminServiceClient) SetAgencyStatus(ctx context.Context, in *SetAgencyStatusRequest, opts ...grpc.CallOption) (*SetAgencyStatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SetAgencyStatusResponse) + err := c.cc.Invoke(ctx, UserHostAdminService_SetAgencyStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userHostAdminServiceClient) SetAgencyJoinEnabled(ctx context.Context, in *SetAgencyJoinEnabledRequest, opts ...grpc.CallOption) (*SetAgencyJoinEnabledResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SetAgencyJoinEnabledResponse) @@ -1101,6 +1113,7 @@ type UserHostAdminServiceServer interface { CreateAgency(context.Context, *CreateAgencyRequest) (*CreateAgencyResponse, error) CloseAgency(context.Context, *CloseAgencyRequest) (*CloseAgencyResponse, error) DeleteAgency(context.Context, *DeleteAgencyRequest) (*DeleteAgencyResponse, error) + SetAgencyStatus(context.Context, *SetAgencyStatusRequest) (*SetAgencyStatusResponse, error) SetAgencyJoinEnabled(context.Context, *SetAgencyJoinEnabledRequest) (*SetAgencyJoinEnabledResponse, error) mustEmbedUnimplementedUserHostAdminServiceServer() } @@ -1136,6 +1149,9 @@ func (UnimplementedUserHostAdminServiceServer) CloseAgency(context.Context, *Clo func (UnimplementedUserHostAdminServiceServer) DeleteAgency(context.Context, *DeleteAgencyRequest) (*DeleteAgencyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteAgency not implemented") } +func (UnimplementedUserHostAdminServiceServer) SetAgencyStatus(context.Context, *SetAgencyStatusRequest) (*SetAgencyStatusResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetAgencyStatus not implemented") +} func (UnimplementedUserHostAdminServiceServer) SetAgencyJoinEnabled(context.Context, *SetAgencyJoinEnabledRequest) (*SetAgencyJoinEnabledResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SetAgencyJoinEnabled not implemented") } @@ -1304,6 +1320,24 @@ func _UserHostAdminService_DeleteAgency_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } +func _UserHostAdminService_SetAgencyStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetAgencyStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserHostAdminServiceServer).SetAgencyStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserHostAdminService_SetAgencyStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserHostAdminServiceServer).SetAgencyStatus(ctx, req.(*SetAgencyStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserHostAdminService_SetAgencyJoinEnabled_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SetAgencyJoinEnabledRequest) if err := dec(in); err != nil { @@ -1361,6 +1395,10 @@ var UserHostAdminService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeleteAgency", Handler: _UserHostAdminService_DeleteAgency_Handler, }, + { + MethodName: "SetAgencyStatus", + Handler: _UserHostAdminService_SetAgencyStatus_Handler, + }, { MethodName: "SetAgencyJoinEnabled", Handler: _UserHostAdminService_SetAgencyJoinEnabled_Handler, diff --git a/server/admin/internal/integration/userclient/client.go b/server/admin/internal/integration/userclient/client.go index 831c1a3b..72c9a58c 100644 --- a/server/admin/internal/integration/userclient/client.go +++ b/server/admin/internal/integration/userclient/client.go @@ -40,6 +40,7 @@ type Client interface { CreateAgency(ctx context.Context, req CreateAgencyRequest) (*CreateAgencyResult, error) CloseAgency(ctx context.Context, req CloseAgencyRequest) (*Agency, error) DeleteAgency(ctx context.Context, req DeleteAgencyRequest) (*Agency, error) + SetAgencyStatus(ctx context.Context, req SetAgencyStatusRequest) (*Agency, error) SetAgencyJoinEnabled(ctx context.Context, req SetAgencyJoinEnabledRequest) (*Agency, error) QuickCreateAccount(ctx context.Context, req QuickCreateAccountRequest) (*QuickCreateAccountResult, error) } @@ -532,6 +533,16 @@ type DeleteAgencyRequest struct { Reason string } +type SetAgencyStatusRequest struct { + RequestID string + Caller string + CommandID string + AdminUserID int64 + AgencyID int64 + Status string + Reason string +} + type SetAgencyJoinEnabledRequest struct { RequestID string Caller string @@ -562,6 +573,7 @@ type BDProfile struct { CreatedByDisplayUserID string `json:"createdByDisplayUserId"` CreatedByUsername string `json:"createdByUsername"` CreatedByAvatar string `json:"createdByAvatar"` + AgencyCount int64 `json:"agencyCount"` SubBDCount int64 `json:"subBdCount"` SalaryWallet SalaryWallet `json:"salaryWallet"` } @@ -585,6 +597,7 @@ type Agency struct { ParentBDUsername string `json:"parentBdUsername"` ParentBDAvatar string `json:"parentBdAvatar"` RegionName string `json:"regionName"` + ActiveHostCount int64 `json:"activeHostCount"` SalaryWallet SalaryWallet `json:"salaryWallet"` } @@ -784,6 +797,21 @@ func (c *GRPCClient) DeleteAgency(ctx context.Context, req DeleteAgencyRequest) return fromProtoAgency(resp.GetAgency()), nil } +func (c *GRPCClient) SetAgencyStatus(ctx context.Context, req SetAgencyStatusRequest) (*Agency, error) { + resp, err := c.hostAdminClient.SetAgencyStatus(ctx, &userv1.SetAgencyStatusRequest{ + Meta: requestMeta(ctx, req.RequestID, req.Caller), + CommandId: req.CommandID, + AdminUserId: req.AdminUserID, + AgencyId: req.AgencyID, + Status: req.Status, + Reason: req.Reason, + }) + if err != nil { + return nil, err + } + return fromProtoAgency(resp.GetAgency()), nil +} + func (c *GRPCClient) SetAgencyJoinEnabled(ctx context.Context, req SetAgencyJoinEnabledRequest) (*Agency, error) { resp, err := c.hostAdminClient.SetAgencyJoinEnabled(ctx, &userv1.SetAgencyJoinEnabledRequest{ Meta: requestMeta(ctx, req.RequestID, req.Caller), @@ -840,6 +868,7 @@ func fromProtoAgency(agency *userv1.Agency) *Agency { CreatedByUserID: agency.GetCreatedByUserId(), CreatedAtMs: agency.GetCreatedAtMs(), UpdatedAtMs: agency.GetUpdatedAtMs(), + ActiveHostCount: int64(agency.GetHostCount()), } } diff --git a/server/admin/internal/modules/gamemanagement/sync_games.go b/server/admin/internal/modules/gamemanagement/sync_games.go index ab3f695b..4186882d 100644 --- a/server/admin/internal/modules/gamemanagement/sync_games.go +++ b/server/admin/internal/modules/gamemanagement/sync_games.go @@ -28,6 +28,7 @@ const ( adapterZeeOneV1 = "zeeone_v1" adapterVivaGamesV1 = "vivagames_v1" adapterReyouV1 = "reyou_v1" + adapterZGameV1 = "zgame_v1" adapterYomiV4 = "yomi_v4" defaultGameStatus = "disabled" defaultGameCategory = "casino" @@ -138,6 +139,8 @@ func fetchProviderGameSyncPlan(ctx context.Context, platform *gamev1.GamePlatfor return fetchVivaGamesGameSyncPlan(platform, req) case adapterReyouV1: return fetchReyouGameSyncPlan(platform, req) + case adapterZGameV1: + return fetchZGameGameSyncPlan(platform, req) case adapterYomiV4: return fetchYomiGameSyncPlan(platform, req) default: @@ -202,6 +205,14 @@ type reyouSyncConfig struct { GameCovers map[string]string `json:"game_covers"` } +type zgameSyncConfig struct { + // ZGame 接入只约束固定回调和 JS Bridge;游戏 H5 地址由运营配置,后台据此生成可同步目录。 + GameURLs map[string]string `json:"game_urls"` + GameNames map[string]string `json:"game_names"` + GameIcons map[string]string `json:"game_icons"` + GameCovers map[string]string `json:"game_covers"` +} + type yomiSyncConfig struct { // Yomi V4 文档只提供启动鉴权地址,没有游戏列表 API;后台通过 game_names 维护截图里的 gameUid 清单。 GameNames map[string]string `json:"game_names"` @@ -366,6 +377,21 @@ func fetchReyouGameSyncPlan(platform *gamev1.GamePlatform, req syncGamesRequest) }, nil } +func fetchZGameGameSyncPlan(platform *gamev1.GamePlatform, req syncGamesRequest) (providerGameSyncPlan, error) { + config, err := decodeZGameSyncConfig(platform.GetAdapterConfigJson()) + if err != nil { + return providerGameSyncPlan{}, err + } + games, gameURLs := zgameCatalogItems(platform.GetPlatformCode(), config, req) + if len(games) == 0 { + return providerGameSyncPlan{}, fmt.Errorf("ZGame 游戏列表为空:请在 adapterConfigJson.game_urls 配置游戏 ID 到 H5 URL 的映射") + } + return providerGameSyncPlan{ + Games: games, + GameURLs: gameURLs, + }, nil +} + func fetchYomiGameSyncPlan(platform *gamev1.GamePlatform, req syncGamesRequest) (providerGameSyncPlan, error) { config, err := decodeYomiSyncConfig(platform.GetAdapterConfigJson()) if err != nil { @@ -392,6 +418,17 @@ func decodeReyouSyncConfig(raw string) (reyouSyncConfig, error) { return config, nil } +func decodeZGameSyncConfig(raw string) (zgameSyncConfig, error) { + if strings.TrimSpace(raw) == "" { + return zgameSyncConfig{}, nil + } + var config zgameSyncConfig + if err := json.Unmarshal([]byte(raw), &config); err != nil { + return zgameSyncConfig{}, fmt.Errorf("ZGame 适配器配置 JSON 不合法") + } + return config, nil +} + func decodeYomiSyncConfig(raw string) (yomiSyncConfig, error) { if strings.TrimSpace(raw) == "" { return yomiSyncConfig{}, nil @@ -438,6 +475,42 @@ func reyouCatalogItems(platformCode string, config reyouSyncConfig, req syncGame return items, gameURLs } +func zgameCatalogItems(platformCode string, config zgameSyncConfig, req syncGamesRequest) ([]catalogRequest, map[string]string) { + keys := make([]string, 0, len(config.GameURLs)) + for providerGameID, launchURL := range config.GameURLs { + if strings.TrimSpace(providerGameID) != "" && strings.TrimSpace(launchURL) != "" { + keys = append(keys, strings.TrimSpace(providerGameID)) + } + } + sort.Strings(keys) + items := make([]catalogRequest, 0, len(keys)) + gameURLs := make(map[string]string, len(keys)) + for index, providerGameID := range keys { + launchURL := strings.TrimSpace(config.GameURLs[providerGameID]) + gameURLs[providerGameID] = launchURL + // ZGame 没有厂商列表 API 返回展示名,优先使用后台维护名称,再从 URL 尽量提取可读标题。 + name := firstNonEmpty(config.GameNames[providerGameID], zeeoneGameNameFromURL(launchURL), providerGameID) + iconURL := strings.TrimSpace(config.GameIcons[providerGameID]) + coverURL := firstNonEmpty(config.GameCovers[providerGameID], iconURL) + items = append(items, catalogRequest{ + GameID: stableGameID(platformCode, providerGameID), + PlatformCode: strings.TrimSpace(platformCode), + ProviderGameID: providerGameID, + GameName: name, + Category: defaulted(req.Category, defaultGameCategory), + IconURL: iconURL, + CoverURL: coverURL, + LaunchMode: defaulted(req.LaunchMode, defaultLaunchMode), + Orientation: defaultOrientation, + MinCoin: req.MinCoin, + Status: defaulted(req.Status, defaultGameStatus), + SortOrder: int32((index + 1) * 10), + Tags: compactTags(append([]string{strings.TrimSpace(platformCode), adapterZGameV1}, req.Tags...)), + }) + } + return items, gameURLs +} + func yomiCatalogItems(platformCode string, config yomiSyncConfig, req syncGamesRequest) ([]catalogRequest, map[string]string) { keys := make([]string, 0, len(config.GameNames)+len(config.GameURLs)) seen := make(map[string]struct{}, len(config.GameNames)+len(config.GameURLs)) diff --git a/server/admin/internal/modules/gamemanagement/sync_games_test.go b/server/admin/internal/modules/gamemanagement/sync_games_test.go index 5b65645b..ffdf6230 100644 --- a/server/admin/internal/modules/gamemanagement/sync_games_test.go +++ b/server/admin/internal/modules/gamemanagement/sync_games_test.go @@ -167,6 +167,40 @@ func TestFetchReyouGameSyncPlanReadsConfiguredGameURLs(t *testing.T) { } } +func TestFetchZGameGameSyncPlanReadsConfiguredGameURLs(t *testing.T) { + plan, err := fetchProviderGameSyncPlan(t.Context(), &gamev1.GamePlatform{ + PlatformCode: "zgame", + AdapterType: adapterZGameV1, + AdapterConfigJson: `{ + "game_urls": { + "1001": "https://zgame.example/h5/1001/index.html" + }, + "game_names": { + "1001": "ZGame Demo" + } + }`, + }, syncGamesRequest{}) + if err != nil { + t.Fatalf("fetchProviderGameSyncPlan failed: %v", err) + } + if len(plan.Games) != 1 { + t.Fatalf("games len = %d, want 1", len(plan.Games)) + } + game := plan.Games[0] + if game.GameID != "zgame_1001" || game.ProviderGameID != "1001" || game.GameName != "ZGame Demo" { + t.Fatalf("zgame game mismatch: %+v", game) + } + if plan.GameURLs["1001"] != "https://zgame.example/h5/1001/index.html" { + t.Fatalf("game url mismatch: %+v", plan.GameURLs) + } + if game.Status != "disabled" || game.LaunchMode != "full_screen" || game.Orientation != "portrait" { + t.Fatalf("default fields mismatch: %+v", game) + } + if len(game.Tags) < 2 || game.Tags[0] != "zgame" || game.Tags[1] != adapterZGameV1 { + t.Fatalf("tags mismatch: %+v", game.Tags) + } +} + func TestFetchYomiGameSyncPlanReadsConfiguredGameNames(t *testing.T) { plan, err := fetchProviderGameSyncPlan(t.Context(), &gamev1.GamePlatform{ PlatformCode: "yomi", diff --git a/server/admin/internal/modules/hostorg/handler.go b/server/admin/internal/modules/hostorg/handler.go index 9a565e97..148c9b3e 100644 --- a/server/admin/internal/modules/hostorg/handler.go +++ b/server/admin/internal/modules/hostorg/handler.go @@ -416,6 +416,26 @@ func (h *Handler) CloseAgency(c *gin.Context) { response.OK(c, agency) } +func (h *Handler) SetAgencyStatus(c *gin.Context) { + agencyID, ok := parseInt64ID(c, "agency_id") + if !ok { + return + } + var req agencyStatusRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "Agency 状态参数不正确") + return + } + agency, err := h.service.SetAgencyStatus(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + writeHostOrgAuditLog(c, h.audit, "set-agency-status", "agencies", agency.AgencyID, + fmt.Sprintf("command_id=%s agency_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.Status, strings.TrimSpace(req.Reason))) + response.OK(c, agency) +} + func (h *Handler) DeleteAgency(c *gin.Context) { agencyID, ok := parseInt64ID(c, "agency_id") if !ok { diff --git a/server/admin/internal/modules/hostorg/reader.go b/server/admin/internal/modules/hostorg/reader.go index 8e3209a8..7c06a8ec 100644 --- a/server/admin/internal/modules/hostorg/reader.go +++ b/server/admin/internal/modules/hostorg/reader.go @@ -156,11 +156,12 @@ func (r *Reader) ListBDProfiles(ctx context.Context, query listQuery, role strin return nil, 0, err } limitSQL := "LIMIT ? OFFSET ?" - queryArgs := append(args, query.PageSize, offset(query.Page, query.PageSize)) + queryArgs := append([]any{agencyStatusDeleted}, args...) + queryArgs = append(queryArgs, query.PageSize, offset(query.Page, query.PageSize)) if query.SortBy == sortBySalaryWallet { // 工资钱包余额来自 wallet-service 读模型,不能只排序 SQL 当前页;先取出所有匹配身份,补齐余额后再分页。 limitSQL = "" - queryArgs = args + queryArgs = append([]any{agencyStatusDeleted}, args...) } rows, err := r.db.QueryContext(ctx, fmt.Sprintf(` SELECT bp.user_id, bp.role, `+userCountryRegionIDSQL("user_region")+`, COALESCE(bp.parent_leader_user_id, 0), @@ -173,10 +174,10 @@ func (r *Reader) ListBDProfiles(ctx context.Context, query listQuery, role strin COALESCE(creator.avatar, ''), ( SELECT COUNT(1) - FROM bd_profiles child - WHERE child.app_code = bp.app_code - AND child.role = 'bd' - AND child.parent_leader_user_id = bp.user_id + FROM agencies child_agency + WHERE child_agency.app_code = bp.app_code + AND child_agency.parent_bd_user_id = bp.user_id + AND child_agency.status <> ? ) %s ORDER BY bp.created_at_ms DESC, bp.user_id DESC @@ -209,7 +210,7 @@ func (r *Reader) ListBDProfiles(ctx context.Context, query listQuery, role strin &item.CreatedByDisplayUserID, &item.CreatedByUsername, &item.CreatedByAvatar, - &item.SubBDCount, + &item.AgencyCount, ); err != nil { return nil, 0, err } @@ -840,11 +841,12 @@ func (r *Reader) ListAgencies(ctx context.Context, query listQuery) ([]*userclie return nil, 0, err } limitSQL := "LIMIT ? OFFSET ?" - queryArgs := append(args, query.PageSize, offset(query.Page, query.PageSize)) + queryArgs := append([]any{membershipStatusActive}, args...) + queryArgs = append(queryArgs, query.PageSize, offset(query.Page, query.PageSize)) if query.SortBy == sortBySalaryWallet { // Agency 展示的是 owner 的 Agency 工资钱包;先补余额再排序,保证跨页顺序和真实余额一致。 limitSQL = "" - queryArgs = args + queryArgs = append([]any{membershipStatusActive}, args...) } rows, err := r.db.QueryContext(ctx, fmt.Sprintf(` SELECT a.agency_id, a.owner_user_id, `+userCountryRegionIDSQL("owner_region")+`, a.parent_bd_user_id, @@ -853,7 +855,14 @@ func (r *Reader) ListAgencies(ctx context.Context, query listQuery) ([]*userclie COALESCE(owner.current_display_user_id, ''), COALESCE(owner.username, ''), COALESCE(owner.avatar, ''), COALESCE(parent_bd.current_display_user_id, ''), COALESCE(parent_bd.username, ''), - COALESCE(parent_bd.avatar, ''), `+userCountryRegionNameSQL("owner_region")+` + COALESCE(parent_bd.avatar, ''), `+userCountryRegionNameSQL("owner_region")+`, + ( + SELECT COUNT(*) + FROM agency_memberships active_membership + WHERE active_membership.app_code = a.app_code + AND active_membership.agency_id = a.agency_id + AND active_membership.status = ? + ) %s ORDER BY a.created_at_ms DESC, a.agency_id DESC %s @@ -885,6 +894,7 @@ func (r *Reader) ListAgencies(ctx context.Context, query listQuery) ([]*userclie &item.ParentBDUsername, &item.ParentBDAvatar, &item.RegionName, + &item.ActiveHostCount, ); err != nil { return nil, 0, err } diff --git a/server/admin/internal/modules/hostorg/request.go b/server/admin/internal/modules/hostorg/request.go index fd283fb0..5e7d23d8 100644 --- a/server/admin/internal/modules/hostorg/request.go +++ b/server/admin/internal/modules/hostorg/request.go @@ -229,6 +229,12 @@ type agencyCloseRequest struct { Reason string `json:"reason"` } +type agencyStatusRequest struct { + CommandID string `json:"commandId" binding:"required"` + Status string `json:"status" binding:"required"` + Reason string `json:"reason"` +} + type agencyDeleteRequest struct { CommandID string `json:"commandId" binding:"required"` Reason string `json:"reason"` diff --git a/server/admin/internal/modules/hostorg/routes.go b/server/admin/internal/modules/hostorg/routes.go index 67247767..d6dd0f41 100644 --- a/server/admin/internal/modules/hostorg/routes.go +++ b/server/admin/internal/modules/hostorg/routes.go @@ -21,6 +21,7 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.GET("/admin/agencies", middleware.RequirePermission("agency:view"), h.ListAgencies) protected.POST("/admin/agencies", middleware.RequirePermission("agency:create"), h.CreateAgency) protected.POST("/admin/agencies/:agency_id/close", middleware.RequirePermission("agency:status"), h.CloseAgency) + protected.PATCH("/admin/agencies/:agency_id/status", middleware.RequirePermission("agency:status"), h.SetAgencyStatus) protected.POST("/admin/agencies/:agency_id/delete", middleware.RequirePermission("agency:delete"), h.DeleteAgency) protected.POST("/admin/agencies/:agency_id/join-enabled", middleware.RequirePermission("agency:status"), h.SetAgencyJoinEnabled) protected.GET("/admin/hosts", middleware.RequirePermission("host:view"), h.ListHosts) diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index c370ed26..4f8d7d06 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -17,6 +17,8 @@ const ( coinSellerStockTypePurchase = "usdt_purchase" coinSellerStockTypeDeduction = "usdt_deduction" coinSellerStockTypeCompensate = "coin_compensation" + agencyStatusDeleted = "deleted" + membershipStatusActive = "active" paidCurrencyUSDT = "USDT" sortByDiamond = "diamond" sortByMerchantBalance = "merchant_balance" @@ -452,6 +454,18 @@ func (s *Service) CloseAgency(ctx context.Context, actorID int64, agencyID int64 }) } +func (s *Service) SetAgencyStatus(ctx context.Context, actorID int64, agencyID int64, requestID string, req agencyStatusRequest) (*userclient.Agency, error) { + return s.userClient.SetAgencyStatus(ctx, userclient.SetAgencyStatusRequest{ + RequestID: requestID, + Caller: "hyapp-admin-server", + CommandID: strings.TrimSpace(req.CommandID), + AdminUserID: actorID, + AgencyID: agencyID, + Status: strings.ToLower(strings.TrimSpace(req.Status)), + Reason: strings.TrimSpace(req.Reason), + }) +} + func (s *Service) DeleteAgency(ctx context.Context, actorID int64, agencyID int64, requestID string, req agencyDeleteRequest) (*userclient.Agency, error) { return s.userClient.DeleteAgency(ctx, userclient.DeleteAgencyRequest{ RequestID: requestID, diff --git a/services/game-service/internal/domain/game/game.go b/services/game-service/internal/domain/game/game.go index 4b8f241e..8e69cea4 100644 --- a/services/game-service/internal/domain/game/game.go +++ b/services/game-service/internal/domain/game/game.go @@ -7,6 +7,8 @@ const ( SceneVoiceRoom = "voice_room" + PlatformCodeZGame = "zgame" + LaunchModeFullScreen = "full_screen" LaunchModeHalfScreen = "half_screen" LaunchModeThreeQuarterScreen = "three_quarter_screen" @@ -20,6 +22,7 @@ const ( AdapterBaishunV1 = "baishun_v1" AdapterVivaGamesV1 = "vivagames_v1" AdapterReyouV1 = "reyou_v1" + AdapterZGameV1 = "zgame_v1" OrderStatusWalletApplying = "wallet_applying" OrderStatusSucceeded = "succeeded" diff --git a/services/game-service/internal/service/game/service.go b/services/game-service/internal/service/game/service.go index 0fae85b8..81330832 100644 --- a/services/game-service/internal/service/game/service.go +++ b/services/game-service/internal/service/game/service.go @@ -296,7 +296,7 @@ func (s *Service) LaunchGame(ctx context.Context, command LaunchCommand) (Launch sessionID := "game_sess_" + strconv.FormatInt(now.UnixMilli(), 10) + "_" + randomHex(6) token := strings.TrimSpace(command.AccessToken) if token == "" { - if strings.EqualFold(game.AdapterType, gamedomain.AdapterYomiV4) || strings.EqualFold(game.AdapterType, gamedomain.AdapterLeaderCCV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterBaishunV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterVivaGamesV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterReyouV1) { + if strings.EqualFold(game.AdapterType, gamedomain.AdapterYomiV4) || strings.EqualFold(game.AdapterType, gamedomain.AdapterLeaderCCV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterBaishunV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterVivaGamesV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterReyouV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterZGameV1) { return LaunchResult{}, xerr.New(xerr.InvalidArgument, "access token is required for provider game launch") } token = "gt_" + randomHex(24) @@ -315,6 +315,8 @@ func (s *Service) LaunchGame(ctx context.Context, command LaunchCommand) (Launch sessionTTL = maxDuration(sessionTTL, vivaGamesConfigFromPlatform(game).TokenTTL()) } else if strings.EqualFold(game.AdapterType, gamedomain.AdapterReyouV1) { sessionTTL = maxDuration(sessionTTL, reyouConfigFromPlatform(game).TokenTTL()) + } else if strings.EqualFold(game.AdapterType, gamedomain.AdapterZGameV1) { + sessionTTL = maxDuration(sessionTTL, zgameConfigFromPlatform(game).TokenTTL()) } expiresAt := now.Add(sessionTTL).UnixMilli() session := gamedomain.LaunchSession{ @@ -390,12 +392,18 @@ func (s *Service) HandleCallback(ctx context.Context, req *gamev1.CallbackReques responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleVivaGamesOperation(ctx, app, platform, req, operation, requestHash) case strings.EqualFold(platform.AdapterType, gamedomain.AdapterReyouV1): responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleReyouOperation(ctx, app, platform, req, operation, requestHash) + case strings.EqualFold(platform.AdapterType, gamedomain.AdapterZGameV1): + responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleZGameOperation(ctx, app, platform, req, operation, requestHash) default: responseBody, contentType, statusCode, err = s.handleDemoOperation(ctx, app, req, operation, requestHash) } } else { - // 找不到平台时退回 demo,保留旧测试入口行为,避免管理后台未配置时直接打断联调。 - responseBody, contentType, statusCode, err = s.handleDemoOperation(ctx, app, req, operation, requestHash) + if strings.EqualFold(req.GetPlatformCode(), gamedomain.PlatformCodeZGame) { + responseBody, contentType, statusCode, signatureValid, providerRequestID, err = zgameAdapterError(zgameCodeInvalidSession, "Invalid Session", false, "") + } else { + // 找不到平台时退回 demo,保留旧测试入口行为,避免管理后台未配置时直接打断联调。 + responseBody, contentType, statusCode, err = s.handleDemoOperation(ctx, app, req, operation, requestHash) + } } responseHash := stableHashBytes(responseBody) logStatus := "succeeded" @@ -822,6 +830,12 @@ func buildLaunchURL(game gamedomain.LaunchableGame, session gamedomain.LaunchSes base = configuredBase } } + if strings.EqualFold(game.AdapterType, gamedomain.AdapterZGameV1) { + // ZGame H5 地址由厂商提供;固定回调路径只影响服务端回调,启动页仍按后台 game_urls/template 热配置。 + if configuredBase := zgameLaunchBaseURL(game, zgameConfigFromPlatform(game)); configuredBase != "" { + base = configuredBase + } + } if base == "" { if strings.EqualFold(game.AdapterType, gamedomain.AdapterYomiV4) { return "", xerr.New(xerr.InvalidArgument, "yomi auth url is required") @@ -838,6 +852,9 @@ func buildLaunchURL(game gamedomain.LaunchableGame, session gamedomain.LaunchSes if strings.EqualFold(game.AdapterType, gamedomain.AdapterReyouV1) { return "", xerr.New(xerr.InvalidArgument, "reyou launch url is required") } + if strings.EqualFold(game.AdapterType, gamedomain.AdapterZGameV1) { + return "", xerr.New(xerr.InvalidArgument, "zgame launch url is required") + } // demo 平台可以没有真实厂商域名,保留本地默认地址用于开发自测。 base = "https://game.example.local/h5" } @@ -977,6 +994,36 @@ func buildLaunchURL(game gamedomain.LaunchableGame, session gamedomain.LaunchSes parsed.RawQuery = query.Encode() return parsed.String(), nil } + if strings.EqualFold(game.AdapterType, gamedomain.AdapterZGameV1) { + // ZGame 客户端通过 ThirdPlatformBridge.login 拿 js_code;为避免 App 发版,远程桥接脚本直接从启动配置读取同一个短期 token。 + config := zgameConfigFromPlatform(game) + openID := externalUserID(session, config.UIDMode) + query.Set("openId", openID) + query.Set("open_id", openID) + query.Set("userId", openID) + query.Set("uid", openID) + query.Set("code", token) + query.Set("js_code", token) + query.Set("session", token) + query.Set("gameId", strings.TrimSpace(session.ProviderGameID)) + query.Set("game_id", strings.TrimSpace(session.ProviderGameID)) + query.Set("callbackBase", "/api/v1/zgame/callback") + query.Set("callback_base", "/api/v1/zgame/callback") + if config.DefaultLang != "" { + query.Set("lang", config.DefaultLang) + } + if session.RoomID != "" { + query.Set("roomId", session.RoomID) + query.Set("room_id", session.RoomID) + } + if config.MerchantPayload != "" { + query.Set("merchantPayload", config.MerchantPayload) + query.Set("merchant_payload", config.MerchantPayload) + } + appendBridgeScriptQuery(query, game) + parsed.RawQuery = query.Encode() + return parsed.String(), nil + } // demo adapter 保持内部调试参数完整,方便用一个简单 H5 验证 session 和订单链路。 query.Set("session_id", session.SessionID) query.Set("session_token", token) diff --git a/services/game-service/internal/service/game/service_test.go b/services/game-service/internal/service/game/service_test.go index b4df1926..7db50a53 100644 --- a/services/game-service/internal/service/game/service_test.go +++ b/services/game-service/internal/service/game/service_test.go @@ -5,6 +5,7 @@ import ( "crypto/aes" "crypto/cipher" "crypto/md5" + "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" @@ -545,6 +546,86 @@ func TestLaunchGameBuildsReyouURL(t *testing.T) { } } +func TestLaunchGameBuildsZGameURL(t *testing.T) { + token := leaderccTestAccessToken(t, "lalu", 42, "420001", 1700007200) + repo := &fakeRepository{ + launchable: gamedomain.LaunchableGame{ + CatalogItem: gamedomain.CatalogItem{ + AppCode: "lalu", + GameID: "zgame_1001", + PlatformCode: gamedomain.PlatformCodeZGame, + ProviderGameID: "1001", + GameName: "ZGame Demo", + Status: gamedomain.StatusActive, + Orientation: "portrait", + }, + PlatformStatus: gamedomain.StatusActive, + APIBaseURL: "https://fallback.example.invalid/zgame.html", + AdapterType: gamedomain.AdapterZGameV1, + AdapterConfigJSON: `{ + "default_lang":"en", + "token_ttl_seconds":7200, + "uid_mode":"display_user_id", + "merchant_payload":"room_game", + "bridge_script_url":"https://cdn.example/zgame-bridge.js", + "bridge_script_version":"20260629.1", + "game_urls":{"1001":"https://zgame.example/h5/1001"} + }`, + }, + } + svc := New(Config{LaunchSessionTTL: 15 * time.Minute}, repo, &fakeWallet{}, &fakeUser{}) + svc.now = func() time.Time { return time.UnixMilli(1700000000000) } + + result, err := svc.LaunchGame(context.Background(), LaunchCommand{ + AppCode: "lalu", + UserID: 42, + DisplayUserID: "420001", + GameID: "zgame_1001", + RoomID: "room_1", + AccessToken: token, + }) + if err != nil { + t.Fatalf("LaunchGame failed: %v", err) + } + if result.ExpiresAtMS != 1700007200000 { + t.Fatalf("zgame launch must use adapter token ttl, got %+v", result) + } + parsed, err := url.Parse(result.LaunchURL) + if err != nil { + t.Fatalf("parse zgame launch url failed: %v", err) + } + if parsed.Scheme+"://"+parsed.Host+parsed.Path != "https://zgame.example/h5/1001" { + t.Fatalf("zgame launch url must use per-game configured url: %s", result.LaunchURL) + } + expected := map[string]string{ + "openId": "420001", + "open_id": "420001", + "userId": "420001", + "uid": "420001", + "code": token, + "js_code": token, + "session": token, + "gameId": "1001", + "game_id": "1001", + "callbackBase": "/api/v1/zgame/callback", + "callback_base": "/api/v1/zgame/callback", + "lang": "en", + "roomId": "room_1", + "room_id": "room_1", + "merchantPayload": "room_game", + "merchant_payload": "room_game", + "bridge_script_url": "https://cdn.example/zgame-bridge.js", + "bridgeScriptUrl": "https://cdn.example/zgame-bridge.js", + "bridge_script_version": "20260629.1", + "bridgeScriptVersion": "20260629.1", + } + for key, want := range expected { + if got := parsed.Query().Get(key); got != want { + t.Fatalf("zgame launch query %s mismatch: got %q want %q url=%s", key, got, want, result.LaunchURL) + } + } +} + func TestLaunchGameRequiresBaishunLaunchURL(t *testing.T) { repo := &fakeRepository{ launchable: gamedomain.LaunchableGame{ @@ -1458,6 +1539,95 @@ func TestHandleReyouUserInfoAndUpdateBalance(t *testing.T) { } } +func TestHandleCallbackZGameAdapter(t *testing.T) { + secret := "zgame-test-secret" + token := leaderccTestAccessToken(t, "lalu", 42, "420001", 1700007200) + repo := &fakeRepository{ + platform: gamedomain.Platform{ + PlatformCode: gamedomain.PlatformCodeZGame, + AdapterType: gamedomain.AdapterZGameV1, + CallbackSecretCiphertext: secret, + AdapterConfigJSON: `{"uid_mode":"display_user_id","level":10,"gender":1}`, + }, + } + wallet := &fakeWallet{balanceAfter: 1880} + user := &fakeUser{} + svc := New(Config{}, repo, wallet, user) + svc.now = func() time.Time { return time.UnixMilli(1700000000000) } + + raw, contentType, err := svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-zgame-login", AppCode: "lalu"}, + PlatformCode: gamedomain.PlatformCodeZGame, + Operation: "server/login", + RawBody: []byte(`{"open_id":"420001","js_code":"` + token + `"}`), + }) + if err != nil { + t.Fatalf("HandleCallback login failed: %v", err) + } + var loginResp map[string]any + if contentType != "application/json" || json.Unmarshal(raw, &loginResp) != nil { + t.Fatalf("zgame login response must be json: content_type=%s raw=%s", contentType, raw) + } + loginData := loginResp["data"].(map[string]any) + if loginResp["code"].(float64) != 0 || loginData["session"] != token || loginData["openId"] != "420001" || loginData["userName"] != "tester" || int64(loginData["balance"].(float64)) != 1880 || int64(loginData["level"].(float64)) != 10 { + t.Fatalf("zgame login response mismatch: %s", raw) + } + if int64(loginData["session_expired"].(float64)) != 7200000 { + t.Fatalf("zgame login session ttl mismatch: %s", raw) + } + + signature := zgameTestSignature("420001", token, secret) + raw, _, err = svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-zgame-renew", AppCode: "lalu"}, + PlatformCode: gamedomain.PlatformCodeZGame, + Operation: "api/server/session_renew", + RawBody: []byte(`{"open_id":"420001","session":"` + token + `","signature":"` + signature + `"}`), + }) + if err != nil { + t.Fatalf("HandleCallback session_renew failed: %v", err) + } + var renewResp map[string]any + if json.Unmarshal(raw, &renewResp) != nil || renewResp["code"].(float64) != 0 || int64(renewResp["data"].(map[string]any)["session_expired"].(float64)) != 7200000 { + t.Fatalf("zgame session_renew response mismatch: %s", raw) + } + + raw, _, err = svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-zgame-users", AppCode: "lalu"}, + PlatformCode: gamedomain.PlatformCodeZGame, + Operation: "server/user_info_batch", + RawBody: []byte(`{"open_id":"420001","open_id_list":["420001"],"session":"` + token + `","signature":"` + signature + `"}`), + }) + if err != nil { + t.Fatalf("HandleCallback user_info_batch failed: %v", err) + } + var usersResp map[string]any + if json.Unmarshal(raw, &usersResp) != nil { + t.Fatalf("decode zgame user_info_batch response failed: %s", raw) + } + userInfos := usersResp["data"].(map[string]any)["user_infos"].(map[string]any) + userInfo := userInfos["420001"].(map[string]any) + if usersResp["code"].(float64) != 0 || userInfo["nickname"] != "tester" || int64(userInfo["balance"].(float64)) != 1880 { + t.Fatalf("zgame user_info_batch response mismatch: %s", raw) + } + + raw, _, err = svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-zgame-consume", AppCode: "lalu"}, + PlatformCode: gamedomain.PlatformCodeZGame, + Operation: "server/consume", + RawBody: []byte(`{"open_id":"420001","session":"` + token + `","amount":120,"order_id":"zord_1","game_id":"1001","round_id":"zr_1","type":0,"signature":"` + signature + `"}`), + }) + if err != nil { + t.Fatalf("HandleCallback consume failed: %v", err) + } + var consumeResp map[string]any + if json.Unmarshal(raw, &consumeResp) != nil || consumeResp["code"].(float64) != 0 || int64(consumeResp["balance"].(float64)) != 1880 { + t.Fatalf("zgame consume response mismatch: %s", raw) + } + if wallet.lastApply.GetCommandId() != "game:zgame:zord_1:debit" || wallet.lastApply.GetOpType() != "debit" || wallet.lastApply.GetCoinAmount() != 120 || wallet.lastApply.GetGameId() != "1001" { + t.Fatalf("zgame wallet command mismatch: %+v", wallet.lastApply) + } +} + func TestHandleBaishunAccessTokenIgnoresStaleLaunchSessionGameID(t *testing.T) { secret := "baishun-test-app-key" userID := int64(312900923573673984) @@ -1964,6 +2134,11 @@ func reyouTestSign(key string, parts ...string) string { return strings.ToUpper(hex.EncodeToString(sum[:])) } +func zgameTestSignature(openID string, session string, secret string) string { + sum := sha256.Sum256([]byte(strings.TrimSpace(openID) + strings.TrimSpace(session) + strings.TrimSpace(secret))) + return hex.EncodeToString(sum[:]) +} + func leaderccTestAccessToken(t *testing.T, app string, userID int64, displayUserID string, expiresAtSec int64) string { t.Helper() token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ diff --git a/services/game-service/internal/service/game/zgame_adapter.go b/services/game-service/internal/service/game/zgame_adapter.go new file mode 100644 index 00000000..3af181d6 --- /dev/null +++ b/services/game-service/internal/service/game/zgame_adapter.go @@ -0,0 +1,549 @@ +package game + +import ( + "context" + "crypto/sha256" + "crypto/subtle" + "encoding/hex" + "encoding/json" + "fmt" + "math" + "strconv" + "strings" + "time" + + gamev1 "hyapp.local/api/proto/game/v1" + "hyapp/pkg/xerr" + gamedomain "hyapp/services/game-service/internal/domain/game" +) + +const ( + // ZGame 文档的业务码会被游戏服务端直接消费;HTTP 200 只表示网关成功接收并处理回调。 + zgameCodeOK = 0 + zgameCodeInvalidSession = 201 + zgameCodeInvalidSignature = 400 + zgameCodeUnauthorized = 401 + zgameCodeInvalidCode = 403 + zgameCodeInsufficientBalance = 501 + zgameCodeInternalError = 500 + + zgameDefaultTokenTTL = 24 * time.Hour +) + +type zgameAdapterConfig struct { + // uid_mode 必须和启动链接、login open_id、后续签名 open_id 保持一致,避免同一 token 被不同用户标识复用。 + UIDMode string `json:"uid_mode"` + DefaultLang string `json:"default_lang"` + TokenTTLSeconds int64 `json:"token_ttl_seconds"` + // game_urls 支持 ZGame 每款游戏独立 H5 地址;launch_url_template 用于批量上新时按 provider_game_id 生成地址。 + GameURLs map[string]string `json:"game_urls"` + LaunchURLTemplate string `json:"launch_url_template"` + // merchant_payload 是 ZGame consume 回调的透传字段来源;只参与厂商回传,不进入内部业务判断。 + MerchantPayload string `json:"merchant_payload"` + // level/gender 是 ZGame 用户资料响应里的展示字段;真实等级接入前保持显式默认值,避免从其它体系误推。 + Level int32 `json:"level"` + Gender int32 `json:"gender"` +} + +func zgameConfigFromPlatform(value any) zgameAdapterConfig { + var raw string + switch typed := value.(type) { + case gamedomain.Platform: + raw = typed.AdapterConfigJSON + case gamedomain.LaunchableGame: + raw = typed.AdapterConfigJSON + } + var config zgameAdapterConfig + _ = json.Unmarshal([]byte(strings.TrimSpace(raw)), &config) + config.UIDMode = strings.ToLower(strings.TrimSpace(config.UIDMode)) + config.DefaultLang = strings.TrimSpace(config.DefaultLang) + config.LaunchURLTemplate = strings.TrimSpace(config.LaunchURLTemplate) + config.MerchantPayload = strings.TrimSpace(config.MerchantPayload) + config.GameURLs = normalizeStringMap(config.GameURLs) + return config +} + +func (c zgameAdapterConfig) TokenTTL() time.Duration { + if c.TokenTTLSeconds > 0 { + return time.Duration(c.TokenTTLSeconds) * time.Second + } + return zgameDefaultTokenTTL +} + +func zgameLaunchBaseURL(game gamedomain.LaunchableGame, config zgameAdapterConfig) string { + for _, key := range []string{game.ProviderGameID, game.GameID, strings.ToLower(game.GameID)} { + if raw := strings.TrimSpace(config.GameURLs[strings.TrimSpace(key)]); raw != "" { + return raw + } + } + if config.LaunchURLTemplate == "" { + return "" + } + replacer := strings.NewReplacer( + "{provider_game_id}", strings.TrimSpace(game.ProviderGameID), + "{providerGameId}", strings.TrimSpace(game.ProviderGameID), + "{game_id}", strings.TrimSpace(game.GameID), + "{gameId}", strings.TrimSpace(game.GameID), + ) + return strings.TrimSpace(replacer.Replace(config.LaunchURLTemplate)) +} + +func (s *Service) handleZGameOperation(ctx context.Context, app string, platform gamedomain.Platform, req *gamev1.CallbackRequest, operation string, requestHash string) ([]byte, string, string, bool, string, error) { + // IP 白名单为空时兼容联调环境;一旦后台配置,固定回调入口先挡掉非厂商来源。 + if !callbackIPAllowed(req, platform.CallbackIPWhitelist) { + return zgameAdapterError(zgameCodeUnauthorized, "Unauthorized", false, "") + } + config := zgameConfigFromPlatform(platform) + switch zgameOperation(operation) { + case "login": + return s.handleZGameLogin(ctx, app, config, req) + case "session_renew": + return s.handleZGameSessionRenew(ctx, app, config, platform.CallbackSecretCiphertext, req) + case "user_info_batch": + return s.handleZGameUserInfoBatch(ctx, app, config, platform.CallbackSecretCiphertext, req) + case "consume": + return s.handleZGameConsume(ctx, app, config, platform.CallbackSecretCiphertext, req, requestHash) + default: + return zgameAdapterError(zgameCodeOK, "success", false, "") + } +} + +func zgameOperation(operation string) string { + normalized := strings.Trim(strings.ToLower(strings.TrimSpace(operation)), "/") + normalized = strings.TrimPrefix(normalized, "api/") + normalized = strings.TrimPrefix(normalized, "server/") + normalized = strings.TrimPrefix(normalized, "client/") + return strings.Trim(normalized, "/") +} + +type zgameLoginBody struct { + OpenID string `json:"open_id"` + OpenIDV2 string `json:"openId"` + JSCode string `json:"js_code"` + JSCodeV2 string `json:"jsCode"` + JSCodeV3 string `json:"code"` + CallbackURL string `json:"callback_url"` +} + +func (body zgameLoginBody) openID() string { + return firstNonEmpty(body.OpenID, body.OpenIDV2) +} + +func (body zgameLoginBody) jsCode() string { + return firstNonEmpty(body.JSCode, body.JSCodeV2, body.JSCodeV3) +} + +func (s *Service) handleZGameLogin(ctx context.Context, app string, config zgameAdapterConfig, req *gamev1.CallbackRequest) ([]byte, string, string, bool, string, error) { + var body zgameLoginBody + if err := decodeYomiJSON(req.GetRawBody(), &body); err != nil { + return zgameAdapterError(zgameCodeInvalidCode, "Invalid or Expired Code", false, "") + } + openID := body.openID() + jsCode := body.jsCode() + session, err := s.validZGameSession(ctx, app, gamedomain.PlatformCodeZGame, jsCode, "") + if err != nil || !zgameSessionMatches(session, config, openID, "") { + return zgameAdapterError(zgameCodeInvalidCode, "Invalid or Expired Code", true, "") + } + snapshot, err := s.yomiUserSnapshot(ctx, app, req, session.UserID) + if err != nil { + return zgameAdapterError(zgameCodeFromError(err), zgameMessageFromError(err), true, "") + } + raw, contentType := zgameJSON(zgameCodeOK, "success", zgameLoginData(session, config, jsCode, snapshot, s.now())) + return raw, contentType, strconv.Itoa(zgameCodeOK), true, "", nil +} + +type zgameSignedSessionBody struct { + OpenID string `json:"open_id"` + OpenIDV2 string `json:"openId"` + Session string `json:"session"` + Signature string `json:"signature"` + RawGameID any `json:"game_id"` + RawGameIDV2 any `json:"gameId"` + RawTimestamp any `json:"timestamp"` +} + +func (body zgameSignedSessionBody) openID() string { + return firstNonEmpty(body.OpenID, body.OpenIDV2) +} + +func (body zgameSignedSessionBody) gameIDText() string { + return zgameAnyString(firstNonEmpty(zgameAnyString(body.RawGameID), zgameAnyString(body.RawGameIDV2))) +} + +func (s *Service) handleZGameSessionRenew(ctx context.Context, app string, config zgameAdapterConfig, secret string, req *gamev1.CallbackRequest) ([]byte, string, string, bool, string, error) { + body, signed, session, err := s.zgameSignedSession(ctx, app, config, secret, req) + if !signed { + return zgameAdapterError(zgameCodeInvalidSignature, "Invalid Signature", false, "") + } + if err != nil || !zgameSessionMatches(session, config, body.openID(), body.gameIDText()) { + return zgameAdapterError(zgameCodeInvalidSession, "Invalid Session", true, "") + } + raw, contentType := zgameJSON(zgameCodeOK, "success", map[string]any{ + "session": body.Session, + "session_expired": zgameSessionTTLMS(session, s.now()), + }) + return raw, contentType, strconv.Itoa(zgameCodeOK), true, "", nil +} + +type zgameUserInfoBatchBody struct { + OpenIDList []string `json:"open_id_list"` + OpenIDListV2 []string `json:"openIdList"` + OpenID string `json:"open_id"` + OpenIDV2 string `json:"openId"` + Session string `json:"session"` + Signature string `json:"signature"` +} + +func (body zgameUserInfoBatchBody) openID() string { + return firstNonEmpty(body.OpenID, body.OpenIDV2) +} + +func (body zgameUserInfoBatchBody) openIDList() []string { + if len(body.OpenIDList) > 0 { + return body.OpenIDList + } + return body.OpenIDListV2 +} + +func (s *Service) handleZGameUserInfoBatch(ctx context.Context, app string, config zgameAdapterConfig, secret string, req *gamev1.CallbackRequest) ([]byte, string, string, bool, string, error) { + var body zgameUserInfoBatchBody + if err := decodeYomiJSON(req.GetRawBody(), &body); err != nil { + return zgameAdapterError(zgameCodeInvalidSession, "Invalid Session", false, "") + } + if !zgameSignatureValid(body.openID(), body.Session, body.Signature, secret) { + return zgameAdapterError(zgameCodeInvalidSignature, "Invalid Signature", false, "") + } + session, err := s.validZGameSession(ctx, app, gamedomain.PlatformCodeZGame, body.Session, "") + if err != nil || !zgameSessionMatches(session, config, body.openID(), "") { + return zgameAdapterError(zgameCodeInvalidSession, "Invalid Session", true, "") + } + userInfos := make(map[string]any, len(body.openIDList())) + for _, openID := range body.openIDList() { + openID = strings.TrimSpace(openID) + if openID == "" { + continue + } + data, ok := s.zgameUserInfoForOpenID(ctx, app, config, req, session, openID) + if ok { + userInfos[openID] = data + } + } + raw, contentType := zgameJSON(zgameCodeOK, "success", map[string]any{"user_infos": userInfos}) + return raw, contentType, strconv.Itoa(zgameCodeOK), true, "", nil +} + +type zgameConsumeBody struct { + OpenID string `json:"open_id"` + OpenIDV2 string `json:"openId"` + Session string `json:"session"` + Amount json.Number `json:"amount"` + OrderID string `json:"order_id"` + OrderIDV2 string `json:"orderId"` + GameID string `json:"game_id"` + GameIDV2 string `json:"gameId"` + Timestamp int64 `json:"timestamp"` + RoundID string `json:"round_id"` + RoundIDV2 string `json:"roundId"` + Type int32 `json:"type"` + MerchantPayload string `json:"merchant_payload"` + MerchantPayloadV2 string `json:"merchantPayload"` + Signature string `json:"signature"` +} + +func (body zgameConsumeBody) openID() string { + return firstNonEmpty(body.OpenID, body.OpenIDV2) +} + +func (body zgameConsumeBody) orderID() string { + return firstNonEmpty(body.OrderID, body.OrderIDV2) +} + +func (body zgameConsumeBody) gameID() string { + return firstNonEmpty(body.GameID, body.GameIDV2) +} + +func (body zgameConsumeBody) roundID() string { + return firstNonEmpty(body.RoundID, body.RoundIDV2) +} + +func (body zgameConsumeBody) merchantPayload() string { + return firstNonEmpty(body.MerchantPayload, body.MerchantPayloadV2) +} + +func (s *Service) handleZGameConsume(ctx context.Context, app string, config zgameAdapterConfig, secret string, req *gamev1.CallbackRequest, requestHash string) ([]byte, string, string, bool, string, error) { + var body zgameConsumeBody + if err := decodeYomiJSON(req.GetRawBody(), &body); err != nil { + return zgameAdapterError(zgameCodeUnauthorized, "Unauthorized", false, "") + } + if !zgameSignatureValid(body.openID(), body.Session, body.Signature, secret) { + return zgameAdapterError(zgameCodeInvalidSignature, "Invalid Signature", false, body.orderID()) + } + session, err := s.validZGameSession(ctx, app, gamedomain.PlatformCodeZGame, body.Session, body.gameID()) + if err != nil || !zgameSessionMatches(session, config, body.openID(), body.gameID()) { + return zgameAdapterError(zgameCodeUnauthorized, "Unauthorized", true, body.orderID()) + } + amount, amountOK := zgameAmount(body.Amount) + opType, coinAmount := zgameOpType(body.Type, amount) + if body.orderID() == "" || body.gameID() == "" || !amountOK || coinAmount < 0 || opType == "" { + return zgameAdapterError(zgameCodeUnauthorized, "Unauthorized", true, body.orderID()) + } + if session.GameID == "" { + session.GameID = body.gameID() + } + if session.ProviderGameID == "" { + session.ProviderGameID = body.gameID() + } + providerOrderID := zgameProviderOrderID(body.orderID(), opType) + result, err := s.applyYomiCoinChange(ctx, app, req, session, providerOrderID, body.roundID(), opType, coinAmount, "", requestHash) + if err != nil { + code := zgameCodeFromError(err) + balance := s.bestEffortCoinBalance(ctx, app, req.GetMeta().GetRequestId(), session.UserID) + raw, contentType := zgameBalanceJSON(code, zgameMessageFromError(err), balance) + return raw, contentType, strconv.Itoa(code), true, body.orderID(), nil + } + raw, contentType := zgameBalanceJSON(zgameCodeOK, "success", result.BalanceAfter) + return raw, contentType, strconv.Itoa(zgameCodeOK), true, body.orderID(), nil +} + +func (s *Service) zgameSignedSession(ctx context.Context, app string, config zgameAdapterConfig, secret string, req *gamev1.CallbackRequest) (zgameSignedSessionBody, bool, gamedomain.LaunchSession, error) { + var body zgameSignedSessionBody + if err := decodeYomiJSON(req.GetRawBody(), &body); err != nil { + return zgameSignedSessionBody{}, false, gamedomain.LaunchSession{}, xerr.New(xerr.InvalidArgument, "invalid payload") + } + if !zgameSignatureValid(body.openID(), body.Session, body.Signature, secret) { + return body, false, gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "signature invalid") + } + session, err := s.validZGameSession(ctx, app, gamedomain.PlatformCodeZGame, body.Session, body.gameIDText()) + if err != nil { + return body, true, gamedomain.LaunchSession{}, err + } + if !zgameSessionMatches(session, config, body.openID(), body.gameIDText()) { + return body, true, gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "session mismatch") + } + return body, true, session, nil +} + +func (s *Service) validZGameSession(ctx context.Context, app string, platformCode string, token string, providerGameID string) (gamedomain.LaunchSession, error) { + token = strings.TrimSpace(token) + if token == "" { + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "session invalid") + } + // 当前 ZGame 不要求 App 原生生成一次性 jscode;优先消费 App access token,远程桥接脚本即可免发版接入。 + if strings.Count(token, ".") == 2 { + if session, err := s.appSessionFromAccessToken(app, token); err == nil { + return session, nil + } + } + if session, err := s.validScopedYomiSession(ctx, app, platformCode, token, providerGameID); err == nil { + return session, nil + } + if strings.Count(token, ".") == 2 { + return s.appSessionFromAccessToken(app, token) + } + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "session invalid") +} + +func zgameSessionMatches(session gamedomain.LaunchSession, config zgameAdapterConfig, openID string, gameID string) bool { + if strings.TrimSpace(gameID) != "" && strings.TrimSpace(session.ProviderGameID) != "" && strings.TrimSpace(gameID) != strings.TrimSpace(session.ProviderGameID) { + return false + } + openID = strings.TrimSpace(openID) + return openID != "" && (openID == externalUserID(session, config.UIDMode) || + openID == strings.TrimSpace(session.DisplayUserID) || + openID == strconv.FormatInt(session.UserID, 10)) +} + +func zgameSignatureValid(openID string, session string, signature string, secret string) bool { + openID = strings.TrimSpace(openID) + session = strings.TrimSpace(session) + secret = strings.TrimSpace(secret) + signature = strings.TrimSpace(signature) + if openID == "" || session == "" || secret == "" || signature == "" { + return false + } + sum := sha256.Sum256([]byte(openID + session + secret)) + expected := hex.EncodeToString(sum[:]) + return subtle.ConstantTimeCompare([]byte(strings.ToLower(signature)), []byte(expected)) == 1 +} + +func zgameLoginData(session gamedomain.LaunchSession, config zgameAdapterConfig, token string, snapshot yomiUserSnapshot, now time.Time) map[string]any { + openID := externalUserID(session, config.UIDMode) + return map[string]any{ + "session": token, + "session_expired": zgameSessionTTLMS(session, now), + "openId": openID, + "userName": snapshot.Nickname, + "nickname": snapshot.Nickname, + "avatar": snapshot.Avatar, + "balance": snapshot.Balance, + "level": config.Level, + "country": "", + "gender": config.Gender, + "sex": config.Gender, + } +} + +func (s *Service) zgameUserInfoForOpenID(ctx context.Context, app string, config zgameAdapterConfig, req *gamev1.CallbackRequest, session gamedomain.LaunchSession, openID string) (map[string]any, bool) { + userID := int64(0) + if openID == externalUserID(session, config.UIDMode) || openID == strings.TrimSpace(session.DisplayUserID) { + userID = session.UserID + } else if !strings.EqualFold(config.UIDMode, "display_user_id") { + // 批量查询没有 display_id -> user_id 解析依赖;默认 user_id 模式可直接按 open_id 查用户资料。 + parsed, err := strconv.ParseInt(openID, 10, 64) + if err == nil && parsed > 0 { + userID = parsed + } + } + if userID <= 0 { + return nil, false + } + snapshot, err := s.yomiUserSnapshot(ctx, app, req, userID) + if err != nil { + return nil, false + } + return zgameUserInfoData(config, snapshot), true +} + +func zgameUserInfoData(config zgameAdapterConfig, snapshot yomiUserSnapshot) map[string]any { + return map[string]any{ + "userName": snapshot.Nickname, + "nickname": snapshot.Nickname, + "gender": config.Gender, + "level": config.Level, + "avatar": snapshot.Avatar, + "balance": snapshot.Balance, + } +} + +func zgameSessionTTLMS(session gamedomain.LaunchSession, now time.Time) int64 { + if session.ExpiresAtMS <= 0 { + return int64(zgameDefaultTokenTTL / time.Millisecond) + } + ttl := session.ExpiresAtMS - now.UnixMilli() + if ttl < 0 { + return 0 + } + return ttl +} + +func zgameAmount(value json.Number) (int64, bool) { + raw := strings.TrimSpace(value.String()) + if raw == "" { + return 0, false + } + amount, err := strconv.ParseInt(raw, 10, 64) + if err != nil { + return 0, false + } + return amount, true +} + +func zgameOpType(op int32, amount int64) (string, int64) { + if amount == -1<<63 { + return "", -1 + } + coinAmount := amount + if coinAmount < 0 { + coinAmount = -coinAmount + } + if amount < 0 || op == 1 { + return "credit", coinAmount + } + if op == 0 { + return "debit", coinAmount + } + return "", coinAmount +} + +func zgameProviderOrderID(orderID string, opType string) string { + orderID = strings.TrimSpace(orderID) + opType = strings.TrimSpace(opType) + if orderID == "" || opType == "" { + return orderID + } + return orderID + ":" + opType +} + +func zgameAnyString(value any) string { + switch typed := value.(type) { + case nil: + return "" + case string: + return strings.TrimSpace(typed) + case json.Number: + return strings.TrimSpace(typed.String()) + case float64: + if typed == math.Trunc(typed) { + return strconv.FormatInt(int64(typed), 10) + } + return strconv.FormatFloat(typed, 'f', -1, 64) + case float32: + return strconv.FormatFloat(float64(typed), 'f', -1, 32) + case int: + return strconv.Itoa(typed) + case int64: + return strconv.FormatInt(typed, 10) + case int32: + return strconv.FormatInt(int64(typed), 10) + case uint64: + return strconv.FormatUint(typed, 10) + default: + return strings.TrimSpace(fmt.Sprint(value)) + } +} + +func zgameAdapterError(code int, message string, signatureValid bool, providerRequestID string) ([]byte, string, string, bool, string, error) { + raw, contentType := zgameJSON(code, message, nil) + return raw, contentType, strconv.Itoa(code), signatureValid, strings.TrimSpace(providerRequestID), nil +} + +func zgameJSON(code int, message string, data any) ([]byte, string) { + if strings.TrimSpace(message) == "" && code == zgameCodeOK { + message = "success" + } + return jsonResponse(map[string]any{ + "code": code, + "errmsg": strings.TrimSpace(message), + "data": data, + }) +} + +func zgameBalanceJSON(code int, message string, balance int64) ([]byte, string) { + if strings.TrimSpace(message) == "" && code == zgameCodeOK { + message = "success" + } + return jsonResponse(map[string]any{ + "code": code, + "errmsg": strings.TrimSpace(message), + "balance": balance, + "data": map[string]any{ + "balance": balance, + }, + }) +} + +func zgameCodeFromError(err error) int { + switch { + case err == nil: + return zgameCodeOK + case xerr.IsCode(err, xerr.InsufficientBalance): + return zgameCodeInsufficientBalance + case xerr.IsCode(err, xerr.SessionExpired), xerr.IsCode(err, xerr.Unauthorized): + return zgameCodeUnauthorized + default: + return zgameCodeInternalError + } +} + +func zgameMessageFromError(err error) string { + switch zgameCodeFromError(err) { + case zgameCodeInsufficientBalance: + return "Insufficient Funds" + case zgameCodeUnauthorized: + return "Unauthorized" + case zgameCodeOK: + return "success" + default: + return "Internal Error" + } +} diff --git a/services/game-service/internal/transport/grpc/server.go b/services/game-service/internal/transport/grpc/server.go index 7a0024f5..9399fd4b 100644 --- a/services/game-service/internal/transport/grpc/server.go +++ b/services/game-service/internal/transport/grpc/server.go @@ -1165,6 +1165,8 @@ func normalizeAdapterType(adapterType string) string { return gamedomain.AdapterVivaGamesV1 case gamedomain.AdapterReyouV1: return gamedomain.AdapterReyouV1 + case gamedomain.AdapterZGameV1: + return gamedomain.AdapterZGameV1 default: return "" } diff --git a/services/game-service/internal/transport/grpc/server_test.go b/services/game-service/internal/transport/grpc/server_test.go index 1ec25ef9..3e8c65ba 100644 --- a/services/game-service/internal/transport/grpc/server_test.go +++ b/services/game-service/internal/transport/grpc/server_test.go @@ -26,7 +26,7 @@ func TestPlatformToProtoExposesCallbackSecretForAdmin(t *testing.T) { func TestNormalizePlatformAcceptsProviderAdapters(t *testing.T) { // 平台创建入口会先规范化 adapter_type;新增厂商必须在这里放行,否则后台配置页会被 gRPC 直接拒绝。 - for _, adapterType := range []string{gamedomain.AdapterVivaGamesV1, gamedomain.AdapterReyouV1} { + for _, adapterType := range []string{gamedomain.AdapterVivaGamesV1, gamedomain.AdapterReyouV1, gamedomain.AdapterZGameV1} { got, err := normalizePlatform(gamedomain.Platform{ PlatformCode: strings.TrimSuffix(adapterType, "_v1"), PlatformName: adapterType, diff --git a/services/gateway-service/internal/transport/http/game_handler_test.go b/services/gateway-service/internal/transport/http/game_handler_test.go index 9ea76209..5863b808 100644 --- a/services/gateway-service/internal/transport/http/game_handler_test.go +++ b/services/gateway-service/internal/transport/http/game_handler_test.go @@ -554,6 +554,25 @@ func TestGameCallbackIsRawPublicResponse(t *testing.T) { } } +func TestZGameFixedCallbackRouteIsRawPublicResponse(t *testing.T) { + gameClient := &fakeGatewayGameClient{callbackResp: &gamev1.CallbackResponse{RawBody: []byte(`{"code":0,"errmsg":"success"}`), ContentType: "application/json"}} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) + handler.SetGameClient(gameClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/zgame/callback/api/server/login?nonce=1", bytes.NewReader([]byte(`{"open_id":"420001"}`))) + request.Header.Set("X-App-Code", "lalu") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK || recorder.Body.String() != `{"code":0,"errmsg":"success"}` { + t.Fatalf("zgame callback response must not use app envelope: status=%d body=%s", recorder.Code, recorder.Body.String()) + } + if gameClient.lastCallback.GetPlatformCode() != "zgame" || gameClient.lastCallback.GetOperation() != "server/login" || string(gameClient.lastCallback.GetRawBody()) != `{"open_id":"420001"}` || gameClient.lastCallback.GetQuery()["nonce"] != "1" { + t.Fatalf("zgame callback request mismatch: %+v", gameClient.lastCallback) + } +} + func TestHotgameCompatFallbacksToHyappReyouCallback(t *testing.T) { body := `{"gameId":"101","uid":"420001","token":"hyapp-token","sign":"s"}` gameClient := &fakeGatewayGameClient{callbackResp: &gamev1.CallbackResponse{RawBody: []byte(`{"errorCode":0}`), ContentType: "application/json"}} diff --git a/services/gateway-service/internal/transport/http/gameapi/game_handler.go b/services/gateway-service/internal/transport/http/gameapi/game_handler.go index 0aa1e52e..93fde676 100644 --- a/services/gateway-service/internal/transport/http/gameapi/game_handler.go +++ b/services/gateway-service/internal/transport/http/gameapi/game_handler.go @@ -26,6 +26,7 @@ const ( hyappExpiresInHeader = "X-Hyapp-Expires-In" selfGameIDDice = "dice" selfGameIDRock = "rock" + zgameCallbackPlatformCode = "zgame" ) func (h *Handler) listGames(writer http.ResponseWriter, request *http.Request) { @@ -763,6 +764,22 @@ func (h *Handler) handleGameCallback(writer http.ResponseWriter, request *http.R h.handleGameCallbackRaw(writer, request, raw, platformCode, operation) } +func (h *Handler) handleZGameCallback(writer http.ResponseWriter, request *http.Request) { + raw, err := io.ReadAll(request.Body) + if err != nil { + http.Error(writer, "invalid request body", http.StatusBadRequest) + return + } + operation := strings.Trim(strings.TrimSpace(request.PathValue("operation")), "/") + operation = strings.TrimPrefix(operation, "api/") + if operation == "" { + http.Error(writer, "invalid callback operation", http.StatusBadRequest) + return + } + // ZGame 后台只能配置固定 callback 前缀;gateway 只把固定尾段映射为 adapter operation,具体协议和钱包语义仍归 game-service。 + h.handleGameCallbackRaw(writer, request, raw, zgameCallbackPlatformCode, operation) +} + func (h *Handler) handleGameCallbackRaw(writer http.ResponseWriter, request *http.Request, raw []byte, platformCode string, operation string) { if h.gameClient == nil { http.Error(writer, "upstream service error", http.StatusBadGateway) diff --git a/services/gateway-service/internal/transport/http/gameapi/handler.go b/services/gateway-service/internal/transport/http/gameapi/handler.go index e9377b53..f3128257 100644 --- a/services/gateway-service/internal/transport/http/gameapi/handler.go +++ b/services/gateway-service/internal/transport/http/gameapi/handler.go @@ -66,6 +66,7 @@ func (h *Handler) Handlers() httproutes.GameHandlers { AcceptRoomRPSChallenge: h.acceptRoomRPSChallenge, GetRoomRPSChallenge: h.getRoomRPSChallenge, HandleCallback: h.handleGameCallback, + HandleZGameCallback: h.handleZGameCallback, HandleHotgameGetUserInfo: h.handleHotgameGetUserInfo, HandleHotgameUpdateBalance: h.handleHotgameUpdateBalance, } diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index c32dd700..817f95ef 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -309,6 +309,7 @@ type GameHandlers struct { AcceptRoomRPSChallenge http.HandlerFunc GetRoomRPSChallenge http.HandlerFunc HandleCallback http.HandlerFunc + HandleZGameCallback http.HandlerFunc HandleHotgameGetUserInfo http.HandlerFunc HandleHotgameUpdateBalance http.HandlerFunc } @@ -666,5 +667,6 @@ func (r routes) registerGameRoutes() { // 热游后台只能配置根路径回调;这里仍复用 public wrapper,让请求日志、request_id 和 app_code 解析保持一致。 r.rootPublic("/getUserInfo", http.MethodPost, h.HandleHotgameGetUserInfo) r.rootPublic("/updateBalance", http.MethodPost, h.HandleHotgameUpdateBalance) + r.public("/zgame/callback/{operation...}", http.MethodPost, h.HandleZGameCallback) r.public("/game-callbacks/{platform_code}/{operation}", http.MethodPost, h.HandleCallback) } diff --git a/services/user-service/internal/domain/host/host.go b/services/user-service/internal/domain/host/host.go index 953386d9..8ed14cc3 100644 --- a/services/user-service/internal/domain/host/host.go +++ b/services/user-service/internal/domain/host/host.go @@ -118,6 +118,8 @@ const ( CommandTypeCreateAgency = "admin_create_agency" // CommandTypeCloseAgency 记录后台关闭 Agency 命令。 CommandTypeCloseAgency = "admin_close_agency" + // CommandTypeSetAgencyStatus 记录后台显式启用或关闭 Agency 命令。 + CommandTypeSetAgencyStatus = "admin_set_agency_status" // CommandTypeDeleteAgency 记录后台删除 Agency 身份命令。 CommandTypeDeleteAgency = "admin_delete_agency" // CommandTypeSetAgencyJoinEnabled 记录后台设置 Agency 入会开关命令。 diff --git a/services/user-service/internal/service/host/commands.go b/services/user-service/internal/service/host/commands.go index bb8a0e5c..5df3f964 100644 --- a/services/user-service/internal/service/host/commands.go +++ b/services/user-service/internal/service/host/commands.go @@ -346,6 +346,28 @@ type DeleteAgencyCommand struct { NowMs int64 } +// SetAgencyStatusInput 是后台显式切换 Agency 状态的外部输入。 +type SetAgencyStatusInput struct { + CommandID string + AdminUserID int64 + AgencyID int64 + Status string + Reason string + RequestID string +} + +// SetAgencyStatusCommand 是后台显式切换 Agency 状态事务需要的完整命令。 +type SetAgencyStatusCommand struct { + CommandID string + AdminUserID int64 + AgencyID int64 + Status string + Reason string + RequestID string + EventID int64 + NowMs int64 +} + // SetAgencyJoinEnabledInput 是后台设置 Agency 入会开关的外部输入。 type SetAgencyJoinEnabledInput struct { CommandID string diff --git a/services/user-service/internal/service/host/service.go b/services/user-service/internal/service/host/service.go index 89a7fc7e..fd04645a 100644 --- a/services/user-service/internal/service/host/service.go +++ b/services/user-service/internal/service/host/service.go @@ -35,6 +35,7 @@ type Repository interface { CreateAgency(ctx context.Context, command CreateAgencyCommand) (hostdomain.CreateAgencyResult, error) CloseAgency(ctx context.Context, command CloseAgencyCommand) (hostdomain.Agency, error) DeleteAgency(ctx context.Context, command DeleteAgencyCommand) (hostdomain.Agency, error) + SetAgencyStatus(ctx context.Context, command SetAgencyStatusCommand) (hostdomain.Agency, error) SetAgencyJoinEnabled(ctx context.Context, command SetAgencyJoinEnabledCommand) (hostdomain.Agency, error) GetHostProfile(ctx context.Context, userID int64) (hostdomain.HostProfile, error) BatchGetHostProfiles(ctx context.Context, userIDs []int64) (map[int64]hostdomain.HostProfile, error) @@ -566,6 +567,32 @@ func (s *Service) DeleteAgency(ctx context.Context, command DeleteAgencyInput) ( }) } +// SetAgencyStatus 显式切换 Agency 可用状态;closed 可恢复为 active,但 deleted 是删除事实,不能复活。 +func (s *Service) SetAgencyStatus(ctx context.Context, command SetAgencyStatusInput) (hostdomain.Agency, error) { + if err := s.requireWriteDependencies(); err != nil { + return hostdomain.Agency{}, err + } + status := normalizeStatus(command.Status) + if strings.TrimSpace(command.CommandID) == "" || command.AdminUserID <= 0 || command.AgencyID <= 0 { + return hostdomain.Agency{}, xerr.New(xerr.InvalidArgument, "command_id, admin_user_id and agency_id are required") + } + if status != hostdomain.AgencyStatusActive && status != hostdomain.AgencyStatusClosed { + return hostdomain.Agency{}, xerr.New(xerr.InvalidArgument, "agency status is invalid") + } + nowMs := s.now().UnixMilli() + + return s.repository.SetAgencyStatus(ctx, SetAgencyStatusCommand{ + CommandID: strings.TrimSpace(command.CommandID), + AdminUserID: command.AdminUserID, + AgencyID: command.AgencyID, + Status: status, + Reason: strings.TrimSpace(command.Reason), + RequestID: strings.TrimSpace(command.RequestID), + EventID: s.idGenerator.NewInt64(), + NowMs: nowMs, + }) +} + // SetAgencyJoinEnabled 设置 Agency 是否允许 App 用户申请加入。 func (s *Service) SetAgencyJoinEnabled(ctx context.Context, command SetAgencyJoinEnabledInput) (hostdomain.Agency, error) { if err := s.requireWriteDependencies(); err != nil { diff --git a/services/user-service/internal/service/host/service_test.go b/services/user-service/internal/service/host/service_test.go index 83fb4fef..733ced37 100644 --- a/services/user-service/internal/service/host/service_test.go +++ b/services/user-service/internal/service/host/service_test.go @@ -700,6 +700,36 @@ func TestAdminCreateAgencyControlsAppSearch(t *testing.T) { t.Fatalf("closed agency mismatch: %+v", closed) } + reopened, err := svc.SetAgencyStatus(ctx, hostservice.SetAgencyStatusInput{ + CommandID: "admin-reopen-agency-901", + AdminUserID: 1, + AgencyID: created.Agency.AgencyID, + Status: hostdomain.AgencyStatusActive, + Reason: "reopen agency", + RequestID: "req-agency-status-1", + }) + if err != nil { + t.Fatalf("SetAgencyStatus active failed: %v", err) + } + if reopened.Status != hostdomain.AgencyStatusActive || reopened.JoinEnabled { + t.Fatalf("reopened agency should keep join disabled until admin explicitly opens it: %+v", reopened) + } + + enabledJoin, err := svc.SetAgencyJoinEnabled(ctx, hostservice.SetAgencyJoinEnabledInput{ + CommandID: "admin-enable-agency-join-901", + AdminUserID: 1, + AgencyID: created.Agency.AgencyID, + JoinEnabled: true, + Reason: "resume join", + RequestID: "req-agency-join-2", + }) + if err != nil { + t.Fatalf("SetAgencyJoinEnabled after reopen failed: %v", err) + } + if !enabledJoin.JoinEnabled { + t.Fatalf("agency join should be enabled after explicit open: %+v", enabledJoin) + } + deleted, err := svc.DeleteAgency(ctx, hostservice.DeleteAgencyInput{ CommandID: "admin-delete-agency-901", AdminUserID: 1, diff --git a/services/user-service/internal/storage/mysql/host/admin.go b/services/user-service/internal/storage/mysql/host/admin.go index 6d9834aa..f894ab87 100644 --- a/services/user-service/internal/storage/mysql/host/admin.go +++ b/services/user-service/internal/storage/mysql/host/admin.go @@ -442,6 +442,53 @@ func (r *Repository) DeleteAgency(ctx context.Context, command hostservice.Delet return agency, nil } +// SetAgencyStatus 显式切换 Agency 状态;关闭会同步关入会,恢复只恢复组织本体,避免误把申请入口重新放开。 +func (r *Repository) SetAgencyStatus(ctx context.Context, command hostservice.SetAgencyStatusCommand) (hostdomain.Agency, error) { + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return hostdomain.Agency{}, err + } + defer tx.Rollback() + + if existing, ok, err := commandResult(ctx, tx, command.CommandID); err != nil { + return hostdomain.Agency{}, err + } else if ok { + if err := requireCommandResult(existing, hostdomain.CommandTypeSetAgencyStatus, hostdomain.ResultTypeAgency); err != nil { + return hostdomain.Agency{}, err + } + return queryAgency(ctx, tx, "WHERE agency_id = ?", existing.ResultID) + } + + agency, err := queryAgency(ctx, tx, "WHERE agency_id = ? FOR UPDATE", command.AgencyID) + if err != nil { + return hostdomain.Agency{}, err + } + if agency.Status == hostdomain.AgencyStatusDeleted { + // deleted 已经解除当前 Agency 归属,是删除事实;重新激活会破坏 host_profile 当前归属和历史 membership 语义。 + return hostdomain.Agency{}, xerr.New(xerr.Conflict, "deleted agency cannot be reopened") + } + + agency.Status = command.Status + if command.Status == hostdomain.AgencyStatusClosed { + // 关闭组织必须同时停止 App 申请入口;重新 active 时保留当前 join_enabled,让管理员显式决定是否开放入会。 + agency.JoinEnabled = false + } + agency.UpdatedAtMs = command.NowMs + if err := updateAgencyAdminState(ctx, tx, agency); err != nil { + return hostdomain.Agency{}, mapHostDuplicateError(err) + } + if err := insertCommandResult(ctx, tx, hostdomain.CommandResult{CommandID: command.CommandID, CommandType: hostdomain.CommandTypeSetAgencyStatus, ResultType: hostdomain.ResultTypeAgency, ResultID: agency.AgencyID, CreatedAtMs: command.NowMs}); err != nil { + return hostdomain.Agency{}, mapHostDuplicateError(err) + } + if err := insertHostOutbox(ctx, tx, command.EventID, "AgencyChanged", "agency", agency.AgencyID, command.NowMs); err != nil { + return hostdomain.Agency{}, err + } + if err := tx.Commit(); err != nil { + return hostdomain.Agency{}, err + } + return agency, nil +} + // SetAgencyJoinEnabled 调整 Agency 入会开关。 func (r *Repository) SetAgencyJoinEnabled(ctx context.Context, command hostservice.SetAgencyJoinEnabledCommand) (hostdomain.Agency, error) { return r.updateAgencyAdmin(ctx, command.CommandID, hostdomain.CommandTypeSetAgencyJoinEnabled, command.AgencyID, command.EventID, command.NowMs, func(agency hostdomain.Agency) hostdomain.Agency { diff --git a/services/user-service/internal/transport/grpc/host_admin.go b/services/user-service/internal/transport/grpc/host_admin.go index cdd5ee6a..0b23b7a9 100644 --- a/services/user-service/internal/transport/grpc/host_admin.go +++ b/services/user-service/internal/transport/grpc/host_admin.go @@ -172,6 +172,26 @@ func (s *Server) DeleteAgency(ctx context.Context, req *userv1.DeleteAgencyReque return &userv1.DeleteAgencyResponse{Agency: toProtoAgency(agency)}, nil } +// SetAgencyStatus 处理后台显式切换 Agency 状态;恢复 closed 不自动开放 join_enabled。 +func (s *Server) SetAgencyStatus(ctx context.Context, req *userv1.SetAgencyStatusRequest) (*userv1.SetAgencyStatusResponse, error) { + if s.hostSvc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) + } + ctx = contextWithApp(ctx, req.GetMeta()) + agency, err := s.hostSvc.SetAgencyStatus(ctx, hostservice.SetAgencyStatusInput{ + CommandID: req.GetCommandId(), + AdminUserID: req.GetAdminUserId(), + AgencyID: req.GetAgencyId(), + Status: req.GetStatus(), + Reason: req.GetReason(), + RequestID: req.GetMeta().GetRequestId(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &userv1.SetAgencyStatusResponse{Agency: toProtoAgency(agency)}, nil +} + // SetAgencyJoinEnabled 处理后台设置 Agency 入会开关。 func (s *Server) SetAgencyJoinEnabled(ctx context.Context, req *userv1.SetAgencyJoinEnabledRequest) (*userv1.SetAgencyJoinEnabledResponse, error) { if s.hostSvc == nil {