Files

128 lines
4.8 KiB
Go

package validator
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"strings"
"browser.local/platform/domain"
)
const (
MaxArtifactChunkBytes = 1024 * 1024
MaxArtifactBytes = int64(512 * 1024 * 1024)
)
func ValidateArtifactTransferOpen(open domain.ArtifactTransferOpen) error {
var violations []string
violations = appendRequired(violations, "runEndpointId", open.RunEndpointID)
violations = appendRequired(violations, "sessionToken", open.SessionToken)
violations = appendRequired(violations, "artifactId", open.ArtifactID)
violations = appendRequired(violations, "ownerId", open.OwnerID)
violations = appendRequired(violations, "checksum", open.Checksum)
violations = appendRequired(violations, "idempotencyKey", open.IdempotencyKey)
if open.Direction != domain.ArtifactTransferDirectionUpload {
violations = append(violations, "direction must be upload")
}
if !validArtifactOwnerKind(open.OwnerKind) {
violations = append(violations, "ownerKind is invalid")
}
if open.OwnerKind != domain.ArtifactOwnerKindJob && open.OwnerKind != domain.ArtifactOwnerKindServerInstance {
violations = append(violations, "ownerKind must be job or server-instance for run uploads")
}
if open.SizeBytes <= 0 {
violations = append(violations, "sizeBytes must be positive")
}
if open.SizeBytes > MaxArtifactBytes {
violations = append(violations, fmt.Sprintf("sizeBytes must not exceed %d", MaxArtifactBytes))
}
if open.ChunkSizeBytes <= 0 {
violations = append(violations, "chunkSizeBytes must be positive")
}
if open.ChunkSizeBytes > MaxArtifactChunkBytes {
violations = append(violations, fmt.Sprintf("chunkSizeBytes must not exceed %d", MaxArtifactChunkBytes))
}
if open.Checksum != "" && !validSHA256Checksum(open.Checksum) {
violations = append(violations, "checksum must be sha256:<hex>")
}
return finish(violations)
}
func ValidateArtifactChunkUpload(chunk domain.ArtifactChunkUpload) error {
var violations []string
violations = appendRequired(violations, "runEndpointId", chunk.RunEndpointID)
violations = appendRequired(violations, "sessionToken", chunk.SessionToken)
violations = appendRequired(violations, "transferId", chunk.TransferID)
violations = appendRequired(violations, "artifactId", chunk.ArtifactID)
violations = appendRequired(violations, "checksum", chunk.Checksum)
if chunk.ChunkIndex < 0 {
violations = append(violations, "chunkIndex must not be negative")
}
if chunk.Offset < 0 {
violations = append(violations, "offset must not be negative")
}
if chunk.SizeBytes <= 0 {
violations = append(violations, "sizeBytes must be positive")
}
if chunk.SizeBytes > MaxArtifactChunkBytes {
violations = append(violations, fmt.Sprintf("sizeBytes must not exceed %d", MaxArtifactChunkBytes))
}
if len(chunk.Payload) == 0 {
violations = append(violations, "payload must not be empty")
}
if chunk.SizeBytes > 0 && len(chunk.Payload) != chunk.SizeBytes {
violations = append(violations, "sizeBytes must match payload size")
}
if chunk.Checksum != "" {
if !validSHA256Checksum(chunk.Checksum) {
violations = append(violations, "checksum must be sha256:<hex>")
} else if chunk.Checksum != BytesChecksum(chunk.Payload) {
violations = append(violations, "checksum does not match payload")
}
}
return finish(violations)
}
func ValidateArtifactTransferStatusQuery(query domain.ArtifactTransferStatusQuery) error {
var violations []string
violations = appendRequired(violations, "runEndpointId", query.RunEndpointID)
violations = appendRequired(violations, "sessionToken", query.SessionToken)
violations = appendRequired(violations, "transferId", query.TransferID)
violations = appendRequired(violations, "artifactId", query.ArtifactID)
return finish(violations)
}
func ValidateArtifactTransferComplete(complete domain.ArtifactTransferComplete) error {
var violations []string
violations = appendRequired(violations, "runEndpointId", complete.RunEndpointID)
violations = appendRequired(violations, "sessionToken", complete.SessionToken)
violations = appendRequired(violations, "transferId", complete.TransferID)
violations = appendRequired(violations, "artifactId", complete.ArtifactID)
violations = appendRequired(violations, "checksum", complete.Checksum)
if complete.SizeBytes <= 0 {
violations = append(violations, "sizeBytes must be positive")
}
if complete.Checksum != "" && !validSHA256Checksum(complete.Checksum) {
violations = append(violations, "checksum must be sha256:<hex>")
}
return finish(violations)
}
func BytesChecksum(payload []byte) string {
sum := sha256.Sum256(payload)
return "sha256:" + hex.EncodeToString(sum[:])
}
func validSHA256Checksum(value string) bool {
if !strings.HasPrefix(value, "sha256:") {
return false
}
hexValue := strings.TrimPrefix(value, "sha256:")
if len(hexValue) != sha256.Size*2 {
return false
}
_, err := hex.DecodeString(hexValue)
return err == nil
}