@lenne.tech/cli 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/blocks/add.js +4 -3
- package/build/commands/blocks/blocks.js +1 -1
- package/build/commands/claude/plugins.js +17 -12
- package/build/commands/cli/create.js +1 -1
- package/build/commands/cli/rename.js +1 -1
- package/build/commands/completion.js +1 -1
- package/build/commands/components/add.js +4 -3
- package/build/commands/components/components.js +1 -1
- package/build/commands/config/help.js +1 -1
- package/build/commands/config/validate.js +10 -1
- package/build/commands/directus/docker-setup.js +1 -1
- package/build/commands/directus/remove.js +2 -3
- package/build/commands/directus/typegen.js +1 -1
- package/build/commands/doctor.js +4 -4
- package/build/commands/frontend/angular.js +1 -1
- package/build/commands/frontend/nuxt.js +2 -2
- package/build/commands/fullstack/init.js +14 -10
- package/build/commands/git/clean.js +6 -6
- package/build/commands/git/force-pull.js +6 -3
- package/build/commands/git/get.js +2 -3
- package/build/commands/git/install-scripts.js +2 -2
- package/build/commands/git/rebase.js +5 -2
- package/build/commands/git/rename.js +3 -4
- package/build/commands/git/reset.js +14 -11
- package/build/commands/git/squash.js +5 -2
- package/build/commands/git/undo.js +6 -3
- package/build/commands/git/update.js +3 -3
- package/build/commands/history.js +1 -1
- package/build/commands/mongodb/s3-restore.js +10 -7
- package/build/commands/qdrant/delete.js +2 -2
- package/build/commands/qdrant/stats.js +2 -11
- package/build/commands/server/add-property.js +46 -31
- package/build/commands/server/create.js +5 -3
- package/build/commands/server/module.js +30 -13
- package/build/commands/server/object.js +1 -1
- package/build/commands/server/permissions.js +318 -0
- package/build/commands/server/set-secrets.js +2 -2
- package/build/commands/status.js +13 -19
- package/build/commands/templates/list.js +4 -4
- package/build/commands/templates/llm.js +8 -14
- package/build/commands/tools/install-scripts.js +2 -2
- package/build/commands/tools/regex.js +1 -1
- package/build/extensions/api-mode.js +3 -2
- package/build/extensions/config.js +5 -5
- package/build/extensions/frontend-helper.js +1 -1
- package/build/extensions/git.js +11 -11
- package/build/extensions/history.js +1 -1
- package/build/extensions/logger.js +3 -6
- package/build/extensions/package-manager.js +6 -6
- package/build/extensions/parse-properties.js +4 -4
- package/build/extensions/server.js +35 -23
- package/build/extensions/template.js +5 -5
- package/build/extensions/tools.js +5 -5
- package/build/extensions/typescript.js +2 -2
- package/build/lib/claude-cli.js +2 -6
- package/build/lib/fallback-scanner.js +852 -0
- package/build/lib/marketplace.js +7 -7
- package/build/lib/nuxt-base-components.js +3 -3
- package/build/lib/plugin-utils.js +9 -13
- package/build/lib/shell-config.js +5 -8
- package/build/lib/validation.js +5 -5
- package/build/templates/permissions/report.html.ejs +402 -0
- package/docs/commands.md +24 -0
- package/docs/lt.config.md +31 -0
- package/package.json +2 -1
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildEffectiveMatrix = buildEffectiveMatrix;
|
|
4
|
+
exports.calculateStats = calculateStats;
|
|
5
|
+
exports.collectRoleEnums = collectRoleEnums;
|
|
6
|
+
exports.detectSecurityGaps = detectSecurityGaps;
|
|
7
|
+
exports.discoverModules = discoverModules;
|
|
8
|
+
exports.extractDecoratorRoles = extractDecoratorRoles;
|
|
9
|
+
exports.extractSecurityCheckInfo = extractSecurityCheckInfo;
|
|
10
|
+
exports.formatRole = formatRole;
|
|
11
|
+
exports.formatRolesDisplay = formatRolesDisplay;
|
|
12
|
+
exports.generateMarkdownReport = generateMarkdownReport;
|
|
13
|
+
exports.parseEndpointPermissions = parseEndpointPermissions;
|
|
14
|
+
exports.parseFieldPermission = parseFieldPermission;
|
|
15
|
+
exports.parseFilePermissions = parseFilePermissions;
|
|
16
|
+
exports.parseRestrictedDecorator = parseRestrictedDecorator;
|
|
17
|
+
exports.parseRolesDecorator = parseRolesDecorator;
|
|
18
|
+
exports.resolveInheritedFields = resolveInheritedFields;
|
|
19
|
+
exports.scanModule = scanModule;
|
|
20
|
+
exports.scanObjects = scanObjects;
|
|
21
|
+
exports.scanPermissions = scanPermissions;
|
|
22
|
+
/**
|
|
23
|
+
* Fallback permissions scanner for CLI usage.
|
|
24
|
+
*
|
|
25
|
+
* This is a standalone copy of the scanner from @lenne.tech/nest-server
|
|
26
|
+
* (src/core/modules/permissions/permissions-scanner.ts).
|
|
27
|
+
*
|
|
28
|
+
* It is used as a fallback when the project's nest-server does not include
|
|
29
|
+
* the permissions scanner (versions < 11.17.0).
|
|
30
|
+
*
|
|
31
|
+
* Prefer the nest-server scanner when available — it is the single source of truth.
|
|
32
|
+
*/
|
|
33
|
+
const fs_1 = require("fs");
|
|
34
|
+
const path_1 = require("path");
|
|
35
|
+
const ts_morph_1 = require("ts-morph");
|
|
36
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
37
|
+
// Exported functions (alphabetically sorted per ESLint perfectionist rules)
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
39
|
+
function buildEffectiveMatrix(mod) {
|
|
40
|
+
const allRoles = new Set();
|
|
41
|
+
for (const ctrl of mod.controllers) {
|
|
42
|
+
for (const r of ctrl.classRoles)
|
|
43
|
+
allRoles.add(r);
|
|
44
|
+
for (const m of ctrl.methods) {
|
|
45
|
+
for (const r of m.roles)
|
|
46
|
+
allRoles.add(r);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const res of mod.resolvers) {
|
|
50
|
+
for (const r of res.classRoles)
|
|
51
|
+
allRoles.add(r);
|
|
52
|
+
for (const m of res.methods) {
|
|
53
|
+
for (const r of m.roles)
|
|
54
|
+
allRoles.add(r);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const result = [];
|
|
58
|
+
for (const role of [...allRoles].sort()) {
|
|
59
|
+
const endpoints = [];
|
|
60
|
+
for (const ctrl of mod.controllers) {
|
|
61
|
+
for (const m of ctrl.methods) {
|
|
62
|
+
const effective = m.roles.length > 0 ? m.roles : ctrl.classRoles;
|
|
63
|
+
if (effective.includes(role)) {
|
|
64
|
+
endpoints.push({ effectiveRoles: effective, method: m.httpMethod, name: m.name, source: 'Controller' });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const res of mod.resolvers) {
|
|
69
|
+
for (const m of res.methods) {
|
|
70
|
+
const effective = m.roles.length > 0 ? m.roles : res.classRoles;
|
|
71
|
+
if (effective.includes(role)) {
|
|
72
|
+
endpoints.push({ effectiveRoles: effective, method: m.httpMethod, name: m.name, source: 'Resolver' });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
result.push({ endpoints, role });
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
function calculateStats(modules, objects, warnings) {
|
|
81
|
+
const warningsByType = {
|
|
82
|
+
NO_RESTRICTION: 0,
|
|
83
|
+
NO_ROLES: 0,
|
|
84
|
+
NO_SECURITY_CHECK: 0,
|
|
85
|
+
UNRESTRICTED_FIELD: 0,
|
|
86
|
+
UNRESTRICTED_METHOD: 0,
|
|
87
|
+
};
|
|
88
|
+
for (const w of warnings) {
|
|
89
|
+
if (w.type in warningsByType) {
|
|
90
|
+
warningsByType[w.type]++;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const totalModels = modules.reduce((s, m) => s + m.models.length, 0);
|
|
94
|
+
let totalMethods = 0;
|
|
95
|
+
let methodsWithRoles = 0;
|
|
96
|
+
for (const mod of modules) {
|
|
97
|
+
for (const ctrl of mod.controllers) {
|
|
98
|
+
for (const m of ctrl.methods) {
|
|
99
|
+
totalMethods++;
|
|
100
|
+
if (m.roles.length > 0 || ctrl.classRoles.length > 0)
|
|
101
|
+
methodsWithRoles++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const res of mod.resolvers) {
|
|
105
|
+
for (const m of res.methods) {
|
|
106
|
+
totalMethods++;
|
|
107
|
+
if (m.roles.length > 0 || res.classRoles.length > 0)
|
|
108
|
+
methodsWithRoles++;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
let modelsWithBothChecks = 0;
|
|
113
|
+
for (const mod of modules) {
|
|
114
|
+
for (const model of mod.models) {
|
|
115
|
+
if (model.classRestriction.length > 0 && model.securityCheck) {
|
|
116
|
+
modelsWithBothChecks++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const endpointCoverage = totalMethods > 0 ? Math.round((methodsWithRoles / totalMethods) * 100) : 100;
|
|
121
|
+
const securityCoverage = totalModels > 0 ? Math.round((modelsWithBothChecks / totalModels) * 100) : 100;
|
|
122
|
+
return {
|
|
123
|
+
endpointCoverage,
|
|
124
|
+
securityCoverage,
|
|
125
|
+
totalEndpoints: totalMethods,
|
|
126
|
+
totalModels,
|
|
127
|
+
totalModules: modules.length,
|
|
128
|
+
totalSubObjects: objects.length,
|
|
129
|
+
totalWarnings: warnings.length,
|
|
130
|
+
warningsByType,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function collectRoleEnums(project, projectPath) {
|
|
134
|
+
const enums = [];
|
|
135
|
+
const enumPatterns = [
|
|
136
|
+
(0, path_1.join)(projectPath, 'src', 'server', 'common', 'enums'),
|
|
137
|
+
(0, path_1.join)(projectPath, 'src', 'server', 'modules'),
|
|
138
|
+
];
|
|
139
|
+
for (const dir of enumPatterns) {
|
|
140
|
+
try {
|
|
141
|
+
const enumFiles = project.addSourceFilesAtPaths((0, path_1.join)(dir, '**', '*.enum.ts'));
|
|
142
|
+
for (const sf of enumFiles) {
|
|
143
|
+
for (const enumDecl of sf.getEnums()) {
|
|
144
|
+
const enumName = enumDecl.getName();
|
|
145
|
+
if (enumName.toLowerCase().includes('role')) {
|
|
146
|
+
const values = enumDecl.getMembers().map((m) => {
|
|
147
|
+
var _a;
|
|
148
|
+
return ({
|
|
149
|
+
key: m.getName(),
|
|
150
|
+
value: ((_a = m.getValue()) === null || _a === void 0 ? void 0 : _a.toString()) || m.getName(),
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
enums.push({
|
|
154
|
+
file: (0, path_1.relative)(projectPath, sf.getFilePath()),
|
|
155
|
+
name: enumName,
|
|
156
|
+
values,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (_a) {
|
|
163
|
+
// Directory may not exist
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return enums;
|
|
167
|
+
}
|
|
168
|
+
function detectSecurityGaps(modules, objects) {
|
|
169
|
+
const warnings = [];
|
|
170
|
+
for (const mod of modules) {
|
|
171
|
+
for (const model of mod.models) {
|
|
172
|
+
if (model.classRestriction.length === 0) {
|
|
173
|
+
warnings.push({
|
|
174
|
+
details: `Model ${model.className} has no @Restricted class-level restriction`,
|
|
175
|
+
file: model.filePath,
|
|
176
|
+
module: mod.name,
|
|
177
|
+
type: 'NO_RESTRICTION',
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (!model.securityCheck) {
|
|
181
|
+
warnings.push({
|
|
182
|
+
details: `Model ${model.className} has no securityCheck override`,
|
|
183
|
+
file: model.filePath,
|
|
184
|
+
module: mod.name,
|
|
185
|
+
type: 'NO_SECURITY_CHECK',
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
for (const field of model.fields) {
|
|
189
|
+
if (field.roles === '*(none)*') {
|
|
190
|
+
warnings.push({
|
|
191
|
+
details: `Field '${field.name}' has no role restriction`,
|
|
192
|
+
file: model.filePath,
|
|
193
|
+
module: mod.name,
|
|
194
|
+
type: 'UNRESTRICTED_FIELD',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
for (const input of mod.inputs) {
|
|
200
|
+
for (const field of input.fields) {
|
|
201
|
+
if (field.roles === '*(none)*') {
|
|
202
|
+
warnings.push({
|
|
203
|
+
details: `Field '${field.name}' has no role restriction`,
|
|
204
|
+
file: input.filePath,
|
|
205
|
+
module: mod.name,
|
|
206
|
+
type: 'UNRESTRICTED_FIELD',
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
for (const ctrl of mod.controllers) {
|
|
212
|
+
if (ctrl.classRoles.length === 0) {
|
|
213
|
+
warnings.push({
|
|
214
|
+
details: `Controller ${ctrl.className} has no @Roles class-level restriction`,
|
|
215
|
+
file: ctrl.filePath,
|
|
216
|
+
module: mod.name,
|
|
217
|
+
type: 'NO_ROLES',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
for (const method of ctrl.methods) {
|
|
221
|
+
if (method.roles.length === 0 && ctrl.classRoles.length === 0) {
|
|
222
|
+
warnings.push({
|
|
223
|
+
details: `Method '${method.name}' has no @Roles and class has no @Roles`,
|
|
224
|
+
file: ctrl.filePath,
|
|
225
|
+
module: mod.name,
|
|
226
|
+
type: 'UNRESTRICTED_METHOD',
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
for (const res of mod.resolvers) {
|
|
232
|
+
if (res.classRoles.length === 0) {
|
|
233
|
+
warnings.push({
|
|
234
|
+
details: `Resolver ${res.className} has no @Roles class-level restriction`,
|
|
235
|
+
file: res.filePath,
|
|
236
|
+
module: mod.name,
|
|
237
|
+
type: 'NO_ROLES',
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
for (const method of res.methods) {
|
|
241
|
+
if (method.roles.length === 0 && res.classRoles.length === 0) {
|
|
242
|
+
warnings.push({
|
|
243
|
+
details: `Method '${method.name}' has no @Roles and class has no @Roles`,
|
|
244
|
+
file: res.filePath,
|
|
245
|
+
module: mod.name,
|
|
246
|
+
type: 'UNRESTRICTED_METHOD',
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
for (const obj of objects) {
|
|
253
|
+
for (const field of obj.fields) {
|
|
254
|
+
if (field.roles === '*(none)*') {
|
|
255
|
+
warnings.push({
|
|
256
|
+
details: `Field '${field.name}' has no role restriction`,
|
|
257
|
+
file: obj.filePath,
|
|
258
|
+
module: 'objects',
|
|
259
|
+
type: 'UNRESTRICTED_FIELD',
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return warnings;
|
|
265
|
+
}
|
|
266
|
+
function discoverModules(modulesDir) {
|
|
267
|
+
if (!(0, fs_1.existsSync)(modulesDir))
|
|
268
|
+
return [];
|
|
269
|
+
return (0, fs_1.readdirSync)(modulesDir)
|
|
270
|
+
.filter((item) => (0, fs_1.statSync)((0, path_1.join)(modulesDir, item)).isDirectory())
|
|
271
|
+
.sort();
|
|
272
|
+
}
|
|
273
|
+
function extractDecoratorRoles(decoratorArgs) {
|
|
274
|
+
const roles = [];
|
|
275
|
+
for (const arg of decoratorArgs) {
|
|
276
|
+
const cleaned = arg.trim();
|
|
277
|
+
if (cleaned.startsWith('[')) {
|
|
278
|
+
const inner = cleaned.slice(1, -1);
|
|
279
|
+
for (const item of inner.split(',')) {
|
|
280
|
+
roles.push(formatRole(item.trim()));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
roles.push(formatRole(cleaned));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return roles;
|
|
288
|
+
}
|
|
289
|
+
function extractSecurityCheckInfo(classDecl) {
|
|
290
|
+
const method = classDecl.getMethod('securityCheck');
|
|
291
|
+
if (!method)
|
|
292
|
+
return undefined;
|
|
293
|
+
const body = method.getBodyText() || '';
|
|
294
|
+
const fieldsStripped = [];
|
|
295
|
+
const deleteMatches = body.matchAll(/delete\s+\w+\.(\w+)/g);
|
|
296
|
+
for (const m of deleteMatches)
|
|
297
|
+
fieldsStripped.push(m[1]);
|
|
298
|
+
const arrayMatches = body.matchAll(/(?:fieldsToRemove|removeFields|stripFields|fieldsToStrip)\s*=\s*\[([^\]]+)\]/g);
|
|
299
|
+
for (const m of arrayMatches) {
|
|
300
|
+
fieldsStripped.push(...m[1].split(',').map((f) => f.trim().replace(/['"]/g, '')));
|
|
301
|
+
}
|
|
302
|
+
const graphqlFieldMatches = body.matchAll(/(?:removeKeys|filterKeys)\s*\([^,]*,\s*\[([^\]]+)\]/g);
|
|
303
|
+
for (const m of graphqlFieldMatches) {
|
|
304
|
+
fieldsStripped.push(...m[1].split(',').map((f) => f.trim().replace(/['"]/g, '')));
|
|
305
|
+
}
|
|
306
|
+
const returnsUndefined = body.includes('return undefined') || body.includes('return null');
|
|
307
|
+
const summaryParts = ['Present'];
|
|
308
|
+
if (fieldsStripped.length > 0)
|
|
309
|
+
summaryParts.push(`Strips fields: ${fieldsStripped.join(', ')}`);
|
|
310
|
+
if (returnsUndefined)
|
|
311
|
+
summaryParts.push('May return undefined');
|
|
312
|
+
return { fieldsStripped: [...new Set(fieldsStripped)], returnsUndefined, summary: summaryParts.join('. ') };
|
|
313
|
+
}
|
|
314
|
+
function formatRole(role) {
|
|
315
|
+
if (!role)
|
|
316
|
+
return '';
|
|
317
|
+
const dotIndex = role.lastIndexOf('.');
|
|
318
|
+
return dotIndex >= 0 ? role.substring(dotIndex + 1) : role;
|
|
319
|
+
}
|
|
320
|
+
function formatRolesDisplay(roles) {
|
|
321
|
+
if (roles.length === 0)
|
|
322
|
+
return '*(none)*';
|
|
323
|
+
if (roles.length === 1)
|
|
324
|
+
return `\`${roles[0]}\``;
|
|
325
|
+
return roles.map((r) => `\`${r}\``).join(', ');
|
|
326
|
+
}
|
|
327
|
+
function generateMarkdownReport(report, projectPath) {
|
|
328
|
+
const lines = [];
|
|
329
|
+
// Header
|
|
330
|
+
lines.push('# Permissions Report');
|
|
331
|
+
lines.push('');
|
|
332
|
+
lines.push(`> Generated: ${report.generated}`);
|
|
333
|
+
if (projectPath)
|
|
334
|
+
lines.push(`> Project: ${projectPath}`);
|
|
335
|
+
lines.push(`> Modules: ${report.stats.totalModules} | Models: ${report.stats.totalModels} | Endpoints: ${report.stats.totalEndpoints} | SubObjects: ${report.stats.totalSubObjects}`);
|
|
336
|
+
lines.push(`> Warnings: ${report.stats.totalWarnings} | Endpoint Coverage: ${report.stats.endpointCoverage}% | Security Coverage: ${report.stats.securityCoverage}%`);
|
|
337
|
+
lines.push('');
|
|
338
|
+
// Table of contents
|
|
339
|
+
lines.push('## Table of Contents');
|
|
340
|
+
lines.push('');
|
|
341
|
+
lines.push('- [Role Index](#role-index)');
|
|
342
|
+
lines.push('- [Summary](#summary)');
|
|
343
|
+
lines.push('- [Warnings](#warnings)');
|
|
344
|
+
for (const mod of report.modules) {
|
|
345
|
+
const anchor = mod.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
346
|
+
lines.push(`- [Module: ${mod.name}](#module-${anchor})`);
|
|
347
|
+
}
|
|
348
|
+
if (report.objects.length > 0) {
|
|
349
|
+
lines.push('- [SubObjects](#subobjects)');
|
|
350
|
+
}
|
|
351
|
+
lines.push('');
|
|
352
|
+
// Role index
|
|
353
|
+
lines.push('## Role Index');
|
|
354
|
+
lines.push('');
|
|
355
|
+
if (report.roleEnums.length > 0) {
|
|
356
|
+
lines.push('| Enum | Value | Type |');
|
|
357
|
+
lines.push('|------|-------|------|');
|
|
358
|
+
for (const enumInfo of report.roleEnums) {
|
|
359
|
+
for (const v of enumInfo.values) {
|
|
360
|
+
const isSystem = v.key.startsWith('S_');
|
|
361
|
+
lines.push(`| ${enumInfo.name}.${v.key} | ${isSystem ? '*(system)*' : `\`${v.value}\``} | ${isSystem ? 'System' : 'Real'} |`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
lines.push('*No role enums found.*');
|
|
367
|
+
}
|
|
368
|
+
lines.push('');
|
|
369
|
+
// Summary table
|
|
370
|
+
lines.push('## Summary');
|
|
371
|
+
lines.push('');
|
|
372
|
+
lines.push('| Module | Models | Inputs | Outputs | Controllers | Resolvers | Warnings |');
|
|
373
|
+
lines.push('|--------|--------|--------|---------|-------------|-----------|----------|');
|
|
374
|
+
for (const mod of report.modules) {
|
|
375
|
+
const modWarnings = report.warnings.filter((w) => w.module === mod.name).length;
|
|
376
|
+
lines.push(`| ${mod.name} | ${mod.models.length} | ${mod.inputs.length} | ${mod.outputs.length} | ${mod.controllers.length} | ${mod.resolvers.length} | ${modWarnings} |`);
|
|
377
|
+
}
|
|
378
|
+
lines.push('');
|
|
379
|
+
if (report.stats.totalWarnings > 0) {
|
|
380
|
+
lines.push('### Warnings by Type');
|
|
381
|
+
lines.push('');
|
|
382
|
+
lines.push('| Type | Count |');
|
|
383
|
+
lines.push('|------|-------|');
|
|
384
|
+
for (const [type, count] of Object.entries(report.stats.warningsByType)) {
|
|
385
|
+
if (count > 0)
|
|
386
|
+
lines.push(`| ${type} | ${count} |`);
|
|
387
|
+
}
|
|
388
|
+
lines.push('');
|
|
389
|
+
}
|
|
390
|
+
// Warnings
|
|
391
|
+
lines.push('## Warnings');
|
|
392
|
+
lines.push('');
|
|
393
|
+
if (report.warnings.length > 0) {
|
|
394
|
+
lines.push('| # | Module | File | Type | Details |');
|
|
395
|
+
lines.push('|---|--------|------|------|---------|');
|
|
396
|
+
report.warnings.forEach((w, i) => {
|
|
397
|
+
const fileName = w.file.split('/').pop() || w.file;
|
|
398
|
+
lines.push(`| ${i + 1} | ${w.module} | ${fileName} | ${w.type} | ${w.details} |`);
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
lines.push('*No warnings found.*');
|
|
403
|
+
}
|
|
404
|
+
lines.push('');
|
|
405
|
+
// Module details
|
|
406
|
+
for (const mod of report.modules) {
|
|
407
|
+
lines.push('---');
|
|
408
|
+
lines.push('');
|
|
409
|
+
lines.push(`## Module: ${mod.name}`);
|
|
410
|
+
lines.push('');
|
|
411
|
+
// Models
|
|
412
|
+
for (const model of mod.models) {
|
|
413
|
+
lines.push(`### Model: ${model.className}`);
|
|
414
|
+
lines.push(`- **File:** \`${model.filePath}\``);
|
|
415
|
+
if (model.extendsClass)
|
|
416
|
+
lines.push(`- **Extends:** \`${model.extendsClass}\``);
|
|
417
|
+
lines.push(`- **Class Restriction:** ${model.classRestriction.length > 0 ? model.classRestriction.map((r) => `\`${r}\``).join(', ') : '*(none)*'}`);
|
|
418
|
+
if (model.securityCheck) {
|
|
419
|
+
lines.push(`- **securityCheck:** ${model.securityCheck.summary}`);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
lines.push('- **securityCheck:** Not present');
|
|
423
|
+
}
|
|
424
|
+
lines.push('');
|
|
425
|
+
if (model.fields.length > 0) {
|
|
426
|
+
lines.push('| Field | Roles | Source |');
|
|
427
|
+
lines.push('|-------|-------|--------|');
|
|
428
|
+
for (const field of model.fields) {
|
|
429
|
+
const source = field.inherited ? 'inherited' : 'local';
|
|
430
|
+
lines.push(`| ${field.name} | ${field.roles} | ${source} |`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
lines.push('');
|
|
434
|
+
}
|
|
435
|
+
// Inputs
|
|
436
|
+
for (const input of mod.inputs) {
|
|
437
|
+
lines.push(`### Input: ${input.className}`);
|
|
438
|
+
lines.push(`- **File:** \`${input.filePath}\``);
|
|
439
|
+
if (input.extendsClass)
|
|
440
|
+
lines.push(`- **Extends:** \`${input.extendsClass}\``);
|
|
441
|
+
lines.push(`- **Class Restriction:** ${input.classRestriction.length > 0 ? input.classRestriction.map((r) => `\`${r}\``).join(', ') : '*(none)*'}`);
|
|
442
|
+
lines.push('');
|
|
443
|
+
if (input.fields.length > 0) {
|
|
444
|
+
lines.push('| Field | Roles |');
|
|
445
|
+
lines.push('|-------|-------|');
|
|
446
|
+
for (const field of input.fields) {
|
|
447
|
+
lines.push(`| ${field.name} | ${field.roles} |`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
lines.push('');
|
|
451
|
+
}
|
|
452
|
+
// Outputs
|
|
453
|
+
for (const output of mod.outputs) {
|
|
454
|
+
lines.push(`### Output: ${output.className}`);
|
|
455
|
+
lines.push(`- **File:** \`${output.filePath}\``);
|
|
456
|
+
if (output.extendsClass)
|
|
457
|
+
lines.push(`- **Extends:** \`${output.extendsClass}\``);
|
|
458
|
+
lines.push('');
|
|
459
|
+
if (output.fields.length > 0) {
|
|
460
|
+
lines.push('| Field | Roles |');
|
|
461
|
+
lines.push('|-------|-------|');
|
|
462
|
+
for (const field of output.fields) {
|
|
463
|
+
lines.push(`| ${field.name} | ${field.roles} |`);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
lines.push('');
|
|
467
|
+
}
|
|
468
|
+
// Controllers
|
|
469
|
+
for (const ctrl of mod.controllers) {
|
|
470
|
+
lines.push(`### Controller: ${ctrl.className}`);
|
|
471
|
+
lines.push(`- **File:** \`${ctrl.filePath}\``);
|
|
472
|
+
lines.push(`- **Class Roles:** ${ctrl.classRoles.length > 0 ? ctrl.classRoles.map((r) => `\`${r}\``).join(', ') : '*(none)*'}`);
|
|
473
|
+
lines.push('');
|
|
474
|
+
if (ctrl.methods.length > 0) {
|
|
475
|
+
lines.push('| Method | HTTP | Route | Roles | Effective |');
|
|
476
|
+
lines.push('|--------|------|-------|-------|-----------|');
|
|
477
|
+
for (const m of ctrl.methods) {
|
|
478
|
+
const effective = m.roles.length > 0 ? formatRolesDisplay(m.roles) : `${formatRolesDisplay(ctrl.classRoles)} (class)`;
|
|
479
|
+
lines.push(`| ${m.name} | ${m.httpMethod} | ${m.route || '/'} | ${formatRolesDisplay(m.roles)} | ${effective} |`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
lines.push('');
|
|
483
|
+
}
|
|
484
|
+
// Resolvers
|
|
485
|
+
for (const res of mod.resolvers) {
|
|
486
|
+
lines.push(`### Resolver: ${res.className}`);
|
|
487
|
+
lines.push(`- **File:** \`${res.filePath}\``);
|
|
488
|
+
lines.push(`- **Class Roles:** ${res.classRoles.length > 0 ? res.classRoles.map((r) => `\`${r}\``).join(', ') : '*(none)*'}`);
|
|
489
|
+
lines.push('');
|
|
490
|
+
if (res.methods.length > 0) {
|
|
491
|
+
lines.push('| Method | Type | Roles | Effective |');
|
|
492
|
+
lines.push('|--------|------|-------|-----------|');
|
|
493
|
+
for (const m of res.methods) {
|
|
494
|
+
const effective = m.roles.length > 0 ? formatRolesDisplay(m.roles) : `${formatRolesDisplay(res.classRoles)} (class)`;
|
|
495
|
+
lines.push(`| ${m.name} | ${m.httpMethod} | ${formatRolesDisplay(m.roles)} | ${effective} |`);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
lines.push('');
|
|
499
|
+
}
|
|
500
|
+
// Effective matrix
|
|
501
|
+
const matrix = buildEffectiveMatrix(mod);
|
|
502
|
+
if (matrix.length > 0) {
|
|
503
|
+
lines.push(`### Effective Permissions: ${mod.name}`);
|
|
504
|
+
lines.push('');
|
|
505
|
+
lines.push('| Role | Endpoint Access |');
|
|
506
|
+
lines.push('|------|-----------------|');
|
|
507
|
+
for (const entry of matrix) {
|
|
508
|
+
const endpointList = entry.endpoints.map((e) => `${e.method} ${e.name}`).join(', ');
|
|
509
|
+
lines.push(`| \`${entry.role}\` | ${endpointList || '*(none)*'} |`);
|
|
510
|
+
}
|
|
511
|
+
lines.push('');
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
// SubObjects
|
|
515
|
+
if (report.objects.length > 0) {
|
|
516
|
+
lines.push('---');
|
|
517
|
+
lines.push('');
|
|
518
|
+
lines.push('## SubObjects');
|
|
519
|
+
lines.push('');
|
|
520
|
+
for (const obj of report.objects) {
|
|
521
|
+
lines.push(`### ${obj.className}`);
|
|
522
|
+
lines.push(`- **File:** \`${obj.filePath}\``);
|
|
523
|
+
if (obj.extendsClass)
|
|
524
|
+
lines.push(`- **Extends:** \`${obj.extendsClass}\``);
|
|
525
|
+
lines.push(`- **Class Restriction:** ${obj.classRestriction.length > 0 ? obj.classRestriction.map((r) => `\`${r}\``).join(', ') : '*(none)*'}`);
|
|
526
|
+
lines.push('');
|
|
527
|
+
if (obj.fields.length > 0) {
|
|
528
|
+
lines.push('| Field | Roles | Source |');
|
|
529
|
+
lines.push('|-------|-------|--------|');
|
|
530
|
+
for (const field of obj.fields) {
|
|
531
|
+
const source = field.inherited ? 'inherited' : 'local';
|
|
532
|
+
lines.push(`| ${field.name} | ${field.roles} | ${source} |`);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
lines.push('');
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return lines.join('\n');
|
|
539
|
+
}
|
|
540
|
+
function parseEndpointPermissions(sourceFile, filePath) {
|
|
541
|
+
const classes = sourceFile.getClasses();
|
|
542
|
+
if (classes.length === 0)
|
|
543
|
+
return undefined;
|
|
544
|
+
const classDecl = classes[0];
|
|
545
|
+
const className = classDecl.getName() || 'Unknown';
|
|
546
|
+
const classRoles = parseRolesDecorator(classDecl);
|
|
547
|
+
let controllerPrefix = '';
|
|
548
|
+
const controllerDeco = classDecl.getDecorator('Controller');
|
|
549
|
+
if (controllerDeco) {
|
|
550
|
+
const args = controllerDeco.getArguments();
|
|
551
|
+
if (args.length > 0)
|
|
552
|
+
controllerPrefix = args[0].getText().replace(/['"]/g, '');
|
|
553
|
+
}
|
|
554
|
+
const methods = [];
|
|
555
|
+
for (const method of classDecl.getMethods()) {
|
|
556
|
+
const methodName = method.getName();
|
|
557
|
+
if (methodName.startsWith('_') || ['onModuleDestroy', 'onModuleInit'].includes(methodName))
|
|
558
|
+
continue;
|
|
559
|
+
const methodRoles = parseRolesDecorator(method);
|
|
560
|
+
for (const httpDeco of ['Delete', 'Get', 'Patch', 'Post', 'Put']) {
|
|
561
|
+
const deco = method.getDecorator(httpDeco);
|
|
562
|
+
if (deco) {
|
|
563
|
+
const args = deco.getArguments();
|
|
564
|
+
const route = args.length > 0 ? args[0].getText().replace(/['"]/g, '') : '/';
|
|
565
|
+
const fullRoute = controllerPrefix
|
|
566
|
+
? `/${controllerPrefix}/${route}`.replace(/\/+/g, '/')
|
|
567
|
+
: `/${route}`.replace(/\/+/g, '/');
|
|
568
|
+
methods.push({ httpMethod: httpDeco.toUpperCase(), name: methodName, roles: methodRoles, route: fullRoute });
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
for (const gqlDeco of ['Mutation', 'Query', 'Subscription']) {
|
|
572
|
+
const deco = method.getDecorator(gqlDeco);
|
|
573
|
+
if (deco) {
|
|
574
|
+
methods.push({ httpMethod: gqlDeco, name: methodName, roles: methodRoles });
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
return { className, classRoles, filePath, methods };
|
|
579
|
+
}
|
|
580
|
+
function parseFieldPermission(prop) {
|
|
581
|
+
var _a, _b;
|
|
582
|
+
const fieldName = prop.getName();
|
|
583
|
+
let roles = '*(none)*';
|
|
584
|
+
let description;
|
|
585
|
+
const unifiedField = prop.getDecorator('UnifiedField');
|
|
586
|
+
if (unifiedField) {
|
|
587
|
+
const args = unifiedField.getArguments();
|
|
588
|
+
if (args.length > 0) {
|
|
589
|
+
const optionsArg = args[0];
|
|
590
|
+
if (optionsArg.getKind() === ts_morph_1.SyntaxKind.ObjectLiteralExpression) {
|
|
591
|
+
const objLit = optionsArg.asKind(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
|
|
592
|
+
const rolesProp = objLit === null || objLit === void 0 ? void 0 : objLit.getProperty('roles');
|
|
593
|
+
if (rolesProp) {
|
|
594
|
+
const init = (_a = rolesProp.asKind(ts_morph_1.SyntaxKind.PropertyAssignment)) === null || _a === void 0 ? void 0 : _a.getInitializer();
|
|
595
|
+
if (init) {
|
|
596
|
+
const rolesText = init.getText();
|
|
597
|
+
if (rolesText.startsWith('[')) {
|
|
598
|
+
const inner = rolesText.slice(1, -1);
|
|
599
|
+
const roleList = inner.split(',').map((r) => formatRole(r.trim()));
|
|
600
|
+
roles = roleList.map((r) => `\`${r}\``).join(', ');
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
roles = `\`${formatRole(rolesText)}\``;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
const descProp = objLit === null || objLit === void 0 ? void 0 : objLit.getProperty('description');
|
|
608
|
+
if (descProp) {
|
|
609
|
+
const init = (_b = descProp.asKind(ts_morph_1.SyntaxKind.PropertyAssignment)) === null || _b === void 0 ? void 0 : _b.getInitializer();
|
|
610
|
+
if (init)
|
|
611
|
+
description = init.getText().replace(/^['"]|['"]$/g, '');
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
if (roles === '*(none)*') {
|
|
617
|
+
const restricted = prop.getDecorator('Restricted');
|
|
618
|
+
if (restricted) {
|
|
619
|
+
const args = restricted.getArguments().map((a) => a.getText());
|
|
620
|
+
if (args.length > 0) {
|
|
621
|
+
const roleList = extractDecoratorRoles(args);
|
|
622
|
+
roles = roleList.map((r) => `\`${r}\``).join(', ');
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
return { description, name: fieldName, roles };
|
|
627
|
+
}
|
|
628
|
+
function parseFilePermissions(sourceFile, filePath, isModel) {
|
|
629
|
+
var _a;
|
|
630
|
+
const classes = sourceFile.getClasses();
|
|
631
|
+
if (classes.length === 0)
|
|
632
|
+
return undefined;
|
|
633
|
+
const classDecl = classes[0];
|
|
634
|
+
const className = classDecl.getName() || 'Unknown';
|
|
635
|
+
const extendsExpr = classDecl.getExtends();
|
|
636
|
+
const extendsClass = ((_a = extendsExpr === null || extendsExpr === void 0 ? void 0 : extendsExpr.getText()) === null || _a === void 0 ? void 0 : _a.replace(/<.*>/, '')) || undefined;
|
|
637
|
+
const classRestriction = parseRestrictedDecorator(classDecl);
|
|
638
|
+
const securityCheck = isModel ? extractSecurityCheckInfo(classDecl) : undefined;
|
|
639
|
+
const fields = [];
|
|
640
|
+
for (const prop of classDecl.getProperties()) {
|
|
641
|
+
fields.push(parseFieldPermission(prop));
|
|
642
|
+
}
|
|
643
|
+
return { className, classRestriction, extendsClass, fields, filePath, securityCheck };
|
|
644
|
+
}
|
|
645
|
+
function parseRestrictedDecorator(node) {
|
|
646
|
+
const restricted = node.getDecorator('Restricted');
|
|
647
|
+
if (!restricted)
|
|
648
|
+
return [];
|
|
649
|
+
const args = restricted.getArguments().map((a) => a.getText());
|
|
650
|
+
return extractDecoratorRoles(args);
|
|
651
|
+
}
|
|
652
|
+
function parseRolesDecorator(node) {
|
|
653
|
+
const roles = node.getDecorator('Roles');
|
|
654
|
+
if (!roles)
|
|
655
|
+
return [];
|
|
656
|
+
const args = roles.getArguments().map((a) => a.getText());
|
|
657
|
+
return extractDecoratorRoles(args);
|
|
658
|
+
}
|
|
659
|
+
function resolveInheritedFields(project, classDecl) {
|
|
660
|
+
const inherited = [];
|
|
661
|
+
const extendsExpr = classDecl.getExtends();
|
|
662
|
+
if (!extendsExpr)
|
|
663
|
+
return inherited;
|
|
664
|
+
const baseClassName = extendsExpr.getText().replace(/<.*>/, '');
|
|
665
|
+
for (const sf of project.getSourceFiles()) {
|
|
666
|
+
for (const cls of sf.getClasses()) {
|
|
667
|
+
if (cls.getName() === baseClassName) {
|
|
668
|
+
for (const prop of cls.getProperties()) {
|
|
669
|
+
const field = parseFieldPermission(prop);
|
|
670
|
+
field.inherited = true;
|
|
671
|
+
inherited.push(field);
|
|
672
|
+
}
|
|
673
|
+
const parentFields = resolveInheritedFields(project, cls);
|
|
674
|
+
inherited.push(...parentFields);
|
|
675
|
+
return inherited;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return inherited;
|
|
680
|
+
}
|
|
681
|
+
function scanModule(project, modulesDir, moduleName, projectPath) {
|
|
682
|
+
const moduleDir = (0, path_1.join)(modulesDir, moduleName);
|
|
683
|
+
const result = {
|
|
684
|
+
controllers: [],
|
|
685
|
+
inputs: [],
|
|
686
|
+
models: [],
|
|
687
|
+
name: moduleName,
|
|
688
|
+
outputs: [],
|
|
689
|
+
resolvers: [],
|
|
690
|
+
};
|
|
691
|
+
// Models
|
|
692
|
+
for (const file of listDir(moduleDir).filter((f) => f.endsWith('.model.ts'))) {
|
|
693
|
+
try {
|
|
694
|
+
const sf = project.addSourceFileAtPath((0, path_1.join)(moduleDir, file));
|
|
695
|
+
const perms = parseFilePermissions(sf, (0, path_1.relative)(projectPath, (0, path_1.join)(moduleDir, file)), true);
|
|
696
|
+
if (perms) {
|
|
697
|
+
const classDecl = sf.getClasses()[0];
|
|
698
|
+
if (classDecl) {
|
|
699
|
+
const inheritedFields = resolveInheritedFields(project, classDecl);
|
|
700
|
+
const localNames = new Set(perms.fields.map((f) => f.name));
|
|
701
|
+
for (const iField of inheritedFields) {
|
|
702
|
+
if (!localNames.has(iField.name))
|
|
703
|
+
perms.fields.push(iField);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
result.models.push(perms);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
catch (_a) {
|
|
710
|
+
/* skip */
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// Inputs
|
|
714
|
+
const inputDir = (0, path_1.join)(moduleDir, 'inputs');
|
|
715
|
+
for (const file of listDir(inputDir).filter((f) => f.endsWith('.input.ts'))) {
|
|
716
|
+
try {
|
|
717
|
+
const sf = project.addSourceFileAtPath((0, path_1.join)(inputDir, file));
|
|
718
|
+
const perms = parseFilePermissions(sf, (0, path_1.relative)(projectPath, (0, path_1.join)(inputDir, file)), false);
|
|
719
|
+
if (perms)
|
|
720
|
+
result.inputs.push(perms);
|
|
721
|
+
}
|
|
722
|
+
catch (_b) {
|
|
723
|
+
/* skip */
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
// Outputs
|
|
727
|
+
const outputDir = (0, path_1.join)(moduleDir, 'outputs');
|
|
728
|
+
for (const file of listDir(outputDir).filter((f) => f.endsWith('.output.ts'))) {
|
|
729
|
+
try {
|
|
730
|
+
const sf = project.addSourceFileAtPath((0, path_1.join)(outputDir, file));
|
|
731
|
+
const perms = parseFilePermissions(sf, (0, path_1.relative)(projectPath, (0, path_1.join)(outputDir, file)), false);
|
|
732
|
+
if (perms)
|
|
733
|
+
result.outputs.push(perms);
|
|
734
|
+
}
|
|
735
|
+
catch (_c) {
|
|
736
|
+
/* skip */
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
// Controllers
|
|
740
|
+
for (const file of listDir(moduleDir).filter((f) => f.endsWith('.controller.ts'))) {
|
|
741
|
+
try {
|
|
742
|
+
const sf = project.addSourceFileAtPath((0, path_1.join)(moduleDir, file));
|
|
743
|
+
const perms = parseEndpointPermissions(sf, (0, path_1.relative)(projectPath, (0, path_1.join)(moduleDir, file)));
|
|
744
|
+
if (perms)
|
|
745
|
+
result.controllers.push(perms);
|
|
746
|
+
}
|
|
747
|
+
catch (_d) {
|
|
748
|
+
/* skip */
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
// Resolvers
|
|
752
|
+
for (const file of listDir(moduleDir).filter((f) => f.endsWith('.resolver.ts'))) {
|
|
753
|
+
try {
|
|
754
|
+
const sf = project.addSourceFileAtPath((0, path_1.join)(moduleDir, file));
|
|
755
|
+
const perms = parseEndpointPermissions(sf, (0, path_1.relative)(projectPath, (0, path_1.join)(moduleDir, file)));
|
|
756
|
+
if (perms)
|
|
757
|
+
result.resolvers.push(perms);
|
|
758
|
+
}
|
|
759
|
+
catch (_e) {
|
|
760
|
+
/* skip */
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
return result;
|
|
764
|
+
}
|
|
765
|
+
function scanObjects(project, objectsDir, projectPath) {
|
|
766
|
+
const objects = [];
|
|
767
|
+
if (!(0, fs_1.existsSync)(objectsDir))
|
|
768
|
+
return objects;
|
|
769
|
+
for (const dir of listDir(objectsDir)) {
|
|
770
|
+
const dirPath = (0, path_1.join)(objectsDir, dir);
|
|
771
|
+
try {
|
|
772
|
+
if (!(0, fs_1.statSync)(dirPath).isDirectory())
|
|
773
|
+
continue;
|
|
774
|
+
}
|
|
775
|
+
catch (_a) {
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
778
|
+
for (const file of listDir(dirPath).filter((f) => f.endsWith('.object.ts'))) {
|
|
779
|
+
try {
|
|
780
|
+
const sf = project.addSourceFileAtPath((0, path_1.join)(dirPath, file));
|
|
781
|
+
const perms = parseFilePermissions(sf, (0, path_1.relative)(projectPath, (0, path_1.join)(dirPath, file)), false);
|
|
782
|
+
if (perms)
|
|
783
|
+
objects.push(perms);
|
|
784
|
+
}
|
|
785
|
+
catch (_b) {
|
|
786
|
+
/* skip */
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return objects;
|
|
791
|
+
}
|
|
792
|
+
function scanPermissions(projectPath, logger) {
|
|
793
|
+
const log = (logger === null || logger === void 0 ? void 0 : logger.log) || (() => { });
|
|
794
|
+
const warn = (logger === null || logger === void 0 ? void 0 : logger.warn) || (() => { });
|
|
795
|
+
log('Scanning permissions...');
|
|
796
|
+
const project = new ts_morph_1.Project({ compilerOptions: { allowJs: true }, skipAddingFilesFromTsConfig: true });
|
|
797
|
+
const modulesDir = (0, path_1.join)(projectPath, 'src', 'server', 'modules');
|
|
798
|
+
const objectsDir = (0, path_1.join)(projectPath, 'src', 'server', 'common', 'objects');
|
|
799
|
+
// Preload nest-server base classes once (used by resolveInheritedFields for all models)
|
|
800
|
+
preloadBaseClasses(project, projectPath);
|
|
801
|
+
const roleEnums = collectRoleEnums(project, projectPath);
|
|
802
|
+
const moduleNames = discoverModules(modulesDir);
|
|
803
|
+
const modules = [];
|
|
804
|
+
for (const name of moduleNames) {
|
|
805
|
+
try {
|
|
806
|
+
modules.push(scanModule(project, modulesDir, name, projectPath));
|
|
807
|
+
}
|
|
808
|
+
catch (error) {
|
|
809
|
+
warn(`Failed to scan module '${name}': ${error}`);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
const objects = scanObjects(project, objectsDir, projectPath);
|
|
813
|
+
const warnings = detectSecurityGaps(modules, objects);
|
|
814
|
+
const stats = calculateStats(modules, objects, warnings);
|
|
815
|
+
log(`Scan complete: ${modules.length} modules, ${objects.length} objects, ${warnings.length} warnings`);
|
|
816
|
+
return {
|
|
817
|
+
generated: new Date().toISOString(),
|
|
818
|
+
modules,
|
|
819
|
+
objects,
|
|
820
|
+
roleEnums,
|
|
821
|
+
stats,
|
|
822
|
+
warnings,
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
826
|
+
// Internal helpers
|
|
827
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
828
|
+
function listDir(dir) {
|
|
829
|
+
try {
|
|
830
|
+
return (0, fs_1.readdirSync)(dir);
|
|
831
|
+
}
|
|
832
|
+
catch (_a) {
|
|
833
|
+
return [];
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
function preloadBaseClasses(project, projectPath) {
|
|
837
|
+
const nestServerPaths = [
|
|
838
|
+
(0, path_1.join)(projectPath, 'node_modules', '@lenne.tech', 'nest-server', 'src'),
|
|
839
|
+
(0, path_1.join)(projectPath, 'node_modules', '@lenne.tech', 'nest-server', 'dist'),
|
|
840
|
+
];
|
|
841
|
+
for (const basePath of nestServerPaths) {
|
|
842
|
+
try {
|
|
843
|
+
if ((0, fs_1.existsSync)(basePath)) {
|
|
844
|
+
project.addSourceFilesAtPaths((0, path_1.join)(basePath, '**', '*.ts'));
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
catch (_a) {
|
|
848
|
+
// Base path not available
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFsbGJhY2stc2Nhbm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvZmFsbGJhY2stc2Nhbm5lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQXlIQSxvREE0Q0M7QUFFRCx3Q0EwREM7QUFFRCw0Q0FnQ0M7QUFFRCxnREFvR0M7QUFFRCwwQ0FLQztBQUVELHNEQWNDO0FBRUQsNERBMkJDO0FBRUQsZ0NBSUM7QUFFRCxnREFJQztBQUVELHdEQXVQQztBQUVELDREQTJDQztBQUVELG9EQWlEQztBQUVELG9EQWlCQztBQUVELDREQUtDO0FBRUQsa0RBS0M7QUFFRCx3REF1QkM7QUFFRCxnQ0FvRkM7QUFFRCxrQ0F1QkM7QUFFRCwwQ0EwQ0M7QUF2OUJEOzs7Ozs7Ozs7O0dBVUc7QUFDSCwyQkFBdUQ7QUFDdkQsK0JBQXNDO0FBQ3RDLHVDQUErQztBQXdHL0MsZ0ZBQWdGO0FBQ2hGLDRFQUE0RTtBQUM1RSxnRkFBZ0Y7QUFFaEYsU0FBZ0Isb0JBQW9CLENBQUMsR0FBc0I7SUFDekQsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUVuQyxLQUFLLE1BQU0sSUFBSSxJQUFJLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNuQyxLQUFLLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVO1lBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRCxLQUFLLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUM3QixLQUFLLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLO2dCQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0MsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNoQyxLQUFLLE1BQU0sQ0FBQyxJQUFJLEdBQUcsQ0FBQyxVQUFV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Q0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQzlELENBQUM7Z0JBQ0gsQ0FBQztnQkFDRCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1QixDQUFDO1FBQ0gsQ0FBQztRQUFDLFdBQU0sQ0FBQztZQUNQLFVBQVU7UUFDWixDQUFDO0lBQ0gsQ0FBQztJQUVELFNBQVM7SUFDVCxNQUFNLFFBQVEsR0FBRyxJQUFBLFdBQUksRUFBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDM0MsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUM1RSxJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsSUFBQSxXQUFJLEVBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDN0QsTUFBTSxLQUFLLEdBQUcsb0JBQW9CLENBQUMsRUFBRSxFQUFFLElBQUEsZUFBUSxFQUFDLFdBQVcsRUFBRSxJQUFBLFdBQUksRUFBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMzRixJQUFJLEtBQUs7Z0JBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkMsQ0FBQztRQUFDLFdBQU0sQ0FBQztZQUNQLFVBQVU7UUFDWixDQUFDO0lBQ0gsQ0FBQztJQUVELFVBQVU7SUFDVixNQUFNLFNBQVMsR0FBRyxJQUFBLFdBQUksRUFBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDN0MsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFD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
|