247 lines
7.1 KiB
Go
247 lines
7.1 KiB
Go
package conf
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
defer os.Clearenv()
|
|
os.Exit(m.Run())
|
|
}
|
|
|
|
func TestGlobal(t *testing.T) {
|
|
os.Setenv("GOTRUE_SITE_URL", "http://localhost:8080")
|
|
os.Setenv("GOTRUE_DB_DRIVER", "postgres")
|
|
os.Setenv("GOTRUE_DB_DATABASE_URL", "fake")
|
|
os.Setenv("GOTRUE_OPERATOR_TOKEN", "token")
|
|
os.Setenv("GOTRUE_API_REQUEST_ID_HEADER", "X-Request-ID")
|
|
os.Setenv("GOTRUE_JWT_SECRET", "secret")
|
|
os.Setenv("API_EXTERNAL_URL", "http://localhost:9999")
|
|
os.Setenv("GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_URI", "pg-functions://postgres/auth/count_failed_attempts")
|
|
os.Setenv("GOTRUE_HOOK_SEND_SMS_SECRETS", "v1,whsec_aWxpa2VzdXBhYmFzZXZlcnltdWNoYW5kaWhvcGV5b3Vkb3Rvbw==")
|
|
os.Setenv("GOTRUE_SMTP_HEADERS", `{"X-PM-Metadata-project-ref":["project_ref"],"X-SES-Message-Tags":["ses:feedback-id-a=project_ref,ses:feedback-id-b=$messageType"]}`)
|
|
os.Setenv("GOTRUE_MAILER_EMAIL_VALIDATION_SERVICE_HEADERS", `{"apikey":["test"]}`)
|
|
os.Setenv("GOTRUE_SMTP_LOGGING_ENABLED", "true")
|
|
gc, err := LoadGlobal("")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, true, gc.SMTP.LoggingEnabled)
|
|
assert.Equal(t, "project_ref", gc.SMTP.NormalizedHeaders()["X-PM-Metadata-project-ref"][0])
|
|
require.NotNil(t, gc)
|
|
assert.Equal(t, "X-Request-ID", gc.API.RequestIDHeader)
|
|
assert.Equal(t, "pg-functions://postgres/auth/count_failed_attempts", gc.Hook.MFAVerificationAttempt.URI)
|
|
|
|
{
|
|
hdrs := gc.Mailer.GetEmailValidationServiceHeaders()
|
|
assert.Equal(t, 1, len(hdrs["apikey"]))
|
|
assert.Equal(t, "test", hdrs["apikey"][0])
|
|
}
|
|
|
|
}
|
|
|
|
func TestRateLimits(t *testing.T) {
|
|
{
|
|
os.Setenv("GOTRUE_RATE_LIMIT_EMAIL_SENT", "0/1h")
|
|
|
|
gc, err := LoadGlobal("")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, float64(0), gc.RateLimitEmailSent.Events)
|
|
assert.Equal(t, time.Hour, gc.RateLimitEmailSent.OverTime)
|
|
}
|
|
|
|
{
|
|
os.Setenv("GOTRUE_RATE_LIMIT_EMAIL_SENT", "10/1h")
|
|
|
|
gc, err := LoadGlobal("")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, float64(10), gc.RateLimitEmailSent.Events)
|
|
assert.Equal(t, time.Hour, gc.RateLimitEmailSent.OverTime)
|
|
}
|
|
}
|
|
|
|
func TestPasswordRequiredCharactersDecode(t *testing.T) {
|
|
examples := []struct {
|
|
Value string
|
|
Result []string
|
|
}{
|
|
{
|
|
Value: "a:b:c",
|
|
Result: []string{
|
|
"a",
|
|
"b",
|
|
"c",
|
|
},
|
|
},
|
|
{
|
|
Value: "a\\:b:c",
|
|
Result: []string{
|
|
"a:b",
|
|
"c",
|
|
},
|
|
},
|
|
{
|
|
Value: "a:b\\:c",
|
|
Result: []string{
|
|
"a",
|
|
"b:c",
|
|
},
|
|
},
|
|
{
|
|
Value: "\\:a:b:c",
|
|
Result: []string{
|
|
":a",
|
|
"b",
|
|
"c",
|
|
},
|
|
},
|
|
{
|
|
Value: "a:b:c\\:",
|
|
Result: []string{
|
|
"a",
|
|
"b",
|
|
"c:",
|
|
},
|
|
},
|
|
{
|
|
Value: "::\\::",
|
|
Result: []string{
|
|
":",
|
|
},
|
|
},
|
|
{
|
|
Value: "",
|
|
Result: nil,
|
|
},
|
|
{
|
|
Value: " ",
|
|
Result: []string{
|
|
" ",
|
|
},
|
|
},
|
|
}
|
|
|
|
for i, example := range examples {
|
|
var into PasswordRequiredCharacters
|
|
require.NoError(t, into.Decode(example.Value), "Example %d failed with error", i)
|
|
|
|
require.Equal(t, []string(into), example.Result, "Example %d got unexpected result", i)
|
|
}
|
|
}
|
|
|
|
func TestHTTPHookSecretsDecode(t *testing.T) {
|
|
examples := []struct {
|
|
Value string
|
|
Result []string
|
|
}{
|
|
{
|
|
Value: "v1,whsec_secret1|v1a,whpk_secrets:whsk_secret2|v1,whsec_secret3",
|
|
Result: []string{"v1,whsec_secret1", "v1a,whpk_secrets:whsk_secret2", "v1,whsec_secret3"},
|
|
},
|
|
{
|
|
Value: "v1,whsec_singlesecret",
|
|
Result: []string{"v1,whsec_singlesecret"},
|
|
},
|
|
{
|
|
Value: " ",
|
|
Result: []string{" "},
|
|
},
|
|
{
|
|
Value: "",
|
|
Result: nil,
|
|
},
|
|
{
|
|
Value: "|a|b|c",
|
|
Result: []string{
|
|
"a",
|
|
"b",
|
|
"c",
|
|
},
|
|
},
|
|
{
|
|
Value: "||||",
|
|
Result: nil,
|
|
},
|
|
{
|
|
Value: "::",
|
|
Result: []string{"::"},
|
|
},
|
|
{
|
|
Value: "secret1::secret3",
|
|
Result: []string{"secret1::secret3"},
|
|
},
|
|
}
|
|
|
|
for i, example := range examples {
|
|
var into HTTPHookSecrets
|
|
|
|
require.NoError(t, into.Decode(example.Value), "Example %d failed with error", i)
|
|
require.Equal(t, []string(into), example.Result, "Example %d got unexpected result", i)
|
|
}
|
|
}
|
|
|
|
func TestValidateExtensibilityPointURI(t *testing.T) {
|
|
cases := []struct {
|
|
desc string
|
|
uri string
|
|
expectError bool
|
|
}{
|
|
// Positive test cases
|
|
{desc: "Valid HTTPS URI", uri: "https://asdfgggqqwwerty.website.co/functions/v1/custom-sms-sender", expectError: false},
|
|
{desc: "Valid HTTPS URI", uri: "HTTPS://www.asdfgggqqwwerty.website.co/functions/v1/custom-sms-sender", expectError: false},
|
|
{desc: "Valid Postgres URI", uri: "pg-functions://postgres/auth/verification_hook_reject", expectError: false},
|
|
{desc: "Another Valid URI", uri: "pg-functions://postgres/user_management/add_user", expectError: false},
|
|
{desc: "Another Valid URI", uri: "pg-functions://postgres/MySpeCial/FUNCTION_THAT_YELLS_AT_YOU", expectError: false},
|
|
{desc: "Valid HTTP URI", uri: "http://localhost/functions/v1/custom-sms-sender", expectError: false},
|
|
|
|
// Negative test cases
|
|
{desc: "Invalid HTTP URI", uri: "http://asdfgggg.website.co/functions/v1/custom-sms-sender", expectError: true},
|
|
{desc: "Invalid HTTPS URI (HTTP)", uri: "http://asdfgggqqwwerty.supabase.co/functions/v1/custom-sms-sender", expectError: true},
|
|
{desc: "Invalid Schema Name", uri: "pg-functions://postgres/123auth/verification_hook_reject", expectError: true},
|
|
{desc: "Invalid Function Name", uri: "pg-functions://postgres/auth/123verification_hook_reject", expectError: true},
|
|
{desc: "Insufficient Path Parts", uri: "pg-functions://postgres/auth", expectError: true},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
ep := ExtensibilityPointConfiguration{URI: tc.uri}
|
|
err := ep.ValidateExtensibilityPoint()
|
|
if tc.expectError {
|
|
require.Error(t, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateExtensibilityPointSecrets(t *testing.T) {
|
|
validHTTPSURI := "https://asdfgggqqwwerty.website.co/functions/v1/custom-sms-sender"
|
|
cases := []struct {
|
|
desc string
|
|
secret []string
|
|
expectError bool
|
|
}{
|
|
// Positive test cases
|
|
{desc: "Valid Symmetric Secret", secret: []string{"v1,whsec_NDYzODhlNTY0ZGI1OWZjYTU2NjMwN2FhYzM3YzBkMWQ0NzVjNWRkNTJmZDU0MGNhYTAzMjVjNjQzMzE3Mjk2Zg====="}, expectError: false},
|
|
{desc: "Valid Asymmetric Secret", secret: []string{"v1a,whpk_NDYzODhlNTY0ZGI1OWZjYTU2NjMwN2FhYzM3YzBkMWQ0NzVjNWRkNTJmZDU0MGNhYTAzMjVjNjQzMzE3Mjk2Zg==:whsk_abc889a6b1160015025064f108a48d6aba1c7c95fa8e304b4d225e8ae0121511"}, expectError: false},
|
|
{desc: "Valid Mix of Symmetric and asymmetric Secret", secret: []string{"v1,whsec_2b49264c90fd15db3bb0e05f4e1547b9c183eb06d585be8a", "v1a,whpk_46388e564db59fca566307aac37c0d1d475c5dd52fd540caa0325c643317296f:whsk_YWJjODg5YTZiMTE2MDAxNTAyNTA2NGYxMDhhNDhkNmFiYTFjN2M5NWZhOGUzMDRiNGQyMjVlOGFlMDEyMTUxMSI="}, expectError: false},
|
|
|
|
// Negative test cases
|
|
{desc: "Invalid Asymmetric Secret", secret: []string{"v1a,john:jill", "jill"}, expectError: true},
|
|
{desc: "Invalid Symmetric Secret", secret: []string{"tommy"}, expectError: true},
|
|
}
|
|
for _, tc := range cases {
|
|
ep := ExtensibilityPointConfiguration{URI: validHTTPSURI, HTTPHookSecrets: tc.secret}
|
|
err := ep.ValidateExtensibilityPoint()
|
|
if tc.expectError {
|
|
require.Error(t, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
}
|
|
|
|
}
|