The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/pkg/services/store/validate.go

91 lines
2.2 KiB

package store
import (
"context"
"encoding/json"
"path/filepath"
"github.com/grafana/grafana/pkg/infra/filestorage"
"github.com/grafana/grafana/pkg/models"
)
var (
allowedImageExtensions = map[string]bool{
".jpg": true,
".jpeg": true,
".gif": true,
".png": true,
".webp": true,
}
imageExtensionsToMatchingMimeTypes = map[string]map[string]bool{
".jpg": {"image/jpg": true, "image/jpeg": true},
".jpeg": {"image/jpg": true, "image/jpeg": true},
".gif": {"image/gif": true},
".png": {"image/png": true},
".webp": {"image/webp": true},
}
)
type validationResult struct {
ok bool
reason string
}
func success() validationResult {
return validationResult{
ok: true,
}
}
func fail(reason string) validationResult {
return validationResult{
ok: false,
reason: reason,
}
}
func (s *standardStorageService) detectMimeType(ctx context.Context, user *models.SignedInUser, uploadRequest *UploadRequest) string {
// TODO: implement a spoofing-proof MimeType detection based on the contents
return uploadRequest.MimeType
}
func (s *standardStorageService) validateImage(ctx context.Context, user *models.SignedInUser, uploadRequest *UploadRequest) validationResult {
ext := filepath.Ext(uploadRequest.Path)
if !allowedImageExtensions[ext] {
return fail("unsupported extension")
}
mimeType := s.detectMimeType(ctx, user, uploadRequest)
if !imageExtensionsToMatchingMimeTypes[ext][mimeType] {
return fail("mismatched extension and file contents")
}
return success()
}
func (s *standardStorageService) validateUploadRequest(ctx context.Context, user *models.SignedInUser, req *UploadRequest, storagePath string) validationResult {
// TODO: validateSize
// TODO: validateProperties
if err := filestorage.ValidatePath(storagePath); err != nil {
return fail("path validation failed: " + err.Error())
}
switch req.EntityType {
case EntityTypeFolder:
fallthrough
case EntityTypeDashboard:
// TODO: add proper validation
var something interface{}
if err := json.Unmarshal(req.Contents, &something); err != nil {
return fail(err.Error())
}
return success()
case EntityTypeImage:
return s.validateImage(ctx, user, req)
default:
return fail("unknown entity")
}
}