[#168] acl: Implement binary/JSON encoders/decoders on Table
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
ae68790bbd
commit
233756ca8f
6 changed files with 117 additions and 96 deletions
|
@ -111,3 +111,47 @@ func NewTableFromV2(table *v2acl.Table) *Table {
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marshal marshals Table into a protobuf binary form.
|
||||||
|
//
|
||||||
|
// Buffer is allocated when the argument is empty.
|
||||||
|
// Otherwise, the first buffer is used.
|
||||||
|
func (t *Table) Marshal(b ...[]byte) ([]byte, error) {
|
||||||
|
var buf []byte
|
||||||
|
if len(b) > 0 {
|
||||||
|
buf = b[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.ToV2().
|
||||||
|
StableMarshal(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal unmarshals protobuf binary representation of Table.
|
||||||
|
func (t *Table) Unmarshal(data []byte) error {
|
||||||
|
fV2 := new(v2acl.Table)
|
||||||
|
if err := fV2.Unmarshal(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = *NewTableFromV2(fV2)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON encodes Table to protobuf JSON format.
|
||||||
|
func (t *Table) MarshalJSON() ([]byte, error) {
|
||||||
|
return t.ToV2().
|
||||||
|
MarshalJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON decodes Table from protobuf JSON format.
|
||||||
|
func (t *Table) UnmarshalJSON(data []byte) error {
|
||||||
|
tV2 := new(v2acl.Table)
|
||||||
|
if err := tV2.UnmarshalJSON(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = *NewTableFromV2(tV2)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -78,3 +78,30 @@ func TestTable_AddRecord(t *testing.T) {
|
||||||
|
|
||||||
require.Equal(t, records, table.Records())
|
require.Equal(t, records, table.Records())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecordEncoding(t *testing.T) {
|
||||||
|
tab := eacl.NewTable()
|
||||||
|
tab.AddRecord(
|
||||||
|
eacl.CreateRecord(eacl.ActionDeny, eacl.OperationHead),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run("binary", func(t *testing.T) {
|
||||||
|
data, err := tab.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tab2 := eacl.NewTable()
|
||||||
|
require.NoError(t, tab2.Unmarshal(data))
|
||||||
|
|
||||||
|
require.Equal(t, tab, tab2)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("json", func(t *testing.T) {
|
||||||
|
data, err := tab.MarshalJSON()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
r2 := eacl.NewTable()
|
||||||
|
require.NoError(t, r2.UnmarshalJSON(data))
|
||||||
|
|
||||||
|
require.Equal(t, tab, r2)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -11,54 +11,6 @@ var (
|
||||||
errEmptyInput = errors.New("empty input")
|
errEmptyInput = errors.New("empty input")
|
||||||
)
|
)
|
||||||
|
|
||||||
func RecordToJSON(r *Record) ([]byte, error) {
|
|
||||||
if r == nil {
|
|
||||||
return nil, errEmptyInput
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := RecordToGRPCMessage(r)
|
|
||||||
|
|
||||||
return protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RecordFromJSON(data []byte) (*Record, error) {
|
|
||||||
if len(data) == 0 {
|
|
||||||
return nil, errEmptyInput
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := new(acl.EACLRecord)
|
|
||||||
|
|
||||||
if err := protojson.Unmarshal(data, msg); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return RecordFromGRPCMessage(msg), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TableToJSON(t *Table) ([]byte, error) {
|
|
||||||
if t == nil {
|
|
||||||
return nil, errEmptyInput
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := TableToGRPCMessage(t)
|
|
||||||
|
|
||||||
return protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TableFromJSON(data []byte) (*Table, error) {
|
|
||||||
if len(data) == 0 {
|
|
||||||
return nil, errEmptyInput
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := new(acl.EACLTable)
|
|
||||||
|
|
||||||
if err := protojson.Unmarshal(data, msg); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return TableFromGRPCMessage(msg), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BearerTokenToJSON(t *BearerToken) ([]byte, error) {
|
func BearerTokenToJSON(t *BearerToken) ([]byte, error) {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return nil, errEmptyInput
|
return nil, errEmptyInput
|
||||||
|
@ -142,3 +94,23 @@ func (r *Record) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Table) MarshalJSON() ([]byte, error) {
|
||||||
|
return protojson.MarshalOptions{
|
||||||
|
EmitUnpopulated: true,
|
||||||
|
}.Marshal(
|
||||||
|
TableToGRPCMessage(t),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Table) UnmarshalJSON(data []byte) error {
|
||||||
|
msg := new(acl.EACLTable)
|
||||||
|
|
||||||
|
if err := protojson.Unmarshal(data, msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = *TableFromGRPCMessage(msg)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -7,50 +7,6 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRecordJSON(t *testing.T) {
|
|
||||||
exp := generateRecord(false)
|
|
||||||
|
|
||||||
t.Run("non empty", func(t *testing.T) {
|
|
||||||
data, err := acl.RecordToJSON(exp)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
got, err := acl.RecordFromJSON(data)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Equal(t, exp, got)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("empty", func(t *testing.T) {
|
|
||||||
_, err := acl.RecordToJSON(nil)
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
_, err = acl.RecordFromJSON(nil)
|
|
||||||
require.Error(t, err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEACLTableJSON(t *testing.T) {
|
|
||||||
exp := generateEACL()
|
|
||||||
|
|
||||||
t.Run("non empty", func(t *testing.T) {
|
|
||||||
data, err := acl.TableToJSON(exp)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
got, err := acl.TableFromJSON(data)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Equal(t, exp, got)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("empty", func(t *testing.T) {
|
|
||||||
_, err := acl.TableToJSON(nil)
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
_, err = acl.TableFromJSON(nil)
|
|
||||||
require.Error(t, err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBearerTokenJSON(t *testing.T) {
|
func TestBearerTokenJSON(t *testing.T) {
|
||||||
exp := generateBearerToken("token")
|
exp := generateBearerToken("token")
|
||||||
|
|
||||||
|
@ -88,3 +44,16 @@ func TestTargetJSON(t *testing.T) {
|
||||||
|
|
||||||
require.Equal(t, tar, tar2)
|
require.Equal(t, tar, tar2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTable_MarshalJSON(t *testing.T) {
|
||||||
|
tab := new(acl.Table)
|
||||||
|
tab.SetRecords([]*acl.Record{generateRecord(false)})
|
||||||
|
|
||||||
|
data, err := tab.MarshalJSON()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tab2 := new(acl.Table)
|
||||||
|
require.NoError(t, tab2.UnmarshalJSON(data))
|
||||||
|
|
||||||
|
require.Equal(t, tab, tab2)
|
||||||
|
}
|
||||||
|
|
|
@ -94,6 +94,17 @@ func (t *Table) StableSize() (size int) {
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Table) Unmarshal(data []byte) error {
|
||||||
|
m := new(acl.EACLTable)
|
||||||
|
if err := proto.Unmarshal(data, m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = *TableFromGRPCMessage(m)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// StableMarshal marshals unified acl record structure in a protobuf
|
// StableMarshal marshals unified acl record structure in a protobuf
|
||||||
// compatible way without field order shuffle.
|
// compatible way without field order shuffle.
|
||||||
func (r *Record) StableMarshal(buf []byte) ([]byte, error) {
|
func (r *Record) StableMarshal(buf []byte) ([]byte, error) {
|
||||||
|
|
|
@ -170,7 +170,6 @@ func TestRecord_StableMarshal(t *testing.T) {
|
||||||
|
|
||||||
func TestTable_StableMarshal(t *testing.T) {
|
func TestTable_StableMarshal(t *testing.T) {
|
||||||
tableFrom := new(acl.Table)
|
tableFrom := new(acl.Table)
|
||||||
transport := new(grpc.EACLTable)
|
|
||||||
|
|
||||||
t.Run("non empty", func(t *testing.T) {
|
t.Run("non empty", func(t *testing.T) {
|
||||||
cid := new(refs.ContainerID)
|
cid := new(refs.ContainerID)
|
||||||
|
@ -190,10 +189,9 @@ func TestTable_StableMarshal(t *testing.T) {
|
||||||
wire, err := tableFrom.StableMarshal(nil)
|
wire, err := tableFrom.StableMarshal(nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = goproto.Unmarshal(wire, transport)
|
tableTo := new(acl.Table)
|
||||||
require.NoError(t, err)
|
require.NoError(t, tableTo.Unmarshal(wire))
|
||||||
|
|
||||||
tableTo := acl.TableFromGRPCMessage(transport)
|
|
||||||
require.Equal(t, tableFrom, tableTo)
|
require.Equal(t, tableFrom, tableTo)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue