Skip to content
Snippets Groups Projects
random.go 1.08 KiB
Newer Older
  • Learn to ignore specific revisions
  • package util
    
    import (
    	"crypto/rand"
    
    	"owo.codes/whats-this/api/lib/db"
    
    	"github.com/pkg/errors"
    	"github.com/akamensky/base58"
    )
    
    // GenerateRandomKey generates a cryptographically secure 7 character base 58
    // string for object keys.
    func GenerateRandomKey() (string, error) {
    	data := make([]byte, 7)
    	_, err := rand.Read(data)
    	if err != nil {
    		return "", err
    	}
    	str := base58.Encode(data)
    	if len(str) >= 7 {
    		return str[0:7], nil
    	}
    	return GenerateRandomKey()
    }
    
    // GenerateAvailableKey runs GenerateRandomKey and verifies that the generated
    // key isn't already being used.
    func GenerateAvailableKey(maxAttempts int) (string, error) {
    	for n := 0; n < maxAttempts; n++ {
    		key, err := GenerateRandomKey()
    		if err != nil {
    			return "", errors.Wrap(err, "failed to generate random key")
    		}
    
    		exists, err := db.ObjectKeyExists(key)
    		if err != nil {
    			return "", errors.Wrapf(err, `failed to check if object exists with key "%s"`, key)
    		}
    		if exists {
    			continue
    		}
    		return key, nil
    	}
    	return "", errors.Errorf("failed to generate an available key within %v attempts", maxAttempts)
    }