@@ -5,15 +5,83 @@ import * as mailer from "$/services/mailer.js";
55import { uuid } from "$/utils/id.js" ;
66import { refreshEnvCache } from "$/config/env.js" ;
77
8+ import { PluginCapabilityError } from "./plugin-auth.js" ;
9+
810export const DEV_ALLOW_ALL_CAPS = process . env . DEV_ALLOW_ALL_CAPS === "true" ;
911
12+ const SENSITIVE_MODELS = new Set ( [
13+ "User" ,
14+ "UserProfile" ,
15+ "UserEmail" ,
16+ "UserRole" ,
17+ "UserRoleAssignment" ,
18+ "UserRoleCapability" ,
19+ "UserCapability" ,
20+ "Session" ,
21+ "PasskeyCredential" ,
22+ "PasskeyChallenge" ,
23+ "VerificationToken" ,
24+ "PasswordResetToken" ,
25+ "Invite" ,
26+ "AuditLog" ,
27+ "Tenant" ,
28+ ] ) ;
29+
30+ function normalizeNamespace ( value ) {
31+ return String ( value || "" )
32+ . replace ( / ^ @ [ ^ / ] + \/ + / , "" )
33+ . trim ( )
34+ . toLowerCase ( ) ;
35+ }
36+
37+ function isWhitelistedForSensitiveModels ( plugin , config = { } ) {
38+ const configured = Array . isArray ( config . SENSITIVE_PLUGIN_ALLOWLIST )
39+ ? config . SENSITIVE_PLUGIN_ALLOWLIST
40+ : [ ] ;
41+ const allowlist = new Set ( configured . map ( ( item ) => normalizeNamespace ( item ) ) ) ;
42+
43+ const ns = normalizeNamespace ( plugin ?. namespace ) ;
44+ const id = normalizeNamespace ( plugin ?. id ) ;
45+ return allowlist . has ( ns ) || allowlist . has ( id ) ;
46+ }
47+
48+ function getPrismaForPlugin ( plugin , config = { } ) {
49+ const namespace = ( plugin ?. namespace || plugin ?. id || "<unknown>" ) . toString ( ) ;
50+
51+ const isWhitelistedCore =
52+ plugin ?. corePlugin === true && isWhitelistedForSensitiveModels ( plugin , config ) ;
53+
54+ if ( isWhitelistedCore ) return prisma ;
55+
56+ return prisma . $extends ( {
57+ name : `plugin-guard:${ namespace } ` ,
58+ query : {
59+ $allModels : {
60+ async $allOperations ( { model } , next ) {
61+ if ( SENSITIVE_MODELS . has ( model ) ) {
62+ throw new PluginCapabilityError (
63+ `Plugin "${ namespace } " is not allowed to access model "${ model } "` ,
64+ {
65+ status : 403 ,
66+ code : "ERR_PLUGIN_DATA_ACCESS" ,
67+ meta : { namespace, model } ,
68+ }
69+ ) ;
70+ }
71+ return next ( ) ;
72+ } ,
73+ } ,
74+ } ,
75+ } ) ;
76+ }
77+
1078const capabilityRegistry = {
1179 database : {
1280 key : "database" ,
1381 provides : "prisma" ,
1482 description : "Read/write access to the primary database via Prisma client" ,
1583 risk : "critical" ,
16- resolve : ( ) => prisma ,
84+ resolve : ( { plugin , config } ) => getPrismaForPlugin ( plugin , config ) ,
1785 } ,
1886 git : {
1987 key : "git" ,
0 commit comments