package database_test import ( "bytes" "context" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "sneak.berlin/go/webhooker/internal/database" ) // passwordField is the banner line carrying the plaintext. const passwordField = "password: " // bannerPassword returns the password the banner printed. func bannerPassword(t *testing.T, out string) string { t.Helper() for line := range strings.SplitSeq(out, "\n") { _, value, found := strings.Cut(line, passwordField) if found { return strings.TrimSpace(value) } } t.Fatalf("no %q line in the banner:\n%s", passwordField, out) return "" } // TestFirstBoot_PrintsTheAdminPasswordAsABanner is the bootstrap half // of https://git.eeqj.de/sneak/webhooker/issues/208. // // The password is shown exactly once, and it used to be shown as one // slog record among the roughly 45 fx PROVIDE/RUN/HOOK lines a boot // writes — which is how deployments lost it and, with no reset path, // locked themselves out. It must be emitted as a block an operator can // find by eye, it must carry the plaintext that actually opens the // account, and it must name the command that recovers it. func TestFirstBoot_PrintsTheAdminPasswordAsABanner(t *testing.T) { t.Parallel() db, lc := setupTestDB(t) var out bytes.Buffer db.ExportSetBannerOut(&out) ctx := context.Background() require.NoError(t, lc.Start(ctx)) defer func() { require.NoError(t, lc.Stop(ctx)) }() printed := out.String() require.Contains( t, printed, strings.Repeat("=", 20), "the banner must be ruled off, not read as one more log line", ) require.Contains(t, printed, "username: admin") assert.Contains( t, printed, "resetpw", "the banner must name the command that recovers the account", ) password := bannerPassword(t, printed) require.NotEmpty(t, password) // The printed plaintext must be the one that opens the account: // a banner showing a different string would be worse than none. var user database.User require.NoError( t, db.DB().Where("username = ?", "admin").First(&user).Error, ) ok, err := database.VerifyPassword(password, user.Password) require.NoError(t, err) assert.True( t, ok, "the printed password must open the seeded account", ) }