first commit
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
)
|
||||
|
||||
const MaxArtifactChunkBytes = 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.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
|
||||
}
|
||||
Reference in New Issue
Block a user