JCC-CSScheduler/common/pkgs/db/upload_data.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
}