entc/gen/privacy: adding decision context support (#462)

Decision context holds a privacy decision (i.e. allow / deny) and if
exists will be returned before any rule is evaluated.

Signed-off-by: Alex Snast <alexsn@fb.com>
This commit is contained in:
Alex Snast
2020-05-05 15:53:15 +03:00
committed by GitHub
parent 51cdda421f
commit 66255ea86e
26 changed files with 615 additions and 16 deletions

View File

@@ -43,6 +43,24 @@ func Skipf(format string, a ...interface{}) error {
return fmt.Errorf(format+": %w", append(a, Skip)...)
}
type decisionCtxKey struct{}
// DecisionContext creates a decision context.
func DecisionContext(parent context.Context, decision error) context.Context {
if decision == nil || errors.Is(decision, Skip) {
return parent
}
return context.WithValue(parent, decisionCtxKey{}, decision)
}
func decisionFromContext(ctx context.Context) (error, bool) {
err, ok := ctx.Value(decisionCtxKey{}).(error)
if ok && errors.Is(err, Allow) {
err = nil
}
return err, ok
}
type (
// QueryPolicy combines multiple query rules into a single policy.
QueryPolicy []QueryRule
@@ -56,6 +74,9 @@ type (
// EvalQuery evaluates a query against a query policy.
func (policy QueryPolicy) EvalQuery(ctx context.Context, q ent.Query) error {
if err, ok := decisionFromContext(ctx); ok {
return err
}
for _, rule := range policy {
switch err := rule.EvalQuery(ctx, q); {
case err == nil || errors.Is(err, Skip):
@@ -90,6 +111,9 @@ type (
// EvalMutation evaluates a mutation against a mutation policy.
func (policy MutationPolicy) EvalMutation(ctx context.Context, m ent.Mutation) error {
if err, ok := decisionFromContext(ctx); ok {
return err
}
for _, rule := range policy {
switch err := rule.EvalMutation(ctx, m); {
case err == nil || errors.Is(err, Skip):