mirror of
https://github.com/ent/ent.git
synced 2026-05-28 09:49:08 +03:00
ent/privacy: initial privacy package (#836)
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -10,22 +10,26 @@ in the LICENSE file in the root directory of this source tree.
|
||||
{{ template "header" . }}
|
||||
{{ end }}
|
||||
|
||||
import "{{ $.Config.Package }}"
|
||||
import (
|
||||
"{{ $.Config.Package }}"
|
||||
|
||||
"github.com/facebook/ent/privacy"
|
||||
)
|
||||
|
||||
{{ $pkg := base $.Config.Package }}
|
||||
|
||||
var (
|
||||
// Allow may be returned by rules to indicate that the policy
|
||||
// evaluation should terminate with an allow decision.
|
||||
Allow = errors.New("ent/privacy: allow rule")
|
||||
Allow = privacy.Allow
|
||||
|
||||
// Deny may be returned by rules to indicate that the policy
|
||||
// evaluation should terminate with an deny decision.
|
||||
Deny = errors.New("ent/privacy: deny rule")
|
||||
Deny = privacy.Deny
|
||||
|
||||
// Skip may be returned by rules to indicate that the policy
|
||||
// evaluation should continue to the next rule.
|
||||
Skip = errors.New("ent/privacy: skip rule")
|
||||
Skip = privacy.Skip
|
||||
)
|
||||
|
||||
{{- range $decision := list "Allow" "Deny" "Skip" }}
|
||||
@@ -35,52 +39,25 @@ var (
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
type decisionCtxKey struct {}
|
||||
|
||||
// DecisionContext creates a decision context.
|
||||
// DecisionContext creates a new context from the given parent context with
|
||||
// a policy decision attach to it.
|
||||
func DecisionContext(parent context.Context, decision error) context.Context {
|
||||
if decision == nil || errors.Is(decision, Skip) {
|
||||
return parent
|
||||
}
|
||||
return context.WithValue(parent, decisionCtxKey{}, decision)
|
||||
return privacy.DecisionContext(parent, decision)
|
||||
}
|
||||
|
||||
func decisionFromContext(ctx context.Context) (error, bool) {
|
||||
decision, ok := ctx.Value(decisionCtxKey{}).(error)
|
||||
if ok && errors.Is(decision, Allow) {
|
||||
decision = nil
|
||||
}
|
||||
return decision, ok
|
||||
// DecisionFromContext retrieves the policy decision from the context.
|
||||
func DecisionFromContext(ctx context.Context) (error, bool) {
|
||||
return privacy.DecisionFromContext(ctx)
|
||||
}
|
||||
|
||||
type (
|
||||
// QueryPolicy combines multiple query rules into a single policy.
|
||||
QueryPolicy []QueryRule
|
||||
|
||||
// QueryRule defines the interface deciding whether a
|
||||
// query is allowed and optionally modify it.
|
||||
QueryRule interface {
|
||||
EvalQuery(context.Context, {{ $pkg }}.Query) error
|
||||
}
|
||||
QueryRule = privacy.QueryRule
|
||||
// QueryPolicy combines multiple query rules into a single policy.
|
||||
QueryPolicy = privacy.QueryPolicy
|
||||
)
|
||||
|
||||
// EvalQuery evaluates a query against a query policy.
|
||||
func (policy QueryPolicy) EvalQuery(ctx context.Context, q {{ $pkg }}.Query) error {
|
||||
if decision, ok := decisionFromContext(ctx); ok {
|
||||
return decision
|
||||
}
|
||||
for _, rule := range policy {
|
||||
switch decision := rule.EvalQuery(ctx, q); {
|
||||
case decision == nil || errors.Is(decision, Skip):
|
||||
case errors.Is(decision, Allow):
|
||||
return nil
|
||||
default:
|
||||
return decision
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// QueryRuleFunc type is an adapter to allow the use of
|
||||
// ordinary functions as query rules.
|
||||
type QueryRuleFunc func(context.Context, {{ $pkg }}.Query) error
|
||||
@@ -91,32 +68,13 @@ func (f QueryRuleFunc) EvalQuery(ctx context.Context, q {{ $pkg }}.Query) error
|
||||
}
|
||||
|
||||
type (
|
||||
// MutationPolicy combines multiple mutation rules into a single policy.
|
||||
MutationPolicy []MutationRule
|
||||
|
||||
// MutationRule defines the interface deciding whether a
|
||||
// mutation is allowed and optionally modify it.
|
||||
MutationRule interface {
|
||||
EvalMutation(context.Context, {{ $pkg }}.Mutation) error
|
||||
}
|
||||
MutationRule = privacy.MutationRule
|
||||
// MutationPolicy combines multiple mutation rules into a single policy.
|
||||
MutationPolicy = privacy.MutationPolicy
|
||||
)
|
||||
|
||||
// EvalMutation evaluates a mutation against a mutation policy.
|
||||
func (policy MutationPolicy) EvalMutation(ctx context.Context, m {{ $pkg }}.Mutation) error {
|
||||
if decision, ok := decisionFromContext(ctx); ok {
|
||||
return decision
|
||||
}
|
||||
for _, rule := range policy {
|
||||
switch decision := rule.EvalMutation(ctx, m); {
|
||||
case decision == nil || errors.Is(decision, Skip):
|
||||
case errors.Is(decision, Allow):
|
||||
return nil
|
||||
default:
|
||||
return decision
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MutationRuleFunc type is an adapter to allow the use of
|
||||
// ordinary functions as mutation rules.
|
||||
|
||||
@@ -76,6 +76,7 @@ import (
|
||||
{{- end }}
|
||||
|
||||
"github.com/facebook/ent"
|
||||
"github.com/facebook/ent/privacy"
|
||||
)
|
||||
|
||||
|
||||
@@ -91,7 +92,7 @@ func init() {
|
||||
{{- end }}
|
||||
{{- with $policies := $n.PolicyPositions }}
|
||||
{{- /* policies defined in schema and mixins. */}}
|
||||
{{ $pkg }}.Policy = newPolicy({{ range $idx := $n.MixedInPolicies }}{{ $pkg }}Mixin[{{ $idx }}],{{ end }}{{ $schema }}.{{ $n.Name }}{})
|
||||
{{ $pkg }}.Policy = privacy.NewPolicies({{ range $idx := $n.MixedInPolicies }}{{ $pkg }}Mixin[{{ $idx }}],{{ end }}{{ $schema }}.{{ $n.Name }}{})
|
||||
{{ $pkg }}.Hooks[0] = func(next ent.Mutator) ent.Mutator {
|
||||
return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if err := {{ $pkg }}.Policy.EvalMutation(ctx, m); err != nil {
|
||||
@@ -190,39 +191,4 @@ func init() {
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{ $hasPolicy := false }}{{ range $n := $.Nodes }}{{ if $n.NumPolicy }}{{ $hasPolicy = true }}{{ end }}{{ end }}
|
||||
{{ if $hasPolicy }}
|
||||
type policies []ent.Policy
|
||||
|
||||
// newPolicy creates a policy from list of mixin and ent.Schema.
|
||||
func newPolicy(ps ...interface{ Policy() ent.Policy }) ent.Policy {
|
||||
pocs := make(policies, 0, len(ps))
|
||||
for _, p := range ps {
|
||||
if policy := p.Policy(); policy != nil {
|
||||
pocs = append(pocs, policy)
|
||||
}
|
||||
}
|
||||
return pocs
|
||||
}
|
||||
|
||||
func (p policies) EvalMutation(ctx context.Context, m ent.Mutation) error {
|
||||
for i := range p {
|
||||
if err := p[i].EvalMutation(ctx, m); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p policies) EvalQuery(ctx context.Context, q ent.Query) error {
|
||||
for i := range p {
|
||||
if err := p[i].EvalQuery(ctx, q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
|
||||
Reference in New Issue
Block a user