wallet-sync-server/env/env.go
2022-08-22 12:05:53 -04:00

136 lines
4.8 KiB
Go

package env
import (
"fmt"
"os"
"strings"
"lbryio/wallet-sync-server/auth"
)
// NOTE for users: If you have weird characters in your email address, please
// remember to properly escape it as necessary when putting it in an
// environmental variable, lest you run commands you didn't mean to run.
//
// We'll replace this with a config file later.
const whitelistKey = "ACCOUNT_WHITELIST"
const verificationModeKey = "ACCOUNT_VERIFICATION_MODE"
const mailgunIsDomainEUKey = "MAILGUN_SENDING_DOMAIN_IS_EU"
const mailgunPrivateAPIKeyKey = "MAILGUN_PRIVATE_API_KEY"
// for the "from" address
const mailgunSendingDomainKey = "MAILGUN_SENDING_DOMAIN"
// for links in the emails
const mailgunServerDomainKey = "MAILGUN_SERVER_DOMAIN"
type AccountVerificationMode string
// Everyone can make an account. Only use for dev purposes.
const AccountVerificationModeAllowAll = AccountVerificationMode("AllowAll")
// Verify accounts via email. Good for big open servers.
const AccountVerificationModeEmailVerify = AccountVerificationMode("EmailVerify")
// Specific email accounts are automatically verified. Good for small
// self-hosting users.
const AccountVerificationModeWhitelist = AccountVerificationMode("Whitelist")
// For test stubs
type EnvInterface interface {
Getenv(key string) string
}
type Env struct{}
func (e *Env) Getenv(key string) string {
return os.Getenv(key)
}
func GetAccountVerificationMode(e EnvInterface) (AccountVerificationMode, error) {
return getAccountVerificationMode(e.Getenv(verificationModeKey))
}
func GetAccountWhitelist(e EnvInterface, mode AccountVerificationMode) (emails []auth.Email, err error) {
return getAccountWhitelist(e.Getenv(whitelistKey), mode)
}
func GetMailgunConfigs(e EnvInterface, mode AccountVerificationMode) (sendingDomain string, serverDomain string, isDomainEU bool, privateAPIKey string, err error) {
return getMailgunConfigs(e.Getenv(mailgunSendingDomainKey), e.Getenv(mailgunServerDomainKey), e.Getenv(mailgunIsDomainEUKey), e.Getenv(mailgunPrivateAPIKeyKey), mode)
}
// Factor out the guts of the functions so we can test them by just passing in
// the env vars
func getAccountVerificationMode(modeStr string) (AccountVerificationMode, error) {
mode := AccountVerificationMode(modeStr)
switch mode {
case "":
// Whitelist is the least dangerous mode. If you forget to set any env
// vars, it effectively disables all account creation.
return AccountVerificationModeWhitelist, nil
case AccountVerificationModeAllowAll:
case AccountVerificationModeEmailVerify:
case AccountVerificationModeWhitelist:
default:
return "", fmt.Errorf("Invalid account verification mode in %s: %s", verificationModeKey, mode)
}
return mode, nil
}
func getAccountWhitelist(whitelist string, mode AccountVerificationMode) (emails []auth.Email, err error) {
if whitelist == "" {
return []auth.Email{}, nil
}
if mode != AccountVerificationModeWhitelist {
return nil, fmt.Errorf("Do not specify %s in env if %s is not %s",
whitelistKey,
verificationModeKey,
AccountVerificationModeWhitelist,
)
}
rawEmails := strings.Split(whitelist, ",")
for _, rawEmail := range rawEmails {
// Give them a specific error here to let them know not to add spaces. It
// could be confusing otherwise to figure out what's invalid.
if strings.TrimSpace(rawEmail) != rawEmail {
return nil, fmt.Errorf("Emails in %s should be comma separated with no spaces.", whitelistKey)
}
email := auth.Email(rawEmail)
if !email.Validate() {
return nil, fmt.Errorf("Invalid email in %s: %s", whitelistKey, email)
}
emails = append(emails, email)
}
return emails, nil
}
func getMailgunConfigs(sendingDomain string, serverDomain string, isDomainEUStr string, privateAPIKey string, mode AccountVerificationMode) (string, string, bool, string, error) {
if mode != AccountVerificationModeEmailVerify && (sendingDomain != "" || serverDomain != "" || isDomainEUStr != "" || privateAPIKey != "") {
return "", "", false, "", fmt.Errorf("Do not specify %s, %s, %s or %s in env if %s is not %s",
mailgunSendingDomainKey,
mailgunServerDomainKey,
mailgunIsDomainEUKey,
mailgunPrivateAPIKeyKey,
verificationModeKey,
AccountVerificationModeEmailVerify,
)
}
if mode == AccountVerificationModeEmailVerify && (sendingDomain == "" || serverDomain == "" || privateAPIKey == "") {
return "", "", false, "", fmt.Errorf("Specify %s, %s and %s in env if %s is %s",
mailgunSendingDomainKey,
mailgunServerDomainKey,
mailgunPrivateAPIKeyKey,
verificationModeKey,
AccountVerificationModeEmailVerify,
)
}
if isDomainEUStr != "true" && isDomainEUStr != "false" && isDomainEUStr != "" {
return "", "", false, "", fmt.Errorf("%s must be 'true' or 'false'", mailgunIsDomainEUKey)
}
return sendingDomain, serverDomain, isDomainEUStr == "true", privateAPIKey, nil
}