feat: Web 管理后台及 e2e 测试适配 API 路径变更
- e2e-tests API 路径统一更新为 /api/admin/ 和 /api/member/ 前缀 - Gateway isPublicPath 更新为 /api/admin/auth/ 和 /api/member/auth/ - Gateway 签名白名单路径更新 - 移除已废弃的 /api/checkIn/ 和 /api/auth/login 公开路径
This commit is contained in:
@@ -5,7 +5,7 @@ test.describe('认证和授权测试', () => {
|
|||||||
let userId: number;
|
let userId: number;
|
||||||
|
|
||||||
test.beforeAll(async ({ request }) => {
|
test.beforeAll(async ({ request }) => {
|
||||||
const response = await request.post('http://localhost:8080/api/auth/login', {
|
const response = await request.post('http://localhost:8080/api/admin/auth/login', {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
@@ -28,7 +28,7 @@ test.describe('认证和授权测试', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await test.step('发送登录请求', async () => {
|
await test.step('发送登录请求', async () => {
|
||||||
const response = await page.request.post('http://localhost:8080/api/auth/login', {
|
const response = await page.request.post('http://localhost:8080/api/admin/auth/login', {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
@@ -78,7 +78,7 @@ test.describe('认证和授权测试', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await test.step('查询指定用户信息', async () => {
|
await test.step('查询指定用户信息', async () => {
|
||||||
const response = await page.request.get(`http://localhost:8080/api/users/${userId}`, {
|
const response = await page.request.get(`http://localhost:8080/api/admin/users/${userId}`, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${authToken}`
|
'Authorization': `Bearer ${authToken}`
|
||||||
}
|
}
|
||||||
@@ -98,10 +98,10 @@ test.describe('认证和授权测试', () => {
|
|||||||
test('权限验证测试', async ({ page }) => {
|
test('权限验证测试', async ({ page }) => {
|
||||||
await test.step('测试访问受保护的API', async () => {
|
await test.step('测试访问受保护的API', async () => {
|
||||||
const protectedEndpoints = [
|
const protectedEndpoints = [
|
||||||
'/api/users',
|
'/api/admin/users',
|
||||||
'/api/roles',
|
'/api/admin/roles',
|
||||||
'/api/menus',
|
'/api/admin/menus',
|
||||||
'/api/config'
|
'/api/admin/config'
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const endpoint of protectedEndpoints) {
|
for (const endpoint of protectedEndpoints) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ test.describe('参数配置功能测试', () => {
|
|||||||
let authToken: string;
|
let authToken: string;
|
||||||
|
|
||||||
test.beforeAll(async ({ request }) => {
|
test.beforeAll(async ({ request }) => {
|
||||||
const response = await request.post('http://localhost:8080/api/auth/login', {
|
const response = await request.post('http://localhost:8080/api/admin/auth/login', {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ test.describe('字典管理功能测试', () => {
|
|||||||
let authToken: string;
|
let authToken: string;
|
||||||
|
|
||||||
test.beforeAll(async ({ request }) => {
|
test.beforeAll(async ({ request }) => {
|
||||||
const response = await request.post('http://localhost:8080/api/auth/login', {
|
const response = await request.post('http://localhost:8080/api/admin/auth/login', {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ async function verifyAllServices(): Promise<void> {
|
|||||||
|
|
||||||
console.log(' 验证网关到后端的连通性...');
|
console.log(' 验证网关到后端的连通性...');
|
||||||
try {
|
try {
|
||||||
const response = await fetch('http://localhost:8080/api/auth/login', {
|
const response = await fetch('http://localhost:8080/api/admin/auth/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ username: 'admin', password: 'Test@123' }),
|
body: JSON.stringify({ username: 'admin', password: 'Test@123' }),
|
||||||
@@ -316,7 +316,7 @@ async function waitForBackendReady(): Promise<void> {
|
|||||||
console.log(`✅ 后端服务健康检查通过 (尝试 ${i + 1}/${maxRetries})`);
|
console.log(`✅ 后端服务健康检查通过 (尝试 ${i + 1}/${maxRetries})`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const loginTest = await fetch('http://localhost:8084/api/auth/login', {
|
const loginTest = await fetch('http://localhost:8084/api/admin/auth/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ username: 'admin', password: 'Test@123' }),
|
body: JSON.stringify({ username: 'admin', password: 'Test@123' }),
|
||||||
@@ -364,7 +364,7 @@ async function waitForGatewayReady(): Promise<void> {
|
|||||||
console.log(`✅ 网关服务健康检查通过 (尝试 ${i + 1}/${maxRetries})`);
|
console.log(`✅ 网关服务健康检查通过 (尝试 ${i + 1}/${maxRetries})`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const loginTest = await fetch('http://localhost:8080/api/auth/login', {
|
const loginTest = await fetch('http://localhost:8080/api/admin/auth/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ username: 'admin', password: 'Test@123' }),
|
body: JSON.stringify({ username: 'admin', password: 'Test@123' }),
|
||||||
@@ -425,7 +425,7 @@ async function waitForFrontendReady(): Promise<void> {
|
|||||||
async function cleanupTestData(): Promise<void> {
|
async function cleanupTestData(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// 登录获取token(通过网关)
|
// 登录获取token(通过网关)
|
||||||
const loginResponse = await fetch('http://localhost:8080/api/auth/login', {
|
const loginResponse = await fetch('http://localhost:8080/api/admin/auth/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -458,7 +458,7 @@ async function cleanupTestData(): Promise<void> {
|
|||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
if (user.id > 10) {
|
if (user.id > 10) {
|
||||||
try {
|
try {
|
||||||
await fetch(`http://localhost:8080/api/users/${user.id}`, {
|
await fetch(`http://localhost:8080/api/admin/users/${user.id}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
@@ -486,7 +486,7 @@ async function cleanupTestData(): Promise<void> {
|
|||||||
for (const role of roles) {
|
for (const role of roles) {
|
||||||
if (role.id > 4) {
|
if (role.id > 4) {
|
||||||
try {
|
try {
|
||||||
await fetch(`http://localhost:8080/api/roles/${role.id}`, {
|
await fetch(`http://localhost:8080/api/admin/roles/${role.id}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ test.describe('管理员完整工作流', () => {
|
|||||||
await test.step('提交表单', async () => {
|
await test.step('提交表单', async () => {
|
||||||
const [response] = await Promise.all([
|
const [response] = await Promise.all([
|
||||||
page.waitForResponse(resp =>
|
page.waitForResponse(resp =>
|
||||||
resp.url().includes('/api/roles') && resp.request().method() === 'POST',
|
resp.url().includes('/api/admin/roles') && resp.request().method() === 'POST',
|
||||||
{ timeout: 10000 }
|
{ timeout: 10000 }
|
||||||
).catch(() => null),
|
).catch(() => null),
|
||||||
page.locator('.el-dialog button:has-text("确定")').click()
|
page.locator('.el-dialog button:has-text("确定")').click()
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ test.describe('用户权限边界验证', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await test.step('尝试访问受限API', async () => {
|
await test.step('尝试访问受限API', async () => {
|
||||||
const response = await page.request.get('/api/users?page=0&size=10');
|
const response = await page.request.get('/api/admin/users?page=0&size=10');
|
||||||
expect([200, 401, 403]).toContain(response.status());
|
expect([200, 401, 403]).toContain(response.status());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ test.describe('菜单管理功能测试', () => {
|
|||||||
let authToken: string;
|
let authToken: string;
|
||||||
|
|
||||||
test.beforeAll(async ({ request }) => {
|
test.beforeAll(async ({ request }) => {
|
||||||
const response = await request.post('http://localhost:8080/api/auth/login', {
|
const response = await request.post('http://localhost:8080/api/admin/auth/login', {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async login(username: string, password: string): Promise<{ token: string; userId: number }> {
|
async login(username: string, password: string): Promise<{ token: string; userId: number }> {
|
||||||
const response = await this.request.post(`${this.baseURL}/api/auth/login`, {
|
const response = await this.request.post(`${this.baseURL}/api/admin/auth/login`, {
|
||||||
data: {
|
data: {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
@@ -29,7 +29,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async logout(token: string): Promise<void> {
|
async logout(token: string): Promise<void> {
|
||||||
await this.request.post(`${this.baseURL}/api/auth/logout`, {
|
await this.request.post(`${this.baseURL}/api/admin/auth/logout`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
@@ -37,7 +37,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getUsers(token: string): Promise<any[]> {
|
async getUsers(token: string): Promise<any[]> {
|
||||||
const response = await this.request.get(`${this.baseURL}/api/users`, {
|
const response = await this.request.get(`${this.baseURL}/api/admin/users`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
@@ -51,7 +51,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createUser(token: string, userData: any): Promise<any> {
|
async createUser(token: string, userData: any): Promise<any> {
|
||||||
const response = await this.request.post(`${this.baseURL}/api/users`, {
|
const response = await this.request.post(`${this.baseURL}/api/admin/users`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
@@ -66,7 +66,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateUser(token: string, userId: number, userData: any): Promise<any> {
|
async updateUser(token: string, userId: number, userData: any): Promise<any> {
|
||||||
const response = await this.request.put(`${this.baseURL}/api/users/${userId}`, {
|
const response = await this.request.put(`${this.baseURL}/api/admin/users/${userId}`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
@@ -81,7 +81,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteUser(token: string, userId: number): Promise<void> {
|
async deleteUser(token: string, userId: number): Promise<void> {
|
||||||
const response = await this.request.delete(`${this.baseURL}/api/users/${userId}`, {
|
const response = await this.request.delete(`${this.baseURL}/api/admin/users/${userId}`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
@@ -93,7 +93,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRoles(token: string): Promise<any[]> {
|
async getRoles(token: string): Promise<any[]> {
|
||||||
const response = await this.request.get(`${this.baseURL}/api/roles`, {
|
const response = await this.request.get(`${this.baseURL}/api/admin/roles`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
@@ -107,7 +107,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createRole(token: string, roleData: any): Promise<any> {
|
async createRole(token: string, roleData: any): Promise<any> {
|
||||||
const response = await this.request.post(`${this.baseURL}/api/roles`, {
|
const response = await this.request.post(`${this.baseURL}/api/admin/roles`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
@@ -122,7 +122,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteRole(token: string, roleId: number): Promise<void> {
|
async deleteRole(token: string, roleId: number): Promise<void> {
|
||||||
const response = await this.request.delete(`${this.baseURL}/api/roles/${roleId}`, {
|
const response = await this.request.delete(`${this.baseURL}/api/admin/roles/${roleId}`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
@@ -134,7 +134,7 @@ export class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getMenus(token: string): Promise<any[]> {
|
async getMenus(token: string): Promise<any[]> {
|
||||||
const response = await this.request.get(`${this.baseURL}/api/menus`, {
|
const response = await this.request.get(`${this.baseURL}/api/admin/menus`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export class TestDataManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async createTestUser(request: APIRequestContext, userData: TestUser): Promise<any> {
|
static async createTestUser(request: APIRequestContext, userData: TestUser): Promise<any> {
|
||||||
const response = await request.post(`${this.apiBaseUrl}/api/users`, {
|
const response = await request.post(`${this.apiBaseUrl}/api/admin/users`, {
|
||||||
data: userData,
|
data: userData,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ export class TestDataManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async createTestRole(request: APIRequestContext, roleData: TestRole): Promise<any> {
|
static async createTestRole(request: APIRequestContext, roleData: TestRole): Promise<any> {
|
||||||
const response = await request.post(`${this.apiBaseUrl}/api/roles`, {
|
const response = await request.post(`${this.apiBaseUrl}/api/admin/roles`, {
|
||||||
data: roleData,
|
data: roleData,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ export class TestDataManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await request.delete(`${this.apiBaseUrl}/api/users/${userData.id}`);
|
const response = await request.delete(`${this.apiBaseUrl}/api/admin/users/${userData.id}`);
|
||||||
if (!response.ok()) {
|
if (!response.ok()) {
|
||||||
console.warn(`Failed to delete test user ${username}: ${await response.text()}`);
|
console.warn(`Failed to delete test user ${username}: ${await response.text()}`);
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ export class TestDataManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await request.delete(`${this.apiBaseUrl}/api/roles/${roleData.id}`);
|
const response = await request.delete(`${this.apiBaseUrl}/api/admin/roles/${roleData.id}`);
|
||||||
if (!response.ok()) {
|
if (!response.ok()) {
|
||||||
console.warn(`Failed to delete test role ${roleKey}: ${await response.text()}`);
|
console.warn(`Failed to delete test role ${roleKey}: ${await response.text()}`);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -81,11 +81,9 @@ public class JwtAuthenticationFilter extends AbstractGatewayFilterFactory<JwtAut
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPublicPath(String path) {
|
private boolean isPublicPath(String path) {
|
||||||
return path.startsWith("/api/auth/") ||
|
return path.startsWith("/api/admin/auth/") ||
|
||||||
path.equals("/actuator/health") ||
|
path.equals("/actuator/health") ||
|
||||||
path.startsWith("/api/member/auth/") ||
|
path.startsWith("/api/member/auth/") ||
|
||||||
path.equals("/api/auth/login") ||
|
|
||||||
path.startsWith("/api/checkIn/") ||
|
|
||||||
path.startsWith("/actuator/info");
|
path.startsWith("/actuator/info");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ signature:
|
|||||||
max-age-minutes: ${SIGNATURE_MAX_AGE_MINUTES:5}
|
max-age-minutes: ${SIGNATURE_MAX_AGE_MINUTES:5}
|
||||||
nonce-cache-size: ${SIGNATURE_NONCE_CACHE_SIZE:10000}
|
nonce-cache-size: ${SIGNATURE_NONCE_CACHE_SIZE:10000}
|
||||||
whitelist:
|
whitelist:
|
||||||
paths: ${SIGNATURE_WHITELIST_PATHS:/actuator/health,/actuator/info,/api/auth/login,/api/auth/register,/api/member/auth/miniapp/login,/api/member/auth/mp/callback}
|
paths: ${SIGNATURE_WHITELIST_PATHS:/actuator/health,/actuator/info,/api/admin/auth/login,/api/admin/auth/register,/api/member/auth/miniapp/login,/api/member/auth/mp/callback}
|
||||||
|
|
||||||
resilience:
|
resilience:
|
||||||
enabled: ${RESILIENCE_ENABLED:true}
|
enabled: ${RESILIENCE_ENABLED:true}
|
||||||
|
|||||||
Reference in New Issue
Block a user