Add basic account security

This adds a secret token associated with each account

	The token must then be sent with follow-up requests to ensure they get accepted

	This is _very_ basic security, and without TLS is completely vulnerable to MITM attacks, as well as brute force guessing (though it'd take a while to guess the a correct UUID)
This commit is contained in:
Marc Di Luzio 2020-07-07 22:20:23 +01:00
parent df30a0d689
commit 92222127a6
7 changed files with 413 additions and 232 deletions

View file

@ -80,47 +80,69 @@ func TestServer_Register(t *testing.T) {
func TestServer_Command(t *testing.T) { func TestServer_Command(t *testing.T) {
acc := uuid.New().String() acc := uuid.New().String()
err := serv.Request("POST", "register", &rove.RegisterRequest{Name: acc}, &rove.RegisterResponse{}) var resp rove.RegisterResponse
err := serv.Request("POST", "register", &rove.RegisterRequest{Name: acc}, &resp)
assert.NoError(t, err, "First register attempt should pass") assert.NoError(t, err, "First register attempt should pass")
err = serv.Request("POST", "command", &rove.CommandRequest{ req := &rove.CommandRequest{
Account: acc, Account: &rove.Account{
Name: resp.Account.Name,
},
Commands: []*rove.Command{ Commands: []*rove.Command{
{ {
Command: "move", Command: "move",
Bearing: "NE", Bearing: "NE",
}, },
}, },
}, &rove.CommandResponse{}) }
assert.NoError(t, err, "Commands should should pass")
assert.Error(t, serv.Request("POST", "command", req, &rove.CommandResponse{}), "Commands should fail with no secret")
req.Account.Secret = resp.Account.Secret
assert.NoError(t, serv.Request("POST", "command", req, &rove.CommandResponse{}), "Commands should pass")
} }
func TestServer_Radar(t *testing.T) { func TestServer_Radar(t *testing.T) {
acc := uuid.New().String() acc := uuid.New().String()
err := serv.Request("POST", "register", &rove.RegisterRequest{Name: acc}, &rove.RegisterResponse{}) var reg rove.RegisterResponse
err := serv.Request("POST", "register", &rove.RegisterRequest{Name: acc}, &reg)
assert.NoError(t, err, "First register attempt should pass") assert.NoError(t, err, "First register attempt should pass")
resp := &rove.RadarResponse{} resp := &rove.RadarResponse{}
err = serv.Request("POST", "radar", &rove.RadarRequest{ req := &rove.RadarRequest{
Account: acc, Account: &rove.Account{
}, resp) Name: reg.Account.Name,
assert.NoError(t, err, "Radar sould pass should pass") },
}
assert.Error(t, serv.Request("POST", "radar", req, resp), "Radar should fail without secret")
req.Account.Secret = reg.Account.Secret
assert.NoError(t, serv.Request("POST", "radar", req, resp), "Radar should pass")
assert.NotZero(t, resp.Range, "Radar should return valid range") assert.NotZero(t, resp.Range, "Radar should return valid range")
w := int(resp.Range*2 + 1) w := int(resp.Range*2 + 1)
assert.Equal(t, w*w, len(resp.Tiles), "radar should return correct number of tiles") assert.Equal(t, w*w, len(resp.Tiles), "radar should return correct number of tiles")
assert.Equal(t, w*w, len(resp.Objects), "radar should return correct number of objects") assert.Equal(t, w*w, len(resp.Objects), "radar should return correct number of objects")
} }
func TestServer_Rover(t *testing.T) { func TestServer_Status(t *testing.T) {
acc := uuid.New().String() acc := uuid.New().String()
err := serv.Request("POST", "register", &rove.RegisterRequest{Name: acc}, &rove.RegisterResponse{}) var reg rove.RegisterResponse
err := serv.Request("POST", "register", &rove.RegisterRequest{Name: acc}, &reg)
assert.NoError(t, err, "First register attempt should pass") assert.NoError(t, err, "First register attempt should pass")
resp := &rove.StatusResponse{} resp := &rove.StatusResponse{}
err = serv.Request("POST", "status", &rove.StatusRequest{ req := &rove.StatusRequest{
Account: acc, Account: &rove.Account{
}, resp) Name: reg.Account.Name,
assert.NoError(t, err, "Rover sould pass should pass") },
}
assert.Error(t, serv.Request("POST", "status", req, resp), "Status should fail without secret")
req.Account.Secret = reg.Account.Secret
assert.NoError(t, serv.Request("POST", "status", req, resp), "Status should pass")
assert.NotZero(t, resp.Range, "Rover should return valid range") assert.NotZero(t, resp.Range, "Rover should return valid range")
assert.NotZero(t, len(resp.Name), "Rover should return valid name") assert.NotZero(t, len(resp.Name), "Rover should return valid name")
assert.NotZero(t, resp.Position, "Rover should return valid position") assert.NotZero(t, resp.Position, "Rover should return valid position")

View file

@ -34,7 +34,7 @@ func (s *Server) Register(ctx context.Context, req *rove.RegisterRequest) (*rove
return nil, fmt.Errorf("empty account name") return nil, fmt.Errorf("empty account name")
} }
if _, err := s.accountant.RegisterAccount(req.Name); err != nil { if acc, err := s.accountant.RegisterAccount(req.Name); err != nil {
return nil, err return nil, err
} else if _, err := s.SpawnRoverForAccount(req.Name); err != nil { } else if _, err := s.SpawnRoverForAccount(req.Name); err != nil {
@ -42,17 +42,26 @@ func (s *Server) Register(ctx context.Context, req *rove.RegisterRequest) (*rove
} else if err := s.SaveWorld(); err != nil { } else if err := s.SaveWorld(); err != nil {
return nil, fmt.Errorf("internal server error when saving world: %s", err) return nil, fmt.Errorf("internal server error when saving world: %s", err)
}
return &rove.RegisterResponse{}, nil } else {
return &rove.RegisterResponse{
Account: &rove.Account{
Name: acc.Name,
Secret: acc.Data["secret"],
},
}, nil
}
} }
// Status returns rover information for a gRPC request // Status returns rover information for a gRPC request
func (s *Server) Status(ctx context.Context, req *rove.StatusRequest) (response *rove.StatusResponse, err error) { func (s *Server) Status(ctx context.Context, req *rove.StatusRequest) (response *rove.StatusResponse, err error) {
if len(req.Account) == 0 { if valid, err := s.accountant.VerifySecret(req.Account.Name, req.Account.Secret); err != nil {
return nil, fmt.Errorf("empty account name") return nil, err
} else if resp, err := s.accountant.GetValue(req.Account, "rover"); err != nil { } else if !valid {
return nil, fmt.Errorf("Secret incorrect for account %s", req.Account.Name)
} else if resp, err := s.accountant.GetValue(req.Account.Name, "rover"); err != nil {
return nil, err return nil, err
} else if rover, err := s.world.GetRover(resp); err != nil { } else if rover, err := s.world.GetRover(resp); err != nil {
@ -101,13 +110,16 @@ func (s *Server) Status(ctx context.Context, req *rove.StatusRequest) (response
// Radar returns the radar information for a rover // Radar returns the radar information for a rover
func (s *Server) Radar(ctx context.Context, req *rove.RadarRequest) (*rove.RadarResponse, error) { func (s *Server) Radar(ctx context.Context, req *rove.RadarRequest) (*rove.RadarResponse, error) {
if len(req.Account) == 0 { if valid, err := s.accountant.VerifySecret(req.Account.Name, req.Account.Secret); err != nil {
return nil, fmt.Errorf("empty account name") return nil, err
} else if !valid {
return nil, fmt.Errorf("Secret incorrect for account %s", req.Account.Name)
} }
response := &rove.RadarResponse{} response := &rove.RadarResponse{}
resp, err := s.accountant.GetValue(req.Account, "rover") resp, err := s.accountant.GetValue(req.Account.Name, "rover")
if err != nil { if err != nil {
return nil, err return nil, err
@ -128,10 +140,14 @@ func (s *Server) Radar(ctx context.Context, req *rove.RadarRequest) (*rove.Radar
// Command issues commands to the world based on a gRPC request // Command issues commands to the world based on a gRPC request
func (s *Server) Command(ctx context.Context, req *rove.CommandRequest) (*rove.CommandResponse, error) { func (s *Server) Command(ctx context.Context, req *rove.CommandRequest) (*rove.CommandResponse, error) {
if len(req.Account) == 0 { if valid, err := s.accountant.VerifySecret(req.Account.Name, req.Account.Secret); err != nil {
return nil, fmt.Errorf("empty account") return nil, err
} else if !valid {
return nil, fmt.Errorf("Secret incorrect for account %s", req.Account.Name)
} }
resp, err := s.accountant.GetValue(req.Account, "rover")
resp, err := s.accountant.GetValue(req.Account.Name, "rover")
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -48,7 +48,8 @@ const gRPCport = 9090
// Account stores data for an account // Account stores data for an account
type Account struct { type Account struct {
Name string `json:"name"` Name string `json:"name"`
Secret string `json:"secret"`
} }
// Config is used to store internal data // Config is used to store internal data
@ -114,10 +115,12 @@ func SaveConfig(config Config) error {
return nil return nil
} }
// verifyID will verify an account ID // checkAccount will verify an account ID
func verifyID(id string) error { func checkAccount(a Account) error {
if len(id) == 0 { if len(a.Name) == 0 {
return fmt.Errorf("no account ID set, must register first") return fmt.Errorf("no account ID set, must register first")
} else if len(a.Secret) == 0 {
return fmt.Errorf("empty account secret, must register first")
} }
return nil return nil
} }
@ -181,26 +184,27 @@ func InnerMain(command string, args ...string) error {
} }
case "register": case "register":
if len(args) == 0 { if len(args) == 0 || len(args[0]) == 0 {
return fmt.Errorf("must pass name to 'register'") return fmt.Errorf("must pass name to 'register'")
} }
name := args[0] resp, err := client.Register(ctx, &rove.RegisterRequest{
d := rove.RegisterRequest{ Name: args[0],
Name: name, })
}
_, err := client.Register(ctx, &d)
switch { switch {
case err != nil: case err != nil:
return err return err
default: default:
fmt.Printf("Registered account with id: %s\n", name) fmt.Printf("Registered account with id: %s\n", resp.Account.Name)
config.Account.Name = name config.Account.Name = resp.Account.Name
config.Account.Secret = resp.Account.Secret
} }
case "command": case "command":
if len(args) == 0 { if err := checkAccount(config.Account); err != nil {
return err
} else if len(args) == 0 {
return fmt.Errorf("must pass commands to 'commands'") return fmt.Errorf("must pass commands to 'commands'")
} }
@ -231,16 +235,14 @@ func InnerMain(command string, args ...string) error {
} }
} }
d := rove.CommandRequest{ _, err := client.Command(ctx, &rove.CommandRequest{
Account: config.Account.Name, Account: &rove.Account{
Name: config.Account.Name,
Secret: config.Account.Secret,
},
Commands: commands, Commands: commands,
} })
if err := verifyID(d.Account); err != nil {
return err
}
_, err := client.Command(ctx, &d)
switch { switch {
case err != nil: case err != nil:
return err return err
@ -250,12 +252,17 @@ func InnerMain(command string, args ...string) error {
} }
case "radar": case "radar":
dat := rove.RadarRequest{Account: config.Account.Name} if err := checkAccount(config.Account); err != nil {
if err := verifyID(dat.Account); err != nil {
return err return err
} }
response, err := client.Radar(ctx, &dat) response, err := client.Radar(ctx, &rove.RadarRequest{
Account: &rove.Account{
Name: config.Account.Name,
Secret: config.Account.Secret,
},
})
switch { switch {
case err != nil: case err != nil:
return err return err
@ -282,11 +289,16 @@ func InnerMain(command string, args ...string) error {
} }
case "status": case "status":
req := rove.StatusRequest{Account: config.Account.Name} if err := checkAccount(config.Account); err != nil {
if err := verifyID(req.Account); err != nil {
return err return err
} }
response, err := client.Status(ctx, &req)
response, err := client.Status(ctx, &rove.StatusRequest{
Account: &rove.Account{
Name: config.Account.Name,
Secret: config.Account.Secret,
},
})
switch { switch {
case err != nil: case err != nil:

View file

@ -3,6 +3,8 @@ package accounts
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/google/uuid"
) )
// Account represents a registered user // Account represents a registered user
@ -29,7 +31,7 @@ func NewAccountant() *Accountant {
// RegisterAccount adds an account to the set of internal accounts // RegisterAccount adds an account to the set of internal accounts
func (a *Accountant) RegisterAccount(name string) (acc Account, err error) { func (a *Accountant) RegisterAccount(name string) (acc Account, err error) {
// Set the account name // Set up the account info
acc.Name = name acc.Name = name
acc.Data = make(map[string]string) acc.Data = make(map[string]string)
@ -43,12 +45,25 @@ func (a *Accountant) RegisterAccount(name string) (acc Account, err error) {
// Set the creation time // Set the creation time
acc.Data["created"] = time.Now().String() acc.Data["created"] = time.Now().String()
// Create a secret
acc.Data["secret"] = uuid.New().String()
// Simply add the account to the map // Simply add the account to the map
a.Accounts[acc.Name] = acc a.Accounts[acc.Name] = acc
return return
} }
// VerifySecret verifies if an account secret is correct
func (a *Accountant) VerifySecret(account string, secret string) (bool, error) {
// Find the account matching the ID
if this, ok := a.Accounts[account]; ok {
return this.Data["secret"] == secret, nil
}
return false, fmt.Errorf("no account found for id: %s", account)
}
// AssignData assigns data to an account // AssignData assigns data to an account
func (a *Accountant) AssignData(account string, key string, value string) error { func (a *Accountant) AssignData(account string, key string, value string) error {

View file

@ -101,7 +101,7 @@ type CommandRequest struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// The account to execute these commands // The account to execute these commands
Account string `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
// The set of desired commands // The set of desired commands
Commands []*Command `protobuf:"bytes,2,rep,name=commands,proto3" json:"commands,omitempty"` Commands []*Command `protobuf:"bytes,2,rep,name=commands,proto3" json:"commands,omitempty"`
} }
@ -138,11 +138,11 @@ func (*CommandRequest) Descriptor() ([]byte, []int) {
return file_rove_rove_proto_rawDescGZIP(), []int{1} return file_rove_rove_proto_rawDescGZIP(), []int{1}
} }
func (x *CommandRequest) GetAccount() string { func (x *CommandRequest) GetAccount() *Account {
if x != nil { if x != nil {
return x.Account return x.Account
} }
return "" return nil
} }
func (x *CommandRequest) GetCommands() []*Command { func (x *CommandRequest) GetCommands() []*Command {
@ -245,7 +245,7 @@ type RadarRequest struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// The account for this request // The account for this request
Account string `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
} }
func (x *RadarRequest) Reset() { func (x *RadarRequest) Reset() {
@ -280,11 +280,11 @@ func (*RadarRequest) Descriptor() ([]byte, []int) {
return file_rove_rove_proto_rawDescGZIP(), []int{4} return file_rove_rove_proto_rawDescGZIP(), []int{4}
} }
func (x *RadarRequest) GetAccount() string { func (x *RadarRequest) GetAccount() *Account {
if x != nil { if x != nil {
return x.Account return x.Account
} }
return "" return nil
} }
type RadarResponse struct { type RadarResponse struct {
@ -353,45 +353,6 @@ func (x *RadarResponse) GetObjects() []byte {
return nil return nil
} }
// Empty placeholder
type RegisterResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *RegisterResponse) Reset() {
*x = RegisterResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_rove_rove_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RegisterResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RegisterResponse) ProtoMessage() {}
func (x *RegisterResponse) ProtoReflect() protoreflect.Message {
mi := &file_rove_rove_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RegisterResponse.ProtoReflect.Descriptor instead.
func (*RegisterResponse) Descriptor() ([]byte, []int) {
return file_rove_rove_proto_rawDescGZIP(), []int{6}
}
type RegisterRequest struct { type RegisterRequest struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -404,7 +365,7 @@ type RegisterRequest struct {
func (x *RegisterRequest) Reset() { func (x *RegisterRequest) Reset() {
*x = RegisterRequest{} *x = RegisterRequest{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_rove_rove_proto_msgTypes[7] mi := &file_rove_rove_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -417,7 +378,7 @@ func (x *RegisterRequest) String() string {
func (*RegisterRequest) ProtoMessage() {} func (*RegisterRequest) ProtoMessage() {}
func (x *RegisterRequest) ProtoReflect() protoreflect.Message { func (x *RegisterRequest) ProtoReflect() protoreflect.Message {
mi := &file_rove_rove_proto_msgTypes[7] mi := &file_rove_rove_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -430,7 +391,7 @@ func (x *RegisterRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RegisterRequest.ProtoReflect.Descriptor instead. // Deprecated: Use RegisterRequest.ProtoReflect.Descriptor instead.
func (*RegisterRequest) Descriptor() ([]byte, []int) { func (*RegisterRequest) Descriptor() ([]byte, []int) {
return file_rove_rove_proto_rawDescGZIP(), []int{7} return file_rove_rove_proto_rawDescGZIP(), []int{6}
} }
func (x *RegisterRequest) GetName() string { func (x *RegisterRequest) GetName() string {
@ -440,13 +401,62 @@ func (x *RegisterRequest) GetName() string {
return "" return ""
} }
// Empty placeholder
type RegisterResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The registered account information
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
}
func (x *RegisterResponse) Reset() {
*x = RegisterResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_rove_rove_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RegisterResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RegisterResponse) ProtoMessage() {}
func (x *RegisterResponse) ProtoReflect() protoreflect.Message {
mi := &file_rove_rove_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RegisterResponse.ProtoReflect.Descriptor instead.
func (*RegisterResponse) Descriptor() ([]byte, []int) {
return file_rove_rove_proto_rawDescGZIP(), []int{7}
}
func (x *RegisterResponse) GetAccount() *Account {
if x != nil {
return x.Account
}
return nil
}
type StatusRequest struct { type StatusRequest struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// The account for this request // The account for this request
Account string `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
} }
func (x *StatusRequest) Reset() { func (x *StatusRequest) Reset() {
@ -481,11 +491,11 @@ func (*StatusRequest) Descriptor() ([]byte, []int) {
return file_rove_rove_proto_rawDescGZIP(), []int{8} return file_rove_rove_proto_rawDescGZIP(), []int{8}
} }
func (x *StatusRequest) GetAccount() string { func (x *StatusRequest) GetAccount() *Account {
if x != nil { if x != nil {
return x.Account return x.Account
} }
return "" return nil
} }
type StatusResponse struct { type StatusResponse struct {
@ -804,6 +814,61 @@ func (x *Vector) GetY() int32 {
return 0 return 0
} }
type Account struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Secret string `protobuf:"bytes,2,opt,name=secret,proto3" json:"secret,omitempty"`
}
func (x *Account) Reset() {
*x = Account{}
if protoimpl.UnsafeEnabled {
mi := &file_rove_rove_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Account) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Account) ProtoMessage() {}
func (x *Account) ProtoReflect() protoreflect.Message {
mi := &file_rove_rove_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Account.ProtoReflect.Descriptor instead.
func (*Account) Descriptor() ([]byte, []int) {
return file_rove_rove_proto_rawDescGZIP(), []int{13}
}
func (x *Account) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Account) GetSecret() string {
if x != nil {
return x.Secret
}
return ""
}
var File_rove_rove_proto protoreflect.FileDescriptor var File_rove_rove_proto protoreflect.FileDescriptor
var file_rove_rove_proto_rawDesc = []byte{ var file_rove_rove_proto_rawDesc = []byte{
@ -814,97 +879,106 @@ var file_rove_rove_proto_rawDesc = []byte{
0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x65, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x65,
0x61, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x65, 0x61, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x65, 0x61,
0x72, 0x69, 0x6e, 0x67, 0x22, 0x55, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x64, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x41,
0x12, 0x29, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12,
0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x29, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
0x64, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x43, 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x43, 0x6f,
0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x0a,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x28, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18,
0x0c, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x37, 0x0a, 0x0c,
0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x07,
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x55, 0x0a, 0x0d, 0x52, 0x61, 0x64, 0x61, 0x72, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x63,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x55, 0x0a, 0x0d, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65,
0x0a, 0x05, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18,
0x69, 0x6c, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x12, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x69, 0x6c,
0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, 0x20,
0x73, 0x65, 0x22, 0x25, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x25, 0x0a, 0x0f,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x29, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x61, 0x6d, 0x65, 0x22, 0x3b, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75,
0x6f, 0x75, 0x6e, 0x74, 0x22, 0x98, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x08, 0x70, 0x22, 0x38, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x12, 0x27, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
0x72, 0x6f, 0x76, 0x65, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x74, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x98, 0x03, 0x0a, 0x0e, 0x53,
0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a,
0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x61, 0x70, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f,
0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x72, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x72,
0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67,
0x69, 0x74, 0x79, 0x12, 0x2a, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x49, 0x6e, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x04,
0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x12,
0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28,
0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x69,
0x06, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
0x75, 0x6d, 0x43, 0x68, 0x61, 0x72, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2a, 0x0a, 0x10, 0x6d, 0x61, 0x78,
0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x43, 0x68, 0x61, 0x72, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x69, 0x6d, 0x75, 0x6d, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20,
0x10, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x49, 0x6e, 0x74, 0x65,
0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x67, 0x72, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x18,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x12, 0x24, 0x0a,
0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x12, 0x35, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x75, 0x0d, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x43, 0x68, 0x61, 0x72, 0x67, 0x65, 0x18, 0x09,
0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x43, 0x68, 0x61,
0x32, 0x0d, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x72, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x43,
0x0e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
0x15, 0x0a, 0x13, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x10, 0x69, 0x6e,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa1, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x65, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x12, 0x35,
0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f,
0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x43, 0x6f, 0x6d,
0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x12, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53,
0x1a, 0x0a, 0x08, 0x74, 0x69, 0x63, 0x6b, 0x52, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa1, 0x01, 0x0a,
0x05, 0x52, 0x08, 0x74, 0x69, 0x63, 0x6b, 0x52, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x14, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73,
0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x12, 0x1b, 0x0a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
0x09, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x69, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05,
0x52, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x22, 0x24, 0x0a, 0x06, 0x56, 0x65, 0x72, 0x65, 0x61, 0x64, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x63, 0x6b, 0x52, 0x61, 0x74,
0x63, 0x74, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x74, 0x69, 0x63, 0x6b, 0x52, 0x61, 0x74,
0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x01, 0x79, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x63, 0x6b,
0x32, 0x91, 0x03, 0x0a, 0x04, 0x52, 0x6f, 0x76, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54,
0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x69, 0x63, 0x6b, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x69, 0x63, 0x6b,
0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x69, 0x63, 0x6b,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x22, 0x24, 0x0a, 0x06, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18,
0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x02, 0x20,
0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x01, 0x28, 0x05, 0x52, 0x01, 0x79, 0x22, 0x35, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4f, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x73, 0x74, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18,
0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x32, 0x91, 0x03,
0x76, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x0a, 0x04, 0x52, 0x6f, 0x76, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x22, 0x09, 0x2f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x53, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x4b, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x6d, 0x61, 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53,
0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x72, 0x6f, 0x76, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82,
0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, 0x73,
0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, 0x08, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4f, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x61, 0x6e, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x43, 0x0a, 0x05, 0x52, 0x61, 0x64, 0x61, 0x72, 0x12, 0x72, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x12, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e,
0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0b, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x22, 0x09, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73,
0x22, 0x06, 0x2f, 0x72, 0x61, 0x64, 0x61, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x47, 0x0a, 0x06, 0x53, 0x74, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x4b, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x64, 0x12, 0x14, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x6f, 0x76, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43,
0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13,
0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x22, 0x07, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, 0x08, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x73, 0x3a, 0x01, 0x2a, 0x42, 0x21, 0x5a, 0x1f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x3a, 0x01, 0x2a, 0x12, 0x43, 0x0a, 0x05, 0x52, 0x61, 0x64, 0x61, 0x72, 0x12, 0x12, 0x2e, 0x72,
0x6f, 0x6d, 0x2f, 0x6d, 0x64, 0x69, 0x6c, 0x75, 0x7a, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x2f, 0x70, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x6b, 0x67, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x1a, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0b, 0x22, 0x06, 0x2f,
0x72, 0x61, 0x64, 0x61, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x47, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x12, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x53,
0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x22, 0x07, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3a, 0x01,
0x2a, 0x42, 0x21, 0x5a, 0x1f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x6d, 0x64, 0x69, 0x6c, 0x75, 0x7a, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f,
0x72, 0x6f, 0x76, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@ -919,7 +993,7 @@ func file_rove_rove_proto_rawDescGZIP() []byte {
return file_rove_rove_proto_rawDescData return file_rove_rove_proto_rawDescData
} }
var file_rove_rove_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_rove_rove_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_rove_rove_proto_goTypes = []interface{}{ var file_rove_rove_proto_goTypes = []interface{}{
(*Command)(nil), // 0: rove.Command (*Command)(nil), // 0: rove.Command
(*CommandRequest)(nil), // 1: rove.CommandRequest (*CommandRequest)(nil), // 1: rove.CommandRequest
@ -927,34 +1001,39 @@ var file_rove_rove_proto_goTypes = []interface{}{
(*Error)(nil), // 3: rove.Error (*Error)(nil), // 3: rove.Error
(*RadarRequest)(nil), // 4: rove.RadarRequest (*RadarRequest)(nil), // 4: rove.RadarRequest
(*RadarResponse)(nil), // 5: rove.RadarResponse (*RadarResponse)(nil), // 5: rove.RadarResponse
(*RegisterResponse)(nil), // 6: rove.RegisterResponse (*RegisterRequest)(nil), // 6: rove.RegisterRequest
(*RegisterRequest)(nil), // 7: rove.RegisterRequest (*RegisterResponse)(nil), // 7: rove.RegisterResponse
(*StatusRequest)(nil), // 8: rove.StatusRequest (*StatusRequest)(nil), // 8: rove.StatusRequest
(*StatusResponse)(nil), // 9: rove.StatusResponse (*StatusResponse)(nil), // 9: rove.StatusResponse
(*ServerStatusRequest)(nil), // 10: rove.ServerStatusRequest (*ServerStatusRequest)(nil), // 10: rove.ServerStatusRequest
(*ServerStatusResponse)(nil), // 11: rove.ServerStatusResponse (*ServerStatusResponse)(nil), // 11: rove.ServerStatusResponse
(*Vector)(nil), // 12: rove.Vector (*Vector)(nil), // 12: rove.Vector
(*Account)(nil), // 13: rove.Account
} }
var file_rove_rove_proto_depIdxs = []int32{ var file_rove_rove_proto_depIdxs = []int32{
0, // 0: rove.CommandRequest.commands:type_name -> rove.Command 13, // 0: rove.CommandRequest.account:type_name -> rove.Account
12, // 1: rove.StatusResponse.position:type_name -> rove.Vector 0, // 1: rove.CommandRequest.commands:type_name -> rove.Command
0, // 2: rove.StatusResponse.incomingCommands:type_name -> rove.Command 13, // 2: rove.RadarRequest.account:type_name -> rove.Account
0, // 3: rove.StatusResponse.queuedCommands:type_name -> rove.Command 13, // 3: rove.RegisterResponse.account:type_name -> rove.Account
10, // 4: rove.Rove.ServerStatus:input_type -> rove.ServerStatusRequest 13, // 4: rove.StatusRequest.account:type_name -> rove.Account
7, // 5: rove.Rove.Register:input_type -> rove.RegisterRequest 12, // 5: rove.StatusResponse.position:type_name -> rove.Vector
1, // 6: rove.Rove.Command:input_type -> rove.CommandRequest 0, // 6: rove.StatusResponse.incomingCommands:type_name -> rove.Command
4, // 7: rove.Rove.Radar:input_type -> rove.RadarRequest 0, // 7: rove.StatusResponse.queuedCommands:type_name -> rove.Command
8, // 8: rove.Rove.Status:input_type -> rove.StatusRequest 10, // 8: rove.Rove.ServerStatus:input_type -> rove.ServerStatusRequest
11, // 9: rove.Rove.ServerStatus:output_type -> rove.ServerStatusResponse 6, // 9: rove.Rove.Register:input_type -> rove.RegisterRequest
6, // 10: rove.Rove.Register:output_type -> rove.RegisterResponse 1, // 10: rove.Rove.Command:input_type -> rove.CommandRequest
2, // 11: rove.Rove.Command:output_type -> rove.CommandResponse 4, // 11: rove.Rove.Radar:input_type -> rove.RadarRequest
5, // 12: rove.Rove.Radar:output_type -> rove.RadarResponse 8, // 12: rove.Rove.Status:input_type -> rove.StatusRequest
9, // 13: rove.Rove.Status:output_type -> rove.StatusResponse 11, // 13: rove.Rove.ServerStatus:output_type -> rove.ServerStatusResponse
9, // [9:14] is the sub-list for method output_type 7, // 14: rove.Rove.Register:output_type -> rove.RegisterResponse
4, // [4:9] is the sub-list for method input_type 2, // 15: rove.Rove.Command:output_type -> rove.CommandResponse
4, // [4:4] is the sub-list for extension type_name 5, // 16: rove.Rove.Radar:output_type -> rove.RadarResponse
4, // [4:4] is the sub-list for extension extendee 9, // 17: rove.Rove.Status:output_type -> rove.StatusResponse
0, // [0:4] is the sub-list for field type_name 13, // [13:18] is the sub-list for method output_type
8, // [8:13] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
} }
func init() { file_rove_rove_proto_init() } func init() { file_rove_rove_proto_init() }
@ -1036,7 +1115,7 @@ func file_rove_rove_proto_init() {
} }
} }
file_rove_rove_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { file_rove_rove_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegisterResponse); i { switch v := v.(*RegisterRequest); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -1048,7 +1127,7 @@ func file_rove_rove_proto_init() {
} }
} }
file_rove_rove_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { file_rove_rove_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegisterRequest); i { switch v := v.(*RegisterResponse); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -1119,6 +1198,18 @@ func file_rove_rove_proto_init() {
return nil return nil
} }
} }
file_rove_rove_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Account); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
} }
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
@ -1126,7 +1217,7 @@ func file_rove_rove_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_rove_rove_proto_rawDesc, RawDescriptor: file_rove_rove_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 13, NumMessages: 14,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },

View file

@ -207,6 +207,17 @@
} }
} }
}, },
"roveAccount": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"secret": {
"type": "string"
}
}
},
"roveCommand": { "roveCommand": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -224,7 +235,7 @@
"type": "object", "type": "object",
"properties": { "properties": {
"account": { "account": {
"type": "string", "$ref": "#/definitions/roveAccount",
"title": "The account to execute these commands" "title": "The account to execute these commands"
}, },
"commands": { "commands": {
@ -244,7 +255,7 @@
"type": "object", "type": "object",
"properties": { "properties": {
"account": { "account": {
"type": "string", "$ref": "#/definitions/roveAccount",
"title": "The account for this request" "title": "The account for this request"
} }
} }
@ -280,6 +291,12 @@
}, },
"roveRegisterResponse": { "roveRegisterResponse": {
"type": "object", "type": "object",
"properties": {
"account": {
"$ref": "#/definitions/roveAccount",
"title": "The registered account information"
}
},
"title": "Empty placeholder" "title": "Empty placeholder"
}, },
"roveServerStatusResponse": { "roveServerStatusResponse": {
@ -314,7 +331,7 @@
"type": "object", "type": "object",
"properties": { "properties": {
"account": { "account": {
"type": "string", "$ref": "#/definitions/roveAccount",
"title": "The account for this request" "title": "The account for this request"
} }
} }

View file

@ -74,7 +74,7 @@ message Command {
message CommandRequest { message CommandRequest {
// The account to execute these commands // The account to execute these commands
string account = 1; Account account = 1;
// The set of desired commands // The set of desired commands
repeated Command commands = 2; repeated Command commands = 2;
@ -90,7 +90,7 @@ message Error {
message RadarRequest { message RadarRequest {
// The account for this request // The account for this request
string account = 1; Account account = 1;
} }
message RadarResponse { message RadarResponse {
@ -104,17 +104,20 @@ message RadarResponse {
bytes objects = 3; bytes objects = 3;
} }
// Empty placeholder
message RegisterResponse{}
message RegisterRequest { message RegisterRequest {
// The desired account name // The desired account name
string name = 1; string name = 1;
} }
// Empty placeholder
message RegisterResponse{
// The registered account information
Account account = 1;
}
message StatusRequest { message StatusRequest {
// The account for this request // The account for this request
string account = 1; Account account = 1;
} }
message StatusResponse { message StatusResponse {
@ -176,3 +179,8 @@ message Vector {
int32 x = 1; int32 x = 1;
int32 y = 2; int32 y = 2;
} }
message Account {
string name = 1;
string secret = 2;
}