api: implement get notification

This commit is contained in:
Jimmy Zelinskie 2016-02-01 19:10:10 -05:00
parent 116ce1a806
commit 3eaae478f9
2 changed files with 97 additions and 12 deletions

View File

@ -16,6 +16,7 @@ package v1
import ( import (
"errors" "errors"
"fmt"
"github.com/coreos/clair/database" "github.com/coreos/clair/database"
"github.com/coreos/clair/utils/types" "github.com/coreos/clair/utils/types"
@ -153,16 +154,36 @@ type Feature struct {
} }
type Notification struct { type Notification struct {
Name string `json:"Name,omitempty"` Name string `json:"Name,omitempty"`
Created string `json:"Created,omitempty"` Created string `json:"Created,omitempty"`
Notified string `json:"Notified,omitempty"` Notified string `json:"Notified,omitempty"`
Deleted string `json:"Deleted,omitempty"` Deleted string `json:"Deleted,omitempty"`
Limit int `json:"Limit,omitempty"` Limit int `json:"Limit,omitempty"`
Page string `json:"Page,omitempty"` Page string `json:"Page,omitempty"`
NextPage string `json:"NextPage,omitempty"` NextPage string `json:"NextPage,omitempty"`
Old VulnerabilityWithLayers `json:"Old,omitempty"` Old *VulnerabilityWithLayers `json:"Old,omitempty"`
New VulnerabilityWithLayers `json:"New,omitempty"` New VulnerabilityWithLayers `json:"New,omitempty"`
Changed []string `json:"Changed,omitempty"` Changed []string `json:"Changed,omitempty"`
}
func NotificationFromDatabaseModel(dbNotification database.VulnerabilityNotification, limit int, page, nextPage database.VulnerabilityNotificationPageNumber) Notification {
var oldVuln *VulnerabilityWithLayers
if dbNotification.OldVulnerability != nil {
*oldVuln = VulnerabilityWithLayersFromDatabaseModel(*dbNotification.OldVulnerability)
}
// TODO(jzelinskie): implement "changed" key
return Notification{
Name: dbNotification.Name,
Created: fmt.Sprintf("%d", dbNotification.Created.Unix()),
Notified: fmt.Sprintf("%d", dbNotification.Notified.Unix()),
Deleted: fmt.Sprintf("%d", dbNotification.Deleted.Unix()),
Limit: limit,
Page: DBPageNumberToString(page),
NextPage: DBPageNumberToString(nextPage),
Old: oldVuln,
New: VulnerabilityWithLayersFromDatabaseModel(dbNotification.NewVulnerability),
}
} }
type VulnerabilityWithLayers struct { type VulnerabilityWithLayers struct {
@ -170,6 +191,20 @@ type VulnerabilityWithLayers struct {
LayersIntroducingVulnerability []string `json:"LayersIntroducingVulnerability,omitempty"` LayersIntroducingVulnerability []string `json:"LayersIntroducingVulnerability,omitempty"`
} }
func VulnerabilityWithLayersFromDatabaseModel(dbVuln database.Vulnerability) VulnerabilityWithLayers {
vuln := VulnerabilityFromDatabaseModel(dbVuln, true)
var layers []string
for _, layer := range dbVuln.LayersIntroducingVulnerability {
layers = append(layers, layer.Name)
}
return VulnerabilityWithLayers{
Vulnerability: &vuln,
LayersIntroducingVulnerability: layers,
}
}
type LayerEnvelope struct { type LayerEnvelope struct {
Layer *Layer `json:"Layer,omitempty"` Layer *Layer `json:"Layer,omitempty"`
Error *Error `json:"Error,omitempty"` Error *Error `json:"Error,omitempty"`
@ -184,3 +219,20 @@ type VulnerabilityEnvelope struct {
Vulnerability *Vulnerability `json:"Vulnerability,omitempty"` Vulnerability *Vulnerability `json:"Vulnerability,omitempty"`
Error *Error `json:"Error,omitempty"` Error *Error `json:"Error,omitempty"`
} }
type NotificationEnvelope struct {
Notification *Notification `json:"Notification,omitempty"`
Error *Error `json:"Error,omitempty"`
}
func pageStringToDBPageNumber(pageStr string) (database.VulnerabilityNotificationPageNumber, error) {
// TODO(jzelinskie): turn pagination into an encrypted token
var old, new int
_, err := fmt.Sscanf(pageStr, "%d-%d", &old, &new)
return database.VulnerabilityNotificationPageNumber{old, new}, err
}
func DBPageNumberToString(page database.VulnerabilityNotificationPageNumber) string {
// TODO(jzelinskie): turn pagination into an encrypted token
return fmt.Sprintf("%d-%d", page.OldVulnerability, page.NewVulnerability)
}

View File

@ -18,6 +18,7 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"net/http" "net/http"
"strconv"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
@ -227,9 +228,41 @@ func deleteFix(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx
} }
func getNotification(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx *context.RouteContext) int { func getNotification(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx *context.RouteContext) int {
// ez query := r.URL.Query()
return 0
limitStrs, limitExists := query["limit"]
if !limitExists {
writeResponse(w, NotificationEnvelope{Error: &Error{"must provide limit query parameter"}})
return writeHeader(w, http.StatusBadRequest)
}
limit, err := strconv.Atoi(limitStrs[0])
if err != nil {
writeResponse(w, NotificationEnvelope{Error: &Error{"invalid limit format: " + err.Error()}})
return writeHeader(w, http.StatusBadRequest)
}
page := database.VulnerabilityNotificationFirstPage
pageStrs, pageExists := query["page"]
if pageExists {
page, err = pageStringToDBPageNumber(pageStrs[0])
if err != nil {
writeResponse(w, NotificationEnvelope{Error: &Error{"invalid page format: " + err.Error()}})
return writeHeader(w, http.StatusBadRequest)
}
}
dbNotification, nextPage, err := ctx.Store.GetNotification(p.ByName("notificationName"), limit, page)
if err != nil {
writeResponse(w, NotificationEnvelope{Error: &Error{err.Error()}})
return writeHeader(w, http.StatusInternalServerError)
}
notification := NotificationFromDatabaseModel(dbNotification, limit, page, nextPage)
writeResponse(w, NotificationEnvelope{Notification: &notification})
return writeHeader(w, http.StatusOK)
} }
func deleteNotification(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx *context.RouteContext) int { func deleteNotification(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx *context.RouteContext) int {
// ez // ez
return 0 return 0