Skip to content

Commit 79f8dd3

Browse files
committed
feat: Extend rule engine to include missing checks when the resource does not exist
1 parent 887c514 commit 79f8dd3

File tree

7 files changed

+40
-10
lines changed

7 files changed

+40
-10
lines changed

src/rules-engine/data-processors/dgraph-data-processor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ export default class DgraphDataProcessor implements DataProcessor {
145145

146146
private prepareEntitiesMutations(findings: RuleFinding[]): RuleFinding[] {
147147
// Group Findings by schema type
148-
const { manual: manualData = [], ...processedRules } = groupBy(
148+
const { manual: manualData = [], missing: missingData = [], ...processedRules } = groupBy(
149149
findings,
150150
'typename'
151151
)
152152

153-
const mutations = [...manualData]
153+
const mutations = [...manualData, ...missingData]
154154
for (const findingType in processedRules) {
155155
if (!isEmpty(findingType)) {
156156
// Group Findings by resource
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import cuid from 'cuid'
2+
import { ResourceData, Result, Rule, RuleFinding } from '../types'
3+
import { RuleEvaluator } from './rule-evaluator'
4+
5+
export default abstract class BaseEvaluator<K extends Rule> implements RuleEvaluator<K>
6+
{
7+
abstract canEvaluate(rule: K): boolean
8+
9+
abstract evaluateSingleResource(rule: K, data?: ResourceData): Promise<RuleFinding>
10+
11+
async evaluateMissingResource({ id, severity, resource }: K): Promise<RuleFinding> {
12+
return {
13+
id: `${id}/missing/${cuid()}`,
14+
resourceId: resource?.replace('[*]', ''),
15+
result: Result.MISSING,
16+
typename: 'missing',
17+
rule: {
18+
id,
19+
severity,
20+
},
21+
} as RuleFinding
22+
}
23+
}

src/rules-engine/evaluators/js-evaluator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import {
66
RuleFinding,
77
Result,
88
} from '../types'
9-
import { RuleEvaluator } from './rule-evaluator'
9+
import BaseEvaluator from './base-evaluator'
1010

11-
export default class JsEvaluator implements RuleEvaluator<JsRule> {
11+
export default class JsEvaluator extends BaseEvaluator<JsRule> {
1212
canEvaluate(rule: Rule | JsRule): boolean {
1313
return 'check' in rule
1414
}

src/rules-engine/evaluators/json-evaluator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import {
1212
} from '../types'
1313
import AdditionalOperators from '../operators'
1414
import ComparisonOperators from '../operators/comparison'
15-
import { RuleEvaluator } from './rule-evaluator'
15+
import BaseEvaluator from './base-evaluator'
1616

17-
export default class JsonEvaluator implements RuleEvaluator<JsonRule> {
17+
export default class JsonEvaluator extends BaseEvaluator<JsonRule> {
1818
canEvaluate(rule: JsonRule): boolean {
1919
return 'conditions' in rule
2020
}

src/rules-engine/evaluators/manual-evaluator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { JsonRule, Result, Rule, RuleFinding } from '../types'
2-
import { RuleEvaluator } from './rule-evaluator'
2+
import BaseEvaluator from './base-evaluator'
33

4-
export default class ManualEvaluator implements RuleEvaluator<JsonRule> {
4+
export default class ManualEvaluator extends BaseEvaluator<JsonRule> {
55
canEvaluate(rule: Rule): boolean {
66
return !('gql' in rule) && !('conditions' in rule) && !('resource' in rule)
77
}

src/rules-engine/evaluators/rule-evaluator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ import { ResourceData, Rule, RuleFinding } from '../types'
33
export interface RuleEvaluator<K extends Rule> {
44
canEvaluate: (rule: K) => boolean
55
evaluateSingleResource: (rule: K, data?: ResourceData) => Promise<RuleFinding>
6+
evaluateMissingResource: (rule: K) => Promise<RuleFinding>
67
}

src/rules-engine/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,20 @@ export default class RulesProvider implements Engine {
9191
const resourcePaths = data ? jsonpath.nodes(data, rule.resource) : []
9292
const evaluator = this.getRuleEvaluator(rule)
9393

94+
if (!evaluator) {
95+
return []
96+
}
97+
9498
if (isEmpty(data) && evaluator instanceof ManualEvaluator) {
9599
// Returned Manual Rule Response
96100
res.push(await evaluator.evaluateSingleResource(rule))
97101
return res
98102
}
99103

100-
if (!evaluator) {
101-
return []
104+
if (isEmpty(resourcePaths)) {
105+
// Returned Missing Resource Rule Response
106+
res.push(await evaluator.evaluateMissingResource(rule))
107+
return res
102108
}
103109

104110
// @NOTE: here we can evaluate things such as Data being empty (may imply rule to pass)

0 commit comments

Comments
 (0)