Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphaelGauthier committed Dec 21, 2023
1 parent abffb51 commit 7b55ea6
Show file tree
Hide file tree
Showing 34 changed files with 1,779 additions and 127 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Compliance.JsonDecoder exposing (..)

import Json.Decode exposing (Decoder, float, succeed, map)
import Json.Decode.Pipeline exposing (optional)

import Compliance.DataTypes exposing (..)

decodeComplianceDetails : Decoder ComplianceDetails
decodeComplianceDetails =
succeed ComplianceDetails
|> optional "successNotApplicable" (map Just float) Nothing
|> optional "successAlreadyOK" (map Just float) Nothing
|> optional "successRepaired" (map Just float) Nothing
|> optional "error" (map Just float) Nothing
|> optional "auditCompliant" (map Just float) Nothing
|> optional "auditNonCompliant" (map Just float) Nothing
|> optional "auditError" (map Just float) Nothing
|> optional "auditNotApplicable" (map Just float) Nothing
|> optional "unexpectedUnknownComponent" (map Just float) Nothing
|> optional "unexpectedMissingComponent" (map Just float) Nothing
|> optional "noReport" (map Just float) Nothing
|> optional "reportsDisabled" (map Just float) Nothing
|> optional "applying" (map Just float) Nothing
|> optional "badPolicyMode" (map Just float) Nothing
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ getComplianceStatusTitle id =
"noReport" -> "No report"
_ -> ""

defaultComplianceFilter : ComplianceFilters
defaultComplianceFilter = ComplianceFilters False False []

filterCompliance : ComplianceDetails -> ComplianceFilters -> ComplianceDetails
filterCompliance complianceDetails complianceFilters =
Expand Down Expand Up @@ -376,7 +378,6 @@ filterReportsByCompliance filter = \i ->
|> List.any (filterReports filter)
)


displayComplianceFilters : ComplianceFilters -> (ComplianceFilters -> msg) -> Html msg
displayComplianceFilters complianceFilters updateAction =
( if complianceFilters.showComplianceFilters then
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module ComplianceScore.ApiCalls exposing (..)

import Http exposing (..)
import Url.Builder exposing (QueryParameter)

import ComplianceScore.DataTypes exposing (..)
import ComplianceScore.JsonDecoder exposing (decodeGetComplianceScore, decodeGetScoreDetails)


--
-- This files contains all API calls for the Directive compliance UI
--

getUrl: Model -> List String -> List QueryParameter -> String
getUrl m url p=
Url.Builder.relative (m.contextPath :: "secure" :: "api" :: url) p

getItemScoreUrl : ItemType -> List String
getItemScoreUrl item =
case item of
Node id -> ["nodes" , id.value, "score"]
Rule id -> ["rules" , id.value, "score"]

getComplianceScore : Model -> ItemType -> Cmd Msg
getComplianceScore model itemType =
let
url = (getItemScoreUrl itemType)
req =
request
{ method = "GET"
, headers = []
, url = getUrl model url []
, body = emptyBody
, expect = expectJson GetComplianceScore decodeGetComplianceScore
, timeout = Nothing
, tracker = Nothing
}
in
req

getScoreDetails : Model -> ItemType -> Cmd Msg
getScoreDetails model itemType =
let
url = List.append (getItemScoreUrl itemType) ["details"]
req =
request
{ method = "GET"
, headers = []
, url = getUrl model url []
, body = emptyBody
, expect = expectJson GetScoreDetails decodeGetScoreDetails
, timeout = Nothing
, tracker = Nothing
}
in
req
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
module ComplianceScore.DataTypes exposing (..)

import Http exposing (Error)
--DEBUG
import Json.Decode as D exposing (..)

import NodeCompliance.DataTypes exposing (NodeId)
import Rules.DataTypes exposing (RuleId)
import Compliance.DataTypes exposing (ComplianceDetails)

--
-- All our data types
--

type ScoreValue = A | B | C | D | E | F | X

type alias GlobalComplianceScore =
{ value : ScoreValue -- "A/B/C/D/E/F/-"
, message : String -- "un message en markdown"
, details : List GlobalScoreDetails
}

type alias GlobalScoreDetails =
{ value : ScoreValue -- "A/B/C/D/E/F/-"
, name : String -- "compliance"
, message : String -- "un message en markdown"
}

type alias ComplianceScoreDetails =
{ value : ScoreValue -- "A/B/C/D/E/F/-"
, name : String -- "compliance"
, message : String -- "un message en markdown"
, details : ComplianceDetails
}

type alias SystemUpdatesScoreDetails =
{ value : ScoreValue -- "A/B/C/D/E/F/-"
, name : String -- "system-updates"
, message : String -- "un message en markdown"
, details : SystemUpdatesDetails -- { "updates" : x, "security" : y, ....} // bref ce qui te permet de construire un affichage des updates sur une machine }
}

type alias SystemUpdatesDetails =
{ update : Maybe Int
, enhancement : Maybe Int
, security : Maybe Int
, bugfix : Maybe Int
}

type alias ScoreDetails =
{ compliance : ComplianceScoreDetails
, systemUpdates : Maybe SystemUpdatesScoreDetails
}

type ItemType
= Node NodeId
| Rule RuleId

type alias Model =
{ item : Maybe ItemType
, complianceScore : Maybe GlobalComplianceScore
, scoreDetails : Maybe ScoreDetails
, contextPath : String
}

type Msg
= Ignore
| GetComplianceScore (Result Http.Error GlobalComplianceScore )
| GetScoreDetails (Result Http.Error ScoreDetails)
--DEBUG
| DGetComplianceScore (Result D.Error GlobalComplianceScore )
| DGetScoreDetails (Result D.Error ScoreDetails)
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
port module ComplianceScore.Init exposing (..)

import ComplianceScore.DataTypes exposing (..)
import ComplianceScore.ApiCalls exposing (getComplianceScore, getScoreDetails)

import NodeCompliance.DataTypes exposing (NodeId)
import Rules.DataTypes exposing (RuleId)

--DEBUG
import ComplianceScore.JsonDecoder exposing (..)
import Json.Decode exposing (..)

-- PORTS / SUBSCRIPTIONS
port errorNotification : String -> Cmd msg
--DEBUG
port getScore : (Value -> msg) -> Sub msg
port getDetails : (Value -> msg) -> Sub msg

subscriptions : Model -> Sub Msg
subscriptions _ = Sub.batch
[ getScore (DGetComplianceScore << decodeValue decodeComplianceScore)
, getDetails (DGetScoreDetails << decodeValue decodeScoreDetails)
]

{--
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
--}

init : { item : String, id : String, contextPath : String } -> ( Model, Cmd Msg )
init flags =
let
itemType = case flags.item of
"node" -> Just ( Node (NodeId flags.id) )
"rule" -> Just ( Rule (RuleId flags.id) )
_ -> Nothing

initModel = Model itemType Nothing Nothing flags.contextPath

action = case itemType of
Just iT -> Cmd.batch [ getComplianceScore initModel iT, getScoreDetails initModel iT]
Nothing -> errorNotification ("Cannot get compliance score. Reason : unknown object '" ++ flags.item ++ "'")

in
( initModel
, action
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
module ComplianceScore.JsonDecoder exposing (..)

import Json.Decode exposing (Decoder, andThen, string, int, list, succeed, at, map)
import Json.Decode.Pipeline exposing (required, optional)

import ComplianceScore.DataTypes exposing (..)
import Compliance.JsonDecoder exposing (decodeComplianceDetails)

decodeGetComplianceScore : Decoder GlobalComplianceScore
decodeGetComplianceScore =
at [ "data" ] decodeComplianceScore

decodeComplianceScore : Decoder GlobalComplianceScore
decodeComplianceScore =
succeed GlobalComplianceScore
|> required "value" ( string |> andThen (\s -> toScoreValue s) )
|> required "message" string
|> required "details" (list decodeGlobalScoreDetails)

decodeGlobalScoreDetails : Decoder GlobalScoreDetails
decodeGlobalScoreDetails =
succeed GlobalScoreDetails
|> required "value" ( string |> andThen (\s -> toScoreValue s) )
|> required "name" string
|> required "message" string

decodeGetScoreDetails : Decoder ScoreDetails
decodeGetScoreDetails =
at [ "data" ] decodeScoreDetails

decodeScoreDetails : Decoder ScoreDetails
decodeScoreDetails =
succeed ScoreDetails
|> required "compliance" decodeComplianceScoreDetails
|> optional "system-updates" (map Just decodeSystemUpdatesScoreDetails) Nothing

decodeComplianceScoreDetails : Decoder ComplianceScoreDetails
decodeComplianceScoreDetails =
succeed ComplianceScoreDetails
|> required "value" ( string |> andThen (\s -> toScoreValue s) )
|> required "name" string
|> required "message" string
|> required "details" decodeComplianceDetails

decodeSystemUpdatesScoreDetails : Decoder SystemUpdatesScoreDetails
decodeSystemUpdatesScoreDetails =
succeed SystemUpdatesScoreDetails
|> required "value" ( string |> andThen (\s -> toScoreValue s) )
|> required "name" string
|> required "message" string
|> required "details" decodeSystemUpdatesDetails

decodeSystemUpdatesDetails : Decoder SystemUpdatesDetails
decodeSystemUpdatesDetails =
succeed SystemUpdatesDetails
|> optional "update" (map Just int) Nothing
|> optional "enhancement" (map Just int) Nothing
|> optional "security" (map Just int) Nothing
|> optional "bugfix" (map Just int) Nothing

toScoreValue : String -> Decoder ScoreValue
toScoreValue str =
succeed ( case str of
"A" -> A
"B" -> B
"C" -> C
"D" -> D
"E" -> E
"F" -> F
_ -> X
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
module ComplianceScore.View exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import List
import Html.Lazy
import List.Extra
import Markdown

import ComplianceScore.DataTypes exposing (..)
import NodeCompliance.DataTypes exposing (NodeId)
import Compliance.Utils exposing (buildComplianceBar, defaultComplianceFilter)

view : Model -> Html Msg
view model =
let
scoreLabel : ScoreValue -> String
scoreLabel score =
case score of
A -> "A"
B -> "B"
C -> "C"
D -> "D"
E -> "E"
F -> "F"
X -> "X"

getScoreBadge : ScoreValue -> Bool -> Html Msg
getScoreBadge score smallSize =
let
smallClass = if smallSize then " sm" else ""
in
span [ class ("badge-compliance-score " ++ (scoreLabel score) ++ smallClass) ][]

complianceBar = case model.scoreDetails of
Just score -> buildComplianceBar defaultComplianceFilter score.compliance.details
Nothing -> text ""

scoreBreakdownList : List GlobalScoreDetails -> List (Html Msg)
scoreBreakdownList scoreDetails = scoreDetails
|> List.map(\sD ->
div[class "d-flex flex-column pe-5 align-items-center"]
[ getScoreBadge sD.value True
, label[class "text-center pt-2"][text sD.name]
]
)

in
div[ class "compliance-score d-flex flex-column" ]
( case model.complianceScore of
Just complianceScore ->
[ div[class "global-score d-flex"]
[ div[class "score-badge"]
[ getScoreBadge complianceScore.value False
]
, div[class "score-breakdown ps-5 flex-grow-1 flex-column"]
[ h3[][text "Score breakdown"]
, div[class "d-flex"](scoreBreakdownList complianceScore.details)
]
, div[class "score-explanation ps-3 flex-grow-1"]
( Markdown.toHtml Nothing complianceScore.message )

]
, div[class "score-details mt-4 mb-4"]
[ h3[][text "Score details"]
, div[]
[ label[][text "Compliance"]
, complianceBar
]
, div[]
[ label[][text "System updates"]
]
]
]
Nothing -> [] -- Pas de score de compliance, que faire ? Loading | Message d'erreur
)
Loading

0 comments on commit 7b55ea6

Please sign in to comment.