Files
ucan/pkg/policy/policy.go

179 lines
4.5 KiB
Go
Raw Normal View History

2024-08-19 23:16:36 +02:00
package policy
// https://github.com/ucan-wg/delegation/blob/4094d5878b58f5d35055a3b93fccda0b8329ebae/README.md#policy
import (
"fmt"
"strings"
2024-08-20 15:55:04 +02:00
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/codec/dagjson"
2024-09-24 11:40:28 -04:00
"github.com/ucan-wg/go-ucan/pkg/policy/selector"
2024-08-19 23:16:36 +02:00
)
const (
KindEqual = "==" // implemented by equality
KindGreaterThan = ">" // implemented by equality
KindGreaterThanOrEqual = ">=" // implemented by equality
KindLessThan = "<" // implemented by equality
KindLessThanOrEqual = "<=" // implemented by equality
KindNot = "not" // implemented by negation
KindAnd = "and" // implemented by connective
KindOr = "or" // implemented by connective
KindLike = "like" // implemented by wildcard
KindAll = "all" // implemented by quantifier
KindAny = "any" // implemented by quantifier
2024-08-19 23:16:36 +02:00
)
2024-09-01 20:27:54 +02:00
type Policy []Statement
2024-08-19 23:16:36 +02:00
func (p Policy) String() string {
if len(p) == 0 {
return "[]"
}
childs := make([]string, len(p))
for i, statement := range p {
childs[i] = strings.ReplaceAll(statement.String(), "\n", "\n ")
}
return fmt.Sprintf("[\n %s\n]", strings.Join(childs, ",\n "))
}
2024-08-19 23:16:36 +02:00
type Statement interface {
Kind() string
String() string
2024-08-19 23:16:36 +02:00
}
type equality struct {
kind string
selector selector.Selector
2024-08-20 15:55:04 +02:00
value ipld.Node
2024-08-19 23:16:36 +02:00
}
func (e equality) Kind() string {
return e.kind
}
func (e equality) String() string {
child, err := ipld.Encode(e.value, dagjson.Encode)
if err != nil {
return "ERROR: INVALID VALUE"
}
return fmt.Sprintf(`["%s", "%s", %s]`, e.kind, e.selector, strings.ReplaceAll(string(child), "\n", "\n "))
}
func Equal(selector selector.Selector, value ipld.Node) Statement {
return equality{kind: KindEqual, selector: selector, value: value}
2024-08-19 23:16:36 +02:00
}
func GreaterThan(selector selector.Selector, value ipld.Node) Statement {
return equality{kind: KindGreaterThan, selector: selector, value: value}
2024-08-19 23:16:36 +02:00
}
func GreaterThanOrEqual(selector selector.Selector, value ipld.Node) Statement {
return equality{kind: KindGreaterThanOrEqual, selector: selector, value: value}
2024-08-19 23:16:36 +02:00
}
func LessThan(selector selector.Selector, value ipld.Node) Statement {
return equality{kind: KindLessThan, selector: selector, value: value}
2024-08-19 23:16:36 +02:00
}
func LessThanOrEqual(selector selector.Selector, value ipld.Node) Statement {
return equality{kind: KindLessThanOrEqual, selector: selector, value: value}
2024-08-19 23:16:36 +02:00
}
type negation struct {
statement Statement
}
func (n negation) Kind() string {
return KindNot
2024-08-19 23:16:36 +02:00
}
func (n negation) String() string {
child := n.statement.String()
return fmt.Sprintf(`["%s", "%s"]`, n.Kind(), strings.ReplaceAll(child, "\n", "\n "))
}
func Not(stmt Statement) Statement {
return negation{statement: stmt}
2024-08-19 23:16:36 +02:00
}
2024-09-01 20:27:54 +02:00
type connective struct {
kind string
2024-08-19 23:16:36 +02:00
statements []Statement
}
2024-09-01 20:27:54 +02:00
func (c connective) Kind() string {
return c.kind
2024-08-19 23:16:36 +02:00
}
func (c connective) String() string {
childs := make([]string, len(c.statements))
for i, statement := range c.statements {
childs[i] = strings.ReplaceAll(statement.String(), "\n", "\n ")
}
return fmt.Sprintf("[\"%s\", [\n %s]]\n", c.kind, strings.Join(childs, ",\n "))
}
func And(stmts ...Statement) Statement {
return connective{kind: KindAnd, statements: stmts}
2024-08-19 23:16:36 +02:00
}
func Or(stmts ...Statement) Statement {
return connective{kind: KindOr, statements: stmts}
2024-08-19 23:16:36 +02:00
}
type wildcard struct {
selector selector.Selector
pattern glob
2024-08-19 23:16:36 +02:00
}
func (n wildcard) Kind() string {
return KindLike
2024-08-19 23:16:36 +02:00
}
func (n wildcard) String() string {
return fmt.Sprintf(`["%s", "%s", "%s"]`, n.Kind(), n.selector, n.pattern)
}
func Like(selector selector.Selector, pattern string) (Statement, error) {
g, err := parseGlob(pattern)
2024-09-17 14:15:36 +02:00
if err != nil {
return nil, err
}
return wildcard{selector: selector, pattern: g}, nil
2024-08-19 23:16:36 +02:00
}
func MustLike(selector selector.Selector, pattern string) Statement {
g, err := Like(selector, pattern)
if err != nil {
panic(err)
}
return g
}
2024-08-19 23:16:36 +02:00
type quantifier struct {
kind string
selector selector.Selector
statement Statement
2024-08-19 23:16:36 +02:00
}
func (n quantifier) Kind() string {
return n.kind
}
func (n quantifier) String() string {
child := n.statement.String()
return fmt.Sprintf("[\"%s\", \"%s\",\n %s]", n.Kind(), n.selector, strings.ReplaceAll(child, "\n", "\n "))
}
func All(selector selector.Selector, statement Statement) Statement {
return quantifier{kind: KindAll, selector: selector, statement: statement}
2024-08-19 23:16:36 +02:00
}
func Any(selector selector.Selector, statement Statement) Statement {
return quantifier{kind: KindAny, selector: selector, statement: statement}
2024-08-19 23:16:36 +02:00
}