chore: 初始化 Cloudreve 源码仓库

This commit is contained in:
2026-09-13 11:28:59 +08:00
commit 2a7b03ab1d
489 changed files with 163867 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
package node
+120
View File
@@ -0,0 +1,120 @@
package node
import (
"context"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/inventory"
"github.com/cloudreve/Cloudreve/v4/pkg/credmanager"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager"
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
"github.com/cloudreve/Cloudreve/v4/pkg/util"
"github.com/gin-gonic/gin"
)
type SlaveNotificationService struct {
Subject string `uri:"subject" binding:"required"`
}
type (
OauthCredentialParamCtx struct{}
OauthCredentialService struct {
ID string `uri:"id" binding:"required"`
}
)
// Get 获取主机Oauth策略的AccessToken
func (s *OauthCredentialService) Get(c *gin.Context) (*credmanager.CredentialResponse, error) {
dep := dependency.FromContext(c)
credManager := dep.CredManager()
cred, err := credManager.Obtain(c, s.ID)
if cred == nil || err != nil {
return nil, serializer.NewError(serializer.CodeNotFound, "Credential not found", err)
}
return &credmanager.CredentialResponse{
Token: cred.String(),
ExpireAt: cred.Expiry(),
}, nil
}
type (
StatelessPrepareUploadParamCtx struct{}
)
func StatelessPrepareUpload(s *fs.StatelessPrepareUploadService, c *gin.Context) (*fs.StatelessPrepareUploadResponse, error) {
dep := dependency.FromContext(c)
userClient := dep.UserClient()
user, err := userClient.GetLoginUserByID(c, s.UserID)
if err != nil {
return nil, err
}
ctx := context.WithValue(c.Request.Context(), inventory.UserCtx{}, user)
fm := manager.NewFileManager(dep, user)
uploadSession, err := fm.PrepareUpload(ctx, s.UploadRequest)
if err != nil {
return nil, err
}
return &fs.StatelessPrepareUploadResponse{
Session: uploadSession,
Req: s.UploadRequest,
}, nil
}
type (
StatelessCompleteUploadParamCtx struct{}
)
func StatelessCompleteUpload(s *fs.StatelessCompleteUploadService, c *gin.Context) (fs.File, error) {
dep := dependency.FromContext(c)
userClient := dep.UserClient()
user, err := userClient.GetLoginUserByID(c, s.UserID)
if err != nil {
return nil, err
}
util.WithValue(c, inventory.UserCtx{}, user)
fm := manager.NewFileManager(dep, user)
return fm.CompleteUpload(c, s.UploadSession)
}
type (
StatelessOnUploadFailedParamCtx struct{}
)
func StatelessOnUploadFailed(s *fs.StatelessOnUploadFailedService, c *gin.Context) error {
dep := dependency.FromContext(c)
userClient := dep.UserClient()
user, err := userClient.GetLoginUserByID(c, s.UserID)
if err != nil {
return err
}
util.WithValue(c, inventory.UserCtx{}, user)
fm := manager.NewFileManager(dep, user)
fm.OnUploadFailed(c, s.UploadSession)
return nil
}
type StatelessCreateFileParamCtx struct{}
func StatelessCreateFile(s *fs.StatelessCreateFileService, c *gin.Context) error {
dep := dependency.FromContext(c)
userClient := dep.UserClient()
user, err := userClient.GetLoginUserByID(c, s.UserID)
if err != nil {
return err
}
uri, err := fs.NewUriFromString(s.Path)
if err != nil {
return err
}
util.WithValue(c, inventory.UserCtx{}, user)
fm := manager.NewFileManager(dep, user)
_, err = fm.Create(c, uri, s.Type)
return err
}
+150
View File
@@ -0,0 +1,150 @@
package node
import (
"context"
"fmt"
"os"
"strconv"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/ent/task"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/pkg/cluster"
"github.com/cloudreve/Cloudreve/v4/pkg/cluster/routes"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/workflows"
"github.com/cloudreve/Cloudreve/v4/pkg/logging"
"github.com/cloudreve/Cloudreve/v4/pkg/queue"
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
"github.com/gin-gonic/gin"
)
type (
CreateSlaveTaskParamCtx struct{}
)
func CreateTaskInSlave(s *cluster.CreateSlaveTask, c *gin.Context) (int, error) {
dep := dependency.FromContext(c)
registry := dep.TaskRegistry()
props, err := slaveTaskPropsFromContext(c)
if err != nil {
return 0, serializer.NewError(serializer.CodeParamErr, "failed to get master props from header", err)
}
var t queue.Task
switch s.Type {
case queue.SlaveUploadTaskType:
t = workflows.NewSlaveUploadTask(c, props, registry.NextID(), s.State)
case queue.SlaveCreateArchiveTaskType:
t = workflows.NewSlaveCreateArchiveTask(c, props, registry.NextID(), s.State)
case queue.SlaveExtractArchiveType:
t = workflows.NewSlaveExtractArchiveTask(c, props, registry.NextID(), s.State)
default:
return 0, serializer.NewError(serializer.CodeParamErr, "type not supported", nil)
}
if err := dep.SlaveQueue(c).QueueTask(c, t); err != nil {
return 0, serializer.NewError(serializer.CodeInternalSetting, "failed to queue task", err)
}
registry.Set(t.ID(), t)
return t.ID(), nil
}
type (
GetSlaveTaskParamCtx struct{}
GetSlaveTaskService struct {
ID int `uri:"id" binding:"required"`
}
)
func (s *GetSlaveTaskService) Get(c *gin.Context) (*cluster.SlaveTaskSummary, error) {
dep := dependency.FromContext(c)
registry := dep.TaskRegistry()
t, ok := registry.Get(s.ID)
if !ok {
return nil, serializer.NewError(serializer.CodeNotFound, "task not found", nil)
}
status := t.Status()
_, clearOnComplete := c.GetQuery(routes.SlaveClearTaskRegistryQuery)
if clearOnComplete && status == task.StatusCompleted ||
status == task.StatusError ||
status == task.StatusCanceled {
registry.Delete(s.ID)
}
res := &cluster.SlaveTaskSummary{
Status: status,
PrivateState: t.State(),
Progress: t.Progress(c),
}
err := t.Error()
if err != nil {
res.Error = err.Error()
}
return res, nil
}
func slaveTaskPropsFromContext(ctx context.Context) (*types.SlaveTaskProps, error) {
nodeIdStr, ok := ctx.Value(cluster.SlaveNodeIDCtx{}).(string)
if !ok {
return nil, fmt.Errorf("failed to get node ID from context")
}
nodeId, err := strconv.Atoi(nodeIdStr)
if err != nil {
return nil, fmt.Errorf("failed to convert node ID to int: %w", err)
}
masterSiteUrl := cluster.MasterSiteUrlFromContext(ctx)
if masterSiteUrl == "" {
return nil, fmt.Errorf("failed to get master site URL from context")
}
masterSiteVersion, ok := ctx.Value(cluster.MasterSiteVersionCtx{}).(string)
if !ok {
return nil, fmt.Errorf("failed to get master site version from context")
}
masterSiteId, ok := ctx.Value(cluster.MasterSiteIDCtx{}).(string)
if !ok {
return nil, fmt.Errorf("failed to convert master site ID to int: %w", err)
}
props := &types.SlaveTaskProps{
NodeID: nodeId,
MasterSiteID: masterSiteId,
MasterSiteURl: masterSiteUrl,
MasterSiteVersion: masterSiteVersion,
}
return props, nil
}
type (
FolderCleanupParamCtx struct{}
)
func Cleanup(args *cluster.FolderCleanup, c *gin.Context) error {
l := logging.FromContext(c)
ae := serializer.NewAggregateError()
for _, p := range args.Path {
l.Info("Cleaning up folder %q", p)
if err := os.RemoveAll(p); err != nil {
l.Warning("Failed to clean up folder %q: %s", p, err)
ae.Add(p, err)
}
}
return ae.Aggregate()
}
type (
CreateSlaveDownloadTaskParamCtx struct{}
GetSlaveDownloadTaskParamCtx struct{}
CancelSlaveDownloadTaskParamCtx struct{}
SelectSlaveDownloadFilesParamCtx struct{}
TestSlaveDownloadParamCtx struct{}
)