fix(09): WR-13 read admin passwords from a prompt or stdin and deprecate the --password flag
This commit is contained in:
@@ -226,3 +226,57 @@ func TestAdminCreateRejectsCrossFieldCollision(t *testing.T) {
|
||||
t.Fatalf("admins after refused creates = %d, %v; want 1", n, err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestAdminPasswordWithoutFlag pins WR-13: the password can come from stdin
|
||||
// (the non-terminal path of the prompt) instead of the command line, the
|
||||
// --password flag still works but warns that it is deprecated, and no password
|
||||
// at all is refused.
|
||||
func TestAdminPasswordWithoutFlag(t *testing.T) {
|
||||
gdb := adminGorm(t)
|
||||
app := commandApp(t, gdb)
|
||||
create := commandByName(t, cabana.RuntimeCommands(app), "admin:create")
|
||||
reset := commandByName(t, cabana.RuntimeCommands(app), "admin:reset-password")
|
||||
const piped = "password-piped-on-stdin"
|
||||
|
||||
var buf bytes.Buffer
|
||||
out := bonfire.NewOutput(strings.NewReader(piped+"\n"), &buf, &buf)
|
||||
if err := create.Run(context.Background(), flagInput{flags: map[string]string{"email": "stdin-pw@example.test"}}, out); err != nil {
|
||||
t.Fatalf("create with the password on stdin: %v", err)
|
||||
}
|
||||
var user cabana.BackendUser
|
||||
if err := gdb.Where("login = ?", "stdin-pw@example.test").First(&user).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bouncer.CheckPassword(user.Password, piped) {
|
||||
t.Fatal("password read from stdin was not stored")
|
||||
}
|
||||
if strings.Contains(buf.String(), piped) || strings.Contains(buf.String(), "deprecated") {
|
||||
t.Fatalf("stdin path leaked the password or warned: %s", buf.String())
|
||||
}
|
||||
|
||||
const next = "replacement-piped-on-stdin"
|
||||
buf.Reset()
|
||||
out = bonfire.NewOutput(strings.NewReader(next+"\n"), &buf, &buf)
|
||||
if err := reset.Run(context.Background(), flagInput{args: []string{"stdin-pw@example.test"}}, out); err != nil {
|
||||
t.Fatalf("reset with the password on stdin: %v", err)
|
||||
}
|
||||
if err := gdb.Where("login = ?", "stdin-pw@example.test").First(&user).Error; err != nil || !bouncer.CheckPassword(user.Password, next) {
|
||||
t.Fatalf("reset did not store the stdin password: %v", err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
out = bonfire.NewOutput(strings.NewReader(""), &buf, &buf)
|
||||
err := reset.Run(context.Background(), flagInput{args: []string{"stdin-pw@example.test"}}, out)
|
||||
if err == nil || !strings.Contains(err.Error(), "password is required") {
|
||||
t.Fatalf("reset with no password err = %v", err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
out = bonfire.NewOutput(strings.NewReader(""), &buf, &buf)
|
||||
if err := reset.Run(context.Background(), flagInput{args: []string{"stdin-pw@example.test"}, flags: map[string]string{"password": "flag-password-value"}}, out); err != nil {
|
||||
t.Fatalf("reset with the deprecated flag: %v", err)
|
||||
}
|
||||
if !strings.Contains(buf.String(), "deprecated") || strings.Contains(buf.String(), "flag-password-value") {
|
||||
t.Fatalf("deprecated flag output = %s", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user