use tokenMarshal/unmarshal in page encoding

Signed-off-by: liangchenye <liangchenye@huawei.com>
This commit is contained in:
liangchenye 2016-03-07 14:52:26 +08:00
parent 48ffb2687a
commit 27e5e42340
2 changed files with 24 additions and 42 deletions

View File

@ -19,7 +19,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"strconv"
"time" "time"
"github.com/coreos/clair/database" "github.com/coreos/clair/database"
@ -216,7 +215,8 @@ func NotificationFromDatabaseModel(dbNotification database.VulnerabilityNotifica
var nextPageStr string var nextPageStr string
if nextPage != database.NoVulnerabilityNotificationPage { if nextPage != database.NoVulnerabilityNotificationPage {
nextPageStr = pageNumberToToken(nextPage, key) nextPageBytes, _ := tokenMarshal(nextPage, key)
nextPageStr = string(nextPageBytes)
} }
var created, notified, deleted string var created, notified, deleted string
@ -292,51 +292,23 @@ type FeatureEnvelope struct {
Error *Error `json:"Error,omitempty"` Error *Error `json:"Error,omitempty"`
} }
func tokenToPageNumber(token, key string) (database.VulnerabilityNotificationPageNumber, error) { func tokenUnmarshal(token string, key string, v interface{}) error {
k, _ := fernet.DecodeKey(key) k, _ := fernet.DecodeKey(key)
msg := fernet.VerifyAndDecrypt([]byte(token), time.Hour, []*fernet.Key{k}) msg := fernet.VerifyAndDecrypt([]byte(token), time.Hour, []*fernet.Key{k})
if msg == nil { if msg == nil {
return database.VulnerabilityNotificationPageNumber{}, errors.New("invalid or expired pagination token") return errors.New("invalid or expired pagination token")
} }
page := database.VulnerabilityNotificationPageNumber{} return json.NewDecoder(bytes.NewBuffer(msg)).Decode(&v)
err := json.NewDecoder(bytes.NewBuffer(msg)).Decode(&page)
return page, err
} }
func pageNumberToToken(page database.VulnerabilityNotificationPageNumber, key string) string { func tokenMarshal(v interface{}, key string) ([]byte, error) {
var buf bytes.Buffer var buf bytes.Buffer
err := json.NewEncoder(&buf).Encode(page) err := json.NewEncoder(&buf).Encode(v)
if err != nil { if err != nil {
log.Fatal("failed to encode VulnerabilityNotificationPageNumber") return nil, err
} }
k, _ := fernet.DecodeKey(key) k, _ := fernet.DecodeKey(key)
tokenBytes, err := fernet.EncryptAndSign(buf.Bytes(), k) return fernet.EncryptAndSign(buf.Bytes(), k)
if err != nil {
log.Fatal("failed to encrypt VulnerabilityNotificationpageNumber")
}
return string(tokenBytes)
}
func tokenToNumber(token, key string) (int, error) {
k, _ := fernet.DecodeKey(key)
msg := fernet.VerifyAndDecrypt([]byte(token), time.Hour, []*fernet.Key{k})
if msg == nil {
return -1, errors.New("invalid or expired pagination token")
}
page, err := strconv.Atoi(string(msg))
return page, err
}
func numberToToken(page int, key string) string {
k, _ := fernet.DecodeKey(key)
tokenBytes, err := fernet.EncryptAndSign([]byte(strconv.Itoa(page)), k)
if err != nil {
log.Fatal("failed to encrypt number")
}
return string(tokenBytes)
} }

View File

@ -197,7 +197,7 @@ func getVulnerabilities(w http.ResponseWriter, r *http.Request, p httprouter.Par
if err != nil { if err != nil {
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"invalid limit format: " + err.Error()}}) writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"invalid limit format: " + err.Error()}})
return getVulnerabilitiesRoute, http.StatusBadRequest return getVulnerabilitiesRoute, http.StatusBadRequest
} else if limit <= 0 { } else if limit < 0 {
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"limit value should not be less than zero"}}) writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"limit value should not be less than zero"}})
return getVulnerabilitiesRoute, http.StatusBadRequest return getVulnerabilitiesRoute, http.StatusBadRequest
} }
@ -205,7 +205,7 @@ func getVulnerabilities(w http.ResponseWriter, r *http.Request, p httprouter.Par
page := 0 page := 0
pageStrs, pageExists := query["page"] pageStrs, pageExists := query["page"]
if pageExists { if pageExists {
page, err = tokenToNumber(pageStrs[0], ctx.Config.PaginationKey) err = tokenUnmarshal(pageStrs[0], ctx.Config.PaginationKey, &page)
if err != nil { if err != nil {
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"invalid page format: " + err.Error()}}) writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"invalid page format: " + err.Error()}})
return getNotificationRoute, http.StatusBadRequest return getNotificationRoute, http.StatusBadRequest
@ -226,7 +226,12 @@ func getVulnerabilities(w http.ResponseWriter, r *http.Request, p httprouter.Par
var nextPageStr string var nextPageStr string
if nextPage != -1 { if nextPage != -1 {
nextPageStr = numberToToken(nextPage, ctx.Config.PaginationKey) nextPageBytes, err := tokenMarshal(nextPage, ctx.Config.PaginationKey)
if err != nil {
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"failed to marshal token: " + err.Error()}})
return getNotificationRoute, http.StatusBadRequest
}
nextPageStr = string(nextPageBytes)
} }
writeResponse(w, r, http.StatusOK, VulnerabilityEnvelope{Vulnerabilities: &vulns, NextPage: &nextPageStr}) writeResponse(w, r, http.StatusOK, VulnerabilityEnvelope{Vulnerabilities: &vulns, NextPage: &nextPageStr})
@ -434,14 +439,19 @@ func getNotification(w http.ResponseWriter, r *http.Request, p httprouter.Params
page := database.VulnerabilityNotificationFirstPage page := database.VulnerabilityNotificationFirstPage
pageStrs, pageExists := query["page"] pageStrs, pageExists := query["page"]
if pageExists { if pageExists {
page, err = tokenToPageNumber(pageStrs[0], ctx.Config.PaginationKey) err := tokenUnmarshal(pageStrs[0], ctx.Config.PaginationKey, &page)
if err != nil { if err != nil {
writeResponse(w, r, http.StatusBadRequest, NotificationEnvelope{Error: &Error{"invalid page format: " + err.Error()}}) writeResponse(w, r, http.StatusBadRequest, NotificationEnvelope{Error: &Error{"invalid page format: " + err.Error()}})
return getNotificationRoute, http.StatusBadRequest return getNotificationRoute, http.StatusBadRequest
} }
pageToken = pageStrs[0] pageToken = pageStrs[0]
} else { } else {
pageToken = pageNumberToToken(page, ctx.Config.PaginationKey) pageTokenBytes, err := tokenMarshal(page, ctx.Config.PaginationKey)
if err != nil {
writeResponse(w, r, http.StatusBadRequest, NotificationEnvelope{Error: &Error{"failed to marshal token: " + err.Error()}})
return getNotificationRoute, http.StatusBadRequest
}
pageToken = string(pageTokenBytes)
} }
dbNotification, nextPage, err := ctx.Store.GetNotification(p.ByName("notificationName"), limit, page) dbNotification, nextPage, err := ctx.Store.GetNotification(p.ByName("notificationName"), limit, page)