This commit is contained in:
Adele Reed 2019-12-17 09:41:31 -08:00
Родитель 825ad79141
Коммит f90cde75cd
15 изменённых файлов: 206 добавлений и 33 удалений

Просмотреть файл

@ -58,10 +58,26 @@ func (d DirectoryURL) NewDirectoryURL(directoryName string) DirectoryURL {
// Create creates a new directory within a storage account.
// For more information, see https://docs.microsoft.com/rest/api/storageservices/create-directory.
// Pass default values for SMB properties (ex: "None" for file attributes).
func (d DirectoryURL) Create(ctx context.Context, metadata Metadata) (*DirectoryCreateResponse, error) {
defaultPermissions := "inherit"
// If permissions is empty, the default permission "inherit" is used.
// For SDDL strings over 9KB, upload using ShareURL.CreatePermission, and supply the permissionKey.
func (d DirectoryURL) Create(ctx context.Context, metadata Metadata, permissions, permissionKey string) (*DirectoryCreateResponse, error) {
defaultPermissions := &defaultPermissionString
// pkptr (permission key pointer) remains nil unless the user defines a permission key.
var pkptr *string
// If the user is supplying a permission key, permissions will be empty.
if permissions != "" {
defaultPermissions = &permissions
}
// This is handled AFTER permissions, in case the user accidentally supplies both.
if permissionKey != "" {
defaultPermissions = nil
pkptr = &permissionKey
}
return d.directoryClient.Create(ctx, "None", "now", "now", nil, metadata,
&defaultPermissions, nil)
defaultPermissions, pkptr)
}
// Delete removes the specified empty directory. Note that the directory must be empty before it can be deleted..
@ -76,6 +92,28 @@ func (d DirectoryURL) GetProperties(ctx context.Context) (*DirectoryGetPropertie
return d.directoryClient.GetProperties(ctx, nil, nil)
}
// SetProperties sets the directory's metadata and system properties.
// Preserves values for SMB properties.
// For more information, see https://docs.microsoft.com/en-us/rest/api/storageservices/set-directory-properties.
func (d DirectoryURL) SetProperties(ctx context.Context, permissions, permissionKey string) (*DirectorySetPropertiesResponse, error) {
defaultPermissions := &defaultPreservePermissionString
// pkptr (permission key pointer) remains nil unless the user defines a permission key.
var pkptr *string
// If the user is supplying a permission key, permissions will be empty.
if permissions != "" {
defaultPermissions = &permissions
}
// This is handled AFTER permissions, in case the user accidentally supplies both.
if permissionKey != "" {
defaultPermissions = nil
pkptr = &permissionKey
}
return d.directoryClient.SetProperties(ctx, "preserve", "preserve", "preserve", nil, defaultPermissions, pkptr)
}
// SetMetadata sets the directory's metadata.
// For more information, see https://docs.microsoft.com/rest/api/storageservices/set-directory-metadata.
func (d DirectoryURL) SetMetadata(ctx context.Context, metadata Metadata) (*DirectorySetMetadataResponse, error) {

Просмотреть файл

@ -3,6 +3,7 @@ package azfile
import (
"context"
"errors"
"fmt"
"io"
"net/http"
"net/url"
@ -20,6 +21,11 @@ const (
FileMaxSizeInBytes int64 = 1 * 1024 * 1024 * 1024 * 1024 // 1TB
)
// For all intents and purposes, this is a constant.
// But you can't take the address of a constant string, so it's a variable.
var defaultPermissionString = "inherit"
var defaultPreservePermissionString = "preserve"
// A FileURL represents a URL to an Azure Storage file.
type FileURL struct {
fileClient fileClient
@ -60,10 +66,24 @@ func (f FileURL) WithSnapshot(shareSnapshot string) FileURL {
// For more information, see https://docs.microsoft.com/en-us/rest/api/storageservices/create-file.
// Pass default values for SMB properties (ex: "None" for file attributes).
func (f FileURL) Create(ctx context.Context, size int64, h FileHTTPHeaders, metadata Metadata) (*FileCreateResponse, error) {
defaultPermissions := "inherit"
defaultPermissions := &defaultPermissionString
// pkptr (permission key pointer) remains nil unless the user defines a permission key.
var pkptr *string
// If the user is supplying a permission key, permissions will be empty.
if h.PermissionString != "" {
defaultPermissions = &h.PermissionString
}
// This is handled AFTER permissions, in case the user accidentally supplies both.
if h.PermissionKey != "" {
defaultPermissions = nil
pkptr = &h.PermissionKey
}
return f.fileClient.Create(ctx, size, "None", "now", "now", nil,
&h.ContentType, &h.ContentEncoding, &h.ContentLanguage, &h.CacheControl,
h.ContentMD5, &h.ContentDisposition, metadata, &defaultPermissions, nil)
h.ContentMD5, &h.ContentDisposition, metadata, defaultPermissions, pkptr)
}
// StartCopy copies the data at the source URL to a file.
@ -142,10 +162,26 @@ func (f FileURL) GetProperties(ctx context.Context) (*FileGetPropertiesResponse,
// SetHTTPHeaders sets file's system properties.
// For more information, see https://docs.microsoft.com/rest/api/storageservices/set-file-properties.
func (f FileURL) SetHTTPHeaders(ctx context.Context, h FileHTTPHeaders) (*FileSetHTTPHeadersResponse, error) {
defaultPermissions := "preserve"
defaultPermissions := &defaultPreservePermissionString
// pkptr (permission key pointer) remains nil unless the user defines a permission key.
var pkptr *string
// If the user is supplying a permission key, permissions will be empty.
if h.PermissionString != "" {
defaultPermissions = &h.PermissionString
}
// This is handled AFTER permissions, in case the user accidentally supplies both.
if h.PermissionKey != "" {
defaultPermissions = nil
pkptr = &h.PermissionKey
}
fmt.Println(defaultPermissions, *defaultPermissions, pkptr)
return f.fileClient.SetHTTPHeaders(ctx, "preserve", "preserve", "preserve", nil,
nil, &h.ContentType, &h.ContentEncoding, &h.ContentLanguage, &h.CacheControl, h.ContentMD5,
&h.ContentDisposition, &defaultPermissions, nil)
&h.ContentDisposition, defaultPermissions, nil)
}
// SetMetadata sets a file's metadata.

Просмотреть файл

@ -116,6 +116,22 @@ func (s ShareURL) GetPermissions(ctx context.Context) (*SignedIdentifiers, error
return s.shareClient.GetAccessPolicy(ctx, nil)
}
// CreatePermission uploads a SDDL permission string, and returns a permission key to use in conjunction with a file or folder.
// Note that this is only required for 9KB or larger permission strings.
// Furthermore, note that SDDL strings should be converted to a portable format before being uploaded.
// In order to make a SDDL portable, please replace well-known SIDs with their domain specific counterpart.
// Well-known SIDs are listed here: https://docs.microsoft.com/en-us/windows/win32/secauthz/sid-strings
// More info about SDDL strings can be located at: https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format
func (s ShareURL) CreatePermission(ctx context.Context, permission string) (*ShareCreatePermissionResponse, error) {
perm := SharePermission{Permission: permission}
return s.shareClient.CreatePermission(ctx, perm, nil)
}
// GetPermission obtains a SDDL permission string from the service using a known permission key.
func (s ShareURL) GetPermission(ctx context.Context, permissionKey string) (*SharePermission, error) {
return s.shareClient.GetPermission(ctx, permissionKey, nil)
}
// The AccessPolicyPermission type simplifies creating the permissions string for a share's access policy.
// Initialize an instance of this type and then call its String method to set AccessPolicy's Permission field.
type AccessPolicyPermission struct {

Просмотреть файл

@ -99,7 +99,7 @@ func Example() {
// New a reference to a directory with name DemoDir in share, and create the directory.
directoryDemoURL := shareURL.NewDirectoryURL("DemoDir")
_, err = directoryDemoURL.Create(ctx, azfile.Metadata{})
_, err = directoryDemoURL.Create(ctx, azfile.Metadata{}, "", "")
if err != nil && err.(azfile.StorageError) != nil && err.(azfile.StorageError).ServiceCode() != azfile.ServiceCodeResourceAlreadyExists {
log.Fatal(err)
}

Просмотреть файл

@ -183,7 +183,7 @@ func createNewDirectoryWithPrefix(c *chk.C, parentDirectory azfile.DirectoryURL,
name = generateName(prefix)
dir = parentDirectory.NewDirectoryURL(name)
cResp, err := dir.Create(ctx, azfile.Metadata{})
cResp, err := dir.Create(ctx, azfile.Metadata{}, "", "")
c.Assert(err, chk.IsNil)
c.Assert(cResp.StatusCode(), chk.Equals, 201)
return dir, name
@ -202,7 +202,7 @@ func createNewFileWithPrefix(c *chk.C, dir azfile.DirectoryURL, prefix string, s
func createNewDirectoryFromShare(c *chk.C, share azfile.ShareURL) (dir azfile.DirectoryURL, name string) {
dir, name = getDirectoryURLFromShare(c, share)
cResp, err := dir.Create(ctx, nil)
cResp, err := dir.Create(ctx, nil, "", "")
c.Assert(err, chk.IsNil)
c.Assert(cResp.StatusCode(), chk.Equals, 201)
return dir, name
@ -211,7 +211,7 @@ func createNewDirectoryFromShare(c *chk.C, share azfile.ShareURL) (dir azfile.Di
func createNewDirectoryFromDirectory(c *chk.C, parentDirectory azfile.DirectoryURL) (dir azfile.DirectoryURL, name string) {
dir, name = getDirectoryURLFromDirectory(c, parentDirectory)
cResp, err := dir.Create(ctx, nil)
cResp, err := dir.Create(ctx, nil, "", "")
c.Assert(err, chk.IsNil)
c.Assert(cResp.StatusCode(), chk.Equals, 201)
return dir, name

Просмотреть файл

@ -52,7 +52,7 @@ func (s *DirectoryURLSuite) TestDirWithNewPipeline(c *chk.C) {
dirURL := fsu.NewShareURL(sharePrefix).NewDirectoryURL(directoryPrefix)
newDirURL := dirURL.WithPipeline(testPipeline{})
_, err := newDirURL.Create(ctx, azfile.Metadata{})
_, err := newDirURL.Create(ctx, azfile.Metadata{}, "", "")
c.Assert(err, chk.NotNil)
c.Assert(err.Error(), chk.Equals, testPipelineMessage)
}
@ -66,7 +66,7 @@ func (s *DirectoryURLSuite) TestDirCreateDeleteDefault(c *chk.C) {
directory := share.NewDirectoryURL(directoryName)
cResp, err := directory.Create(context.Background(), azfile.Metadata{})
cResp, err := directory.Create(context.Background(), azfile.Metadata{}, "", "")
c.Assert(err, chk.IsNil)
c.Assert(cResp.Response().StatusCode, chk.Equals, 201)
c.Assert(cResp.Date().IsZero(), chk.Equals, false)
@ -82,6 +82,31 @@ func (s *DirectoryURLSuite) TestDirCreateDeleteDefault(c *chk.C) {
defer delDirectory(c, directory)
}
func (s *DirectoryURLSuite) TestDirSetProperties(c *chk.C) {
directoryName := generateDirectoryName()
sa := getFSU()
share, _ := createNewShare(c, sa)
defer delShare(c, share, azfile.DeleteSnapshotsOptionNone)
directory := share.NewDirectoryURL(directoryName)
cResp, err := directory.Create(ctx, azfile.Metadata{}, "", "")
c.Assert(err, chk.IsNil)
key := cResp.FilePermissionKey()
// Set the custom permissions
sResp, err := directory.SetProperties(ctx, sampleSDDL, "")
c.Assert(err, chk.IsNil)
c.Assert(sResp.FilePermissionKey(), chk.Not(chk.Equals), key)
key = sResp.FilePermissionKey()
gResp, err := directory.GetProperties(ctx)
c.Assert(err, chk.IsNil)
// Ensure the new key is present when we GetProperties
c.Assert(gResp.FilePermissionKey(), chk.Equals, key)
}
func (s *DirectoryURLSuite) TestDirCreateDeleteNonDefault(c *chk.C) {
directoryName := generateDirectoryName()
sa := getFSU()
@ -96,8 +121,10 @@ func (s *DirectoryURLSuite) TestDirCreateDeleteNonDefault(c *chk.C) {
"bar": "bArvaLue",
}
cResp, err := directory.Create(context.Background(), md)
cResp, err := directory.Create(context.Background(), md, sampleSDDL, "")
c.Assert(err, chk.IsNil)
// Ensure that the file key isn't empty, but don't worry about checking the permission. We just need to know it exists.
c.Assert(cResp.FilePermissionKey(), chk.Not(chk.Equals), "")
c.Assert(cResp.Response().StatusCode, chk.Equals, 201)
c.Assert(cResp.Date().IsZero(), chk.Equals, false)
c.Assert(cResp.ETag(), chk.Not(chk.Equals), azfile.ETagNone)
@ -110,7 +137,7 @@ func (s *DirectoryURLSuite) TestDirCreateDeleteNonDefault(c *chk.C) {
c.Assert(gResp.StatusCode(), chk.Equals, 200)
// Creating again will result in 409 and ResourceAlreadyExists.
cResp, err = directory.Create(context.Background(), md)
cResp, err = directory.Create(context.Background(), md, "", "")
c.Assert(err, chk.Not(chk.IsNil))
serr := err.(azfile.StorageError)
c.Assert(serr.Response().StatusCode, chk.Equals, 409)
@ -142,17 +169,17 @@ func (s *DirectoryURLSuite) TestDirCreateDeleteNegativeMultiLevelDir(c *chk.C) {
subDirURL := parentDirURL.NewDirectoryURL(subDirName)
// Directory create with subDirURL
cResp, err := subDirURL.Create(context.Background(), nil)
cResp, err := subDirURL.Create(context.Background(), nil, "", "")
c.Assert(err, chk.NotNil)
serr := err.(azfile.StorageError)
c.Assert(serr.Response().StatusCode, chk.Equals, 404)
c.Assert(serr.ServiceCode(), chk.Equals, azfile.ServiceCodeParentNotFound)
cResp, err = parentDirURL.Create(context.Background(), nil)
cResp, err = parentDirURL.Create(context.Background(), nil, "", "")
c.Assert(err, chk.IsNil)
c.Assert(cResp.Response().StatusCode, chk.Equals, 201)
cResp, err = subDirURL.Create(context.Background(), nil)
cResp, err = subDirURL.Create(context.Background(), nil, "", "")
c.Assert(err, chk.IsNil)
c.Assert(cResp.Response().StatusCode, chk.Equals, 201)
@ -187,7 +214,7 @@ func (s *DirectoryURLSuite) TestDirCreateEndWithSlash(c *chk.C) {
defer delDirectory(c, directory)
cResp, err := directory.Create(context.Background(), nil)
cResp, err := directory.Create(context.Background(), nil, "", "")
c.Assert(err, chk.IsNil)
c.Assert(cResp.Response().StatusCode, chk.Equals, 201)
c.Assert(cResp.Date().IsZero(), chk.Equals, false)

Просмотреть файл

@ -163,6 +163,7 @@ func (s *FileURLSuite) TestFileGetSetPropertiesNonDefault(c *chk.C) {
ContentMD5: testMd5,
CacheControl: "no-transform",
ContentDisposition: "attachment",
PermissionString: sampleSDDL, // Because our permission string is less than 9KB, it can be used here.
}
setResp, err := fileURL.SetHTTPHeaders(context.Background(), properties)
c.Assert(err, chk.IsNil)
@ -187,6 +188,8 @@ func (s *FileURLSuite) TestFileGetSetPropertiesNonDefault(c *chk.C) {
c.Assert(getResp.CacheControl(), chk.Equals, properties.CacheControl)
c.Assert(getResp.ContentDisposition(), chk.Equals, properties.ContentDisposition)
c.Assert(getResp.ContentLength(), chk.Equals, int64(0))
// We'll just ensure a permission exists, no need to test overlapping functionality.
c.Assert(getResp.FilePermissionKey(), chk.Not(chk.Equals), "")
c.Assert(getResp.ETag(), chk.Not(chk.Equals), azfile.ETagNone)
c.Assert(getResp.RequestID(), chk.Not(chk.Equals), "")
@ -739,7 +742,7 @@ func (f *FileURLSuite) TestServiceSASShareSAS(c *chk.C) {
_, err = fileURL.Delete(ctx)
c.Assert(err, chk.IsNil)
_, err = dirURL.Create(ctx, azfile.Metadata{})
_, err = dirURL.Create(ctx, azfile.Metadata{}, "", "")
c.Assert(err, chk.IsNil)
_, err = dirURL.ListFilesAndDirectoriesSegment(ctx, azfile.Marker{}, azfile.ListFilesAndDirectoriesOptions{})

Просмотреть файл

@ -350,7 +350,7 @@ func (s *StorageAccountSuite) TestAccountSAS(c *chk.C) {
testDirURL := dParts.URL()
dirURLWithSAS := azfile.NewDirectoryURL(testDirURL, azfile.NewPipeline(azfile.NewAnonymousCredential(), azfile.PipelineOptions{}))
// Create
_, err = dirURLWithSAS.Create(ctx, azfile.Metadata{})
_, err = dirURLWithSAS.Create(ctx, azfile.Metadata{}, "", "")
c.Assert(err, chk.IsNil)
// Write
_, err = dirURLWithSAS.SetMetadata(ctx, metadata)

Просмотреть файл

@ -17,12 +17,40 @@ type ShareURLSuite struct{}
var _ = chk.Suite(&ShareURLSuite{})
// a sample SDDL string at https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format
var sampleSDDL = `O:S-1-5-32-548G:S-1-5-21-397955417-626881126-188441444-512D:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)`
func delShare(c *chk.C, share azfile.ShareURL, option azfile.DeleteSnapshotsOptionType) {
resp, err := share.Delete(context.Background(), option)
c.Assert(err, chk.IsNil)
c.Assert(resp.Response().StatusCode, chk.Equals, 202)
}
func (s *ShareURLSuite) TestPutAndGetPermission(c *chk.C) {
fsu := getFSU()
shareURL, _ := getShareURL(c, fsu)
// Create the share.
_, err := shareURL.Create(ctx, azfile.Metadata{}, 0)
c.Assert(err, chk.IsNil)
// Create a permission and check that it's not empty.
createResp, err := shareURL.CreatePermission(ctx, sampleSDDL)
c.Assert(err, chk.IsNil)
c.Assert(createResp.FilePermissionKey(), chk.Not(chk.Equals), "")
getResp, err := shareURL.GetPermission(ctx, createResp.FilePermissionKey())
c.Assert(err, chk.IsNil)
// Why check for emptiness instead of against the original?
// Fun fact: Azure Files does some processing themselves, apparently!
// This is a mitigation for it.
/*
Expected :string = "O:S-1-5-32-548G:S-1-5-21-397955417-626881126-188441444-512D:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)"
Actual :string = "O:AOG:S-1-5-21-397955417-626881126-188441444-512D:(A;;CCDCLCSWRPWPRCWDWOGA;;;S-1-0-0)S:NO_ACCESS_CONTROL"
*/
c.Assert(getResp.Permission, chk.Not(chk.Equals), "")
}
func (s *ShareURLSuite) TestShareCreateRootDirectoryURL(c *chk.C) {
fsu := getFSU()
testURL := fsu.NewShareURL(sharePrefix).NewRootDirectoryURL()

Просмотреть файл

@ -177,6 +177,16 @@ const (
StorageErrorCodeAuthenticationFailed StorageErrorCodeType = "AuthenticationFailed"
// StorageErrorCodeAuthorizationFailure ...
StorageErrorCodeAuthorizationFailure StorageErrorCodeType = "AuthorizationFailure"
// StorageErrorCodeAuthorizationPermissionMismatch ...
StorageErrorCodeAuthorizationPermissionMismatch StorageErrorCodeType = "AuthorizationPermissionMismatch"
// StorageErrorCodeAuthorizationProtocolMismatch ...
StorageErrorCodeAuthorizationProtocolMismatch StorageErrorCodeType = "AuthorizationProtocolMismatch"
// StorageErrorCodeAuthorizationResourceTypeMismatch ...
StorageErrorCodeAuthorizationResourceTypeMismatch StorageErrorCodeType = "AuthorizationResourceTypeMismatch"
// StorageErrorCodeAuthorizationServiceMismatch ...
StorageErrorCodeAuthorizationServiceMismatch StorageErrorCodeType = "AuthorizationServiceMismatch"
// StorageErrorCodeAuthorizationSourceIPMismatch ...
StorageErrorCodeAuthorizationSourceIPMismatch StorageErrorCodeType = "AuthorizationSourceIPMismatch"
// StorageErrorCodeCannotDeleteFileOrDirectory ...
StorageErrorCodeCannotDeleteFileOrDirectory StorageErrorCodeType = "CannotDeleteFileOrDirectory"
// StorageErrorCodeClientCacheFlushDelay ...
@ -193,6 +203,8 @@ const (
StorageErrorCodeDirectoryNotEmpty StorageErrorCodeType = "DirectoryNotEmpty"
// StorageErrorCodeEmptyMetadataKey ...
StorageErrorCodeEmptyMetadataKey StorageErrorCodeType = "EmptyMetadataKey"
// StorageErrorCodeFeatureVersionMismatch ...
StorageErrorCodeFeatureVersionMismatch StorageErrorCodeType = "FeatureVersionMismatch"
// StorageErrorCodeFileLockConflict ...
StorageErrorCodeFileLockConflict StorageErrorCodeType = "FileLockConflict"
// StorageErrorCodeInsufficientAccountPermissions ...
@ -293,7 +305,7 @@ const (
// PossibleStorageErrorCodeTypeValues returns an array of possible values for the StorageErrorCodeType const type.
func PossibleStorageErrorCodeTypeValues() []StorageErrorCodeType {
return []StorageErrorCodeType{StorageErrorCodeAccountAlreadyExists, StorageErrorCodeAccountBeingCreated, StorageErrorCodeAccountIsDisabled, StorageErrorCodeAuthenticationFailed, StorageErrorCodeAuthorizationFailure, StorageErrorCodeCannotDeleteFileOrDirectory, StorageErrorCodeClientCacheFlushDelay, StorageErrorCodeConditionHeadersNotSupported, StorageErrorCodeConditionNotMet, StorageErrorCodeContainerQuotaDowngradeNotAllowed, StorageErrorCodeDeletePending, StorageErrorCodeDirectoryNotEmpty, StorageErrorCodeEmptyMetadataKey, StorageErrorCodeFileLockConflict, StorageErrorCodeInsufficientAccountPermissions, StorageErrorCodeInternalError, StorageErrorCodeInvalidAuthenticationInfo, StorageErrorCodeInvalidFileOrDirectoryPathName, StorageErrorCodeInvalidHeaderValue, StorageErrorCodeInvalidHTTPVerb, StorageErrorCodeInvalidInput, StorageErrorCodeInvalidMd5, StorageErrorCodeInvalidMetadata, StorageErrorCodeInvalidQueryParameterValue, StorageErrorCodeInvalidRange, StorageErrorCodeInvalidResourceName, StorageErrorCodeInvalidURI, StorageErrorCodeInvalidXMLDocument, StorageErrorCodeInvalidXMLNodeValue, StorageErrorCodeMd5Mismatch, StorageErrorCodeMetadataTooLarge, StorageErrorCodeMissingContentLengthHeader, StorageErrorCodeMissingRequiredHeader, StorageErrorCodeMissingRequiredQueryParameter, StorageErrorCodeMissingRequiredXMLNode, StorageErrorCodeMultipleConditionHeadersNotSupported, StorageErrorCodeNone, StorageErrorCodeOperationTimedOut, StorageErrorCodeOutOfRangeInput, StorageErrorCodeOutOfRangeQueryParameterValue, StorageErrorCodeParentNotFound, StorageErrorCodeReadOnlyAttribute, StorageErrorCodeRequestBodyTooLarge, StorageErrorCodeRequestURLFailedToParse, StorageErrorCodeResourceAlreadyExists, StorageErrorCodeResourceNotFound, StorageErrorCodeResourceTypeMismatch, StorageErrorCodeServerBusy, StorageErrorCodeShareAlreadyExists, StorageErrorCodeShareBeingDeleted, StorageErrorCodeShareDisabled, StorageErrorCodeShareHasSnapshots, StorageErrorCodeShareNotFound, StorageErrorCodeShareSnapshotCountExceeded, StorageErrorCodeShareSnapshotInProgress, StorageErrorCodeShareSnapshotOperationNotSupported, StorageErrorCodeSharingViolation, StorageErrorCodeUnsupportedHeader, StorageErrorCodeUnsupportedHTTPVerb, StorageErrorCodeUnsupportedQueryParameter, StorageErrorCodeUnsupportedXMLNode}
return []StorageErrorCodeType{StorageErrorCodeAccountAlreadyExists, StorageErrorCodeAccountBeingCreated, StorageErrorCodeAccountIsDisabled, StorageErrorCodeAuthenticationFailed, StorageErrorCodeAuthorizationFailure, StorageErrorCodeAuthorizationPermissionMismatch, StorageErrorCodeAuthorizationProtocolMismatch, StorageErrorCodeAuthorizationResourceTypeMismatch, StorageErrorCodeAuthorizationServiceMismatch, StorageErrorCodeAuthorizationSourceIPMismatch, StorageErrorCodeCannotDeleteFileOrDirectory, StorageErrorCodeClientCacheFlushDelay, StorageErrorCodeConditionHeadersNotSupported, StorageErrorCodeConditionNotMet, StorageErrorCodeContainerQuotaDowngradeNotAllowed, StorageErrorCodeDeletePending, StorageErrorCodeDirectoryNotEmpty, StorageErrorCodeEmptyMetadataKey, StorageErrorCodeFeatureVersionMismatch, StorageErrorCodeFileLockConflict, StorageErrorCodeInsufficientAccountPermissions, StorageErrorCodeInternalError, StorageErrorCodeInvalidAuthenticationInfo, StorageErrorCodeInvalidFileOrDirectoryPathName, StorageErrorCodeInvalidHeaderValue, StorageErrorCodeInvalidHTTPVerb, StorageErrorCodeInvalidInput, StorageErrorCodeInvalidMd5, StorageErrorCodeInvalidMetadata, StorageErrorCodeInvalidQueryParameterValue, StorageErrorCodeInvalidRange, StorageErrorCodeInvalidResourceName, StorageErrorCodeInvalidURI, StorageErrorCodeInvalidXMLDocument, StorageErrorCodeInvalidXMLNodeValue, StorageErrorCodeMd5Mismatch, StorageErrorCodeMetadataTooLarge, StorageErrorCodeMissingContentLengthHeader, StorageErrorCodeMissingRequiredHeader, StorageErrorCodeMissingRequiredQueryParameter, StorageErrorCodeMissingRequiredXMLNode, StorageErrorCodeMultipleConditionHeadersNotSupported, StorageErrorCodeNone, StorageErrorCodeOperationTimedOut, StorageErrorCodeOutOfRangeInput, StorageErrorCodeOutOfRangeQueryParameterValue, StorageErrorCodeParentNotFound, StorageErrorCodeReadOnlyAttribute, StorageErrorCodeRequestBodyTooLarge, StorageErrorCodeRequestURLFailedToParse, StorageErrorCodeResourceAlreadyExists, StorageErrorCodeResourceNotFound, StorageErrorCodeResourceTypeMismatch, StorageErrorCodeServerBusy, StorageErrorCodeShareAlreadyExists, StorageErrorCodeShareBeingDeleted, StorageErrorCodeShareDisabled, StorageErrorCodeShareHasSnapshots, StorageErrorCodeShareNotFound, StorageErrorCodeShareSnapshotCountExceeded, StorageErrorCodeShareSnapshotInProgress, StorageErrorCodeShareSnapshotOperationNotSupported, StorageErrorCodeSharingViolation, StorageErrorCodeUnsupportedHeader, StorageErrorCodeUnsupportedHTTPVerb, StorageErrorCodeUnsupportedQueryParameter, StorageErrorCodeUnsupportedXMLNode}
}
// AccessPolicy - An Access policy.
@ -2676,7 +2688,7 @@ type ShareItem struct {
type SharePermission struct {
rawResponse *http.Response
// Permission - The permission in the Security Descriptor Definition Language (SDDL).
Permission string `xml:"permission"`
Permission string
}
// Response returns the raw HTTP response object.

Просмотреть файл

@ -6,6 +6,7 @@ package azfile
import (
"bytes"
"context"
"encoding/json"
"encoding/xml"
"github.com/Azure/azure-pipeline-go/pipeline"
"io"
@ -126,7 +127,7 @@ func (client shareClient) createPermissionPreparer(sharePermission SharePermissi
params.Set("comp", "filepermission")
req.URL.RawQuery = params.Encode()
req.Header.Set("x-ms-version", ServiceVersion)
b, err := xml.Marshal(sharePermission)
b, err := json.Marshal(sharePermission)
if err != nil {
return req, pipeline.NewError(err, "failed to marshal request body")
}
@ -331,12 +332,11 @@ func (client shareClient) getAccessPolicyResponder(resp pipeline.Response) (pipe
// GetPermission returns the permission (security descriptor) for a given key
//
// filePermissionKey is key of the permission to be set for the directory/file. Note: Only one of the
// x-ms-file-permission or x-ms-file-permission-key should be specified. timeout is the timeout parameter is expressed
// in seconds. For more information, see <a
// filePermissionKey is key of the permission to be set for the directory/file. timeout is the timeout parameter is
// expressed in seconds. For more information, see <a
// href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting
// Timeouts for File Service Operations.</a>
func (client shareClient) GetPermission(ctx context.Context, filePermissionKey *string, timeout *int32) (*SharePermission, error) {
func (client shareClient) GetPermission(ctx context.Context, filePermissionKey string, timeout *int32) (*SharePermission, error) {
if err := validate([]validation{
{targetValue: timeout,
constraints: []constraint{{target: "timeout", name: null, rule: false,
@ -355,7 +355,7 @@ func (client shareClient) GetPermission(ctx context.Context, filePermissionKey *
}
// getPermissionPreparer prepares the GetPermission request.
func (client shareClient) getPermissionPreparer(filePermissionKey *string, timeout *int32) (pipeline.Request, error) {
func (client shareClient) getPermissionPreparer(filePermissionKey string, timeout *int32) (pipeline.Request, error) {
req, err := pipeline.NewRequest("GET", client.url, nil)
if err != nil {
return req, pipeline.NewError(err, "failed to create request")
@ -367,9 +367,7 @@ func (client shareClient) getPermissionPreparer(filePermissionKey *string, timeo
params.Set("restype", "share")
params.Set("comp", "filepermission")
req.URL.RawQuery = params.Encode()
if filePermissionKey != nil {
req.Header.Set("x-ms-file-permission-key", *filePermissionKey)
}
req.Header.Set("x-ms-file-permission-key", filePermissionKey)
req.Header.Set("x-ms-version", ServiceVersion)
return req, nil
}
@ -391,7 +389,7 @@ func (client shareClient) getPermissionResponder(resp pipeline.Response) (pipeli
}
if len(b) > 0 {
b = removeBOM(b)
err = xml.Unmarshal(b, result)
err = json.Unmarshal(b, result)
if err != nil {
return result, NewResponseError(err, resp.Response(), "failed to unmarshal response body")
}

Просмотреть файл

@ -15,6 +15,10 @@ type FileHTTPHeaders struct {
ContentLanguage string
ContentDisposition string
CacheControl string
// NOTE: Permission strings are required to be sub-9KB. Please upload the permission to the share, and submit a key instead if yours exceeds this limit.
PermissionString string
PermissionKey string
}
// NewHTTPHeaders returns the user-modifiable properties for this file.

1
go.mod
Просмотреть файл

@ -4,6 +4,7 @@ require (
github.com/Azure/azure-pipeline-go v0.2.1
github.com/kr/pretty v0.1.0 // indirect
github.com/kr/pty v1.1.5 // indirect
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
)

6
go.sum
Просмотреть файл

@ -9,7 +9,13 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

Просмотреть файл

@ -9,6 +9,10 @@ autorest README.md --use=@microsoft.azure/autorest.go@v3.0.63
gofmt -w Go_FileStorage/*
```
More modifications have to be made after generation in order to fix issues that the Go generator can't work around right now`. Namely:
- Under shareClient.getPermissionResponder and shareClient.createPermissionPreparer, change all xml.Marshal and xml.Unmarshal lines to json.Marshal and json.Unmarshal respectively
- (Issue opened: https://github.com/Azure/go-autorest/issues/495)
### Settings
``` yaml
input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/storage-dataplane-preview/specification/storage/data-plane/Microsoft.FileStorage/preview/2019-02-02/file.json