Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 225 additions & 0 deletions internal/db/attribute_values.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package db

import (
"context"

sq "github.com/Masterminds/squirrel"
"github.com/jackc/pgx/v5"
"github.com/opentdf/opentdf-v2-poc/sdk/attributes"
"github.com/opentdf/opentdf-v2-poc/sdk/common"
"google.golang.org/protobuf/encoding/protojson"
)

var AttributeValueTable = tableName(TableAttributeValues)

func attributeValueHydrateItem(row pgx.Row) (*attributes.Value, error) {
var (
id string
value string
members []string
metadataJson []byte
)
if err := row.Scan(&id, &value, &members, &metadataJson); err != nil {
return nil, err
}

m := &common.Metadata{}
if metadataJson != nil {
if err := protojson.Unmarshal(metadataJson, m); err != nil {
return nil, err
}
}

v := &attributes.Value{
Id: id,
Value: value,
Members: members,
Metadata: m,
}
return v, nil
}

///
/// CRUD
///

func createAttributeValueSql(
attribute_id string,
value string,
members []string,
metadata []byte) (string, []interface{}, error) {
return newStatementBuilder().
Insert(AttributeValueTable).
Columns(
tableField(AttributeValueTable, "attribute_id"),
tableField(AttributeValueTable, "value"),
tableField(AttributeValueTable, "members"),
tableField(AttributeValueTable, "metadata"),
).
Values(
attribute_id,
value,
members,
metadata,
).
Suffix("RETURNING id").
ToSql()
}
func (c Client) CreateAttributeValue(ctx context.Context, v *attributes.ValueCreate) (*attributes.Value, error) {
metadataJson, metadata, err := marshalCreateMetadata(v.Metadata)
if err != nil {
return nil, err
}

sql, args, err := createAttributeValueSql(
v.AttributeId,
v.Value,
v.Members,
metadataJson,
)
if err != nil {
return nil, err
}

var id string
if r, err := c.queryRow(ctx, sql, args, err); err != nil {
return nil, err
} else if err := r.Scan(&id); err != nil {
return nil, err
}

rV := &attributes.Value{
Id: id,
Value: v.Value,
Members: v.Members,
Metadata: metadata,
}
return rV, nil
}

func getAttributeValueSql(id string) (string, []interface{}, error) {
return newStatementBuilder().
Select(
tableField(AttributeValueTable, "id"),
tableField(AttributeValueTable, "value"),
tableField(AttributeValueTable, "members"),
tableField(AttributeValueTable, "metadata"),
).
From(AttributeValueTable).
Where(sq.Eq{tableField(AttributeValueTable, "id"): id}).
ToSql()
}
func (c Client) GetAttributeValue(ctx context.Context, id string) (*attributes.Value, error) {
sql, args, err := getAttributeValueSql(id)
row, err := c.queryRow(ctx, sql, args, err)
if err != nil {
return nil, err
}

v, err := attributeValueHydrateItem(row)
if err != nil {
return nil, err
}

return v, nil
}

func listAttributeValuesSql(attribute_id string) (string, []interface{}, error) {
return newStatementBuilder().
Select(
tableField(AttributeValueTable, "id"),
tableField(AttributeValueTable, "value"),
tableField(AttributeValueTable, "members"),
tableField(AttributeValueTable, "metadata"),
).
From(AttributeValueTable).
Where(sq.Eq{tableField(AttributeValueTable, "attribute_id"): attribute_id}).
ToSql()
}
func (c Client) ListAttributeValues(ctx context.Context, attribute_id string) ([]*attributes.Value, error) {
sql, args, err := listAttributeValuesSql(attribute_id)
rows, err := c.query(ctx, sql, args, err)
if err != nil {
return nil, err
}
defer rows.Close()

list := make([]*attributes.Value, 0)
for rows.Next() {
v, err := attributeValueHydrateItem(rows)
if err != nil {
return nil, err
}
list = append(list, v)
}

return list, nil
}

func updateAttributeValueSql(
id string,
value string,
members []string,
metadata []byte) (string, []interface{}, error) {
sb := newStatementBuilder().
Update(AttributeValueTable)

if value != "" {
sb = sb.Set(tableField(AttributeValueTable, "value"), value)
}
if members != nil {
sb = sb.Set(tableField(AttributeValueTable, "members"), members)
}
sb.Set(tableField(AttributeValueTable, "metadata"), metadata)

return sb.
Where(sq.Eq{tableField(AttributeValueTable, "id"): id}).
ToSql()
}
func (c Client) UpdateAttributeValue(ctx context.Context, id string, v *attributes.ValueUpdate) (*attributes.Value, error) {
prev, err := c.GetAttributeValue(ctx, id)
if err != nil {
return nil, err
}

metadataJson, _, err := marshalUpdateMetadata(prev.Metadata, v.Metadata)
if err != nil {
return nil, err
}

sql, args, err := updateAttributeValueSql(
id,
v.Value,
v.Members,
metadataJson,
)
if err != nil {
return nil, err
}

if err := c.exec(ctx, sql, args, err); err != nil {
return nil, err
}

return prev, nil
}

func deleteAttributeValueSql(id string) (string, []interface{}, error) {
return newStatementBuilder().
Delete(AttributeValueTable).
Where(sq.Eq{tableField(AttributeValueTable, "id"): id}).
ToSql()
}
func (c Client) DeleteAttributeValue(ctx context.Context, id string) (*attributes.Value, error) {
prev, err := c.GetAttributeValue(ctx, id)
if err != nil {
return nil, err
}

sql, args, err := deleteAttributeValueSql(id)
if err := c.exec(ctx, sql, args, err); err != nil {
return nil, err
}

return prev, nil
}
17 changes: 11 additions & 6 deletions internal/db/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
)

var AttributeTable = tableName(TableAttributes)
var AttributeValueTable = tableName(TableAttributeValues)
var AttributeRuleTypeEnumPrefix = "ATTRIBUTE_RULE_TYPE_ENUM_"

func attributesRuleTypeEnumTransformIn(value string) string {
Expand Down Expand Up @@ -256,11 +255,17 @@ func (c Client) CreateAttribute(ctx context.Context, attr *attributes.AttributeC
}

func updateAttributeSql(id string, name string, rule string, metadata []byte) (string, []interface{}, error) {
return newStatementBuilder().
Update(AttributeTable).
Set("name", name).
Set("rule", rule).
Set("metadata", metadata).
sb := newStatementBuilder().
Update(AttributeTable)

if name != "" {
sb = sb.Set("name", name)
}
if rule != "" {
sb = sb.Set("rule", rule)
}

return sb.Set("metadata", metadata).
Where(sq.Eq{"id": id}).
ToSql()
}
Expand Down
30 changes: 21 additions & 9 deletions proto/attributes/attributes.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ message AttributeCreateUpdate {
];

// optional
repeated ValueCreateUpdate values = 5;
repeated ValueCreate values = 5;
}

message Value {
Expand All @@ -62,16 +62,26 @@ message Value {

common.Metadata metadata = 2;

string attribute_definition_id = 3 [(buf.validate.field).required = true];
string attribute_id = 3 [(buf.validate.field).required = true];

string value = 4;

// list of attribute values that this value is related to (attribute group)
repeated string members = 5;
}

// Definition of a single attribute value
message ValueCreateUpdate {
message ValueCreate {
common.MetadataMutable metadata = 1;

string attribute_id = 2 [(buf.validate.field).required = true];

string value = 3;

// list of attribute values that this value is related to (attribute group)
repeated string members = 4;
}

message ValueUpdate {
common.MetadataMutable metadata = 1;

string value = 2;
Expand All @@ -85,12 +95,12 @@ message ValueCreateUpdate {
*/

message DefinitionKeyAccessServerGrant {
string attribute_definition_id = 1;
string attribute_id = 1;
string key_access_server_id = 2;
}

message ValueKeyAccessServerGrant {
string attribute_value_id = 1;
string value_id = 1;
string key_access_server_id = 2;
}

Expand Down Expand Up @@ -149,15 +159,15 @@ message ListValuesResponse {

message CreateValueRequest {
string attribute_id = 1 [(buf.validate.field).required = true];
ValueCreateUpdate value = 2 [(buf.validate.field).required = true];
ValueCreate value = 2 [(buf.validate.field).required = true];
}
message CreateValueResponse {
Value value = 1;
}

message UpdateValueRequest {
string id = 1 [(buf.validate.field).required = true];
ValueCreateUpdate value = 2 [(buf.validate.field).required = true];
ValueUpdate value = 2 [(buf.validate.field).required = true];
}
message UpdateValueResponse {
Value value = 1;
Expand All @@ -166,7 +176,9 @@ message UpdateValueResponse {
message DeleteValueRequest {
string id = 1 [(buf.validate.field).required = true];
}
message DeleteValueResponse {}
message DeleteValueResponse {
Value value = 1;
}

///
/// Attribute Service
Expand Down
Loading