1
0
Fork 0
mirror of https://github.com/gocsaf/csaf.git synced 2025-12-22 05:40:11 +01:00

write dynamic categories into feed categories document.

This commit is contained in:
Sascha L. Teichmann 2022-06-30 11:58:36 +02:00
parent 72a7240fd0
commit 198e5b8897
4 changed files with 122 additions and 8 deletions

View file

@ -14,6 +14,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"log"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -182,11 +183,24 @@ func (c *controller) upload(r *http.Request) (interface{}, error) {
} }
} }
ex, err := csaf.NewAdvisorySummary(util.NewPathEval(), content) // Extract informations from the document.
pe := util.NewPathEval()
ex, err := csaf.NewAdvisorySummary(pe, content)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Check if we have to search for dynamic categories.
var dynamicCategories []string
if catExprs := c.cfg.DynamicCategories(); len(catExprs) > 0 {
var err error
if dynamicCategories, err = pe.Strings(catExprs, true, content); err != nil {
// XXX: Should we die here?
log.Printf("eval of dynamic catecory expressions failed: %v\n", err)
}
}
t, err := c.tlpParam(r) t, err := c.tlpParam(r)
if err != nil { if err != nil {
return nil, err return nil, err
@ -217,6 +231,14 @@ func (c *controller) upload(r *http.Request) (interface{}, error) {
return err return err
} }
// if we have found dynamic categories merge them into
// the existing once.
if len(dynamicCategories) > 0 {
if err := c.mergeCategories(folder, t, dynamicCategories); err != nil {
return err
}
}
// Create yearly subfolder // Create yearly subfolder
year := strconv.Itoa(ex.InitialReleaseDate.Year()) year := strconv.Itoa(ex.InitialReleaseDate.Year())

View file

@ -19,6 +19,52 @@ import (
"github.com/csaf-poc/csaf_distribution/util" "github.com/csaf-poc/csaf_distribution/util"
) )
// mergeCategories merges the given categories into the old ones.
func (c *controller) mergeCategories(
folder string,
t tlp,
categories []string,
) error {
ts := string(t)
catName := "category-" + ts + ".json"
catPath := filepath.Join(folder, catName)
catDoc, err := loadCategoryDocument(catPath)
if err != nil {
return err
}
var changed bool
if catDoc == nil {
catDoc = csaf.NewROLIECategoryDocument(categories...)
changed = true
} else {
changed = catDoc.Merge(categories...)
}
if changed {
if err := util.WriteToFile(catPath, catDoc); err != nil {
return err
}
}
return nil
}
// loadROLIEFeed loads a ROLIE feed from file if its exists.
// Returns nil if the file does not exists.
func loadCategoryDocument(path string) (*csaf.ROLIECategoryDocument, error) {
f, err := os.Open(path)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
defer f.Close()
return csaf.LoadROLIECategoryDocument(f)
}
// extendROLIE adds a new entry to the ROLIE feed for a given advisory. // extendROLIE adds a new entry to the ROLIE feed for a given advisory.
func (c *controller) extendROLIE( func (c *controller) extendROLIE(
folder string, folder string,

View file

@ -82,15 +82,41 @@ type ROLIECategoryDocument struct {
// NewROLIECategoryDocument creates a new ROLIE category document from a list // NewROLIECategoryDocument creates a new ROLIE category document from a list
// of categories. // of categories.
func NewROLIECategoryDocument(categories ...string) *ROLIECategoryDocument { func NewROLIECategoryDocument(categories ...string) *ROLIECategoryDocument {
cats := make([]ROLIECategory, len(categories)) rcd := &ROLIECategoryDocument{}
for i, cat := range categories { rcd.Merge(categories...)
cats[i] = ROLIECategory{Term: cat} return rcd
}
// Merge merges the given categories into the existing ones.
// The results indicates if there were changes.
func (rcd *ROLIECategoryDocument) Merge(categories ...string) bool {
index := make(map[string]bool)
for i := range rcd.Categories.Category {
index[rcd.Categories.Category[i].Term] = true
} }
return &ROLIECategoryDocument{
Categories: ROLIECategories{ oldLen := len(index)
Category: cats,
}, for _, cat := range categories {
if index[cat] {
continue
}
index[cat] = true
rcd.Categories.Category = append(
rcd.Categories.Category, ROLIECategory{Term: cat})
} }
if len(index) == oldLen {
// No new categories
return false
}
// Re-establish order.
sort.Slice(rcd.Categories.Category, func(i, j int) bool {
return rcd.Categories.Category[i].Term < rcd.Categories.Category[j].Term
})
return true
} }
// LoadROLIECategoryDocument loads a ROLIE category document from a reader. // LoadROLIECategoryDocument loads a ROLIE category document from a reader.

View file

@ -146,3 +146,23 @@ func (pe *PathEval) Match(matcher []PathEvalMatcher, doc interface{}) error {
} }
return nil return nil
} }
// Strings searches the given document for the given set of expressions
// and returns the corresponding strings. The optional flag indicates
// if the expression evaluation have to succseed or not.
func (pe *PathEval) Strings(
exprs []string,
optional bool,
doc interface{},
) ([]string, error) {
results := make([]string, 0, len(exprs))
var result string
matcher := StringMatcher(&result)
for _, expr := range exprs {
if err := pe.Extract(expr, matcher, optional, doc); err != nil {
return nil, err
}
results = append(results, result)
}
return results, nil
}