import { chromium } from 'playwright'; const BASE = 'http://localhost:13001'; const API = 'http://localhost:3001'; const USERS = [ { label: 'SUPER_ADMIN (admin)', username: 'admin', password: 'admin123', expectedPerms: 26 }, { label: 'TENANT_ADMIN (ta_admin)', username: 'ta_admin', password: 'pass123', expectedPerms: 21 }, { label: 'USER (user1)', username: 'user1', password: 'pass123', expectedPerms: 5 }, ]; async function login(page, username, password) { await page.goto(`${BASE}/login`, { waitUntil: 'networkidle' }); await page.waitForTimeout(1000); await page.locator('input[type="text"]').first().fill(username); await page.locator('input[type="password"]').first().fill(password); await page.locator('button[type="submit"]').click(); await page.waitForURL('**/'); await page.waitForTimeout(1000); } async function getApiKey(page) { return await page.evaluate(() => localStorage.getItem('kb_api_key') || ''); } async function run() { const browser = await chromium.launch({ headless: true }); const results = []; for (const u of USERS) { console.log(`\n${'='.repeat(60)}`); console.log(`🧑‍💻 ${u.label}`); console.log(`${'='.repeat(60)}`); const page = await browser.newPage({ viewport: { width: 1440, height: 900 } }); const r = { user: u.label, login: false, perms: 0, nav: [], settingsTabs: [], api: {} }; try { // Login await login(page, u.username, u.password); r.login = true; console.log(` ✅ 登录成功`); // Get API key from page const apiKey = await getApiKey(page); console.log(` 🔑 API Key: ${apiKey.substring(0, 16)}...`); // Check navigation sidebar r.nav = await page.evaluate(() => { return Array.from(document.querySelectorAll('aside, nav, [class*="sidebar"], [class*="navigation"]')) .flatMap(el => Array.from(el.querySelectorAll('a, button'))) .map(el => (el.textContent || '').trim()) .filter(Boolean) .filter(t => !t.startsWith('AuraK') && !t.startsWith('Admin')) .filter((v, i, a) => a.indexOf(v) === i); }); console.log(` 📋 导航: ${r.nav.join(', ')}`); // Check settings tabs await page.goto(`${BASE}/settings`, { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); r.settingsTabs = await page.evaluate(() => { return Array.from(document.querySelectorAll('aside button, [class*="sidebar"] button')) .map(b => (b.textContent || '').trim()) .filter(Boolean) .filter((v, i, a) => a.indexOf(v) === i); }); console.log(` ⚙️ 设置Tab: ${r.settingsTabs.join(', ')}`); // API permission checks const headers = { 'x-api-key': apiKey }; // /api/permissions/mine const permRes = await fetch(`${API}/api/permissions/mine`, { headers }); const permData = await permRes.json(); r.perms = (permData.permissions || []).length; console.log(` 🔒 权限数: ${r.perms} (期望: ${u.expectedPerms})`); // /api/users (user:view) const usersRes = await fetch(`${API}/api/users`, { headers }); r.api['user:view'] = usersRes.status; console.log(` GET /api/users: ${usersRes.ok ? '✅' : '❌'} (${usersRes.status})`); // /api/roles (TENANT_ADMIN+) const rolesRes = await fetch(`${API}/api/roles`, { headers }); r.api['roles'] = rolesRes.status; console.log(` GET /api/roles: ${rolesRes.ok ? '✅' : '❌'} (${rolesRes.status})`); // Check assessment access await page.goto(`${BASE}/assessment`, { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); const assessOK = await page.evaluate(() => { const body = document.body.textContent || ''; return body.includes('AI协作技巧') || body.includes('开始专业评估'); }); r.api['assessment'] = assessOK; console.log(` 📝 考核页可访问: ${assessOK ? '✅' : '❌'}`); } catch (err) { console.error(` ❌ 错误: ${err.message}`); } finally { await page.close(); } results.push(r); } // Summary table console.log(`\n${'='.repeat(60)}`); console.log('📊 权限测试汇总'); console.log(`${'='.repeat(60)}`); console.log(`用户 登录 权限 users roles 设置Tab`); console.log(`${'─'.repeat(60)}`); for (const r of results) { const tabStr = r.settingsTabs.filter(t => !['基本设置'].includes(t)).join('/') || '-'; console.log( r.user.padEnd(22), r.login ? '✅' : '❌', String(r.perms).padStart(3), r.api['user:view'] === 200 ? ' ✅' : ' ❌', String(r.api['roles']).padStart(3), tabStr, ); } console.log(`${'='.repeat(60)}`); console.log('✅ 测试完成'); await browser.close(); } run().catch(e => { console.error('❌', e.message); process.exit(1); });