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

This commit is contained in:
upstream-mirror
2026-09-16 01:08:34 +05:00
commit 9456a4e922
2560 changed files with 120911 additions and 0 deletions

130
schema/typechecks.go Normal file
View File

@@ -0,0 +1,130 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package schema
import "github.com/ory/keto/internal/namespace/ast"
type (
namespaceQuery []namespace
relationQuery []ast.Relation
typeCheck func(p *parser)
)
func (p *parser) query() namespaceQuery {
return p.namespaces
}
func (ns namespaceQuery) find(name string) (*namespace, bool) {
for _, n := range ns {
if n.Name == name {
return &n, true
}
}
return nil, false
}
func (ns namespaceQuery) findRelation(namespace, relation string) (*ast.Relation, bool) {
n, ok := ns.find(namespace)
if !ok {
return nil, false
}
return relationQuery(n.Relations).find(relation)
}
func (rs relationQuery) find(name string) (*ast.Relation, bool) {
for _, r := range rs {
if r.Name == name {
return &r, true
}
}
return nil, false
}
func (p *parser) typeCheck() {
for _, check := range p.checks {
check(p)
}
}
func (p *parser) addCheck(check typeCheck) {
p.checks = append(p.checks, check)
}
// checkNamespace checks that the there exists a namespace with the given name.
func checkNamespaceExists(namespace item) typeCheck {
return func(p *parser) {
if _, ok := namespaceQuery(p.namespaces).find(namespace.Val); ok {
return
}
p.addErr(namespace, "namespace %q was not declared", namespace.Val)
}
}
// checkNamespaceHasRelation checks that 1. there exists the given namespace,
// and 2. that there exists the given relation in that namespace.
func checkNamespaceHasRelation(namespace, relation item) typeCheck {
return func(p *parser) {
if n, ok := namespaceQuery(p.namespaces).find(namespace.Val); ok {
if _, ok := relationQuery(n.Relations).find(relation.Val); ok {
return
}
p.addErr(relation,
"namespace %q did not declare relation %q",
namespace.Val, relation.Val)
return
}
p.addErr(namespace, "namespace %q was not declared", namespace.Val)
}
}
// checkCurrentNamespaceHasRelation checks that the give relation exists in the
// current namespace.
func checkCurrentNamespaceHasRelation(current *namespace, relation item) typeCheck {
namespace := current.Name
return func(p *parser) {
if n, ok := namespaceQuery(p.namespaces).find(namespace); ok {
if _, ok := relationQuery(n.Relations).find(relation.Val); ok {
return
}
p.addErr(relation,
"namespace %q did not declare relation %q",
namespace, relation.Val)
return
}
p.addErr(relation, "namespace %q was not declared", namespace)
}
}
func checkAllRelationsTypesHaveRelation(current *namespace, relationType item, relation string) typeCheck {
namespace := current.Name
return func(p *parser) {
recursiveCheckAllRelationsTypesHaveRelation(p, relationType, namespace, relationType.Val, relation, tupleToSubjectSetTypeCheckMaxDepth)
}
}
func recursiveCheckAllRelationsTypesHaveRelation(p *parser, item item, namespace string, relationType string, relation string, depth int) {
if depth < 0 {
p.addErr(item, "could not typecheck deeply nested SubjectSet further")
return
}
r, ok := namespaceQuery(p.namespaces).findRelation(namespace, relationType)
if !ok {
p.addErr(item, "relation %q was not declared in namespace %q",
relationType, namespace)
return
}
for _, t := range r.Types {
if t.Relation == "" {
if _, ok := p.query().findRelation(t.Namespace, relation); !ok {
p.addErr(item, "relation %q was not declared in namespace %q",
relation, t.Namespace)
}
} else {
// Type is a subject set, we need to recursively check if the type has
// the required relation.
recursiveCheckAllRelationsTypesHaveRelation(
p, item, t.Namespace, t.Relation, relation, depth-1)
}
}
}