551 lines
14 KiB
Go
551 lines
14 KiB
Go
package db
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
sch "gitlink.org.cn/cloudream/common/sdks/pcmscheduler"
|
|
schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler"
|
|
cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
|
|
uploadersdk "gitlink.org.cn/cloudream/common/sdks/uploader"
|
|
"gitlink.org.cn/cloudream/common/utils/serder"
|
|
"gorm.io/gorm/clause"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type UploadDataDB struct {
|
|
*DB
|
|
}
|
|
|
|
func (db *DB) UploadData() *UploadDataDB {
|
|
return &UploadDataDB{DB: db}
|
|
}
|
|
|
|
func (db *UploadDataDB) GetByPackageID(ctx SQLContext, packageIDs []cdssdk.PackageID, bindingIDs []int64) ([]uploadersdk.PackageDAO, error) {
|
|
var ret []uploadersdk.PackageDAO
|
|
err := ctx.Table("package").Where("package_id IN ? or binding_id IN ?", packageIDs, bindingIDs).Preload("UploadedCluster").Find(&ret).Error
|
|
return ret, err
|
|
}
|
|
|
|
func (db *UploadDataDB) GetByID(ctx SQLContext, ids []uploadersdk.DataID) ([]uploadersdk.Package, error) {
|
|
var ret []uploadersdk.Package
|
|
err := ctx.Table("UploadData").Where("ID IN ?", ids).Find(&ret).Error
|
|
return ret, err
|
|
}
|
|
|
|
func (db *UploadDataDB) QueryFolder(ctx SQLContext, queryParams sch.QueryData) ([]uploadersdk.Folder, error) {
|
|
var ret []uploadersdk.Folder
|
|
err := ctx.Table("folders").Where("package_id = ? and path_name like ?", queryParams.PackageID, queryParams.Path+"%").Find(&ret).Error
|
|
|
|
// 使用 map 来去重路径
|
|
pathSet := make(map[string]struct{})
|
|
for _, folder := range ret {
|
|
// 如果路径是输入路径的后一级子路径
|
|
if strings.HasPrefix(folder.Path, queryParams.Path+"/") {
|
|
path := folder.Path[len(queryParams.Path)+1:]
|
|
pathArr := strings.Split(path, "/")
|
|
if len(pathArr) == 0 {
|
|
continue
|
|
}
|
|
path = queryParams.Path + "/" + pathArr[0]
|
|
// 保留输入路径后的下一级路径,并去重
|
|
pathSet[path] = struct{}{}
|
|
}
|
|
}
|
|
|
|
// 将去重后的路径从 map 转换回切片
|
|
var result []uploadersdk.Folder
|
|
for path := range pathSet {
|
|
result = append(result, uploadersdk.Folder{Path: path})
|
|
}
|
|
|
|
return result, err
|
|
}
|
|
|
|
func (db *UploadDataDB) InsertFolder(ctx SQLContext, packageID cdssdk.PackageID, path string) error {
|
|
folder := uploadersdk.Folder{
|
|
PackageID: packageID,
|
|
Path: path,
|
|
CreateTime: time.Now(),
|
|
}
|
|
|
|
if err := ctx.Table("folders").Create(&folder).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) DeleteFolder(ctx SQLContext, packageID cdssdk.PackageID, path string) error {
|
|
err := ctx.Table("folders").Where("package_id = ? and path_name like ?", packageID, path+"%").Delete(&uploadersdk.Folder{}).Error
|
|
return err
|
|
}
|
|
|
|
func (db *UploadDataDB) QueryPackage(ctx SQLContext, queryParams sch.QueryData) ([]uploadersdk.Package, error) {
|
|
var ret []uploadersdk.PackageDAO
|
|
err := ctx.Table("package").Where("user_id = ? and data_type = ?", queryParams.UserID, queryParams.DataType).Preload("UploadedCluster").Find(&ret).Error
|
|
|
|
// 将数据转换成 uploadersdk.Package
|
|
var res []uploadersdk.Package
|
|
for _, dao := range ret {
|
|
|
|
uploadPriority, err := serder.JSONToObjectEx[sch.UploadPriority]([]byte(dao.UploadPriority))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pkg := uploadersdk.Package{
|
|
UserID: dao.UserID,
|
|
PackageID: dao.PackageID,
|
|
PackageName: dao.PackageName,
|
|
BucketID: dao.BucketID,
|
|
DataType: dao.DataType,
|
|
JsonData: dao.JsonData,
|
|
BindingID: dao.BindingID,
|
|
UploadPriority: uploadPriority,
|
|
CreateTime: dao.CreateTime,
|
|
UploadedCluster: dao.UploadedCluster,
|
|
}
|
|
res = append(res, pkg)
|
|
}
|
|
|
|
return res, err
|
|
}
|
|
|
|
func (db *UploadDataDB) QueryPackageByBindingID(ctx SQLContext, id uploadersdk.DataID) ([]uploadersdk.Package, error) {
|
|
var ret []uploadersdk.PackageDAO
|
|
err := ctx.Table("package").Where("binding_id = ?", id).Preload("Versions").Find(&ret).Error
|
|
|
|
// 将数据转换成 uploadersdk.Package
|
|
var res []uploadersdk.Package
|
|
for _, dao := range ret {
|
|
pkg := uploadersdk.Package{
|
|
UserID: dao.UserID,
|
|
PackageID: dao.PackageID,
|
|
PackageName: dao.PackageName,
|
|
BucketID: dao.BucketID,
|
|
DataType: dao.DataType,
|
|
JsonData: dao.JsonData,
|
|
BindingID: dao.BindingID,
|
|
CreateTime: dao.CreateTime,
|
|
UploadedCluster: dao.UploadedCluster,
|
|
Versions: dao.Versions,
|
|
}
|
|
res = append(res, pkg)
|
|
}
|
|
|
|
return res, err
|
|
}
|
|
|
|
func (db *UploadDataDB) InsertPackage(ctx SQLContext, newPackage uploadersdk.Package) error {
|
|
|
|
// 查询是否存在
|
|
if err := ctx.Table("package").Where("package_id = ?", newPackage.PackageID).First(&uploadersdk.PackageDAO{}).Error; err == nil {
|
|
return fmt.Errorf("package already exists")
|
|
}
|
|
|
|
// 将uploadPriority转成json string
|
|
uploadPriorityStr, err := json.Marshal(newPackage.UploadPriority)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal uploadPriority: %w", err)
|
|
}
|
|
|
|
dao := uploadersdk.PackageDAO{
|
|
PackageID: newPackage.PackageID,
|
|
PackageName: newPackage.PackageName,
|
|
DataType: newPackage.DataType,
|
|
UserID: newPackage.UserID,
|
|
BucketID: newPackage.BucketID,
|
|
UploadPriority: string(uploadPriorityStr),
|
|
CreateTime: time.Now(),
|
|
BindingID: -1,
|
|
}
|
|
|
|
// 插入新包
|
|
if err := ctx.Table("package").Create(&dao).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) DeletePackage(ctx SQLContext, userID cdssdk.UserID, packageID cdssdk.PackageID) error {
|
|
// 开启事务
|
|
tx := ctx.Begin()
|
|
err := tx.Table("package").
|
|
Where("package_id = ? and user_id = ?", packageID, userID).
|
|
Delete(&uploadersdk.PackageDAO{}).Error
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
err = tx.Table("uploadedCluster").
|
|
Where("package_id = ?", packageID).
|
|
Delete(&uploadersdk.Cluster{}).Error
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
err = tx.Table("folders").
|
|
Where("package_id = ?", packageID).
|
|
Delete(&uploadersdk.Folder{}).Error
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
err = tx.Table("packageVersion").
|
|
Where("parent_package_id = ?", packageID).
|
|
Delete(&uploadersdk.PackageVersion{}).Error
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
// 提交事务
|
|
tx.Commit()
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) QueryPackageByID(ctx SQLContext, ID cdssdk.PackageID) (uploadersdk.PackageDAO, error) {
|
|
var ret uploadersdk.PackageDAO
|
|
err := ctx.Table("package").Where("package_id = ?", ID).
|
|
Omit("Objects").Preload("Versions").
|
|
Preload("UploadedCluster").Find(&ret).Error
|
|
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
|
|
// 判断是否查询到数据
|
|
if ret.PackageID == 0 {
|
|
sql := `
|
|
select
|
|
pv.package_id,
|
|
pv.package_name,
|
|
pkg.user_id,
|
|
pkg.bucket_id,
|
|
pkg.data_type,
|
|
pkg.json_data,
|
|
pkg.binding_id,
|
|
pkg.upload_priority
|
|
from
|
|
(
|
|
select
|
|
*
|
|
from
|
|
packageVersion
|
|
where
|
|
package_id = ?
|
|
) as pv
|
|
left join(
|
|
select
|
|
*
|
|
from
|
|
package
|
|
) as pkg
|
|
on
|
|
pv.parent_package_id = pkg.package_id
|
|
`
|
|
err = ctx.Raw(sql, ID).Scan(&ret).Error
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
if ret.PackageID == 0 {
|
|
return ret, fmt.Errorf("package not found")
|
|
}
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
type ClusterMappingRow struct {
|
|
ClusterID schsdk.ClusterID `gorm:"column:clusterID" json:"clusterID"`
|
|
StorageID cdssdk.StorageID `gorm:"column:storageID" json:"storageID"`
|
|
}
|
|
|
|
func (db *UploadDataDB) GetClusterMapping(ctx SQLContext) (map[schsdk.ClusterID]cdssdk.StorageID, error) {
|
|
var rows []ClusterMappingRow
|
|
err := ctx.Table("ClusterMapping").Find(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 手动将查询结果转换为 map
|
|
ret := make(map[schsdk.ClusterID]cdssdk.StorageID)
|
|
for _, row := range rows {
|
|
ret[row.ClusterID] = row.StorageID
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (db *UploadDataDB) InsertUploadedCluster(ctx SQLContext, cluster uploadersdk.Cluster) error {
|
|
|
|
if err := ctx.Table("uploadedCluster").Create(&cluster).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) UpdatePackage(ctx SQLContext, packageID cdssdk.PackageID, jsonData string, bindingID uploadersdk.DataID) error {
|
|
|
|
if jsonData != "" {
|
|
if err := ctx.Table("package").Where("package_id = ?", packageID).Update("json_data", jsonData).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if bindingID != -1 {
|
|
if err := ctx.Table("package").Where("package_id = ?", packageID).Update("binding_id", bindingID).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) InsertPackageVersion(ctx SQLContext, parentPackageID cdssdk.PackageID, packageID cdssdk.PackageID, packageName string, version int64) error {
|
|
if err := ctx.Table("packageVersion").Where("parent_package_id = ? and package_version = ?", parentPackageID, version).First(&uploadersdk.PackageVersion{}).Error; err == nil {
|
|
return fmt.Errorf("package %d has version %d", parentPackageID, version)
|
|
}
|
|
if err := ctx.Table("packageVersion").Create(&uploadersdk.PackageVersion{
|
|
ParentPackageID: parentPackageID,
|
|
PackageID: packageID,
|
|
PackageName: packageName,
|
|
Version: version,
|
|
}).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) GetMaxVersion(ctx SQLContext, parentPackageID cdssdk.PackageID) (int64, error) {
|
|
sql := "SELECT MAX(package_version) FROM packageVersion WHERE parent_package_id = ? or package_id = ?"
|
|
var ret int64
|
|
if err := ctx.Raw(sql, parentPackageID, parentPackageID).Scan(&ret).Error; err != nil {
|
|
return 0, err
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (db *UploadDataDB) InsertBlockchains(ctx SQLContext, blockchains []*uploadersdk.BlockChain) error {
|
|
|
|
if err := ctx.Table("BlockChain").Create(&blockchains).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) GetPrivateBindings(ctx SQLContext, userID cdssdk.UserID, dataType string) ([]uploadersdk.Binding, error) {
|
|
|
|
var rows []uploadersdk.Binding
|
|
err := ctx.Table("BindingData").Where("user_id = ? and data_type = ?", userID, dataType).Find(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return rows, nil
|
|
}
|
|
|
|
func (db *UploadDataDB) GetApplyBindings(ctx SQLContext, userID cdssdk.UserID, level string, dataType string) ([]uploadersdk.BindingAccessData, error) {
|
|
var ret []uploadersdk.BindingAccessData
|
|
sql := `
|
|
select
|
|
bd.id as ID,
|
|
bd.user_id,
|
|
bd.name,
|
|
bd.data_type,
|
|
bd.content,
|
|
ar.applicant_id,
|
|
ar.status,
|
|
usr.username,
|
|
usr.sso_id
|
|
from
|
|
(
|
|
select
|
|
*
|
|
from
|
|
BindingData
|
|
where
|
|
access_level = ?
|
|
and data_type = ?
|
|
and user_id != ?
|
|
) as bd
|
|
left join (
|
|
select
|
|
data_owner_id,
|
|
binding_id,
|
|
applicant_id,
|
|
status
|
|
from
|
|
accessRequests
|
|
where applicant_id = ?
|
|
and status != ?
|
|
) as ar on
|
|
bd.user_id = ar.data_owner_id
|
|
and bd.id = ar.binding_id
|
|
left join (
|
|
select * from users
|
|
) as usr on
|
|
bd.user_id = usr.id
|
|
`
|
|
err := ctx.Raw(sql, level, dataType, userID, userID, sch.ExpiredStatus).Scan(&ret).Error
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (db *UploadDataDB) GetPublicBindings(ctx SQLContext, level string, dataType string, userID cdssdk.UserID) ([]uploadersdk.BindingAccessData, error) {
|
|
var ret []uploadersdk.BindingAccessData
|
|
sql := `
|
|
select
|
|
bd.id as ID,
|
|
bd.user_id,
|
|
bd.name,
|
|
bd.data_type,
|
|
bd.content,
|
|
bd.access_level,
|
|
ar.applicant_id,
|
|
ar.status,
|
|
usr.username,
|
|
usr.sso_id
|
|
from
|
|
(
|
|
select
|
|
*
|
|
from
|
|
BindingData
|
|
where
|
|
access_level = ?
|
|
and data_type = ?
|
|
and user_id not in (?)
|
|
) as bd
|
|
left join (
|
|
select
|
|
data_owner_id as user_id,
|
|
applicant_id,
|
|
status
|
|
from
|
|
accessRequests
|
|
) as ar on
|
|
bd.user_id = ar.user_id
|
|
left join (
|
|
select * from users
|
|
) as usr on
|
|
bd.user_id = usr.id
|
|
`
|
|
err := ctx.Raw(sql, level, dataType, userID).Scan(&ret).Error
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (db *UploadDataDB) GetBindingsByID(ctx SQLContext, ID uploadersdk.DataID) (*uploadersdk.Binding, error) {
|
|
|
|
var rows uploadersdk.Binding
|
|
err := ctx.Table("BindingData").Where("id = ?", ID).Find(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &rows, nil
|
|
}
|
|
|
|
func (db *UploadDataDB) DeleteBindingsByID(ctx SQLContext, IDs []int64) error {
|
|
tx := ctx.Begin()
|
|
if err := tx.Table("package").Where("binding_id in ?", IDs).Update("binding_id", -1).Error; err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
|
|
err := tx.Table("accessRequests").Where("binding_id in ? and status = ?", IDs, sch.ApprovedStatus).Update("status", sch.ExpiredStatus).Error
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
|
|
if err := tx.Table("BindingData").Where("id in ?", IDs).Delete(&uploadersdk.Binding{}).Error; err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
|
|
tx.Commit()
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) InsertOrUpdateBinding(ctx SQLContext, data uploadersdk.Binding) (*uploadersdk.DataID, error) {
|
|
// 根据name查询是否存在
|
|
var existData uploadersdk.Binding
|
|
err := ctx.Table("BindingData").Where("user_id = ? and name = ? and data_type = ?", data.UserID, data.Name, data.DataType).Find(&existData).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// 如果存在,则报错
|
|
if existData.ID != 0 {
|
|
return nil, fmt.Errorf("the binding name is already exists")
|
|
}
|
|
|
|
err = ctx.Table("BindingData").Clauses(clause.OnConflict{
|
|
Columns: []clause.Column{{Name: "ID"}}, // 指定冲突列
|
|
DoUpdates: clause.Assignments(map[string]interface{}{
|
|
"name": data.Name,
|
|
"content": data.Content,
|
|
}),
|
|
}).Create(&data).Error
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if data.ID == 0 {
|
|
return nil, fmt.Errorf("insert failed: ID is 0")
|
|
}
|
|
|
|
return &data.ID, nil
|
|
}
|
|
|
|
func (db *UploadDataDB) UpdateBindingAccess(ctx SQLContext, id uploadersdk.DataID, level string) error {
|
|
if err := ctx.Table("BindingData").Where("id = ?", id).Update("access_level", level).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (db *UploadDataDB) GetImageByID(ctx SQLContext, IDs []int64) ([]sch.ClusterImage, error) {
|
|
|
|
sql := `
|
|
select
|
|
bd.id as id,
|
|
bd.name as name,
|
|
ig.cluster_id as ClusterID,
|
|
ig.image_id as ClusterImageID,
|
|
ig.card_type as CardType
|
|
from
|
|
(
|
|
select
|
|
id,
|
|
name
|
|
from
|
|
BindingData
|
|
where
|
|
id in (?)
|
|
) as bd
|
|
left join (
|
|
select
|
|
id,
|
|
cluster_id,
|
|
image_id,
|
|
card_type
|
|
from
|
|
clusterImage
|
|
) as ig
|
|
on
|
|
bd.id = ig.id
|
|
`
|
|
var rows []sch.ClusterImage
|
|
err := ctx.Raw(sql, IDs).Scan(&rows).Error
|
|
//err := ctx.Table("clusterImage").Where("ID = ?", ID).Find(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return rows, nil
|
|
}
|