mirror of
https://github.com/GMWalletApp/epusdt.git
synced 2026-07-07 02:06:16 +00:00
268 lines
7.5 KiB
Go
268 lines
7.5 KiB
Go
package data
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/GMWalletApp/epusdt/internal/testutil"
|
|
"github.com/GMWalletApp/epusdt/model/dao"
|
|
"github.com/GMWalletApp/epusdt/model/mdb"
|
|
)
|
|
|
|
func TestUpsertSettingRowRestoresSoftDeletedSetting(t *testing.T) {
|
|
cleanup := testutil.SetupTestDatabases(t)
|
|
defer cleanup()
|
|
|
|
row := mdb.Setting{
|
|
Group: mdb.SettingGroupSystem,
|
|
Key: mdb.SettingKeyInitAdminPasswordChanged,
|
|
Value: "false",
|
|
Type: mdb.SettingTypeBool,
|
|
}
|
|
if err := upsertSettingRow(dao.Mdb, row); err != nil {
|
|
t.Fatalf("seed setting: %v", err)
|
|
}
|
|
if err := dao.Mdb.Where("`key` = ?", row.Key).Delete(&mdb.Setting{}).Error; err != nil {
|
|
t.Fatalf("delete setting: %v", err)
|
|
}
|
|
|
|
row.Value = "true"
|
|
if err := upsertSettingRow(dao.Mdb, row); err != nil {
|
|
t.Fatalf("restore setting: %v", err)
|
|
}
|
|
|
|
var restored mdb.Setting
|
|
if err := dao.Mdb.Where("`key` = ?", row.Key).Take(&restored).Error; err != nil {
|
|
t.Fatalf("load restored setting: %v", err)
|
|
}
|
|
if restored.Value != "true" {
|
|
t.Fatalf("restored value = %q, want true", restored.Value)
|
|
}
|
|
if restored.DeletedAt.Valid {
|
|
t.Fatalf("restored setting still has deleted_at=%v", restored.DeletedAt)
|
|
}
|
|
}
|
|
|
|
func TestGetInitialAdminPasswordKeepsPlaintext(t *testing.T) {
|
|
cleanup := testutil.SetupTestDatabases(t)
|
|
defer cleanup()
|
|
|
|
const password = "init-pass-plain"
|
|
if err := initAdminPasswordState(password); err != nil {
|
|
t.Fatalf("seed initial password state: %v", err)
|
|
}
|
|
|
|
got, err := GetInitialAdminPassword()
|
|
if err != nil {
|
|
t.Fatalf("get initial password: %v", err)
|
|
}
|
|
if got != password {
|
|
t.Fatalf("password = %q, want %q", got, password)
|
|
}
|
|
|
|
var count int64
|
|
if err := dao.Mdb.Unscoped().
|
|
Model(&mdb.Setting{}).
|
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
|
Count(&count).Error; err != nil {
|
|
t.Fatalf("count plaintext setting: %v", err)
|
|
}
|
|
if count != 1 {
|
|
t.Fatalf("plaintext setting rows after read = %d, want 1", count)
|
|
}
|
|
if GetSettingBool(mdb.SettingKeyInitAdminPasswordFetched, false) {
|
|
t.Fatal("expected fetched flag to stay false before password change")
|
|
}
|
|
}
|
|
|
|
func TestUpdateAdminUserPasswordHardDeletesInitialPasswordPlaintext(t *testing.T) {
|
|
cleanup := testutil.SetupTestDatabases(t)
|
|
defer cleanup()
|
|
|
|
const (
|
|
oldPassword = "init-pass-plain"
|
|
newPassword = "new-password-123"
|
|
)
|
|
if err := initAdminPasswordState(oldPassword); err != nil {
|
|
t.Fatalf("seed initial password state: %v", err)
|
|
}
|
|
|
|
hash, err := HashPassword(oldPassword)
|
|
if err != nil {
|
|
t.Fatalf("hash password: %v", err)
|
|
}
|
|
user := &mdb.AdminUser{
|
|
Username: defaultAdminUsername,
|
|
PasswordHash: hash,
|
|
Status: mdb.AdminUserStatusEnable,
|
|
}
|
|
if err := dao.Mdb.Create(user).Error; err != nil {
|
|
t.Fatalf("seed admin user: %v", err)
|
|
}
|
|
|
|
if err := UpdateAdminUserPassword(uint64(user.ID), newPassword); err != nil {
|
|
t.Fatalf("update admin password: %v", err)
|
|
}
|
|
|
|
var count int64
|
|
if err := dao.Mdb.Unscoped().
|
|
Model(&mdb.Setting{}).
|
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
|
Count(&count).Error; err != nil {
|
|
t.Fatalf("count plaintext setting: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Fatalf("plaintext setting rows after password change = %d, want 0", count)
|
|
}
|
|
if !GetSettingBool(mdb.SettingKeyInitAdminPasswordFetched, false) {
|
|
t.Fatal("expected fetched flag to be true after password change")
|
|
}
|
|
}
|
|
|
|
func TestUpdateAdminUserPasswordHardDeletesPlaintextWithoutHashMetadata(t *testing.T) {
|
|
cleanup := testutil.SetupTestDatabases(t)
|
|
defer cleanup()
|
|
|
|
const (
|
|
oldPassword = "legacy-init-pass"
|
|
newPassword = "new-password-456"
|
|
)
|
|
if err := upsertSettingRow(dao.Mdb, mdb.Setting{
|
|
Group: mdb.SettingGroupSystem,
|
|
Key: mdb.SettingKeyInitAdminPasswordPlain,
|
|
Value: oldPassword,
|
|
Type: mdb.SettingTypeString,
|
|
}); err != nil {
|
|
t.Fatalf("seed plaintext setting: %v", err)
|
|
}
|
|
|
|
hash, err := HashPassword(oldPassword)
|
|
if err != nil {
|
|
t.Fatalf("hash password: %v", err)
|
|
}
|
|
user := &mdb.AdminUser{
|
|
Username: defaultAdminUsername,
|
|
PasswordHash: hash,
|
|
Status: mdb.AdminUserStatusEnable,
|
|
}
|
|
if err := dao.Mdb.Create(user).Error; err != nil {
|
|
t.Fatalf("seed admin user: %v", err)
|
|
}
|
|
|
|
if err := UpdateAdminUserPassword(uint64(user.ID), newPassword); err != nil {
|
|
t.Fatalf("update admin password: %v", err)
|
|
}
|
|
|
|
var count int64
|
|
if err := dao.Mdb.Unscoped().
|
|
Model(&mdb.Setting{}).
|
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
|
Count(&count).Error; err != nil {
|
|
t.Fatalf("count plaintext setting: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Fatalf("plaintext setting rows after password change = %d, want 0", count)
|
|
}
|
|
if !GetSettingBool(mdb.SettingKeyInitAdminPasswordFetched, false) {
|
|
t.Fatal("expected fetched flag to be true after clearing plaintext")
|
|
}
|
|
}
|
|
|
|
func TestEnsureDefaultAdminPurgesLegacySoftDeletedPlaintext(t *testing.T) {
|
|
cleanup := testutil.SetupTestDatabases(t)
|
|
defer cleanup()
|
|
|
|
hash, err := HashPassword("existing-password")
|
|
if err != nil {
|
|
t.Fatalf("hash password: %v", err)
|
|
}
|
|
if err := dao.Mdb.Create(&mdb.AdminUser{
|
|
Username: defaultAdminUsername,
|
|
PasswordHash: hash,
|
|
Status: mdb.AdminUserStatusEnable,
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed admin: %v", err)
|
|
}
|
|
if err := dao.Mdb.Create(&mdb.Setting{
|
|
Group: mdb.SettingGroupSystem,
|
|
Key: mdb.SettingKeyInitAdminPasswordPlain,
|
|
Value: "legacy-soft-deleted-plain",
|
|
Type: mdb.SettingTypeString,
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed plaintext setting: %v", err)
|
|
}
|
|
if err := dao.Mdb.Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).Delete(&mdb.Setting{}).Error; err != nil {
|
|
t.Fatalf("soft delete plaintext setting: %v", err)
|
|
}
|
|
|
|
password, created, err := EnsureDefaultAdmin()
|
|
if err != nil {
|
|
t.Fatalf("ensure default admin: %v", err)
|
|
}
|
|
if created || password != "" {
|
|
t.Fatalf("created=%v password=%q, want existing admin unchanged", created, password)
|
|
}
|
|
|
|
var count int64
|
|
if err := dao.Mdb.Unscoped().
|
|
Model(&mdb.Setting{}).
|
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
|
Count(&count).Error; err != nil {
|
|
t.Fatalf("count plaintext setting: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Fatalf("legacy plaintext rows after ensure = %d, want 0", count)
|
|
}
|
|
}
|
|
|
|
func TestEnsureDefaultAdminRollsBackWhenInitialPasswordStateFails(t *testing.T) {
|
|
cleanup := testutil.SetupTestDatabases(t)
|
|
defer cleanup()
|
|
|
|
if err := dao.Mdb.Exec(`
|
|
CREATE TRIGGER fail_initial_password_state
|
|
BEFORE INSERT ON settings
|
|
WHEN NEW.key = 'system.init_admin_password_plain'
|
|
BEGIN
|
|
SELECT RAISE(FAIL, 'forced initial password state failure');
|
|
END;
|
|
`).Error; err != nil {
|
|
t.Fatalf("create failure trigger: %v", err)
|
|
}
|
|
|
|
password, created, err := EnsureDefaultAdmin()
|
|
if err == nil {
|
|
t.Fatal("expected EnsureDefaultAdmin to fail")
|
|
}
|
|
if created || password != "" {
|
|
t.Fatalf("created=%v password=%q, want no created admin on failure", created, password)
|
|
}
|
|
|
|
var adminCount int64
|
|
if err := dao.Mdb.Model(&mdb.AdminUser{}).Count(&adminCount).Error; err != nil {
|
|
t.Fatalf("count admin users after failure: %v", err)
|
|
}
|
|
if adminCount != 0 {
|
|
t.Fatalf("admin users after failed initial password state = %d, want 0", adminCount)
|
|
}
|
|
|
|
if err := dao.Mdb.Exec(`DROP TRIGGER fail_initial_password_state`).Error; err != nil {
|
|
t.Fatalf("drop failure trigger: %v", err)
|
|
}
|
|
|
|
password, created, err = EnsureDefaultAdmin()
|
|
if err != nil {
|
|
t.Fatalf("retry EnsureDefaultAdmin: %v", err)
|
|
}
|
|
if !created || password == "" {
|
|
t.Fatalf("retry created=%v password=%q, want new admin with password", created, password)
|
|
}
|
|
|
|
got, err := GetInitialAdminPassword()
|
|
if err != nil {
|
|
t.Fatalf("get initial password after retry: %v", err)
|
|
}
|
|
if got != password {
|
|
t.Fatalf("initial password after retry = %q, want %q", got, password)
|
|
}
|
|
}
|