mirror of https://github.com/cloudreve/Cloudreve
193 lines
6.4 KiB
Go
193 lines
6.4 KiB
Go
package migrator
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/cloudreve/Cloudreve/v4/application/migrator/model"
|
|
"github.com/cloudreve/Cloudreve/v4/ent/node"
|
|
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
|
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/conf"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/setting"
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
func (m *Migrator) migratePolicy() (map[int]bool, error) {
|
|
m.l.Info("Migrating storage policies...")
|
|
var policies []model.Policy
|
|
if err := model.DB.Find(&policies).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to list v3 storage policies: %w", err)
|
|
}
|
|
|
|
if m.state.LocalPolicyIDs == nil {
|
|
m.state.LocalPolicyIDs = make(map[int]bool)
|
|
}
|
|
|
|
if m.state.PolicyIDs == nil {
|
|
m.state.PolicyIDs = make(map[int]bool)
|
|
}
|
|
|
|
m.l.Info("Found %d v3 storage policies to be migrated.", len(policies))
|
|
|
|
// get thumb proxy settings
|
|
var (
|
|
thumbProxySettings []model.Setting
|
|
thumbProxyEnabled bool
|
|
thumbProxyPolicy []int
|
|
)
|
|
if err := model.DB.Where("name in (?)", []string{"thumb_proxy_enabled", "thumb_proxy_policy"}).Find(&thumbProxySettings).Error; err != nil {
|
|
m.l.Warning("Failed to list v3 thumb proxy settings: %w", err)
|
|
}
|
|
|
|
tx, err := m.v4client.Tx(context.Background())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to start transaction: %w", err)
|
|
}
|
|
|
|
for _, s := range thumbProxySettings {
|
|
if s.Name == "thumb_proxy_enabled" {
|
|
thumbProxyEnabled = setting.IsTrueValue(s.Value)
|
|
} else if s.Name == "thumb_proxy_policy" {
|
|
if err := json.Unmarshal([]byte(s.Value), &thumbProxyPolicy); err != nil {
|
|
m.l.Warning("Failed to unmarshal v3 thumb proxy policy: %w", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, policy := range policies {
|
|
m.l.Info("Migrating storage policy %q...", policy.Name)
|
|
if err := json.Unmarshal([]byte(policy.Options), &policy.OptionsSerialized); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal options for policy %q: %w", policy.Name, err)
|
|
}
|
|
|
|
settings := &types.PolicySetting{
|
|
Token: policy.OptionsSerialized.Token,
|
|
FileType: policy.OptionsSerialized.FileType,
|
|
OauthRedirect: policy.OptionsSerialized.OauthRedirect,
|
|
OdDriver: policy.OptionsSerialized.OdDriver,
|
|
Region: policy.OptionsSerialized.Region,
|
|
ServerSideEndpoint: policy.OptionsSerialized.ServerSideEndpoint,
|
|
ChunkSize: int64(policy.OptionsSerialized.ChunkSize),
|
|
TPSLimit: policy.OptionsSerialized.TPSLimit,
|
|
TPSLimitBurst: policy.OptionsSerialized.TPSLimitBurst,
|
|
S3ForcePathStyle: policy.OptionsSerialized.S3ForcePathStyle,
|
|
ThumbExts: policy.OptionsSerialized.ThumbExts,
|
|
}
|
|
|
|
if policy.Type == types.PolicyTypeOd {
|
|
settings.ThumbSupportAllExts = true
|
|
} else {
|
|
switch policy.Type {
|
|
case types.PolicyTypeCos:
|
|
settings.ThumbExts = []string{"png", "jpg", "jpeg", "gif", "bmp", "webp", "heif", "heic"}
|
|
case types.PolicyTypeOss:
|
|
settings.ThumbExts = []string{"png", "jpg", "jpeg", "gif", "bmp", "webp", "heic", "tiff", "avif"}
|
|
case types.PolicyTypeUpyun:
|
|
settings.ThumbExts = []string{"png", "jpg", "jpeg", "gif", "bmp", "webp", "svg"}
|
|
case types.PolicyTypeQiniu:
|
|
settings.ThumbExts = []string{"png", "jpg", "jpeg", "gif", "bmp", "webp", "tiff", "avif", "psd"}
|
|
case types.PolicyTypeRemote:
|
|
settings.ThumbExts = []string{"png", "jpg", "jpeg", "gif"}
|
|
}
|
|
}
|
|
|
|
if policy.Type != types.PolicyTypeOd && policy.BaseURL != "" {
|
|
settings.CustomProxy = true
|
|
settings.ProxyServer = policy.BaseURL
|
|
} else if policy.OptionsSerialized.OdProxy != "" {
|
|
settings.CustomProxy = true
|
|
settings.ProxyServer = policy.OptionsSerialized.OdProxy
|
|
}
|
|
|
|
if policy.DirNameRule == "" {
|
|
policy.DirNameRule = "uploads/{uid}/{path}"
|
|
}
|
|
|
|
if policy.Type == types.PolicyTypeCos {
|
|
settings.ChunkSize = 1024 * 1024 * 25
|
|
}
|
|
|
|
if thumbProxyEnabled && lo.Contains(thumbProxyPolicy, int(policy.ID)) {
|
|
settings.ThumbGeneratorProxy = true
|
|
}
|
|
|
|
mustContain := []string{"{randomkey16}", "{randomkey8}", "{uuid}"}
|
|
hasRandomElement := false
|
|
for _, c := range mustContain {
|
|
if strings.Contains(policy.FileNameRule, c) {
|
|
hasRandomElement = true
|
|
break
|
|
}
|
|
}
|
|
if !hasRandomElement {
|
|
policy.FileNameRule = "{uid}_{randomkey8}_{originname}"
|
|
m.l.Warning("Storage policy %q has no random element in file name rule, using default file name rule.", policy.Name)
|
|
}
|
|
|
|
stm := tx.StoragePolicy.Create().
|
|
SetRawID(int(policy.ID)).
|
|
SetCreatedAt(formatTime(policy.CreatedAt)).
|
|
SetUpdatedAt(formatTime(policy.UpdatedAt)).
|
|
SetName(policy.Name).
|
|
SetType(policy.Type).
|
|
SetServer(policy.Server).
|
|
SetBucketName(policy.BucketName).
|
|
SetIsPrivate(policy.IsPrivate).
|
|
SetAccessKey(policy.AccessKey).
|
|
SetSecretKey(policy.SecretKey).
|
|
SetMaxSize(int64(policy.MaxSize)).
|
|
SetDirNameRule(policy.DirNameRule).
|
|
SetFileNameRule(policy.FileNameRule).
|
|
SetSettings(settings)
|
|
|
|
if policy.Type == types.PolicyTypeRemote {
|
|
m.l.Info("Storage policy %q is remote, creating node for it...", policy.Name)
|
|
bs := &boolset.BooleanSet{}
|
|
n, err := tx.Node.Create().
|
|
SetName(policy.Name).
|
|
SetStatus(node.StatusActive).
|
|
SetServer(policy.Server).
|
|
SetSlaveKey(policy.SecretKey).
|
|
SetType(node.TypeSlave).
|
|
SetCapabilities(bs).
|
|
SetSettings(&types.NodeSetting{
|
|
Provider: types.DownloaderProviderAria2,
|
|
}).
|
|
Save(context.Background())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create node for storage policy %q: %w", policy.Name, err)
|
|
}
|
|
|
|
stm.SetNodeID(n.ID)
|
|
}
|
|
|
|
if _, err := stm.Save(context.Background()); err != nil {
|
|
return nil, fmt.Errorf("failed to create storage policy %q: %w", policy.Name, err)
|
|
}
|
|
|
|
m.state.PolicyIDs[int(policy.ID)] = true
|
|
if policy.Type == types.PolicyTypeLocal {
|
|
m.state.LocalPolicyIDs[int(policy.ID)] = true
|
|
}
|
|
}
|
|
if err := tx.Commit(); err != nil {
|
|
return nil, fmt.Errorf("failed to commit transaction: %w", err)
|
|
}
|
|
|
|
if m.dep.ConfigProvider().Database().Type == conf.PostgresDB {
|
|
m.l.Info("Resetting storage policy ID sequence for postgres...")
|
|
m.v4client.StoragePolicy.ExecContext(context.Background(), "SELECT SETVAL('storage_policies_id_seq', (SELECT MAX(id) FROM storage_policies))")
|
|
}
|
|
|
|
if m.dep.ConfigProvider().Database().Type == conf.PostgresDB {
|
|
m.l.Info("Resetting node ID sequence for postgres...")
|
|
m.v4client.Node.ExecContext(context.Background(), "SELECT SETVAL('nodes_id_seq', (SELECT MAX(id) FROM nodes))")
|
|
}
|
|
|
|
return m.state.PolicyIDs, nil
|
|
}
|