UNPKG

prisma-zod-generator

Version:

Prisma 2+ generator to emit Zod schemas from your Prisma schema

129 lines 5.53 kB
"use strict"; /** * The gate `license.ts` consults before letting a paid feature run. * * This file described itself as "comprehensive protection against business logic * vulnerabilities including authorization bypasses, privilege escalation, and data leakage", * and was 520 lines of exactly that shape: an authorization rule registry, tenant-isolation * checks, a recursive `sanitizeData` for sensitive fields, and an audit log. * * None of it was reachable. `validateFeatureAccess` is the only thing any caller uses; the * registry, the sanitiser and the audit log had no readers at all, so nothing was being * protected by them. What is left is the licence gate itself, which is real and tested in * tests/business-security-gate.test.ts. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.businessSecurity = exports.BusinessSecurity = exports.BusinessSecurityError = void 0; class BusinessSecurityError extends Error { constructor(message, errorType, context) { super(message); this.errorType = errorType; this.context = context; this.name = 'BusinessSecurityError'; } } exports.BusinessSecurityError = BusinessSecurityError; /** * Business Logic Security Manager */ class BusinessSecurity { /** * Validate feature access with comprehensive checks */ validateFeatureAccess(feature, license, context) { var _a; // Step 1: License validation if (!license) { return { allowed: false, reason: 'No valid license found' }; } // Step 2: Feature-to-plan mapping (corrected logic) const featurePlans = this.getFeaturePlans(); const requiredPlans = featurePlans.get(feature); if (!requiredPlans) { return { allowed: false, reason: `Unknown feature: ${feature}` }; } if (!requiredPlans.includes(license.plan)) { const minPlan = this.getMinimumPlan(requiredPlans); const requiredName = this.describePlan(minPlan); const currentName = this.describePlan(license.plan); return { allowed: false, reason: `Feature '${feature}' requires ${requiredName} plan or higher, current: ${currentName}`, }; } // Step 3: Additional security checks if (license.status && license.status !== 'active') { return { allowed: false, reason: `License status: ${license.status}` }; } const expiry = (_a = license.valid_until) !== null && _a !== void 0 ? _a : new Date(license.validUntil); if (new Date() > expiry) { return { allowed: false, reason: 'License has expired' }; } // Step 4: Context validation if (!this.validateSecurityContext(context)) { return { allowed: false, reason: 'Invalid security context' }; } // A successful access used to be appended to an in-memory `auditLog` array. Nothing ever // read it — the only accessor, getAuditLog(), had no caller — so it grew for the life of the // process and was discarded. That is not an audit trail; if one is wanted it needs a sink // that outlives the run. return { allowed: true }; } // Private helper methods getFeaturePlans() { return new Map([ ['policies', ['professional', 'business', 'enterprise']], ['server-actions', ['starter', 'professional', 'business', 'enterprise']], ['sdk-publisher', ['professional', 'business', 'enterprise']], ['drift-guard', ['professional', 'business', 'enterprise']], ['contract-testing-pack', ['business', 'enterprise']], ['postgres-rls-pack', ['professional', 'business', 'enterprise']], ['form-ux', ['starter', 'professional', 'business', 'enterprise']], ['api-docs-pack', ['business', 'enterprise']], ['multi-tenant-kit', ['enterprise']], ['performance-pack', ['professional', 'business', 'enterprise']], ['data-factories', ['business', 'enterprise']], ]); } getMinimumPlan(plans) { const hierarchy = ['starter', 'professional', 'business', 'enterprise']; for (const plan of hierarchy) { if (plans.includes(plan)) { return plan; } } return 'enterprise'; } describePlan(plan) { switch (plan) { case 'starter': return 'Starter'; case 'professional': return 'Professional'; case 'business': return 'Business'; case 'enterprise': return 'Enterprise'; default: return plan; } } validateSecurityContext(context) { return !!(context.userId && context.sessionId && Array.isArray(context.roles) && Array.isArray(context.permissions)); } } exports.BusinessSecurity = BusinessSecurity; /** * Global business security instance */ exports.businessSecurity = new BusinessSecurity(); /* * secureBusinessLogic, a method decorator wrapping calls in an authorisation check, was removed * as unreachable — no caller inside or outside this module. The live entry point is the * `businessSecurity` singleton's validateFeatureAccess, which license.ts calls directly and * tests/business-security-gate.test.ts covers. */ //# sourceMappingURL=businessSecurity.js.map