package scrubber
import (
"crypto/md5"
"fmt"
"net/url"
"strconv"
"strings"
)
type SanitiserOption func(*sanitiserOptions)
func SanitiseWithKeyName(keyName string) SanitiserOption {
return func(so *sanitiserOptions) {
so.keyName = keyName
}
}
type sanitiserOptions struct {
keyName string
}
type Sanitisatiser func(value string, opts ...SanitiserOption) string
func SanitiseRedact(value string, opts ...SanitiserOption) string {
options := mergeSanitiserOpts(opts)
if options.keyName != "" {
return "[redacted:" + options.keyName + "]"
}
return "[redacted]"
}
func SanitiseHash(value string, opts ...SanitiserOption) string {
options := mergeSanitiserOpts(opts)
hash := md5.New()
_, _ = hash.Write([]byte(value))
res := fmt.Sprintf("[redacted:md5:%x", hash.Sum(nil))
if options.keyName != "" {
res += ":" + options.keyName
}
res += "]"
return res
}
func SanitiseHashURLPathSegments(value string, opts ...SanitiserOption) string {
options := mergeSanitiserOpts(opts)
u, err := url.Parse(value)
if err != nil {
return SanitiseHash(value, opts...)
}
path := u.Path
query := u.RawQuery
u.Path = ""
u.RawQuery = ""
u.Fragment = ""
pathSegmentAllowList := []string{
"-",
"blob",
"blobs",
"commit",
"commits",
"issue",
"issues",
"merge_request",
"merge_requests",
"pull-request",
"pull-requests",
"pull",
"release",
"releases",
"src",
"tag",
"tags",
"tree",
"users",
"projects",
"scm",
"repos",
"browse",
"branches",
}
var pathSegements []string
SEGMENTS:
for _, p := range strings.Split(path, "/") {
if len(p) <= 0 {
continue SEGMENTS
}
if _, err := strconv.Atoi(p); err == nil {
pathSegements = append(pathSegements, p)
continue SEGMENTS
}
p = strings.TrimPrefix(p, "~")
p = strings.TrimSuffix(p, ".git")
for _, a := range pathSegmentAllowList {
if p == a {
pathSegements = append(pathSegements, p)
continue SEGMENTS
}
}
pathSegements = append(pathSegements, SanitiseHash(p))
}
res := fmt.Sprintf("%s/%s", SanitiseHash(u.String()), strings.Join(pathSegements, "/"))
if len(query) > 0 {
res += fmt.Sprintf("?%s", SanitiseHash(query))
}
if options.keyName != "" {
res += " [" + options.keyName + "]"
}
return res
}
func mergeSanitiserOpts(opts []SanitiserOption) sanitiserOptions {
var res sanitiserOptions
for _, opt := range opts {
opt(&res)
}
return res
}