| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- package auth
- import (
- "context"
- "database/sql"
- "errors"
- "strings"
- "testing"
- "time"
- "perms-system-server/internal/loaders"
- "perms-system-server/internal/middleware"
- userModel "perms-system-server/internal/model/user"
- "perms-system-server/internal/response"
- "perms-system-server/internal/svc"
- "perms-system-server/internal/testutil"
- "perms-system-server/internal/types"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "golang.org/x/crypto/bcrypt"
- )
- func ctxWithUserId(userId int64) context.Context {
- return middleware.WithUserDetails(context.Background(), &loaders.UserDetails{UserId: userId})
- }
- func insertTestUser(t *testing.T, ctx context.Context, username, password string) int64 {
- t.Helper()
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- now := time.Now().Unix()
- res, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
- Username: username,
- Password: password,
- Nickname: "test",
- Avatar: sql.NullString{},
- Email: username + "@test.com",
- Phone: "13800000000",
- Remark: "",
- DeptId: 0,
- IsSuperAdmin: 2,
- MustChangePassword: 1,
- Status: 1,
- CreateTime: now,
- UpdateTime: now,
- })
- require.NoError(t, err)
- id, _ := res.LastInsertId()
- return id
- }
- // TC-0050: 正常修改
- func TestChangePassword_Success(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- ctx := context.Background()
- oldPwd := "oldpass123"
- newPwd := "newpass456"
- username := testutil.UniqueId()
- hashed := testutil.HashPassword(oldPwd)
- userId := insertTestUser(t, ctx, username, hashed)
- t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) })
- logic := NewChangePasswordLogic(ctxWithUserId(userId), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: oldPwd,
- NewPassword: newPwd,
- })
- require.NoError(t, err)
- updated, err := svcCtx.SysUserModel.FindOne(ctx, userId)
- require.NoError(t, err)
- assert.NoError(t, bcrypt.CompareHashAndPassword([]byte(updated.Password), []byte(newPwd)))
- }
- // TC-0051: mustChangePassword重置
- func TestChangePassword_MustChangePasswordReset(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- ctx := context.Background()
- oldPwd := "oldpass123"
- newPwd := "newpass456"
- username := testutil.UniqueId()
- hashed := testutil.HashPassword(oldPwd)
- userId := insertTestUser(t, ctx, username, hashed)
- t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) })
- logic := NewChangePasswordLogic(ctxWithUserId(userId), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: oldPwd,
- NewPassword: newPwd,
- })
- require.NoError(t, err)
- updated, err := svcCtx.SysUserModel.FindOne(ctx, userId)
- require.NoError(t, err)
- assert.Equal(t, int64(2), updated.MustChangePassword)
- }
- // TC-0052: 原密码错误
- func TestChangePassword_WrongOldPassword(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- ctx := context.Background()
- username := testutil.UniqueId()
- hashed := testutil.HashPassword("realpass")
- userId := insertTestUser(t, ctx, username, hashed)
- t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) })
- logic := NewChangePasswordLogic(ctxWithUserId(userId), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: "wrongpass",
- NewPassword: "newpass456",
- })
- var codeErr *response.CodeError
- require.True(t, errors.As(err, &codeErr))
- assert.Equal(t, 400, codeErr.Code())
- assert.Equal(t, "原密码错误", codeErr.Error())
- }
- // TC-0053: 新密码少于6字符
- func TestChangePassword_NewPasswordTooShort(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- logic := NewChangePasswordLogic(ctxWithUserId(1), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: "oldpass",
- NewPassword: "12345",
- })
- var codeErr *response.CodeError
- require.True(t, errors.As(err, &codeErr))
- assert.Equal(t, 400, codeErr.Code())
- assert.Equal(t, "密码长度不能少于6个字符", codeErr.Error())
- }
- // TC-0054: 新密码恰好6字符
- func TestChangePassword_NewPasswordExactly6Chars(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- ctx := context.Background()
- oldPwd := "oldpass123"
- newPwd := "abcdef"
- username := testutil.UniqueId()
- hashed := testutil.HashPassword(oldPwd)
- userId := insertTestUser(t, ctx, username, hashed)
- t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) })
- logic := NewChangePasswordLogic(ctxWithUserId(userId), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: oldPwd,
- NewPassword: newPwd,
- })
- require.NoError(t, err)
- updated, err := svcCtx.SysUserModel.FindOne(ctx, userId)
- require.NoError(t, err)
- assert.NoError(t, bcrypt.CompareHashAndPassword([]byte(updated.Password), []byte(newPwd)))
- }
- // TC-0055: 新密码空字符串
- func TestChangePassword_NewPasswordEmpty(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- logic := NewChangePasswordLogic(ctxWithUserId(1), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: "oldpass",
- NewPassword: "",
- })
- var codeErr *response.CodeError
- require.True(t, errors.As(err, &codeErr))
- assert.Equal(t, 400, codeErr.Code())
- assert.Equal(t, "密码长度不能少于6个字符", codeErr.Error())
- }
- // TC-0056: 新密码超过72字符
- func TestChangePassword_NewPasswordTooLong(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- longPwd := strings.Repeat("a", 73)
- logic := NewChangePasswordLogic(ctxWithUserId(1), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: "oldpass",
- NewPassword: longPwd,
- })
- var codeErr *response.CodeError
- require.True(t, errors.As(err, &codeErr))
- assert.Equal(t, 400, codeErr.Code())
- assert.Equal(t, "密码长度不能超过72个字符", codeErr.Error())
- }
- // TC-0057: 新密码恰好72字符
- func TestChangePassword_NewPasswordExactly72Chars(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- ctx := context.Background()
- oldPwd := "oldpass123"
- newPwd := strings.Repeat("b", 72)
- username := testutil.UniqueId()
- hashed := testutil.HashPassword(oldPwd)
- userId := insertTestUser(t, ctx, username, hashed)
- t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) })
- logic := NewChangePasswordLogic(ctxWithUserId(userId), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: oldPwd,
- NewPassword: newPwd,
- })
- require.NoError(t, err)
- updated, err := svcCtx.SysUserModel.FindOne(ctx, userId)
- require.NoError(t, err)
- assert.NoError(t, bcrypt.CompareHashAndPassword([]byte(updated.Password), []byte(newPwd)))
- }
- // TC-0058: 新旧密码相同
- func TestChangePassword_SameOldAndNew(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- ctx := context.Background()
- pwd := "samepass123"
- username := testutil.UniqueId()
- hashed := testutil.HashPassword(pwd)
- userId := insertTestUser(t, ctx, username, hashed)
- t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) })
- logic := NewChangePasswordLogic(ctxWithUserId(userId), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: pwd,
- NewPassword: pwd,
- })
- var codeErr *response.CodeError
- require.True(t, errors.As(err, &codeErr))
- assert.Equal(t, 400, codeErr.Code())
- assert.Equal(t, "新密码不能与原密码相同", codeErr.Error())
- }
- // TC-0059: 用户不存在
- func TestChangePassword_UserNotFound(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- logic := NewChangePasswordLogic(ctxWithUserId(99999999), svcCtx)
- err := logic.ChangePassword(&types.ChangePasswordReq{
- OldPassword: "oldpass",
- NewPassword: "newpass456",
- })
- var codeErr *response.CodeError
- require.True(t, errors.As(err, &codeErr))
- assert.Equal(t, 404, codeErr.Code())
- assert.Equal(t, "用户不存在", codeErr.Error())
- }
|