diff --git a/explorer/impact.go b/explorer/impact.go index 1e160a69df..cb2b2efb5d 100644 --- a/explorer/impact.go +++ b/explorer/impact.go @@ -11,6 +11,15 @@ import ( "gopkg.in/yaml.v3" ) +// Impact represents severity rating scale when impact is provided as human-readable string value +var impactMapping = map[string]int32{ + "none": 0, + "low": 20, + "medium": 55, + "high": 80, + "critical": 95, +} + func (v *Impact) HumanReadable() string { if v.Value == nil { return "unknown" @@ -22,10 +31,10 @@ func (v *Impact) HumanReadable() string { return "high" case v.Value.Value >= 40: return "medium" - case v.Value.Value > 0: + case v.Value.Value >= 10: return "low" default: - return "info" + return "none" } } @@ -65,10 +74,12 @@ func (v *Impact) Checksum() uint64 { return uint64(res) } +// UnmarshalJSON implements the json.Unmarshaler interface for impact value. It supports human-readable string, int and +// complex struct. func (v *Impact) UnmarshalJSON(data []byte) error { - var res int32 - if err := json.Unmarshal(data, &res); err == nil { - v.Value = &ImpactValue{Value: res} + var intRes int32 + if err := json.Unmarshal(data, &intRes); err == nil { + v.Value = &ImpactValue{Value: intRes} if v.Value.Value < 0 || v.Value.Value > 100 { return errors.New("impact must be between 0 and 100") @@ -76,6 +87,16 @@ func (v *Impact) UnmarshalJSON(data []byte) error { return nil } + var stringRes string + if err := json.Unmarshal(data, &stringRes); err == nil { + val, ok := impactMapping[stringRes] + if !ok { + return errors.New("impact must use critical, high, medium, low or none") + } + v.Value = &ImpactValue{Value: val} + return nil + } + type tmp Impact return json.Unmarshal(data, (*tmp)(v)) } diff --git a/explorer/impact_test.go b/explorer/impact_test.go index 5f11f908de..212efacd87 100644 --- a/explorer/impact_test.go +++ b/explorer/impact_test.go @@ -34,6 +34,20 @@ func TestImpactParsing(t *testing.T) { Value: &ImpactValue{Value: 40}, }, }, + { + "critical rating", + `"critical"`, + &Impact{ + Value: &ImpactValue{Value: 95}, + }, + }, + { + "low rating", + `"low"`, + &Impact{ + Value: &ImpactValue{Value: 20}, + }, + }, } for i := range tests { @@ -71,6 +85,11 @@ func TestImpactParsing(t *testing.T) { `{"value": 101, "weight": 90}`, "impact must be between 0 and 100", }, + { + "invalid string value", + `"mycustomcritical"`, + "impact must use critical, high, medium, low or none", + }, } for i := range errTests {