From 83fa932f3c78c178e4facf945be82141a96cbe79 Mon Sep 17 00:00:00 2001 From: mpl Date: Fri, 1 Feb 2013 15:37:28 +0100 Subject: [PATCH] signhandler: inject the claimdate (if present) in the signrequest This allows to set a signature time (instead of using time.Now()), so that identical files will result in identical permanodes. Change-Id: I315c06bd30e8ac5e4d36b0e3f758483c22a31063 --- pkg/jsonsign/signhandler/sig.go | 8 ++++++++ pkg/schema/blob.go | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/pkg/jsonsign/signhandler/sig.go b/pkg/jsonsign/signhandler/sig.go index 3ecf8d9dc..3be3a1d5d 100644 --- a/pkg/jsonsign/signhandler/sig.go +++ b/pkg/jsonsign/signhandler/sig.go @@ -255,5 +255,13 @@ func (h *Handler) Sign(bb *schema.Builder) (string, error) { ServerMode: true, SecretKeyringPath: h.secretRing, } + claimTime, err := bb.Blob().ClaimDate() + if err != nil { + if !schema.IsMissingField(err) { + return "", err + } + } else { + sreq.SignatureTime = claimTime + } return sreq.Sign() } diff --git a/pkg/schema/blob.go b/pkg/schema/blob.go index d664da902..eb6a6c4bf 100644 --- a/pkg/schema/blob.go +++ b/pkg/schema/blob.go @@ -27,6 +27,19 @@ import ( "camlistore.org/pkg/blobref" ) +// A MissingFieldError represents a missing JSON field in a schema blob. +type MissingFieldError string + +func (e MissingFieldError) Error() string { + return fmt.Sprintf("schema: missing field %q", string(e)) +} + +// IsMissingField returns whether error is of type MissingFieldError. +func IsMissingField(err error) bool { + _, ok := err.(MissingFieldError) + return ok +} + // AnyBlob represents any type of schema blob. type AnyBlob interface { Blob() *Blob @@ -73,6 +86,17 @@ func (b *Blob) FileName() string { return b.ss.FileNameString() } +// ClaimDate returns the "claimDate" field. +// If there is no claimDate, the error will be a MissingFieldError. +func (b *Blob) ClaimDate() (time.Time, error) { + var ct time.Time + claimDate := b.ss.ClaimDate + if claimDate == "" { + return ct, MissingFieldError("claimDate") + } + return time.Parse(time.RFC3339, claimDate) +} + // ByteParts returns the "parts" field. The caller owns the returned // slice. func (b *Blob) ByteParts() []BytesPart {