From 40355bf77fae4067e7c346a6825c21178b5567c5 Mon Sep 17 00:00:00 2001 From: Rong Zhou Date: Thu, 5 Sep 2024 06:46:32 +0000 Subject: [PATCH] add shares apis --- CHANGELOG.md | 1 + api-specs | 2 +- iam/apis/api_delete_group.go | 96 +++++++++++++ iam/apis/delete_group/api.go | 15 +++ internal/api-generator/client.go | 55 +++++--- internal/api-generator/form.go | 4 - internal/api-generator/query.go | 13 +- storagev2/apis/api_check_share.go | 161 ++++++++++++++++++++++ storagev2/apis/api_create_share.go | 143 ++++++++++++++++++++ storagev2/apis/api_post_object.go | 3 +- storagev2/apis/api_verify_share.go | 172 ++++++++++++++++++++++++ storagev2/apis/check_share/api.go | 16 +++ storagev2/apis/create_share/api.go | 111 +++++++++++++++ storagev2/apis/get_bucket_quota/api.go | 3 + storagev2/apis/set_bucket_remark/api.go | 3 + storagev2/apis/verify_share/api.go | 128 ++++++++++++++++++ 16 files changed, 897 insertions(+), 29 deletions(-) create mode 100644 iam/apis/api_delete_group.go create mode 100644 iam/apis/delete_group/api.go create mode 100644 storagev2/apis/api_check_share.go create mode 100644 storagev2/apis/api_create_share.go create mode 100644 storagev2/apis/api_verify_share.go create mode 100644 storagev2/apis/check_share/api.go create mode 100644 storagev2/apis/create_share/api.go create mode 100644 storagev2/apis/verify_share/api.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 3233013c..5d2e1301 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * 多媒体处理库 [media](github.com/qiniu/go-sdk/v7/media/apis) 包,提供多媒体处理接口 * IAM [iam](github.com/qiniu/go-sdk/v7/iam/apis) 包,提供权限管理系统接口 * 获取下载 URL 的实用方法 + * 提供文件夹分享接口 * 修复 * `downloader.DownloadDirectory` 下载根目录出错的 Bug diff --git a/api-specs b/api-specs index 5c453e9b..fdbd3ec7 160000 --- a/api-specs +++ b/api-specs @@ -1 +1 @@ -Subproject commit 5c453e9bdfcf1a88a42281dab2e22d79251edacc +Subproject commit fdbd3ec75dd2024454a3ad0fef0bdf1a8a032d85 diff --git a/iam/apis/api_delete_group.go b/iam/apis/api_delete_group.go new file mode 100644 index 00000000..3f4d1c91 --- /dev/null +++ b/iam/apis/api_delete_group.go @@ -0,0 +1,96 @@ +// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY! + +package apis + +import ( + "context" + auth "github.com/qiniu/go-sdk/v7/auth" + deletegroup "github.com/qiniu/go-sdk/v7/iam/apis/delete_group" + uplog "github.com/qiniu/go-sdk/v7/internal/uplog" + errors "github.com/qiniu/go-sdk/v7/storagev2/errors" + httpclient "github.com/qiniu/go-sdk/v7/storagev2/http_client" + region "github.com/qiniu/go-sdk/v7/storagev2/region" + uptoken "github.com/qiniu/go-sdk/v7/storagev2/uptoken" + "strings" + "time" +) + +type innerDeleteGroupRequest deletegroup.Request + +func (path *innerDeleteGroupRequest) buildPath() ([]string, error) { + allSegments := make([]string, 0, 1) + if path.Alias != "" { + allSegments = append(allSegments, path.Alias) + } else { + return nil, errors.MissingRequiredFieldError{Name: "Alias"} + } + return allSegments, nil +} + +type DeleteGroupRequest = deletegroup.Request +type DeleteGroupResponse = deletegroup.Response + +// 删除用户分组 +func (iam *Iam) DeleteGroup(ctx context.Context, request *DeleteGroupRequest, options *Options) (*DeleteGroupResponse, error) { + if options == nil { + options = &Options{} + } + innerRequest := (*innerDeleteGroupRequest)(request) + serviceNames := []region.ServiceName{region.ServiceApi} + if innerRequest.Credentials == nil && iam.client.GetCredentials() == nil { + return nil, errors.MissingRequiredFieldError{Name: "Credentials"} + } + pathSegments := make([]string, 0, 4) + pathSegments = append(pathSegments, "iam", "v1", "groups") + if segments, err := innerRequest.buildPath(); err != nil { + return nil, err + } else { + pathSegments = append(pathSegments, segments...) + } + path := "/" + strings.Join(pathSegments, "/") + var rawQuery string + uplogInterceptor, err := uplog.NewRequestUplog("deleteGroup", "", "", func() (string, error) { + credentials := innerRequest.Credentials + if credentials == nil { + credentials = iam.client.GetCredentials() + } + putPolicy, err := uptoken.NewPutPolicy("", time.Now().Add(time.Hour)) + if err != nil { + return "", err + } + return uptoken.NewSigner(putPolicy, credentials).GetUpToken(ctx) + }) + if err != nil { + return nil, err + } + req := httpclient.Request{Method: "DELETE", ServiceNames: serviceNames, Path: path, RawQuery: rawQuery, Endpoints: options.OverwrittenEndpoints, Region: options.OverwrittenRegion, Interceptors: []httpclient.Interceptor{uplogInterceptor}, AuthType: auth.TokenQiniu, Credentials: innerRequest.Credentials, OnRequestProgress: options.OnRequestProgress} + if options.OverwrittenEndpoints == nil && options.OverwrittenRegion == nil && iam.client.GetRegions() == nil { + bucketHosts := httpclient.DefaultBucketHosts() + + req.Region = iam.client.GetAllRegions() + if req.Region == nil { + if options.OverwrittenBucketHosts != nil { + if bucketHosts, err = options.OverwrittenBucketHosts.GetEndpoints(ctx); err != nil { + return nil, err + } + } + allRegionsOptions := region.AllRegionsProviderOptions{UseInsecureProtocol: iam.client.UseInsecureProtocol(), HostFreezeDuration: iam.client.GetHostFreezeDuration(), Resolver: iam.client.GetResolver(), Chooser: iam.client.GetChooser(), BeforeSign: iam.client.GetBeforeSignCallback(), AfterSign: iam.client.GetAfterSignCallback(), SignError: iam.client.GetSignErrorCallback(), BeforeResolve: iam.client.GetBeforeResolveCallback(), AfterResolve: iam.client.GetAfterResolveCallback(), ResolveError: iam.client.GetResolveErrorCallback(), BeforeBackoff: iam.client.GetBeforeBackoffCallback(), AfterBackoff: iam.client.GetAfterBackoffCallback(), BeforeRequest: iam.client.GetBeforeRequestCallback(), AfterResponse: iam.client.GetAfterResponseCallback()} + if hostRetryConfig := iam.client.GetHostRetryConfig(); hostRetryConfig != nil { + allRegionsOptions.RetryMax = hostRetryConfig.RetryMax + allRegionsOptions.Backoff = hostRetryConfig.Backoff + } + credentials := innerRequest.Credentials + if credentials == nil { + credentials = iam.client.GetCredentials() + } + if req.Region, err = region.NewAllRegionsProvider(credentials, bucketHosts, &allRegionsOptions); err != nil { + return nil, err + } + } + } + resp, err := iam.client.Do(ctx, &req) + if err != nil { + return nil, err + } + return &DeleteGroupResponse{}, resp.Body.Close() +} diff --git a/iam/apis/delete_group/api.go b/iam/apis/delete_group/api.go new file mode 100644 index 00000000..22e9764f --- /dev/null +++ b/iam/apis/delete_group/api.go @@ -0,0 +1,15 @@ +// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY! + +// 删除用户分组 +package delete_group + +import credentials "github.com/qiniu/go-sdk/v7/storagev2/credentials" + +// 调用 API 所用的请求 +type Request struct { + Alias string // 用户分组别名 + Credentials credentials.CredentialsProvider // 鉴权参数,用于生成鉴权凭证,如果为空,则使用 HTTPClientOptions 中的 CredentialsProvider +} + +// 获取 API 所用的响应 +type Response struct{} diff --git a/internal/api-generator/client.go b/internal/api-generator/client.go index 40cac1f3..0e6fcd2e 100644 --- a/internal/api-generator/client.go +++ b/internal/api-generator/client.go @@ -178,14 +178,20 @@ func (description *ApiDetailedDescription) generatePackage(group *jen.Group, opt } } } - group.Add(jen.Id("pathSegments").Op(":=").Make(jen.Index().String(), jen.Lit(0), jen.Lit(guessPathSegmentsCount))) + if guessPathSegmentsCount > 0 { + group.Add(jen.Id("pathSegments").Op(":=").Make(jen.Index().String(), jen.Lit(0), jen.Lit(guessPathSegmentsCount))) + } else { + group.Add(jen.Id("pathSegments").Op(":=").Make(jen.Index().String(), jen.Lit(0))) + } if description.BasePath != "" { - group.Add(jen.Id("pathSegments").Op("=").AppendFunc(func(group *jen.Group) { - group.Add(jen.Id("pathSegments")) - for _, pathSegment := range description.getBasePathSegments() { - group.Add(jen.Lit(pathSegment)) - } - })) + if basePathSegments := description.getBasePathSegments(); len(basePathSegments) > 0 { + group.Add(jen.Id("pathSegments").Op("=").AppendFunc(func(group *jen.Group) { + group.Add(jen.Id("pathSegments")) + for _, pathSegment := range basePathSegments { + group.Add(jen.Lit(pathSegment)) + } + })) + } } if description.Request.PathParams != nil { group.Add( @@ -207,14 +213,19 @@ func (description *ApiDetailedDescription) generatePackage(group *jen.Group, opt ) } if description.PathSuffix != "" { - group.Add(jen.Id("pathSegments").Op("=").AppendFunc(func(group *jen.Group) { - group.Add(jen.Id("pathSegments")) - for _, pathSegment := range description.getPathSuffixSegments() { - group.Add(jen.Lit(pathSegment)) - } - })) + if suffixSegments := description.getPathSuffixSegments(); len(suffixSegments) > 0 { + group.Add(jen.Id("pathSegments").Op("=").AppendFunc(func(group *jen.Group) { + group.Add(jen.Id("pathSegments")) + for _, pathSegment := range suffixSegments { + group.Add(jen.Lit(pathSegment)) + } + })) + } } group.Add(jen.Id("path").Op(":=").Lit("/").Op("+").Qual("strings", "Join").Call(jen.Id("pathSegments"), jen.Lit("/"))) + if description.PathSuffix == "/" { + group.Add(jen.Id("path").Op("+=").Lit("/")) + } if description.Command != "" { group.Add(jen.Id("rawQuery").Op(":=").Lit(description.Command + "&")) } else { @@ -867,13 +878,27 @@ func (description *ApiDetailedDescription) addJsonMarshalerUnmarshaler(group *je func (description *ApiDetailedDescription) getBasePathSegments() []string { basePath := strings.TrimPrefix(description.BasePath, "/") basePath = strings.TrimSuffix(basePath, "/") - return strings.Split(basePath, "/") + segments := strings.Split(basePath, "/") + newSegments := make([]string, 0, len(segments)) + for _, segment := range segments { + if segment != "" { + newSegments = append(newSegments, segment) + } + } + return newSegments } func (description *ApiDetailedDescription) getPathSuffixSegments() []string { pathSuffix := strings.TrimPrefix(description.PathSuffix, "/") pathSuffix = strings.TrimSuffix(pathSuffix, "/") - return strings.Split(pathSuffix, "/") + segments := strings.Split(pathSuffix, "/") + newSegments := make([]string, 0, len(segments)) + for _, segment := range segments { + if segment != "" { + newSegments = append(newSegments, segment) + } + } + return newSegments } func (description *ApiDetailedDescription) isBucketService() bool { diff --git a/internal/api-generator/form.go b/internal/api-generator/form.go index dc9f2f15..a35254af 100644 --- a/internal/api-generator/form.go +++ b/internal/api-generator/form.go @@ -1,7 +1,6 @@ package main import ( - "errors" "fmt" "github.com/dave/jennifer/jen" @@ -217,9 +216,6 @@ func (form *FormUrlencodedRequestStruct) addSetCall(group *jen.Group, field Form ) fieldName := field.camelCaseName() if field.Multiple { - if field.Optional.ToOptionalType() != OptionalTypeRequired { - return errors.New("multiple field must be required") - } valueConvertCode, err = field.Type.GenerateConvertCodeToString(jen.Id("value")) if err != nil { return err diff --git a/internal/api-generator/query.go b/internal/api-generator/query.go index 21a297b2..af2eb9bb 100644 --- a/internal/api-generator/query.go +++ b/internal/api-generator/query.go @@ -191,23 +191,22 @@ func (names QueryNames) generateSetCall(group *jen.Group, queryName QueryName, q fieldName := queryName.camelCaseName() field := jen.Id("query").Dot(fieldName) if queryName.Multiple { - if queryName.Optional.ToOptionalType() != OptionalTypeRequired { - return errors.New("multiple field must be required") - } valueConvertCode, err = queryName.QueryType.GenerateConvertCodeToString(jen.Id("value")) if err != nil { return err } - group.Add(jen.If(jen.Len(jen.Id("query").Dot(fieldName)).Op(">").Lit(0)). + code := jen.If(jen.Len(jen.Id("query").Dot(fieldName)).Op(">").Lit(0)). BlockFunc(func(group *jen.Group) { group.Add( jen.For(jen.List(jen.Id("_"), jen.Id("value")).Op(":=").Range().Add(jen.Id("query").Dot(fieldName))).BlockFunc(func(group *jen.Group) { group.Add(jen.Id(queryVarName).Dot("Add").Call(jen.Lit(queryName.QueryName), valueConvertCode)) }), ) - }). - Else(). - BlockFunc(appendMissingRequiredFieldErrorFunc(fieldName))) + }) + if queryName.Optional.ToOptionalType() == OptionalTypeRequired { + code = code.Else().BlockFunc(appendMissingRequiredFieldErrorFunc(fieldName)) + } + group.Add(code) } else { if queryName.Optional.ToOptionalType() == OptionalTypeNullable { valueConvertCode, err = queryName.QueryType.GenerateConvertCodeToString(jen.Op("*").Add(field)) diff --git a/storagev2/apis/api_check_share.go b/storagev2/apis/api_check_share.go new file mode 100644 index 00000000..615ea14d --- /dev/null +++ b/storagev2/apis/api_check_share.go @@ -0,0 +1,161 @@ +// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY! + +package apis + +import ( + "context" + auth "github.com/qiniu/go-sdk/v7/auth" + uplog "github.com/qiniu/go-sdk/v7/internal/uplog" + checkshare "github.com/qiniu/go-sdk/v7/storagev2/apis/check_share" + errors "github.com/qiniu/go-sdk/v7/storagev2/errors" + httpclient "github.com/qiniu/go-sdk/v7/storagev2/http_client" + region "github.com/qiniu/go-sdk/v7/storagev2/region" + uptoken "github.com/qiniu/go-sdk/v7/storagev2/uptoken" + "net/url" + "strings" + "time" +) + +type innerCheckShareRequest checkshare.Request + +func (path *innerCheckShareRequest) buildPath() ([]string, error) { + allSegments := make([]string, 0, 1) + if path.ShareId != "" { + allSegments = append(allSegments, path.ShareId) + } else { + return nil, errors.MissingRequiredFieldError{Name: "ShareId"} + } + return allSegments, nil +} +func (query *innerCheckShareRequest) buildQuery() (url.Values, error) { + allQuery := make(url.Values) + if query.Token != "" { + allQuery.Set("token", query.Token) + } else { + return nil, errors.MissingRequiredFieldError{Name: "Token"} + } + return allQuery, nil +} +func (request *innerCheckShareRequest) getAccessKey(ctx context.Context) (string, error) { + if request.Credentials != nil { + if credentials, err := request.Credentials.Get(ctx); err != nil { + return "", err + } else { + return credentials.AccessKey, nil + } + } + return "", nil +} + +type CheckShareRequest = checkshare.Request +type CheckShareResponse = checkshare.Response + +// 检查目录分享 +func (storage *Storage) CheckShare(ctx context.Context, request *CheckShareRequest, options *Options) (*CheckShareResponse, error) { + if options == nil { + options = &Options{} + } + innerRequest := (*innerCheckShareRequest)(request) + serviceNames := []region.ServiceName{region.ServiceApi} + if innerRequest.Credentials == nil && storage.client.GetCredentials() == nil { + return nil, errors.MissingRequiredFieldError{Name: "Credentials"} + } + pathSegments := make([]string, 0, 3) + pathSegments = append(pathSegments, "shares") + if segments, err := innerRequest.buildPath(); err != nil { + return nil, err + } else { + pathSegments = append(pathSegments, segments...) + } + pathSegments = append(pathSegments, "check") + path := "/" + strings.Join(pathSegments, "/") + var rawQuery string + if query, err := innerRequest.buildQuery(); err != nil { + return nil, err + } else { + rawQuery += query.Encode() + } + bucketName := options.OverwrittenBucketName + uplogInterceptor, err := uplog.NewRequestUplog("checkShare", bucketName, "", func() (string, error) { + credentials := innerRequest.Credentials + if credentials == nil { + credentials = storage.client.GetCredentials() + } + putPolicy, err := uptoken.NewPutPolicy(bucketName, time.Now().Add(time.Hour)) + if err != nil { + return "", err + } + return uptoken.NewSigner(putPolicy, credentials).GetUpToken(ctx) + }) + if err != nil { + return nil, err + } + req := httpclient.Request{Method: "POST", ServiceNames: serviceNames, Path: path, RawQuery: rawQuery, Endpoints: options.OverwrittenEndpoints, Region: options.OverwrittenRegion, Interceptors: []httpclient.Interceptor{uplogInterceptor}, AuthType: auth.TokenQiniu, Credentials: innerRequest.Credentials, OnRequestProgress: options.OnRequestProgress} + if options.OverwrittenEndpoints == nil && options.OverwrittenRegion == nil && storage.client.GetRegions() == nil { + bucketHosts := httpclient.DefaultBucketHosts() + if bucketName != "" { + query := storage.client.GetBucketQuery() + if query == nil { + if options.OverwrittenBucketHosts != nil { + if bucketHosts, err = options.OverwrittenBucketHosts.GetEndpoints(ctx); err != nil { + return nil, err + } + } + queryOptions := region.BucketRegionsQueryOptions{UseInsecureProtocol: storage.client.UseInsecureProtocol(), AccelerateUploading: storage.client.AccelerateUploadingEnabled(), HostFreezeDuration: storage.client.GetHostFreezeDuration(), Resolver: storage.client.GetResolver(), Chooser: storage.client.GetChooser(), BeforeResolve: storage.client.GetBeforeResolveCallback(), AfterResolve: storage.client.GetAfterResolveCallback(), ResolveError: storage.client.GetResolveErrorCallback(), BeforeBackoff: storage.client.GetBeforeBackoffCallback(), AfterBackoff: storage.client.GetAfterBackoffCallback(), BeforeRequest: storage.client.GetBeforeRequestCallback(), AfterResponse: storage.client.GetAfterResponseCallback()} + if hostRetryConfig := storage.client.GetHostRetryConfig(); hostRetryConfig != nil { + queryOptions.RetryMax = hostRetryConfig.RetryMax + queryOptions.Backoff = hostRetryConfig.Backoff + } + if query, err = region.NewBucketRegionsQuery(bucketHosts, &queryOptions); err != nil { + return nil, err + } + } + if query != nil { + var accessKey string + var err error + if accessKey, err = innerRequest.getAccessKey(ctx); err != nil { + return nil, err + } + if accessKey == "" { + if credentialsProvider := storage.client.GetCredentials(); credentialsProvider != nil { + if creds, err := credentialsProvider.Get(ctx); err != nil { + return nil, err + } else if creds != nil { + accessKey = creds.AccessKey + } + } + } + if accessKey != "" { + req.Region = query.Query(accessKey, bucketName) + } + } + } else { + + req.Region = storage.client.GetAllRegions() + if req.Region == nil { + if options.OverwrittenBucketHosts != nil { + if bucketHosts, err = options.OverwrittenBucketHosts.GetEndpoints(ctx); err != nil { + return nil, err + } + } + allRegionsOptions := region.AllRegionsProviderOptions{UseInsecureProtocol: storage.client.UseInsecureProtocol(), HostFreezeDuration: storage.client.GetHostFreezeDuration(), Resolver: storage.client.GetResolver(), Chooser: storage.client.GetChooser(), BeforeSign: storage.client.GetBeforeSignCallback(), AfterSign: storage.client.GetAfterSignCallback(), SignError: storage.client.GetSignErrorCallback(), BeforeResolve: storage.client.GetBeforeResolveCallback(), AfterResolve: storage.client.GetAfterResolveCallback(), ResolveError: storage.client.GetResolveErrorCallback(), BeforeBackoff: storage.client.GetBeforeBackoffCallback(), AfterBackoff: storage.client.GetAfterBackoffCallback(), BeforeRequest: storage.client.GetBeforeRequestCallback(), AfterResponse: storage.client.GetAfterResponseCallback()} + if hostRetryConfig := storage.client.GetHostRetryConfig(); hostRetryConfig != nil { + allRegionsOptions.RetryMax = hostRetryConfig.RetryMax + allRegionsOptions.Backoff = hostRetryConfig.Backoff + } + credentials := innerRequest.Credentials + if credentials == nil { + credentials = storage.client.GetCredentials() + } + if req.Region, err = region.NewAllRegionsProvider(credentials, bucketHosts, &allRegionsOptions); err != nil { + return nil, err + } + } + } + } + resp, err := storage.client.Do(ctx, &req) + if err != nil { + return nil, err + } + return &CheckShareResponse{}, resp.Body.Close() +} diff --git a/storagev2/apis/api_create_share.go b/storagev2/apis/api_create_share.go new file mode 100644 index 00000000..b9bb1a81 --- /dev/null +++ b/storagev2/apis/api_create_share.go @@ -0,0 +1,143 @@ +// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY! + +package apis + +import ( + "context" + "encoding/json" + auth "github.com/qiniu/go-sdk/v7/auth" + uplog "github.com/qiniu/go-sdk/v7/internal/uplog" + createshare "github.com/qiniu/go-sdk/v7/storagev2/apis/create_share" + errors "github.com/qiniu/go-sdk/v7/storagev2/errors" + httpclient "github.com/qiniu/go-sdk/v7/storagev2/http_client" + region "github.com/qiniu/go-sdk/v7/storagev2/region" + uptoken "github.com/qiniu/go-sdk/v7/storagev2/uptoken" + "strings" + "time" +) + +type innerCreateShareRequest createshare.Request + +func (j *innerCreateShareRequest) MarshalJSON() ([]byte, error) { + return json.Marshal((*createshare.Request)(j)) +} +func (j *innerCreateShareRequest) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, (*createshare.Request)(j)) +} +func (request *innerCreateShareRequest) getAccessKey(ctx context.Context) (string, error) { + if request.Credentials != nil { + if credentials, err := request.Credentials.Get(ctx); err != nil { + return "", err + } else { + return credentials.AccessKey, nil + } + } + return "", nil +} + +type CreateShareRequest = createshare.Request +type CreateShareResponse = createshare.Response + +// 创建目录分享 +func (storage *Storage) CreateShare(ctx context.Context, request *CreateShareRequest, options *Options) (*CreateShareResponse, error) { + if options == nil { + options = &Options{} + } + innerRequest := (*innerCreateShareRequest)(request) + serviceNames := []region.ServiceName{region.ServiceApi} + if innerRequest.Credentials == nil && storage.client.GetCredentials() == nil { + return nil, errors.MissingRequiredFieldError{Name: "Credentials"} + } + pathSegments := make([]string, 0, 1) + pathSegments = append(pathSegments, "shares") + path := "/" + strings.Join(pathSegments, "/") + path += "/" + var rawQuery string + body, err := httpclient.GetJsonRequestBody(&innerRequest) + if err != nil { + return nil, err + } + bucketName := options.OverwrittenBucketName + uplogInterceptor, err := uplog.NewRequestUplog("createShare", bucketName, "", func() (string, error) { + credentials := innerRequest.Credentials + if credentials == nil { + credentials = storage.client.GetCredentials() + } + putPolicy, err := uptoken.NewPutPolicy(bucketName, time.Now().Add(time.Hour)) + if err != nil { + return "", err + } + return uptoken.NewSigner(putPolicy, credentials).GetUpToken(ctx) + }) + if err != nil { + return nil, err + } + req := httpclient.Request{Method: "POST", ServiceNames: serviceNames, Path: path, RawQuery: rawQuery, Endpoints: options.OverwrittenEndpoints, Region: options.OverwrittenRegion, Interceptors: []httpclient.Interceptor{uplogInterceptor}, AuthType: auth.TokenQiniu, Credentials: innerRequest.Credentials, BufferResponse: true, RequestBody: body, OnRequestProgress: options.OnRequestProgress} + if options.OverwrittenEndpoints == nil && options.OverwrittenRegion == nil && storage.client.GetRegions() == nil { + bucketHosts := httpclient.DefaultBucketHosts() + if bucketName != "" { + query := storage.client.GetBucketQuery() + if query == nil { + if options.OverwrittenBucketHosts != nil { + if bucketHosts, err = options.OverwrittenBucketHosts.GetEndpoints(ctx); err != nil { + return nil, err + } + } + queryOptions := region.BucketRegionsQueryOptions{UseInsecureProtocol: storage.client.UseInsecureProtocol(), AccelerateUploading: storage.client.AccelerateUploadingEnabled(), HostFreezeDuration: storage.client.GetHostFreezeDuration(), Resolver: storage.client.GetResolver(), Chooser: storage.client.GetChooser(), BeforeResolve: storage.client.GetBeforeResolveCallback(), AfterResolve: storage.client.GetAfterResolveCallback(), ResolveError: storage.client.GetResolveErrorCallback(), BeforeBackoff: storage.client.GetBeforeBackoffCallback(), AfterBackoff: storage.client.GetAfterBackoffCallback(), BeforeRequest: storage.client.GetBeforeRequestCallback(), AfterResponse: storage.client.GetAfterResponseCallback()} + if hostRetryConfig := storage.client.GetHostRetryConfig(); hostRetryConfig != nil { + queryOptions.RetryMax = hostRetryConfig.RetryMax + queryOptions.Backoff = hostRetryConfig.Backoff + } + if query, err = region.NewBucketRegionsQuery(bucketHosts, &queryOptions); err != nil { + return nil, err + } + } + if query != nil { + var accessKey string + var err error + if accessKey, err = innerRequest.getAccessKey(ctx); err != nil { + return nil, err + } + if accessKey == "" { + if credentialsProvider := storage.client.GetCredentials(); credentialsProvider != nil { + if creds, err := credentialsProvider.Get(ctx); err != nil { + return nil, err + } else if creds != nil { + accessKey = creds.AccessKey + } + } + } + if accessKey != "" { + req.Region = query.Query(accessKey, bucketName) + } + } + } else { + + req.Region = storage.client.GetAllRegions() + if req.Region == nil { + if options.OverwrittenBucketHosts != nil { + if bucketHosts, err = options.OverwrittenBucketHosts.GetEndpoints(ctx); err != nil { + return nil, err + } + } + allRegionsOptions := region.AllRegionsProviderOptions{UseInsecureProtocol: storage.client.UseInsecureProtocol(), HostFreezeDuration: storage.client.GetHostFreezeDuration(), Resolver: storage.client.GetResolver(), Chooser: storage.client.GetChooser(), BeforeSign: storage.client.GetBeforeSignCallback(), AfterSign: storage.client.GetAfterSignCallback(), SignError: storage.client.GetSignErrorCallback(), BeforeResolve: storage.client.GetBeforeResolveCallback(), AfterResolve: storage.client.GetAfterResolveCallback(), ResolveError: storage.client.GetResolveErrorCallback(), BeforeBackoff: storage.client.GetBeforeBackoffCallback(), AfterBackoff: storage.client.GetAfterBackoffCallback(), BeforeRequest: storage.client.GetBeforeRequestCallback(), AfterResponse: storage.client.GetAfterResponseCallback()} + if hostRetryConfig := storage.client.GetHostRetryConfig(); hostRetryConfig != nil { + allRegionsOptions.RetryMax = hostRetryConfig.RetryMax + allRegionsOptions.Backoff = hostRetryConfig.Backoff + } + credentials := innerRequest.Credentials + if credentials == nil { + credentials = storage.client.GetCredentials() + } + if req.Region, err = region.NewAllRegionsProvider(credentials, bucketHosts, &allRegionsOptions); err != nil { + return nil, err + } + } + } + } + var respBody CreateShareResponse + if err := storage.client.DoAndAcceptJSON(ctx, &req, &respBody); err != nil { + return nil, err + } + return &respBody, nil +} diff --git a/storagev2/apis/api_post_object.go b/storagev2/apis/api_post_object.go index 4bc556d2..8a45403d 100644 --- a/storagev2/apis/api_post_object.go +++ b/storagev2/apis/api_post_object.go @@ -81,8 +81,7 @@ func (storage *Storage) PostObject(ctx context.Context, request *PostObjectReque } innerRequest := (*innerPostObjectRequest)(request) serviceNames := []region.ServiceName{region.ServiceUp} - pathSegments := make([]string, 0, 1) - pathSegments = append(pathSegments, "") + pathSegments := make([]string, 0) path := "/" + strings.Join(pathSegments, "/") var rawQuery string body, err := innerRequest.build(ctx) diff --git a/storagev2/apis/api_verify_share.go b/storagev2/apis/api_verify_share.go new file mode 100644 index 00000000..c9de293b --- /dev/null +++ b/storagev2/apis/api_verify_share.go @@ -0,0 +1,172 @@ +// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY! + +package apis + +import ( + "context" + "encoding/json" + auth "github.com/qiniu/go-sdk/v7/auth" + uplog "github.com/qiniu/go-sdk/v7/internal/uplog" + verifyshare "github.com/qiniu/go-sdk/v7/storagev2/apis/verify_share" + errors "github.com/qiniu/go-sdk/v7/storagev2/errors" + httpclient "github.com/qiniu/go-sdk/v7/storagev2/http_client" + region "github.com/qiniu/go-sdk/v7/storagev2/region" + uptoken "github.com/qiniu/go-sdk/v7/storagev2/uptoken" + "net/url" + "strings" + "time" +) + +type innerVerifyShareRequest verifyshare.Request + +func (path *innerVerifyShareRequest) buildPath() ([]string, error) { + allSegments := make([]string, 0, 1) + if path.ShareId != "" { + allSegments = append(allSegments, path.ShareId) + } else { + return nil, errors.MissingRequiredFieldError{Name: "ShareId"} + } + return allSegments, nil +} +func (query *innerVerifyShareRequest) buildQuery() (url.Values, error) { + allQuery := make(url.Values) + if query.Token != "" { + allQuery.Set("token", query.Token) + } else { + return nil, errors.MissingRequiredFieldError{Name: "Token"} + } + return allQuery, nil +} +func (j *innerVerifyShareRequest) MarshalJSON() ([]byte, error) { + return json.Marshal((*verifyshare.Request)(j)) +} +func (j *innerVerifyShareRequest) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, (*verifyshare.Request)(j)) +} +func (request *innerVerifyShareRequest) getAccessKey(ctx context.Context) (string, error) { + if request.Credentials != nil { + if credentials, err := request.Credentials.Get(ctx); err != nil { + return "", err + } else { + return credentials.AccessKey, nil + } + } + return "", nil +} + +type VerifyShareRequest = verifyshare.Request +type VerifyShareResponse = verifyshare.Response + +// 校验目录分享并提取分享信息 +func (storage *Storage) VerifyShare(ctx context.Context, request *VerifyShareRequest, options *Options) (*VerifyShareResponse, error) { + if options == nil { + options = &Options{} + } + innerRequest := (*innerVerifyShareRequest)(request) + serviceNames := []region.ServiceName{region.ServiceApi} + if innerRequest.Credentials == nil && storage.client.GetCredentials() == nil { + return nil, errors.MissingRequiredFieldError{Name: "Credentials"} + } + pathSegments := make([]string, 0, 3) + pathSegments = append(pathSegments, "shares") + if segments, err := innerRequest.buildPath(); err != nil { + return nil, err + } else { + pathSegments = append(pathSegments, segments...) + } + pathSegments = append(pathSegments, "verify") + path := "/" + strings.Join(pathSegments, "/") + var rawQuery string + if query, err := innerRequest.buildQuery(); err != nil { + return nil, err + } else { + rawQuery += query.Encode() + } + body, err := httpclient.GetJsonRequestBody(&innerRequest) + if err != nil { + return nil, err + } + bucketName := options.OverwrittenBucketName + uplogInterceptor, err := uplog.NewRequestUplog("verifyShare", bucketName, "", func() (string, error) { + credentials := innerRequest.Credentials + if credentials == nil { + credentials = storage.client.GetCredentials() + } + putPolicy, err := uptoken.NewPutPolicy(bucketName, time.Now().Add(time.Hour)) + if err != nil { + return "", err + } + return uptoken.NewSigner(putPolicy, credentials).GetUpToken(ctx) + }) + if err != nil { + return nil, err + } + req := httpclient.Request{Method: "POST", ServiceNames: serviceNames, Path: path, RawQuery: rawQuery, Endpoints: options.OverwrittenEndpoints, Region: options.OverwrittenRegion, Interceptors: []httpclient.Interceptor{uplogInterceptor}, AuthType: auth.TokenQiniu, Credentials: innerRequest.Credentials, BufferResponse: true, RequestBody: body, OnRequestProgress: options.OnRequestProgress} + if options.OverwrittenEndpoints == nil && options.OverwrittenRegion == nil && storage.client.GetRegions() == nil { + bucketHosts := httpclient.DefaultBucketHosts() + if bucketName != "" { + query := storage.client.GetBucketQuery() + if query == nil { + if options.OverwrittenBucketHosts != nil { + if bucketHosts, err = options.OverwrittenBucketHosts.GetEndpoints(ctx); err != nil { + return nil, err + } + } + queryOptions := region.BucketRegionsQueryOptions{UseInsecureProtocol: storage.client.UseInsecureProtocol(), AccelerateUploading: storage.client.AccelerateUploadingEnabled(), HostFreezeDuration: storage.client.GetHostFreezeDuration(), Resolver: storage.client.GetResolver(), Chooser: storage.client.GetChooser(), BeforeResolve: storage.client.GetBeforeResolveCallback(), AfterResolve: storage.client.GetAfterResolveCallback(), ResolveError: storage.client.GetResolveErrorCallback(), BeforeBackoff: storage.client.GetBeforeBackoffCallback(), AfterBackoff: storage.client.GetAfterBackoffCallback(), BeforeRequest: storage.client.GetBeforeRequestCallback(), AfterResponse: storage.client.GetAfterResponseCallback()} + if hostRetryConfig := storage.client.GetHostRetryConfig(); hostRetryConfig != nil { + queryOptions.RetryMax = hostRetryConfig.RetryMax + queryOptions.Backoff = hostRetryConfig.Backoff + } + if query, err = region.NewBucketRegionsQuery(bucketHosts, &queryOptions); err != nil { + return nil, err + } + } + if query != nil { + var accessKey string + var err error + if accessKey, err = innerRequest.getAccessKey(ctx); err != nil { + return nil, err + } + if accessKey == "" { + if credentialsProvider := storage.client.GetCredentials(); credentialsProvider != nil { + if creds, err := credentialsProvider.Get(ctx); err != nil { + return nil, err + } else if creds != nil { + accessKey = creds.AccessKey + } + } + } + if accessKey != "" { + req.Region = query.Query(accessKey, bucketName) + } + } + } else { + + req.Region = storage.client.GetAllRegions() + if req.Region == nil { + if options.OverwrittenBucketHosts != nil { + if bucketHosts, err = options.OverwrittenBucketHosts.GetEndpoints(ctx); err != nil { + return nil, err + } + } + allRegionsOptions := region.AllRegionsProviderOptions{UseInsecureProtocol: storage.client.UseInsecureProtocol(), HostFreezeDuration: storage.client.GetHostFreezeDuration(), Resolver: storage.client.GetResolver(), Chooser: storage.client.GetChooser(), BeforeSign: storage.client.GetBeforeSignCallback(), AfterSign: storage.client.GetAfterSignCallback(), SignError: storage.client.GetSignErrorCallback(), BeforeResolve: storage.client.GetBeforeResolveCallback(), AfterResolve: storage.client.GetAfterResolveCallback(), ResolveError: storage.client.GetResolveErrorCallback(), BeforeBackoff: storage.client.GetBeforeBackoffCallback(), AfterBackoff: storage.client.GetAfterBackoffCallback(), BeforeRequest: storage.client.GetBeforeRequestCallback(), AfterResponse: storage.client.GetAfterResponseCallback()} + if hostRetryConfig := storage.client.GetHostRetryConfig(); hostRetryConfig != nil { + allRegionsOptions.RetryMax = hostRetryConfig.RetryMax + allRegionsOptions.Backoff = hostRetryConfig.Backoff + } + credentials := innerRequest.Credentials + if credentials == nil { + credentials = storage.client.GetCredentials() + } + if req.Region, err = region.NewAllRegionsProvider(credentials, bucketHosts, &allRegionsOptions); err != nil { + return nil, err + } + } + } + } + var respBody VerifyShareResponse + if err := storage.client.DoAndAcceptJSON(ctx, &req, &respBody); err != nil { + return nil, err + } + return &respBody, nil +} diff --git a/storagev2/apis/check_share/api.go b/storagev2/apis/check_share/api.go new file mode 100644 index 00000000..ea28dba1 --- /dev/null +++ b/storagev2/apis/check_share/api.go @@ -0,0 +1,16 @@ +// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY! + +// 检查目录分享 +package check_share + +import credentials "github.com/qiniu/go-sdk/v7/storagev2/credentials" + +// 调用 API 所用的请求 +type Request struct { + ShareId string // 分享 ID + Token string // 分享 Token + Credentials credentials.CredentialsProvider // 鉴权参数,用于生成鉴权凭证,如果为空,则使用 HTTPClientOptions 中的 CredentialsProvider +} + +// 获取 API 所用的响应 +type Response struct{} diff --git a/storagev2/apis/create_share/api.go b/storagev2/apis/create_share/api.go new file mode 100644 index 00000000..f4c466f1 --- /dev/null +++ b/storagev2/apis/create_share/api.go @@ -0,0 +1,111 @@ +// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY! + +// 创建目录分享 +package create_share + +import ( + "encoding/json" + credentials "github.com/qiniu/go-sdk/v7/storagev2/credentials" + errors "github.com/qiniu/go-sdk/v7/storagev2/errors" +) + +// 调用 API 所用的请求 +type Request struct { + Credentials credentials.CredentialsProvider // 鉴权参数,用于生成鉴权凭证,如果为空,则使用 HTTPClientOptions 中的 CredentialsProvider + Bucket string // 分享的空间名称 + Prefix string // 分享的对象名称前缀 + DurationSeconds int64 // 分享过期时间,单位为秒,最小 900 秒,最长 7200 秒 + ExtractCode string // 提取码,必须给出 6 个字符,仅大小写字母和数字 + Permission string // 权限,目前仅支持 READONLY,未来会支持 READWRITE +} + +// 新创建的分享参数 +type NewShareParams = Request +type jsonRequest struct { + Bucket string `json:"bucket"` // 分享的空间名称 + Prefix string `json:"prefix"` // 分享的对象名称前缀 + DurationSeconds int64 `json:"duration_seconds"` // 分享过期时间,单位为秒,最小 900 秒,最长 7200 秒 + ExtractCode string `json:"extract_code"` // 提取码,必须给出 6 个字符,仅大小写字母和数字 + Permission string `json:"permission"` // 权限,目前仅支持 READONLY,未来会支持 READWRITE +} + +func (j *Request) MarshalJSON() ([]byte, error) { + if err := j.validate(); err != nil { + return nil, err + } + return json.Marshal(&jsonRequest{Bucket: j.Bucket, Prefix: j.Prefix, DurationSeconds: j.DurationSeconds, ExtractCode: j.ExtractCode, Permission: j.Permission}) +} +func (j *Request) UnmarshalJSON(data []byte) error { + var nj jsonRequest + if err := json.Unmarshal(data, &nj); err != nil { + return err + } + j.Bucket = nj.Bucket + j.Prefix = nj.Prefix + j.DurationSeconds = nj.DurationSeconds + j.ExtractCode = nj.ExtractCode + j.Permission = nj.Permission + return nil +} +func (j *Request) validate() error { + if j.Bucket == "" { + return errors.MissingRequiredFieldError{Name: "Bucket"} + } + if j.Prefix == "" { + return errors.MissingRequiredFieldError{Name: "Prefix"} + } + if j.DurationSeconds == 0 { + return errors.MissingRequiredFieldError{Name: "DurationSeconds"} + } + if j.ExtractCode == "" { + return errors.MissingRequiredFieldError{Name: "ExtractCode"} + } + if j.Permission == "" { + return errors.MissingRequiredFieldError{Name: "Permission"} + } + return nil +} + +// 获取 API 所用的响应 +type Response struct { + Id string // 分享 ID + Token string // 分享 Token + Expires string // 分享过期时间,遵循 ISO8601 风格,使用 UTC 0 时区时间 +} + +// 返回的分享信息 +type NewShareInfo = Response +type jsonResponse struct { + Id string `json:"id"` // 分享 ID + Token string `json:"token"` // 分享 Token + Expires string `json:"expires"` // 分享过期时间,遵循 ISO8601 风格,使用 UTC 0 时区时间 +} + +func (j *Response) MarshalJSON() ([]byte, error) { + if err := j.validate(); err != nil { + return nil, err + } + return json.Marshal(&jsonResponse{Id: j.Id, Token: j.Token, Expires: j.Expires}) +} +func (j *Response) UnmarshalJSON(data []byte) error { + var nj jsonResponse + if err := json.Unmarshal(data, &nj); err != nil { + return err + } + j.Id = nj.Id + j.Token = nj.Token + j.Expires = nj.Expires + return nil +} +func (j *Response) validate() error { + if j.Id == "" { + return errors.MissingRequiredFieldError{Name: "Id"} + } + if j.Token == "" { + return errors.MissingRequiredFieldError{Name: "Token"} + } + if j.Expires == "" { + return errors.MissingRequiredFieldError{Name: "Expires"} + } + return nil +} diff --git a/storagev2/apis/get_bucket_quota/api.go b/storagev2/apis/get_bucket_quota/api.go index 3964cb5c..45af282f 100644 --- a/storagev2/apis/get_bucket_quota/api.go +++ b/storagev2/apis/get_bucket_quota/api.go @@ -19,6 +19,9 @@ type Response struct { Size int64 // 空间存储量配额 Count int64 // 空间文件数配额 } + +// Bucket 配额信息 +type BucketQuota = Response type jsonResponse struct { Size int64 `json:"size,omitempty"` // 空间存储量配额 Count int64 `json:"count,omitempty"` // 空间文件数配额 diff --git a/storagev2/apis/set_bucket_remark/api.go b/storagev2/apis/set_bucket_remark/api.go index a4b5c826..d57b4bd4 100644 --- a/storagev2/apis/set_bucket_remark/api.go +++ b/storagev2/apis/set_bucket_remark/api.go @@ -15,6 +15,9 @@ type Request struct { Credentials credentials.CredentialsProvider // 鉴权参数,用于生成鉴权凭证,如果为空,则使用 HTTPClientOptions 中的 CredentialsProvider Remark string // 空间备注信息, 字符长度不能超过 100, 允许为空 } + +// 空间备注信息 +type BucketRemark = Request type jsonRequest struct { Remark string `json:"remark"` // 空间备注信息, 字符长度不能超过 100, 允许为空 } diff --git a/storagev2/apis/verify_share/api.go b/storagev2/apis/verify_share/api.go new file mode 100644 index 00000000..966430b8 --- /dev/null +++ b/storagev2/apis/verify_share/api.go @@ -0,0 +1,128 @@ +// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY! + +// 校验目录分享并提取分享信息 +package verify_share + +import ( + "encoding/json" + credentials "github.com/qiniu/go-sdk/v7/storagev2/credentials" + errors "github.com/qiniu/go-sdk/v7/storagev2/errors" +) + +// 调用 API 所用的请求 +type Request struct { + ShareId string // 分享 ID + Token string // 分享 Token + Credentials credentials.CredentialsProvider // 鉴权参数,用于生成鉴权凭证,如果为空,则使用 HTTPClientOptions 中的 CredentialsProvider + ExtractCode string // 提取码 +} +type jsonRequest struct { + ExtractCode string `json:"extract_code"` // 提取码 +} + +func (j *Request) MarshalJSON() ([]byte, error) { + if err := j.validate(); err != nil { + return nil, err + } + return json.Marshal(&jsonRequest{ExtractCode: j.ExtractCode}) +} +func (j *Request) UnmarshalJSON(data []byte) error { + var nj jsonRequest + if err := json.Unmarshal(data, &nj); err != nil { + return err + } + j.ExtractCode = nj.ExtractCode + return nil +} +func (j *Request) validate() error { + if j.ExtractCode == "" { + return errors.MissingRequiredFieldError{Name: "ExtractCode"} + } + return nil +} + +// 获取 API 所用的响应 +type Response struct { + Endpoint string // 空间所用的 S3 域名 + Region string // 空间所在的 S3 区域 ID + BucketName string // 空间名称 + BucketId string // 空间 ID + Prefix string // 被分享的目录路径 + Permission string // 权限,目前仅支持 READONLY,未来会支持 READWRITE + Expires string // 分享过期时间,遵循 ISO8601 风格,使用 UTC 0 时区时间 + FederatedAk string // S3 STS Access Key + FederatedSk string // S3 STS Secret Key + SessionToken string // S3 STS Session Token +} + +// 返回的经过校验的分享信息 +type VerifiedShareInfo = Response +type jsonResponse struct { + Endpoint string `json:"endpoint"` // 空间所用的 S3 域名 + Region string `json:"region"` // 空间所在的 S3 区域 ID + BucketName string `json:"bucket_name"` // 空间名称 + BucketId string `json:"bucket_id"` // 空间 ID + Prefix string `json:"prefix"` // 被分享的目录路径 + Permission string `json:"permission"` // 权限,目前仅支持 READONLY,未来会支持 READWRITE + Expires string `json:"expires"` // 分享过期时间,遵循 ISO8601 风格,使用 UTC 0 时区时间 + FederatedAk string `json:"federated_ak"` // S3 STS Access Key + FederatedSk string `json:"federated_sk"` // S3 STS Secret Key + SessionToken string `json:"session_token"` // S3 STS Session Token +} + +func (j *Response) MarshalJSON() ([]byte, error) { + if err := j.validate(); err != nil { + return nil, err + } + return json.Marshal(&jsonResponse{Endpoint: j.Endpoint, Region: j.Region, BucketName: j.BucketName, BucketId: j.BucketId, Prefix: j.Prefix, Permission: j.Permission, Expires: j.Expires, FederatedAk: j.FederatedAk, FederatedSk: j.FederatedSk, SessionToken: j.SessionToken}) +} +func (j *Response) UnmarshalJSON(data []byte) error { + var nj jsonResponse + if err := json.Unmarshal(data, &nj); err != nil { + return err + } + j.Endpoint = nj.Endpoint + j.Region = nj.Region + j.BucketName = nj.BucketName + j.BucketId = nj.BucketId + j.Prefix = nj.Prefix + j.Permission = nj.Permission + j.Expires = nj.Expires + j.FederatedAk = nj.FederatedAk + j.FederatedSk = nj.FederatedSk + j.SessionToken = nj.SessionToken + return nil +} +func (j *Response) validate() error { + if j.Endpoint == "" { + return errors.MissingRequiredFieldError{Name: "Endpoint"} + } + if j.Region == "" { + return errors.MissingRequiredFieldError{Name: "Region"} + } + if j.BucketName == "" { + return errors.MissingRequiredFieldError{Name: "BucketName"} + } + if j.BucketId == "" { + return errors.MissingRequiredFieldError{Name: "BucketId"} + } + if j.Prefix == "" { + return errors.MissingRequiredFieldError{Name: "Prefix"} + } + if j.Permission == "" { + return errors.MissingRequiredFieldError{Name: "Permission"} + } + if j.Expires == "" { + return errors.MissingRequiredFieldError{Name: "Expires"} + } + if j.FederatedAk == "" { + return errors.MissingRequiredFieldError{Name: "FederatedAk"} + } + if j.FederatedSk == "" { + return errors.MissingRequiredFieldError{Name: "FederatedSk"} + } + if j.SessionToken == "" { + return errors.MissingRequiredFieldError{Name: "SessionToken"} + } + return nil +}