Files
OpenFlare/backend/cmd/reset_passwd_test.go
T

228 lines
5.5 KiB
Go

// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
"Wavelet/pkg/testhelper"
"bytes"
"io"
"os"
"testing"
"time"
userdomain "Wavelet/plugins/domain/user"
)
func TestResetPasswdCmd_WithUserAndPassword(t *testing.T) {
dbConn, _, cleanup := testhelper.SetupTestEnvironment(t)
defer cleanup()
// Seed test user
user := userdomain.User{
ID: 1001,
Username: "testuser1",
Nickname: "Test User 1",
Email: "test1@example.com",
IsActive: true,
LastLoginAt: time.Now(),
}
_ = user.SetEncryptedPassword("oldpassword")
if err := dbConn.Create(&user).Error; err != nil {
t.Fatalf("failed to create test user: %v", err)
}
// Create access token to test invalidation/deletion
token := userdomain.AccessToken{
ID: 1,
UserID: user.ID,
Name: "testtoken",
TokenHash: "somehash",
MaskedToken: "some...",
}
if err := dbConn.Create(&token).Error; err != nil {
t.Fatalf("failed to create access token: %v", err)
}
// Override PreRun to bypass goose migrations in unit tests
oldPreRun := resetPasswdCmd.PreRun
resetPasswdCmd.PreRun = nil
defer func() { resetPasswdCmd.PreRun = oldPreRun }()
// Execute command with args
rootCmd.SetArgs([]string{"reset-passwd", "--user", "testuser1", "--password", "newpassword123"})
// Capture output
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
err := rootCmd.Execute()
w.Close()
os.Stdout = oldStdout
if err != nil {
t.Fatalf("command execute failed: %v", err)
}
var buf bytes.Buffer
_, _ = io.Copy(&buf, r)
output := buf.String()
if !bytes.Contains([]byte(output), []byte("成功重置密码!")) {
t.Errorf("expected output to contain success message, got: %s", output)
}
// Verify password in DB
var dbUser userdomain.User
if err := dbConn.Where("id = ?", user.ID).First(&dbUser).Error; err != nil {
t.Fatalf("failed to query user from DB: %v", err)
}
if !dbUser.CheckPassword("newpassword123") {
t.Errorf("password was not updated correctly in DB")
}
// Verify token deleted
var count int64
dbConn.Model(&userdomain.AccessToken{}).Where("user_id = ?", user.ID).Count(&count)
if count != 0 {
t.Errorf("expected access tokens to be deleted, got %d", count)
}
}
func TestResetPasswdCmd_WithUserAndRandomPassword(t *testing.T) {
dbConn, _, cleanup := testhelper.SetupTestEnvironment(t)
defer cleanup()
// Seed test user
user := userdomain.User{
ID: 1002,
Username: "testuser2",
Nickname: "Test User 2",
Email: "test2@example.com",
IsActive: true,
LastLoginAt: time.Now(),
}
_ = user.SetEncryptedPassword("oldpassword")
if err := dbConn.Create(&user).Error; err != nil {
t.Fatalf("failed to create test user: %v", err)
}
// Override PreRun
oldPreRun := resetPasswdCmd.PreRun
resetPasswdCmd.PreRun = nil
defer func() { resetPasswdCmd.PreRun = oldPreRun }()
// Reset flags
usernameFlag = ""
passwordFlag = ""
// Execute command with args (no --password)
rootCmd.SetArgs([]string{"reset-passwd", "--user", "testuser2"})
// Capture output
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
err := rootCmd.Execute()
w.Close()
os.Stdout = oldStdout
if err != nil {
t.Fatalf("command execute failed: %v", err)
}
var buf bytes.Buffer
_, _ = io.Copy(&buf, r)
output := buf.String()
if !bytes.Contains([]byte(output), []byte("成功重置密码!")) {
t.Errorf("expected output to contain success message, got: %s", output)
}
// Verify password in DB (should be updated and not equal to old one)
var dbUser userdomain.User
if err := dbConn.Where("id = ?", user.ID).First(&dbUser).Error; err != nil {
t.Fatalf("failed to query user from DB: %v", err)
}
if dbUser.CheckPassword("oldpassword") {
t.Errorf("expected password to change, but it matches the old one")
}
}
func TestResetPasswdCmd_InteractiveMode(t *testing.T) {
dbConn, _, cleanup := testhelper.SetupTestEnvironment(t)
defer cleanup()
// Seed test user
user := userdomain.User{
ID: 1003,
Username: "testuser3",
Nickname: "Test User 3",
Email: "test3@example.com",
IsActive: true,
LastLoginAt: time.Now(),
}
_ = user.SetEncryptedPassword("oldpassword")
if err := dbConn.Create(&user).Error; err != nil {
t.Fatalf("failed to create test user: %v", err)
}
// Override PreRun
oldPreRun := resetPasswdCmd.PreRun
resetPasswdCmd.PreRun = nil
defer func() { resetPasswdCmd.PreRun = oldPreRun }()
// Mock stdin
inR, inW, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
defer inR.Close()
defer inW.Close()
oldStdin := os.Stdin
os.Stdin = inR
defer func() { os.Stdin = oldStdin }()
// Write username to stdin
_, _ = inW.WriteString("testuser3\n")
inW.Close()
// Reset flags
usernameFlag = ""
passwordFlag = ""
rootCmd.SetArgs([]string{"reset-passwd"})
// Capture output
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
err = rootCmd.Execute()
w.Close()
os.Stdout = oldStdout
if err != nil {
t.Fatalf("command execute failed: %v", err)
}
var buf bytes.Buffer
_, _ = io.Copy(&buf, r)
output := buf.String()
if !bytes.Contains([]byte(output), []byte("成功重置密码!")) {
t.Errorf("expected output to contain success message, got: %s", output)
}
// Verify user password changed in DB
var dbUser userdomain.User
if err := dbConn.Where("id = ?", user.ID).First(&dbUser).Error; err != nil {
t.Fatalf("failed to query user from DB: %v", err)
}
if dbUser.CheckPassword("oldpassword") {
t.Errorf("expected password to change, but it matches the old one")
}
}