@@ -16,7 +16,9 @@ describe('With Policy: connect-disconnect', () => {
16
16
model M1 {
17
17
id String @id @default(uuid())
18
18
m2 M2[]
19
+ value Int @default(0)
19
20
21
+ @@deny('read', value < 0)
20
22
@@allow('all', true)
21
23
}
22
24
@@ -49,6 +51,7 @@ describe('With Policy: connect-disconnect', () => {
49
51
50
52
const db = withPolicy ( ) ;
51
53
54
+ // m1-1 -> m2-1
52
55
await db . m2 . create ( { data : { id : 'm2-1' , value : 1 , deleted : false } } ) ;
53
56
await db . m1 . create ( {
54
57
data : {
@@ -58,7 +61,9 @@ describe('With Policy: connect-disconnect', () => {
58
61
} ,
59
62
} ,
60
63
} ) ;
64
+ // mark m2-1 deleted
61
65
await prisma . m2 . update ( { where : { id : 'm2-1' } , data : { deleted : true } } ) ;
66
+ // disconnect denied because of violation of m2's update rule
62
67
await expect (
63
68
db . m1 . update ( {
64
69
where : { id : 'm1-1' } ,
@@ -69,7 +74,9 @@ describe('With Policy: connect-disconnect', () => {
69
74
} ,
70
75
} )
71
76
) . toBeRejectedByPolicy ( ) ;
77
+ // reset m2-1 delete
72
78
await prisma . m2 . update ( { where : { id : 'm2-1' } , data : { deleted : false } } ) ;
79
+ // disconnect allowed
73
80
await db . m1 . update ( {
74
81
where : { id : 'm1-1' } ,
75
82
data : {
@@ -79,6 +86,7 @@ describe('With Policy: connect-disconnect', () => {
79
86
} ,
80
87
} ) ;
81
88
89
+ // connect during create denied
82
90
await db . m2 . create ( { data : { id : 'm2-2' , value : 1 , deleted : true } } ) ;
83
91
await expect (
84
92
db . m1 . create ( {
@@ -138,6 +146,21 @@ describe('With Policy: connect-disconnect', () => {
138
146
} ,
139
147
} )
140
148
) . toBeRejectedByPolicy ( ) ;
149
+
150
+ // // connect from m2 to m1, require m1 to be readable
151
+ // await db.m2.create({ data: { id: 'm2-7', value: 1 } });
152
+ // await prisma.m1.create({ data: { id: 'm1-2', value: -1 } });
153
+ // // connect is denied because m1 is not readable
154
+ // await expect(
155
+ // db.m2.update({
156
+ // where: { id: 'm2-7' },
157
+ // data: {
158
+ // m1: {
159
+ // connect: { id: 'm1-2' },
160
+ // },
161
+ // },
162
+ // })
163
+ // ).toBeRejectedByPolicy();
141
164
} ) ;
142
165
143
166
it ( 'nested to-many' , async ( ) => {
@@ -267,4 +290,113 @@ describe('With Policy: connect-disconnect', () => {
267
290
} )
268
291
) . toBeRejectedByPolicy ( ) ;
269
292
} ) ;
293
+
294
+ const modelImplicitManyToMany = `
295
+ model M1 {
296
+ id String @id @default(uuid())
297
+ value Int @default(0)
298
+ m2 M2[]
299
+
300
+ @@deny('read', value < 0)
301
+ @@allow('all', true)
302
+ }
303
+
304
+ model M2 {
305
+ id String @id @default(uuid())
306
+ value Int
307
+ deleted Boolean @default(false)
308
+ m1 M1[]
309
+
310
+ @@deny('read', value < 0)
311
+ @@allow('read,create', true)
312
+ @@allow('update', !deleted)
313
+ }
314
+ ` ;
315
+
316
+ it ( 'implicit many-to-many' , async ( ) => {
317
+ const { withPolicy, prisma } = await loadSchema ( modelImplicitManyToMany ) ;
318
+
319
+ const db = withPolicy ( ) ;
320
+
321
+ await prisma . m1 . create ( { data : { id : 'm1-1' , value : 1 } } ) ;
322
+ await prisma . m2 . create ( { data : { id : 'm2-1' , value : 1 } } ) ;
323
+ await expect (
324
+ db . m1 . update ( {
325
+ where : { id : 'm1-1' } ,
326
+ data : { m2 : { connect : { id : 'm2-1' } } } ,
327
+ } )
328
+ ) . toResolveTruthy ( ) ;
329
+
330
+ await prisma . m1 . create ( { data : { id : 'm1-2' , value : 1 } } ) ;
331
+ await prisma . m2 . create ( { data : { id : 'm2-2' , value : 1 , deleted : true } } ) ;
332
+ // m2-2 not updatable
333
+ await expect (
334
+ db . m1 . update ( {
335
+ where : { id : 'm1-2' } ,
336
+ data : { m2 : { connect : { id : 'm2-2' } } } ,
337
+ } )
338
+ ) . toBeRejectedByPolicy ( ) ;
339
+
340
+ // await prisma.m1.create({ data: { id: 'm1-3', value: -1 } });
341
+ // await prisma.m2.create({ data: { id: 'm2-3', value: 1 } });
342
+ // // m1-3 not readable
343
+ // await expect(
344
+ // db.m2.update({
345
+ // where: { id: 'm2-3' },
346
+ // data: { m1: { connect: { id: 'm1-3' } } },
347
+ // })
348
+ // ).toBeRejectedByPolicy();
349
+ } ) ;
350
+
351
+ const modelExplicitManyToMany = `
352
+ model M1 {
353
+ id String @id @default(uuid())
354
+ value Int @default(0)
355
+ m2 M1OnM2[]
356
+
357
+ @@allow('all', true)
358
+ }
359
+
360
+ model M2 {
361
+ id String @id @default(uuid())
362
+ value Int
363
+ deleted Boolean @default(false)
364
+ m1 M1OnM2[]
365
+
366
+ @@allow('read,create', true)
367
+ }
368
+
369
+ model M1OnM2 {
370
+ m1 M1 @relation(fields: [m1Id], references: [id])
371
+ m1Id String
372
+ m2 M2 @relation(fields: [m2Id], references: [id])
373
+ m2Id String
374
+
375
+ @@id([m1Id, m2Id])
376
+ @@allow('read', true)
377
+ @@allow('create', !m2.deleted)
378
+ }
379
+ ` ;
380
+
381
+ it ( 'explicit many-to-many' , async ( ) => {
382
+ const { withPolicy, prisma } = await loadSchema ( modelExplicitManyToMany ) ;
383
+
384
+ const db = withPolicy ( ) ;
385
+
386
+ await prisma . m1 . create ( { data : { id : 'm1-1' , value : 1 } } ) ;
387
+ await prisma . m2 . create ( { data : { id : 'm2-1' , value : 1 } } ) ;
388
+ await expect (
389
+ db . m1OnM2 . create ( {
390
+ data : { m1 : { connect : { id : 'm1-1' } } , m2 : { connect : { id : 'm2-1' } } } ,
391
+ } )
392
+ ) . toResolveTruthy ( ) ;
393
+
394
+ await prisma . m1 . create ( { data : { id : 'm1-2' , value : 1 } } ) ;
395
+ await prisma . m2 . create ( { data : { id : 'm2-2' , value : 1 , deleted : true } } ) ;
396
+ await expect (
397
+ db . m1OnM2 . create ( {
398
+ data : { m1 : { connect : { id : 'm1-2' } } , m2 : { connect : { id : 'm2-2' } } } ,
399
+ } )
400
+ ) . toBeRejectedByPolicy ( ) ;
401
+ } ) ;
270
402
} ) ;
0 commit comments