All other API's now support signature v4

master
Harshavardhana 9 years ago
parent 00890c254e
commit 84f427f14a
  1. 44
      pkg/donut/donut-v1_test.go
  2. 73
      pkg/donut/donut-v2.go
  3. 44
      pkg/donut/donut-v2_test.go
  4. 20
      pkg/donut/interfaces.go
  5. 49
      pkg/donut/multipart.go
  6. 80
      pkg/server/api/bucket-handlers.go
  7. 65
      pkg/server/api/object-handlers.go
  8. 2
      pkg/server/api/response.go

@ -74,7 +74,7 @@ func (s *MyDonutSuite) SetUpSuite(c *C) {
c.Assert(err, IsNil) c.Assert(err, IsNil)
// testing empty donut // testing empty donut
buckets, err := dd.ListBuckets() buckets, err := dd.ListBuckets(nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 0) c.Assert(len(buckets), Equals, 0)
} }
@ -86,20 +86,20 @@ func (s *MyDonutSuite) TearDownSuite(c *C) {
// test make bucket without name // test make bucket without name
func (s *MyDonutSuite) TestBucketWithoutNameFails(c *C) { func (s *MyDonutSuite) TestBucketWithoutNameFails(c *C) {
// fail to create new bucket without a name // fail to create new bucket without a name
err := dd.MakeBucket("", "private") err := dd.MakeBucket("", "private", nil)
c.Assert(err, Not(IsNil)) c.Assert(err, Not(IsNil))
err = dd.MakeBucket(" ", "private") err = dd.MakeBucket(" ", "private", nil)
c.Assert(err, Not(IsNil)) c.Assert(err, Not(IsNil))
} }
// test empty bucket // test empty bucket
func (s *MyDonutSuite) TestEmptyBucket(c *C) { func (s *MyDonutSuite) TestEmptyBucket(c *C) {
c.Assert(dd.MakeBucket("foo1", "private"), IsNil) c.Assert(dd.MakeBucket("foo1", "private", nil), IsNil)
// check if bucket is empty // check if bucket is empty
var resources BucketResourcesMetadata var resources BucketResourcesMetadata
resources.Maxkeys = 1 resources.Maxkeys = 1
objectsMetadata, resources, err := dd.ListObjects("foo1", resources) objectsMetadata, resources, err := dd.ListObjects("foo1", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(objectsMetadata), Equals, 0) c.Assert(len(objectsMetadata), Equals, 0)
c.Assert(resources.CommonPrefixes, DeepEquals, []string{}) c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
@ -109,11 +109,11 @@ func (s *MyDonutSuite) TestEmptyBucket(c *C) {
// test bucket list // test bucket list
func (s *MyDonutSuite) TestMakeBucketAndList(c *C) { func (s *MyDonutSuite) TestMakeBucketAndList(c *C) {
// create bucket // create bucket
err := dd.MakeBucket("foo2", "private") err := dd.MakeBucket("foo2", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
// check bucket exists // check bucket exists
buckets, err := dd.ListBuckets() buckets, err := dd.ListBuckets(nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 5) c.Assert(len(buckets), Equals, 5)
c.Assert(buckets[0].ACL, Equals, BucketACL("private")) c.Assert(buckets[0].ACL, Equals, BucketACL("private"))
@ -121,33 +121,33 @@ func (s *MyDonutSuite) TestMakeBucketAndList(c *C) {
// test re-create bucket // test re-create bucket
func (s *MyDonutSuite) TestMakeBucketWithSameNameFails(c *C) { func (s *MyDonutSuite) TestMakeBucketWithSameNameFails(c *C) {
err := dd.MakeBucket("foo3", "private") err := dd.MakeBucket("foo3", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
err = dd.MakeBucket("foo3", "private") err = dd.MakeBucket("foo3", "private", nil)
c.Assert(err, Not(IsNil)) c.Assert(err, Not(IsNil))
} }
// test make multiple buckets // test make multiple buckets
func (s *MyDonutSuite) TestCreateMultipleBucketsAndList(c *C) { func (s *MyDonutSuite) TestCreateMultipleBucketsAndList(c *C) {
// add a second bucket // add a second bucket
err := dd.MakeBucket("foo4", "private") err := dd.MakeBucket("foo4", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
err = dd.MakeBucket("bar1", "private") err = dd.MakeBucket("bar1", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
buckets, err := dd.ListBuckets() buckets, err := dd.ListBuckets(nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 2) c.Assert(len(buckets), Equals, 2)
c.Assert(buckets[0].Name, Equals, "bar1") c.Assert(buckets[0].Name, Equals, "bar1")
c.Assert(buckets[1].Name, Equals, "foo4") c.Assert(buckets[1].Name, Equals, "foo4")
err = dd.MakeBucket("foobar1", "private") err = dd.MakeBucket("foobar1", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
buckets, err = dd.ListBuckets() buckets, err = dd.ListBuckets(nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 3) c.Assert(len(buckets), Equals, 3)
@ -168,7 +168,7 @@ func (s *MyDonutSuite) TestNewObjectMetadata(c *C) {
expectedMd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil)) expectedMd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
reader := ioutil.NopCloser(bytes.NewReader([]byte(data))) reader := ioutil.NopCloser(bytes.NewReader([]byte(data)))
err := dd.MakeBucket("foo6", "private") err := dd.MakeBucket("foo6", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
objectMetadata, err := dd.CreateObject("foo6", "obj", expectedMd5Sum, int64(len(data)), reader, map[string]string{"contentType": "application/json"}, nil) objectMetadata, err := dd.CreateObject("foo6", "obj", expectedMd5Sum, int64(len(data)), reader, map[string]string{"contentType": "application/json"}, nil)
@ -185,7 +185,7 @@ func (s *MyDonutSuite) TestNewObjectFailsWithEmptyName(c *C) {
// test create object // test create object
func (s *MyDonutSuite) TestNewObjectCanBeWritten(c *C) { func (s *MyDonutSuite) TestNewObjectCanBeWritten(c *C) {
err := dd.MakeBucket("foo", "private") err := dd.MakeBucket("foo", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
data := "Hello World" data := "Hello World"
@ -205,7 +205,7 @@ func (s *MyDonutSuite) TestNewObjectCanBeWritten(c *C) {
c.Assert(size, Equals, int64(len(data))) c.Assert(size, Equals, int64(len(data)))
c.Assert(buffer.Bytes(), DeepEquals, []byte(data)) c.Assert(buffer.Bytes(), DeepEquals, []byte(data))
actualMetadata, err = dd.GetObjectMetadata("foo", "obj") actualMetadata, err = dd.GetObjectMetadata("foo", "obj", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum) c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
c.Assert(int64(len(data)), Equals, actualMetadata.Size) c.Assert(int64(len(data)), Equals, actualMetadata.Size)
@ -213,7 +213,7 @@ func (s *MyDonutSuite) TestNewObjectCanBeWritten(c *C) {
// test list objects // test list objects
func (s *MyDonutSuite) TestMultipleNewObjects(c *C) { func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
c.Assert(dd.MakeBucket("foo5", "private"), IsNil) c.Assert(dd.MakeBucket("foo5", "private", nil), IsNil)
one := ioutil.NopCloser(bytes.NewReader([]byte("one"))) one := ioutil.NopCloser(bytes.NewReader([]byte("one")))
@ -244,7 +244,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o" resources.Prefix = "o"
resources.Delimiter = "1" resources.Delimiter = "1"
resources.Maxkeys = 10 resources.Maxkeys = 10
objectsMetadata, resources, err := dd.ListObjects("foo5", resources) objectsMetadata, resources, err := dd.ListObjects("foo5", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, false) c.Assert(resources.IsTruncated, Equals, false)
c.Assert(resources.CommonPrefixes[0], Equals, "obj1") c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
@ -253,7 +253,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "" resources.Prefix = ""
resources.Delimiter = "1" resources.Delimiter = "1"
resources.Maxkeys = 10 resources.Maxkeys = 10
objectsMetadata, resources, err = dd.ListObjects("foo5", resources) objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(objectsMetadata[0].Object, Equals, "obj2") c.Assert(objectsMetadata[0].Object, Equals, "obj2")
c.Assert(resources.IsTruncated, Equals, false) c.Assert(resources.IsTruncated, Equals, false)
@ -263,7 +263,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o" resources.Prefix = "o"
resources.Delimiter = "" resources.Delimiter = ""
resources.Maxkeys = 10 resources.Maxkeys = 10
objectsMetadata, resources, err = dd.ListObjects("foo5", resources) objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, false) c.Assert(resources.IsTruncated, Equals, false)
c.Assert(objectsMetadata[0].Object, Equals, "obj1") c.Assert(objectsMetadata[0].Object, Equals, "obj1")
@ -283,7 +283,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o" resources.Prefix = "o"
resources.Delimiter = "" resources.Delimiter = ""
resources.Maxkeys = 2 resources.Maxkeys = 2
objectsMetadata, resources, err = dd.ListObjects("foo5", resources) objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, true) c.Assert(resources.IsTruncated, Equals, true)
c.Assert(len(objectsMetadata), Equals, 2) c.Assert(len(objectsMetadata), Equals, 2)

@ -180,6 +180,7 @@ func (donut API) GetPartialObject(w io.Writer, bucket, object string, start, len
"start": strconv.FormatInt(start, 10), "start": strconv.FormatInt(start, 10),
"length": strconv.FormatInt(length, 10), "length": strconv.FormatInt(length, 10),
} }
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return 0, iodine.New(BucketNameInvalid{Bucket: bucket}, errParams) return 0, iodine.New(BucketNameInvalid{Bucket: bucket}, errParams)
} }
@ -226,10 +227,20 @@ func (donut API) GetPartialObject(w io.Writer, bucket, object string, start, len
} }
// GetBucketMetadata - // GetBucketMetadata -
func (donut API) GetBucketMetadata(bucket string) (BucketMetadata, error) { func (donut API) GetBucketMetadata(bucket string, signature *Signature) (BucketMetadata, error) {
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return BucketMetadata{}, iodine.New(err, nil)
}
if !ok {
return BucketMetadata{}, iodine.New(SignatureDoesNotMatch{}, nil)
}
}
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return BucketMetadata{}, iodine.New(BucketNameInvalid{Bucket: bucket}, nil) return BucketMetadata{}, iodine.New(BucketNameInvalid{Bucket: bucket}, nil)
} }
@ -249,10 +260,20 @@ func (donut API) GetBucketMetadata(bucket string) (BucketMetadata, error) {
} }
// SetBucketMetadata - // SetBucketMetadata -
func (donut API) SetBucketMetadata(bucket string, metadata map[string]string) error { func (donut API) SetBucketMetadata(bucket string, metadata map[string]string, signature *Signature) error {
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return iodine.New(err, nil)
}
if !ok {
return iodine.New(SignatureDoesNotMatch{}, nil)
}
}
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return iodine.New(BucketNameInvalid{Bucket: bucket}, nil) return iodine.New(BucketNameInvalid{Bucket: bucket}, nil)
} }
@ -424,10 +445,20 @@ func (donut API) createObject(bucket, key, contentType, expectedMD5Sum string, s
} }
// MakeBucket - create bucket in cache // MakeBucket - create bucket in cache
func (donut API) MakeBucket(bucketName, acl string) error { func (donut API) MakeBucket(bucketName, acl string, signature *Signature) error {
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return iodine.New(err, nil)
}
if !ok {
return iodine.New(SignatureDoesNotMatch{}, nil)
}
}
if donut.storedBuckets.Stats().Items == totalBuckets { if donut.storedBuckets.Stats().Items == totalBuckets {
return iodine.New(TooManyBuckets{Bucket: bucketName}, nil) return iodine.New(TooManyBuckets{Bucket: bucketName}, nil)
} }
@ -463,10 +494,20 @@ func (donut API) MakeBucket(bucketName, acl string) error {
} }
// ListObjects - list objects from cache // ListObjects - list objects from cache
func (donut API) ListObjects(bucket string, resources BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, error) { func (donut API) ListObjects(bucket string, resources BucketResourcesMetadata, signature *Signature) ([]ObjectMetadata, BucketResourcesMetadata, error) {
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return nil, BucketResourcesMetadata{}, iodine.New(err, nil)
}
if !ok {
return nil, BucketResourcesMetadata{}, iodine.New(SignatureDoesNotMatch{}, nil)
}
}
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return nil, BucketResourcesMetadata{IsTruncated: false}, iodine.New(BucketNameInvalid{Bucket: bucket}, nil) return nil, BucketResourcesMetadata{IsTruncated: false}, iodine.New(BucketNameInvalid{Bucket: bucket}, nil)
} }
@ -556,10 +597,20 @@ func (b byBucketName) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
func (b byBucketName) Less(i, j int) bool { return b[i].Name < b[j].Name } func (b byBucketName) Less(i, j int) bool { return b[i].Name < b[j].Name }
// ListBuckets - List buckets from cache // ListBuckets - List buckets from cache
func (donut API) ListBuckets() ([]BucketMetadata, error) { func (donut API) ListBuckets(signature *Signature) ([]BucketMetadata, error) {
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return nil, iodine.New(err, nil)
}
if !ok {
return nil, iodine.New(SignatureDoesNotMatch{}, nil)
}
}
var results []BucketMetadata var results []BucketMetadata
if len(donut.config.NodeDiskMap) > 0 { if len(donut.config.NodeDiskMap) > 0 {
buckets, err := donut.listBuckets() buckets, err := donut.listBuckets()
@ -580,10 +631,20 @@ func (donut API) ListBuckets() ([]BucketMetadata, error) {
} }
// GetObjectMetadata - get object metadata from cache // GetObjectMetadata - get object metadata from cache
func (donut API) GetObjectMetadata(bucket, key string) (ObjectMetadata, error) { func (donut API) GetObjectMetadata(bucket, key string, signature *Signature) (ObjectMetadata, error) {
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return ObjectMetadata{}, iodine.New(err, nil)
}
if !ok {
return ObjectMetadata{}, iodine.New(SignatureDoesNotMatch{}, nil)
}
}
// check if bucket exists // check if bucket exists
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return ObjectMetadata{}, iodine.New(BucketNameInvalid{Bucket: bucket}, nil) return ObjectMetadata{}, iodine.New(BucketNameInvalid{Bucket: bucket}, nil)

@ -49,7 +49,7 @@ func (s *MyCacheSuite) SetUpSuite(c *C) {
c.Assert(err, IsNil) c.Assert(err, IsNil)
// testing empty cache // testing empty cache
buckets, err := dc.ListBuckets() buckets, err := dc.ListBuckets(nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 0) c.Assert(len(buckets), Equals, 0)
} }
@ -61,20 +61,20 @@ func (s *MyCacheSuite) TearDownSuite(c *C) {
// test make bucket without name // test make bucket without name
func (s *MyCacheSuite) TestBucketWithoutNameFails(c *C) { func (s *MyCacheSuite) TestBucketWithoutNameFails(c *C) {
// fail to create new bucket without a name // fail to create new bucket without a name
err := dc.MakeBucket("", "private") err := dc.MakeBucket("", "private", nil)
c.Assert(err, Not(IsNil)) c.Assert(err, Not(IsNil))
err = dc.MakeBucket(" ", "private") err = dc.MakeBucket(" ", "private", nil)
c.Assert(err, Not(IsNil)) c.Assert(err, Not(IsNil))
} }
// test empty bucket // test empty bucket
func (s *MyCacheSuite) TestEmptyBucket(c *C) { func (s *MyCacheSuite) TestEmptyBucket(c *C) {
c.Assert(dc.MakeBucket("foo1", "private"), IsNil) c.Assert(dc.MakeBucket("foo1", "private", nil), IsNil)
// check if bucket is empty // check if bucket is empty
var resources BucketResourcesMetadata var resources BucketResourcesMetadata
resources.Maxkeys = 1 resources.Maxkeys = 1
objectsMetadata, resources, err := dc.ListObjects("foo1", resources) objectsMetadata, resources, err := dc.ListObjects("foo1", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(objectsMetadata), Equals, 0) c.Assert(len(objectsMetadata), Equals, 0)
c.Assert(resources.CommonPrefixes, DeepEquals, []string{}) c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
@ -84,11 +84,11 @@ func (s *MyCacheSuite) TestEmptyBucket(c *C) {
// test bucket list // test bucket list
func (s *MyCacheSuite) TestMakeBucketAndList(c *C) { func (s *MyCacheSuite) TestMakeBucketAndList(c *C) {
// create bucket // create bucket
err := dc.MakeBucket("foo2", "private") err := dc.MakeBucket("foo2", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
// check bucket exists // check bucket exists
buckets, err := dc.ListBuckets() buckets, err := dc.ListBuckets(nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 5) c.Assert(len(buckets), Equals, 5)
c.Assert(buckets[0].ACL, Equals, BucketACL("private")) c.Assert(buckets[0].ACL, Equals, BucketACL("private"))
@ -96,33 +96,33 @@ func (s *MyCacheSuite) TestMakeBucketAndList(c *C) {
// test re-create bucket // test re-create bucket
func (s *MyCacheSuite) TestMakeBucketWithSameNameFails(c *C) { func (s *MyCacheSuite) TestMakeBucketWithSameNameFails(c *C) {
err := dc.MakeBucket("foo3", "private") err := dc.MakeBucket("foo3", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
err = dc.MakeBucket("foo3", "private") err = dc.MakeBucket("foo3", "private", nil)
c.Assert(err, Not(IsNil)) c.Assert(err, Not(IsNil))
} }
// test make multiple buckets // test make multiple buckets
func (s *MyCacheSuite) TestCreateMultipleBucketsAndList(c *C) { func (s *MyCacheSuite) TestCreateMultipleBucketsAndList(c *C) {
// add a second bucket // add a second bucket
err := dc.MakeBucket("foo4", "private") err := dc.MakeBucket("foo4", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
err = dc.MakeBucket("bar1", "private") err = dc.MakeBucket("bar1", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
buckets, err := dc.ListBuckets() buckets, err := dc.ListBuckets(nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 2) c.Assert(len(buckets), Equals, 2)
c.Assert(buckets[0].Name, Equals, "bar1") c.Assert(buckets[0].Name, Equals, "bar1")
c.Assert(buckets[1].Name, Equals, "foo4") c.Assert(buckets[1].Name, Equals, "foo4")
err = dc.MakeBucket("foobar1", "private") err = dc.MakeBucket("foobar1", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
buckets, err = dc.ListBuckets() buckets, err = dc.ListBuckets(nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 3) c.Assert(len(buckets), Equals, 3)
@ -143,7 +143,7 @@ func (s *MyCacheSuite) TestNewObjectMetadata(c *C) {
expectedMd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil)) expectedMd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
reader := ioutil.NopCloser(bytes.NewReader([]byte(data))) reader := ioutil.NopCloser(bytes.NewReader([]byte(data)))
err := dc.MakeBucket("foo6", "private") err := dc.MakeBucket("foo6", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
objectMetadata, err := dc.CreateObject("foo6", "obj", expectedMd5Sum, int64(len(data)), reader, map[string]string{"contentType": "application/json"}, nil) objectMetadata, err := dc.CreateObject("foo6", "obj", expectedMd5Sum, int64(len(data)), reader, map[string]string{"contentType": "application/json"}, nil)
@ -160,7 +160,7 @@ func (s *MyCacheSuite) TestNewObjectFailsWithEmptyName(c *C) {
// test create object // test create object
func (s *MyCacheSuite) TestNewObjectCanBeWritten(c *C) { func (s *MyCacheSuite) TestNewObjectCanBeWritten(c *C) {
err := dc.MakeBucket("foo", "private") err := dc.MakeBucket("foo", "private", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
data := "Hello World" data := "Hello World"
@ -180,7 +180,7 @@ func (s *MyCacheSuite) TestNewObjectCanBeWritten(c *C) {
c.Assert(size, Equals, int64(len(data))) c.Assert(size, Equals, int64(len(data)))
c.Assert(buffer.Bytes(), DeepEquals, []byte(data)) c.Assert(buffer.Bytes(), DeepEquals, []byte(data))
actualMetadata, err = dc.GetObjectMetadata("foo", "obj") actualMetadata, err = dc.GetObjectMetadata("foo", "obj", nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum) c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
c.Assert(int64(len(data)), Equals, actualMetadata.Size) c.Assert(int64(len(data)), Equals, actualMetadata.Size)
@ -188,7 +188,7 @@ func (s *MyCacheSuite) TestNewObjectCanBeWritten(c *C) {
// test list objects // test list objects
func (s *MyCacheSuite) TestMultipleNewObjects(c *C) { func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
c.Assert(dc.MakeBucket("foo5", "private"), IsNil) c.Assert(dc.MakeBucket("foo5", "private", nil), IsNil)
one := ioutil.NopCloser(bytes.NewReader([]byte("one"))) one := ioutil.NopCloser(bytes.NewReader([]byte("one")))
@ -219,7 +219,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o" resources.Prefix = "o"
resources.Delimiter = "1" resources.Delimiter = "1"
resources.Maxkeys = 10 resources.Maxkeys = 10
objectsMetadata, resources, err := dc.ListObjects("foo5", resources) objectsMetadata, resources, err := dc.ListObjects("foo5", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, false) c.Assert(resources.IsTruncated, Equals, false)
c.Assert(resources.CommonPrefixes[0], Equals, "obj1") c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
@ -228,7 +228,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "" resources.Prefix = ""
resources.Delimiter = "1" resources.Delimiter = "1"
resources.Maxkeys = 10 resources.Maxkeys = 10
objectsMetadata, resources, err = dc.ListObjects("foo5", resources) objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(objectsMetadata[0].Object, Equals, "obj2") c.Assert(objectsMetadata[0].Object, Equals, "obj2")
c.Assert(resources.IsTruncated, Equals, false) c.Assert(resources.IsTruncated, Equals, false)
@ -238,7 +238,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o" resources.Prefix = "o"
resources.Delimiter = "" resources.Delimiter = ""
resources.Maxkeys = 10 resources.Maxkeys = 10
objectsMetadata, resources, err = dc.ListObjects("foo5", resources) objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, false) c.Assert(resources.IsTruncated, Equals, false)
c.Assert(objectsMetadata[0].Object, Equals, "obj1") c.Assert(objectsMetadata[0].Object, Equals, "obj1")
@ -258,7 +258,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o" resources.Prefix = "o"
resources.Delimiter = "" resources.Delimiter = ""
resources.Maxkeys = 2 resources.Maxkeys = 2
objectsMetadata, resources, err = dc.ListObjects("foo5", resources) objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, true) c.Assert(resources.IsTruncated, Equals, true)
c.Assert(len(objectsMetadata), Equals, 2) c.Assert(len(objectsMetadata), Equals, 2)

@ -29,18 +29,18 @@ type Interface interface {
// ObjectStorage is a donut object storage interface // ObjectStorage is a donut object storage interface
type ObjectStorage interface { type ObjectStorage interface {
// Storage service operations // Storage service operations
GetBucketMetadata(bucket string) (BucketMetadata, error) GetBucketMetadata(bucket string, signature *Signature) (BucketMetadata, error)
SetBucketMetadata(bucket string, metadata map[string]string) error SetBucketMetadata(bucket string, metadata map[string]string, signature *Signature) error
ListBuckets() ([]BucketMetadata, error) ListBuckets(signature *Signature) ([]BucketMetadata, error)
MakeBucket(bucket string, ACL string) error MakeBucket(bucket string, ACL string, signature *Signature) error
// Bucket operations // Bucket operations
ListObjects(bucket string, resources BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, error) ListObjects(string, BucketResourcesMetadata, *Signature) ([]ObjectMetadata, BucketResourcesMetadata, error)
// Object operations // Object operations
GetObject(w io.Writer, bucket, object string) (int64, error) GetObject(w io.Writer, bucket, object string) (int64, error)
GetPartialObject(w io.Writer, bucket, object string, start, length int64) (int64, error) GetPartialObject(w io.Writer, bucket, object string, start, length int64) (int64, error)
GetObjectMetadata(bucket, object string) (ObjectMetadata, error) GetObjectMetadata(bucket, object string, signature *Signature) (ObjectMetadata, error)
// bucket, object, expectedMD5Sum, size, reader, metadata, signature // bucket, object, expectedMD5Sum, size, reader, metadata, signature
CreateObject(string, string, string, int64, io.Reader, map[string]string, *Signature) (ObjectMetadata, error) CreateObject(string, string, string, int64, io.Reader, map[string]string, *Signature) (ObjectMetadata, error)
@ -49,12 +49,12 @@ type ObjectStorage interface {
// Multipart API // Multipart API
type Multipart interface { type Multipart interface {
NewMultipartUpload(bucket, key, contentType string) (string, error) NewMultipartUpload(bucket, key, contentType string, signature *Signature) (string, error)
AbortMultipartUpload(bucket, key, uploadID string) error AbortMultipartUpload(bucket, key, uploadID string, signature *Signature) error
CreateObjectPart(string, string, string, int, string, string, int64, io.Reader, *Signature) (string, error) CreateObjectPart(string, string, string, int, string, string, int64, io.Reader, *Signature) (string, error)
CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *Signature) (ObjectMetadata, error) CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *Signature) (ObjectMetadata, error)
ListMultipartUploads(bucket string, resources BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, error) ListMultipartUploads(string, BucketMultipartResourcesMetadata, *Signature) (BucketMultipartResourcesMetadata, error)
ListObjectParts(bucket, key string, resources ObjectResourcesMetadata) (ObjectResourcesMetadata, error) ListObjectParts(string, string, ObjectResourcesMetadata, *Signature) (ObjectResourcesMetadata, error)
} }
// Management is a donut management system interface // Management is a donut management system interface

@ -39,10 +39,20 @@ import (
) )
// NewMultipartUpload - initiate a new multipart session // NewMultipartUpload - initiate a new multipart session
func (donut API) NewMultipartUpload(bucket, key, contentType string) (string, error) { func (donut API) NewMultipartUpload(bucket, key, contentType string, signature *Signature) (string, error) {
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return "", iodine.New(err, nil)
}
if !ok {
return "", iodine.New(SignatureDoesNotMatch{}, nil)
}
}
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return "", iodine.New(BucketNameInvalid{Bucket: bucket}, nil) return "", iodine.New(BucketNameInvalid{Bucket: bucket}, nil)
} }
@ -74,10 +84,20 @@ func (donut API) NewMultipartUpload(bucket, key, contentType string) (string, er
} }
// AbortMultipartUpload - abort an incomplete multipart session // AbortMultipartUpload - abort an incomplete multipart session
func (donut API) AbortMultipartUpload(bucket, key, uploadID string) error { func (donut API) AbortMultipartUpload(bucket, key, uploadID string, signature *Signature) error {
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return iodine.New(err, nil)
}
if !ok {
return iodine.New(SignatureDoesNotMatch{}, nil)
}
}
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return iodine.New(BucketNameInvalid{Bucket: bucket}, nil) return iodine.New(BucketNameInvalid{Bucket: bucket}, nil)
} }
@ -313,14 +333,25 @@ func (a byKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byKey) Less(i, j int) bool { return a[i].Key < a[j].Key } func (a byKey) Less(i, j int) bool { return a[i].Key < a[j].Key }
// ListMultipartUploads - list incomplete multipart sessions for a given bucket // ListMultipartUploads - list incomplete multipart sessions for a given bucket
func (donut API) ListMultipartUploads(bucket string, resources BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, error) { func (donut API) ListMultipartUploads(bucket string, resources BucketMultipartResourcesMetadata, signature *Signature) (BucketMultipartResourcesMetadata, error) {
// TODO handle delimiter // TODO handle delimiter
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return BucketMultipartResourcesMetadata{}, iodine.New(err, nil)
}
if !ok {
return BucketMultipartResourcesMetadata{}, iodine.New(SignatureDoesNotMatch{}, nil)
}
}
if !donut.storedBuckets.Exists(bucket) { if !donut.storedBuckets.Exists(bucket) {
return BucketMultipartResourcesMetadata{}, iodine.New(BucketNotFound{Bucket: bucket}, nil) return BucketMultipartResourcesMetadata{}, iodine.New(BucketNotFound{Bucket: bucket}, nil)
} }
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket) storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
var uploads []*UploadMetadata var uploads []*UploadMetadata
@ -376,11 +407,21 @@ func (a partNumber) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a partNumber) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber } func (a partNumber) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber }
// ListObjectParts - list parts from incomplete multipart session for a given object // ListObjectParts - list parts from incomplete multipart session for a given object
func (donut API) ListObjectParts(bucket, key string, resources ObjectResourcesMetadata) (ObjectResourcesMetadata, error) { func (donut API) ListObjectParts(bucket, key string, resources ObjectResourcesMetadata, signature *Signature) (ObjectResourcesMetadata, error) {
// Verify upload id // Verify upload id
donut.lock.Lock() donut.lock.Lock()
defer donut.lock.Unlock() defer donut.lock.Unlock()
if signature != nil {
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
if err != nil {
return ObjectResourcesMetadata{}, iodine.New(err, nil)
}
if !ok {
return ObjectResourcesMetadata{}, iodine.New(SignatureDoesNotMatch{}, nil)
}
}
if !donut.storedBuckets.Exists(bucket) { if !donut.storedBuckets.Exists(bucket) {
return ObjectResourcesMetadata{}, iodine.New(BucketNotFound{Bucket: bucket}, nil) return ObjectResourcesMetadata{}, iodine.New(BucketNotFound{Bucket: bucket}, nil)
} }

@ -29,7 +29,7 @@ func (api Minio) isValidOp(w http.ResponseWriter, req *http.Request, acceptsCont
vars := mux.Vars(req) vars := mux.Vars(req)
bucket := vars["bucket"] bucket := vars["bucket"]
bucketMetadata, err := api.Donut.GetBucketMetadata(bucket) bucketMetadata, err := api.Donut.GetBucketMetadata(bucket, nil)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case donut.BucketNotFound: case donut.BucketNotFound:
{ {
@ -95,7 +95,18 @@ func (api Minio) ListMultipartUploadsHandler(w http.ResponseWriter, req *http.Re
vars := mux.Vars(req) vars := mux.Vars(req)
bucket := vars["bucket"] bucket := vars["bucket"]
resources, err := api.Donut.ListMultipartUploads(bucket, resources) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
resources, err := api.Donut.ListMultipartUploads(bucket, resources, signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: // success case nil: // success
{ {
@ -153,7 +164,18 @@ func (api Minio) ListObjectsHandler(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req) vars := mux.Vars(req)
bucket := vars["bucket"] bucket := vars["bucket"]
objects, resources, err := api.Donut.ListObjects(bucket, resources) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
objects, resources, err := api.Donut.ListObjects(bucket, resources, signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
// generate response // generate response
@ -199,7 +221,18 @@ func (api Minio) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
// return // return
// } // }
buckets, err := api.Donut.ListBuckets() var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
buckets, err := api.Donut.ListBuckets(signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
// generate response // generate response
@ -250,7 +283,18 @@ func (api Minio) PutBucketHandler(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req) vars := mux.Vars(req)
bucket := vars["bucket"] bucket := vars["bucket"]
err := api.Donut.MakeBucket(bucket, getACLTypeString(aclType)) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
err := api.Donut.MakeBucket(bucket, getACLTypeString(aclType), signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
// Make sure to add Location information here only for bucket // Make sure to add Location information here only for bucket
@ -293,7 +337,18 @@ func (api Minio) PutBucketACLHandler(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req) vars := mux.Vars(req)
bucket := vars["bucket"] bucket := vars["bucket"]
err := api.Donut.SetBucketMetadata(bucket, map[string]string{"acl": getACLTypeString(aclType)}) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
err := api.Donut.SetBucketMetadata(bucket, map[string]string{"acl": getACLTypeString(aclType)}, signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
writeSuccessResponse(w, acceptsContentType) writeSuccessResponse(w, acceptsContentType)
@ -328,7 +383,18 @@ func (api Minio) HeadBucketHandler(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req) vars := mux.Vars(req)
bucket := vars["bucket"] bucket := vars["bucket"]
_, err := api.Donut.GetBucketMetadata(bucket) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
_, err := api.Donut.GetBucketMetadata(bucket, signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
writeSuccessResponse(w, acceptsContentType) writeSuccessResponse(w, acceptsContentType)

@ -54,7 +54,18 @@ func (api Minio) GetObjectHandler(w http.ResponseWriter, req *http.Request) {
bucket = vars["bucket"] bucket = vars["bucket"]
object = vars["object"] object = vars["object"]
metadata, err := api.Donut.GetObjectMetadata(bucket, object) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
metadata, err := api.Donut.GetObjectMetadata(bucket, object, signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: // success case nil: // success
{ {
@ -117,7 +128,18 @@ func (api Minio) HeadObjectHandler(w http.ResponseWriter, req *http.Request) {
bucket = vars["bucket"] bucket = vars["bucket"]
object = vars["object"] object = vars["object"]
metadata, err := api.Donut.GetObjectMetadata(bucket, object) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
metadata, err := api.Donut.GetObjectMetadata(bucket, object, signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
setObjectHeaders(w, metadata) setObjectHeaders(w, metadata)
@ -270,7 +292,18 @@ func (api Minio) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Requ
bucket = vars["bucket"] bucket = vars["bucket"]
object = vars["object"] object = vars["object"]
uploadID, err := api.Donut.NewMultipartUpload(bucket, object, "") var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
uploadID, err := api.Donut.NewMultipartUpload(bucket, object, req.Header.Get("Content-Type"), signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
{ {
@ -401,7 +434,18 @@ func (api Minio) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Re
objectResourcesMetadata := getObjectResources(req.URL.Query()) objectResourcesMetadata := getObjectResources(req.URL.Query())
err := api.Donut.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
err := api.Donut.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
setCommonHeaders(w, getContentTypeString(acceptsContentType), 0) setCommonHeaders(w, getContentTypeString(acceptsContentType), 0)
@ -439,7 +483,18 @@ func (api Minio) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request
bucket := vars["bucket"] bucket := vars["bucket"]
object := vars["object"] object := vars["object"]
objectResourcesMetadata, err := api.Donut.ListObjectParts(bucket, object, objectResourcesMetadata) var signature *donut.Signature
if _, ok := req.Header["Authorization"]; ok {
// Init signature V4 verification
var err error
signature, err = InitSignatureV4(req)
if err != nil {
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
return
}
}
objectResourcesMetadata, err := api.Donut.ListObjectParts(bucket, object, objectResourcesMetadata, signature)
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
{ {

@ -85,7 +85,7 @@ func generateListObjectsResponse(bucket string, objects []donut.ObjectMetadata,
continue continue
} }
content.Key = object.Object content.Key = object.Object
content.LastModified = object.Created.Format(iso8601Format) content.LastModified = object.Created.Format(rfcFormat)
content.ETag = "\"" + object.MD5Sum + "\"" content.ETag = "\"" + object.MD5Sum + "\""
content.Size = object.Size content.Size = object.Size
content.StorageClass = "STANDARD" content.StorageClass = "STANDARD"

Loading…
Cancel
Save