github.com/minio/minio-go/v6@v6.0.57/api-get-object-acl-context.go (about)

     1  /*
     2   * MinIO Go Library for Amazon S3 Compatible Cloud Storage
     3   * Copyright 2018 MinIO, Inc.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package minio
    19  
    20  import (
    21  	"context"
    22  	"net/http"
    23  	"net/url"
    24  )
    25  
    26  type accessControlPolicy struct {
    27  	Owner struct {
    28  		ID          string `xml:"ID"`
    29  		DisplayName string `xml:"DisplayName"`
    30  	} `xml:"Owner"`
    31  	AccessControlList struct {
    32  		Grant []struct {
    33  			Grantee struct {
    34  				ID          string `xml:"ID"`
    35  				DisplayName string `xml:"DisplayName"`
    36  				URI         string `xml:"URI"`
    37  			} `xml:"Grantee"`
    38  			Permission string `xml:"Permission"`
    39  		} `xml:"Grant"`
    40  	} `xml:"AccessControlList"`
    41  }
    42  
    43  //GetObjectACLWithContext get object ACLs
    44  func (c Client) GetObjectACLWithContext(ctx context.Context, bucketName, objectName string) (*ObjectInfo, error) {
    45  	resp, err := c.executeMethod(ctx, "GET", requestMetadata{
    46  		bucketName: bucketName,
    47  		objectName: objectName,
    48  		queryValues: url.Values{
    49  			"acl": []string{""},
    50  		},
    51  	})
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	defer closeResponse(resp)
    56  
    57  	if resp.StatusCode != http.StatusOK {
    58  		return nil, httpRespToErrorResponse(resp, bucketName, objectName)
    59  	}
    60  
    61  	res := &accessControlPolicy{}
    62  
    63  	if err := xmlDecoder(resp.Body, res); err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	objInfo, err := c.statObject(ctx, bucketName, objectName, StatObjectOptions{})
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	objInfo.Owner.DisplayName = res.Owner.DisplayName
    73  	objInfo.Owner.ID = res.Owner.ID
    74  
    75  	objInfo.Grant = append(objInfo.Grant, res.AccessControlList.Grant...)
    76  
    77  	cannedACL := getCannedACL(res)
    78  	if cannedACL != "" {
    79  		objInfo.Metadata.Add("X-Amz-Acl", cannedACL)
    80  		return &objInfo, nil
    81  	}
    82  
    83  	grantACL := getAmzGrantACL(res)
    84  	for k, v := range grantACL {
    85  		objInfo.Metadata[k] = v
    86  	}
    87  
    88  	return &objInfo, nil
    89  }
    90  
    91  func getCannedACL(aCPolicy *accessControlPolicy) string {
    92  	grants := aCPolicy.AccessControlList.Grant
    93  
    94  	switch {
    95  	case len(grants) == 1:
    96  		if grants[0].Grantee.URI == "" && grants[0].Permission == "FULL_CONTROL" {
    97  			return "private"
    98  		}
    99  	case len(grants) == 2:
   100  		for _, g := range grants {
   101  			if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" && g.Permission == "READ" {
   102  				return "authenticated-read"
   103  			}
   104  			if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" && g.Permission == "READ" {
   105  				return "public-read"
   106  			}
   107  			if g.Permission == "READ" && g.Grantee.ID == aCPolicy.Owner.ID {
   108  				return "bucket-owner-read"
   109  			}
   110  		}
   111  	case len(grants) == 3:
   112  		for _, g := range grants {
   113  			if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" && g.Permission == "WRITE" {
   114  				return "public-read-write"
   115  			}
   116  		}
   117  	}
   118  	return ""
   119  }
   120  
   121  func getAmzGrantACL(aCPolicy *accessControlPolicy) map[string][]string {
   122  	grants := aCPolicy.AccessControlList.Grant
   123  	res := map[string][]string{}
   124  
   125  	for _, g := range grants {
   126  		switch {
   127  		case g.Permission == "READ":
   128  			res["X-Amz-Grant-Read"] = append(res["X-Amz-Grant-Read"], "id="+g.Grantee.ID)
   129  		case g.Permission == "WRITE":
   130  			res["X-Amz-Grant-Write"] = append(res["X-Amz-Grant-Write"], "id="+g.Grantee.ID)
   131  		case g.Permission == "READ_ACP":
   132  			res["X-Amz-Grant-Read-Acp"] = append(res["X-Amz-Grant-Read-Acp"], "id="+g.Grantee.ID)
   133  		case g.Permission == "WRITE_ACP":
   134  			res["X-Amz-Grant-Write-Acp"] = append(res["X-Amz-Grant-Write-Acp"], "id="+g.Grantee.ID)
   135  		case g.Permission == "FULL_CONTROL":
   136  			res["X-Amz-Grant-Full-Control"] = append(res["X-Amz-Grant-Full-Control"], "id="+g.Grantee.ID)
   137  		}
   138  	}
   139  	return res
   140  }