onepanel/pkg/files.go
2021-07-30 14:21:15 -07:00

111 lines
2.7 KiB
Go

package v1
import (
"fmt"
"github.com/minio/minio-go/v6"
"github.com/onepanelio/core/pkg/util"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"net/url"
"strings"
"time"
)
// GetPresignedURLDownload represents the information available when downloading an object
type GetPresignedURLDownload struct {
URL string
Size int64
}
// ListFiles returns an array of files for the given namespace/key
func (c *Client) ListFiles(namespace, key string) (files []*File, err error) {
config, err := c.GetNamespaceConfig(namespace)
if err != nil {
return
}
if config.ArtifactRepository.S3 == nil {
return nil, util.NewUserError(codes.Internal, "S3 compatible artifact repository not set")
}
files = make([]*File, 0)
if len(key) > 0 && strings.HasPrefix(key, "/") {
key = key[1:]
}
if len(key) > 0 {
if string(key[len(key)-1]) != "/" {
key += "/"
}
}
s3Client, err := c.GetS3Client(namespace, config.ArtifactRepository.S3)
if err != nil {
return nil, err
}
doneCh := make(chan struct{})
defer close(doneCh)
for objInfo := range s3Client.ListObjects(config.ArtifactRepository.S3.Bucket, key, false, doneCh) {
if objInfo.Key == key {
continue
}
isDirectory := (objInfo.ETag == "" || strings.HasSuffix(objInfo.Key, "/")) && objInfo.Size == 0
newFile := &File{
Path: objInfo.Key,
Name: FilePathToName(objInfo.Key),
Extension: FilePathToExtension(objInfo.Key),
Size: objInfo.Size,
LastModified: objInfo.LastModified,
ContentType: objInfo.ContentType,
Directory: isDirectory,
}
files = append(files, newFile)
}
return
}
// GetObjectPresignedURL generates a presigned url for the object that is valid for 24 hours.
func (c *Client) GetObjectPresignedURL(namespace, key string) (download *GetPresignedURLDownload, err error) {
config, err := c.GetNamespaceConfig(namespace)
if err != nil {
return
}
s3Client, err := c.GetPublicS3Client(namespace, config.ArtifactRepository.S3)
if err != nil {
return
}
objInfo, err := s3Client.StatObject(config.ArtifactRepository.S3.Bucket, key, minio.StatObjectOptions{})
if err != nil {
log.WithFields(log.Fields{
"Namespace": namespace,
"Key": key,
"Error": err.Error(),
}).Error("StatObject")
return
}
reqParams := make(url.Values)
reqParams.Set("response-content-disposition", fmt.Sprintf("attachment; filename=\"%s\"", key))
presignedURL, err := s3Client.PresignedGetObject(config.ArtifactRepository.S3.Bucket, key, time.Hour*24, reqParams)
if err != nil {
log.WithFields(log.Fields{
"Namespace": namespace,
"Key": key,
"Error": err.Error(),
}).Error("PresignedGetObject")
return
}
return &GetPresignedURLDownload{
URL: presignedURL.String(),
Size: objInfo.Size,
}, nil
}