mirror of
https://github.com/grafana/grafana.git
synced 2024-11-27 03:11:01 -06:00
99fd7b8141
* add ValidateUID to util * provisioning to validate UID on rule creation --------- Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com> Co-authored-by: Alexander Weaver <weaver.alex.d@gmail.com>
78 lines
2.1 KiB
Go
78 lines
2.1 KiB
Go
package util
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math/rand"
|
|
"regexp"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
const MaxUIDLength = 40
|
|
|
|
var uidrand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
var alphaRunes = []rune("abcdefghijklmnopqrstuvwxyz")
|
|
var hexLetters = []rune("abcdef")
|
|
|
|
var (
|
|
ErrUIDTooLong = fmt.Errorf("UID is longer than %d symbols", MaxUIDLength)
|
|
ErrUIDFormatInvalid = errors.New("invalid format of UID. Only letters, numbers, '-' and '_' are allowed")
|
|
ErrUIDEmpty = fmt.Errorf("UID is empty")
|
|
)
|
|
|
|
// We want to protect our number generator as they are not thread safe. Not using
|
|
// the mutex could result in panics in certain cases where UIDs would be generated
|
|
// at the same time.
|
|
var mtx sync.Mutex
|
|
|
|
// Legacy UID pattern
|
|
var validUIDPattern = regexp.MustCompile(`^[a-zA-Z0-9\-\_]*$`).MatchString
|
|
|
|
// IsValidShortUID checks if short unique identifier contains valid characters
|
|
// NOTE: future Grafana UIDs will need conform to https://github.com/kubernetes/apimachinery/blob/master/pkg/util/validation/validation.go#L43
|
|
func IsValidShortUID(uid string) bool {
|
|
return validUIDPattern(uid)
|
|
}
|
|
|
|
// IsShortUIDTooLong checks if short unique identifier is too long
|
|
func IsShortUIDTooLong(uid string) bool {
|
|
return len(uid) > MaxUIDLength
|
|
}
|
|
|
|
// GenerateShortUID will generate a UUID that can also be a k8s name
|
|
// it is guaranteed to have a character as the first letter
|
|
// This UID will be a valid k8s name
|
|
func GenerateShortUID() string {
|
|
mtx.Lock()
|
|
defer mtx.Unlock()
|
|
uid, err := uuid.NewRandom()
|
|
if err != nil {
|
|
// This should never happen... but this seems better than a panic
|
|
for i := range uid {
|
|
uid[i] = byte(uidrand.Intn(255))
|
|
}
|
|
}
|
|
uuid := uid.String()
|
|
if rune(uuid[0]) < rune('a') {
|
|
return string(hexLetters[uidrand.Intn(len(hexLetters))]) + uuid[1:]
|
|
}
|
|
return uuid
|
|
}
|
|
|
|
// ValidateUID checks the format and length of the string and returns error if it does not pass the condition
|
|
func ValidateUID(uid string) error {
|
|
if len(uid) == 0 {
|
|
return ErrUIDEmpty
|
|
}
|
|
if IsShortUIDTooLong(uid) {
|
|
return ErrUIDTooLong
|
|
}
|
|
if !IsValidShortUID(uid) {
|
|
return ErrUIDFormatInvalid
|
|
}
|
|
return nil
|
|
}
|