90 lines
3.7 KiB
Go
90 lines
3.7 KiB
Go
package config
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
const validTencentSMSJSON = `{"enabled":true,"secret_id":"fixture-id","secret_key":"fixture-private-key","sdk_app_id":"1400006666","sign_name":"安芯伴","templates":{"login":"101","register":"102","change_password":"103","change_phone":"104"}}`
|
||
|
|
|
||
|
|
func smsConfigFixture(t *testing.T, content string) string {
|
||
|
|
t.Helper()
|
||
|
|
path := filepath.Join(t.TempDir(), "tencent-sms.json")
|
||
|
|
if err := os.WriteFile(path, []byte(content), 0600); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
return path
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestTencentSMSFileLoadsAllTemplatesAndOverridesLegacyConfiguration(t *testing.T) {
|
||
|
|
c := OnboardingConfig{MasterKey: strings.Repeat("ab", 32), EntryURL: "https://platform.example/onboarding/entry", SMSProvider: "gateway", TencentSMSTemplateID: "old"}
|
||
|
|
t.Setenv("TENCENT_SMS_CONFIG_FILE", smsConfigFixture(t, "\xef\xbb\xbf"+validTencentSMSJSON))
|
||
|
|
if err := c.loadTencentSMSFile("api"); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if err := c.validate(EnvironmentProd); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if !c.SMSLoginEnabled || c.SMSProvider != "tencent" || c.TencentSMSSecretKey != "fixture-private-key" || c.TencentSMSTemplateID != "" || c.TencentSMSTemplates["change_phone"] != "104" {
|
||
|
|
t.Fatal("single-file settings did not take precedence")
|
||
|
|
}
|
||
|
|
if err := c.readTencentSMSFile(smsConfigFixture(t, strings.Replace(validTencentSMSJSON, `"enabled":true`, `"enabled":false`, 1)), true); err != nil || c.SMSLoginEnabled {
|
||
|
|
t.Fatal("file could not disable SMS")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestTencentSMSFileRejectsBrokenConfigurationWithoutLeakingSecrets(t *testing.T) {
|
||
|
|
for _, raw := range []string{
|
||
|
|
validTencentSMSJSON + `{}`,
|
||
|
|
strings.Replace(validTencentSMSJSON, `"enabled":true,`, "", 1),
|
||
|
|
strings.Replace(validTencentSMSJSON, `"secret_key"`, `"fixture-private-key"`, 1),
|
||
|
|
strings.Replace(validTencentSMSJSON, `"change_phone"`, `"fixture-private-key"`, 1),
|
||
|
|
strings.Replace(validTencentSMSJSON, `"104"`, `"not-an-id"`, 1),
|
||
|
|
strings.Replace(validTencentSMSJSON, `,"change_phone":"104"`, "", 1),
|
||
|
|
} {
|
||
|
|
c := OnboardingConfig{MasterKey: strings.Repeat("ab", 32), EntryURL: "https://platform.example/onboarding/entry"}
|
||
|
|
err := c.readTencentSMSFile(smsConfigFixture(t, raw), true)
|
||
|
|
if err == nil {
|
||
|
|
err = c.validate(EnvironmentProd)
|
||
|
|
}
|
||
|
|
if err == nil || strings.Contains(err.Error(), "fixture-private-key") {
|
||
|
|
t.Fatal("invalid configuration accepted or secret exposed in error")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestTencentSMSFileMissingAndNonSMSServiceBehavior(t *testing.T) {
|
||
|
|
path := filepath.Join(t.TempDir(), "missing.json")
|
||
|
|
c := OnboardingConfig{}
|
||
|
|
if err := c.readTencentSMSFile(path, false); err != nil {
|
||
|
|
t.Fatal("absent optional file broke existing deployments", err)
|
||
|
|
}
|
||
|
|
t.Setenv("TENCENT_SMS_CONFIG_FILE", path)
|
||
|
|
if err := c.loadTencentSMSFile("api"); err == nil {
|
||
|
|
t.Fatal("explicit missing configuration silently ignored")
|
||
|
|
}
|
||
|
|
if err := c.loadTencentSMSFile("callbacks"); err != nil || c.SMSLoginEnabled {
|
||
|
|
t.Fatal("SMS file affected callbacks service")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestTencentSMSFileTemplateParameterOrder(t *testing.T) {
|
||
|
|
raw := strings.TrimSuffix(validTencentSMSJSON, "}") + `,"template_params":{"register":["code","expires_minutes"]}}`
|
||
|
|
c := OnboardingConfig{MasterKey: strings.Repeat("ab", 32), EntryURL: "https://platform.example/onboarding/entry"}
|
||
|
|
if err := c.readTencentSMSFile(smsConfigFixture(t, raw), true); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if err := c.validate(EnvironmentProd); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if len(c.TencentSMSTemplateParams["register"]) != 2 || c.TencentSMSTemplateParams["register"][1] != "expires_minutes" {
|
||
|
|
t.Fatal("parameter order was not preserved")
|
||
|
|
}
|
||
|
|
c.TencentSMSTemplateParams["register"] = []string{"code", "unknown"}
|
||
|
|
if err := c.validate(EnvironmentProd); err == nil {
|
||
|
|
t.Fatal("invalid template parameter accepted")
|
||
|
|
}
|
||
|
|
}
|