UNPKG

@addon24/eslint-config

Version:

ESLint configuration rules for WorldOfTextcraft projects - Centralized configuration for all project types

181 lines (158 loc) 6.18 kB
/** * ESLint-Regel: Admin Controller Security * Stellt sicher, dass alle Admin-Controller die erforderlichen Security Guards verwenden müssen. * Alle Controller im Admin-Ordner müssen @UseGuards(AuthGuard, AdminGuard) verwenden. */ /** @type {import('eslint').Rule.RuleModule} */ const adminControllerSecurityRule = { meta: { type: "problem", docs: { description: "Admin-Controller müssen AuthGuard und AdminGuard verwenden", category: "Security", recommended: true, }, schema: [], messages: { missingAuthGuardImport: "Admin-Controller müssen AuthGuard importieren: import AuthGuard from '@/guards/AuthGuard'", missingAdminGuardImport: "Admin-Controller müssen AdminGuard importieren: import AdminGuard from '@/guards/AdminGuard'", missingUseGuardsImport: "Admin-Controller müssen UseGuards importieren: import { UseGuards } from '@nestjs/common'", missingUseGuardsDecorator: "Admin-Controller müssen @UseGuards(AuthGuard, AdminGuard) als Klassen-Decorator verwenden", incorrectGuardsOrder: "@UseGuards muss exakt 'AuthGuard, AdminGuard' in dieser Reihenfolge enthalten", missingApiBearerAuth: "Admin-Controller müssen @ApiBearerAuth() Decorator verwenden", }, }, create(context) { const filename = context.getFilename(); // Prüfe, ob es sich um einen Admin-Controller handelt const isAdminController = filename.includes("/Admin/") && filename.endsWith("Controller.ts") && !filename.includes("BaseController") && !filename.includes(".test.") && !filename.includes(".spec."); if (!isAdminController) return {}; let hasAuthGuardImport = false; let hasAdminGuardImport = false; let hasUseGuardsImport = false; let hasCorrectUseGuardsDecorator = false; let hasApiBearerAuthDecorator = false; let classNode = null; return { // Prüfe Import-Statements ImportDeclaration(node) { if (node.source.value === "@/guards/AuthGuard") { // Prüfe auf default import const defaultImport = node.specifiers.find(spec => spec.type === "ImportDefaultSpecifier" && spec.local.name === "AuthGuard" ); if (defaultImport) { hasAuthGuardImport = true; } } if (node.source.value === "@/guards/AdminGuard") { // Prüfe auf default import const defaultImport = node.specifiers.find(spec => spec.type === "ImportDefaultSpecifier" && spec.local.name === "AdminGuard" ); if (defaultImport) { hasAdminGuardImport = true; } } if (node.source.value === "@nestjs/common") { // Prüfe auf UseGuards import const useGuardsImport = node.specifiers.find(spec => spec.type === "ImportSpecifier" && spec.imported.name === "UseGuards" ); if (useGuardsImport) { hasUseGuardsImport = true; } } }, // Prüfe Klassen-Decorators ClassDeclaration(node) { classNode = node; if (node.decorators) { for (const decorator of node.decorators) { // Prüfe @UseGuards Decorator if (decorator.expression.type === "CallExpression" && decorator.expression.callee.type === "Identifier" && decorator.expression.callee.name === "UseGuards") { const args = decorator.expression.arguments; if (args.length === 2 && args[0].type === "Identifier" && args[0].name === "AuthGuard" && args[1].type === "Identifier" && args[1].name === "AdminGuard") { hasCorrectUseGuardsDecorator = true; } } // Prüfe @ApiBearerAuth Decorator if (decorator.expression.type === "CallExpression" && decorator.expression.callee.type === "Identifier" && decorator.expression.callee.name === "ApiBearerAuth") { hasApiBearerAuthDecorator = true; } } } }, // Validierung am Ende der Datei "Program:exit"(node) { if (!classNode) return; // Prüfe alle erforderlichen Importe if (!hasAuthGuardImport) { context.report({ node: classNode, messageId: "missingAuthGuardImport", }); } if (!hasAdminGuardImport) { context.report({ node: classNode, messageId: "missingAdminGuardImport", }); } if (!hasUseGuardsImport) { context.report({ node: classNode, messageId: "missingUseGuardsImport", }); } // Prüfe @UseGuards Decorator if (!hasCorrectUseGuardsDecorator) { // Finde UseGuards Decorator, um spezifische Fehlermeldung zu geben let foundIncorrectUseGuards = false; if (classNode.decorators) { for (const decorator of classNode.decorators) { if (decorator.expression.type === "CallExpression" && decorator.expression.callee.type === "Identifier" && decorator.expression.callee.name === "UseGuards") { foundIncorrectUseGuards = true; context.report({ node: decorator, messageId: "incorrectGuardsOrder", }); break; } } } if (!foundIncorrectUseGuards) { context.report({ node: classNode, messageId: "missingUseGuardsDecorator", }); } } // Prüfe @ApiBearerAuth Decorator if (!hasApiBearerAuthDecorator) { context.report({ node: classNode, messageId: "missingApiBearerAuth", }); } }, }; }, }; export default { rules: { "admin-controller-security": adminControllerSecurityRule, }, };