func (m *Manager) EntityKVAdd(ID string, d []*pb.KVData) error {
	de := &pb.Entity{
		ID: &ID,
		Meta: &pb.EntityMeta{
			KV: d,
		},
	}
	_, err := m.RunEntityChain("KV-ADD", de)
	return err
}
EntityKVAdd handles adding a new key to the KV store for an entity
identified by ID.  The key must not previously exist.
package tree
import (
	"fmt"
	"strings"
	"github.com/netauth/netauth/internal/tree/util"
	"google.golang.org/protobuf/proto"
	"github.com/netauth/netauth/internal/db"
	pb "github.com/netauth/protocol"
)
func (m *Manager) CreateEntity(ID string, number int32, secret string) error {
	de := &pb.Entity{
		ID:     &ID,
		Number: &number,
		Secret: &secret,
	}
	_, err := m.RunEntityChain("CREATE", de)
	return err
}
func (m *Manager) DestroyEntity(ID string) error {
	de := &pb.Entity{
		ID: &ID,
	}
	_, err := m.RunEntityChain("DESTROY", de)
	return err
}
func (m *Manager) SetEntityCapability(ID string, c string) error {
	capIndex, ok := pb.Capability_value[c]
	if !ok {
		return ErrUnknownCapability
	}
	cap := pb.Capability(capIndex)
	return m.SetEntityCapability2(ID, &cap)
}
func (m *Manager) SetEntityCapability2(ID string, c *pb.Capability) error {
	if c == nil {
		return ErrUnknownCapability
	}
	de := &pb.Entity{
		ID: &ID,
		Meta: &pb.EntityMeta{
			Capabilities: []pb.Capability{*c},
		},
	}
	_, err := m.RunEntityChain("SET-CAPABILITY", de)
	return err
}
func (m *Manager) DropEntityCapability(ID string, c string) error {
	capIndex, ok := pb.Capability_value[c]
	if !ok {
		return ErrUnknownCapability
	}
	cap := pb.Capability(capIndex)
	return m.DropEntityCapability2(ID, &cap)
}
func (m *Manager) DropEntityCapability2(ID string, c *pb.Capability) error {
	if c == nil {
		return ErrUnknownCapability
	}
	de := &pb.Entity{
		ID: &ID,
		Meta: &pb.EntityMeta{
			Capabilities: []pb.Capability{*c},
		},
	}
	_, err := m.RunEntityChain("DROP-CAPABILITY", de)
	return err
}
func (m *Manager) SetSecret(ID string, secret string) error {
	de := &pb.Entity{
		ID:     &ID,
		Secret: &secret,
	}
	_, err := m.RunEntityChain("SET-SECRET", de)
	return err
}
func (m *Manager) ValidateSecret(ID string, secret string) error {
	de := &pb.Entity{
		ID:     &ID,
		Secret: &secret,
	}
	_, err := m.RunEntityChain("VALIDATE-IDENTITY", de)
	return err
}
func (m *Manager) FetchEntity(ID string) (*pb.Entity, error) {
	de := &pb.Entity{
		ID: &ID,
	}
	e, err := m.RunEntityChain("FETCH", de)
	if err != nil {
		return nil, err
	}
	return safeCopyEntity(e), nil
}
func (m *Manager) UpdateEntityMeta(ID string, newMeta *pb.EntityMeta) error {
	de := &pb.Entity{
		ID:   &ID,
		Meta: newMeta,
	}
	_, err := m.RunEntityChain("MERGE-METADATA", de)
	return err
}
func (m *Manager) UpdateEntityKeys(ID, mode, keytype, key string) ([]string, error) {
	mode = strings.ToUpper(mode)
	keytype = strings.ToUpper(keytype)
	de := &pb.Entity{
		ID: &ID,
		Meta: &pb.EntityMeta{
			Keys: []string{fmt.Sprintf("%s:%s", keytype, key)},
		},
	}
	chain := "FETCH"
	switch mode {
	case "ADD":
		chain = "ADD-KEY"
	case "DROP":
		fallthrough
	case "DEL":
		chain = "DEL-KEY"
	default:
		mode = "LIST"
	}
	e, err := m.RunEntityChain(chain, de)
	if err != nil {
		return nil, err
	}
	if mode == "LIST" {
		return e.GetMeta().GetKeys(), nil
	}
	return nil, nil
}
func (m *Manager) ManageUntypedEntityMeta(ID, mode, key, value string) ([]string, error) {
	de := &pb.Entity{
		ID: &ID,
		Meta: &pb.EntityMeta{
			UntypedMeta: []string{fmt.Sprintf("%s:%s", key, value)},
		},
	}
	chain := "FETCH"
	switch strings.ToUpper(mode) {
	case "UPSERT":
		chain = "UEM-UPSERT"
	case "CLEARFUZZY":
		chain = "UEM-CLEARFUZZY"
	case "CLEAREXACT":
		chain = "UEM-CLEAREXACT"
	default:
		mode = "READ"
	}
	e, err := m.RunEntityChain(chain, de)
	if err != nil {
		return nil, err
	}
	if strings.ToUpper(mode) == "READ" {
		return util.PatchKeyValueSlice(e.GetMeta().GetUntypedMeta(), "READ", key, ""), nil
	}
	return nil, nil
}