Organize backend into product executable and shared Go modules
This commit is contained in:
1 parent
981e84a4b4
commit
f0720ec66b
382 files changed
+1944
-6989
No files matched your search
@@ -0,0 +1,245 @@
|
||||
package accountserviceimp
|
||||
|
||||
import (
|
||||
customermodel "git.sendico.io/tech/sxchnge/product/customers/model"
|
||||
sharedmodel "git.sendico.io/tech/sxchnge/shared/model"
|
||||
"testing"
|
||||
|
||||
apiconfig "git.sendico.io/tech/sxchnge/product/auth/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// TestValidatePassword tests the password validation logic directly
|
||||
func TestValidatePassword(t *testing.T) {
|
||||
config := &apiconfig.PasswordConfig{
|
||||
Check: apiconfig.PasswordChecks{
|
||||
MinLength: 8,
|
||||
Digit: true,
|
||||
Upper: true,
|
||||
Lower: true,
|
||||
Special: true,
|
||||
},
|
||||
TokenLength: 32,
|
||||
}
|
||||
|
||||
// Create a minimal service for testing password validation
|
||||
logger := zap.NewNop() // Use no-op logger for tests
|
||||
service := &service{
|
||||
config: config,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
t.Run("ValidPassword", func(t *testing.T) {
|
||||
err := service.ValidatePassword("TestPassword123!", nil)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("PasswordTooShort", func(t *testing.T) {
|
||||
err := service.ValidatePassword("Test1!", nil)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "at least 8 characters")
|
||||
})
|
||||
|
||||
t.Run("PasswordMissingDigit", func(t *testing.T) {
|
||||
err := service.ValidatePassword("TestPassword!", nil)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "at least one digit")
|
||||
})
|
||||
|
||||
t.Run("PasswordMissingUppercase", func(t *testing.T) {
|
||||
err := service.ValidatePassword("testpassword123!", nil)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "at least one uppercase")
|
||||
})
|
||||
|
||||
t.Run("PasswordMissingLowercase", func(t *testing.T) {
|
||||
err := service.ValidatePassword("TESTPASSWORD123!", nil)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "at least one lowercase")
|
||||
})
|
||||
|
||||
t.Run("PasswordMissingSpecialCharacter", func(t *testing.T) {
|
||||
err := service.ValidatePassword("TestPassword123", nil)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "at least one special character")
|
||||
})
|
||||
|
||||
t.Run("PasswordSameAsOld", func(t *testing.T) {
|
||||
oldPassword := "TestPassword123!"
|
||||
err := service.ValidatePassword("TestPassword123!", &oldPassword)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "cannot be the same as the old password")
|
||||
})
|
||||
}
|
||||
|
||||
// TestValidateAccount tests the account validation logic directly
|
||||
func TestValidateAccount(t *testing.T) {
|
||||
config := &apiconfig.PasswordConfig{
|
||||
Check: apiconfig.PasswordChecks{
|
||||
MinLength: 8,
|
||||
Digit: true,
|
||||
Upper: true,
|
||||
Lower: true,
|
||||
Special: true,
|
||||
},
|
||||
TokenLength: 32,
|
||||
}
|
||||
|
||||
logger := zap.NewNop() // Use no-op logger for tests
|
||||
service := &service{
|
||||
config: config,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
t.Run("ValidAccount", func(t *testing.T) {
|
||||
account := &customermodel.Account{
|
||||
AccountPublic: customermodel.AccountPublic{
|
||||
AccountBase: customermodel.AccountBase{
|
||||
Describable: sharedmodel.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: customermodel.UserDataBase{
|
||||
Login: "test@example.com",
|
||||
},
|
||||
},
|
||||
Password: "TestPassword123!",
|
||||
}
|
||||
|
||||
originalPassword := account.Password
|
||||
err := service.ValidateAccount(account)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Password should be hashed after validation
|
||||
assert.NotEqual(t, originalPassword, account.Password)
|
||||
})
|
||||
|
||||
t.Run("AccountMissingName", func(t *testing.T) {
|
||||
account := &customermodel.Account{
|
||||
AccountPublic: customermodel.AccountPublic{
|
||||
UserDataBase: customermodel.UserDataBase{
|
||||
Login: "test@example.com",
|
||||
},
|
||||
},
|
||||
Password: "TestPassword123!",
|
||||
}
|
||||
|
||||
err := service.ValidateAccount(account)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "Name must not be empty")
|
||||
})
|
||||
|
||||
t.Run("AccountMissingLogin", func(t *testing.T) {
|
||||
account := &customermodel.Account{
|
||||
AccountPublic: customermodel.AccountPublic{
|
||||
AccountBase: customermodel.AccountBase{
|
||||
Describable: sharedmodel.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
},
|
||||
Password: "TestPassword123!",
|
||||
}
|
||||
|
||||
err := service.ValidateAccount(account)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "Login must not be empty")
|
||||
})
|
||||
|
||||
t.Run("AccountMissingPassword", func(t *testing.T) {
|
||||
account := &customermodel.Account{
|
||||
AccountPublic: customermodel.AccountPublic{
|
||||
AccountBase: customermodel.AccountBase{
|
||||
Describable: sharedmodel.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: customermodel.UserDataBase{
|
||||
Login: "test@example.com",
|
||||
},
|
||||
},
|
||||
Password: "",
|
||||
}
|
||||
|
||||
err := service.ValidateAccount(account)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "Password must not be empty")
|
||||
})
|
||||
|
||||
t.Run("AccountInvalidPassword", func(t *testing.T) {
|
||||
account := &customermodel.Account{
|
||||
AccountPublic: customermodel.AccountPublic{
|
||||
AccountBase: customermodel.AccountBase{
|
||||
Describable: sharedmodel.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: customermodel.UserDataBase{
|
||||
Login: "test@example.com",
|
||||
},
|
||||
},
|
||||
Password: "weak", // Should fail validation
|
||||
}
|
||||
|
||||
err := service.ValidateAccount(account)
|
||||
assert.Error(t, err)
|
||||
// Should fail on password validation
|
||||
assert.Contains(t, err.Error(), "at least 8 characters")
|
||||
})
|
||||
}
|
||||
|
||||
// TestPasswordConfiguration verifies different password rule configurations
|
||||
func TestPasswordConfiguration(t *testing.T) {
|
||||
t.Run("MinimalRequirements", func(t *testing.T) {
|
||||
config := &apiconfig.PasswordConfig{
|
||||
Check: apiconfig.PasswordChecks{
|
||||
MinLength: 4,
|
||||
Digit: false,
|
||||
Upper: false,
|
||||
Lower: false,
|
||||
Special: false,
|
||||
},
|
||||
TokenLength: 16,
|
||||
}
|
||||
|
||||
logger := zap.NewNop() // Use no-op logger for tests
|
||||
service := &service{
|
||||
config: config,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
// Should pass with minimal requirements
|
||||
err := service.ValidatePassword("test", nil)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("StrictRequirements", func(t *testing.T) {
|
||||
config := &apiconfig.PasswordConfig{
|
||||
Check: apiconfig.PasswordChecks{
|
||||
MinLength: 12,
|
||||
Digit: true,
|
||||
Upper: true,
|
||||
Lower: true,
|
||||
Special: true,
|
||||
},
|
||||
TokenLength: 64,
|
||||
}
|
||||
|
||||
logger := zap.NewNop() // Use no-op logger for tests
|
||||
service := &service{
|
||||
config: config,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
// Should fail with shorter password
|
||||
err := service.ValidatePassword("Test123!", nil)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "at least 12 characters")
|
||||
|
||||
// Should pass with longer password
|
||||
err = service.ValidatePassword("TestPassword123!", nil)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user