-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #38 from opencontrol/summary-tables-C
rename Table to SummaryTable
- Loading branch information
Showing
19 changed files
with
548 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package control | ||
|
||
import ( | ||
"errors" | ||
"regexp" | ||
|
||
"github.com/jbowtie/gokogiri/xml" | ||
docxHelper "github.com/opencontrol/fedramp-templater/docx/helper" | ||
"github.com/opencontrol/fedramp-templater/opencontrols" | ||
xmlHelper "github.com/opencontrol/fedramp-templater/xml/helper" | ||
) | ||
|
||
type narrativeSection struct { | ||
row xml.Node | ||
} | ||
|
||
func (n narrativeSection) parsePart() (key string, err error) { | ||
re := regexp.MustCompile(`Part ([a-z])`) | ||
content := []byte(n.row.Content()) | ||
subMatches := re.FindSubmatch(content) | ||
if len(subMatches) != 2 { | ||
err = errors.New("No Parts found.") | ||
return | ||
} | ||
key = string(subMatches[1]) | ||
return | ||
} | ||
|
||
// GetKey returns the narrative section "part"/key. `key` will be an empty string if there is no "Part". | ||
func (n narrativeSection) GetKey() (key string, err error) { | ||
cells, err := xmlHelper.SearchSubtree(n.row, `./w:tc`) | ||
numCells := len(cells) | ||
if numCells == 1 { | ||
// there is only a single narrative section | ||
key = "" | ||
} else if numCells == 2 { | ||
key, err = n.parsePart() | ||
if err != nil { | ||
return | ||
} | ||
} else { | ||
err = errors.New("Don't know how to parse row.") | ||
} | ||
|
||
return | ||
} | ||
|
||
// Fill populates the section/part with the narrative for this control part from the provided data. | ||
func (n narrativeSection) Fill(data opencontrols.Data, control string) (err error) { | ||
// the row should have one or two cells; either way, the last one is what should be filled | ||
cellNode, err := xmlHelper.SearchOne(n.row, `./w:tc[last()]`) | ||
if err != nil { | ||
return | ||
} | ||
|
||
key, err := n.GetKey() | ||
if err != nil { | ||
return | ||
} | ||
|
||
narrative := data.GetNarrative(control, key) | ||
docxHelper.FillCell(cellNode, narrative) | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package control | ||
|
||
import ( | ||
"github.com/jbowtie/gokogiri/xml" | ||
"github.com/opencontrol/fedramp-templater/opencontrols" | ||
) | ||
|
||
func fillRows(rows []xml.Node, data opencontrols.Data, control string) error { | ||
for _, row := range rows { | ||
section := narrativeSection{row} | ||
err := section.Fill(data, control) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// NarrativeTable represents the node in the Word docx XML tree that corresponds to the justification fields for a security control. | ||
type NarrativeTable struct { | ||
table | ||
} | ||
|
||
// NewNarrativeTable creates a NarrativeTable instance. | ||
func NewNarrativeTable(root xml.Node) NarrativeTable { | ||
tbl := table{Root: root} | ||
return NarrativeTable{tbl} | ||
} | ||
|
||
// SectionRows returns the list of rows which correspond to each "part" of the narrative. Will return a single row when the narrative isn't split into parts. | ||
func (t *NarrativeTable) SectionRows() ([]xml.Node, error) { | ||
// skip the header row | ||
return t.table.searchSubtree(`.//w:tr[position() > 1]`) | ||
} | ||
|
||
// Fill inserts the OpenControl data into the table. | ||
func (t *NarrativeTable) Fill(openControlData opencontrols.Data) (err error) { | ||
control, err := t.table.controlName() | ||
if err != nil { | ||
return | ||
} | ||
|
||
rows, err := t.SectionRows() | ||
if err != nil { | ||
return | ||
} | ||
|
||
fillRows(rows, openControlData, control) | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package control_test | ||
|
||
import ( | ||
. "github.com/opencontrol/fedramp-templater/control" | ||
"github.com/opencontrol/fedramp-templater/fixtures" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("NarrativeTable", func() { | ||
Describe("SectionRows", func() { | ||
It("returns the correct number for a singular narrative", func() { | ||
doc := fixtures.LoadSSP("FedRAMP_ac-2-1_v2.1.docx") | ||
defer doc.Close() | ||
root, err := doc.NarrativeTable("AC-2 (1)") | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
table := NewNarrativeTable(root) | ||
sections, err := table.SectionRows() | ||
Expect(err).NotTo(HaveOccurred()) | ||
Expect(len(sections)).To(Equal(1)) | ||
}) | ||
|
||
It("returns the correct number for multiple narrative sections", func() { | ||
doc := fixtures.LoadSSP("FedRAMP_ac-2_v2.1.docx") | ||
defer doc.Close() | ||
root, err := doc.NarrativeTable("AC-2") | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
table := NewNarrativeTable(root) | ||
sections, err := table.SectionRows() | ||
Expect(err).NotTo(HaveOccurred()) | ||
Expect(len(sections)).To(Equal(11)) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package control | ||
|
||
import ( | ||
"github.com/jbowtie/gokogiri/xml" | ||
"github.com/opencontrol/fedramp-templater/opencontrols" | ||
"github.com/opencontrol/fedramp-templater/reporter" | ||
) | ||
|
||
const ( | ||
responsibleRoleField = "Responsible Role" | ||
) | ||
|
||
// SummaryTable represents the node in the Word docx XML tree that corresponds to the summary information for a security control. | ||
type SummaryTable struct { | ||
table | ||
} | ||
|
||
// NewSummaryTable creates a SummaryTable instance. | ||
func NewSummaryTable(root xml.Node) SummaryTable { | ||
tbl := table{Root: root} | ||
return SummaryTable{tbl} | ||
} | ||
|
||
func (st *SummaryTable) controlName() (name string, err error) { | ||
return st.table.controlName() | ||
} | ||
|
||
// Fill inserts the OpenControl justifications into the table. Note this modifies the `table`. | ||
func (st *SummaryTable) Fill(openControlData opencontrols.Data) (err error) { | ||
roleCell, err := findResponsibleRole(st) | ||
if err != nil { | ||
return | ||
} | ||
|
||
control, err := st.controlName() | ||
if err != nil { | ||
return | ||
} | ||
|
||
roles := openControlData.GetResponsibleRoles(control) | ||
roleCell.setValue(roles) | ||
|
||
return | ||
} | ||
|
||
// diffResponsibleRole computes the diff of the responsible role cell. | ||
func (st *SummaryTable) diffResponsibleRole(control string, openControlData opencontrols.Data) ([]reporter.Reporter, error) { | ||
roleCell, err := findResponsibleRole(st) | ||
if err != nil { | ||
return []reporter.Reporter{}, err | ||
} | ||
yamlRoles := openControlData.GetResponsibleRoles(control) | ||
sspRoles := roleCell.getValue() | ||
if roleCell.isDefaultValue(sspRoles) || yamlRoles == sspRoles { | ||
return []reporter.Reporter{}, nil | ||
} | ||
return []reporter.Reporter{ | ||
NewDiff(control, responsibleRoleField, sspRoles, yamlRoles), | ||
}, nil | ||
} | ||
|
||
// Diff returns the list of diffs in the control table. | ||
func (st *SummaryTable) Diff(openControlData opencontrols.Data) ([]reporter.Reporter, error) { | ||
control, err := st.controlName() | ||
if err != nil { | ||
return []reporter.Reporter{}, err | ||
} | ||
return st.diffResponsibleRole(control, openControlData) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.