diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index 52ae98ba5..169be6bc5 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -13,7 +13,10 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) -const methodGetSubject = "getSubject" +const ( + methodGetSubject = "getSubject" + methodGetSubjectExtended = "getSubjectExtended" +) func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) { prm := client.TestInvokePrm{} @@ -33,6 +36,24 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) return subj, nil } +func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.SubjectExtended, error) { + prm := client.TestInvokePrm{} + prm.SetMethod(methodGetSubjectExtended) + prm.SetArgs(addr) + + res, err := c.client.TestInvoke(prm) + if err != nil { + return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) + } + + subj, err := parseSubjectExtended(res) + if err != nil { + return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) + } + + return subj, nil +} + func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) { if ln := len(res); ln != 1 { return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) @@ -79,6 +100,64 @@ func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) { return &subj, nil } +func parseSubjectExtended(res []stackitem.Item) (*frostfsidclient.SubjectExtended, error) { + if ln := len(res); ln != 1 { + return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) + } + + structArr, err := client.ArrayFromStackItem(res[0]) + if err != nil { + return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) + } + + var subj frostfsidclient.SubjectExtended + + subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) + if err != nil { + return nil, err + } + + if !structArr[1].Equals(stackitem.Null{}) { + subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) + if err != nil { + return nil, err + } + } + + if !structArr[2].Equals(stackitem.Null{}) { + subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) + if err != nil { + return nil, err + } + } + + if !structArr[3].Equals(stackitem.Null{}) { + subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) + if err != nil { + return nil, err + } + } + + subj.KV, err = parseMap(structArr[4]) + if err != nil { + return nil, err + } + + if !structArr[5].Equals(stackitem.Null{}) { + groupItems, ok := structArr[5].Value().([]stackitem.Item) + if !ok { + return nil, errors.New("invalid groups field") + } + + subj.Groups, err = parseGroups(groupItems) + if err != nil { + return nil, err + } + } + + return &subj, nil +} + func makeValidRes(item stackitem.Item) (*result.Invoke, error) { return &result.Invoke{ Stack: []stackitem.Item{item}, @@ -116,3 +195,54 @@ func parseMap(item stackitem.Item) (map[string]string, error) { return res, nil } + +func parseGroups(items []stackitem.Item) ([]*frostfsidclient.Group, error) { + var err error + res := make([]*frostfsidclient.Group, len(items)) + + for i := 0; i < len(items); i++ { + arr, ok := items[i].Value().([]stackitem.Item) + if !ok { + return nil, errors.New("invalid group type") + } + res[i], err = parseGroup(arr) + if err != nil { + return nil, err + } + } + + return res, nil +} + +func parseGroup(structArr []stackitem.Item) (*frostfsidclient.Group, error) { + if len(structArr) < 4 { + return nil, errors.New("invalid response group struct") + } + + groupID, err := structArr[0].TryInteger() + if err != nil { + return nil, err + } + + name, err := structArr[1].TryBytes() + if err != nil { + return nil, err + } + + namespace, err := structArr[2].TryBytes() + if err != nil { + return nil, err + } + + kvs, err := parseMap(structArr[3]) + if err != nil { + return nil, err + } + + return &frostfsidclient.Group{ + ID: groupID.Int64(), + Name: string(name), + Namespace: string(namespace), + KV: kvs, + }, nil +}