schema: add Share type

This changes allows to get rid of the use of map[string]interface{} in
pkg/server/share.go

Change-Id: Ifeae6b194ff4db679be63d0087cb6d1c5df2f3ca
This commit is contained in:
mpl 2013-03-08 17:59:26 +01:00
parent ea3e16adf9
commit 0830902ffb
4 changed files with 42 additions and 13 deletions

View File

@ -132,7 +132,7 @@ func NewFromShareRoot(shareBlobURL string) (c *Client, target *blobref.BlobRef,
if err != nil {
return nil, nil, fmt.Errorf("Error parsing JSON from %s: %v", shareBlobURL, err)
}
if blob.ShareAuthType() != "haveref" {
if blob.ShareAuthType() != schema.ShareHaveRef {
return nil, nil, fmt.Errorf("Unknown share authType of %q", blob.ShareAuthType())
}
target = blob.ShareTarget()

View File

@ -91,7 +91,7 @@ func (b *Blob) FileName() string {
func (b *Blob) ClaimDate() (time.Time, error) {
var ct time.Time
claimDate := b.ss.ClaimDate
if claimDate.IsZero() {
if claimDate.IsZero() {
return ct, MissingFieldError("claimDate")
}
return claimDate.Time(), nil
@ -126,6 +126,18 @@ func (b *Blob) AsClaim() (c Claim, ok bool) {
return
}
// AsShare returns a Share if the receiver Blob has all the required fields.
func (b *Blob) AsShare() (s Share, ok bool) {
c, ok := b.AsClaim()
if !ok {
return
}
if b.ss.Type == "share" && b.ss.AuthType == ShareHaveRef && b.ss.Target != nil {
return Share{c}, true
}
return
}
// DirectoryEntries the "entries" field if valid and b's type is "directory", else
// it returns nil
func (b *Blob) DirectoryEntries() *blobref.BlobRef {
@ -191,6 +203,25 @@ func (c Claim) ModifiedPermanode() *blobref.BlobRef {
return c.b.ss.Permanode
}
// A Share is a claim for giving access to a user's blob(s).
// When returned from (*Blob).AsShare, it always represents
// a valid share with all required fields.
type Share struct {
Claim
}
// Target returns the blob referenced by the Share.
func (s Share) Target() *blobref.BlobRef {
return s.b.ShareTarget()
}
// IsTransitive returns whether the Share transitively
// gives access to everything reachable from the referenced
// blob.
func (s Share) IsTransitive() bool {
return s.b.ss.Transitive
}
// A Builder builds a JSON blob.
// After mutating the Builder, call Blob to get the built blob.
type Builder struct {

View File

@ -713,7 +713,7 @@ func NewDelAttributeClaim(permaNode *blobref.BlobRef, attr string) *Builder {
})
}
// ShareHaveRef is the a share type specifying that if you "have the
// ShareHaveRef is the auth type specifying that if you "have the
// reference" (know the blobref to the haveref share blob), then you
// have access to the referenced object from that share blob.
// This is the "send a link to a friend" access model.

View File

@ -18,7 +18,6 @@ package server
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
@ -122,22 +121,21 @@ func handleGetViaSharing(conn http.ResponseWriter, req *http.Request,
auth.SendUnauthorized(conn, req)
return
}
jd := json.NewDecoder(file)
m := make(map[string]interface{})
if err := jd.Decode(&m); err != nil {
log.Printf("Fetch chain 0 of %s wasn't JSON: %v", br.String(), err)
blob, err := schema.BlobFromReader(br, file)
if err != nil {
log.Printf("Can't create a blob from %v: %v", br.String(), err)
auth.SendUnauthorized(conn, req)
return
}
// TODO(mpl): make and use a struct type with json tags instead of map[string]interface{}.
if m["camliType"].(string) != "share" {
log.Printf("Fetch chain 0 of %s wasn't a share", br.String())
share, ok := blob.AsShare()
if !ok {
log.Printf("Fetch chain 0 of %s wasn't a valid Share", br.String())
auth.SendUnauthorized(conn, req)
return
}
if len(fetchChain) > 1 && fetchChain[1].String() != m["target"].(string) {
if len(fetchChain) > 1 && fetchChain[1].String() != share.Target().String() {
log.Printf("Fetch chain 0->1 (%s -> %q) unauthorized, expected hop to %q",
br.String(), fetchChain[1].String(), m["target"])
br.String(), fetchChain[1].String(), share.Target().String())
auth.SendUnauthorized(conn, req)
return
}