An atproto PDS written in Go
1package helpers 2 3import ( 4 crand "crypto/rand" 5 "encoding/hex" 6 "errors" 7 "math/rand" 8 "net/url" 9 10 "github.com/labstack/echo/v4" 11 "github.com/lestrrat-go/jwx/v2/jwk" 12) 13 14// This will confirm to the regex in the application if 5 chars are used for each side of the - 15// /^[A-Z2-7]{5}-[A-Z2-7]{5}$/ 16var letters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567") 17 18func InputError(e echo.Context, custom *string) error { 19 msg := "InvalidRequest" 20 if custom != nil { 21 msg = *custom 22 } 23 return genericError(e, 400, msg) 24} 25 26func ServerError(e echo.Context, suffix *string) error { 27 msg := "Internal server error" 28 if suffix != nil { 29 msg += ". " + *suffix 30 } 31 return genericError(e, 400, msg) 32} 33 34func genericError(e echo.Context, code int, msg string) error { 35 return e.JSON(code, map[string]string{ 36 "error": msg, 37 }) 38} 39 40func RandomVarchar(length int) string { 41 b := make([]rune, length) 42 for i := range b { 43 b[i] = letters[rand.Intn(len(letters))] 44 } 45 return string(b) 46} 47 48func RandomHex(n int) (string, error) { 49 bytes := make([]byte, n) 50 if _, err := crand.Read(bytes); err != nil { 51 return "", err 52 } 53 return hex.EncodeToString(bytes), nil 54} 55 56func RandomBytes(n int) []byte { 57 bs := make([]byte, n) 58 crand.Read(bs) 59 return bs 60} 61 62func ParseJWKFromBytes(b []byte) (jwk.Key, error) { 63 return jwk.ParseKey(b) 64} 65 66func OauthParseHtu(htu string) (string, error) { 67 u, err := url.Parse(htu) 68 if err != nil { 69 return "", errors.New("`htu` is not a valid URL") 70 } 71 72 if u.User != nil { 73 _, containsPass := u.User.Password() 74 if u.User.Username() != "" || containsPass { 75 return "", errors.New("`htu` must not contain credentials") 76 } 77 } 78 79 if u.Scheme != "http" && u.Scheme != "https" { 80 return "", errors.New("`htu` must be http or https") 81 } 82 83 return OauthNormalizeHtu(u), nil 84} 85 86func OauthNormalizeHtu(u *url.URL) string { 87 return u.Scheme + "://" + u.Host + u.RawPath 88}