utils.go

 1package utils
 2
 3import (
 4	"errors"
 5	"fmt"
 6	"net/mail"
 7	"path"
 8	"strings"
 9	"unicode"
10)
11
12var (
13
14	// ErrInvalidEmail indicates that an email address is invalid.
15	ErrInvalidEmail = errors.New("invalid email address")
16)
17
18// SanitizeRepo returns a sanitized version of the given repository name.
19func SanitizeRepo(repo string) string {
20	repo = strings.TrimPrefix(repo, "/")
21	// We're using path instead of filepath here because this is not OS dependent
22	// looking at you Windows
23	repo = path.Clean(repo)
24	repo = strings.TrimSuffix(repo, ".git")
25	return repo
26}
27
28// ValidateHandle returns an error if any of the given usernames are invalid.
29func ValidateHandle(handle string) error {
30	if handle == "" {
31		return fmt.Errorf("cannot be empty")
32	}
33
34	if !unicode.IsLetter(rune(handle[0])) {
35		return fmt.Errorf("must start with a letter")
36	}
37
38	for _, r := range handle {
39		if !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != '-' {
40			return fmt.Errorf("can only contain letters, numbers, and hyphens")
41		}
42	}
43
44	return nil
45}
46
47// ValidateRepo returns an error if the given repository name is invalid.
48func ValidateRepo(repo string) error {
49	if repo == "" {
50		return fmt.Errorf("repo cannot be empty")
51	}
52
53	for _, r := range repo {
54		if !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != '-' && r != '_' && r != '.' && r != '/' {
55			return fmt.Errorf("repo can only contain letters, numbers, hyphens, underscores, periods, and slashes")
56		}
57	}
58
59	return nil
60}
61
62// ValidateEmail returns an error if the given email address is invalid.
63func ValidateEmail(email string) error {
64	if strings.ContainsAny(email, " <>") {
65		return ErrInvalidEmail
66	}
67
68	_, err := mail.ParseAddress(email)
69	if err != nil {
70		return fmt.Errorf("%w: %s", ErrInvalidEmail, err)
71	}
72
73	return nil
74}