snapshot of https://github.com/ory/keto.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
153
ketoapi/enc_string.go
Normal file
153
ketoapi/enc_string.go
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package ketoapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/ory/herodot"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func ErrMalformedInput() *herodot.DefaultError {
|
||||
return herodot.ErrBadRequest().WithError("malformed string input")
|
||||
}
|
||||
|
||||
func (r *RelationTuple) String() string {
|
||||
if r == nil {
|
||||
return ""
|
||||
}
|
||||
sb := strings.Builder{}
|
||||
sb.WriteString(r.Namespace)
|
||||
sb.WriteRune(':')
|
||||
sb.WriteString(r.Object)
|
||||
sb.WriteRune('#')
|
||||
sb.WriteString(r.Relation)
|
||||
sb.WriteRune('@')
|
||||
|
||||
if r.SubjectID != nil {
|
||||
sb.WriteString(*r.SubjectID)
|
||||
} else if r.SubjectSet != nil {
|
||||
sb.WriteString(r.SubjectSet.String())
|
||||
} else {
|
||||
sb.WriteString("<ERROR: no subject>")
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (r *RelationTuple) FromString(s string) (*RelationTuple, error) {
|
||||
var (
|
||||
objectAndRelationAndSubject string
|
||||
relationAndSubject string
|
||||
subject string
|
||||
ok bool
|
||||
)
|
||||
if r.Namespace, objectAndRelationAndSubject, ok = strings.Cut(s, ":"); !ok {
|
||||
return nil, errors.WithStack(ErrMalformedInput().WithDebug("expected input to contain ':'"))
|
||||
}
|
||||
|
||||
if r.Object, relationAndSubject, ok = strings.Cut(objectAndRelationAndSubject, "#"); !ok {
|
||||
return nil, errors.WithStack(ErrMalformedInput().WithDebug("expected input to contain '#'"))
|
||||
}
|
||||
|
||||
if r.Relation, subject, ok = strings.Cut(relationAndSubject, "@"); !ok {
|
||||
return nil, errors.WithStack(ErrMalformedInput().WithDebug("expected input to contain '@'"))
|
||||
}
|
||||
|
||||
// remove optional brackets around the subject set
|
||||
subject = strings.Trim(subject, "()")
|
||||
if strings.Contains(subject, ":") {
|
||||
subSet, err := (&SubjectSet{}).FromString(subject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.SubjectSet = subSet
|
||||
} else {
|
||||
r.SubjectID = &subject
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (s *SubjectSet) String() string {
|
||||
if s.Relation == "" {
|
||||
return fmt.Sprintf("%s:%s", s.Namespace, s.Object)
|
||||
}
|
||||
return fmt.Sprintf("%s:%s#%s", s.Namespace, s.Object, s.Relation)
|
||||
}
|
||||
|
||||
func (s *SubjectSet) FromString(str string) (*SubjectSet, error) {
|
||||
// If there is no '#' we have a subject set without a relation, such as
|
||||
// Users:Bob, which just means that the relation is empty.
|
||||
namespaceAndObject, relation, _ := strings.Cut(str, "#")
|
||||
|
||||
namespace, object, ok := strings.Cut(namespaceAndObject, ":")
|
||||
if !ok {
|
||||
return nil, errors.WithStack(ErrMalformedInput().WithDebug("expected subject set to contain ':'"))
|
||||
}
|
||||
|
||||
return &SubjectSet{
|
||||
Namespace: namespace,
|
||||
Object: object,
|
||||
Relation: relation,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t TreeNodeType) String() string {
|
||||
return string(t)
|
||||
}
|
||||
|
||||
func (t *Tree[NodeT]) Label() string {
|
||||
if t == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return t.Tuple.String()
|
||||
}
|
||||
|
||||
func (t *Tree[NodeT]) String() string {
|
||||
if t == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
nodeLabel := t.Label()
|
||||
|
||||
if t.Type == TreeNodeLeaf {
|
||||
return fmt.Sprintf("∋ %s️", nodeLabel)
|
||||
}
|
||||
|
||||
children := make([]string, len(t.Children))
|
||||
for i, c := range t.Children {
|
||||
var indent string
|
||||
if i == len(t.Children)-1 {
|
||||
indent = " "
|
||||
} else {
|
||||
indent = "│ "
|
||||
}
|
||||
children[i] = strings.Join(strings.Split(c.String(), "\n"), "\n"+indent)
|
||||
}
|
||||
|
||||
setOperation := ""
|
||||
switch t.Type {
|
||||
case TreeNodeIntersection:
|
||||
setOperation = "and"
|
||||
case TreeNodeUnion:
|
||||
setOperation = "or"
|
||||
case TreeNodeExclusion:
|
||||
setOperation = `\`
|
||||
case TreeNodeNot:
|
||||
setOperation = `not`
|
||||
case TreeNodeTupleToSubjectSet:
|
||||
setOperation = "┐ tuple to userset"
|
||||
case TreeNodeComputedSubjectSet:
|
||||
setOperation = "┐ computed userset"
|
||||
}
|
||||
|
||||
boxSymbol := "├"
|
||||
if len(children) == 1 {
|
||||
boxSymbol = "└"
|
||||
}
|
||||
return fmt.Sprintf("%s %s\n%s──%s", setOperation, nodeLabel, boxSymbol, strings.Join(children, "\n└──"))
|
||||
}
|
||||
Reference in New Issue
Block a user