53fa259284
Deploy Server / release-deploy-server (push) Successful in 40s
会话/设备管理后端:user_sessions 会话表、JWT 加 sid 校验、按平台类限并发登录、 登录失败锁定、修复禁用账号仍可凭 refresh 续期漏洞、/auth/ping、/auth/logout、 GET /sessions、DELETE /sessions/:id(管理员强制下线)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
133 lines
3.7 KiB
Go
133 lines
3.7 KiB
Go
package service
|
||
|
||
import (
|
||
"testing"
|
||
|
||
"github.com/stretchr/testify/assert"
|
||
"github.com/stretchr/testify/require"
|
||
|
||
"github.com/wangjia/jiu/backend/testutil"
|
||
)
|
||
|
||
func TestAuthService_Login_Success(t *testing.T) {
|
||
db := testutil.SetupTestDB()
|
||
shop := testutil.CreateTestShop(db, "HOTEL001")
|
||
testutil.CreateTestUser(db, shop.ID, "admin", "password123", "admin")
|
||
|
||
svc := NewAuthService(db)
|
||
pair, user, err := svc.Login("HOTEL001", "admin", "password123", DeviceInfo{Platform: "windows"})
|
||
|
||
require.NoError(t, err)
|
||
require.NotNil(t, pair)
|
||
require.NotNil(t, user)
|
||
assert.NotEmpty(t, pair.AccessToken)
|
||
assert.NotEmpty(t, pair.RefreshToken)
|
||
assert.Equal(t, "admin", user.Username)
|
||
}
|
||
|
||
func TestAuthService_Login_WrongPassword(t *testing.T) {
|
||
db := testutil.SetupTestDB()
|
||
shop := testutil.CreateTestShop(db, "HOTEL002")
|
||
testutil.CreateTestUser(db, shop.ID, "admin", "password123", "admin")
|
||
|
||
svc := NewAuthService(db)
|
||
pair, user, err := svc.Login("HOTEL002", "admin", "wrongpassword", DeviceInfo{Platform: "windows"})
|
||
|
||
assert.Error(t, err)
|
||
assert.Equal(t, ErrInvalidCredentials, err)
|
||
assert.Nil(t, pair)
|
||
assert.Nil(t, user)
|
||
}
|
||
|
||
func TestAuthService_Login_WrongHotel(t *testing.T) {
|
||
db := testutil.SetupTestDB()
|
||
testutil.CreateTestShop(db, "HOTEL003")
|
||
|
||
svc := NewAuthService(db)
|
||
pair, user, err := svc.Login("NONEXISTENT", "admin", "password123", DeviceInfo{Platform: "windows"})
|
||
|
||
assert.Error(t, err)
|
||
assert.Equal(t, ErrInvalidCredentials, err)
|
||
assert.Nil(t, pair)
|
||
assert.Nil(t, user)
|
||
}
|
||
|
||
func TestAuthService_Login_DisabledUser(t *testing.T) {
|
||
db := testutil.SetupTestDB()
|
||
shop := testutil.CreateTestShop(db, "HOTEL004")
|
||
user := testutil.CreateTestUser(db, shop.ID, "disabled", "password123", "operator")
|
||
// 禁用用户
|
||
db.Model(user).Update("is_active", false)
|
||
|
||
svc := NewAuthService(db)
|
||
pair, u, err := svc.Login("HOTEL004", "disabled", "password123", DeviceInfo{Platform: "windows"})
|
||
|
||
assert.Error(t, err)
|
||
assert.Equal(t, ErrUserInactive, err)
|
||
assert.Nil(t, pair)
|
||
assert.Nil(t, u)
|
||
}
|
||
|
||
func TestAuthService_Login_WrongUsername(t *testing.T) {
|
||
db := testutil.SetupTestDB()
|
||
shop := testutil.CreateTestShop(db, "HOTEL005")
|
||
testutil.CreateTestUser(db, shop.ID, "admin", "password123", "admin")
|
||
|
||
svc := NewAuthService(db)
|
||
pair, user, err := svc.Login("HOTEL005", "nonexistent", "password123", DeviceInfo{Platform: "windows"})
|
||
|
||
assert.Error(t, err)
|
||
assert.Equal(t, ErrInvalidCredentials, err)
|
||
assert.Nil(t, pair)
|
||
assert.Nil(t, user)
|
||
}
|
||
|
||
func TestAuthService_RefreshTokens(t *testing.T) {
|
||
db := testutil.SetupTestDB()
|
||
shop := testutil.CreateTestShop(db, "HOTEL006")
|
||
testutil.CreateTestUser(db, shop.ID, "admin", "password123", "admin")
|
||
|
||
svc := NewAuthService(db)
|
||
pair, _, err := svc.Login("HOTEL006", "admin", "password123", DeviceInfo{Platform: "windows"})
|
||
require.NoError(t, err)
|
||
require.NotNil(t, pair)
|
||
|
||
// 用 refresh token 换新 token
|
||
newPair, err := svc.RefreshTokens(pair.RefreshToken)
|
||
require.NoError(t, err)
|
||
require.NotNil(t, newPair)
|
||
assert.NotEmpty(t, newPair.AccessToken)
|
||
assert.NotEmpty(t, newPair.RefreshToken)
|
||
}
|
||
|
||
func TestAuthService_RefreshTokens_Invalid(t *testing.T) {
|
||
db := testutil.SetupTestDB()
|
||
testutil.InitConfig()
|
||
|
||
svc := NewAuthService(db)
|
||
newPair, err := svc.RefreshTokens("invalid.token.here")
|
||
|
||
assert.Error(t, err)
|
||
assert.Nil(t, newPair)
|
||
}
|
||
|
||
func TestHashPassword(t *testing.T) {
|
||
hash, err := HashPassword("mypassword")
|
||
require.NoError(t, err)
|
||
assert.NotEmpty(t, hash)
|
||
assert.NotEqual(t, "mypassword", hash)
|
||
|
||
// 第二次哈希应不同(bcrypt 加 salt)
|
||
hash2, err := HashPassword("mypassword")
|
||
require.NoError(t, err)
|
||
assert.NotEqual(t, hash, hash2)
|
||
}
|
||
|
||
func TestInitConfig(t *testing.T) {
|
||
testutil.InitConfig()
|
||
}
|
||
|
||
func init() {
|
||
testutil.InitConfig()
|
||
}
|