diff --git a/docs/grpc/index.html b/docs/grpc/index.html
index 3f1c62411a..5f6ce072df 100644
--- a/docs/grpc/index.html
+++ b/docs/grpc/index.html
@@ -7059,6 +7059,16 @@
UpdateAttributeRequest
Updating the rule of an Attribute will retroactively alter access to existing TDFs of the Attribute name.
+
+ | values_order |
+ string |
+ repeated |
+ WARNING!!
+Unsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition
+will retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted
+deleted, created, and unsafely re-ordered as necessary. |
+
+
diff --git a/docs/openapi/policy/unsafe/unsafe.swagger.json b/docs/openapi/policy/unsafe/unsafe.swagger.json
index a06e83132f..e9bec6b515 100644
--- a/docs/openapi/policy/unsafe/unsafe.swagger.json
+++ b/docs/openapi/policy/unsafe/unsafe.swagger.json
@@ -201,6 +201,17 @@
"ATTRIBUTE_RULE_TYPE_ENUM_HIERARCHY"
],
"default": "ATTRIBUTE_RULE_TYPE_ENUM_UNSPECIFIED"
+ },
+ {
+ "name": "valuesOrder",
+ "description": "WARNING!!\nUnsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition\nwill retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted\ndeleted, created, and unsafely re-ordered as necessary.",
+ "in": "query",
+ "required": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "collectionFormat": "multi"
}
],
"tags": [
diff --git a/protocol/go/policy/unsafe/unsafe.pb.go b/protocol/go/policy/unsafe/unsafe.pb.go
index 212083b27e..f87dcc9d77 100644
--- a/protocol/go/policy/unsafe/unsafe.pb.go
+++ b/protocol/go/policy/unsafe/unsafe.pb.go
@@ -350,6 +350,11 @@ type UpdateAttributeRequest struct {
// WARNING!!
// Updating the rule of an Attribute will retroactively alter access to existing TDFs of the Attribute name.
Rule policy.AttributeRuleTypeEnum `protobuf:"varint,3,opt,name=rule,proto3,enum=policy.AttributeRuleTypeEnum" json:"rule,omitempty"`
+ // WARNING!!
+ // Unsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition
+ // will retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted
+ // deleted, created, and unsafely re-ordered as necessary.
+ ValuesOrder []string `protobuf:"bytes,4,rep,name=values_order,json=valuesOrder,proto3" json:"values_order,omitempty"`
}
func (x *UpdateAttributeRequest) Reset() {
@@ -405,6 +410,13 @@ func (x *UpdateAttributeRequest) GetRule() policy.AttributeRuleTypeEnum {
return policy.AttributeRuleTypeEnum(0)
}
+func (x *UpdateAttributeRequest) GetValuesOrder() []string {
+ if x != nil {
+ return x.ValuesOrder
+ }
+ return nil
+}
+
type UpdateAttributeResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1021,7 +1033,7 @@ var file_policy_unsafe_unsafe_proto_rawDesc = []byte{
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73,
0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c,
0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e,
- 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x9c, 0x03, 0x0a, 0x16, 0x55, 0x70, 0x64,
+ 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xbf, 0x03, 0x0a, 0x16, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xac, 0x02, 0x0a, 0x04,
@@ -1047,169 +1059,171 @@ var file_policy_unsafe_unsafe_proto_rawDesc = []byte{
0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x54,
0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x42, 0x08, 0xba, 0x48, 0x05, 0x82, 0x01, 0x02, 0x10,
- 0x01, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x22, 0x4a, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74,
- 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41,
- 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
- 0x75, 0x74, 0x65, 0x22, 0x34, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
- 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba,
- 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4e, 0x0a, 0x1b, 0x52, 0x65, 0x61,
- 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72,
- 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f,
- 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09,
- 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x4a, 0x0a, 0x16, 0x44, 0x65, 0x6c,
- 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
- 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, 0x66,
- 0x71, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01,
- 0x52, 0x03, 0x66, 0x71, 0x6e, 0x22, 0x4a, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41,
- 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74,
- 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
- 0x65, 0x22, 0xdf, 0x02, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72,
- 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba,
- 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xa7, 0x02, 0x0a, 0x05, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x90, 0x02, 0xba, 0x48, 0x8c, 0x02,
- 0xba, 0x01, 0x83, 0x02, 0x0a, 0x0c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d,
- 0x61, 0x74, 0x12, 0xb5, 0x01, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20,
- 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72,
- 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79,
- 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73,
- 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73,
- 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61,
- 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68,
- 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
- 0x74, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65,
- 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c,
- 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, 0x74, 0x68, 0x69, 0x73,
- 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41,
- 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a,
- 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d,
- 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x05, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x22, 0x43, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74,
- 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x39, 0x0a, 0x1f, 0x52, 0x65, 0x61, 0x63,
- 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69,
- 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52,
- 0x02, 0x69, 0x64, 0x22, 0x47, 0x0a, 0x20, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
- 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4f, 0x0a, 0x1b,
- 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69,
- 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52,
- 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x22, 0x43, 0x0a,
- 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a,
- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70,
- 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x32, 0xba, 0x0a, 0x0a, 0x0d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x53, 0x65, 0x72,
- 0x76, 0x69, 0x63, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e,
- 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x25, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
- 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e,
- 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e,
- 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x32,
- 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x98, 0x01, 0x0a, 0x13, 0x52, 0x65, 0x61,
- 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
- 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65,
- 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73,
- 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f,
- 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63,
- 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x22,
- 0x22, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76,
- 0x61, 0x74, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61,
- 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x25, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79,
- 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61,
- 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26,
- 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x44,
- 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17,
- 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
- 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61,
- 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x25, 0x2e, 0x70, 0x6f,
+ 0x01, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x73, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x73, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x4a, 0x0a, 0x17, 0x55, 0x70,
+ 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
+ 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
+ 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x34, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4e, 0x0a, 0x1b,
+ 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62,
+ 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11,
+ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x4a, 0x0a, 0x16,
+ 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18,
+ 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03,
+ 0xc8, 0x01, 0x01, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x22, 0x4a, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65,
+ 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
+ 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69,
+ 0x62, 0x75, 0x74, 0x65, 0x22, 0xdf, 0x02, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xa7, 0x02, 0x0a,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x90, 0x02, 0xba,
+ 0x48, 0x8c, 0x02, 0xba, 0x01, 0x83, 0x02, 0x0a, 0x0c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66,
+ 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb5, 0x01, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x65, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20,
+ 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20,
+ 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67,
+ 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64,
+ 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72,
+ 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e,
+ 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x74, 0x74, 0x72,
+ 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, 0x74,
+ 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61,
+ 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a,
+ 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d,
+ 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x43, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
+ 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x39, 0x0a, 0x1f, 0x52,
+ 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
+ 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16,
+ 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8,
+ 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x47, 0x0a, 0x20, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69,
+ 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
+ 0x4f, 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
+ 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16,
+ 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8,
+ 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x03, 0x66, 0x71, 0x6e,
+ 0x22, 0x43, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62,
+ 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0xba, 0x0a, 0x0a, 0x0d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65,
+ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61,
+ 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x25, 0x2e, 0x70, 0x6f,
0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61,
- 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61,
- 0x66, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
- 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93,
- 0x02, 0x19, 0x32, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72,
- 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x98, 0x01, 0x0a, 0x13,
- 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62,
- 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73,
- 0x61, 0x66, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74,
- 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a,
+ 0x66, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
+ 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93,
+ 0x02, 0x19, 0x32, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x98, 0x01, 0x0a, 0x13,
+ 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73,
+ 0x61, 0x66, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61,
+ 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a,
0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x52,
- 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
- 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93,
- 0x02, 0x24, 0x22, 0x22, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72,
- 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63,
+ 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
+ 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93,
+ 0x02, 0x24, 0x22, 0x22, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63,
0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74,
- 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x25, 0x2e, 0x70, 0x6f, 0x6c,
+ 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x25, 0x2e, 0x70, 0x6f, 0x6c,
0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
- 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66,
- 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02,
- 0x19, 0x2a, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69,
- 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x97, 0x01, 0x0a, 0x14, 0x55,
- 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73,
- 0x61, 0x66, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62,
- 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e,
- 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3,
- 0xe4, 0x93, 0x02, 0x20, 0x32, 0x1e, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74,
- 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f,
- 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xae, 0x01, 0x0a, 0x18, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76,
- 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66,
- 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72,
- 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66,
+ 0x19, 0x2a, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73,
+ 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x25,
+ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75,
+ 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72,
+ 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82,
+ 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x32, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x98,
+ 0x01, 0x0a, 0x13, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
+ 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
+ 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66,
0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72,
- 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x29, 0x2f, 0x75, 0x6e, 0x73,
- 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74,
- 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
- 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a,
- 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x44,
- 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x70, 0x6f, 0x6c,
- 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
- 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x2a,
- 0x1e, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
- 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42,
- 0xac, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75,
- 0x6e, 0x73, 0x61, 0x66, 0x65, 0x42, 0x0b, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x50, 0x72, 0x6f,
- 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
- 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
- 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f,
- 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0xa2, 0x02, 0x03, 0x50, 0x55,
- 0x58, 0xaa, 0x02, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66,
- 0x65, 0xca, 0x02, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x55, 0x6e, 0x73, 0x61, 0x66,
- 0x65, 0xe2, 0x02, 0x19, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x55, 0x6e, 0x73, 0x61, 0x66,
- 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e,
- 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x62, 0x06,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82,
+ 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x22, 0x22, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72,
+ 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x44, 0x65,
+ 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x25, 0x2e,
+ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x44, 0x65,
+ 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e,
+ 0x73, 0x61, 0x66, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69,
+ 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3,
+ 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74,
+ 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x97, 0x01,
+ 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
+ 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61,
+ 0x66, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
+ 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
+ 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x32, 0x1e, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65,
+ 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xae, 0x01, 0x0a, 0x18, 0x52, 0x65, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e,
+ 0x73, 0x61, 0x66, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e,
+ 0x73, 0x61, 0x66, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x29, 0x2f,
+ 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
+ 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c,
+ 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x12, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66,
+ 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e,
+ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x44, 0x65,
+ 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93,
+ 0x02, 0x20, 0x2a, 0x1e, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72,
+ 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69,
+ 0x64, 0x7d, 0x42, 0xac, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
+ 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x42, 0x0b, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f,
+ 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0xa2, 0x02,
+ 0x03, 0x50, 0x55, 0x58, 0xaa, 0x02, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x55, 0x6e,
+ 0x73, 0x61, 0x66, 0x65, 0xca, 0x02, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x55, 0x6e,
+ 0x73, 0x61, 0x66, 0x65, 0xe2, 0x02, 0x19, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x55, 0x6e,
+ 0x73, 0x61, 0x66, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0xea, 0x02, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x55, 0x6e, 0x73, 0x61, 0x66,
+ 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/service/integration/attribute_fqns_test.go b/service/integration/attribute_fqns_test.go
index e9f136065a..59e0045fd9 100644
--- a/service/integration/attribute_fqns_test.go
+++ b/service/integration/attribute_fqns_test.go
@@ -366,6 +366,57 @@ func (s *AttributeFqnSuite) TestGetAttributesByValueFqns_Fails_WithDeactivatedAt
s.Require().ErrorIs(err, db.ErrNotFound)
}
+func (s *AttributeFqnSuite) TestGetAttributesByValueFqns_Fails_WithDeactivatedAttributeValue() {
+ // create a new namespace
+ ns, err := s.db.PolicyClient.CreateNamespace(s.ctx, &namespaces.CreateNamespaceRequest{
+ Name: "test_fqn_namespace.goodbye",
+ })
+ s.Require().NoError(err)
+
+ // give it an attribute with two values
+ attr, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.CreateAttributeRequest{
+ NamespaceId: ns.GetId(),
+ Name: "deactivating_attr",
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF,
+ })
+ s.Require().NoError(err)
+
+ v1, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, attr.GetId(), &attributes.CreateAttributeValueRequest{
+ Value: "value1",
+ })
+ s.Require().NoError(err)
+
+ v2, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, attr.GetId(), &attributes.CreateAttributeValueRequest{
+ Value: "value2",
+ })
+ s.Require().NoError(err)
+
+ // deactivate the first attribute value only
+ _, err = s.db.PolicyClient.DeactivateAttributeValue(s.ctx, v1.GetId())
+ s.Require().NoError(err)
+
+ // get the attribute by the value fqn for v1
+ v, err := s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, &attributes.GetAttributeValuesByFqnsRequest{
+ Fqns: []string{fqnBuilder(ns.GetName(), attr.GetName(), v1.GetValue())},
+ WithValue: &policy.AttributeValueSelector{
+ WithSubjectMaps: true,
+ },
+ })
+ s.Require().Error(err)
+ s.Nil(v)
+ s.Require().ErrorIs(err, db.ErrNotFound)
+
+ // get the attribute by the value fqn for v2
+ v, err = s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, &attributes.GetAttributeValuesByFqnsRequest{
+ Fqns: []string{fqnBuilder(ns.GetName(), attr.GetName(), v2.GetValue())},
+ WithValue: &policy.AttributeValueSelector{
+ WithSubjectMaps: true,
+ },
+ })
+ s.Require().NoError(err)
+ s.Len(v, 1)
+}
+
func (s *AttributeFqnSuite) TestGetAttributesByValueFqns_Fails_WithNonValueFqns() {
nsFqn := fqnBuilder("example.com", "", "")
attrFqn := fqnBuilder("example.com", "attr1", "")
diff --git a/service/integration/attributes_test.go b/service/integration/attributes_test.go
index 2fa9ed928d..9165ca2f05 100644
--- a/service/integration/attributes_test.go
+++ b/service/integration/attributes_test.go
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log/slog"
+ "slices"
"strings"
"testing"
"time"
@@ -12,6 +13,7 @@ import (
"github.com/opentdf/platform/protocol/go/policy"
"github.com/opentdf/platform/protocol/go/policy/attributes"
"github.com/opentdf/platform/protocol/go/policy/namespaces"
+ "github.com/opentdf/platform/protocol/go/policy/unsafe"
"github.com/opentdf/platform/service/internal/fixtures"
"github.com/opentdf/platform/service/pkg/db"
policydb "github.com/opentdf/platform/service/policy/db"
@@ -214,11 +216,6 @@ func (s *AttributesSuite) Test_CreateAttribute_WithInvalidRuleFails() {
s.Nil(createdAttr)
}
-func (s *AttributesSuite) Test_UnsafeUpdateAttribute_ReplaceValuesOrder() {
- // TODO: write test when unsafe behaviors are implemented [https://github.com/opentdf/platform/issues/115]
- s.T().Skip("Unsafe service behaviors not yet implemented.")
-}
-
func (s *AttributesSuite) Test_GetAttribute_OrderOfValuesIsPreserved() {
values := []string{"first", "second", "third", "fourth"}
attr := &attributes.CreateAttributeRequest{
@@ -490,72 +487,323 @@ func (s *AttributesSuite) Test_UpdateAttribute_WithInvalidIdFails() {
s.Require().ErrorIs(err, db.ErrNotFound)
}
-func (s *AttributesSuite) Test_UpdateAttribute_NamespaceIsImmutableOnUpdate() {
- s.T().Skip("Defunct test: not possible to test update in this way; check request struct for validation instead.")
- original := &attributes.CreateAttributeRequest{
- Name: "test__update_attribute_namespace_immutable",
- NamespaceId: s.f.GetNamespaceKey("example.com").ID,
- Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_UNSPECIFIED,
+func (s *AttributesSuite) Test_UnsafeUpdateAttribute_WithRuleAndNameAndReordering() {
+ originalName := "test__update_attribute_with_rule_and_name_and_reordering"
+ newName := "updated_hello"
+ namespaceID := s.f.GetNamespaceKey("example.org").ID
+ values := []string{"abc", "def", "xyz", "testing"}
+ attr := &attributes.CreateAttributeRequest{
+ Name: originalName,
+ NamespaceId: namespaceID,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF,
+ Values: values,
}
- createdAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, original)
+ createdAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, attr)
s.Require().NoError(err)
s.NotNil(createdAttr)
- // should error on attempt to change namespace
- update := &attributes.UpdateAttributeRequest{}
- resp, err := s.db.PolicyClient.UpdateAttribute(s.ctx, createdAttr.GetId(), update)
- s.Require().Error(err)
- s.Nil(resp)
- s.Require().ErrorIs(err, db.ErrRestrictViolation)
+ got, err := s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(got)
+ nsName := got.GetNamespace().GetName()
+ updatedVals := []string{"def", "abc", "testing", "xyz"}
+ updatedValIDs := make([]string, len(values))
+ for i, v := range got.GetValues() {
+ idx := slices.Index(updatedVals, v.GetValue())
+ updatedValIDs[i] = got.GetValues()[idx].GetId()
+ }
- // validate namespace should not have been changed
- updated, err := s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ // name, rule, order updates respected
+ updated, err := s.db.PolicyClient.UnsafeUpdateAttribute(s.ctx, &unsafe.UpdateAttributeRequest{
+ Id: createdAttr.GetId(),
+ Name: newName,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_HIERARCHY,
+ ValuesOrder: updatedValIDs,
+ })
s.Require().NoError(err)
s.NotNil(updated)
- s.Equal(original.GetNamespaceId(), updated.GetNamespace().GetId())
+ s.Equal(newName, updated.GetName())
+ s.Equal(policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_HIERARCHY, updated.GetRule())
+
+ // name, rule, order updates respected and fqn is updated
+ updated, err = s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(updated)
+ s.Equal(newName, updated.GetName())
+ s.Equal(policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_HIERARCHY, updated.GetRule())
+ s.Equal(fmt.Sprintf("https://%s/attr/%s", nsName, updated.GetName()), updated.GetFqn())
+ s.Len(updated.GetValues(), len(values))
+
+ // values reflect new updated name and requested update order
+ for i, v := range updated.GetValues() {
+ s.Equal(updatedVals[i], v.GetValue())
+ fqn := fmt.Sprintf("https://%s/attr/%s/value/%s", nsName, newName, v.GetValue())
+
+ val, err := s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, &attributes.GetAttributeValuesByFqnsRequest{
+ Fqns: []string{fqn},
+ WithValue: &policy.AttributeValueSelector{
+ WithSubjectMaps: true,
+ },
+ })
+ s.Require().NoError(err)
+ s.NotNil(val)
+ s.Len(val, 1)
+ s.Equal(v.GetId(), val[fqn].GetValue().GetId())
+ }
}
-func (s *AttributesSuite) Test_UpdateAttributeWithSameNameAndNamespaceConflictFails() {
- s.T().Skip("Defunct test: not possible to test update in this way; check request struct for validation instead.")
- fixtureData := s.f.GetAttributeKey("example.org/attr/attr3")
- original := &attributes.CreateAttributeRequest{
- Name: "test__update_attribute_with_same_name_and_namespace",
- NamespaceId: fixtureData.NamespaceID,
- Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF,
+func (s *AttributesSuite) Test_UnsafeUpdateAttribute_WithRule() {
+ attr := &attributes.CreateAttributeRequest{
+ Name: "test__update_attribute_with_rule",
+ NamespaceId: fixtureNamespaceID,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF,
}
- createdAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, original)
+ createdAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, attr)
s.Require().NoError(err)
s.NotNil(createdAttr)
- conflict := &attributes.UpdateAttributeRequest{}
- resp, err := s.db.PolicyClient.UpdateAttribute(s.ctx, fixtureData.ID, conflict)
- s.Require().Error(err)
- s.Nil(resp)
- s.Require().ErrorIs(err, db.ErrUniqueConstraintViolation)
+ got, err := s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(got)
+ s.Equal(policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF, got.GetRule())
+
+ updated, err := s.db.PolicyClient.UnsafeUpdateAttribute(s.ctx, &unsafe.UpdateAttributeRequest{
+ Id: createdAttr.GetId(),
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF,
+ })
+ s.Require().NoError(err)
+ s.NotNil(updated)
+ s.Equal(policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF, updated.GetRule())
+
+ updated, err = s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(updated)
+ s.Equal(policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF, updated.GetRule())
}
-func (s *AttributesSuite) Test_DeleteAttribute() {
+func (s *AttributesSuite) Test_UnsafeUpdateAttribute_WithNewName() {
+ originalName := "test__update_attribute_with_new_name"
+ newName := originalName + "updated"
attr := &attributes.CreateAttributeRequest{
- Name: "test__delete_attribute",
+ Name: originalName,
+ NamespaceId: fixtureNamespaceID,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF,
+ Values: []string{"abc", "def"},
+ }
+ createdAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, attr)
+ s.Require().NoError(err)
+ s.NotNil(createdAttr)
+
+ got, err := s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(got)
+
+ originalFqn := got.GetFqn()
+ s.NotEqual("", originalFqn)
+
+ // update with a new name
+ updated, err := s.db.PolicyClient.UnsafeUpdateAttribute(s.ctx, &unsafe.UpdateAttributeRequest{
+ Id: createdAttr.GetId(),
+ Name: newName,
+ })
+ s.Require().NoError(err)
+ s.NotNil(updated)
+ s.Equal(newName, updated.GetName())
+ s.NotEqual(originalFqn, updated.GetFqn())
+
+ updated, err = s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(updated)
+
+ // ensure the fqn has changed
+ s.Equal(fmt.Sprintf("https://%s/attr/%s", got.GetNamespace().GetName(), updated.GetName()), updated.GetFqn())
+
+ // ensure the name change is reflected
+ s.Equal(newName, updated.GetName())
+
+ // ensure everything else is unchanged
+ s.Equal(got.GetRule(), updated.GetRule())
+ s.Len(updated.GetValues(), 2)
+ s.True(updated.GetActive().GetValue())
+
+ // values are able to be looked up by fqn with new updated name
+ fqns := []string{
+ fmt.Sprintf("https://%s/attr/%s/value/%s", got.GetNamespace().GetName(), updated.GetName(), updated.GetValues()[0].GetValue()),
+ fmt.Sprintf("https://%s/attr/%s/value/%s", got.GetNamespace().GetName(), updated.GetName(), updated.GetValues()[1].GetValue()),
+ }
+ req := &attributes.GetAttributeValuesByFqnsRequest{
+ Fqns: fqns,
+ WithValue: &policy.AttributeValueSelector{
+ WithSubjectMaps: true,
+ },
+ }
+ retrieved, err := s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, req)
+ s.Require().NoError(err)
+ s.NotNil(retrieved)
+ s.Len(retrieved, 2)
+
+ val, err := s.db.PolicyClient.GetAttributeValue(s.ctx, updated.GetValues()[0].GetId())
+ s.Require().NoError(err)
+ s.NotNil(val)
+ s.Equal(fqns[0], val.GetFqn())
+ s.Contains(val.GetFqn(), updated.GetName())
+
+ val, err = s.db.PolicyClient.GetAttributeValue(s.ctx, updated.GetValues()[1].GetId())
+ s.Require().NoError(err)
+ s.NotNil(val)
+ s.Equal(fqns[1], val.GetFqn())
+ s.Contains(val.GetFqn(), updated.GetName())
+}
+
+func (s *AttributesSuite) Test_UnsafeUpdateAttribute_NormalizesCasing() {
+ created, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.CreateAttributeRequest{
+ Name: "BANANA_PUDDING",
+ NamespaceId: fixtureNamespaceID,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF,
+ Values: []string{"fig", "jam"},
+ })
+ s.Require().NoError(err)
+ s.NotNil(created)
+
+ got, err := s.db.PolicyClient.GetAttribute(s.ctx, created.GetId())
+ s.Require().NoError(err)
+ s.NotNil(got)
+ s.Equal("banana_pudding", got.GetName())
+ s.Contains(got.GetFqn(), "banana_pudding")
+
+ updated, err := s.db.PolicyClient.UnsafeUpdateAttribute(s.ctx, &unsafe.UpdateAttributeRequest{
+ Id: created.GetId(),
+ Name: "STRAWBERRY_SHORTCAKE",
+ })
+ s.Require().NoError(err)
+ s.NotNil(updated)
+ s.Equal("strawberry_shortcake", updated.GetName())
+
+ got, err = s.db.PolicyClient.GetAttribute(s.ctx, created.GetId())
+ s.Require().NoError(err)
+ s.NotNil(got)
+ s.Equal("strawberry_shortcake", got.GetName())
+ s.Contains(got.GetFqn(), "strawberry_shortcake")
+}
+
+func (s *AttributesSuite) Test_UnsafeUpdateAttribute_ReplaceValuesOrder() {
+ toCreate := &attributes.CreateAttributeRequest{
+ Name: "test__unsafe_update_attribute_replace_values_order",
+ NamespaceId: fixtureNamespaceID,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_HIERARCHY,
+ Values: []string{"first", "second", "third"},
+ }
+ created, err := s.db.PolicyClient.CreateAttribute(s.ctx, toCreate)
+ s.Require().NoError(err)
+ s.NotNil(created)
+ s.Len(created.GetValues(), 3)
+
+ // reverse values order
+ reversed := make([]string, len(created.GetValues()))
+ for i, v := range created.GetValues() {
+ reversed[len(created.GetValues())-i-1] = v.GetId()
+ }
+ updated, err := s.db.PolicyClient.UnsafeUpdateAttribute(s.ctx, &unsafe.UpdateAttributeRequest{
+ Id: created.GetId(),
+ ValuesOrder: reversed,
+ })
+ s.Require().NoError(err)
+ s.NotNil(updated)
+ s.Len(updated.GetValues(), 3)
+
+ // get attribute and ensure the order of the values is preserved and successfully reversed
+ got, err := s.db.PolicyClient.GetAttribute(s.ctx, created.GetId())
+ s.Require().NoError(err)
+ s.NotNil(got)
+ s.Len(got.GetValues(), 3)
+ for i, v := range got.GetValues() {
+ s.Equal(reversed[i], v.GetId())
+ }
+}
+
+func (s *AttributesSuite) Test_UnsafeDeleteAttribute() {
+ name := "test__delete_attribute"
+ attr := &attributes.CreateAttributeRequest{
+ Name: name,
NamespaceId: fixtureNamespaceID,
Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_UNSPECIFIED,
+ Values: []string{"value1", "value2", "value3"},
}
createdAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, attr)
s.Require().NoError(err)
s.NotNil(createdAttr)
- deleted, err := s.db.PolicyClient.DeleteAttribute(s.ctx, createdAttr.GetId())
+ got, _ := s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+
+ deleted, err := s.db.PolicyClient.UnsafeDeleteAttribute(s.ctx, got, got.GetFqn())
s.Require().NoError(err)
s.NotNil(deleted)
- // should not exist anymore
+ // attribute should not exist anymore
resp, err := s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
s.Require().Error(err)
s.Nil(resp)
+
+ // values should not exist anymore (cascade delete)
+ for _, v := range createdAttr.GetValues() {
+ resp, err := s.db.PolicyClient.GetAttributeValue(s.ctx, v.GetId())
+ s.Require().Error(err)
+ s.Nil(resp)
+ }
+
+ // namespace should still exist unaffected
+ ns, err := s.db.PolicyClient.GetNamespace(s.ctx, fixtureNamespaceID)
+ s.Require().NoError(err)
+ s.NotNil(ns)
+ s.NotEqual("", ns.GetId())
+
+ // attribute should not be listed anymore
+ list, err := s.db.PolicyClient.ListAllAttributes(s.ctx, policydb.StateAny, fixtureNamespaceID)
+ s.Require().NoError(err)
+ s.NotNil(list)
+ for _, l := range list {
+ s.NotEqual(createdAttr.GetId(), l.GetId())
+ }
+
+ // attr fqn should not be found
+ fqn := fmt.Sprintf("https://%s/attr/%s", ns.GetName(), name)
+ resp, err = s.db.PolicyClient.GetAttributeByFqn(s.ctx, fqn)
+ s.Require().Error(err)
+ s.Nil(resp)
+ s.Require().ErrorIs(err, db.ErrNotFound)
+
+ // value fqns should be deleted and not found
+ for _, v := range got.GetValues() {
+ fqns := []string{fmt.Sprintf("https://%s/attr/%s/value/%s", ns.GetName(), name, v.GetValue())}
+ req := &attributes.GetAttributeValuesByFqnsRequest{
+ Fqns: fqns,
+ WithValue: &policy.AttributeValueSelector{
+ WithSubjectMaps: true,
+ },
+ }
+ retrieved, err := s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, req)
+ s.Require().Error(err)
+ s.Nil(retrieved)
+ s.Require().ErrorIs(err, db.ErrNotFound)
+ }
+
+ // should be able to create attribute of same name as deleted
+ createdAttr, err = s.db.PolicyClient.CreateAttribute(s.ctx, attr)
+ s.Require().NoError(err)
+ s.NotNil(createdAttr)
}
-func (s *AttributesSuite) Test_DeleteAttribute_WithInvalidIdFails() {
- deleted, err := s.db.PolicyClient.DeleteAttribute(s.ctx, nonExistentAttrID)
+func (s *AttributesSuite) Test_UnsafeDeleteAttribute_WithBadFqnFails() {
+ created, _ := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.CreateAttributeRequest{
+ Name: "test__delete_attribute_with_bad_fqn",
+ NamespaceId: fixtureNamespaceID,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF,
+ })
+ got, _ := s.db.PolicyClient.GetAttribute(s.ctx, created.GetId())
+ s.NotNil(got)
+ s.NotEqual("", got.GetFqn())
+
+ deleted, err := s.db.PolicyClient.UnsafeDeleteAttribute(s.ctx, got, "bad_fqn")
s.Require().Error(err)
s.Nil(deleted)
s.Require().ErrorIs(err, db.ErrNotFound)
@@ -732,6 +980,56 @@ func (s *AttributesSuite) Test_DeactivateAttribute_Cascades_ToValues_Get() {
s.False(gotVal.GetActive().GetValue())
}
+func (s *AttributesSuite) Test_UnsafeReactivateAttribute() {
+ // create an attribute
+ attr := &attributes.CreateAttributeRequest{
+ Name: "test__unsafe_reactivate_attribute",
+ NamespaceId: fixtureNamespaceID,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF,
+ Values: []string{"aa", "bb", "cc"},
+ }
+ createdAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, attr)
+ s.Require().NoError(err)
+ s.NotNil(createdAttr)
+
+ // deactivate the attribute
+ deactivatedAttr, err := s.db.PolicyClient.DeactivateAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(deactivatedAttr)
+ s.False(deactivatedAttr.GetActive().GetValue())
+
+ // reactivate the attribute
+ reactivatedAttr, err := s.db.PolicyClient.UnsafeReactivateAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(reactivatedAttr)
+
+ // found to be active
+ activated, err := s.db.PolicyClient.GetAttribute(s.ctx, reactivatedAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(activated)
+ s.True(activated.GetActive().GetValue())
+
+ // found in successive lookup by fqn
+ activated, err = s.db.PolicyClient.GetAttributeByFqn(s.ctx, activated.GetFqn())
+ s.Require().NoError(err)
+ s.NotNil(activated)
+
+ // ensure the values are still inactive
+ for _, v := range reactivatedAttr.GetValues() {
+ got, err := s.db.PolicyClient.GetAttributeValue(s.ctx, v.GetId())
+ s.Require().NoError(err)
+ s.NotNil(got)
+ s.False(got.GetActive().GetValue())
+ }
+}
+
+func (s *AttributesSuite) Test_UnsafeReactivateAttribute_WithInvalidIdFails() {
+ reactivatedAttr, err := s.db.PolicyClient.UnsafeReactivateAttribute(s.ctx, nonExistentAttrID)
+ s.Require().Error(err)
+ s.Nil(reactivatedAttr)
+ s.Require().ErrorIs(err, db.ErrNotFound)
+}
+
func (s *AttributesSuite) Test_AssignKeyAccessServerToAttribute_Returns_Error_When_Attribute_Not_Found() {
aKas := &attributes.AttributeKeyAccessServer{
AttributeId: nonExistentAttrID,
diff --git a/service/integration/namespaces_test.go b/service/integration/namespaces_test.go
index 28ddd4aef2..a055795b15 100644
--- a/service/integration/namespaces_test.go
+++ b/service/integration/namespaces_test.go
@@ -462,8 +462,10 @@ func (s *NamespacesSuite) Test_UnsafeDeleteNamespace_Cascades() {
s.Require().NoError(err)
s.NotNil(createdVal2)
+ existing, _ := s.db.PolicyClient.GetNamespace(s.ctx, n.GetId())
+
// delete the namespace
- deleted, err := s.db.PolicyClient.UnsafeDeleteNamespace(s.ctx, n.GetId())
+ deleted, err := s.db.PolicyClient.UnsafeDeleteNamespace(s.ctx, existing, existing.GetFqn())
s.Require().NoError(err)
s.NotNil(deleted)
@@ -496,8 +498,10 @@ func (s *NamespacesSuite) Test_UnsafeDeleteNamespace_ShouldBeAbleToRecreateDelet
s.Require().NoError(err)
s.NotNil(n)
+ got, _ := s.db.PolicyClient.GetNamespace(s.ctx, n.GetId())
+
// delete the namespace
- _, err = s.db.PolicyClient.UnsafeDeleteNamespace(s.ctx, n.GetId())
+ _, err = s.db.PolicyClient.UnsafeDeleteNamespace(s.ctx, got, got.GetFqn())
s.Require().NoError(err)
// create the namespace again
@@ -506,6 +510,24 @@ func (s *NamespacesSuite) Test_UnsafeDeleteNamespace_ShouldBeAbleToRecreateDelet
s.NotNil(n)
}
+func (s *NamespacesSuite) Test_UnsafeDeleteNamespace_DoesNotExist_ShouldFail() {
+ ns, err := s.db.PolicyClient.UnsafeDeleteNamespace(s.ctx, &policy.Namespace{}, "does.not.exist")
+ s.Require().Error(err)
+ s.Require().ErrorIs(err, db.ErrNotFound)
+ s.Nil(ns)
+
+ created, _ := s.db.PolicyClient.CreateNamespace(s.ctx, &namespaces.CreateNamespaceRequest{Name: "deletingns.com"})
+ s.NotNil(created)
+ got, _ := s.db.PolicyClient.GetNamespace(s.ctx, created.GetId())
+ s.NotNil(got)
+ s.NotEqual("", got.GetFqn())
+
+ ns, err = s.db.PolicyClient.UnsafeDeleteNamespace(s.ctx, got, "https://bad.fqn")
+ s.Require().Error(err)
+ s.Require().ErrorIs(err, db.ErrNotFound)
+ s.Nil(ns)
+}
+
func (s *NamespacesSuite) Test_UnsafeReactivateNamespace_SetsActiveStatusOfNamespace() {
// create a namespace
n, err := s.db.PolicyClient.CreateNamespace(s.ctx, &namespaces.CreateNamespaceRequest{Name: "reactivating-namespace.com"})
@@ -666,6 +688,50 @@ func (s *NamespacesSuite) Test_UnsafeUpdateNamespace() {
s.NotEqual(created.GetId(), recreated.GetId())
}
+// validate a namespace with a definition and values are all lookupable by fqn
+func (s *NamespacesSuite) Test_UnsafeUpdateNamespace_CascadesInFqns() {
+ // create a namespace
+ n, err := s.db.PolicyClient.CreateNamespace(s.ctx, &namespaces.CreateNamespaceRequest{Name: "updating-namespace.io"})
+ s.Require().NoError(err)
+ s.NotNil(n)
+
+ // create an attribute under that namespace
+ attr := &attributes.CreateAttributeRequest{
+ Name: "test__updating-attr",
+ NamespaceId: n.GetId(),
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF,
+ Values: []string{"test_val1"},
+ }
+ createdAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, attr)
+ s.Require().NoError(err)
+ s.NotNil(createdAttr)
+ createdAttr, _ = s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ createdVal := createdAttr.GetValues()[0]
+
+ // update the namespace
+ updated, err := s.db.PolicyClient.UnsafeUpdateNamespace(s.ctx, n.GetId(), "updated.ca")
+ s.Require().NoError(err)
+ s.NotNil(updated)
+
+ // ensure the namespace has the proper fqn
+ gotNs, err := s.db.PolicyClient.GetNamespace(s.ctx, updated.GetId())
+ s.Require().NoError(err)
+ s.NotNil(gotNs)
+ s.Equal("https://updated.ca", gotNs.GetFqn())
+
+ // ensure the attribute has the proper fqn
+ gotAttr, err := s.db.PolicyClient.GetAttribute(s.ctx, createdAttr.GetId())
+ s.Require().NoError(err)
+ s.NotNil(gotAttr)
+ s.Equal("https://updated.ca/attr/test__updating-attr", gotAttr.GetFqn())
+
+ // ensure the value has the proper fqn
+ gotVal, err := s.db.PolicyClient.GetAttributeValue(s.ctx, createdVal.GetId())
+ s.Require().NoError(err)
+ s.NotNil(gotVal)
+ s.Equal("https://updated.ca/attr/test__updating-attr/value/test_val1", gotVal.GetFqn())
+}
+
func (s *NamespacesSuite) Test_UnsafeUpdateNamespace_DoesNotExist_ShouldFail() {
ns, err := s.db.PolicyClient.UnsafeUpdateNamespace(s.ctx, nonExistentNamespaceID, "does.not.exist")
s.Require().Error(err)
@@ -673,6 +739,27 @@ func (s *NamespacesSuite) Test_UnsafeUpdateNamespace_DoesNotExist_ShouldFail() {
s.Nil(ns)
}
+func (s *NamespacesSuite) Test_UnsafeUpdateNamespace_NormalizeCasing() {
+ ns, err := s.db.PolicyClient.CreateNamespace(s.ctx, &namespaces.CreateNamespaceRequest{Name: "TeStInG-XYZ.com"})
+ s.Require().NoError(err)
+ s.NotNil(ns)
+
+ got, _ := s.db.PolicyClient.GetNamespace(s.ctx, ns.GetId())
+ s.NotNil(got)
+ s.Equal("testing-xyz.com", got.GetName())
+
+ updated, err := s.db.PolicyClient.UnsafeUpdateNamespace(s.ctx, ns.GetId(), "HELLOWORLD.COM")
+ s.Require().NoError(err)
+ s.NotNil(updated)
+ s.Equal("helloworld.com", updated.GetName())
+
+ got, _ = s.db.PolicyClient.GetNamespace(s.ctx, ns.GetId())
+ s.NotNil(got)
+ s.Equal("helloworld.com", got.GetName())
+ s.Contains(got.GetFqn(), "helloworld.com")
+ s.Equal("https://helloworld.com", got.GetFqn())
+}
+
func TestNamespacesSuite(t *testing.T) {
if testing.Short() {
t.Skip("skipping namespaces integration tests")
diff --git a/service/policy/db/attribute_fqn.go b/service/policy/db/attribute_fqn.go
index 9873ce055a..0d3de0314e 100644
--- a/service/policy/db/attribute_fqn.go
+++ b/service/policy/db/attribute_fqn.go
@@ -193,7 +193,7 @@ func (c *PolicyDBClient) GetAttributesByValueFqns(ctx context.Context, r *attrib
filtered, selected := filterValues(attr.GetValues(), fqn)
if selected == nil {
slog.Error("could not find value for FQN", slog.String("fqn", fqn))
- return nil, fmt.Errorf("could not find value for FQN: %s", fqn)
+ return nil, fmt.Errorf("could not find value for FQN: %s: %w", fqn, db.ErrNotFound)
}
attr.Values = filtered
list[fqn] = &attributes.GetAttributeValuesByFqnsResponse_AttributeAndValue{
diff --git a/service/policy/db/attribute_values.go b/service/policy/db/attribute_values.go
index f0507e4e31..c227d3753a 100644
--- a/service/policy/db/attribute_values.go
+++ b/service/policy/db/attribute_values.go
@@ -197,7 +197,10 @@ func (c PolicyDBClient) CreateAttributeValue(ctx context.Context, attributeID st
}
// Update FQN
- c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueID: id})
+ fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueID: id})
+ if fqn != "" {
+ slog.Debug("created new attribute value FQN", slog.String("value_id", id), slog.String("value", value), slog.String("fqn", fqn))
+ }
rV := &policy.Value{
Id: id,
diff --git a/service/policy/db/attributes.go b/service/policy/db/attributes.go
index 71a05568f1..8d2498eafc 100644
--- a/service/policy/db/attributes.go
+++ b/service/policy/db/attributes.go
@@ -14,6 +14,7 @@ import (
"github.com/opentdf/platform/protocol/go/common"
"github.com/opentdf/platform/protocol/go/policy"
"github.com/opentdf/platform/protocol/go/policy/attributes"
+ "github.com/opentdf/platform/protocol/go/policy/unsafe"
"github.com/opentdf/platform/service/pkg/db"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/wrapperspb"
@@ -511,9 +512,6 @@ func (c PolicyDBClient) CreateAttribute(ctx context.Context, r *attributes.Creat
return nil, err
}
- // Update the FQN
- c.upsertAttrFqn(ctx, attrFqnUpsertOptions{attributeID: id})
-
// Add values
var values []*policy.Value
for _, v := range r.GetValues() {
@@ -525,6 +523,16 @@ func (c PolicyDBClient) CreateAttribute(ctx context.Context, r *attributes.Creat
values = append(values, value)
}
+ // Update the FQNs
+ namespaceID := r.GetNamespaceId()
+ fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: namespaceID, attributeID: id})
+ slog.Debug("upserted fqn with new attribute definition", slog.Any("fqn", fqn))
+
+ for _, v := range values {
+ fqn = c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: namespaceID, attributeID: id, valueID: v.GetId()})
+ slog.Debug("upserted fqn with new attribute value on new definition create", slog.Any("fqn", fqn))
+ }
+
a := &policy.Attribute{
Id: id,
Name: name,
@@ -539,29 +547,84 @@ func (c PolicyDBClient) CreateAttribute(ctx context.Context, r *attributes.Creat
return a, nil
}
-// TODO: uncomment this and consume when unsafe protos/service is implemented [https://github.com/opentdf/platform/issues/115]
-// func unsafeUpdateAttributeSql(id string, updateName string, updateRule string, replaceValuesOrder []string, metadata []byte) (string, []interface{}, error) {
-// t := Tables.Attributes
-// sb := db.NewStatementBuilder().Update(t.Name())
-
-// if updateName != "" {
-// sb = sb.Set("name", updateName)
-// }
-// if updateRule != "" {
-// sb = sb.Set("rule", updateRule)
-// }
-// // validation should happen before calling that:
-// // 1) replaceValuesOrder should be the same length as the column's current array length
-// // 2) replaceValuesOrder should contain all children value id's of this attribute
-// if len(replaceValuesOrder) > 0 {
-// sb = sb.Set("values_order", replaceValuesOrder)
-// }
-// if metadata != nil {
-// sb = sb.Set("metadata", metadata)
-// }
-
-// return sb.Where(sq.Eq{t.Field("id"): id}).ToSql()
-// }
+func unsafeUpdateAttributeSQL(id string, updateName string, updateRule string, replaceValuesOrder []string) (string, []interface{}, error) {
+ t := Tables.Attributes
+ sb := db.NewStatementBuilder().Update(t.Name())
+
+ if updateName != "" {
+ sb = sb.Set("name", updateName)
+ }
+ if updateRule != "" {
+ sb = sb.Set("rule", updateRule)
+ }
+ if len(replaceValuesOrder) > 0 {
+ sb = sb.Set("values_order", replaceValuesOrder)
+ }
+
+ return sb.Where(sq.Eq{t.Field("id"): id}).
+ ToSql()
+}
+
+func (c PolicyDBClient) UnsafeUpdateAttribute(ctx context.Context, r *unsafe.UpdateAttributeRequest) (*policy.Attribute, error) {
+ id := r.GetId()
+ before, err := c.GetAttribute(ctx, id)
+ if err != nil {
+ return nil, err
+ }
+
+ // Validate that the values_order contains all the children value id's of this attribute
+ lenExistingValues := len(before.GetValues())
+ lenNewValues := len(r.GetValuesOrder())
+ if lenNewValues > 0 {
+ if lenExistingValues != lenNewValues {
+ return nil, fmt.Errorf("values_order can only be updated with current attribute values: %w", db.ErrForeignKeyViolation)
+ }
+ // check if all the children value id's of this attribute are in the values_order
+ for _, v := range before.GetValues() {
+ found := false
+ for _, vo := range r.GetValuesOrder() {
+ if v.GetId() == vo {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return nil, fmt.Errorf("values_order can only be updated with current attribute values: %w", db.ErrForeignKeyViolation)
+ }
+ }
+ }
+
+ // Handle case where rule is not actually being updated
+ rule := ""
+ if r.GetRule() != policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_UNSPECIFIED {
+ rule = attributesRuleTypeEnumTransformIn(r.GetRule().String())
+ }
+
+ sql, args, err := unsafeUpdateAttributeSQL(id, strings.ToLower(r.GetName()), rule, r.GetValuesOrder())
+ if err != nil {
+ return nil, err
+ }
+
+ err = c.Exec(ctx, sql, args)
+ if err != nil {
+ return nil, err
+ }
+
+ // Upsert all the FQNs with the definition name mutation
+ if r.GetName() != "" {
+ namespaceID := before.GetNamespace().GetId()
+ fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: namespaceID, attributeID: id})
+ slog.Debug("upserted attribute fqn with new definition name", slog.Any("fqn", fqn))
+ if len(before.GetValues()) > 0 {
+ for _, v := range before.GetValues() {
+ fqn = c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: namespaceID, attributeID: id, valueID: v.GetId()})
+ slog.Debug("upserted attribute value fqn with new definition name", slog.Any("fqn", fqn))
+ }
+ }
+ }
+
+ return c.GetAttribute(ctx, id)
+}
func safeUpdateAttributeSQL(id string, metadata []byte) (string, []interface{}, error) {
t := Tables.Attributes
@@ -601,9 +664,6 @@ func (c PolicyDBClient) UpdateAttribute(ctx context.Context, id string, r *attri
return nil, err
}
- // Update the FQN
- c.upsertAttrFqn(ctx, attrFqnUpsertOptions{attributeID: id})
-
return &policy.Attribute{
Id: id,
}, nil
@@ -631,34 +691,65 @@ func (c PolicyDBClient) DeactivateAttribute(ctx context.Context, id string) (*po
return c.GetAttribute(ctx, id)
}
-func deleteAttributeSQL(id string) (string, []interface{}, error) {
+func unsafeReactivateAttributeSQL(id string) (string, []interface{}, error) {
t := Tables.Attributes
return db.NewStatementBuilder().
- Delete(t.Name()).
+ Update(t.Name()).
+ Set("active", true).
Where(sq.Eq{t.Field("id"): id}).
+ Suffix("RETURNING \"id\"").
ToSql()
}
-func (c PolicyDBClient) DeleteAttribute(ctx context.Context, id string) (*policy.Attribute, error) {
- // get attribute before deleting
- a, err := c.GetAttribute(ctx, id)
+func (c PolicyDBClient) UnsafeReactivateAttribute(ctx context.Context, id string) (*policy.Attribute, error) {
+ sql, args, err := unsafeReactivateAttributeSQL(id)
if err != nil {
- return nil, db.WrapIfKnownInvalidQueryErr(err)
+ return nil, err
+ }
+
+ if err := c.Exec(ctx, sql, args); err != nil {
+ return nil, err
+ }
+
+ return c.GetAttribute(ctx, id)
+}
+
+func unsafeDeleteAttributeSQL(id string) (string, []interface{}, error) {
+ t := Tables.Attributes
+ return db.NewStatementBuilder().
+ Delete(t.Name()).
+ Where(sq.Eq{t.Field("id"): id}).
+ Suffix("RETURNING \"id\"").
+ ToSql()
+}
+
+func (c PolicyDBClient) UnsafeDeleteAttribute(ctx context.Context, existing *policy.Attribute, fqn string) (*policy.Attribute, error) {
+ if existing == nil {
+ return nil, fmt.Errorf("attribute not found: %w", db.ErrNotFound)
}
+ id := existing.GetId()
- sql, args, err := deleteAttributeSQL(id)
+ if existing.GetFqn() != fqn {
+ return nil, fmt.Errorf("fqn mismatch: %w", db.ErrNotFound)
+ }
+ sql, args, err := unsafeDeleteAttributeSQL(id)
if err != nil {
- return nil, db.WrapIfKnownInvalidQueryErr(err)
+ return nil, err
}
if err := c.Exec(ctx, sql, args); err != nil {
return nil, err
}
- // return the attribute before deleting
- return a, nil
+ return &policy.Attribute{
+ Id: id,
+ }, nil
}
+///
+/// Key Access Server assignments
+///
+
func assignKeyAccessServerToAttributeSQL(attributeID, keyAccessServerID string) (string, []interface{}, error) {
t := Tables.AttributeKeyAccessGrants
return db.NewStatementBuilder().
diff --git a/service/policy/db/namespaces.go b/service/policy/db/namespaces.go
index 802b93d87d..03e206dcb4 100644
--- a/service/policy/db/namespaces.go
+++ b/service/policy/db/namespaces.go
@@ -3,6 +3,7 @@ package db
import (
"context"
"database/sql"
+ "fmt"
"log/slog"
"strings"
@@ -208,7 +209,8 @@ func (c PolicyDBClient) CreateNamespace(ctx context.Context, r *namespaces.Creat
}
// Update FQN
- c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id})
+ fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id})
+ slog.Debug("upserted fqn for created namespace", slog.Any("fqn", fqn))
return &policy.Namespace{
Id: id,
@@ -259,9 +261,6 @@ func (c PolicyDBClient) UpdateNamespace(ctx context.Context, id string, r *names
return nil, err
}
- // Update FQN
- c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id})
-
return &policy.Namespace{
Id: id,
}, nil
@@ -278,7 +277,7 @@ func unsafeUpdateNamespaceSQL(id string, name string) (string, []interface{}, er
}
func (c PolicyDBClient) UnsafeUpdateNamespace(ctx context.Context, id string, name string) (*policy.Namespace, error) {
- sql, args, err := unsafeUpdateNamespaceSQL(id, name)
+ sql, args, err := unsafeUpdateNamespaceSQL(id, strings.ToLower(name))
if db.IsQueryBuilderSetClauseError(err) {
return &policy.Namespace{
Id: id,
@@ -292,8 +291,23 @@ func (c PolicyDBClient) UnsafeUpdateNamespace(ctx context.Context, id string, na
if err != nil {
return nil, err
}
- // Update FQN
- c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id})
+
+ // Update all FQNs that may contain the namespace name
+ fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id})
+ slog.Debug("upserted fqn for unsafely updated namespace", slog.Any("fqn", fqn))
+
+ attrs, err := c.ListAllAttributes(ctx, StateAny, id)
+ if err != nil {
+ return nil, err
+ }
+ for _, attr := range attrs {
+ fqn = c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id, attributeID: attr.GetId()})
+ slog.Debug("upserted definition fqn for unsafely updated namespace", slog.Any("fqn", fqn))
+ for _, value := range attr.GetValues() {
+ fqn = c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id, attributeID: attr.GetId(), valueID: value.GetId()})
+ slog.Debug("upserted value fqn for unsafely updated namespace", slog.Any("fqn", fqn))
+ }
+ }
return hydrateNamespaceItem(row, namespaceSelectOptions{})
}
@@ -367,7 +381,15 @@ func deleteNamespaceSQL(id string) (string, []interface{}, error) {
ToSql()
}
-func (c PolicyDBClient) UnsafeDeleteNamespace(ctx context.Context, id string) (*policy.Namespace, error) {
+func (c PolicyDBClient) UnsafeDeleteNamespace(ctx context.Context, existing *policy.Namespace, fqn string) (*policy.Namespace, error) {
+ if existing == nil {
+ return nil, fmt.Errorf("namespace not found: %w", db.ErrNotFound)
+ }
+ id := existing.GetId()
+
+ if existing.GetFqn() != fqn {
+ return nil, fmt.Errorf("fqn mismatch: %w", db.ErrNotFound)
+ }
sql, args, err := deleteNamespaceSQL(id)
if err != nil {
return nil, err
diff --git a/service/policy/unsafe/unsafe.go b/service/policy/unsafe/unsafe.go
index 810bbc3572..5b5be02be9 100644
--- a/service/policy/unsafe/unsafe.go
+++ b/service/policy/unsafe/unsafe.go
@@ -80,12 +80,7 @@ func (s *UnsafeService) DeleteNamespace(ctx context.Context, req *unsafe.DeleteN
return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId()))
}
- // validate the provided namespace FQN is a match for the provided namespace ID
- if existing.GetFqn() != req.GetFqn() {
- return nil, db.StatusifyError(db.ErrNotFound, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId()), slog.String("fqn", req.GetFqn()))
- }
-
- deleted, err := s.dbClient.UnsafeDeleteNamespace(ctx, req.GetId())
+ deleted, err := s.dbClient.UnsafeDeleteNamespace(ctx, existing, req.GetFqn())
if err != nil {
return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", req.GetId()))
}
@@ -99,58 +94,58 @@ func (s *UnsafeService) DeleteNamespace(ctx context.Context, req *unsafe.DeleteN
// Unsafe Attribute Definition RPCs
//
-func (s *UnsafeService) UpdateAttribute(_ context.Context, req *unsafe.UpdateAttributeRequest) (*unsafe.UpdateAttributeResponse, error) {
- // _, err := s.dbClient.GetAttribute(ctx, req.GetId())
- // if err != nil {
- // return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId()))
- // }
+func (s *UnsafeService) UpdateAttribute(ctx context.Context, req *unsafe.UpdateAttributeRequest) (*unsafe.UpdateAttributeResponse, error) {
+ rsp := &unsafe.UpdateAttributeResponse{}
- // item, err := s.dbClient.UnsafeUpdateAttribute(ctx, req.GetId(), req)
- // if err != nil {
- // return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("attribute", req.String()))
- // }
+ _, err := s.dbClient.GetAttribute(ctx, req.GetId())
+ if err != nil {
+ return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId()))
+ }
- return &unsafe.UpdateAttributeResponse{
- Attribute: &policy.Attribute{
- Id: req.GetId(), // stubbed
- },
- }, nil
+ item, err := s.dbClient.UnsafeUpdateAttribute(ctx, req)
+ if err != nil {
+ return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("attribute", req.String()))
+ }
+
+ rsp.Attribute = item
+
+ return rsp, nil
}
-func (s *UnsafeService) ReactivateAttribute(_ context.Context, req *unsafe.ReactivateAttributeRequest) (*unsafe.ReactivateAttributeResponse, error) {
- // _, err := s.dbClient.GetAttribute(ctx, req.GetId())
- // if err != nil {
- // return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId()))
- // }
+func (s *UnsafeService) ReactivateAttribute(ctx context.Context, req *unsafe.ReactivateAttributeRequest) (*unsafe.ReactivateAttributeResponse, error) {
+ rsp := &unsafe.ReactivateAttributeResponse{}
- // item, err := s.dbClient.UnsafeReactivateAttribute(ctx, req.GetId())
- // if err != nil {
- // return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()))
- // }
+ _, err := s.dbClient.GetAttribute(ctx, req.GetId())
+ if err != nil {
+ return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId()))
+ }
- return &unsafe.ReactivateAttributeResponse{
- Attribute: &policy.Attribute{
- Id: req.GetId(), // stubbed
- },
- }, nil
+ item, err := s.dbClient.UnsafeReactivateAttribute(ctx, req.GetId())
+ if err != nil {
+ return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()))
+ }
+
+ rsp.Attribute = item
+
+ return rsp, nil
}
-func (s *UnsafeService) DeleteAttribute(_ context.Context, req *unsafe.DeleteAttributeRequest) (*unsafe.DeleteAttributeResponse, error) {
- // _, err := s.dbClient.GetAttribute(ctx, req.GetId())
- // if err != nil {
- // return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId()))
- // }
+func (s *UnsafeService) DeleteAttribute(ctx context.Context, req *unsafe.DeleteAttributeRequest) (*unsafe.DeleteAttributeResponse, error) {
+ rsp := &unsafe.DeleteAttributeResponse{}
- // err = s.dbClient.UnsafeDeleteAttribute(ctx, req.GetId())
- // if err != nil {
- // return nil, db.StatusifyError(err, db.ErrTextDeleteFailed, slog.String("id", req.GetId()))
- // }
+ existing, err := s.dbClient.GetAttribute(ctx, req.GetId())
+ if err != nil {
+ return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId()))
+ }
- return &unsafe.DeleteAttributeResponse{
- Attribute: &policy.Attribute{
- Id: req.GetId(), // stubbed
- },
- }, nil
+ deleted, err := s.dbClient.UnsafeDeleteAttribute(ctx, existing, req.GetFqn())
+ if err != nil {
+ return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", req.GetId()))
+ }
+
+ rsp.Attribute = deleted
+
+ return rsp, nil
}
//
diff --git a/service/policy/unsafe/unsafe.proto b/service/policy/unsafe/unsafe.proto
index 5565cbd05f..ba401b552d 100644
--- a/service/policy/unsafe/unsafe.proto
+++ b/service/policy/unsafe/unsafe.proto
@@ -76,6 +76,11 @@ message UpdateAttributeRequest {
AttributeRuleTypeEnum rule = 3 [
(buf.validate.field).enum.defined_only = true
];
+ // WARNING!!
+ // Unsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition
+ // will retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted
+ // deleted, created, and unsafely re-ordered as necessary.
+ repeated string values_order = 4;
}
message UpdateAttributeResponse {
policy.Attribute attribute = 1;