mirror of
https://github.com/datarhei/core.git
synced 2025-09-27 12:22:28 +08:00
176 lines
3.5 KiB
Go
176 lines
3.5 KiB
Go
package value
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// array of s3 storages
|
|
// https://access_key_id:secret_access_id@region.endpoint/bucket?name=aaa&mount=/abc&username=xxx&password=yyy
|
|
|
|
type S3Storage struct {
|
|
Name string `json:"name"`
|
|
Mountpoint string `json:"mountpoint"`
|
|
Auth S3StorageAuth `json:"auth"`
|
|
Endpoint string `json:"endpoint"`
|
|
AccessKeyID string `json:"access_key_id"`
|
|
SecretAccessKey string `json:"secret_access_key"`
|
|
Bucket string `json:"bucket"`
|
|
Region string `json:"region"`
|
|
UseSSL bool `json:"use_ssl"`
|
|
}
|
|
|
|
type S3StorageAuth struct {
|
|
Enable bool `json:"enable"`
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
func (t *S3Storage) String() string {
|
|
u := url.URL{}
|
|
|
|
if t.UseSSL {
|
|
u.Scheme = "https"
|
|
} else {
|
|
u.Scheme = "http"
|
|
}
|
|
|
|
u.User = url.UserPassword(t.AccessKeyID, "---")
|
|
|
|
u.Host = t.Endpoint
|
|
|
|
if len(t.Region) != 0 {
|
|
u.Host = t.Region + "." + u.Host
|
|
}
|
|
|
|
if len(t.Bucket) != 0 {
|
|
u.Path = "/" + t.Bucket
|
|
}
|
|
|
|
v := url.Values{}
|
|
v.Set("name", t.Name)
|
|
v.Set("mount", t.Mountpoint)
|
|
|
|
if t.Auth.Enable {
|
|
if len(t.Auth.Username) != 0 {
|
|
v.Set("username", t.Auth.Username)
|
|
}
|
|
|
|
if len(t.Auth.Password) != 0 {
|
|
v.Set("password", "---")
|
|
}
|
|
}
|
|
|
|
u.RawQuery = v.Encode()
|
|
|
|
return u.String()
|
|
}
|
|
|
|
type s3StorageListValue struct {
|
|
p *[]S3Storage
|
|
separator string
|
|
reName *regexp.Regexp
|
|
}
|
|
|
|
func NewS3StorageListValue(p *[]S3Storage, val []S3Storage, separator string) *s3StorageListValue {
|
|
v := &s3StorageListValue{
|
|
p: p,
|
|
separator: separator,
|
|
reName: regexp.MustCompile(`^[A-Za-z0-9_-]+$`),
|
|
}
|
|
|
|
*p = val
|
|
return v
|
|
}
|
|
|
|
func (s *s3StorageListValue) Set(val string) error {
|
|
list := []S3Storage{}
|
|
|
|
for _, elm := range strings.Split(val, s.separator) {
|
|
u, err := url.Parse(elm)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid S3 storage URL (%s): %w", elm, err)
|
|
}
|
|
|
|
t := S3Storage{
|
|
Name: u.Query().Get("name"),
|
|
Mountpoint: u.Query().Get("mount"),
|
|
AccessKeyID: u.User.Username(),
|
|
}
|
|
|
|
password, _ := u.User.Password()
|
|
t.SecretAccessKey = password
|
|
|
|
region, endpoint, _ := strings.Cut(u.Host, ".")
|
|
t.Endpoint = endpoint
|
|
t.Region = region
|
|
|
|
secret, ok := u.User.Password()
|
|
if ok {
|
|
t.SecretAccessKey = secret
|
|
}
|
|
|
|
t.Bucket = strings.TrimPrefix(u.Path, "/")
|
|
|
|
if u.Scheme == "https" {
|
|
t.UseSSL = true
|
|
}
|
|
|
|
if u.Query().Has("username") || u.Query().Has("password") {
|
|
t.Auth.Enable = true
|
|
t.Auth.Username = u.Query().Get("username")
|
|
t.Auth.Password = u.Query().Get("password")
|
|
}
|
|
|
|
list = append(list, t)
|
|
}
|
|
|
|
*s.p = list
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *s3StorageListValue) String() string {
|
|
if s.IsEmpty() {
|
|
return "(empty)"
|
|
}
|
|
|
|
list := []string{}
|
|
|
|
for _, t := range *s.p {
|
|
list = append(list, t.String())
|
|
}
|
|
|
|
return strings.Join(list, s.separator)
|
|
}
|
|
|
|
func (s *s3StorageListValue) Validate() error {
|
|
for i, t := range *s.p {
|
|
if len(t.Name) == 0 {
|
|
return fmt.Errorf("the name for s3 storage %d is missing", i)
|
|
}
|
|
|
|
if !s.reName.MatchString(t.Name) {
|
|
return fmt.Errorf("the name for s3 storage must match the pattern %s", s.reName.String())
|
|
}
|
|
|
|
if len(t.Mountpoint) == 0 {
|
|
return fmt.Errorf("the mountpoint for s3 storage %d is missing", i)
|
|
}
|
|
|
|
if t.Auth.Enable {
|
|
if len(t.Auth.Username) == 0 && len(t.Auth.Password) == 0 {
|
|
return fmt.Errorf("auth is enabled, but no username and password are set for s3 storage %d", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *s3StorageListValue) IsEmpty() bool {
|
|
return len(*s.p) == 0
|
|
}
|