internal/worker: add module scans to home page

Display information about recent module scans on the server home page.

Change-Id: I76c28ec33ad6e3f241067c3f830d64b7cdc14440
Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/393834
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/worker/server.go b/internal/worker/server.go
index 9039847..5370300 100644
--- a/internal/worker/server.go
+++ b/internal/worker/server.go
@@ -14,6 +14,7 @@
 	"os"
 	"path/filepath"
 	"strconv"
+	"strings"
 	"sync/atomic"
 	"time"
 
@@ -195,7 +196,8 @@
 	}
 	templatePath := template.TrustedSourceJoin(staticPath, filename)
 	return template.New(filename.String()).Funcs(template.FuncMap{
-		"timefmt": FormatTime,
+		"timefmt":  FormatTime,
+		"commasep": func(s []string) string { return strings.Join(s, ", ") },
 	}).ParseFilesFromTrustedSources(templatePath)
 }
 
@@ -237,42 +239,40 @@
 	Updates          []*store.CommitUpdateRecord
 	CVEsNeedingIssue []*store.CVERecord
 	CVEsUpdatedSince []*store.CVERecord
+	ModuleScans      []*store.ModuleScanRecord
 }
 
 func (s *Server) indexPage(w http.ResponseWriter, r *http.Request) error {
 
-	var (
-		updates                    []*store.CommitUpdateRecord
-		needingIssue, updatedSince []*store.CVERecord
-	)
+	var page = indexPage{
+		CVEListRepoURL: cvelistrepo.URL,
+		Namespace:      s.cfg.Namespace,
+	}
 
 	g, ctx := errgroup.WithContext(r.Context())
 	g.Go(func() error {
 		var err error
-		updates, err = s.cfg.Store.ListCommitUpdateRecords(ctx, 10)
+		page.Updates, err = s.cfg.Store.ListCommitUpdateRecords(ctx, 10)
 		return err
 	})
 	g.Go(func() error {
 		var err error
-		needingIssue, err = s.cfg.Store.ListCVERecordsWithTriageState(ctx, store.TriageStateNeedsIssue)
+		page.CVEsNeedingIssue, err = s.cfg.Store.ListCVERecordsWithTriageState(ctx, store.TriageStateNeedsIssue)
 		return err
 	})
 	g.Go(func() error {
 		var err error
-		updatedSince, err = s.cfg.Store.ListCVERecordsWithTriageState(ctx, store.TriageStateUpdatedSinceIssueCreation)
+		page.CVEsUpdatedSince, err = s.cfg.Store.ListCVERecordsWithTriageState(ctx, store.TriageStateUpdatedSinceIssueCreation)
+		return err
+	})
+	g.Go(func() error {
+		var err error
+		page.ModuleScans, err = s.cfg.Store.ListModuleScanRecords(ctx, 300)
 		return err
 	})
 	if err := g.Wait(); err != nil {
 		return err
 	}
-
-	page := indexPage{
-		CVEListRepoURL:   cvelistrepo.URL,
-		Namespace:        s.cfg.Namespace,
-		Updates:          updates,
-		CVEsNeedingIssue: needingIssue,
-		CVEsUpdatedSince: updatedSince,
-	}
 	return renderPage(r.Context(), w, page, s.indexTemplate)
 }
 
diff --git a/internal/worker/static/index.tmpl b/internal/worker/static/index.tmpl
index f06c48c..6f2ca86 100644
--- a/internal/worker/static/index.tmpl
+++ b/internal/worker/static/index.tmpl
@@ -69,6 +69,23 @@
     {{end}}
   </table>
 
+  <h2>Recent Module Scans</h2>
+  <table>
+    <tr>
+      <th>Module</th><th>Version</th><th>DB Time</th><th>Vulns</th><th>Finished</th><th>Error</th>
+    </tr>
+    {{range .ModuleScans}}
+      <tr>
+        <td>{{.Path}}</td>
+        <td>{{.Version}}</td>
+        <td>{{.DBTime | timefmt}}</td>
+        <td>{{.VulnIDs | commasep}}</td>
+        <td>{{.FinishedAt | timefmt}}</td>
+        <td>{{.Error}}</td>
+      </tr>
+    {{end}}
+  </table>
+
 </body>
 </html>