Skip to content

Commit

Permalink
Merge pull request #156 from aml-org/publish-1.6.0
Browse files Browse the repository at this point in the history
publish 1.6.0
  • Loading branch information
arielmirra authored Dec 6, 2023
2 parents 9db1678 + 2a37c8f commit 97edf7d
Show file tree
Hide file tree
Showing 119 changed files with 3,475 additions and 405 deletions.
1 change: 1 addition & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ pipeline {
anyOf {
branch 'develop'
branch 'master'
branch 'release/*'
}
}
agent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,9 @@ violation[matches] {

common_tags = operation_tags & top_level_tags
gen_rego_result_2 = (count(common_tags) == count(top_level_tags))


message = "Operation tags should be defined in global tags."
gen_rego_result_2 != true
_result_0 := trace("rego","",x,{"@type": ["reportSchema:TraceValueNode", "validation:TraceValue"], "negated":false})
matches := error("example15",x,"Operation tags should be defined in global tags.",[_result_0])
matches := error("example15",x,message,[_result_0])
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ violation:
- example15
validations:
example15:
message: Operation tags should be defined in global tags.
targetClass: apiContract.WebAPI
rego: |
o1 = collect with data.nodes as [$node] with data.property as "http://a.ml/vocabularies/apiContract#tag"
Expand All @@ -16,5 +15,6 @@ validations:
p3 = collect with data.nodes as p2 with data.property as "http://a.ml/vocabularies/apiContract#tag"
operation_tags = collect_values with data.nodes as p3 with data.property as "http://a.ml/vocabularies/core#name"
$message = "Operation tags should be defined in global tags."
common_tags = operation_tags & top_level_tags
$result = (count(common_tags) == count(top_level_tags))
4 changes: 3 additions & 1 deletion docs/validation_tutorial/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2013,6 +2013,8 @@ in the `$result` variable.

The code must contain a validation that holds true for all nodes in the spec being selected by the validation containing the Rego rule.

Optionally, the validation message can also be set in Rego code assigning a string (or a function that resolves to a string) to the `$message` variable.

The following profile writes a simple rule to check that the tags defined in an OAS API are being used in all the
operations in the API:

Expand All @@ -2025,7 +2027,6 @@ violation:
- example15
validations:
example15:
message: Operation tags should be defined in global tags.
targetClass: apiContract.WebAPI
rego: |
o1 = collect with data.nodes as [$node] with data.property as "http://a.ml/vocabularies/apiContract#tag"
Expand All @@ -2036,6 +2037,7 @@ validations:
p3 = collect with data.nodes as p2 with data.property as "http://a.ml/vocabularies/apiContract#tag"
operation_tags = collect_values with data.nodes as p3 with data.property as "http://a.ml/vocabularies/core#name"
$message = "Operation tags should be defined in global tags."
common_tags = operation_tags & top_level_tags
$result = (count(common_tags) == count(top_level_tags))
```
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/mna/pigeon v1.2.1 h1:m5FxEbGdQxLaiHF+QurbWUAjmRqd5cstjIPN89svYgg=
github.com/mna/pigeon v1.2.1/go.mod h1:BUZAoRldTdU7Ac3WYkXy8hzIHfCgj1doJxGjlB+AbLI=
github.com/open-policy-agent/opa v0.47.0 h1:d6g0oDNLraIcWl9LXW8cBzRYf2zt7vSbPGEd2+8K3Lg=
github.com/open-policy-agent/opa v0.47.0/go.mod h1:cM7ngEoEdAIfyu9mOHaVcgLAHYkY6amrYfotm+BSkYQ=
github.com/piprate/json-gold v0.4.0 h1:XQ6ZMLCjuXhtvqr60IrGl2uNYojl64B/dIUmI2iqThs=
Expand Down
36 changes: 22 additions & 14 deletions internal/generator/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ func wrapTopLevelRegoResult(e profile.TopLevelExpression, results []GeneratedReg
func wrapBranch(name string, message profile.Message, branch BranchRegoResult, matchesVariable string, mappingVariable string, iriExpander *misc.IriExpander) []string {
var acc []string
resultBindings := make([]string, 0)
customMessage := false

for i, r := range branch.Branch {
bindingResult := fmt.Sprintf("_result_%d", i)
Expand All @@ -216,26 +217,33 @@ func wrapBranch(name string, message profile.Message, branch BranchRegoResult, m
}
matchesLine := fmt.Sprintf(" %s := trace(\"%s\",\"%s\",%s,%s)", bindingResult, r.ConstraintId(), traceResultPath, r.TraceNode, r.TraceValue)
for _, l := range r.Rego {
if strings.Contains(l, "$message") {
customMessage = true
l = strings.ReplaceAll(l, "$message", "message")
}
acc = append(acc, " "+l)
}
acc = append(acc, matchesLine)
}

// Generate message
vars := make([]string, 0)
for varIdx, compactPath := range message.Variables {
expandedPath, _ := iriExpander.Expand(compactPath)
// if not defined in custom rego, generate message from the message key in the profile yaml
if !customMessage {
vars := make([]string, 0)
for varIdx, compactPath := range message.Variables {
expandedPath, _ := iriExpander.Expand(compactPath)

// set variable
varName := fmt.Sprintf("msg_var_%d", varIdx)
acc = append(acc, fmt.Sprintf(" %s := object.get(%s, \"%s\", \"null\")", varName, mappingVariable, expandedPath))
vars = append(vars, varName)
}
if len(vars) > 0 {
acc = append(acc, fmt.Sprintf(" message_vars := [%s]", strings.Join(vars, ",")))
acc = append(acc, fmt.Sprintf(" message := sprintf(\"%s\", message_vars)", sanitizedMessage(message.Expression)))
} else {
acc = append(acc, fmt.Sprintf(" message := \"%s\"", sanitizedMessage(message.Expression)))
// set variable
varName := fmt.Sprintf("msg_var_%d", varIdx)
acc = append(acc, fmt.Sprintf(" %s := object.get(%s, \"%s\", \"null\")", varName, mappingVariable, expandedPath))
vars = append(vars, varName)
}

if len(vars) > 0 {
acc = append(acc, fmt.Sprintf(" message_vars := [%s]", strings.Join(vars, ",")))
acc = append(acc, fmt.Sprintf(" message := sprintf(\"%s\", message_vars)", sanitizedMessage(message.Expression)))
} else {
acc = append(acc, fmt.Sprintf(" message := \"%s\"", sanitizedMessage(message.Expression)))
}
}

acc = append(acc, fmt.Sprintf(" %s := error(\"%s\",%s, message ,[%s])", matchesVariable, name, mappingVariable, strings.Join(resultBindings, ",")))
Expand Down
7 changes: 3 additions & 4 deletions internal/misc/iri_expander.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type IriExpander struct {

func (i *IriExpander) Expand(iri string) (string, error) {
isReservedKeyword := strings.HasPrefix(iri, "@")
compactForm := regexp.MustCompile("^[a-zA-Z-0-9\\-]+\\.[a-zA-Z-0-9\\-]+$")
compactForm := regexp.MustCompile("^[a-zA-Z-0-9\\-]+\\.[\\.(\\\\/)a-zA-Z-0-9\\-]+$")
isCompact := compactForm.MatchString(iri)

if isCompact {
Expand All @@ -28,10 +28,9 @@ func (i *IriExpander) Expand(iri string) (string, error) {
}

func (i *IriExpander) expandCompactIri(iri string) (string, error) {
split := strings.Split(iri, ".")
split := strings.SplitN(iri, ".", 2)
prefix := split[0]
suffix := split[1]

suffix := strings.ReplaceAll(split[1], "\\/", "/")
switch e := i.Context[prefix].(type) {
case string:
return e + suffix, nil
Expand Down
19 changes: 19 additions & 0 deletions internal/parser/path/expand_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,25 @@ func TestANDExpanded(t *testing.T) {
testExpandedPath(source, expected, t)
}

func TestManagementExpanded(t *testing.T) {
source := "management.labels"
expected := "http://anypoint.com/vocabs/management#labels"
testExpandedPath(source, expected, t)
}


func TestDOTExpanded(t *testing.T) {
source := "management.mulesoft.com"
expected := "http://anypoint.com/vocabs/management#mulesoft.com"
testExpandedPath(source, expected, t)
}

func TestSlashExpanded(t *testing.T) {
source := "management.mulesoft.com\\/apiinstance-id"
expected := "http://anypoint.com/vocabs/management#mulesoft.com/apiinstance-id"
testExpandedPath(source, expected, t)
}

func TestORExpanded(t *testing.T) {
source := "shacl.schema | core.name"
expected := "http://www.w3.org/ns/shacl#schema | http://a.ml/vocabularies/core#name"
Expand Down
Loading

0 comments on commit 97edf7d

Please sign in to comment.