1
0
mirror of https://github.com/strongdm/comply synced 2024-11-17 05:14:55 +00:00
comply/internal/render/controller.go

169 lines
3.6 KiB
Go
Raw Normal View History

2018-05-15 21:13:11 +00:00
package render
import (
"fmt"
"sort"
"time"
"html/template"
2018-05-15 21:13:11 +00:00
"github.com/pkg/errors"
2018-05-15 21:13:11 +00:00
"github.com/strongdm/comply/internal/config"
"github.com/strongdm/comply/internal/model"
"github.com/russross/blackfriday/v2"
2018-05-15 21:13:11 +00:00
)
type project struct {
OrganizationName string
Name string
}
type stats struct {
CriteriaTotal int
CriteriaSatisfied int
2018-05-15 21:13:11 +00:00
ProcedureTotal int
ProcedureOpen int
ProcedureOldestDays int
AuditOpen int
AuditClosed int
AuditTotal int
}
type renderData struct {
// duplicates Project.OrganizationName
Name string
Project *project
Stats *stats
Narratives []*model.Document
Policies []*model.Document
Controls []*model.Control
Procedures []*model.Procedure
2020-09-15 19:52:22 +00:00
Frameworks []*model.Framework
Tickets []*model.Ticket
Criteria []*criterion
Links *model.TicketLinks
2018-05-15 21:13:11 +00:00
}
type criterion struct {
2020-09-15 19:52:22 +00:00
Framework string
CriteriaKey string
2018-05-15 21:13:11 +00:00
Name string
Description string
Satisfied bool
SatisfiedBy []string
}
func load() (*model.Data, *renderData, error) {
modelData, err := model.ReadData()
if err != nil {
return nil, nil, err
}
cfg := config.Config()
project := &project{
OrganizationName: cfg.Name,
Name: fmt.Sprintf("%s Compliance Program", cfg.Name),
}
satisfied := model.CriteriaSatisfied(modelData)
criteria := make([]*criterion, 0)
2020-09-15 19:52:22 +00:00
for _, framework := range modelData.Frameworks {
for key, c := range framework.Criteria{
2018-05-15 21:13:11 +00:00
satisfactions, ok := satisfied[key]
satisfied := ok && len(satisfactions) > 0
criteria = append(criteria, &criterion{
2020-09-15 19:52:22 +00:00
Framework: framework.Name,
CriteriaKey: key,
2018-05-15 21:13:11 +00:00
Name: c.Name,
Description: c.Description,
Satisfied: satisfied,
SatisfiedBy: satisfactions,
})
}
}
sort.Slice(criteria, func(i, j int) bool {
return criteria[i].CriteriaKey < criteria[j].CriteriaKey
2018-05-15 21:13:11 +00:00
})
rd := &renderData{}
rd.Narratives = modelData.Narratives
rd.Policies = modelData.Policies
rd.Controls = modelData.Controls
2018-05-15 21:13:11 +00:00
rd.Procedures = modelData.Procedures
2020-09-15 19:52:22 +00:00
rd.Frameworks = modelData.Frameworks
2018-05-15 21:13:11 +00:00
rd.Tickets = modelData.Tickets
rd.Links = &model.TicketLinks{}
rd.Project = project
rd.Name = project.OrganizationName
rd.Criteria= criteria
2018-05-15 21:13:11 +00:00
ts, err := config.Config().TicketSystem()
if err != nil {
return nil, nil, errors.Wrap(err, "error in ticket system configuration")
}
tp := model.GetPlugin(model.TicketSystem(ts))
2018-05-15 21:13:11 +00:00
if tp.Configured() {
links := tp.Links()
rd.Links = &links
}
return modelData, rd, nil
}
func loadWithStats() (*model.Data, *renderData, error) {
modelData, renderData, err := load()
if err != nil {
return nil, nil, err
}
// Convert the markdown body of each control to HTML
for _, n := range modelData.Controls {
b := []byte(n.Body)
n.BodyHTML = template.HTML(blackfriday.Run(b))
}
2018-05-15 21:13:11 +00:00
addStats(modelData, renderData)
return modelData, renderData, nil
}
func addStats(modelData *model.Data, renderData *renderData) {
stats := &stats{}
satisfied := model.CriteriaSatisfied(modelData)
2018-05-15 21:13:11 +00:00
2020-09-15 19:52:22 +00:00
for _, std := range renderData.Frameworks {
stats.CriteriaTotal += len(std.Criteria)
for criteriaKey := range std.Criteria{
if _, ok := satisfied[criteriaKey]; ok {
stats.CriteriaSatisfied++
2018-05-15 21:13:11 +00:00
}
}
}
for _, t := range renderData.Tickets {
if t.Bool("audit") {
stats.AuditTotal++
}
if t.State == model.Open {
2018-06-02 00:27:56 +00:00
if t.Bool("comply-procedure") {
2018-05-15 21:13:11 +00:00
stats.ProcedureOpen++
if t.CreatedAt != nil {
age := int(time.Since(*t.CreatedAt).Hours() / float64(24))
if stats.ProcedureOldestDays < age {
stats.ProcedureOldestDays = age
}
}
}
if t.Bool("audit") {
stats.AuditOpen++
}
}
}
renderData.Stats = stats
}