diff --git a/.golangci.yml b/.golangci.yml index 1255159e63..1104c30ff1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,6 +8,10 @@ issues: text: "SA1019:" linters: - staticcheck + # Exclude scopelint for tests files because of https://github.com/kyoh86/scopelint/issues/4 + - path: _test\.go + linters: + - scopelint linters: enable: - bodyclose diff --git a/go.mod b/go.mod index 90015b75c0..8c213eb7f4 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/mitchellh/reflectwalk v1.0.1 // indirect github.com/oklog/run v1.0.0 github.com/openzipkin/zipkin-go v0.2.2 - github.com/owncloud/ocis-pkg/v2 v2.2.2-0.20200812103920-db41b5a3d14d + github.com/owncloud/ocis-pkg/v2 v2.4.0 github.com/restic/calens v0.2.0 github.com/spf13/viper v1.6.3 github.com/stretchr/testify v1.6.1 @@ -34,6 +34,7 @@ require ( golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 google.golang.org/protobuf v1.23.0 + gotest.tools v2.2.0+incompatible ) replace google.golang.org/grpc => google.golang.org/grpc v1.26.0 diff --git a/go.sum b/go.sum index 7af16ecb75..42f6fcbcf7 100644 --- a/go.sum +++ b/go.sum @@ -534,6 +534,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/haya14busa/goverage v0.0.0-20180129164344-eec3514a20b5 h1:FdBGmSkD2QpQzRWup//SGObvWf2nq89zj9+ta9OvI3A= github.com/haya14busa/goverage v0.0.0-20180129164344-eec3514a20b5/go.mod h1:0YZ2wQSuwviXXXGUiK6zXzskyBLAbLXhamxzcFHSLoM= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -760,6 +761,10 @@ github.com/ory/x v0.0.85/go.mod h1:s44V8t3xyjWZREcU+mWlp4h302rTuM4aLXcW+y5FbQ8= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= github.com/owncloud/ocis-pkg/v2 v2.2.2-0.20200812103920-db41b5a3d14d h1:eruHqxLfS3fiPO1ylg60T++wShVqtayI4LxUhwOEuN4= github.com/owncloud/ocis-pkg/v2 v2.2.2-0.20200812103920-db41b5a3d14d/go.mod h1:FSzIvhx9HcZcq4jgNaDowNvM7PTX/XCyoMvyfzidUpE= +github.com/owncloud/ocis-pkg/v2 v2.3.1-0.20200825114153-bc31e3e4b1e0 h1:dz/I+K7+1t3RKrNafDtb6EWJCQe7+z6c4V9UF0bGxCI= +github.com/owncloud/ocis-pkg/v2 v2.3.1-0.20200825114153-bc31e3e4b1e0/go.mod h1:FSzIvhx9HcZcq4jgNaDowNvM7PTX/XCyoMvyfzidUpE= +github.com/owncloud/ocis-pkg/v2 v2.4.0 h1:/3ZOd4txtwjiNKJA9iLT9BjrJw5YgHSX13fQR4BYfGY= +github.com/owncloud/ocis-pkg/v2 v2.4.0/go.mod h1:FSzIvhx9HcZcq4jgNaDowNvM7PTX/XCyoMvyfzidUpE= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE= @@ -1352,6 +1357,7 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/proto/v0/settings.pb.go b/pkg/proto/v0/settings.pb.go index e5ead90491..50e1228e15 100644 --- a/pkg/proto/v0/settings.pb.go +++ b/pkg/proto/v0/settings.pb.go @@ -89,7 +89,7 @@ func (x Resource_Type) Number() protoreflect.EnumNumber { // Deprecated: Use Resource_Type.Descriptor instead. func (Resource_Type) EnumDescriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{24, 0} + return file_settings_proto_rawDescGZIP(), []int{26, 0} } type Bundle_Type int32 @@ -138,17 +138,19 @@ func (x Bundle_Type) Number() protoreflect.EnumNumber { // Deprecated: Use Bundle_Type.Descriptor instead. func (Bundle_Type) EnumDescriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{25, 0} + return file_settings_proto_rawDescGZIP(), []int{27, 0} } type Permission_Operation int32 const ( - Permission_OPERATION_UNKNOWN Permission_Operation = 0 - Permission_OPERATION_CREATE Permission_Operation = 1 - Permission_OPERATION_READ Permission_Operation = 2 - Permission_OPERATION_UPDATE Permission_Operation = 3 - Permission_OPERATION_DELETE Permission_Operation = 4 + Permission_OPERATION_UNKNOWN Permission_Operation = 0 + Permission_OPERATION_CREATE Permission_Operation = 1 + Permission_OPERATION_READ Permission_Operation = 2 + Permission_OPERATION_UPDATE Permission_Operation = 3 + Permission_OPERATION_DELETE Permission_Operation = 4 + Permission_OPERATION_WRITE Permission_Operation = 5 // WRITE is a combination of CREATE and UPDATE + Permission_OPERATION_READWRITE Permission_Operation = 6 // READWRITE is a combination of READ and WRITE ) // Enum value maps for Permission_Operation. @@ -159,13 +161,17 @@ var ( 2: "OPERATION_READ", 3: "OPERATION_UPDATE", 4: "OPERATION_DELETE", + 5: "OPERATION_WRITE", + 6: "OPERATION_READWRITE", } Permission_Operation_value = map[string]int32{ - "OPERATION_UNKNOWN": 0, - "OPERATION_CREATE": 1, - "OPERATION_READ": 2, - "OPERATION_UPDATE": 3, - "OPERATION_DELETE": 4, + "OPERATION_UNKNOWN": 0, + "OPERATION_CREATE": 1, + "OPERATION_READ": 2, + "OPERATION_UPDATE": 3, + "OPERATION_DELETE": 4, + "OPERATION_WRITE": 5, + "OPERATION_READWRITE": 6, } ) @@ -193,7 +199,7 @@ func (x Permission_Operation) Number() protoreflect.EnumNumber { // Deprecated: Use Permission_Operation.Descriptor instead. func (Permission_Operation) EnumDescriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{33, 0} + return file_settings_proto_rawDescGZIP(), []int{35, 0} } type Permission_Constraint int32 @@ -245,7 +251,7 @@ func (x Permission_Constraint) Number() protoreflect.EnumNumber { // Deprecated: Use Permission_Constraint.Descriptor instead. func (Permission_Constraint) EnumDescriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{33, 1} + return file_settings_proto_rawDescGZIP(), []int{35, 1} } // --- @@ -443,8 +449,6 @@ type ListBundlesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - AccountUuid string `protobuf:"bytes,1,opt,name=account_uuid,json=accountUuid,proto3" json:"account_uuid,omitempty"` } func (x *ListBundlesRequest) Reset() { @@ -479,13 +483,6 @@ func (*ListBundlesRequest) Descriptor() ([]byte, []int) { return file_settings_proto_rawDescGZIP(), []int{4} } -func (x *ListBundlesRequest) GetAccountUuid() string { - if x != nil { - return x.AccountUuid - } - return "" -} - type ListBundlesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1462,6 +1459,108 @@ func (x *UserRoleAssignment) GetRoleId() string { return "" } +type ListPermissionsByResourceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` + RoleIds []string `protobuf:"bytes,2,rep,name=role_ids,json=roleIds,proto3" json:"role_ids,omitempty"` +} + +func (x *ListPermissionsByResourceRequest) Reset() { + *x = ListPermissionsByResourceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_settings_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPermissionsByResourceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPermissionsByResourceRequest) ProtoMessage() {} + +func (x *ListPermissionsByResourceRequest) ProtoReflect() protoreflect.Message { + mi := &file_settings_proto_msgTypes[24] + 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 ListPermissionsByResourceRequest.ProtoReflect.Descriptor instead. +func (*ListPermissionsByResourceRequest) Descriptor() ([]byte, []int) { + return file_settings_proto_rawDescGZIP(), []int{24} +} + +func (x *ListPermissionsByResourceRequest) GetResource() *Resource { + if x != nil { + return x.Resource + } + return nil +} + +func (x *ListPermissionsByResourceRequest) GetRoleIds() []string { + if x != nil { + return x.RoleIds + } + return nil +} + +type ListPermissionsByResourceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Permissions []*Permission `protobuf:"bytes,1,rep,name=permissions,proto3" json:"permissions,omitempty"` +} + +func (x *ListPermissionsByResourceResponse) Reset() { + *x = ListPermissionsByResourceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_settings_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPermissionsByResourceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPermissionsByResourceResponse) ProtoMessage() {} + +func (x *ListPermissionsByResourceResponse) ProtoReflect() protoreflect.Message { + mi := &file_settings_proto_msgTypes[25] + 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 ListPermissionsByResourceResponse.ProtoReflect.Descriptor instead. +func (*ListPermissionsByResourceResponse) Descriptor() ([]byte, []int) { + return file_settings_proto_rawDescGZIP(), []int{25} +} + +func (x *ListPermissionsByResourceResponse) GetPermissions() []*Permission { + if x != nil { + return x.Permissions + } + return nil +} + type Resource struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1474,7 +1573,7 @@ type Resource struct { func (x *Resource) Reset() { *x = Resource{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[24] + mi := &file_settings_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1487,7 +1586,7 @@ func (x *Resource) String() string { func (*Resource) ProtoMessage() {} func (x *Resource) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[24] + mi := &file_settings_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1500,7 +1599,7 @@ func (x *Resource) ProtoReflect() protoreflect.Message { // Deprecated: Use Resource.ProtoReflect.Descriptor instead. func (*Resource) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{24} + return file_settings_proto_rawDescGZIP(), []int{26} } func (x *Resource) GetType() Resource_Type { @@ -1534,7 +1633,7 @@ type Bundle struct { func (x *Bundle) Reset() { *x = Bundle{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[25] + mi := &file_settings_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1547,7 +1646,7 @@ func (x *Bundle) String() string { func (*Bundle) ProtoMessage() {} func (x *Bundle) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[25] + mi := &file_settings_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1560,7 +1659,7 @@ func (x *Bundle) ProtoReflect() protoreflect.Message { // Deprecated: Use Bundle.ProtoReflect.Descriptor instead. func (*Bundle) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{25} + return file_settings_proto_rawDescGZIP(), []int{27} } func (x *Bundle) GetId() string { @@ -1635,7 +1734,7 @@ type Setting struct { func (x *Setting) Reset() { *x = Setting{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[26] + mi := &file_settings_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1648,7 +1747,7 @@ func (x *Setting) String() string { func (*Setting) ProtoMessage() {} func (x *Setting) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[26] + mi := &file_settings_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1661,7 +1760,7 @@ func (x *Setting) ProtoReflect() protoreflect.Message { // Deprecated: Use Setting.ProtoReflect.Descriptor instead. func (*Setting) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{26} + return file_settings_proto_rawDescGZIP(), []int{28} } func (x *Setting) GetId() string { @@ -1803,7 +1902,7 @@ type Int struct { func (x *Int) Reset() { *x = Int{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[27] + mi := &file_settings_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1816,7 +1915,7 @@ func (x *Int) String() string { func (*Int) ProtoMessage() {} func (x *Int) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[27] + mi := &file_settings_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1829,7 +1928,7 @@ func (x *Int) ProtoReflect() protoreflect.Message { // Deprecated: Use Int.ProtoReflect.Descriptor instead. func (*Int) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{27} + return file_settings_proto_rawDescGZIP(), []int{29} } func (x *Int) GetDefault() int64 { @@ -1882,7 +1981,7 @@ type String struct { func (x *String) Reset() { *x = String{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[28] + mi := &file_settings_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1895,7 +1994,7 @@ func (x *String) String() string { func (*String) ProtoMessage() {} func (x *String) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[28] + mi := &file_settings_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1908,7 +2007,7 @@ func (x *String) ProtoReflect() protoreflect.Message { // Deprecated: Use String.ProtoReflect.Descriptor instead. func (*String) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{28} + return file_settings_proto_rawDescGZIP(), []int{30} } func (x *String) GetDefault() string { @@ -1958,7 +2057,7 @@ type Bool struct { func (x *Bool) Reset() { *x = Bool{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[29] + mi := &file_settings_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1971,7 +2070,7 @@ func (x *Bool) String() string { func (*Bool) ProtoMessage() {} func (x *Bool) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[29] + mi := &file_settings_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1984,7 +2083,7 @@ func (x *Bool) ProtoReflect() protoreflect.Message { // Deprecated: Use Bool.ProtoReflect.Descriptor instead. func (*Bool) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{29} + return file_settings_proto_rawDescGZIP(), []int{31} } func (x *Bool) GetDefault() bool { @@ -2012,7 +2111,7 @@ type SingleChoiceList struct { func (x *SingleChoiceList) Reset() { *x = SingleChoiceList{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[30] + mi := &file_settings_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2025,7 +2124,7 @@ func (x *SingleChoiceList) String() string { func (*SingleChoiceList) ProtoMessage() {} func (x *SingleChoiceList) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[30] + mi := &file_settings_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2038,7 +2137,7 @@ func (x *SingleChoiceList) ProtoReflect() protoreflect.Message { // Deprecated: Use SingleChoiceList.ProtoReflect.Descriptor instead. func (*SingleChoiceList) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{30} + return file_settings_proto_rawDescGZIP(), []int{32} } func (x *SingleChoiceList) GetOptions() []*ListOption { @@ -2059,7 +2158,7 @@ type MultiChoiceList struct { func (x *MultiChoiceList) Reset() { *x = MultiChoiceList{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[31] + mi := &file_settings_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2072,7 +2171,7 @@ func (x *MultiChoiceList) String() string { func (*MultiChoiceList) ProtoMessage() {} func (x *MultiChoiceList) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[31] + mi := &file_settings_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2085,7 +2184,7 @@ func (x *MultiChoiceList) ProtoReflect() protoreflect.Message { // Deprecated: Use MultiChoiceList.ProtoReflect.Descriptor instead. func (*MultiChoiceList) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{31} + return file_settings_proto_rawDescGZIP(), []int{33} } func (x *MultiChoiceList) GetOptions() []*ListOption { @@ -2108,7 +2207,7 @@ type ListOption struct { func (x *ListOption) Reset() { *x = ListOption{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[32] + mi := &file_settings_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2121,7 +2220,7 @@ func (x *ListOption) String() string { func (*ListOption) ProtoMessage() {} func (x *ListOption) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[32] + mi := &file_settings_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2134,7 +2233,7 @@ func (x *ListOption) ProtoReflect() protoreflect.Message { // Deprecated: Use ListOption.ProtoReflect.Descriptor instead. func (*ListOption) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{32} + return file_settings_proto_rawDescGZIP(), []int{34} } func (x *ListOption) GetValue() *ListOptionValue { @@ -2170,7 +2269,7 @@ type Permission struct { func (x *Permission) Reset() { *x = Permission{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[33] + mi := &file_settings_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2183,7 +2282,7 @@ func (x *Permission) String() string { func (*Permission) ProtoMessage() {} func (x *Permission) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[33] + mi := &file_settings_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2196,7 +2295,7 @@ func (x *Permission) ProtoReflect() protoreflect.Message { // Deprecated: Use Permission.ProtoReflect.Descriptor instead. func (*Permission) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{33} + return file_settings_proto_rawDescGZIP(), []int{35} } func (x *Permission) GetOperation() Permission_Operation { @@ -2236,7 +2335,7 @@ type Value struct { func (x *Value) Reset() { *x = Value{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[34] + mi := &file_settings_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2249,7 +2348,7 @@ func (x *Value) String() string { func (*Value) ProtoMessage() {} func (x *Value) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[34] + mi := &file_settings_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2262,7 +2361,7 @@ func (x *Value) ProtoReflect() protoreflect.Message { // Deprecated: Use Value.ProtoReflect.Descriptor instead. func (*Value) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{34} + return file_settings_proto_rawDescGZIP(), []int{36} } func (x *Value) GetId() string { @@ -2374,7 +2473,7 @@ type ListValue struct { func (x *ListValue) Reset() { *x = ListValue{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[35] + mi := &file_settings_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2387,7 +2486,7 @@ func (x *ListValue) String() string { func (*ListValue) ProtoMessage() {} func (x *ListValue) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[35] + mi := &file_settings_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2400,7 +2499,7 @@ func (x *ListValue) ProtoReflect() protoreflect.Message { // Deprecated: Use ListValue.ProtoReflect.Descriptor instead. func (*ListValue) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{35} + return file_settings_proto_rawDescGZIP(), []int{37} } func (x *ListValue) GetValues() []*ListOptionValue { @@ -2424,7 +2523,7 @@ type ListOptionValue struct { func (x *ListOptionValue) Reset() { *x = ListOptionValue{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[36] + mi := &file_settings_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2437,7 +2536,7 @@ func (x *ListOptionValue) String() string { func (*ListOptionValue) ProtoMessage() {} func (x *ListOptionValue) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[36] + mi := &file_settings_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2450,7 +2549,7 @@ func (x *ListOptionValue) ProtoReflect() protoreflect.Message { // Deprecated: Use ListOptionValue.ProtoReflect.Descriptor instead. func (*ListOptionValue) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{36} + return file_settings_proto_rawDescGZIP(), []int{38} } func (m *ListOptionValue) GetOption() isListOptionValue_Option { @@ -2515,382 +2614,407 @@ var file_settings_proto_rawDesc = []byte{ 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x06, - 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x37, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x75, 0x69, 0x64, 0x22, - 0x3e, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x07, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x22, - 0x62, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, - 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x22, 0x46, 0x0a, 0x1a, 0x41, 0x64, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x54, 0x6f, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x28, 0x0a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x5c, 0x0a, 0x1e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x6f, 0x6d, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, - 0x09, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x22, 0x36, 0x0a, 0x10, 0x53, 0x61, 0x76, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x22, 0x45, 0x0a, 0x11, 0x53, 0x61, 0x76, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x44, 0x0a, 0x10, 0x47, - 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x57, 0x69, 0x74, 0x68, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x22, 0x53, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, - 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x55, 0x75, 0x69, 0x64, 0x22, 0x48, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x06, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x22, 0x66, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x79, 0x55, 0x6e, - 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x75, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x22, 0x6c, 0x0a, 0x13, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, - 0x31, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x12, 0x22, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x5c, 0x0a, 0x0a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3f, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, - 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x55, 0x75, 0x69, 0x64, 0x22, 0x5a, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, - 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x55, 0x0a, 0x17, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, - 0x6f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x75, 0x69, 0x64, 0x12, - 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x22, 0x55, 0x0a, 0x18, 0x41, 0x73, 0x73, 0x69, - 0x67, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x22, - 0x2b, 0x0a, 0x19, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x46, 0x72, 0x6f, - 0x6d, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x60, 0x0a, 0x12, - 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x55, 0x75, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x22, 0xd1, - 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x8a, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, + 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3e, 0x0a, 0x13, + 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x52, 0x07, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x22, 0x62, 0x0a, 0x19, + 0x41, 0x64, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x22, 0x46, 0x0a, 0x1a, 0x41, 0x64, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, + 0x0a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, + 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x5c, 0x0a, 0x1e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, + 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x22, 0x36, 0x0a, 0x10, 0x53, 0x61, 0x76, 0x65, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, + 0x0a, 0x11, 0x53, 0x61, 0x76, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x44, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x53, + 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, + 0x75, 0x69, 0x64, 0x22, 0x48, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x66, 0x0a, + 0x22, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x79, 0x55, 0x6e, 0x69, 0x71, 0x75, + 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, + 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x55, 0x75, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x49, 0x64, 0x22, 0x6c, 0x0a, 0x13, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x57, 0x69, + 0x74, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x0a, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, + 0x22, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x22, 0x5c, 0x0a, 0x0a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x16, 0x0a, 0x06, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x22, 0x3f, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x75, + 0x69, 0x64, 0x22, 0x5a, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x55, + 0x0a, 0x17, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x75, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, + 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x22, 0x55, 0x0a, 0x18, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x52, + 0x6f, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x2b, 0x0a, 0x19, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x60, 0x0a, 0x12, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x75, + 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x22, 0x6a, 0x0a, 0x20, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x2b, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, + 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0b, + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x28, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x8a, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x54, + 0x45, 0x4d, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, + 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x52, + 0x45, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, + 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x55, + 0x4e, 0x44, 0x4c, 0x45, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, + 0x53, 0x45, 0x52, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, + 0x4f, 0x55, 0x50, 0x10, 0x07, 0x22, 0xa9, 0x02, 0x0a, 0x06, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, + 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, + 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, + 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2b, 0x0a, 0x08, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x39, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, - 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x02, - 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x45, 0x10, 0x03, - 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, - 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x55, 0x4e, 0x44, 0x4c, - 0x45, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, - 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, - 0x10, 0x07, 0x22, 0xa9, 0x02, 0x0a, 0x06, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x0e, 0x0a, + 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, + 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x10, + 0x02, 0x22, 0x88, 0x04, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x26, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, - 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x73, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x73, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2b, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x32, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x49, 0x0a, 0x13, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x63, 0x68, + 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, + 0x68, 0x6f, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x11, 0x73, 0x69, 0x6e, + 0x67, 0x6c, 0x65, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, + 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x4c, 0x69, + 0x73, 0x74, 0x48, 0x00, 0x52, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x6f, 0x69, 0x63, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x10, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x22, 0x39, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x10, 0x0a, - 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x12, - 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x10, 0x02, 0x22, 0x88, - 0x04, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, - 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x49, 0x0a, 0x13, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x63, 0x68, 0x6f, 0x69, 0x63, - 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, 0x68, 0x6f, 0x69, - 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x11, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, - 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x12, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x48, - 0x00, 0x52, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x10, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x48, 0x00, 0x52, 0x0f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x79, 0x0a, 0x03, 0x49, 0x6e, 0x74, + 0x72, 0x63, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x79, 0x0a, 0x03, + 0x49, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, + 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x61, + 0x78, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x65, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x04, 0x73, 0x74, 0x65, 0x70, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, + 0x6c, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x22, 0x9e, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x69, 0x6e, 0x5f, + 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6d, 0x69, + 0x6e, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x6c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6d, 0x61, 0x78, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, + 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x22, 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, - 0x6d, 0x61, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x12, - 0x0a, 0x04, 0x73, 0x74, 0x65, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x74, - 0x65, 0x70, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, - 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, - 0x6c, 0x64, 0x65, 0x72, 0x22, 0x9e, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, - 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6d, 0x69, 0x6e, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6d, 0x61, 0x78, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, - 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, - 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x22, 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x18, 0x0a, - 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x3f, 0x0a, - 0x10, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x3e, - 0x0a, 0x0f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x79, - 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xe4, 0x02, 0x0a, 0x0a, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, - 0x72, 0x61, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, - 0x74, 0x22, 0x78, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x15, - 0x0a, 0x11, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4f, - 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x10, 0x02, 0x12, - 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, - 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x04, 0x22, 0x63, 0x0a, 0x0a, 0x43, - 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x4f, 0x4e, - 0x53, 0x54, 0x52, 0x41, 0x49, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, - 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x52, 0x41, 0x49, 0x4e, 0x54, 0x5f, - 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x52, 0x41, - 0x49, 0x4e, 0x54, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, - 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x52, 0x41, 0x49, 0x4e, 0x54, 0x5f, 0x41, 0x4c, 0x4c, 0x10, 0x03, - 0x22, 0xc4, 0x02, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x75, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x08, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, - 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, - 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x6c, - 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x48, 0x00, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3b, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x22, 0x5f, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, - 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, - 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, - 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xef, 0x04, 0x0a, 0x0d, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6a, 0x0a, 0x0a, 0x53, 0x61, 0x76, 0x65, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x61, - 0x76, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x21, 0x22, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2d, 0x73, 0x61, 0x76, 0x65, - 0x3a, 0x01, 0x2a, 0x12, 0x66, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x2d, 0x67, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, - 0x69, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x1d, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x73, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x8a, 0x01, 0x0a, 0x12, - 0x41, 0x64, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, - 0x24, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x2f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x2d, 0x61, 0x64, 0x64, 0x2d, 0x73, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x01, 0x2a, 0x12, 0x8c, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x27, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x2d, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x01, 0x2a, 0x32, 0xea, 0x03, 0x0a, 0x0c, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x09, 0x53, 0x61, 0x76, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x61, - 0x76, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, - 0x22, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2d, 0x73, 0x61, 0x76, 0x65, 0x3a, 0x01, - 0x2a, 0x12, 0x63, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, - 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, - 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2d, - 0x67, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x21, 0x22, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x3a, - 0x01, 0x2a, 0x12, 0x9f, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, - 0x79, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x73, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x42, 0x79, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x22, 0x31, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2d, 0x67, 0x65, 0x74, 0x2d, 0x62, 0x79, 0x2d, 0x75, - 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x73, 0x3a, 0x01, 0x2a, 0x32, 0x89, 0x04, 0x0a, 0x0b, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x6a, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, - 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, + 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, + 0x22, 0x3f, 0x0a, 0x10, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x22, 0x3e, 0x0a, 0x0f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x22, 0x79, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, + 0x61, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x93, 0x03, 0x0a, + 0x0a, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x09, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, + 0x61, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, + 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, + 0x61, 0x69, 0x6e, 0x74, 0x22, 0xa6, 0x01, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, + 0x12, 0x0a, 0x0e, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, + 0x44, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x04, 0x12, + 0x13, 0x0a, 0x0f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x57, 0x52, 0x49, + 0x54, 0x45, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x06, 0x22, 0x63, 0x0a, + 0x0a, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x43, + 0x4f, 0x4e, 0x53, 0x54, 0x52, 0x41, 0x49, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x52, 0x41, 0x49, 0x4e, + 0x54, 0x5f, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x53, 0x54, + 0x52, 0x41, 0x49, 0x4e, 0x54, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, + 0x0a, 0x0e, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x52, 0x41, 0x49, 0x4e, 0x54, 0x5f, 0x41, 0x4c, 0x4c, + 0x10, 0x03, 0x22, 0xc4, 0x02, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, + 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x75, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x08, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, + 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, + 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x31, 0x0a, + 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3b, 0x0a, 0x09, 0x4c, 0x69, 0x73, + 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x5f, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, + 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x08, 0x0a, + 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xef, 0x04, 0x0a, 0x0d, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6a, 0x0a, 0x0a, 0x53, 0x61, 0x76, + 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x53, 0x61, 0x76, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x42, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x21, 0x22, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2d, 0x73, 0x61, + 0x76, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x66, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, + 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2d, 0x67, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x6e, 0x0a, + 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, - 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x01, 0x2a, - 0x12, 0x8a, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, - 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x22, 0x21, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, - 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x80, 0x01, - 0x0a, 0x10, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, - 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x22, 0x20, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x61, 0x73, - 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x61, 0x64, 0x64, 0x3a, 0x01, 0x2a, - 0x12, 0x7e, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x46, 0x72, - 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x61, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x3a, 0x01, 0x2a, - 0x42, 0xba, 0x02, 0x5a, 0x12, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, - 0x30, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x92, 0x41, 0xa2, 0x02, 0x12, 0xae, 0x01, 0x0a, 0x08, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x50, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, 0x43, - 0x6c, 0x6f, 0x75, 0x64, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x12, 0x29, 0x68, 0x74, 0x74, 0x70, 0x73, - 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x77, - 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6f, 0x63, 0x69, 0x73, 0x2d, 0x73, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x40, 0x6f, 0x77, - 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x2a, 0x4b, 0x0a, 0x0a, 0x41, 0x70, - 0x61, 0x63, 0x68, 0x65, 0x2d, 0x32, 0x2e, 0x30, 0x12, 0x3d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, - 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x77, 0x6e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6f, 0x63, 0x69, 0x73, 0x2d, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2f, - 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x03, 0x31, 0x2e, 0x30, 0x2a, 0x02, 0x01, 0x02, - 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, - 0x6f, 0x6e, 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, - 0x6a, 0x73, 0x6f, 0x6e, 0x72, 0x47, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x12, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, - 0x2f, 0x6f, 0x77, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x69, 0x6f, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x6f, - 0x63, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x1d, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x8a, 0x01, + 0x0a, 0x12, 0x41, 0x64, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x42, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, + 0x64, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x42, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x29, 0x22, 0x24, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x2d, 0x61, 0x64, 0x64, 0x2d, + 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x01, 0x2a, 0x12, 0x8c, 0x01, 0x0a, 0x17, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x6f, 0x6d, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x6f, 0x6d, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x27, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, + 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x2d, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x01, 0x2a, 0x32, 0xea, 0x03, 0x0a, 0x0c, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x09, 0x53, 0x61, + 0x76, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x53, 0x61, 0x76, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x21, 0x22, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2d, 0x73, 0x61, 0x76, 0x65, + 0x3a, 0x01, 0x2a, 0x12, 0x63, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x2d, 0x67, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x21, 0x22, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2d, 0x6c, 0x69, 0x73, + 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x9f, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x42, 0x79, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x79, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, + 0x22, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2d, 0x67, 0x65, 0x74, 0x2d, 0x62, 0x79, + 0x2d, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x32, 0x89, 0x04, 0x0a, 0x0b, 0x52, 0x6f, 0x6c, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6a, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, + 0x6c, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x3a, + 0x01, 0x2a, 0x12, 0x8a, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x41, + 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x22, 0x21, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x61, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x01, 0x2a, 0x12, + 0x80, 0x01, 0x0a, 0x10, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x6f, + 0x55, 0x73, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x22, 0x20, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, + 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x61, 0x64, 0x64, 0x3a, + 0x01, 0x2a, 0x12, 0x7e, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, + 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x61, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x3a, + 0x01, 0x2a, 0x32, 0xbe, 0x01, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa8, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x32, 0x22, 0x2d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2d, + 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x62, 0x79, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x3a, 0x01, 0x2a, 0x42, 0xba, 0x02, 0x5a, 0x12, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x76, 0x30, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x92, 0x41, 0xa2, 0x02, 0x12, 0xae, + 0x01, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x50, 0x0a, 0x0d, 0x6f, + 0x77, 0x6e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x12, 0x29, 0x68, 0x74, + 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x6f, 0x77, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6f, 0x63, 0x69, 0x73, 0x2d, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x40, 0x6f, 0x77, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x2a, 0x4b, 0x0a, + 0x0a, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2d, 0x32, 0x2e, 0x30, 0x12, 0x3d, 0x68, 0x74, 0x74, + 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x6f, 0x77, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6f, 0x63, 0x69, 0x73, 0x2d, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, + 0x65, 0x72, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x03, 0x31, 0x2e, 0x30, 0x2a, + 0x02, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x72, 0x47, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x12, 0x33, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x77, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x69, 0x6f, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x2f, 0x6f, 0x63, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2906,7 +3030,7 @@ func file_settings_proto_rawDescGZIP() []byte { } var file_settings_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_settings_proto_msgTypes = make([]protoimpl.MessageInfo, 37) +var file_settings_proto_msgTypes = make([]protoimpl.MessageInfo, 39) var file_settings_proto_goTypes = []interface{}{ (Resource_Type)(0), // 0: proto.Resource.Type (Bundle_Type)(0), // 1: proto.Bundle.Type @@ -2936,86 +3060,92 @@ var file_settings_proto_goTypes = []interface{}{ (*AssignRoleToUserResponse)(nil), // 25: proto.AssignRoleToUserResponse (*RemoveRoleFromUserRequest)(nil), // 26: proto.RemoveRoleFromUserRequest (*UserRoleAssignment)(nil), // 27: proto.UserRoleAssignment - (*Resource)(nil), // 28: proto.Resource - (*Bundle)(nil), // 29: proto.Bundle - (*Setting)(nil), // 30: proto.Setting - (*Int)(nil), // 31: proto.Int - (*String)(nil), // 32: proto.String - (*Bool)(nil), // 33: proto.Bool - (*SingleChoiceList)(nil), // 34: proto.SingleChoiceList - (*MultiChoiceList)(nil), // 35: proto.MultiChoiceList - (*ListOption)(nil), // 36: proto.ListOption - (*Permission)(nil), // 37: proto.Permission - (*Value)(nil), // 38: proto.Value - (*ListValue)(nil), // 39: proto.ListValue - (*ListOptionValue)(nil), // 40: proto.ListOptionValue - (*empty.Empty)(nil), // 41: google.protobuf.Empty + (*ListPermissionsByResourceRequest)(nil), // 28: proto.ListPermissionsByResourceRequest + (*ListPermissionsByResourceResponse)(nil), // 29: proto.ListPermissionsByResourceResponse + (*Resource)(nil), // 30: proto.Resource + (*Bundle)(nil), // 31: proto.Bundle + (*Setting)(nil), // 32: proto.Setting + (*Int)(nil), // 33: proto.Int + (*String)(nil), // 34: proto.String + (*Bool)(nil), // 35: proto.Bool + (*SingleChoiceList)(nil), // 36: proto.SingleChoiceList + (*MultiChoiceList)(nil), // 37: proto.MultiChoiceList + (*ListOption)(nil), // 38: proto.ListOption + (*Permission)(nil), // 39: proto.Permission + (*Value)(nil), // 40: proto.Value + (*ListValue)(nil), // 41: proto.ListValue + (*ListOptionValue)(nil), // 42: proto.ListOptionValue + (*empty.Empty)(nil), // 43: google.protobuf.Empty } var file_settings_proto_depIdxs = []int32{ - 29, // 0: proto.SaveBundleRequest.bundle:type_name -> proto.Bundle - 29, // 1: proto.SaveBundleResponse.bundle:type_name -> proto.Bundle - 29, // 2: proto.GetBundleResponse.bundle:type_name -> proto.Bundle - 29, // 3: proto.ListBundlesResponse.bundles:type_name -> proto.Bundle - 30, // 4: proto.AddSettingToBundleRequest.setting:type_name -> proto.Setting - 30, // 5: proto.AddSettingToBundleResponse.setting:type_name -> proto.Setting - 38, // 6: proto.SaveValueRequest.value:type_name -> proto.Value + 31, // 0: proto.SaveBundleRequest.bundle:type_name -> proto.Bundle + 31, // 1: proto.SaveBundleResponse.bundle:type_name -> proto.Bundle + 31, // 2: proto.GetBundleResponse.bundle:type_name -> proto.Bundle + 31, // 3: proto.ListBundlesResponse.bundles:type_name -> proto.Bundle + 32, // 4: proto.AddSettingToBundleRequest.setting:type_name -> proto.Setting + 32, // 5: proto.AddSettingToBundleResponse.setting:type_name -> proto.Setting + 40, // 6: proto.SaveValueRequest.value:type_name -> proto.Value 20, // 7: proto.SaveValueResponse.value:type_name -> proto.ValueWithIdentifier 20, // 8: proto.GetValueResponse.value:type_name -> proto.ValueWithIdentifier 20, // 9: proto.ListValuesResponse.values:type_name -> proto.ValueWithIdentifier 21, // 10: proto.ValueWithIdentifier.identifier:type_name -> proto.Identifier - 38, // 11: proto.ValueWithIdentifier.value:type_name -> proto.Value + 40, // 11: proto.ValueWithIdentifier.value:type_name -> proto.Value 27, // 12: proto.ListRoleAssignmentsResponse.assignments:type_name -> proto.UserRoleAssignment 27, // 13: proto.AssignRoleToUserResponse.assignment:type_name -> proto.UserRoleAssignment - 0, // 14: proto.Resource.type:type_name -> proto.Resource.Type - 1, // 15: proto.Bundle.type:type_name -> proto.Bundle.Type - 30, // 16: proto.Bundle.settings:type_name -> proto.Setting - 28, // 17: proto.Bundle.resource:type_name -> proto.Resource - 31, // 18: proto.Setting.int_value:type_name -> proto.Int - 32, // 19: proto.Setting.string_value:type_name -> proto.String - 33, // 20: proto.Setting.bool_value:type_name -> proto.Bool - 34, // 21: proto.Setting.single_choice_value:type_name -> proto.SingleChoiceList - 35, // 22: proto.Setting.multi_choice_value:type_name -> proto.MultiChoiceList - 37, // 23: proto.Setting.permission_value:type_name -> proto.Permission - 28, // 24: proto.Setting.resource:type_name -> proto.Resource - 36, // 25: proto.SingleChoiceList.options:type_name -> proto.ListOption - 36, // 26: proto.MultiChoiceList.options:type_name -> proto.ListOption - 40, // 27: proto.ListOption.value:type_name -> proto.ListOptionValue - 2, // 28: proto.Permission.operation:type_name -> proto.Permission.Operation - 3, // 29: proto.Permission.constraint:type_name -> proto.Permission.Constraint - 28, // 30: proto.Value.resource:type_name -> proto.Resource - 39, // 31: proto.Value.list_value:type_name -> proto.ListValue - 40, // 32: proto.ListValue.values:type_name -> proto.ListOptionValue - 4, // 33: proto.BundleService.SaveBundle:input_type -> proto.SaveBundleRequest - 6, // 34: proto.BundleService.GetBundle:input_type -> proto.GetBundleRequest - 8, // 35: proto.BundleService.ListBundles:input_type -> proto.ListBundlesRequest - 10, // 36: proto.BundleService.AddSettingToBundle:input_type -> proto.AddSettingToBundleRequest - 12, // 37: proto.BundleService.RemoveSettingFromBundle:input_type -> proto.RemoveSettingFromBundleRequest - 13, // 38: proto.ValueService.SaveValue:input_type -> proto.SaveValueRequest - 15, // 39: proto.ValueService.GetValue:input_type -> proto.GetValueRequest - 17, // 40: proto.ValueService.ListValues:input_type -> proto.ListValuesRequest - 19, // 41: proto.ValueService.GetValueByUniqueIdentifiers:input_type -> proto.GetValueByUniqueIdentifiersRequest - 8, // 42: proto.RoleService.ListRoles:input_type -> proto.ListBundlesRequest - 22, // 43: proto.RoleService.ListRoleAssignments:input_type -> proto.ListRoleAssignmentsRequest - 24, // 44: proto.RoleService.AssignRoleToUser:input_type -> proto.AssignRoleToUserRequest - 26, // 45: proto.RoleService.RemoveRoleFromUser:input_type -> proto.RemoveRoleFromUserRequest - 5, // 46: proto.BundleService.SaveBundle:output_type -> proto.SaveBundleResponse - 7, // 47: proto.BundleService.GetBundle:output_type -> proto.GetBundleResponse - 9, // 48: proto.BundleService.ListBundles:output_type -> proto.ListBundlesResponse - 11, // 49: proto.BundleService.AddSettingToBundle:output_type -> proto.AddSettingToBundleResponse - 41, // 50: proto.BundleService.RemoveSettingFromBundle:output_type -> google.protobuf.Empty - 14, // 51: proto.ValueService.SaveValue:output_type -> proto.SaveValueResponse - 16, // 52: proto.ValueService.GetValue:output_type -> proto.GetValueResponse - 18, // 53: proto.ValueService.ListValues:output_type -> proto.ListValuesResponse - 16, // 54: proto.ValueService.GetValueByUniqueIdentifiers:output_type -> proto.GetValueResponse - 9, // 55: proto.RoleService.ListRoles:output_type -> proto.ListBundlesResponse - 23, // 56: proto.RoleService.ListRoleAssignments:output_type -> proto.ListRoleAssignmentsResponse - 25, // 57: proto.RoleService.AssignRoleToUser:output_type -> proto.AssignRoleToUserResponse - 41, // 58: proto.RoleService.RemoveRoleFromUser:output_type -> google.protobuf.Empty - 46, // [46:59] is the sub-list for method output_type - 33, // [33:46] is the sub-list for method input_type - 33, // [33:33] is the sub-list for extension type_name - 33, // [33:33] is the sub-list for extension extendee - 0, // [0:33] is the sub-list for field type_name + 30, // 14: proto.ListPermissionsByResourceRequest.resource:type_name -> proto.Resource + 39, // 15: proto.ListPermissionsByResourceResponse.permissions:type_name -> proto.Permission + 0, // 16: proto.Resource.type:type_name -> proto.Resource.Type + 1, // 17: proto.Bundle.type:type_name -> proto.Bundle.Type + 32, // 18: proto.Bundle.settings:type_name -> proto.Setting + 30, // 19: proto.Bundle.resource:type_name -> proto.Resource + 33, // 20: proto.Setting.int_value:type_name -> proto.Int + 34, // 21: proto.Setting.string_value:type_name -> proto.String + 35, // 22: proto.Setting.bool_value:type_name -> proto.Bool + 36, // 23: proto.Setting.single_choice_value:type_name -> proto.SingleChoiceList + 37, // 24: proto.Setting.multi_choice_value:type_name -> proto.MultiChoiceList + 39, // 25: proto.Setting.permission_value:type_name -> proto.Permission + 30, // 26: proto.Setting.resource:type_name -> proto.Resource + 38, // 27: proto.SingleChoiceList.options:type_name -> proto.ListOption + 38, // 28: proto.MultiChoiceList.options:type_name -> proto.ListOption + 42, // 29: proto.ListOption.value:type_name -> proto.ListOptionValue + 2, // 30: proto.Permission.operation:type_name -> proto.Permission.Operation + 3, // 31: proto.Permission.constraint:type_name -> proto.Permission.Constraint + 30, // 32: proto.Value.resource:type_name -> proto.Resource + 41, // 33: proto.Value.list_value:type_name -> proto.ListValue + 42, // 34: proto.ListValue.values:type_name -> proto.ListOptionValue + 4, // 35: proto.BundleService.SaveBundle:input_type -> proto.SaveBundleRequest + 6, // 36: proto.BundleService.GetBundle:input_type -> proto.GetBundleRequest + 8, // 37: proto.BundleService.ListBundles:input_type -> proto.ListBundlesRequest + 10, // 38: proto.BundleService.AddSettingToBundle:input_type -> proto.AddSettingToBundleRequest + 12, // 39: proto.BundleService.RemoveSettingFromBundle:input_type -> proto.RemoveSettingFromBundleRequest + 13, // 40: proto.ValueService.SaveValue:input_type -> proto.SaveValueRequest + 15, // 41: proto.ValueService.GetValue:input_type -> proto.GetValueRequest + 17, // 42: proto.ValueService.ListValues:input_type -> proto.ListValuesRequest + 19, // 43: proto.ValueService.GetValueByUniqueIdentifiers:input_type -> proto.GetValueByUniqueIdentifiersRequest + 8, // 44: proto.RoleService.ListRoles:input_type -> proto.ListBundlesRequest + 22, // 45: proto.RoleService.ListRoleAssignments:input_type -> proto.ListRoleAssignmentsRequest + 24, // 46: proto.RoleService.AssignRoleToUser:input_type -> proto.AssignRoleToUserRequest + 26, // 47: proto.RoleService.RemoveRoleFromUser:input_type -> proto.RemoveRoleFromUserRequest + 28, // 48: proto.PermissionService.ListPermissionsByResource:input_type -> proto.ListPermissionsByResourceRequest + 5, // 49: proto.BundleService.SaveBundle:output_type -> proto.SaveBundleResponse + 7, // 50: proto.BundleService.GetBundle:output_type -> proto.GetBundleResponse + 9, // 51: proto.BundleService.ListBundles:output_type -> proto.ListBundlesResponse + 11, // 52: proto.BundleService.AddSettingToBundle:output_type -> proto.AddSettingToBundleResponse + 43, // 53: proto.BundleService.RemoveSettingFromBundle:output_type -> google.protobuf.Empty + 14, // 54: proto.ValueService.SaveValue:output_type -> proto.SaveValueResponse + 16, // 55: proto.ValueService.GetValue:output_type -> proto.GetValueResponse + 18, // 56: proto.ValueService.ListValues:output_type -> proto.ListValuesResponse + 16, // 57: proto.ValueService.GetValueByUniqueIdentifiers:output_type -> proto.GetValueResponse + 9, // 58: proto.RoleService.ListRoles:output_type -> proto.ListBundlesResponse + 23, // 59: proto.RoleService.ListRoleAssignments:output_type -> proto.ListRoleAssignmentsResponse + 25, // 60: proto.RoleService.AssignRoleToUser:output_type -> proto.AssignRoleToUserResponse + 43, // 61: proto.RoleService.RemoveRoleFromUser:output_type -> google.protobuf.Empty + 29, // 62: proto.PermissionService.ListPermissionsByResource:output_type -> proto.ListPermissionsByResourceResponse + 49, // [49:63] is the sub-list for method output_type + 35, // [35:49] is the sub-list for method input_type + 35, // [35:35] is the sub-list for extension type_name + 35, // [35:35] is the sub-list for extension extendee + 0, // [0:35] is the sub-list for field type_name } func init() { file_settings_proto_init() } @@ -3313,7 +3443,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Resource); i { + switch v := v.(*ListPermissionsByResourceRequest); i { case 0: return &v.state case 1: @@ -3325,7 +3455,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Bundle); i { + switch v := v.(*ListPermissionsByResourceResponse); i { case 0: return &v.state case 1: @@ -3337,7 +3467,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Setting); i { + switch v := v.(*Resource); i { case 0: return &v.state case 1: @@ -3349,7 +3479,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Int); i { + switch v := v.(*Bundle); i { case 0: return &v.state case 1: @@ -3361,7 +3491,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*String); i { + switch v := v.(*Setting); i { case 0: return &v.state case 1: @@ -3373,7 +3503,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Bool); i { + switch v := v.(*Int); i { case 0: return &v.state case 1: @@ -3385,7 +3515,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SingleChoiceList); i { + switch v := v.(*String); i { case 0: return &v.state case 1: @@ -3397,7 +3527,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MultiChoiceList); i { + switch v := v.(*Bool); i { case 0: return &v.state case 1: @@ -3409,7 +3539,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListOption); i { + switch v := v.(*SingleChoiceList); i { case 0: return &v.state case 1: @@ -3421,7 +3551,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Permission); i { + switch v := v.(*MultiChoiceList); i { case 0: return &v.state case 1: @@ -3433,7 +3563,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Value); i { + switch v := v.(*ListOption); i { case 0: return &v.state case 1: @@ -3445,7 +3575,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListValue); i { + switch v := v.(*Permission); i { case 0: return &v.state case 1: @@ -3457,6 +3587,30 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Value); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_settings_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_settings_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListOptionValue); i { case 0: return &v.state @@ -3469,7 +3623,7 @@ func file_settings_proto_init() { } } } - file_settings_proto_msgTypes[26].OneofWrappers = []interface{}{ + file_settings_proto_msgTypes[28].OneofWrappers = []interface{}{ (*Setting_IntValue)(nil), (*Setting_StringValue)(nil), (*Setting_BoolValue)(nil), @@ -3477,13 +3631,13 @@ func file_settings_proto_init() { (*Setting_MultiChoiceValue)(nil), (*Setting_PermissionValue)(nil), } - file_settings_proto_msgTypes[34].OneofWrappers = []interface{}{ + file_settings_proto_msgTypes[36].OneofWrappers = []interface{}{ (*Value_BoolValue)(nil), (*Value_IntValue)(nil), (*Value_StringValue)(nil), (*Value_ListValue)(nil), } - file_settings_proto_msgTypes[36].OneofWrappers = []interface{}{ + file_settings_proto_msgTypes[38].OneofWrappers = []interface{}{ (*ListOptionValue_StringValue)(nil), (*ListOptionValue_IntValue)(nil), } @@ -3493,9 +3647,9 @@ func file_settings_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_settings_proto_rawDesc, NumEnums: 4, - NumMessages: 37, + NumMessages: 39, NumExtensions: 0, - NumServices: 3, + NumServices: 4, }, GoTypes: file_settings_proto_goTypes, DependencyIndexes: file_settings_proto_depIdxs, diff --git a/pkg/proto/v0/settings.pb.micro.go b/pkg/proto/v0/settings.pb.micro.go index 4ae18404f3..88d0b917c2 100644 --- a/pkg/proto/v0/settings.pb.micro.go +++ b/pkg/proto/v0/settings.pb.micro.go @@ -567,3 +567,77 @@ func (h *roleServiceHandler) AssignRoleToUser(ctx context.Context, in *AssignRol func (h *roleServiceHandler) RemoveRoleFromUser(ctx context.Context, in *RemoveRoleFromUserRequest, out *empty.Empty) error { return h.RoleServiceHandler.RemoveRoleFromUser(ctx, in, out) } + +// Api Endpoints for PermissionService service + +func NewPermissionServiceEndpoints() []*api.Endpoint { + return []*api.Endpoint{ + &api.Endpoint{ + Name: "PermissionService.ListPermissionsByResource", + Path: []string{"/api/v0/settings/permissions-list-by-resource"}, + Method: []string{"POST"}, + Body: "*", + Handler: "rpc", + }, + } +} + +// Client API for PermissionService service + +type PermissionService interface { + ListPermissionsByResource(ctx context.Context, in *ListPermissionsByResourceRequest, opts ...client.CallOption) (*ListPermissionsByResourceResponse, error) +} + +type permissionService struct { + c client.Client + name string +} + +func NewPermissionService(name string, c client.Client) PermissionService { + return &permissionService{ + c: c, + name: name, + } +} + +func (c *permissionService) ListPermissionsByResource(ctx context.Context, in *ListPermissionsByResourceRequest, opts ...client.CallOption) (*ListPermissionsByResourceResponse, error) { + req := c.c.NewRequest(c.name, "PermissionService.ListPermissionsByResource", in) + out := new(ListPermissionsByResourceResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for PermissionService service + +type PermissionServiceHandler interface { + ListPermissionsByResource(context.Context, *ListPermissionsByResourceRequest, *ListPermissionsByResourceResponse) error +} + +func RegisterPermissionServiceHandler(s server.Server, hdlr PermissionServiceHandler, opts ...server.HandlerOption) error { + type permissionService interface { + ListPermissionsByResource(ctx context.Context, in *ListPermissionsByResourceRequest, out *ListPermissionsByResourceResponse) error + } + type PermissionService struct { + permissionService + } + h := &permissionServiceHandler{hdlr} + opts = append(opts, api.WithEndpoint(&api.Endpoint{ + Name: "PermissionService.ListPermissionsByResource", + Path: []string{"/api/v0/settings/permissions-list-by-resource"}, + Method: []string{"POST"}, + Body: "*", + Handler: "rpc", + })) + return s.Handle(s.NewHandler(&PermissionService{h}, opts...)) +} + +type permissionServiceHandler struct { + PermissionServiceHandler +} + +func (h *permissionServiceHandler) ListPermissionsByResource(ctx context.Context, in *ListPermissionsByResourceRequest, out *ListPermissionsByResourceResponse) error { + return h.PermissionServiceHandler.ListPermissionsByResource(ctx, in, out) +} diff --git a/pkg/proto/v0/settings.pb.micro_test.go b/pkg/proto/v0/settings.pb.micro_test.go index 86e58591b5..d8c271f0ec 100644 --- a/pkg/proto/v0/settings.pb.micro_test.go +++ b/pkg/proto/v0/settings.pb.micro_test.go @@ -3,15 +3,15 @@ package proto_test import ( "context" "encoding/json" - fmt "fmt" + "fmt" "log" "os" "testing" merrors "github.com/micro/go-micro/v2/errors" - - mgrpc "github.com/micro/go-micro/v2/client/grpc" + "github.com/micro/go-micro/v2/metadata" ocislog "github.com/owncloud/ocis-pkg/v2/log" + "github.com/owncloud/ocis-pkg/v2/middleware" "github.com/owncloud/ocis-pkg/v2/service/grpc" "github.com/owncloud/ocis-settings/pkg/config" "github.com/owncloud/ocis-settings/pkg/proto/v0" @@ -20,16 +20,23 @@ import ( "github.com/stretchr/testify/assert" ) -var service = grpc.Service{} - var ( + service grpc.Service + handler svc.Service + bundleService proto.BundleService + valueService proto.ValueService + roleService proto.RoleService + permissionService proto.PermissionService + + testAccountID = "e8a7f56b-10ce-4f67-b67f-eca40aa0ef26" + settingsStub = []*proto.Setting{ { Id: "336c4db1-5062-4931-990f-d88e6b02cb02", DisplayName: "dummy setting", Name: "dummy-setting", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Value: &proto.Setting_IntValue{ IntValue: &proto.Int{ @@ -39,193 +46,9 @@ var ( Description: "dummy setting", }, } -) -const dataStore = "/var/tmp/ocis-settings" - -func init() { - service = grpc.NewService( - grpc.Namespace("com.owncloud.api"), - grpc.Name("settings"), - grpc.Address("localhost:9992"), - ) - - cfg := config.New() - cfg.Storage.DataPath = dataStore - // Service initialization is not reliable. It most lilely happens - // asynchronous causing a data race in some tests where it needs - // as service but this is not available. - err := proto.RegisterBundleServiceHandler(service.Server(), svc.NewService(cfg, ocislog.NewLogger(ocislog.Color(true), ocislog.Pretty(true)))) - if err != nil { - log.Fatalf("could not register BundleServiceHandler: %v", err) - } - err = proto.RegisterValueServiceHandler(service.Server(), svc.NewService(cfg, ocislog.NewLogger(ocislog.Color(true), ocislog.Pretty(true)))) - if err != nil { - log.Fatalf("could not register ValueServiceHandler: %v", err) - } - err = proto.RegisterRoleServiceHandler(service.Server(), svc.NewService(cfg, ocislog.NewLogger(ocislog.Color(true), ocislog.Pretty(true)))) - if err != nil { - log.Fatalf("could not register RegisterRoleServiceHandler: %v", err) - } - - if err = service.Server().Start(); err != nil { - log.Fatalf("could not start server: %v", err) - } -} - -/** -testing that saving a settings bundle and retrieving it again works correctly -using various setting bundle properties -*/ -func TestSettingsBundleProperties(t *testing.T) { - client := service.Client() - cl := proto.NewBundleService("com.owncloud.api.settings", client) - - var scenarios = []struct { - name string - bundleName string - displayName string - extensionName string - UUID string - expectedError error - }{ - { - "ASCII", - "bundle-name", - "simple-bundle-key", - "simple-extension-name", - "123e4567-e89b-12d3-a456-426652340000", - nil, - }, - { - "UTF validation on bundle name", - "सिम्प्ले-bundle-name", - "सिम्प्ले-display-name", - "सिम्प्ले-extension-name", - "सिम्प्ले", - merrors.New("ocis-settings", "extension: must be in a valid format; name: must be in a valid format.", 400), - }, - { - "UTF validation on display name", - "सिम्प्ले-bundle-name", - "सिम्प्ले-display-name", - "simple-extension-name", - "123e4567-e89b-12d3-a456-426652340000", - merrors.New("ocis-settings", "name: must be in a valid format.", 400), - }, - { - "extension name with ../ in the name", - "bundle-name", - "simple-display-name", - "../folder-a-level-higher-up", - "123e4567-e89b-12d3-a456-426652340000", - merrors.New("ocis-settings", "extension: must be in a valid format.", 400), - }, - { - "extension name with \\ in the name", - "bundle-name", - "simple-display-name", - "\\", - "123e4567-e89b-12d3-a456-426652340000", - merrors.New("ocis-settings", "extension: must be in a valid format.", 400), - }, - { - "spaces are disallowed in bundle names", - "bundle name", - "simple display name", - "simple extension name", - "123e4567-e89b-12d3-a456-426652340000", - merrors.New("ocis-settings", "extension: must be in a valid format; name: must be in a valid format.", 400), - }, - { - "spaces are allowed in display names", - "bundle-name", - "simple display name", - "simple-extension-name", - "123e4567-e89b-12d3-a456-426652340000", - nil, - }, - { - "extension missing", - "bundle-name", - "simple-display-name", - "", - "123e4567-e89b-12d3-a456-426652340000", - merrors.New("ocis-settings", "extension: cannot be blank.", 400), - }, - { - "display name missing", - "bundleName", - "", - "simple-extension-name", - "123e4567-e89b-12d3-a456-426652340000", - merrors.New("ocis-settings", "display_name: cannot be blank.", 400), - }, - { - "UUID missing (omitted on bundles)", - "bundle-name", - "simple-display-name", - "simple-extension-name", - "", - nil, - }, - } - for _, scenario := range scenarios { - scenario := scenario - t.Run(scenario.name, func(t *testing.T) { - bundle := proto.Bundle{ - Name: scenario.bundleName, - Extension: scenario.extensionName, - DisplayName: scenario.displayName, - Type: proto.Bundle_TYPE_DEFAULT, - Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, - }, - Settings: settingsStub, - } - createRequest := proto.SaveBundleRequest{ - Bundle: &bundle, - } - - cresponse, err := cl.SaveBundle(context.Background(), &createRequest) - if err != nil || scenario.expectedError != nil { - t.Log(err) - assert.Equal(t, scenario.expectedError, err) - } else { - assert.Equal(t, scenario.extensionName, cresponse.Bundle.Extension) - assert.Equal(t, scenario.displayName, cresponse.Bundle.DisplayName) - getRequest := proto.GetBundleRequest{BundleId: cresponse.Bundle.Id} - getResponse, err := cl.GetBundle(context.Background(), &getRequest) - assert.NoError(t, err) - assert.Equal(t, scenario.displayName, getResponse.Bundle.DisplayName) - } - os.RemoveAll(dataStore) - }) - } -} - -func TestSettingsBundleWithoutSettings(t *testing.T) { - client := service.Client() - cl := proto.NewBundleService("com.owncloud.api.settings", client) - - createRequest := proto.SaveBundleRequest{ - Bundle: &proto.Bundle{ - DisplayName: "Alice's Bundle", - }, - } - response, err := cl.SaveBundle(context.Background(), &createRequest) - assert.Error(t, err) - assert.Nil(t, response) - assert.Equal(t, merrors.New("ocis-settings", "extension: cannot be blank; name: cannot be blank; settings: cannot be blank.", 400), err) - os.RemoveAll(dataStore) -} - -// /** -// testing that setting getting and listing a settings bundle works correctly with a set of setting definitions -// */ -func TestSaveGetListSettingsBundle(t *testing.T) { - //options for choice list settings - options := []*proto.ListOption{ + //optionsForListStub for choice list settings + optionsForListStub = []*proto.ListOption{ { Value: &proto.ListOptionValue{ Option: &proto.ListOptionValue_StringValue{StringValue: "list option string value"}, @@ -243,18 +66,19 @@ func TestSaveGetListSettingsBundle(t *testing.T) { } //MultiChoiceList - multipleChoiceSetting := proto.MultiChoiceList{ - Options: options, + multipleChoiceSettingStub = proto.MultiChoiceList{ + Options: optionsForListStub, } //SingleChoiceList - singleChoiceSetting := proto.SingleChoiceList{ - Options: options, + singleChoiceSettingStub = proto.SingleChoiceList{ + Options: optionsForListStub, } - settings := []*proto.Setting{ + complexSettingsStub = []*proto.Setting{ { Name: "int", + Id: "4e00633d-5373-4df4-9299-1c9ed9c3ebed", DisplayName: "an integer value", Description: "with some description", Value: &proto.Setting_IntValue{ @@ -267,11 +91,12 @@ func TestSaveGetListSettingsBundle(t *testing.T) { }, }, Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, }, { Name: "string", + Id: "f792acb4-9f09-4fa8-92d3-4a0d0a6ca721", DisplayName: "a string value", Description: "with some description", Value: &proto.Setting_StringValue{ @@ -284,11 +109,12 @@ func TestSaveGetListSettingsBundle(t *testing.T) { }, }, Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, }, { Name: "bool", + Id: "6ef9268c-f0bd-48a7-a0a0-3ba3ee42b5cc", DisplayName: "a bool value", Description: "with some description", Value: &proto.Setting_BoolValue{ @@ -298,74 +124,407 @@ func TestSaveGetListSettingsBundle(t *testing.T) { }, }, Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, }, { Name: "multipleChoice", + Id: "905da88c-3be0-42c2-a8b2-e6bcd9976b2d", DisplayName: "a multiple choice setting", Description: "with some description", Value: &proto.Setting_MultiChoiceValue{ - MultiChoiceValue: &multipleChoiceSetting, + MultiChoiceValue: &multipleChoiceSettingStub, }, Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, }, { Name: "singleChoice", + Id: "5bf4de47-57cc-4705-a456-4fcf39673994", DisplayName: "a single choice setting", Description: "with some description", Value: &proto.Setting_SingleChoiceValue{ - SingleChoiceValue: &singleChoiceSetting, + SingleChoiceValue: &singleChoiceSettingStub, }, Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, }, } - bundle := proto.Bundle{ + bundleStub = proto.Bundle{ Name: "test", + Id: "b1b8c9d0-fb3c-4e12-b868-5a8508218d2e", DisplayName: "bundleDisplayName", Extension: "testExtension", Type: proto.Bundle_TYPE_DEFAULT, - Settings: settings, + Settings: complexSettingsStub, Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_SYSTEM, }, } - saveRequest := proto.SaveBundleRequest{ - Bundle: &bundle, +) + +const dataPath = "/var/tmp/grpc-tests-ocis-settings" + +func init() { + service = grpc.NewService( + grpc.Namespace("com.owncloud.api"), + grpc.Name("settings"), + grpc.Address("localhost:9992"), + ) + + cfg := config.New() + cfg.Storage.DataPath = dataPath + handler = svc.NewService(cfg, ocislog.NewLogger(ocislog.Color(true), ocislog.Pretty(true))) + err := proto.RegisterBundleServiceHandler(service.Server(), handler) + if err != nil { + log.Fatalf("could not register BundleServiceHandler: %v", err) + } + err = proto.RegisterValueServiceHandler(service.Server(), handler) + if err != nil { + log.Fatalf("could not register ValueServiceHandler: %v", err) + } + err = proto.RegisterRoleServiceHandler(service.Server(), handler) + if err != nil { + log.Fatalf("could not register RoleServiceHandler: %v", err) + } + err = proto.RegisterPermissionServiceHandler(service.Server(), handler) + if err != nil { + log.Fatalf("could not register PermissionServiceHandler: %v", err) + } + + if err = service.Server().Start(); err != nil { + log.Fatalf("could not start server: %v", err) } client := service.Client() - cl := proto.NewBundleService("com.owncloud.api.settings", client) + bundleService = proto.NewBundleService("com.owncloud.api.settings", client) + valueService = proto.NewValueService("com.owncloud.api.settings", client) + roleService = proto.NewRoleService("com.owncloud.api.settings", client) + permissionService = proto.NewPermissionService("com.owncloud.api.settings", client) +} + +func setup() func() { + handler.RegisterDefaultRoles() + return func() { + if err := os.RemoveAll(dataPath); err != nil { + log.Printf("could not delete data root: %s", dataPath) + } else { + log.Println("data root deleted") + } + } +} + +/** +testing that saving a settings bundle and retrieving it again works correctly +using various setting bundle properties +*/ +func TestBundleInputValidation(t *testing.T) { + var scenarios = []struct { + name string + bundleName string + displayName string + extensionName string + expectedError error + }{ + { + "ASCII", + "bundle-name", + "simple-bundle-key", + "simple-extension-name", + nil, + }, + { + "UTF validation on bundle name", + "सिम्प्ले-bundle-name", + "सिम्प्ले-display-name", + "सिम्प्ले-extension-name", + merrors.New("ocis-settings", "extension: must be in a valid format; name: must be in a valid format.", 400), + }, + { + "UTF validation on display name", + "सिम्प्ले-bundle-name", + "सिम्प्ले-display-name", + "simple-extension-name", + merrors.New("ocis-settings", "name: must be in a valid format.", 400), + }, + { + "extension name with ../ in the name", + "bundle-name", + "simple-display-name", + "../folder-a-level-higher-up", + merrors.New("ocis-settings", "extension: must be in a valid format.", 400), + }, + { + "extension name with \\ in the name", + "bundle-name", + "simple-display-name", + "\\", + merrors.New("ocis-settings", "extension: must be in a valid format.", 400), + }, + { + "spaces are disallowed in bundle names", + "bundle name", + "simple display name", + "simple extension name", + merrors.New("ocis-settings", "extension: must be in a valid format; name: must be in a valid format.", 400), + }, + { + "spaces are allowed in display names", + "bundle-name", + "simple display name", + "simple-extension-name", + nil, + }, + { + "extension missing", + "bundle-name", + "simple-display-name", + "", + merrors.New("ocis-settings", "extension: cannot be blank.", 400), + }, + { + "display name missing", + "bundleName", + "", + "simple-extension-name", + merrors.New("ocis-settings", "display_name: cannot be blank.", 400), + }, + } + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + teardown := setup() + defer teardown() + + bundle := proto.Bundle{ + Name: scenario.bundleName, + Extension: scenario.extensionName, + DisplayName: scenario.displayName, + Type: proto.Bundle_TYPE_DEFAULT, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + Settings: settingsStub, + } + createRequest := proto.SaveBundleRequest{ + Bundle: &bundle, + } + + cresponse, err := bundleService.SaveBundle(context.Background(), &createRequest) + if err != nil || scenario.expectedError != nil { + t.Log(err) + assert.Equal(t, scenario.expectedError, err) + } else { + assert.Equal(t, scenario.extensionName, cresponse.Bundle.Extension) + assert.Equal(t, scenario.displayName, cresponse.Bundle.DisplayName) + + // we want to test input validation, so just allow the request permission-wise + setFullReadWriteOnBundle(t, testAccountID, cresponse.Bundle.Id) + + ctx := metadata.Set(context.Background(), middleware.AccountID, testAccountID) + getRequest := proto.GetBundleRequest{BundleId: cresponse.Bundle.Id} + getResponse, err := bundleService.GetBundle(ctx, &getRequest) + assert.NoError(t, err) + if err == nil { + assert.Equal(t, scenario.displayName, getResponse.Bundle.DisplayName) + } + } + }) + } +} + +func TestSaveBundleWithoutSettings(t *testing.T) { + teardown := setup() + defer teardown() + + createRequest := proto.SaveBundleRequest{ + Bundle: &proto.Bundle{ + DisplayName: "Alice's Bundle", + }, + } + response, err := bundleService.SaveBundle(context.Background(), &createRequest) + assert.Error(t, err) + assert.Nil(t, response) + assert.Equal(t, merrors.New("ocis-settings", "extension: cannot be blank; name: cannot be blank; settings: cannot be blank.", 400), err) +} + +func TestGetBundleOfABundleSavedWithoutPermissions(t *testing.T) { + teardown := setup() + defer teardown() + + saveRequest := proto.SaveBundleRequest{ + Bundle: &bundleStub, + } + saveResponse, err := bundleService.SaveBundle(context.Background(), &saveRequest) + assert.NoError(t, err) + assert.Equal(t, bundleStub.Id, saveResponse.Bundle.Id) + + getRequest := proto.GetBundleRequest{BundleId: bundleStub.Id} + ctx := metadata.Set(context.Background(), middleware.AccountID, testAccountID) + getResponse, err := bundleService.GetBundle(ctx, &getRequest) + assert.Empty(t, getResponse) + + assert.Equal(t, merrors.New("ocis-settings", "could not read bundle: b1b8c9d0-fb3c-4e12-b868-5a8508218d2e", 404), err) +} + +func TestGetBundleOfABundleSavedWithFullPermissionsButForAnOtherUser(t *testing.T) { + teardown := setup() + defer teardown() + + saveRequest := proto.SaveBundleRequest{ + Bundle: &bundleStub, + } + saveResponse, err := bundleService.SaveBundle(context.Background(), &saveRequest) + assert.NoError(t, err) + assert.Equal(t, bundleStub.Id, saveResponse.Bundle.Id) + + setFullReadWriteOnBundle(t, "33ba12b3-0340-44ec-afdf-253fb90ea47d", bundleStub.Id) + getRequest := proto.GetBundleRequest{BundleId: bundleStub.Id} + ctx := metadata.Set(context.Background(), middleware.AccountID, testAccountID) + getResponse, err := bundleService.GetBundle(ctx, &getRequest) + assert.Empty(t, getResponse) + + assert.Equal(t, merrors.New("ocis-settings", "could not read bundle: b1b8c9d0-fb3c-4e12-b868-5a8508218d2e", 404), err) +} + +/** +testing that setting getting and listing a settings bundle works correctly with a set of setting definitions +*/ +func TestSaveAndGetBundle(t *testing.T) { + teardown := setup() + defer teardown() + + saveRequest := proto.SaveBundleRequest{ + Bundle: &bundleStub, + } // assert that SaveBundle returns the same bundle as we have sent - saveResponse, err := cl.SaveBundle(context.Background(), &saveRequest) + saveResponse, err := bundleService.SaveBundle(context.Background(), &saveRequest) assert.NoError(t, err) receivedBundle, _ := json.Marshal(saveResponse.Bundle.Settings) - expectedBundle, _ := json.Marshal(&bundle.Settings) + expectedBundle, _ := json.Marshal(&bundleStub.Settings) assert.Equal(t, receivedBundle, expectedBundle) + // set full permissions for getting the created bundle + setFullReadWriteOnBundle(t, testAccountID, saveResponse.Bundle.Id) + //assert that GetBundle returns the same bundle as saved getRequest := proto.GetBundleRequest{BundleId: saveResponse.Bundle.Id} - getResponse, err := cl.GetBundle(context.Background(), &getRequest) + ctx := metadata.Set(context.Background(), middleware.AccountID, testAccountID) + getResponse, err := bundleService.GetBundle(ctx, &getRequest) assert.NoError(t, err) - receivedBundle, _ = json.Marshal(getResponse.Bundle.Settings) - assert.Equal(t, expectedBundle, receivedBundle) + if err == nil { + receivedBundle, _ = json.Marshal(getResponse.Bundle.Settings) + assert.Equal(t, expectedBundle, receivedBundle) + } +} - os.RemoveAll(dataStore) +/** +testing that saving a value works and can be retrieved again +*/ +func TestSaveGetIntValue(t *testing.T) { + tests := []struct { + name string + value proto.Value_IntValue + }{ + { + name: "simple int", + value: proto.Value_IntValue{IntValue: 43}, + }, + { + name: "negative", + value: proto.Value_IntValue{IntValue: -42}, + // https://github.com/owncloud/ocis-settings/issues/57 + }, + { + name: "less than Min", + value: proto.Value_IntValue{IntValue: 0}, + // https://github.com/owncloud/ocis-settings/issues/57 + }, + { + name: "more than Max", + value: proto.Value_IntValue{IntValue: 128}, + // https://github.com/owncloud/ocis-settings/issues/57 + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + teardown := setup() + defer teardown() + + saveResponse, err := bundleService.SaveBundle(context.Background(), &proto.SaveBundleRequest{ + Bundle: &bundleStub, + }) + assert.NoError(t, err) + + saveValueResponse, err := valueService.SaveValue(context.Background(), &proto.SaveValueRequest{ + Value: &proto.Value{ + BundleId: saveResponse.Bundle.Id, + SettingId: "4e00633d-5373-4df4-9299-1c9ed9c3ebed", //setting id of the int setting + AccountUuid: "047d31b0-219a-47a4-8ee5-c5fa3802a3c2", + Value: &tt.value, + Resource: &proto.Resource{ + Type: 0, + Id: ".", + }, + }, + }) + assert.NoError(t, err) + assert.Equal(t, tt.value.IntValue, saveValueResponse.Value.Value.GetIntValue()) + + getValueResponse, err := valueService.GetValue( + context.Background(), &proto.GetValueRequest{Id: saveValueResponse.Value.Value.Id}, + ) + assert.NoError(t, err) + assert.Equal(t, tt.value.IntValue, getValueResponse.Value.Value.GetIntValue()) + }) + } +} + +/** +try to save a wrong type of the value +https://github.com/owncloud/ocis-settings/issues/57 +*/ +func TestSaveGetIntValueIntoString(t *testing.T) { + teardown := setup() + defer teardown() + + saveResponse, err := bundleService.SaveBundle(context.Background(), &proto.SaveBundleRequest{ + Bundle: &bundleStub, + }) + assert.NoError(t, err) + + saveValueResponse, err := valueService.SaveValue(context.Background(), &proto.SaveValueRequest{ + Value: &proto.Value{ + BundleId: saveResponse.Bundle.Id, + SettingId: "f792acb4-9f09-4fa8-92d3-4a0d0a6ca721", //setting id of the string setting + AccountUuid: "047d31b0-219a-47a4-8ee5-c5fa3802a3c2", + Value: &proto.Value_StringValue{StringValue: "forty two"}, + Resource: &proto.Resource{ + Type: 0, + Id: ".", + }, + }, + }) + assert.NoError(t, err) + assert.Equal(t, "forty two", saveValueResponse.Value.Value.GetStringValue()) + + getValueResponse, err := valueService.GetValue( + context.Background(), &proto.GetValueRequest{Id: saveValueResponse.Value.Value.Id}, + ) + assert.NoError(t, err) + assert.Equal(t, "forty two", getValueResponse.Value.Value.GetStringValue()) } // https://github.com/owncloud/ocis-settings/issues/18 -func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { +func TestSaveBundleWithInvalidSettings(t *testing.T) { var tests = []proto.Setting{ { Name: "intValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "intValue default is out of range", Value: &proto.Setting_IntValue{ @@ -379,7 +538,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "intValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "intValue min gt max", Value: &proto.Setting_IntValue{ @@ -393,7 +552,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "intValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "intValue step gt max-min", Value: &proto.Setting_IntValue{ @@ -407,7 +566,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "intValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "intValue step eq 0", Value: &proto.Setting_IntValue{ @@ -421,7 +580,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "intValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "intValue step lt 0", Value: &proto.Setting_IntValue{ @@ -435,7 +594,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "stringValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "stringValue MinLength gt MaxLength", Value: &proto.Setting_StringValue{ @@ -448,7 +607,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "stringValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "stringValue MaxLength eq 0", Value: &proto.Setting_StringValue{ @@ -460,7 +619,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "stringValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "stringValue MinLength lt 0", Value: &proto.Setting_StringValue{ @@ -472,7 +631,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "stringValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "stringValue MaxLength lt 0", Value: &proto.Setting_StringValue{ @@ -484,7 +643,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "multiChoiceValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "multiChoice multiple options are default", Value: &proto.Setting_MultiChoiceValue{ @@ -509,7 +668,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { { Name: "singleChoiceValue", Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_USER, }, Description: "singleChoice multiple options are default", Value: &proto.Setting_SingleChoiceValue{ @@ -534,8 +693,9 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { } for index := range tests { - index := index t.Run(tests[index].Name, func(t *testing.T) { + teardown := setup() + defer teardown() var settings []*proto.Setting @@ -546,7 +706,7 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { DisplayName: "bundledisplayname", Type: proto.Bundle_TYPE_DEFAULT, Resource: &proto.Resource{ - Type: proto.Resource_TYPE_BUNDLE, + Type: proto.Resource_TYPE_SYSTEM, }, Settings: settings, } @@ -554,40 +714,35 @@ func TestSaveSettingsBundleWithInvalidSettingValues(t *testing.T) { Bundle: &bundle, } - client := service.Client() - cl := proto.NewBundleService("com.owncloud.api.settings", client) - //assert that SaveBundle returns the same bundle as we have sent there - saveResponse, err := cl.SaveBundle(context.Background(), &saveRequest) + saveResponse, err := bundleService.SaveBundle(context.Background(), &saveRequest) assert.NoError(t, err) receivedBundle, _ := json.Marshal(saveResponse.Bundle.Settings) expectedBundle, _ := json.Marshal(&bundle.Settings) assert.Equal(t, expectedBundle, receivedBundle) - os.RemoveAll(dataStore) }) } } // https://github.com/owncloud/ocis-settings/issues/19 -func TestGetSettingsBundleCreatesFolder(t *testing.T) { - client := service.Client() - cl := proto.NewBundleService("com.owncloud.api.settings", client) +func TestGetBundleNoSideEffectsOnDisk(t *testing.T) { + teardown := setup() + defer teardown() + getRequest := proto.GetBundleRequest{BundleId: "non-existing-bundle"} - _, _ = cl.GetBundle(context.Background(), &getRequest) + _, _ = bundleService.GetBundle(context.Background(), &getRequest) assert.NoDirExists(t, store.Name+"/bundles/non-existing-bundle") assert.NoFileExists(t, store.Name+"/bundles/non-existing-bundle/not-existing-bundle.json") - os.RemoveAll(dataStore) } // TODO non-deterministic. Fix. func TestCreateRoleAndAssign(t *testing.T) { - c := mgrpc.NewClient() - bundleC := proto.NewBundleService("com.owncloud.api.settings", c) + teardown := setup() + defer teardown() - res, err := bundleC.SaveBundle(context.Background(), &proto.SaveBundleRequest{ + res, err := bundleService.SaveBundle(context.Background(), &proto.SaveBundleRequest{ Bundle: &proto.Bundle{ - // Id: "f36db5e6-a03c-40df-8413-711c67e40b47", // bug: providing the ID ignores its value for the filename. Type: proto.Bundle_TYPE_ROLE, DisplayName: "test role - update", Name: "TEST_ROLE", @@ -600,7 +755,7 @@ func TestCreateRoleAndAssign(t *testing.T) { Type: proto.Resource_TYPE_SETTING, }, Value: &proto.Setting_PermissionValue{ - &proto.Permission{ + PermissionValue: &proto.Permission{ Operation: proto.Permission_OPERATION_UPDATE, Constraint: proto.Permission_CONSTRAINT_OWN, }, @@ -613,8 +768,7 @@ func TestCreateRoleAndAssign(t *testing.T) { }, }) if err == nil { - rolesC := proto.NewRoleService("com.owncloud.api.settings", c) - _, err = rolesC.AssignRoleToUser(context.Background(), &proto.AssignRoleToUserRequest{ + _, err = roleService.AssignRoleToUser(context.Background(), &proto.AssignRoleToUserRequest{ AccountUuid: "4c510ada-c86b-4815-8820-42cdf82c3d51", RoleId: res.Bundle.Id, }) @@ -623,7 +777,6 @@ func TestCreateRoleAndAssign(t *testing.T) { } assert.NoError(t, err) } - os.RemoveAll(dataStore) } // // TODO this tests are non-deterministic at least on my machine. Find a way to make them deterministic. @@ -689,5 +842,779 @@ func TestCreateRoleAndAssign(t *testing.T) { // assert.NoError(t, err) // assert.Equal(t, 1, len(response.Bundles)) // assert.Equal(t, response.Bundles[0].Name, "bundle1") -// os.RemoveAll(dataStore) -// } +// + +func TestListRolesAfterSavingBundle(t *testing.T) { + type expectedBundle struct { + displayName string + name string + } + + tests := []struct { + name string + bundles []*proto.Bundle + expectedBundles []expectedBundle + }{ + {"don't add bundle", + []*proto.Bundle{}, + []expectedBundle{ + {displayName: "Guest", name: "guest"}, + {displayName: "Admin", name: "admin"}, + {displayName: "User", name: "user"}, + }, + }, + {name: "one bundle", + bundles: []*proto.Bundle{{ + Type: proto.Bundle_TYPE_ROLE, + DisplayName: "test role - update", + Name: "TEST_ROLE", + Extension: "ocis-settings", + Settings: []*proto.Setting{ + { + Name: "settingName", + Resource: &proto.Resource{ + Id: settingsStub[0].Id, + Type: proto.Resource_TYPE_SETTING, + }, + Value: &proto.Setting_PermissionValue{ + PermissionValue: &proto.Permission{ + Operation: proto.Permission_OPERATION_UPDATE, + Constraint: proto.Permission_CONSTRAINT_OWN, + }, + }, + }, + }, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }}, + expectedBundles: []expectedBundle{ + {displayName: "test role - update", name: "TEST_ROLE"}, + {displayName: "Guest", name: "guest"}, + {displayName: "Admin", name: "admin"}, + {displayName: "User", name: "user"}, + }, + }, + {name: "two added bundles", + bundles: []*proto.Bundle{{ + Type: proto.Bundle_TYPE_ROLE, + DisplayName: "test role - update", + Name: "TEST_ROLE", + Extension: "ocis-settings", + Settings: []*proto.Setting{ + { + Name: "settingName", + Resource: &proto.Resource{ + Id: settingsStub[0].Id, + Type: proto.Resource_TYPE_SETTING, + }, + Value: &proto.Setting_PermissionValue{ + PermissionValue: &proto.Permission{ + Operation: proto.Permission_OPERATION_UPDATE, + Constraint: proto.Permission_CONSTRAINT_OWN, + }, + }, + }, + }, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + { + Type: proto.Bundle_TYPE_ROLE, + DisplayName: "an other role", + Name: "AnOtherROLE", + Extension: "ocis-settings", + Settings: []*proto.Setting{ + { + Name: "settingName", + Resource: &proto.Resource{ + Id: settingsStub[0].Id, + Type: proto.Resource_TYPE_SETTING, + }, + Value: &proto.Setting_PermissionValue{ + PermissionValue: &proto.Permission{ + Operation: proto.Permission_OPERATION_UPDATE, + Constraint: proto.Permission_CONSTRAINT_OWN, + }, + }, + }, + }, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }}, + expectedBundles: []expectedBundle{ + {displayName: "test role - update", name: "TEST_ROLE"}, + {displayName: "an other role", name: "AnOtherROLE"}, + {displayName: "Guest", name: "guest"}, + {displayName: "Admin", name: "admin"}, + {displayName: "User", name: "user"}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + teardown := setup() + defer teardown() + + for _, bundle := range tt.bundles { + _, err := bundleService.SaveBundle(context.Background(), &proto.SaveBundleRequest{ + Bundle: bundle, + }) + assert.NoError(t, err) + } + rolesRes, err := roleService.ListRoles(context.Background(), &proto.ListBundlesRequest{}) + assert.NoError(t, err) + + for _, bundle := range rolesRes.Bundles { + assert.Contains(t, tt.expectedBundles, expectedBundle{ + displayName: bundle.DisplayName, + name: bundle.Name, + }) + } + assert.Equal(t, len(tt.expectedBundles), len(rolesRes.Bundles)) + }) + } +} + +func TestListFilteredBundle(t *testing.T) { + type expectedBundle struct { + displayName string + name string + } + + type permission struct { + permission proto.Permission_Operation + roleUUID string + } + + type bundleForTest struct { + bundle *proto.Bundle + permission permission + } + + tests := []struct { + name string + bundles []bundleForTest + expectedBundles []expectedBundle + }{ + { + name: "multiple bundles, all have READ(WRITE) permission", + bundles: []bundleForTest{ + { + bundle: &proto.Bundle{ + Name: "test", + Id: "b1b8c9d0-fb3c-4e12-b868-5a8508218d2e", + DisplayName: "bundleDisplayName", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_READWRITE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + bundle: &proto.Bundle{ + Name: "one-more", + Id: "3b9f230a-fc9e-4605-89ee-a21e24728c64", + DisplayName: "an other bundle", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_READ, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + }, + expectedBundles: []expectedBundle{ + {displayName: "bundleDisplayName", name: "test"}, + {displayName: "an other bundle", name: "one-more"}, + }, + }, + { + name: "multiple bundles, only one with READ permission", + bundles: []bundleForTest{ + { + bundle: &proto.Bundle{ + Name: "Permission_OPERATION_WRITE", + Id: "12fe2b67-4a08-4f17-9cb6-924da943da0e", + DisplayName: "Permission_OPERATION_WRITE", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_WRITE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + bundle: &proto.Bundle{ + Name: "Permission_OPERATION_DELETE", + Id: "1a0b65b0-fdbf-4738-b41e-41d36a01376e", + DisplayName: "Permission_OPERATION_DELETE", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_DELETE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + bundle: &proto.Bundle{ + Name: "Permission_OPERATION_UPDATE", + Id: "511fe78e-89c9-4237-a01e-6af5457a135e", + DisplayName: "Permission_OPERATION_UPDATE", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_UPDATE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + bundle: &proto.Bundle{ + Name: "Permission_OPERATION_CREATE", + Id: "aa42fb12-57aa-40c0-b458-3a91f398deba", + DisplayName: "Permission_OPERATION_CREATE", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_CREATE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + bundle: &proto.Bundle{ + Name: "Permission_OPERATION_UNKNOWN", + Id: "eabb2a18-09e2-4b06-aa62-987e8dc5e908", + DisplayName: "Permission_OPERATION_UNKNOWN", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_UNKNOWN, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + bundle: &proto.Bundle{ + Name: "Permission_OPERATION_READ", + Id: "3b9f230a-fc9e-4605-89ee-a21e24728c64", + DisplayName: "Permission_OPERATION_READ", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_READ, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + }, + expectedBundles: []expectedBundle{ + {displayName: "Permission_OPERATION_READ", name: "Permission_OPERATION_READ"}, + }, + }, + { + name: "multiple bundles, all have READ permission, but only one matching role", + bundles: []bundleForTest{ + { + bundle: &proto.Bundle{ + Name: "matching-role", + Id: "b1b8c9d0-fb3c-4e12-b868-5a8508218d2e", + DisplayName: "bundleDisplayName", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_READWRITE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + bundle: &proto.Bundle{ + Name: "NOT-matching-role", + Id: "3b9f230a-fc9e-4605-89ee-a21e24728c64", + DisplayName: "an other bundle", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_READ, + roleUUID: svc.BundleUUIDRoleGuest, + }, + }, + { + bundle: &proto.Bundle{ + Name: "NOT-matching-role2", + Id: "714a5917-627c-40ac-8dc7-5fdac013e4b7", + DisplayName: "an other bundle", + Extension: "testExtension", + Type: proto.Bundle_TYPE_DEFAULT, + Settings: complexSettingsStub, + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + }, + permission: permission{ + permission: proto.Permission_OPERATION_READ, + roleUUID: svc.BundleUUIDRoleUser, + }, + }, + }, + expectedBundles: []expectedBundle{ + {displayName: "bundleDisplayName", name: "matching-role"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + teardown := setup() + defer teardown() + + for _, testBundle := range tt.bundles { + _, err := bundleService.SaveBundle(context.Background(), &proto.SaveBundleRequest{ + Bundle: testBundle.bundle, + }) + assert.NoError(t, err) + + permissionRequest := proto.AddSettingToBundleRequest{ + BundleId: testBundle.permission.roleUUID, + Setting: &proto.Setting{ + Name: "permission", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_BUNDLE, + Id: testBundle.bundle.Id, + }, + Value: &proto.Setting_PermissionValue{ + PermissionValue: &proto.Permission{ + Operation: testBundle.permission.permission, + Constraint: proto.Permission_CONSTRAINT_OWN, + }, + }, + }, + } + addPermissionResponse, err := bundleService.AddSettingToBundle(context.Background(), &permissionRequest) + assert.NoError(t, err) + if err == nil { + assert.NotEmpty(t, addPermissionResponse.Setting) + } + } + _, err := roleService.AssignRoleToUser( + context.Background(), + &proto.AssignRoleToUserRequest{AccountUuid: testAccountID, RoleId: svc.BundleUUIDRoleAdmin}, + ) + assert.NoError(t, err) + + ctx := metadata.Set(context.Background(), middleware.AccountID, testAccountID) + listRes, err := bundleService.ListBundles(ctx, &proto.ListBundlesRequest{}) + assert.NoError(t, err) + + for _, bundle := range listRes.Bundles { + assert.Contains(t, tt.expectedBundles, expectedBundle{ + displayName: bundle.DisplayName, + name: bundle.Name, + }) + } + assert.Equal(t, len(tt.expectedBundles), len(listRes.Bundles)) + }) + } +} + +func TestListGetBundleSettingMixedPermission(t *testing.T) { + type expectedSetting struct { + displayName string + name string + } + + type permission struct { + permission proto.Permission_Operation + roleUUID string + } + + type settingsForTest struct { + setting *proto.Setting + permission permission + } + + tests := []struct { + name string + settings []settingsForTest + expectedSettings []expectedSetting + }{ + { + name: "all settings have R/RW permissions", + settings: []settingsForTest{ + { + setting: &proto.Setting{ + Id: "b86fdb0a-801f-4749-ab84-5c99e90dbd6d", + DisplayName: "RW setting", + Name: "RW-setting", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "RW setting", + }, + permission: permission{ + permission: proto.Permission_OPERATION_READWRITE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + setting: &proto.Setting{ + Id: "cb1bbe58-27e7-461b-91b1-a9c85c488789", + DisplayName: "RO setting", + Name: "RO-setting", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "RO setting", + }, + permission: permission{ + permission: proto.Permission_OPERATION_READWRITE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + }, + expectedSettings: []expectedSetting{ + {displayName: "RW setting", name: "RW-setting"}, + {displayName: "RO setting", name: "RO-setting"}, + }, + }, + { + name: "all settings have R/RW permissions but only one the matching user", + settings: []settingsForTest{ + { + setting: &proto.Setting{ + Id: "b86fdb0a-801f-4749-ab84-5c99e90dbd6d", + DisplayName: "matching user", + Name: "matching-user", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "matching user", + }, + permission: permission{ + permission: proto.Permission_OPERATION_READWRITE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + setting: &proto.Setting{ + Id: "cb1bbe58-27e7-461b-91b1-a9c85c488789", + DisplayName: "NOT matching user", + Name: "NOT-matching-user", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "NOT matching user", + }, + permission: permission{ + permission: proto.Permission_OPERATION_READWRITE, + roleUUID: svc.BundleUUIDRoleGuest, + }, + }, + }, + expectedSettings: []expectedSetting{ + {displayName: "matching user", name: "matching-user"}, + }, + }, + { + name: "only one settings has READ permissions", + settings: []settingsForTest{ + { + setting: &proto.Setting{ + Id: "b86fdb0a-801f-4749-ab84-5c99e90dbd6d", + DisplayName: "WRITE setting", + Name: "WRITE-setting", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "WRITE setting", + }, + permission: permission{ + permission: proto.Permission_OPERATION_WRITE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + setting: &proto.Setting{ + Id: "6163c6bf-79f2-43f7-b0ba-1493534bfc10", + DisplayName: "UNKNOWN setting", + Name: "UNKNOWN-setting", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "UNKNOWN setting", + }, + permission: permission{ + permission: proto.Permission_OPERATION_UNKNOWN, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + setting: &proto.Setting{ + Id: "79eda727-9fa1-459f-aaff-f73ed5693419", + DisplayName: "CREATE setting", + Name: "CREATE-setting", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "CREATE setting", + }, + permission: permission{ + permission: proto.Permission_OPERATION_CREATE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + setting: &proto.Setting{ + Id: "2be7ca51-89fb-4968-b9d2-0ac43197adff", + DisplayName: "UPDATE setting", + Name: "UPDATE-setting", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "UPDATE setting", + }, + permission: permission{ + permission: proto.Permission_OPERATION_UPDATE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + setting: &proto.Setting{ + Id: "f1a0005e-e570-4bd8-a18c-b4afaaa8d7d9", + DisplayName: "DELETE setting", + Name: "DELETE-setting", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "DELETE setting", + }, + permission: permission{ + permission: proto.Permission_OPERATION_DELETE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + { + setting: &proto.Setting{ + Id: "cb1bbe58-27e7-461b-91b1-a9c85c488789", + DisplayName: "RO setting", + Name: "RO-setting", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + Value: &proto.Setting_IntValue{ + IntValue: &proto.Int{ + Default: 42, + }, + }, + Description: "RO setting", + }, + permission: permission{ + permission: proto.Permission_OPERATION_READWRITE, + roleUUID: svc.BundleUUIDRoleAdmin, + }, + }, + }, + expectedSettings: []expectedSetting{ + {displayName: "RO setting", name: "RO-setting"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + teardown := setup() + defer teardown() + + // create bundle with the defined settings + bundle := &bundleStub + var settings []*proto.Setting + + for _, testSetting := range tt.settings { + settings = append(settings, testSetting.setting) + } + bundle.Settings = settings + + _, err := bundleService.SaveBundle(context.Background(), &proto.SaveBundleRequest{ + Bundle: bundle, + }) + assert.NoError(t, err) + + // set permissions for each setting + for _, testSetting := range tt.settings { + permissionRequest := proto.AddSettingToBundleRequest{ + BundleId: testSetting.permission.roleUUID, + Setting: &proto.Setting{ + Name: "permission", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_SETTING, + Id: testSetting.setting.Id, + }, + Value: &proto.Setting_PermissionValue{ + PermissionValue: &proto.Permission{ + Operation: testSetting.permission.permission, + Constraint: proto.Permission_CONSTRAINT_OWN, + }, + }, + }, + } + addPermissionResponse, err := bundleService.AddSettingToBundle(context.Background(), &permissionRequest) + assert.NoError(t, err) + if err == nil { + assert.NotEmpty(t, addPermissionResponse.Setting) + } + } + _, err = roleService.AssignRoleToUser( + context.Background(), + &proto.AssignRoleToUserRequest{AccountUuid: testAccountID, RoleId: svc.BundleUUIDRoleAdmin}, + ) + assert.NoError(t, err) + + ctx := metadata.Set(context.Background(), middleware.AccountID, testAccountID) + listRes, err := bundleService.ListBundles(ctx, &proto.ListBundlesRequest{}) + assert.NoError(t, err) + + for _, setting := range listRes.Bundles[0].Settings { + assert.Contains(t, tt.expectedSettings, expectedSetting{ + displayName: setting.DisplayName, + name: setting.Name, + }) + } + assert.Equal(t, len(tt.expectedSettings), len(listRes.Bundles[0].Settings)) + + getRes, err := bundleService.GetBundle(ctx, &proto.GetBundleRequest{BundleId: bundle.Id}) + assert.NoError(t, err) + + for _, setting := range getRes.Bundle.Settings { + assert.Contains(t, tt.expectedSettings, expectedSetting{ + displayName: setting.DisplayName, + name: setting.Name, + }) + } + assert.Equal(t, len(tt.expectedSettings), len(getRes.Bundle.Settings)) + }) + } +} + +func setFullReadWriteOnBundle(t *testing.T, accountID, bundleID string) { + permissionRequest := proto.AddSettingToBundleRequest{ + BundleId: svc.BundleUUIDRoleAdmin, + Setting: &proto.Setting{ + Name: "test-bundle-permission-readwrite", + Resource: &proto.Resource{ + Type: proto.Resource_TYPE_BUNDLE, + Id: bundleID, + }, + Value: &proto.Setting_PermissionValue{ + PermissionValue: &proto.Permission{ + Operation: proto.Permission_OPERATION_READWRITE, + Constraint: proto.Permission_CONSTRAINT_ALL, + }, + }, + }, + } + addPermissionResponse, err := bundleService.AddSettingToBundle(context.Background(), &permissionRequest) + assert.NoError(t, err) + if err == nil { + assert.NotEmpty(t, addPermissionResponse.Setting) + } + + _, err = roleService.AssignRoleToUser( + context.Background(), + &proto.AssignRoleToUserRequest{AccountUuid: accountID, RoleId: svc.BundleUUIDRoleAdmin}, + ) + assert.NoError(t, err) +} diff --git a/pkg/proto/v0/settings.pb.web.go b/pkg/proto/v0/settings.pb.web.go index bb18c6f21c..4c4cfa8439 100644 --- a/pkg/proto/v0/settings.pb.web.go +++ b/pkg/proto/v0/settings.pb.web.go @@ -389,6 +389,48 @@ func RegisterRoleServiceWeb(r chi.Router, i RoleServiceHandler, middlewares ...f r.MethodFunc("POST", "/api/v0/settings/assignments-remove", handler.RemoveRoleFromUser) } +type webPermissionServiceHandler struct { + r chi.Router + h PermissionServiceHandler +} + +func (h *webPermissionServiceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + h.r.ServeHTTP(w, r) +} + +func (h *webPermissionServiceHandler) ListPermissionsByResource(w http.ResponseWriter, r *http.Request) { + + req := &ListPermissionsByResourceRequest{} + + resp := &ListPermissionsByResourceResponse{} + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusPreconditionFailed) + return + } + + if err := h.h.ListPermissionsByResource( + r.Context(), + req, + resp, + ); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + render.Status(r, http.StatusCreated) + render.JSON(w, r, resp) +} + +func RegisterPermissionServiceWeb(r chi.Router, i PermissionServiceHandler, middlewares ...func(http.Handler) http.Handler) { + handler := &webPermissionServiceHandler{ + r: r, + h: i, + } + + r.MethodFunc("POST", "/api/v0/settings/permissions-list-by-resource", handler.ListPermissionsByResource) +} + // SaveBundleRequestJSONMarshaler describes the default jsonpb.Marshaler used by all // instances of SaveBundleRequest. This struct is safe to replace or modify but // should not be done so concurrently. @@ -1253,6 +1295,78 @@ func (m *UserRoleAssignment) UnmarshalJSON(b []byte) error { var _ json.Unmarshaler = (*UserRoleAssignment)(nil) +// ListPermissionsByResourceRequestJSONMarshaler describes the default jsonpb.Marshaler used by all +// instances of ListPermissionsByResourceRequest. This struct is safe to replace or modify but +// should not be done so concurrently. +var ListPermissionsByResourceRequestJSONMarshaler = new(jsonpb.Marshaler) + +// MarshalJSON satisfies the encoding/json Marshaler interface. This method +// uses the more correct jsonpb package to correctly marshal the message. +func (m *ListPermissionsByResourceRequest) MarshalJSON() ([]byte, error) { + if m == nil { + return json.Marshal(nil) + } + + buf := &bytes.Buffer{} + + if err := ListPermissionsByResourceRequestJSONMarshaler.Marshal(buf, m); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +var _ json.Marshaler = (*ListPermissionsByResourceRequest)(nil) + +// ListPermissionsByResourceRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all +// instances of ListPermissionsByResourceRequest. This struct is safe to replace or modify but +// should not be done so concurrently. +var ListPermissionsByResourceRequestJSONUnmarshaler = new(jsonpb.Unmarshaler) + +// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method +// uses the more correct jsonpb package to correctly unmarshal the message. +func (m *ListPermissionsByResourceRequest) UnmarshalJSON(b []byte) error { + return ListPermissionsByResourceRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m) +} + +var _ json.Unmarshaler = (*ListPermissionsByResourceRequest)(nil) + +// ListPermissionsByResourceResponseJSONMarshaler describes the default jsonpb.Marshaler used by all +// instances of ListPermissionsByResourceResponse. This struct is safe to replace or modify but +// should not be done so concurrently. +var ListPermissionsByResourceResponseJSONMarshaler = new(jsonpb.Marshaler) + +// MarshalJSON satisfies the encoding/json Marshaler interface. This method +// uses the more correct jsonpb package to correctly marshal the message. +func (m *ListPermissionsByResourceResponse) MarshalJSON() ([]byte, error) { + if m == nil { + return json.Marshal(nil) + } + + buf := &bytes.Buffer{} + + if err := ListPermissionsByResourceResponseJSONMarshaler.Marshal(buf, m); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +var _ json.Marshaler = (*ListPermissionsByResourceResponse)(nil) + +// ListPermissionsByResourceResponseJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all +// instances of ListPermissionsByResourceResponse. This struct is safe to replace or modify but +// should not be done so concurrently. +var ListPermissionsByResourceResponseJSONUnmarshaler = new(jsonpb.Unmarshaler) + +// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method +// uses the more correct jsonpb package to correctly unmarshal the message. +func (m *ListPermissionsByResourceResponse) UnmarshalJSON(b []byte) error { + return ListPermissionsByResourceResponseJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m) +} + +var _ json.Unmarshaler = (*ListPermissionsByResourceResponse)(nil) + // ResourceJSONMarshaler describes the default jsonpb.Marshaler used by all // instances of Resource. This struct is safe to replace or modify but // should not be done so concurrently. diff --git a/pkg/proto/v0/settings.proto b/pkg/proto/v0/settings.proto index 854a873de1..4f0421298c 100644 --- a/pkg/proto/v0/settings.proto +++ b/pkg/proto/v0/settings.proto @@ -118,6 +118,15 @@ service RoleService { } } +service PermissionService { + rpc ListPermissionsByResource(ListPermissionsByResourceRequest) returns (ListPermissionsByResourceResponse) { + option (google.api.http) = { + post: "/api/v0/settings/permissions-list-by-resource", + body: "*" + }; + } +} + // --- // requests and responses for settings bundles // --- @@ -138,7 +147,6 @@ message GetBundleResponse { } message ListBundlesRequest { - string account_uuid = 1; } message ListBundlesResponse { @@ -238,6 +246,19 @@ message UserRoleAssignment { string role_id = 3; } +// -- +// requests and responses for permissions +// --- + +message ListPermissionsByResourceRequest { + Resource resource = 1; + repeated string role_ids = 2; +} + +message ListPermissionsByResourceResponse { + repeated Permission permissions = 1; +} + // --- // resource payloads // --- @@ -334,6 +355,8 @@ message Permission { OPERATION_READ = 2; OPERATION_UPDATE = 3; OPERATION_DELETE = 4; + OPERATION_WRITE = 5;// WRITE is a combination of CREATE and UPDATE + OPERATION_READWRITE = 6;// READWRITE is a combination of READ and WRITE } Operation operation = 1; enum Constraint { diff --git a/pkg/proto/v0/settings.swagger.json b/pkg/proto/v0/settings.swagger.json index 3c1eb7cb2f..08495f258a 100644 --- a/pkg/proto/v0/settings.swagger.json +++ b/pkg/proto/v0/settings.swagger.json @@ -280,6 +280,38 @@ ] } }, + "/api/v0/settings/permissions-list-by-resource": { + "post": { + "operationId": "PermissionService_ListPermissionsByResource", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/protoListPermissionsByResourceResponse" + } + }, + "default": { + "description": "An unexpected error response", + "schema": { + "$ref": "#/definitions/runtimeError" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/protoListPermissionsByResourceRequest" + } + } + ], + "tags": [ + "PermissionService" + ] + } + }, "/api/v0/settings/roles-list": { "post": { "operationId": "RoleService_ListRoles", @@ -623,12 +655,7 @@ } }, "protoListBundlesRequest": { - "type": "object", - "properties": { - "account_uuid": { - "type": "string" - } - } + "type": "object" }, "protoListBundlesResponse": { "type": "object", @@ -668,6 +695,31 @@ } } }, + "protoListPermissionsByResourceRequest": { + "type": "object", + "properties": { + "resource": { + "$ref": "#/definitions/protoResource" + }, + "role_ids": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "protoListPermissionsByResourceResponse": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/protoPermission" + } + } + } + }, "protoListRoleAssignmentsRequest": { "type": "object", "properties": { @@ -749,7 +801,9 @@ "OPERATION_CREATE", "OPERATION_READ", "OPERATION_UPDATE", - "OPERATION_DELETE" + "OPERATION_DELETE", + "OPERATION_WRITE", + "OPERATION_READWRITE" ], "default": "OPERATION_UNKNOWN" }, diff --git a/pkg/service/v0/permissions.go b/pkg/service/v0/permissions.go new file mode 100644 index 0000000000..74637677e8 --- /dev/null +++ b/pkg/service/v0/permissions.go @@ -0,0 +1,57 @@ +package svc + +import "github.com/owncloud/ocis-settings/pkg/proto/v0" + +func (g Service) hasPermission( + roleIDs []string, + resource *proto.Resource, + operations []proto.Permission_Operation, + constraint proto.Permission_Constraint, +) bool { + permissions, err := g.manager.ListPermissionsByResource(resource, roleIDs) + if err != nil { + g.logger.Debug().Err(err). + Str("resource-type", resource.Type.String()). + Str("resource-id", resource.Id). + Msg("permissions could not be loaded for resource") + return false + } + permissions = getFilteredPermissionsByOperations(permissions, operations) + return isConstraintFulfilled(permissions, constraint) +} + +// filterPermissionsByOperations returns the subset of the given permissions, where at least one of the given operations is fulfilled. +func getFilteredPermissionsByOperations(permissions []*proto.Permission, operations []proto.Permission_Operation) []*proto.Permission { + var filteredPermissions []*proto.Permission + for _, permission := range permissions { + if isAnyOperationFulfilled(permission, operations) { + filteredPermissions = append(filteredPermissions, permission) + } + } + return filteredPermissions +} + +// isAnyOperationFulfilled checks if the permissions is about any of the operations +func isAnyOperationFulfilled(permission *proto.Permission, operations []proto.Permission_Operation) bool { + for _, operation := range operations { + if operation == permission.Operation { + return true + } + } + return false +} + +// isConstraintFulfilled checks if one of the permissions has the same or a parent of the constraint. +// this is only a comparison on ENUM level. More sophisticated checks cannot happen here... +func isConstraintFulfilled(permissions []*proto.Permission, constraint proto.Permission_Constraint) bool { + for _, permission := range permissions { + // comparing enum by order is not a feasible solution, because `SHARED` is not a superset of `OWN`. + if permission.Constraint == proto.Permission_CONSTRAINT_ALL { + return true + } + if permission.Constraint != proto.Permission_CONSTRAINT_UNKNOWN && permission.Constraint == constraint { + return true + } + } + return false +} diff --git a/pkg/service/v0/service.go b/pkg/service/v0/service.go index c46138a73e..26dc39db45 100644 --- a/pkg/service/v0/service.go +++ b/pkg/service/v0/service.go @@ -2,9 +2,11 @@ package svc import ( "context" + "fmt" "github.com/golang/protobuf/ptypes/empty" merrors "github.com/micro/go-micro/v2/errors" + "github.com/micro/go-micro/v2/metadata" "github.com/owncloud/ocis-pkg/v2/log" "github.com/owncloud/ocis-pkg/v2/middleware" "github.com/owncloud/ocis-settings/pkg/config" @@ -27,23 +29,28 @@ func NewService(cfg *config.Config, logger log.Logger) Service { logger: logger, manager: store.New(cfg), } - // FIXME: we're writing default roles per service start (i.e. twice at the moment, for http and grpc server). + service.RegisterDefaultRoles() + return service +} + +// RegisterDefaultRoles composes default roles and saves them. Skipped if the roles already exist. +func (g Service) RegisterDefaultRoles() { + // FIXME: we're writing default roles per service start (i.e. twice at the moment, for http and grpc server). has to happen only once. for _, role := range generateBundlesDefaultRoles() { bundleID := role.Extension + "." + role.Id // check if the role already exists - bundle, _ := service.manager.ReadBundle(role.Id) + bundle, _ := g.manager.ReadBundle(role.Id) if bundle != nil { - logger.Debug().Msgf("Settings bundle %v already exists. Skipping.", bundleID) + g.logger.Debug().Str("bundleID", bundleID).Msg("bundle already exists. skipping.") continue } // create the role - _, err := service.manager.WriteBundle(role) + _, err := g.manager.WriteBundle(role) if err != nil { - logger.Error().Err(err).Msgf("Failed to register settings bundle %v", bundleID) + g.logger.Error().Err(err).Str("bundleID", bundleID).Msg("failed to register bundle") } - logger.Debug().Msgf("Successfully registered settings bundle %v", bundleID) + g.logger.Debug().Str("bundleID", bundleID).Msg("successfully registered bundle") } - return service } // TODO: check permissions on every request @@ -64,21 +71,28 @@ func (g Service) SaveBundle(c context.Context, req *proto.SaveBundleRequest, res // GetBundle implements the BundleServiceHandler interface func (g Service) GetBundle(c context.Context, req *proto.GetBundleRequest, res *proto.GetBundleResponse) error { + accountUUID := getValidatedAccountUUID(c, "me") if validationError := validateGetBundle(req); validationError != nil { return merrors.BadRequest("ocis-settings", "%s", validationError) } - r, err := g.manager.ReadBundle(req.BundleId) + bundle, err := g.manager.ReadBundle(req.BundleId) if err != nil { return merrors.NotFound("ocis-settings", "%s", err) } - res.Bundle = r + roleIDs := g.getRoleIDs(c, accountUUID) + filteredBundle := g.getFilteredBundle(roleIDs, bundle) + if len(filteredBundle.Settings) == 0 { + err = fmt.Errorf("could not read bundle: %s", req.BundleId) + return merrors.NotFound("ocis-settings", "%s", err) + } + res.Bundle = filteredBundle return nil } // ListBundles implements the BundleServiceHandler interface func (g Service) ListBundles(c context.Context, req *proto.ListBundlesRequest, res *proto.ListBundlesResponse) error { // fetch all bundles - req.AccountUuid = getValidatedAccountUUID(c, req.AccountUuid) + accountUUID := getValidatedAccountUUID(c, "me") if validationError := validateListBundles(req); validationError != nil { return merrors.BadRequest("ocis-settings", "%s", validationError) } @@ -86,10 +100,56 @@ func (g Service) ListBundles(c context.Context, req *proto.ListBundlesRequest, r if err != nil { return merrors.NotFound("ocis-settings", "%s", err) } - res.Bundles = bundles + roleIDs := g.getRoleIDs(c, accountUUID) + + // filter settings in bundles that are allowed according to roles + var filteredBundles []*proto.Bundle + for _, bundle := range bundles { + filteredBundle := g.getFilteredBundle(roleIDs, bundle) + if len(filteredBundle.Settings) > 0 { + filteredBundles = append(filteredBundles, filteredBundle) + } + } + + res.Bundles = filteredBundles return nil } +func (g Service) getFilteredBundle(roleIDs []string, bundle *proto.Bundle) *proto.Bundle { + // check if full bundle is whitelisted + bundleResource := &proto.Resource{ + Type: proto.Resource_TYPE_BUNDLE, + Id: bundle.Id, + } + if g.hasPermission( + roleIDs, + bundleResource, + []proto.Permission_Operation{proto.Permission_OPERATION_READ, proto.Permission_OPERATION_READWRITE}, + proto.Permission_CONSTRAINT_OWN, + ) { + return bundle + } + + // filter settings based on permissions + var filteredSettings []*proto.Setting + for _, setting := range bundle.Settings { + settingResource := &proto.Resource{ + Type: proto.Resource_TYPE_SETTING, + Id: setting.Id, + } + if g.hasPermission( + roleIDs, + settingResource, + []proto.Permission_Operation{proto.Permission_OPERATION_READ, proto.Permission_OPERATION_READWRITE}, + proto.Permission_CONSTRAINT_OWN, + ) { + filteredSettings = append(filteredSettings, setting) + } + } + bundle.Settings = filteredSettings + return bundle +} + // AddSettingToBundle implements the BundleServiceHandler interface func (g Service) AddSettingToBundle(c context.Context, req *proto.AddSettingToBundleRequest, res *proto.AddSettingToBundleResponse) error { cleanUpResource(c, req.Setting.Resource) @@ -194,7 +254,7 @@ func (g Service) ListValues(c context.Context, req *proto.ListValuesRequest, res // ListRoles implements the RoleServiceHandler interface func (g Service) ListRoles(c context.Context, req *proto.ListBundlesRequest, res *proto.ListBundlesResponse) error { - req.AccountUuid = getValidatedAccountUUID(c, req.AccountUuid) + //accountUUID := getValidatedAccountUUID(c, "me") if validationError := validateListRoles(req); validationError != nil { return merrors.BadRequest("ocis-settings", "%s", validationError) } @@ -202,6 +262,7 @@ func (g Service) ListRoles(c context.Context, req *proto.ListBundlesRequest, res if err != nil { return merrors.NotFound("ocis-settings", "%s", err) } + // TODO: only allow to list roles when user has account management permissions res.Bundles = r return nil } @@ -245,6 +306,19 @@ func (g Service) RemoveRoleFromUser(c context.Context, req *proto.RemoveRoleFrom return nil } +// ListPermissionsByResource implements the PermissionServiceHandler interface +func (g Service) ListPermissionsByResource(c context.Context, req *proto.ListPermissionsByResourceRequest, res *proto.ListPermissionsByResourceResponse) error { + if validationError := validateListPermissionsByResource(req); validationError != nil { + return merrors.BadRequest("ocis-settings", "%s", validationError) + } + permissions, err := g.manager.ListPermissionsByResource(req.Resource, req.RoleIds) + if err != nil { + return merrors.BadRequest("ocis-settings", "%s", err) + } + res.Permissions = permissions + return nil +} + // cleanUpResource makes sure that the account uuid of the authenticated user is injected if needed. func cleanUpResource(c context.Context, resource *proto.Resource) { if resource != nil && resource.Type == proto.Resource_TYPE_USER { @@ -256,13 +330,35 @@ func cleanUpResource(c context.Context, resource *proto.Resource) { // the result of this function will always be a valid lower-case UUID or an empty string. func getValidatedAccountUUID(c context.Context, accountUUID string) string { if accountUUID == "me" { - if ownAccountUUID, ok := c.Value(middleware.UUIDKey).(string); ok { + if ownAccountUUID, ok := metadata.Get(c, middleware.AccountID); ok { accountUUID = ownAccountUUID } } + if accountUUID == "me" { + // no matter what happens above, an accountUUID of `me` must not be passed on. Clear it instead. + accountUUID = "" + } return accountUUID } +// getRoleIDs loads the role assignments for the given accountUUID +// TODO: this should work on the context in the future, as roles are supposed to be sent within the context. +func (g Service) getRoleIDs(c context.Context, accountUUID string) []string { + // TODO: replace this with role ids from the context + // WIP PR: https://github.com/owncloud/ocis-proxy/pull/70 + rolesResponse := &proto.ListRoleAssignmentsResponse{} + err := g.ListRoleAssignments(c, &proto.ListRoleAssignmentsRequest{AccountUuid: accountUUID}, rolesResponse) + if err != nil { + g.logger.Err(err).Str("accountUUID", accountUUID).Msg("failed to list role assignments") + return []string{} + } + roleIDs := make([]string, 0) + for _, assignment := range rolesResponse.Assignments { + roleIDs = append(roleIDs, assignment.RoleId) + } + return roleIDs +} + func (g Service) getValueWithIdentifier(value *proto.Value) (*proto.ValueWithIdentifier, error) { bundle, err := g.manager.ReadBundle(value.BundleId) if err != nil { diff --git a/pkg/service/v0/service_test.go b/pkg/service/v0/service_test.go index a1c5ca2dbb..9ddc2e6494 100644 --- a/pkg/service/v0/service_test.go +++ b/pkg/service/v0/service_test.go @@ -4,13 +4,14 @@ import ( "context" "testing" + "github.com/micro/go-micro/v2/metadata" "github.com/owncloud/ocis-pkg/v2/middleware" "github.com/stretchr/testify/assert" ) var ( - ctxWithUUID = context.WithValue(context.Background(), middleware.UUIDKey, "61445573-4dbe-4d56-88dc-88ab47aceba7") - ctxWithEmptyUUID = context.WithValue(context.Background(), middleware.UUIDKey, "") + ctxWithUUID = metadata.Set(context.Background(), middleware.AccountID, "61445573-4dbe-4d56-88dc-88ab47aceba7") + ctxWithEmptyUUID = metadata.Set(context.Background(), middleware.AccountID, "") emptyCtx = context.Background() scenarios = []struct { @@ -23,11 +24,17 @@ var ( name: "context with UUID; identifier = 'me'", ctx: ctxWithUUID, accountUUID: "me", - expect: ctxWithUUID.Value(middleware.UUIDKey).(string), + expect: "61445573-4dbe-4d56-88dc-88ab47aceba7", + }, + { + name: "context with empty UUID; identifier = 'me'", + ctx: ctxWithEmptyUUID, + accountUUID: "me", + expect: "", }, { name: "context without UUID; identifier = 'me'", - ctx: ctxWithEmptyUUID, + ctx: emptyCtx, accountUUID: "me", expect: "", }, diff --git a/pkg/service/v0/validator.go b/pkg/service/v0/validator.go index 919cf17a8c..cd89725b7a 100644 --- a/pkg/service/v0/validator.go +++ b/pkg/service/v0/validator.go @@ -46,11 +46,11 @@ func validateSaveBundle(req *proto.SaveBundleRequest) error { } func validateGetBundle(req *proto.GetBundleRequest) error { - return validation.Validate(&req.BundleId, requireAccountID...) + return validation.Validate(&req.BundleId, is.UUID) } func validateListBundles(req *proto.ListBundlesRequest) error { - return validation.Validate(&req.AccountUuid, requireAccountID...) + return nil } func validateAddSettingToBundle(req *proto.AddSettingToBundleRequest) error { @@ -100,7 +100,7 @@ func validateListValues(req *proto.ListValuesRequest) error { } func validateListRoles(req *proto.ListBundlesRequest) error { - return validation.Validate(&req.AccountUuid, requireAccountID...) + return nil } func validateListRoleAssignments(req *proto.ListRoleAssignmentsRequest) error { @@ -122,6 +122,16 @@ func validateRemoveRoleFromUser(req *proto.RemoveRoleFromUserRequest) error { ) } +func validateListPermissionsByResource(req *proto.ListPermissionsByResourceRequest) error { + if err := validateResource(req.Resource); err != nil { + return err + } + return validation.ValidateStruct( + req, + validation.Field(&req.RoleIds, validation.Each(requireAlphanumeric...)), + ) +} + // validateResource is an internal helper for validating the content of a resource. func validateResource(resource *proto.Resource) error { if err := validation.Validate(&resource, validation.Required); err != nil { diff --git a/pkg/settings/settings.go b/pkg/settings/settings.go index ca8ade6fb2..d8ca22cfc7 100644 --- a/pkg/settings/settings.go +++ b/pkg/settings/settings.go @@ -18,6 +18,7 @@ type Manager interface { BundleManager ValueManager RoleAssignmentManager + PermissionManager } // BundleManager is a bundle service interface for abstraction of storage implementations @@ -44,3 +45,8 @@ type RoleAssignmentManager interface { WriteRoleAssignment(accountUUID, roleID string) (*proto.UserRoleAssignment, error) RemoveRoleAssignment(assignmentID string) error } + +// PermissionManager is a permissions service interface for abstraction of storage implementations +type PermissionManager interface { + ListPermissionsByResource(resource *proto.Resource, roleIDs []string) ([]*proto.Permission, error) +} diff --git a/pkg/store/filesystem/assignments.go b/pkg/store/filesystem/assignments.go index eb475ef6a8..19f7a7e6bb 100644 --- a/pkg/store/filesystem/assignments.go +++ b/pkg/store/filesystem/assignments.go @@ -16,7 +16,6 @@ func (s Store) ListRoleAssignments(accountUUID string) ([]*proto.UserRoleAssignm assignmentsFolder := s.buildFolderPathForRoleAssignments(false) assignmentFiles, err := ioutil.ReadDir(assignmentsFolder) if err != nil { - s.Logger.Error().Err(err).Str("assignmentFiles", assignmentsFolder).Msg("error reading assignment file") return records, nil } @@ -35,7 +34,7 @@ func (s Store) ListRoleAssignments(accountUUID string) ([]*proto.UserRoleAssignm // WriteRoleAssignment appends the given role assignment to the existing assignments of the respective account. func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*proto.UserRoleAssignment, error) { - // as per https://jira.owncloud.com/browse/OCIS-117 "Each user can have exactly one role" + // as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role" list, err := s.ListRoleAssignments(accountUUID) if err != nil { return nil, err diff --git a/pkg/store/filesystem/bundles.go b/pkg/store/filesystem/bundles.go index c6a6f6f28d..3f2b4088bc 100644 --- a/pkg/store/filesystem/bundles.go +++ b/pkg/store/filesystem/bundles.go @@ -73,7 +73,7 @@ func (s Store) ReadSetting(settingID string) (*proto.Setting, error) { } } } - return nil, fmt.Errorf(settingID, fmt.Sprintf("could not read setting: %v", settingID)) + return nil, fmt.Errorf("could not read setting: %v", settingID) } // WriteBundle writes the given record into a file within the dataPath. diff --git a/pkg/store/filesystem/permissions.go b/pkg/store/filesystem/permissions.go new file mode 100644 index 0000000000..8057130cf3 --- /dev/null +++ b/pkg/store/filesystem/permissions.go @@ -0,0 +1,34 @@ +package store + +import ( + "github.com/owncloud/ocis-settings/pkg/proto/v0" + "github.com/owncloud/ocis-settings/pkg/util" +) + +// ListPermissionsByResource collects all permissions from the provided roleIDs that match the requested resource +func (s Store) ListPermissionsByResource(resource *proto.Resource, roleIDs []string) ([]*proto.Permission, error) { + records := make([]*proto.Permission, 0) + for _, roleID := range roleIDs { + role, err := s.ReadBundle(roleID) + if err != nil { + s.Logger.Debug().Str("roleID", roleID).Msg("role not found, skipping") + continue + } + records = append(records, extractPermissionsByResource(resource, role)...) + } + return records, nil +} + +// extractPermissionsByResource collects all permissions from the provided role that match the requested resource +func extractPermissionsByResource(resource *proto.Resource, role *proto.Bundle) []*proto.Permission { + permissions := make([]*proto.Permission, 0) + for _, setting := range role.Settings { + if _, ok := setting.Value.(*proto.Setting_PermissionValue); ok { + value := setting.Value.(*proto.Setting_PermissionValue).PermissionValue + if util.IsResourceMatched(setting.Resource, resource) { + permissions = append(permissions, value) + } + } + } + return permissions +} diff --git a/pkg/util/resource_helper.go b/pkg/util/resource_helper.go new file mode 100644 index 0000000000..d444183eef --- /dev/null +++ b/pkg/util/resource_helper.go @@ -0,0 +1,16 @@ +package util + +import "github.com/owncloud/ocis-settings/pkg/proto/v0" + +const ( + // ResourceIDAll declares on a resource that it matches any id + ResourceIDAll = "all" +) + +// IsResourceMatched checks if the `example` resource is an exact match or a subset of `definition` +func IsResourceMatched(definition, example *proto.Resource) bool { + if definition.Type != example.Type { + return false + } + return definition.Id == ResourceIDAll || definition.Id == example.Id +} diff --git a/pkg/util/resource_helper_test.go b/pkg/util/resource_helper_test.go new file mode 100644 index 0000000000..93423c39de --- /dev/null +++ b/pkg/util/resource_helper_test.go @@ -0,0 +1,91 @@ +package util + +import ( + "testing" + + "github.com/owncloud/ocis-settings/pkg/proto/v0" + "gotest.tools/assert" +) + +func TestIsResourceMatched(t *testing.T) { + scenarios := []struct { + name string + definition *proto.Resource + example *proto.Resource + matched bool + }{ + { + "same resource types without ids match", + &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + true, + }, + { + "different resource types without ids don't match", + &proto.Resource{ + Type: proto.Resource_TYPE_SYSTEM, + }, + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + false, + }, + { + "same resource types with different ids don't match", + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + Id: "einstein", + }, + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + Id: "marie", + }, + false, + }, + { + "same resource types with same ids match", + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + Id: "einstein", + }, + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + Id: "einstein", + }, + true, + }, + { + "same resource types with definition = ALL and without id in example is a match", + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + Id: ResourceIDAll, + }, + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + }, + true, + }, + { + "same resource types with definition.id = ALL and with some id in example is a match", + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + Id: ResourceIDAll, + }, + &proto.Resource{ + Type: proto.Resource_TYPE_USER, + Id: "einstein", + }, + true, + }, + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + assert.Equal(t, scenario.matched, IsResourceMatched(scenario.definition, scenario.example)) + }) + } +}