fix(backend): JWT config mapstructure tag 修复 + 模型从 hotel 重构为 shop
- 修复 JWTConfig 缺少 mapstructure tag 导致 access_expire_min 解析为 0, token 签发即过期,所有 API 请求返回 401 - 全部 config struct 补齐 mapstructure tag(secret/dsn/hmac_secret 等) - 模型层从 hotel/HotelID 统一重命名为 shop/ShopID - 删除旧 migrations(001-004),新增 001_init 综合迁移文件 - 更新 schema.sql、testutil、handler/service/model 相关引用 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/wangjia/jiu/backend/internal/model"
|
||||
"github.com/wangjia/jiu/backend/testutil"
|
||||
)
|
||||
|
||||
func TestLicenseHandler_Activate_Success(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH001")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
expiry := time.Now().Add(30 * 24 * time.Hour)
|
||||
lic := &model.License{
|
||||
ShopID: shop.ID,
|
||||
LicenseKey: "LHACT-BBBBB-CCCCC-DDDDD",
|
||||
IsActive: true,
|
||||
ExpiresAt: &expiry,
|
||||
}
|
||||
require.NoError(t, db.Create(lic).Error)
|
||||
|
||||
w := makeRequest(r, "POST", "/api/v1/license/activate", token, map[string]interface{}{
|
||||
"license_key": "LHACT-BBBBB-CCCCC-DDDDD",
|
||||
"device_id": "device-123",
|
||||
})
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
data := parseResponse(w)["data"].(map[string]interface{})
|
||||
assert.Equal(t, "device-123", data["device_id"])
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Activate_MissingFields(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH002")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
// 缺少 device_id
|
||||
w := makeRequest(r, "POST", "/api/v1/license/activate", token, map[string]interface{}{
|
||||
"license_key": "LHACT-BBBBB-CCCCC-DDDDD",
|
||||
})
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
|
||||
// 缺少 license_key
|
||||
w = makeRequest(r, "POST", "/api/v1/license/activate", token, map[string]interface{}{
|
||||
"device_id": "device-123",
|
||||
})
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Activate_NotFound(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH003")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
w := makeRequest(r, "POST", "/api/v1/license/activate", token, map[string]interface{}{
|
||||
"license_key": "NONEX-ISTEN-TTTTT-LICCC",
|
||||
"device_id": "device-123",
|
||||
})
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Activate_DeviceMismatch(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH004")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
lic := &model.License{
|
||||
ShopID: shop.ID,
|
||||
LicenseKey: "LHBND-BBBBB-CCCCC-DDDDD",
|
||||
DeviceID: "existing-device",
|
||||
IsActive: true,
|
||||
}
|
||||
require.NoError(t, db.Create(lic).Error)
|
||||
|
||||
w := makeRequest(r, "POST", "/api/v1/license/activate", token, map[string]interface{}{
|
||||
"license_key": "LHBND-BBBBB-CCCCC-DDDDD",
|
||||
"device_id": "different-device",
|
||||
})
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Activate_Expired(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH005")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
expiry := time.Now().Add(-24 * time.Hour)
|
||||
lic := &model.License{
|
||||
ShopID: shop.ID,
|
||||
LicenseKey: "LHEXP-BBBBB-CCCCC-DDDDD",
|
||||
IsActive: true,
|
||||
ExpiresAt: &expiry,
|
||||
}
|
||||
require.NoError(t, db.Create(lic).Error)
|
||||
|
||||
w := makeRequest(r, "POST", "/api/v1/license/activate", token, map[string]interface{}{
|
||||
"license_key": "LHEXP-BBBBB-CCCCC-DDDDD",
|
||||
"device_id": "device-123",
|
||||
})
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Activate_NoAuth(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
w := makeRequest(r, "POST", "/api/v1/license/activate", "", map[string]interface{}{
|
||||
"license_key": "XXXXX-XXXXX-XXXXX-XXXXX",
|
||||
"device_id": "device-123",
|
||||
})
|
||||
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Verify_Success(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH006")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
expiry := time.Now().Add(30 * 24 * time.Hour)
|
||||
lic := &model.License{
|
||||
ShopID: shop.ID,
|
||||
LicenseKey: "LHVFY-BBBBB-CCCCC-DDDDD",
|
||||
DeviceID: "my-device",
|
||||
IsActive: true,
|
||||
ExpiresAt: &expiry,
|
||||
}
|
||||
require.NoError(t, db.Create(lic).Error)
|
||||
|
||||
w := makeRequest(r, "GET", "/api/v1/license/verify?device_id=my-device", token, nil)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
data := parseResponse(w)["data"].(map[string]interface{})
|
||||
assert.Equal(t, "my-device", data["device_id"])
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Verify_MissingDeviceID(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH007")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
w := makeRequest(r, "GET", "/api/v1/license/verify", token, nil)
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Verify_NotFound(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH008")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
w := makeRequest(r, "GET", "/api/v1/license/verify?device_id=nonexistent-device", token, nil)
|
||||
assert.Equal(t, http.StatusForbidden, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Verify_Expired(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH009")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
expiry := time.Now().Add(-1 * time.Hour)
|
||||
lic := &model.License{
|
||||
ShopID: shop.ID,
|
||||
LicenseKey: "LHVEX-BBBBB-CCCCC-DDDDD",
|
||||
DeviceID: "expired-device",
|
||||
IsActive: true,
|
||||
ExpiresAt: &expiry,
|
||||
}
|
||||
require.NoError(t, db.Create(lic).Error)
|
||||
|
||||
w := makeRequest(r, "GET", "/api/v1/license/verify?device_id=expired-device", token, nil)
|
||||
assert.Equal(t, http.StatusForbidden, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Verify_NoAuth(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
w := makeRequest(r, "GET", "/api/v1/license/verify?device_id=any", "", nil)
|
||||
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Deactivate_Success(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH010")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
expiry := time.Now().Add(30 * 24 * time.Hour)
|
||||
lic := &model.License{
|
||||
ShopID: shop.ID,
|
||||
LicenseKey: "LHDAC-BBBBB-CCCCC-DDDDD",
|
||||
DeviceID: "deactivate-device",
|
||||
IsActive: true,
|
||||
ExpiresAt: &expiry,
|
||||
}
|
||||
require.NoError(t, db.Create(lic).Error)
|
||||
|
||||
w := makeRequest(r, "POST", "/api/v1/license/deactivate", token, map[string]interface{}{
|
||||
"device_id": "deactivate-device",
|
||||
})
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Deactivate_MissingDeviceID(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
shop := testutil.CreateTestShop(db, "LH011")
|
||||
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
|
||||
token := getAuthToken(user.ID, shop.ID, "admin")
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
w := makeRequest(r, "POST", "/api/v1/license/deactivate", token, map[string]interface{}{})
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
}
|
||||
|
||||
func TestLicenseHandler_Deactivate_NoAuth(t *testing.T) {
|
||||
db := testutil.SetupTestDB()
|
||||
r := setupProtectedRouter(db)
|
||||
|
||||
w := makeRequest(r, "POST", "/api/v1/license/deactivate", "", map[string]interface{}{
|
||||
"device_id": "any-device",
|
||||
})
|
||||
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
||||
}
|
||||
Reference in New Issue
Block a user