penadisk/dal/resources.go
2023-07-30 23:38:27 +05:00

241 lines
6.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package dal
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"strings"
"time"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/policy"
"github.com/minio/minio-go/v7/pkg/set"
)
// GetResourcesList - получить список ресурсов по указанному пути
func (mc *MinioClient) GetResourcesList(ctx context.Context, prefix string, recursive, withVersions bool) []minio.ObjectInfo {
var result []minio.ObjectInfo
for obj := range mc.client.ListObjects(ctx, mc.BucketName, minio.ListObjectsOptions{
WithVersions: withVersions,
WithMetadata: true,
Prefix: prefix,
Recursive: recursive,
}) {
result = append(result, obj)
}
return result
}
// PutResources - создать папку
func (mc *MinioClient) PutResources(ctx context.Context, path string) error {
if !strings.HasSuffix(path, "/") {
path += "/"
}
_, err := mc.client.PutObject(ctx, mc.BucketName, path, nil, 0, minio.PutObjectOptions{
ContentType: "application/directory",
})
mc.err(err)
return err
}
// UploadResources - загрузить файл
func (mc *MinioClient) UploadResources(ctx context.Context, reader io.Reader, size int64, path,
contentType string) error {
_, err := mc.client.PutObject(ctx, mc.BucketName, path, reader, size,
minio.PutObjectOptions{ContentType: contentType})
mc.err(err)
return err
}
// DownloadResources - получить ссылку на скачивание файла
func (mc *MinioClient) DownloadResources(ctx context.Context, path string) (string, error) {
href, err := mc.client.PresignedGetObject(ctx, mc.BucketName, path, time.Minute*30, nil)
mc.err(err)
return href.String(), err
}
// CopyResources - скопировать ресурсы
func (mc *MinioClient) CopyResources(ctx context.Context, src, dst string) error {
_, err := mc.client.CopyObject(ctx, minio.CopyDestOptions{
Bucket: mc.BucketName,
Object: dst,
ReplaceMetadata: true,
ReplaceTags: true,
}, minio.CopySrcOptions{
Bucket: mc.BucketName,
Object: src,
})
mc.err(err)
return err
}
// MoveResources - переместить ресурс
func (mc *MinioClient) MoveResources(ctx context.Context, src, dst string) error {
err := mc.CopyResources(ctx, src, dst)
if mc.err(err) {
return err
}
err = mc.DeleteResources(ctx, src, true)
mc.err(err)
return err
}
// DeleteResources - удалить ресурс.
func (mc *MinioClient) DeleteResources(ctx context.Context, name string, force bool) error {
if strings.HasSuffix(name, "/") {
listChan := mc.client.ListObjects(ctx, mc.BucketName, minio.ListObjectsOptions{
WithVersions: false,
WithMetadata: false,
Prefix: name,
Recursive: true,
})
mc.client.RemoveObjects(ctx, mc.BucketName, listChan, minio.RemoveObjectsOptions{})
}
err := mc.client.RemoveObject(ctx, mc.BucketName, name, minio.RemoveObjectOptions{
ForceDelete: force,
})
mc.err(err)
return err
}
// PublishResources - опубликовать ресурс. Возвращает публичную ссылку на ресурс.
//
// Ссылка на папку не будет работать. Будет получена ошибка: NoSuchKey: The specified key does not exist.
func (mc *MinioClient) PublishResources(ctx context.Context, path string) (string, error) {
curPolicy, err := mc.client.GetBucketPolicy(ctx, mc.BucketName)
if mc.err(err) {
return "", err
}
var p policy.BucketAccessPolicy
if curPolicy == "" {
policyConsoleStatement := policy.Statement{
Actions: set.CreateStringSet("*"),
Conditions: policy.ConditionMap{
"StringLike": policy.ConditionKeyMap{
"aws:referer": set.CreateStringSet(fmt.Sprintf("https://console.cloud.yandex.*/folders/*/storage/buckets/%s*", mc.BucketName)),
},
},
Effect: "Allow",
Principal: policy.User{AWS: set.CreateStringSet("*")},
Resources: set.CreateStringSet(fmt.Sprintf("arn:aws:s3:::%s/*", mc.BucketName),
fmt.Sprintf("arn:aws:s3:::%s", mc.BucketName)),
Sid: "console-statement",
}
policyServiceAccount := policy.Statement{
Actions: set.CreateStringSet("*"),
Conditions: nil,
Effect: "Allow",
Principal: policy.User{CanonicalUser: set.CreateStringSet("ajelmc4tjbct675tjdh9")},
Resources: set.CreateStringSet(fmt.Sprintf("arn:aws:s3:::%s/*", mc.BucketName),
fmt.Sprintf("arn:aws:s3:::%s", mc.BucketName)),
Sid: "service-account-statement",
}
p = policy.BucketAccessPolicy{Version: "2012-10-17", Statements: []policy.Statement{
policyConsoleStatement,
policyServiceAccount,
}}
} else {
err = json.Unmarshal([]byte(curPolicy), &p)
if mc.err(err) {
return "", err
}
}
p.Statements = policy.SetPolicy(p.Statements, policy.BucketPolicyReadOnly, mc.BucketName, path)
out, err := json.Marshal(&p)
if mc.err(err) {
return "", err
}
err = mc.client.SetBucketPolicy(ctx, mc.BucketName, string(out))
mc.err(err)
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
href := fmt.Sprintf("%v/%v%v", mc.client.EndpointURL().String(), mc.BucketName, path)
return href, err
}
// UnpublishResources - отменить публикацию ресурса
func (mc *MinioClient) UnpublishResources(ctx context.Context, path string) error {
curPolicy, err := mc.client.GetBucketPolicy(ctx, mc.BucketName)
if mc.err(err) {
return err
}
var p policy.BucketAccessPolicy
err = json.Unmarshal([]byte(curPolicy), &p)
if mc.err(err) {
return err
}
p.Statements = policy.SetPolicy(p.Statements, policy.BucketPolicyNone, mc.BucketName, path)
out, err := json.Marshal(&p)
if mc.err(err) {
return err
}
err = mc.client.SetBucketPolicy(ctx, mc.BucketName, string(out))
mc.err(err)
return err
}
func (mc *MinioClient) GetPublicResources(ctx context.Context) ([]string, error) {
curPolicy, err := mc.client.GetBucketPolicy(ctx, mc.BucketName)
log.Println(curPolicy)
if mc.err(err) {
return nil, err
}
var p policy.BucketAccessPolicy
if curPolicy == "" {
return nil, nil
}
err = json.Unmarshal([]byte(curPolicy), &p)
if mc.err(err) {
return nil, err
}
policies := policy.GetPolicies(p.Statements, mc.BucketName, "")
var result []string
for k, v := range policies {
if v == policy.BucketPolicyReadOnly {
k = strings.TrimPrefix(k, mc.BucketName+"/")
k = strings.TrimSuffix(k, "*")
result = append(result, k)
}
}
return result, nil
}