const fs = require('node:fs');
|
const path = require('node:path');
|
const menus = require('./permission-menu-snapshot.json');
|
const endpoints = require('./permission-endpoints.json');
|
const report = require('./permission-audit-report.json');
|
function walk(p) {
|
if (!fs.existsSync(p)) return [];
|
if (fs.statSync(p).isFile()) return [p];
|
return fs.readdirSync(p, { withFileTypes: true }).flatMap((e) => e.isDirectory() ? walk(path.join(p, e.name)) : [path.join(p, e.name)]);
|
}
|
const checks = [];
|
for (const menu of menus.filter((v) => v.type === 2 && !v.deleted && !v.status && v.component)) {
|
const dir = 'mom-pro2-before/src/views/' + menu.component.replace(/\/index(?:\.vue)?$/, '').replace(/\.vue$/, '');
|
for (const file of walk(dir).filter((f) => /\.(vue|ts)$/.test(f))) {
|
const s = fs.readFileSync(file, 'utf8');
|
for (const imp of s.matchAll(/import\s+(?!type\b)\{([^]*?)\}\s+from\s+['"](#\/api\/[^'"]+)['"]/g)) {
|
let api = imp[2].replace('#/', 'mom-pro2-before/src/');
|
api = fs.existsSync(api + '.ts') ? api + '.ts' : api + '/index.ts';
|
if (!fs.existsSync(api)) continue;
|
const blocks = [...fs.readFileSync(api, 'utf8').matchAll(/export\s+(?:async\s+)?function\s+(\w+)\b([^]*?)(?=\nexport|$)/g)];
|
for (const name of imp[1].split(',').map((x) => x.trim().split(/\s+as\s+/)[0]).filter((x) => /^\w+$/.test(x))) {
|
const block = blocks.find((x) => x[1] === name);
|
if (!block) continue;
|
const route = block[2].match(/requestClient\.(get|post|put|delete|patch|download|upload)[^]*?(['"`])(\/[^'"`]+)\2/);
|
if (!route) continue;
|
const method = route[1] === 'download' ? 'GET' : route[1] === 'upload' ? 'POST' : route[1].toUpperCase();
|
const url = route[3].split('?')[0];
|
const endpoint = endpoints.find((e) => e.method === method && e.url === url);
|
checks.push({ menu: menu.id, page: menu.name, source: file, api, function: name, method, url, permissions: endpoint?.permissions ?? null });
|
}
|
}
|
}
|
}
|
const unique = [...new Map(checks.map((c) => [c.menu + ':' + c.function + ':' + c.url, c])).values()];
|
fs.writeFileSync('scripts/permission-api-audit.json', JSON.stringify(unique, null, 2));
|
const missing = unique.filter((c) => c.permissions?.some((p) => report.backendWithoutMenu.some((x) => x.key === p)));
|
console.log('Active API calls:', unique.length);
|
console.log('Missing menu permissions:', [...new Set(missing.flatMap((c) => c.permissions))]);
|
console.log('Unmatched endpoints:', unique.filter((c) => c.permissions === null).map((c) => ({ page: c.page, function: c.function, url: c.url })));
|