11import { FieldInfo } from '@zenstackhq/runtime' ;
2- import { loadSchema } from '@zenstackhq/testtools' ;
2+ import { loadSchema , loadModelWithError } from '@zenstackhq/testtools' ;
33import path from 'path' ;
44
55describe ( 'Encrypted test' , ( ) => {
66 let origDir : string ;
7+ const encryptionKey = new Uint8Array ( Buffer . from ( 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=' , 'base64' ) ) ;
78
89 beforeAll ( async ( ) => {
910 origDir = path . resolve ( '.' ) ;
@@ -14,21 +15,25 @@ describe('Encrypted test', () => {
1415 } ) ;
1516
1617 it ( 'Simple encryption test' , async ( ) => {
17- const { enhance } = await loadSchema ( `
18+ const { enhance, prisma } = await loadSchema (
19+ `
1820 model User {
1921 id String @id @default(cuid())
2022 encrypted_value String @encrypted()
2123
2224 @@allow('all', true)
23- }` ) ;
25+ }` ,
26+ {
27+ enhancements : [ 'encryption' ] ,
28+ enhanceOptions : {
29+ encryption : { encryptionKey } ,
30+ } ,
31+ }
32+ ) ;
2433
2534 const sudoDb = enhance ( undefined , { kinds : [ ] } ) ;
26- const encryptionKey = new Uint8Array ( Buffer . from ( 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=' , 'base64' ) ) ;
2735
28- const db = enhance ( undefined , {
29- kinds : [ 'encrypted' ] ,
30- encryption : { encryptionKey } ,
31- } ) ;
36+ const db = enhance ( ) ;
3237
3338 const create = await db . user . create ( {
3439 data : {
@@ -49,9 +54,50 @@ describe('Encrypted test', () => {
4954 } ,
5055 } ) ;
5156
57+ const rawRead = await prisma . user . findUnique ( { where : { id : '1' } } ) ;
58+
5259 expect ( create . encrypted_value ) . toBe ( 'abc123' ) ;
5360 expect ( read . encrypted_value ) . toBe ( 'abc123' ) ;
5461 expect ( sudoRead . encrypted_value ) . not . toBe ( 'abc123' ) ;
62+ expect ( rawRead . encrypted_value ) . not . toBe ( 'abc123' ) ;
63+ } ) ;
64+
65+ it ( 'Multi-field encryption test' , async ( ) => {
66+ const { enhance } = await loadSchema (
67+ `
68+ model User {
69+ id String @id @default(cuid())
70+ x1 String @encrypted()
71+ x2 String @encrypted()
72+
73+ @@allow('all', true)
74+ }` ,
75+ {
76+ enhancements : [ 'encryption' ] ,
77+ enhanceOptions : {
78+ encryption : { encryptionKey } ,
79+ } ,
80+ }
81+ ) ;
82+
83+ const db = enhance ( ) ;
84+
85+ const create = await db . user . create ( {
86+ data : {
87+ id : '1' ,
88+ x1 : 'abc123' ,
89+ x2 : '123abc' ,
90+ } ,
91+ } ) ;
92+
93+ const read = await db . user . findUnique ( {
94+ where : {
95+ id : '1' ,
96+ } ,
97+ } ) ;
98+
99+ expect ( create ) . toMatchObject ( { x1 : 'abc123' , x2 : '123abc' } ) ;
100+ expect ( read ) . toMatchObject ( { x1 : 'abc123' , x2 : '123abc' } ) ;
55101 } ) ;
56102
57103 it ( 'Custom encryption test' , async ( ) => {
@@ -65,7 +111,7 @@ describe('Encrypted test', () => {
65111
66112 const sudoDb = enhance ( undefined , { kinds : [ ] } ) ;
67113 const db = enhance ( undefined , {
68- kinds : [ 'encrypted ' ] ,
114+ kinds : [ 'encryption ' ] ,
69115 encryption : {
70116 encrypt : async ( model : string , field : FieldInfo , data : string ) => {
71117 // Add _enc to the end of the input
@@ -105,4 +151,104 @@ describe('Encrypted test', () => {
105151 expect ( read . encrypted_value ) . toBe ( 'abc123' ) ;
106152 expect ( sudoRead . encrypted_value ) . toBe ( 'abc123_enc' ) ;
107153 } ) ;
154+
155+ it ( 'Only supports string fields' , async ( ) => {
156+ await expect (
157+ loadModelWithError (
158+ `
159+ model User {
160+ id String @id @default(cuid())
161+ encrypted_value Bytes @encrypted()
162+ }`
163+ )
164+ ) . resolves . toContain ( `attribute \"@encrypted\" cannot be used on this type of field` ) ;
165+ } ) ;
166+
167+ it ( 'Returns cipher text when decryption fails' , async ( ) => {
168+ const { enhance, enhanceRaw, prisma } = await loadSchema (
169+ `
170+ model User {
171+ id String @id @default(cuid())
172+ encrypted_value String @encrypted()
173+
174+ @@allow('all', true)
175+ }` ,
176+ { enhancements : [ 'encryption' ] }
177+ ) ;
178+
179+ const db = enhance ( undefined , {
180+ kinds : [ 'encryption' ] ,
181+ encryption : { encryptionKey } ,
182+ } ) ;
183+
184+ const create = await db . user . create ( {
185+ data : {
186+ id : '1' ,
187+ encrypted_value : 'abc123' ,
188+ } ,
189+ } ) ;
190+ expect ( create . encrypted_value ) . toBe ( 'abc123' ) ;
191+
192+ const db1 = enhanceRaw ( prisma , undefined , {
193+ encryption : { encryptionKey : crypto . getRandomValues ( new Uint8Array ( 32 ) ) } ,
194+ } ) ;
195+ const read = await db1 . user . findUnique ( { where : { id : '1' } } ) ;
196+ expect ( read . encrypted_value ) . toBeTruthy ( ) ;
197+ expect ( read . encrypted_value ) . not . toBe ( 'abc123' ) ;
198+ } ) ;
199+
200+ it ( 'Works with length validation' , async ( ) => {
201+ const { enhance } = await loadSchema (
202+ `
203+ model User {
204+ id String @id @default(cuid())
205+ encrypted_value String @encrypted() @length(0, 6)
206+
207+ @@allow('all', true)
208+ }` ,
209+ {
210+ enhanceOptions : { encryption : { encryptionKey } } ,
211+ }
212+ ) ;
213+
214+ const db = enhance ( ) ;
215+
216+ const create = await db . user . create ( {
217+ data : {
218+ id : '1' ,
219+ encrypted_value : 'abc123' ,
220+ } ,
221+ } ) ;
222+ expect ( create . encrypted_value ) . toBe ( 'abc123' ) ;
223+
224+ await expect (
225+ db . user . create ( {
226+ data : { id : '2' , encrypted_value : 'abc1234' } ,
227+ } )
228+ ) . toBeRejectedByPolicy ( ) ;
229+ } ) ;
230+
231+ it ( 'Complains when encrypted fields are used in model-level policy rules' , async ( ) => {
232+ await expect (
233+ loadModelWithError ( `
234+ model User {
235+ id String @id @default(cuid())
236+ encrypted_value String @encrypted()
237+ @@allow('all', encrypted_value != 'abc123')
238+ }
239+ ` )
240+ ) . resolves . toContain ( `Encrypted fields cannot be used in policy rules` ) ;
241+ } ) ;
242+
243+ it ( 'Complains when encrypted fields are used in field-level policy rules' , async ( ) => {
244+ await expect (
245+ loadModelWithError ( `
246+ model User {
247+ id String @id @default(cuid())
248+ encrypted_value String @encrypted()
249+ value Int @allow('all', encrypted_value != 'abc123')
250+ }
251+ ` )
252+ ) . resolves . toContain ( `Encrypted fields cannot be used in policy rules` ) ;
253+ } ) ;
108254} ) ;
0 commit comments