frostfs-rest-gw/handlers/transformers.go
Denis Kirillov 9f752cd756 [#1] Add basic structure and operations
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-29 10:20:37 +03:00

245 lines
6.4 KiB
Go

package handlers
import (
"encoding/hex"
"fmt"
sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session"
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/token"
)
// ToNativeAction converts models.Action to appropriate eacl.Action.
func ToNativeAction(a *models.Action) (eacl.Action, error) {
if a == nil {
return eacl.ActionUnknown, fmt.Errorf("unsupported empty action")
}
switch *a {
case models.ActionALLOW:
return eacl.ActionAllow, nil
case models.ActionDENY:
return eacl.ActionDeny, nil
default:
return eacl.ActionUnknown, fmt.Errorf("unsupported action type: '%s'", *a)
}
}
// ToNativeOperation converts models.Operation to appropriate eacl.Operation.
func ToNativeOperation(o *models.Operation) (eacl.Operation, error) {
if o == nil {
return eacl.OperationUnknown, fmt.Errorf("unsupported empty opertaion")
}
switch *o {
case models.OperationGET:
return eacl.OperationGet, nil
case models.OperationHEAD:
return eacl.OperationHead, nil
case models.OperationPUT:
return eacl.OperationPut, nil
case models.OperationDELETE:
return eacl.OperationDelete, nil
case models.OperationSEARCH:
return eacl.OperationSearch, nil
case models.OperationRANGE:
return eacl.OperationRange, nil
case models.OperationRANGEHASH:
return eacl.OperationRangeHash, nil
default:
return eacl.OperationUnknown, fmt.Errorf("unsupported operation type: '%s'", *o)
}
}
// ToNativeHeaderType converts models.HeaderType to appropriate eacl.FilterHeaderType.
func ToNativeHeaderType(h *models.HeaderType) (eacl.FilterHeaderType, error) {
if h == nil {
return eacl.HeaderTypeUnknown, fmt.Errorf("unsupported empty header type")
}
switch *h {
case models.HeaderTypeOBJECT:
return eacl.HeaderFromObject, nil
case models.HeaderTypeREQUEST:
return eacl.HeaderFromRequest, nil
case models.HeaderTypeSERVICE:
return eacl.HeaderFromService, nil
default:
return eacl.HeaderTypeUnknown, fmt.Errorf("unsupported header type: '%s'", *h)
}
}
// ToNativeMatchType converts models.MatchType to appropriate eacl.Match.
func ToNativeMatchType(t *models.MatchType) (eacl.Match, error) {
if t == nil {
return eacl.MatchUnknown, fmt.Errorf("unsupported empty match type")
}
switch *t {
case models.MatchTypeSTRINGEQUAL:
return eacl.MatchStringEqual, nil
case models.MatchTypeSTRINGNOTEQUAL:
return eacl.MatchStringNotEqual, nil
default:
return eacl.MatchUnknown, fmt.Errorf("unsupported match type: '%s'", *t)
}
}
// ToNativeRole converts models.Role to appropriate eacl.Role.
func ToNativeRole(r *models.Role) (eacl.Role, error) {
if r == nil {
return eacl.RoleUnknown, fmt.Errorf("unsupported empty role")
}
switch *r {
case models.RoleUSER:
return eacl.RoleUser, nil
case models.RoleSYSTEM:
return eacl.RoleSystem, nil
case models.RoleOTHERS:
return eacl.RoleOthers, nil
default:
return eacl.RoleUnknown, fmt.Errorf("unsupported role type: '%s'", *r)
}
}
// ToNativeVerb converts models.Verb to appropriate session.ContainerSessionVerb.
func ToNativeVerb(r *models.Verb) (sessionv2.ContainerSessionVerb, error) {
if r == nil {
return sessionv2.ContainerVerbUnknown, fmt.Errorf("unsupported empty verb type")
}
switch *r {
case models.VerbPUT:
return sessionv2.ContainerVerbPut, nil
case models.VerbDELETE:
return sessionv2.ContainerVerbDelete, nil
case models.VerbSETEACL:
return sessionv2.ContainerVerbSetEACL, nil
default:
return sessionv2.ContainerVerbUnknown, fmt.Errorf("unsupported verb type: '%s'", *r)
}
}
// ToNativeRule converts models.Rule to appropriate session.ContainerContext.
func ToNativeRule(r *models.Rule) (*session.ContainerContext, error) {
var ctx session.ContainerContext
verb, err := ToNativeVerb(r.Verb)
if err != nil {
return nil, err
}
ctx.ToV2().SetVerb(verb)
if r.ContainerID == "" {
ctx.ApplyTo(nil)
} else {
var cnrID cid.ID
if err = cnrID.Parse(r.ContainerID); err != nil {
return nil, fmt.Errorf("couldn't parse container id: %w", err)
}
ctx.ApplyTo(&cnrID)
}
return &ctx, nil
}
// ToNativeContainerToken converts models.Bearer to appropriate session.Token.
func ToNativeContainerToken(b *models.Bearer) (*session.Token, error) {
sctx, err := ToNativeRule(b.Container)
if err != nil {
return nil, fmt.Errorf("couldn't transform rule to native: %w", err)
}
tok := session.NewToken()
tok.SetContext(sctx)
return tok, nil
}
// ToNativeRecord converts models.Record to appropriate eacl.Record.
func ToNativeRecord(r *models.Record) (*eacl.Record, error) {
var record eacl.Record
action, err := ToNativeAction(r.Action)
if err != nil {
return nil, err
}
record.SetAction(action)
operation, err := ToNativeOperation(r.Operation)
if err != nil {
return nil, err
}
record.SetOperation(operation)
for _, filter := range r.Filters {
headerType, err := ToNativeHeaderType(filter.HeaderType)
if err != nil {
return nil, err
}
matchType, err := ToNativeMatchType(filter.MatchType)
if err != nil {
return nil, err
}
if filter.Key == nil || filter.Value == nil {
return nil, fmt.Errorf("invalid filter")
}
record.AddFilter(headerType, matchType, *filter.Key, *filter.Value)
}
targets := make([]eacl.Target, len(r.Targets))
for i, target := range r.Targets {
trgt, err := ToNativeTarget(target)
if err != nil {
return nil, err
}
targets[i] = *trgt
}
record.SetTargets(targets...)
return &record, nil
}
// ToNativeTarget converts models.Target to appropriate eacl.Target.
func ToNativeTarget(t *models.Target) (*eacl.Target, error) {
var target eacl.Target
role, err := ToNativeRole(t.Role)
if err != nil {
return nil, err
}
target.SetRole(role)
keys := make([][]byte, len(t.Keys))
for i, key := range t.Keys {
binaryKey, err := hex.DecodeString(key)
if err != nil {
return nil, fmt.Errorf("couldn't decode target key: %w", err)
}
keys[i] = binaryKey
}
target.SetBinaryKeys(keys)
return &target, nil
}
// ToNativeObjectToken converts Bearer to appropriate token.BearerToken.
func ToNativeObjectToken(b *models.Bearer) (*token.BearerToken, error) {
var btoken token.BearerToken
var table eacl.Table
for _, rec := range b.Object {
record, err := ToNativeRecord(rec)
if err != nil {
return nil, fmt.Errorf("couldn't transform record to native: %w", err)
}
table.AddRecord(record)
}
btoken.SetEACLTable(&table)
return &btoken, nil
}