mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
web: Add more data for jsonrpc responses. (#3296)
This change adds more richer error response for JSON-RPC by interpreting object layer errors to corresponding meaningful errors for the web browser. ```go &json2.Error{ Message: "Bucket Name Invalid, Only lowercase letters, full stops, and numbers are allowed.", } ``` Additionally this patch also allows PresignedGetObject() to take expiry parameter to have variable expiry.
This commit is contained in:
parent
4098025c11
commit
dd93f808c8
@ -65,7 +65,7 @@ type RPCLoginReply struct {
|
|||||||
|
|
||||||
// Validates if incoming token is valid.
|
// Validates if incoming token is valid.
|
||||||
func isRPCTokenValid(tokenStr string) bool {
|
func isRPCTokenValid(tokenStr string) bool {
|
||||||
jwt, err := newJWT(defaultInterNodeJWTExpiry)
|
jwt, err := newJWT(defaultInterNodeJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err, "Unable to initialize JWT")
|
errorIf(err, "Unable to initialize JWT")
|
||||||
return false
|
return false
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
// Login handler implements JWT login token generator, which upon login request
|
// Login handler implements JWT login token generator, which upon login request
|
||||||
// along with username and password is generated.
|
// along with username and password is generated.
|
||||||
func (br *browserPeerAPIHandlers) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
func (br *browserPeerAPIHandlers) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
||||||
jwt, err := newJWT(defaultInterNodeJWTExpiry)
|
jwt, err := newJWT(defaultInterNodeJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ func registerStorageLockers(mux *router.Router, lockServers []*lockServer) error
|
|||||||
|
|
||||||
// LoginHandler - handles LoginHandler RPC call.
|
// LoginHandler - handles LoginHandler RPC call.
|
||||||
func (l *lockServer) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
func (l *lockServer) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
||||||
jwt, err := newJWT(defaultInterNodeJWTExpiry)
|
jwt, err := newJWT(defaultInterNodeJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ func createLockTestServer(t *testing.T) (string, *lockServer, string) {
|
|||||||
t.Fatalf("unable initialize config file, %s", err)
|
t.Fatalf("unable initialize config file, %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
jwt, err := newJWT(defaultJWTExpiry)
|
jwt, err := newJWT(defaultJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to get new JWT, %s", err)
|
t.Fatalf("unable to get new JWT, %s", err)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ package cmd
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
func (s3 *s3PeerAPIHandlers) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
func (s3 *s3PeerAPIHandlers) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
||||||
jwt, err := newJWT(defaultInterNodeJWTExpiry)
|
jwt, err := newJWT(defaultInterNodeJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -42,13 +42,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// newJWT - returns new JWT object.
|
// newJWT - returns new JWT object.
|
||||||
func newJWT(expiry time.Duration) (*JWT, error) {
|
func newJWT(expiry time.Duration, cred credential) (*JWT, error) {
|
||||||
if serverConfig == nil {
|
|
||||||
return nil, errServerNotInitialized
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save access, secret keys.
|
|
||||||
cred := serverConfig.GetCredential()
|
|
||||||
if !isValidAccessKey(cred.AccessKeyID) {
|
if !isValidAccessKey(cred.AccessKeyID) {
|
||||||
return nil, errInvalidAccessKeyLength
|
return nil, errInvalidAccessKeyLength
|
||||||
}
|
}
|
||||||
|
@ -70,16 +70,10 @@ func TestNewJWT(t *testing.T) {
|
|||||||
cred *credential
|
cred *credential
|
||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
// Test non-existent config directory.
|
|
||||||
{path.Join(path1, "non-existent-dir"), false, nil, errServerNotInitialized},
|
|
||||||
// Test empty config directory.
|
|
||||||
{path2, false, nil, errServerNotInitialized},
|
|
||||||
// Test empty config file.
|
|
||||||
{path3, false, nil, errServerNotInitialized},
|
|
||||||
// Test initialized config file.
|
// Test initialized config file.
|
||||||
{path4, true, nil, nil},
|
{path4, true, nil, nil},
|
||||||
// Test to read already created config file.
|
// Test to read already created config file.
|
||||||
{path4, false, nil, nil},
|
{path4, true, nil, nil},
|
||||||
// Access key is too small.
|
// Access key is too small.
|
||||||
{path4, false, &credential{"user", "pass"}, errInvalidAccessKeyLength},
|
{path4, false, &credential{"user", "pass"}, errInvalidAccessKeyLength},
|
||||||
// Access key is too long.
|
// Access key is too long.
|
||||||
@ -100,13 +94,10 @@ func TestNewJWT(t *testing.T) {
|
|||||||
t.Fatalf("unable initialize config file, %s", err)
|
t.Fatalf("unable initialize config file, %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if testCase.cred != nil {
|
if testCase.cred != nil {
|
||||||
serverConfig.SetCredential(*testCase.cred)
|
serverConfig.SetCredential(*testCase.cred)
|
||||||
}
|
}
|
||||||
|
_, err := newJWT(defaultJWTExpiry, serverConfig.GetCredential())
|
||||||
_, err := newJWT(defaultJWTExpiry)
|
|
||||||
|
|
||||||
if testCase.expectedErr != nil {
|
if testCase.expectedErr != nil {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("%+v: expected: %s, got: <nil>", testCase, testCase.expectedErr)
|
t.Fatalf("%+v: expected: %s, got: <nil>", testCase, testCase.expectedErr)
|
||||||
@ -128,7 +119,7 @@ func TestGenerateToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer removeAll(testPath)
|
defer removeAll(testPath)
|
||||||
|
|
||||||
jwt, err := newJWT(defaultJWTExpiry)
|
jwt, err := newJWT(defaultJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable get new JWT, %s", err)
|
t.Fatalf("unable get new JWT, %s", err)
|
||||||
}
|
}
|
||||||
@ -175,7 +166,7 @@ func TestAuthenticate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer removeAll(testPath)
|
defer removeAll(testPath)
|
||||||
|
|
||||||
jwt, err := newJWT(defaultJWTExpiry)
|
jwt, err := newJWT(defaultJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable get new JWT, %s", err)
|
t.Fatalf("unable get new JWT, %s", err)
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ type storageServer struct {
|
|||||||
|
|
||||||
// Login - login handler.
|
// Login - login handler.
|
||||||
func (s *storageServer) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
func (s *storageServer) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
|
||||||
jwt, err := newJWT(defaultInterNodeJWTExpiry)
|
jwt, err := newJWT(defaultInterNodeJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func createTestStorageServer(t *testing.T) *testStorageRPCServer {
|
|||||||
t.Fatalf("unable initialize config file, %s", err)
|
t.Fatalf("unable initialize config file, %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
jwt, err := newJWT(defaultInterNodeJWTExpiry)
|
jwt, err := newJWT(defaultInterNodeJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to get new JWT, %s", err)
|
t.Fatalf("unable to get new JWT, %s", err)
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -41,7 +42,7 @@ import (
|
|||||||
// isJWTReqAuthenticated validates if any incoming request to be a
|
// isJWTReqAuthenticated validates if any incoming request to be a
|
||||||
// valid JWT authenticated request.
|
// valid JWT authenticated request.
|
||||||
func isJWTReqAuthenticated(req *http.Request) bool {
|
func isJWTReqAuthenticated(req *http.Request) bool {
|
||||||
jwt, err := newJWT(defaultJWTExpiry)
|
jwt, err := newJWT(defaultJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err, "unable to initialize a new JWT")
|
errorIf(err, "unable to initialize a new JWT")
|
||||||
return false
|
return false
|
||||||
@ -85,7 +86,7 @@ type ServerInfoRep struct {
|
|||||||
// ServerInfo - get server info.
|
// ServerInfo - get server info.
|
||||||
func (web *webAPIHandlers) ServerInfo(r *http.Request, args *WebGenericArgs, reply *ServerInfoRep) error {
|
func (web *webAPIHandlers) ServerInfo(r *http.Request, args *WebGenericArgs, reply *ServerInfoRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
host, err := os.Hostname()
|
host, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -123,10 +124,10 @@ type StorageInfoRep struct {
|
|||||||
func (web *webAPIHandlers) StorageInfo(r *http.Request, args *GenericArgs, reply *StorageInfoRep) error {
|
func (web *webAPIHandlers) StorageInfo(r *http.Request, args *GenericArgs, reply *StorageInfoRep) error {
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
return toJSONError(errServerNotInitialized)
|
||||||
}
|
}
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
reply.StorageInfo = objectAPI.StorageInfo()
|
reply.StorageInfo = objectAPI.StorageInfo()
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
@ -142,13 +143,13 @@ type MakeBucketArgs struct {
|
|||||||
func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *WebGenericRep) error {
|
func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *WebGenericRep) error {
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
return toJSONError(errServerNotInitialized)
|
||||||
}
|
}
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
if err := objectAPI.MakeBucket(args.BucketName); err != nil {
|
if err := objectAPI.MakeBucket(args.BucketName); err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err, args.BucketName)
|
||||||
}
|
}
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
return nil
|
return nil
|
||||||
@ -172,14 +173,14 @@ type WebBucketInfo struct {
|
|||||||
func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, reply *ListBucketsRep) error {
|
func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, reply *ListBucketsRep) error {
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
return toJSONError(errServerNotInitialized)
|
||||||
}
|
}
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
buckets, err := objectAPI.ListBuckets()
|
buckets, err := objectAPI.ListBuckets()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err)
|
||||||
}
|
}
|
||||||
for _, bucket := range buckets {
|
for _, bucket := range buckets {
|
||||||
// List all buckets which are not private.
|
// List all buckets which are not private.
|
||||||
@ -222,12 +223,12 @@ type WebObjectInfo struct {
|
|||||||
func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, reply *ListObjectsRep) error {
|
func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, reply *ListObjectsRep) error {
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
return toJSONError(errServerNotInitialized)
|
||||||
|
}
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
marker := ""
|
marker := ""
|
||||||
if !isJWTReqAuthenticated(r) {
|
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
|
||||||
}
|
|
||||||
for {
|
for {
|
||||||
lo, err := objectAPI.ListObjects(args.BucketName, args.Prefix, marker, "/", 1000)
|
lo, err := objectAPI.ListObjects(args.BucketName, args.Prefix, marker, "/", 1000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -266,10 +267,10 @@ type RemoveObjectArgs struct {
|
|||||||
func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs, reply *WebGenericRep) error {
|
func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs, reply *WebGenericRep) error {
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
return toJSONError(errServerNotInitialized)
|
||||||
}
|
}
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
if err := objectAPI.DeleteObject(args.BucketName, args.ObjectName); err != nil {
|
if err := objectAPI.DeleteObject(args.BucketName, args.ObjectName); err != nil {
|
||||||
if isErrObjectNotFound(err) {
|
if isErrObjectNotFound(err) {
|
||||||
@ -277,7 +278,7 @@ func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs,
|
|||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err, args.BucketName, args.ObjectName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify object deleted event.
|
// Notify object deleted event.
|
||||||
@ -310,18 +311,18 @@ type LoginRep struct {
|
|||||||
|
|
||||||
// Login - user login handler.
|
// Login - user login handler.
|
||||||
func (web *webAPIHandlers) Login(r *http.Request, args *LoginArgs, reply *LoginRep) error {
|
func (web *webAPIHandlers) Login(r *http.Request, args *LoginArgs, reply *LoginRep) error {
|
||||||
jwt, err := newJWT(defaultJWTExpiry)
|
jwt, err := newJWT(defaultJWTExpiry, serverConfig.GetCredential())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = jwt.Authenticate(args.Username, args.Password); err != nil {
|
if err = jwt.Authenticate(args.Username, args.Password); err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := jwt.GenerateToken(args.Username)
|
token, err := jwt.GenerateToken(args.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err)
|
||||||
}
|
}
|
||||||
reply.Token = token
|
reply.Token = token
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
@ -337,7 +338,7 @@ type GenerateAuthReply struct {
|
|||||||
|
|
||||||
func (web webAPIHandlers) GenerateAuth(r *http.Request, args *WebGenericArgs, reply *GenerateAuthReply) error {
|
func (web webAPIHandlers) GenerateAuth(r *http.Request, args *WebGenericArgs, reply *GenerateAuthReply) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
cred := mustGenAccessKeys()
|
cred := mustGenAccessKeys()
|
||||||
reply.AccessKey = cred.AccessKeyID
|
reply.AccessKey = cred.AccessKeyID
|
||||||
@ -362,34 +363,46 @@ type SetAuthReply struct {
|
|||||||
// SetAuth - Set accessKey and secretKey credentials.
|
// SetAuth - Set accessKey and secretKey credentials.
|
||||||
func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *SetAuthReply) error {
|
func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *SetAuthReply) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
if !isValidAccessKey(args.AccessKey) {
|
|
||||||
return &json2.Error{Message: errInvalidAccessKeyLength.Error()}
|
// Initialize jwt with the new access keys, fail if not possible.
|
||||||
|
jwt, err := newJWT(defaultJWTExpiry, credential{
|
||||||
|
AccessKeyID: args.AccessKey,
|
||||||
|
SecretAccessKey: args.SecretKey,
|
||||||
|
}) // JWT Expiry set to 24Hrs.
|
||||||
|
if err != nil {
|
||||||
|
return toJSONError(err)
|
||||||
}
|
}
|
||||||
if !isValidSecretKey(args.SecretKey) {
|
|
||||||
return &json2.Error{Message: errInvalidSecretKeyLength.Error()}
|
// Authenticate the secret key properly.
|
||||||
|
if err = jwt.Authenticate(args.AccessKey, args.SecretKey); err != nil {
|
||||||
|
return toJSONError(err)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unexpErrsMsg := "Unexpected error(s) occurred - please check minio server logs."
|
||||||
|
gaveUpMsg := func(errMsg error, moreErrors bool) *json2.Error {
|
||||||
|
msg := fmt.Sprintf(
|
||||||
|
"We gave up due to: '%s', but there were more errors. Please check minio server logs.",
|
||||||
|
errMsg.Error(),
|
||||||
|
)
|
||||||
|
var err *json2.Error
|
||||||
|
if moreErrors {
|
||||||
|
err = toJSONError(errors.New(msg))
|
||||||
|
} else {
|
||||||
|
err = toJSONError(errMsg)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cred := credential{args.AccessKey, args.SecretKey}
|
cred := credential{args.AccessKey, args.SecretKey}
|
||||||
unexpErrsMsg := "ALERT: Unexpected error(s) happened - please check the server logs."
|
|
||||||
gaveUpMsg := func(errMsg error, moreErrors bool) *json2.Error {
|
|
||||||
msg := fmt.Sprintf(
|
|
||||||
"ALERT: We gave up due to: '%s', but there were more errors. Please check the server logs.",
|
|
||||||
errMsg.Error(),
|
|
||||||
)
|
|
||||||
if moreErrors {
|
|
||||||
return &json2.Error{Message: msg}
|
|
||||||
}
|
|
||||||
return &json2.Error{Message: errMsg.Error()}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify all other Minio peers to update credentials
|
// Notify all other Minio peers to update credentials
|
||||||
errsMap := updateCredsOnPeers(cred)
|
errsMap := updateCredsOnPeers(cred)
|
||||||
|
|
||||||
// Update local credentials
|
// Update local credentials
|
||||||
serverConfig.SetCredential(cred)
|
serverConfig.SetCredential(cred)
|
||||||
if err := serverConfig.Save(); err != nil {
|
if err = serverConfig.Save(); err != nil {
|
||||||
errsMap[globalMinioAddr] = err
|
errsMap[globalMinioAddr] = err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +420,7 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se
|
|||||||
// Since the error message may be very long to display
|
// Since the error message may be very long to display
|
||||||
// on the browser, we tell the user to check the
|
// on the browser, we tell the user to check the
|
||||||
// server logs.
|
// server logs.
|
||||||
return &json2.Error{Message: unexpErrsMsg}
|
return toJSONError(errors.New(unexpErrsMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did we have peer errors?
|
// Did we have peer errors?
|
||||||
@ -416,16 +429,7 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se
|
|||||||
moreErrors = true
|
moreErrors = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we were able to update locally, we try to generate a new
|
// Generate a JWT token.
|
||||||
// token and complete the request.
|
|
||||||
jwt, err := newJWT(defaultJWTExpiry) // JWT Expiry set to 24Hrs.
|
|
||||||
if err != nil {
|
|
||||||
return gaveUpMsg(err, moreErrors)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = jwt.Authenticate(args.AccessKey, args.SecretKey); err != nil {
|
|
||||||
return gaveUpMsg(err, moreErrors)
|
|
||||||
}
|
|
||||||
token, err := jwt.GenerateToken(args.AccessKey)
|
token, err := jwt.GenerateToken(args.AccessKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gaveUpMsg(err, moreErrors)
|
return gaveUpMsg(err, moreErrors)
|
||||||
@ -446,7 +450,7 @@ type GetAuthReply struct {
|
|||||||
// GetAuth - return accessKey and secretKey credentials.
|
// GetAuth - return accessKey and secretKey credentials.
|
||||||
func (web *webAPIHandlers) GetAuth(r *http.Request, args *WebGenericArgs, reply *GetAuthReply) error {
|
func (web *webAPIHandlers) GetAuth(r *http.Request, args *WebGenericArgs, reply *GetAuthReply) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
creds := serverConfig.GetCredential()
|
creds := serverConfig.GetCredential()
|
||||||
reply.AccessKey = creds.AccessKeyID
|
reply.AccessKey = creds.AccessKeyID
|
||||||
@ -511,7 +515,7 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
|
|||||||
object := vars["object"]
|
object := vars["object"]
|
||||||
tokenStr := r.URL.Query().Get("token")
|
tokenStr := r.URL.Query().Get("token")
|
||||||
|
|
||||||
jwt, err := newJWT(defaultJWTExpiry) // Expiry set to 24Hrs.
|
jwt, err := newJWT(defaultJWTExpiry, serverConfig.GetCredential()) // Expiry set to 24Hrs.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err, "error in getting new JWT")
|
errorIf(err, "error in getting new JWT")
|
||||||
return
|
return
|
||||||
@ -543,50 +547,6 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeWebErrorResponse - set HTTP status code and write error description to the body.
|
|
||||||
func writeWebErrorResponse(w http.ResponseWriter, err error) {
|
|
||||||
if err == errAuthentication {
|
|
||||||
w.WriteHeader(http.StatusForbidden)
|
|
||||||
w.Write([]byte(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err == errServerNotInitialized {
|
|
||||||
w.WriteHeader(http.StatusServiceUnavailable)
|
|
||||||
w.Write([]byte(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert error type to api error code.
|
|
||||||
var apiErrCode APIErrorCode
|
|
||||||
switch err.(type) {
|
|
||||||
case StorageFull:
|
|
||||||
apiErrCode = ErrStorageFull
|
|
||||||
case BucketNotFound:
|
|
||||||
apiErrCode = ErrNoSuchBucket
|
|
||||||
case BucketNameInvalid:
|
|
||||||
apiErrCode = ErrInvalidBucketName
|
|
||||||
case BadDigest:
|
|
||||||
apiErrCode = ErrBadDigest
|
|
||||||
case IncompleteBody:
|
|
||||||
apiErrCode = ErrIncompleteBody
|
|
||||||
case ObjectExistsAsDirectory:
|
|
||||||
apiErrCode = ErrObjectExistsAsDirectory
|
|
||||||
case ObjectNotFound:
|
|
||||||
apiErrCode = ErrNoSuchKey
|
|
||||||
case ObjectNameInvalid:
|
|
||||||
apiErrCode = ErrNoSuchKey
|
|
||||||
case InsufficientWriteQuorum:
|
|
||||||
apiErrCode = ErrWriteQuorum
|
|
||||||
case InsufficientReadQuorum:
|
|
||||||
apiErrCode = ErrReadQuorum
|
|
||||||
default:
|
|
||||||
apiErrCode = ErrInternalError
|
|
||||||
}
|
|
||||||
apiErr := getAPIError(apiErrCode)
|
|
||||||
w.WriteHeader(apiErr.HTTPStatusCode)
|
|
||||||
w.Write([]byte(apiErr.Description))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBucketPolicyArgs - get bucket policy args.
|
// GetBucketPolicyArgs - get bucket policy args.
|
||||||
type GetBucketPolicyArgs struct {
|
type GetBucketPolicyArgs struct {
|
||||||
BucketName string `json:"bucketName"`
|
BucketName string `json:"bucketName"`
|
||||||
@ -627,16 +587,16 @@ func readBucketAccessPolicy(objAPI ObjectLayer, bucketName string) (policy.Bucke
|
|||||||
func (web *webAPIHandlers) GetBucketPolicy(r *http.Request, args *GetBucketPolicyArgs, reply *GetBucketPolicyRep) error {
|
func (web *webAPIHandlers) GetBucketPolicy(r *http.Request, args *GetBucketPolicyArgs, reply *GetBucketPolicyRep) error {
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
return toJSONError(errServerNotInitialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err, args.BucketName)
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
@ -666,16 +626,16 @@ type ListAllBucketPoliciesRep struct {
|
|||||||
func (web *webAPIHandlers) ListAllBucketPolicies(r *http.Request, args *ListAllBucketPoliciesArgs, reply *ListAllBucketPoliciesRep) error {
|
func (web *webAPIHandlers) ListAllBucketPolicies(r *http.Request, args *ListAllBucketPoliciesArgs, reply *ListAllBucketPoliciesRep) error {
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
return toJSONError(errServerNotInitialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err, args.BucketName)
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
@ -699,33 +659,36 @@ type SetBucketPolicyArgs struct {
|
|||||||
func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolicyArgs, reply *WebGenericRep) error {
|
func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolicyArgs, reply *WebGenericRep) error {
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
return toJSONError(errServerNotInitialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
bucketP := policy.BucketPolicy(args.Policy)
|
bucketP := policy.BucketPolicy(args.Policy)
|
||||||
if !bucketP.IsValidBucketPolicy() {
|
if !bucketP.IsValidBucketPolicy() {
|
||||||
return &json2.Error{Message: "Invalid policy type " + args.Policy}
|
return &json2.Error{
|
||||||
|
Message: "Invalid policy type " + args.Policy,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err, args.BucketName)
|
||||||
}
|
}
|
||||||
policyInfo.Statements = policy.SetPolicy(policyInfo.Statements, bucketP, args.BucketName, args.Prefix)
|
policyInfo.Statements = policy.SetPolicy(policyInfo.Statements, bucketP, args.BucketName, args.Prefix)
|
||||||
if len(policyInfo.Statements) == 0 {
|
if len(policyInfo.Statements) == 0 {
|
||||||
if err = persistAndNotifyBucketPolicyChange(args.BucketName, policyChange{true, nil}, objectAPI); err != nil {
|
err = persistAndNotifyBucketPolicyChange(args.BucketName, policyChange{true, nil}, objectAPI)
|
||||||
return &json2.Error{Message: err.Error()}
|
if err != nil {
|
||||||
|
return toJSONError(err, args.BucketName)
|
||||||
}
|
}
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
data, err := json.Marshal(policyInfo)
|
data, err := json.Marshal(policyInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse bucket policy.
|
// Parse bucket policy.
|
||||||
@ -733,18 +696,19 @@ func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolic
|
|||||||
err = parseBucketPolicy(bytes.NewReader(data), policy)
|
err = parseBucketPolicy(bytes.NewReader(data), policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err, "Unable to parse bucket policy.")
|
errorIf(err, "Unable to parse bucket policy.")
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse check bucket policy.
|
// Parse check bucket policy.
|
||||||
if s3Error := checkBucketPolicyResources(args.BucketName, policy); s3Error != ErrNone {
|
if s3Error := checkBucketPolicyResources(args.BucketName, policy); s3Error != ErrNone {
|
||||||
return &json2.Error{Message: getAPIError(s3Error).Description}
|
apiErr := getAPIError(s3Error)
|
||||||
|
return toJSONError(errors.New(apiErr.Description), args.BucketName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: update policy statements according to bucket name,
|
// TODO: update policy statements according to bucket name,
|
||||||
// prefix and policy arguments.
|
// prefix and policy arguments.
|
||||||
if err := persistAndNotifyBucketPolicyChange(args.BucketName, policyChange{false, policy}, objectAPI); err != nil {
|
if err := persistAndNotifyBucketPolicyChange(args.BucketName, policyChange{false, policy}, objectAPI); err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return toJSONError(err, args.BucketName)
|
||||||
}
|
}
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
return nil
|
return nil
|
||||||
@ -760,6 +724,9 @@ type PresignedGetArgs struct {
|
|||||||
|
|
||||||
// Object name to be presigned.
|
// Object name to be presigned.
|
||||||
ObjectName string `json:"object"`
|
ObjectName string `json:"object"`
|
||||||
|
|
||||||
|
// Expiry in seconds.
|
||||||
|
Expiry int64 `json:"expiry"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PresignedGetRep - presigned-get URL reply.
|
// PresignedGetRep - presigned-get URL reply.
|
||||||
@ -771,22 +738,22 @@ type PresignedGetRep struct {
|
|||||||
|
|
||||||
// PresignedGET - returns presigned-Get url.
|
// PresignedGET - returns presigned-Get url.
|
||||||
func (web *webAPIHandlers) PresignedGet(r *http.Request, args *PresignedGetArgs, reply *PresignedGetRep) error {
|
func (web *webAPIHandlers) PresignedGet(r *http.Request, args *PresignedGetArgs, reply *PresignedGetRep) error {
|
||||||
if web.ObjectAPI() == nil {
|
|
||||||
return &json2.Error{Message: errServerNotInitialized.Error()}
|
|
||||||
}
|
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: errAuthentication.Error()}
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.BucketName == "" || args.ObjectName == "" {
|
if args.BucketName == "" || args.ObjectName == "" {
|
||||||
return &json2.Error{Message: "Bucket, Object are mandatory arguments."}
|
return &json2.Error{
|
||||||
|
Message: "Bucket and Object are mandatory arguments.",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
reply.URL = presignedGet(args.HostName, args.BucketName, args.ObjectName)
|
reply.URL = presignedGet(args.HostName, args.BucketName, args.ObjectName, args.Expiry)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns presigned url for GET method.
|
// Returns presigned url for GET method.
|
||||||
func presignedGet(host, bucket, object string) string {
|
func presignedGet(host, bucket, object string, expiry int64) string {
|
||||||
cred := serverConfig.GetCredential()
|
cred := serverConfig.GetCredential()
|
||||||
region := serverConfig.GetRegion()
|
region := serverConfig.GetRegion()
|
||||||
|
|
||||||
@ -797,11 +764,15 @@ func presignedGet(host, bucket, object string) string {
|
|||||||
dateStr := date.Format(iso8601Format)
|
dateStr := date.Format(iso8601Format)
|
||||||
credential := fmt.Sprintf("%s/%s", accessKey, getScope(date, region))
|
credential := fmt.Sprintf("%s/%s", accessKey, getScope(date, region))
|
||||||
|
|
||||||
|
var expiryStr = "604800" // Default set to be expire in 7days.
|
||||||
|
if expiry < 604800 && expiry > 0 {
|
||||||
|
expiryStr = strconv.FormatInt(expiry, 10)
|
||||||
|
}
|
||||||
query := strings.Join([]string{
|
query := strings.Join([]string{
|
||||||
"X-Amz-Algorithm=" + signV4Algorithm,
|
"X-Amz-Algorithm=" + signV4Algorithm,
|
||||||
"X-Amz-Credential=" + strings.Replace(credential, "/", "%2F", -1),
|
"X-Amz-Credential=" + strings.Replace(credential, "/", "%2F", -1),
|
||||||
"X-Amz-Date=" + dateStr,
|
"X-Amz-Date=" + dateStr,
|
||||||
"X-Amz-Expires=" + "604800", // Default set to be expire in 7days.
|
"X-Amz-Expires=" + expiryStr,
|
||||||
"X-Amz-SignedHeaders=host",
|
"X-Amz-SignedHeaders=host",
|
||||||
}, "&")
|
}, "&")
|
||||||
|
|
||||||
@ -818,3 +789,93 @@ func presignedGet(host, bucket, object string) string {
|
|||||||
// Construct the final presigned URL.
|
// Construct the final presigned URL.
|
||||||
return host + path + "?" + query + "&" + "X-Amz-Signature=" + signature
|
return host + path + "?" + query + "&" + "X-Amz-Signature=" + signature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toJSONError converts regular errors into more user friendly
|
||||||
|
// and consumable error message for the browser UI.
|
||||||
|
func toJSONError(err error, params ...string) (jerr *json2.Error) {
|
||||||
|
apiErr := toWebAPIError(err)
|
||||||
|
jerr = &json2.Error{
|
||||||
|
Message: apiErr.Description,
|
||||||
|
}
|
||||||
|
switch apiErr.Code {
|
||||||
|
// Bucket name invalid with custom error message.
|
||||||
|
case "InvalidBucketName":
|
||||||
|
if len(params) > 0 {
|
||||||
|
jerr = &json2.Error{
|
||||||
|
Message: fmt.Sprintf("Bucket Name %s is invalid. Lowercase letters, period and numerals are the only allowed characters.",
|
||||||
|
params[0]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Bucket not found custom error message.
|
||||||
|
case "NoSuchBucket":
|
||||||
|
if len(params) > 0 {
|
||||||
|
jerr = &json2.Error{
|
||||||
|
Message: fmt.Sprintf("The specified bucket %s does not exist.", params[0]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Object not found custom error message.
|
||||||
|
case "NoSuchKey":
|
||||||
|
if len(params) > 1 {
|
||||||
|
jerr = &json2.Error{
|
||||||
|
Message: fmt.Sprintf("The specified key %s does not exist", params[1]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add more custom error messages here with more context.
|
||||||
|
}
|
||||||
|
return jerr
|
||||||
|
}
|
||||||
|
|
||||||
|
// toWebAPIError - convert into error into APIError.
|
||||||
|
func toWebAPIError(err error) APIError {
|
||||||
|
err = errorCause(err)
|
||||||
|
if err == errAuthentication {
|
||||||
|
return APIError{
|
||||||
|
Code: "AccessDenied",
|
||||||
|
HTTPStatusCode: http.StatusForbidden,
|
||||||
|
Description: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == errServerNotInitialized {
|
||||||
|
return APIError{
|
||||||
|
Code: "XMinioServerNotInitialized",
|
||||||
|
HTTPStatusCode: http.StatusServiceUnavailable,
|
||||||
|
Description: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert error type to api error code.
|
||||||
|
var apiErrCode APIErrorCode
|
||||||
|
switch err.(type) {
|
||||||
|
case StorageFull:
|
||||||
|
apiErrCode = ErrStorageFull
|
||||||
|
case BucketNotFound:
|
||||||
|
apiErrCode = ErrNoSuchBucket
|
||||||
|
case BucketNameInvalid:
|
||||||
|
apiErrCode = ErrInvalidBucketName
|
||||||
|
case BadDigest:
|
||||||
|
apiErrCode = ErrBadDigest
|
||||||
|
case IncompleteBody:
|
||||||
|
apiErrCode = ErrIncompleteBody
|
||||||
|
case ObjectExistsAsDirectory:
|
||||||
|
apiErrCode = ErrObjectExistsAsDirectory
|
||||||
|
case ObjectNotFound:
|
||||||
|
apiErrCode = ErrNoSuchKey
|
||||||
|
case ObjectNameInvalid:
|
||||||
|
apiErrCode = ErrNoSuchKey
|
||||||
|
case InsufficientWriteQuorum:
|
||||||
|
apiErrCode = ErrWriteQuorum
|
||||||
|
case InsufficientReadQuorum:
|
||||||
|
apiErrCode = ErrReadQuorum
|
||||||
|
default:
|
||||||
|
apiErrCode = ErrInternalError
|
||||||
|
}
|
||||||
|
apiErr := getAPIError(apiErrCode)
|
||||||
|
return apiErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeWebErrorResponse - set HTTP status code and write error description to the body.
|
||||||
|
func writeWebErrorResponse(w http.ResponseWriter, err error) {
|
||||||
|
apiErr := toWebAPIError(err)
|
||||||
|
w.WriteHeader(apiErr.HTTPStatusCode)
|
||||||
|
w.Write([]byte(apiErr.Description))
|
||||||
|
}
|
||||||
|
@ -485,8 +485,8 @@ func testRemoveObjectWebHandler(obj ObjectLayer, instanceType string, t TestErrH
|
|||||||
|
|
||||||
data := bytes.Repeat([]byte("a"), objectSize)
|
data := bytes.Repeat([]byte("a"), objectSize)
|
||||||
|
|
||||||
_, err = obj.PutObject(bucketName, objectName, int64(len(data)), bytes.NewReader(data), map[string]string{"md5Sum": "c9a34cfc85d982698c6ac89f76071abd"}, "")
|
_, err = obj.PutObject(bucketName, objectName, int64(len(data)), bytes.NewReader(data),
|
||||||
|
map[string]string{"md5Sum": "c9a34cfc85d982698c6ac89f76071abd"}, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Was not able to upload an object, %v", err)
|
t.Fatalf("Was not able to upload an object, %v", err)
|
||||||
}
|
}
|
||||||
@ -505,6 +505,21 @@ func testRemoveObjectWebHandler(obj ObjectLayer, instanceType string, t TestErrH
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed, %v", err)
|
t.Fatalf("Failed, %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeObjectRequest = RemoveObjectArgs{BucketName: bucketName, ObjectName: objectName}
|
||||||
|
removeObjectReply = &WebGenericRep{}
|
||||||
|
req, err = newTestWebRPCRequest("Web.RemoveObject", authorization, removeObjectRequest)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create HTTP request: <ERROR> %v", err)
|
||||||
|
}
|
||||||
|
apiRouter.ServeHTTP(rec, req)
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||||
|
}
|
||||||
|
err = getTestWebRPCResponse(rec, &removeObjectReply)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed, %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper for calling Generate Auth Handler
|
// Wrapper for calling Generate Auth Handler
|
||||||
@ -585,6 +600,7 @@ func testSetAuthWebHandler(obj ObjectLayer, instanceType string, t TestErrHandle
|
|||||||
success bool
|
success bool
|
||||||
}{
|
}{
|
||||||
{"", "", false},
|
{"", "", false},
|
||||||
|
{"1", "1", false},
|
||||||
{"azerty", "foooooooooooooo", true},
|
{"azerty", "foooooooooooooo", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,6 +842,7 @@ func testWebPresignedGetHandler(obj ObjectLayer, instanceType string, t TestErrH
|
|||||||
HostName: "",
|
HostName: "",
|
||||||
BucketName: bucketName,
|
BucketName: bucketName,
|
||||||
ObjectName: objectName,
|
ObjectName: objectName,
|
||||||
|
Expiry: 1000,
|
||||||
}
|
}
|
||||||
presignGetRep := &PresignedGetRep{}
|
presignGetRep := &PresignedGetRep{}
|
||||||
req, err := newTestWebRPCRequest("Web.PresignedGet", authorization, presignGetReq)
|
req, err := newTestWebRPCRequest("Web.PresignedGet", authorization, presignGetReq)
|
||||||
@ -885,8 +902,8 @@ func testWebPresignedGetHandler(obj ObjectLayer, instanceType string, t TestErrH
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Failed, %v", err)
|
t.Fatalf("Failed, %v", err)
|
||||||
}
|
}
|
||||||
if err.Error() != "Bucket, Object are mandatory arguments." {
|
if err.Error() != "Bucket and Object are mandatory arguments." {
|
||||||
t.Fatalf("Unexpected, expected `Bucket, Object are mandatory arguments`, got %s", err)
|
t.Fatalf("Unexpected, expected `Bucket and Object are mandatory arguments`, got %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1329,6 +1346,12 @@ func TestWebObjectLayerNotReady(t *testing.T) {
|
|||||||
|
|
||||||
// TestWebObjectLayerFaultyDisks - Test Web RPC responses with faulty disks
|
// TestWebObjectLayerFaultyDisks - Test Web RPC responses with faulty disks
|
||||||
func TestWebObjectLayerFaultyDisks(t *testing.T) {
|
func TestWebObjectLayerFaultyDisks(t *testing.T) {
|
||||||
|
root, err := newTestConfig("us-east-1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer removeAll(root)
|
||||||
|
|
||||||
// Prepare XL backend
|
// Prepare XL backend
|
||||||
obj, fsDirs, err := prepareXL()
|
obj, fsDirs, err := prepareXL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user