Add server file manager workflow

This commit is contained in:
npc0-hue
2026-08-24 12:56:55 +08:00
parent dc9b0eaf2a
commit 33d3a13e74
20 changed files with 1961 additions and 22 deletions
+114 -2
View File
@@ -1421,6 +1421,104 @@ func ValidateFileOperationDispatchRequest(request domain.FileOperationDispatchRe
return finish(violations)
}
func ValidateServerFileListRequest(request domain.ServerFileListRequest) error {
var violations []string
violations = appendRequired(violations, "serverInstanceId", request.ServerInstanceID)
violations = appendRequired(violations, "directoryKey", request.DirectoryKey)
if !validLogicalFileKey(request.DirectoryKey) {
violations = append(violations, "directoryKey is not allowed")
}
if request.Path != "" && !validLogicalFileKey(request.Path) {
violations = append(violations, "path is not allowed")
}
if len([]rune(request.Query)) > 80 || containsUnsafeRuntimeSecret(request.Query) || looksLikeRawHostPath(request.Query) {
violations = append(violations, "query is not allowed")
}
if request.IdempotencyKey != "" && (containsUnsafeRuntimeSecret(request.IdempotencyKey) || looksLikeRawHostPath(request.IdempotencyKey)) {
violations = append(violations, "idempotencyKey is not allowed")
}
return finish(violations)
}
func ValidateServerFileReadRequest(request domain.ServerFileReadRequest) error {
return ValidateFileOperationDispatchRequest(domain.FileOperationDispatchRequest{ServerInstanceID: request.ServerInstanceID, PluginID: request.PluginID, Operation: domain.FileOperationRead, Key: request.Key, IdempotencyKey: request.IdempotencyKey})
}
func ValidateServerFileWriteRequest(request domain.ServerFileWriteRequest) error {
return ValidateFileOperationDispatchRequest(domain.FileOperationDispatchRequest{ServerInstanceID: request.ServerInstanceID, PluginID: request.PluginID, Operation: domain.FileOperationWrite, Key: request.Key, InputRef: request.InputRef, Content: request.Content, ExpectedConfigVersion: request.ExpectedVersion, ExpectedChecksum: request.ExpectedChecksum, IdempotencyKey: request.IdempotencyKey})
}
func ValidateServerFileUploadRequest(request domain.ServerFileUploadRequest) error {
request = domain.CopyServerFileUploadRequest(request)
var violations []string
violations = appendRequired(violations, "serverInstanceId", request.ServerInstanceID)
violations = appendRequired(violations, "directoryKey", request.DirectoryKey)
violations = appendRequired(violations, "filename", request.Filename)
violations = appendRequired(violations, "checksum", request.Checksum)
violations = appendRequired(violations, "idempotencyKey", request.IdempotencyKey)
if !validLogicalFileKey(request.DirectoryKey) {
violations = append(violations, "directoryKey is not allowed")
}
if request.RelativePath != "" && !validLogicalFileKey(request.RelativePath) {
violations = append(violations, "relativePath is not allowed")
}
if !validUploadFilename(request.Filename) {
violations = append(violations, "filename is not allowed")
}
if len(request.Payload) == 0 {
violations = append(violations, "payload is required")
}
if int64(len(request.Payload)) > MaxArtifactBytes {
violations = append(violations, fmt.Sprintf("payload must not exceed %d", MaxArtifactBytes))
}
if request.Checksum != "" {
if !validSHA256Checksum(request.Checksum) {
violations = append(violations, "checksum must be sha256:<hex>")
} else if request.Checksum != BytesChecksum(request.Payload) {
violations = append(violations, "checksum does not match payload")
}
}
for _, value := range []string{request.ServerInstanceID, request.DirectoryKey, request.RelativePath, request.Filename, request.IdempotencyKey} {
if containsUnsafeRuntimeSecret(value) || looksLikeRawHostPath(value) || strings.Contains(strings.ToLower(value), "unix://") {
violations = append(violations, "request contains unsafe content")
break
}
}
return finish(violations)
}
func ValidateServerFileDownloadRequest(request domain.ServerFileDownloadRequest) error {
var violations []string
violations = appendRequired(violations, "serverInstanceId", request.ServerInstanceID)
violations = appendRequired(violations, "key", request.Key)
violations = appendRequired(violations, "idempotencyKey", request.IdempotencyKey)
if !validLogicalFileKey(request.Key) {
violations = append(violations, "key is not allowed")
}
if containsUnsafeRuntimeSecret(request.IdempotencyKey) || looksLikeRawHostPath(request.IdempotencyKey) {
violations = append(violations, "idempotencyKey is not allowed")
}
return finish(violations)
}
func ValidateRunFileInputChunkRequest(request domain.RunFileInputChunkRequest) error {
var violations []string
violations = appendRequired(violations, "runEndpointId", request.RunEndpointID)
violations = appendRequired(violations, "sessionToken", request.SessionToken)
violations = appendRequired(violations, "jobId", request.JobID)
violations = appendRequired(violations, "leaseToken", request.LeaseToken)
if request.Attempt <= 0 {
violations = append(violations, "attempt must be positive")
}
if request.Offset < 0 {
violations = append(violations, "offset must not be negative")
}
if request.Length <= 0 || request.Length > MaxArtifactDownloadBytes {
violations = append(violations, fmt.Sprintf("length must be between 1 and %d", MaxArtifactDownloadBytes))
}
return finish(violations)
}
func appendPercentViolation(violations []string, field string, value float64) []string {
if value < 0 || value > 100 {
return append(violations, field+" must be between 0 and 100")
@@ -1588,7 +1686,7 @@ func ValidateJob(job domain.Job) error {
if len(job.ExecutionResult.Summary) > maxSummaryLength {
violations = append(violations, "executionResult.summary is too long")
}
if job.Capability == domain.JobCapabilityConfigWrite || job.Capability == domain.JobCapabilityFilesRead || job.Capability == domain.JobCapabilityFilesWrite {
if job.Capability == domain.JobCapabilityConfigWrite || job.Capability == domain.JobCapabilityFilesList || job.Capability == domain.JobCapabilityFilesRead || job.Capability == domain.JobCapabilityFilesWrite {
if job.ServerInstanceID == "" {
violations = append(violations, "serverInstanceId is required for scoped file jobs")
}
@@ -2305,13 +2403,27 @@ func validRemoteDatabaseEngine(engine string) bool {
func validFileOperationKind(operation domain.FileOperationKind) bool {
switch operation {
case domain.FileOperationRead, domain.FileOperationWrite:
case domain.FileOperationList, domain.FileOperationRead, domain.FileOperationWrite:
return true
default:
return false
}
}
func validUploadFilename(name string) bool {
trimmed := strings.TrimSpace(name)
if trimmed == "" || trimmed != name || len([]rune(name)) > 120 || strings.Contains(name, "/") || strings.Contains(name, `\`) || strings.Contains(name, "..") || strings.Contains(name, "://") || looksLikeRawHostPath(name) || containsUnsafeRuntimeSecret(name) {
return false
}
for _, char := range name {
if (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9') || char == '_' || char == '-' || char == '.' || char == ' ' || char == '(' || char == ')' {
continue
}
return false
}
return true
}
func validConfigFileKey(key string) bool {
switch key {
case "server.properties", "config/server.properties":