@cipherstash/jseql
Version:
Encrypted Query Language JavaScript Library
289 lines (243 loc) • 7.19 kB
text/typescript
import 'dotenv/config'
import { describe, expect, it } from 'vitest'
import { createEqlPayload, getPlaintext, eql, LockContext } from '../src'
import type { CsPlaintextV1Schema } from '../src/cs_plaintext_v1'
describe('createEqlPayload', () => {
it('should create a payload with the correct default values', () => {
const result = createEqlPayload({
plaintext: 'test',
table: 'users',
column: 'email',
})
const expectedPayload: CsPlaintextV1Schema = {
v: 1,
k: 'pt',
p: 'test',
i: {
t: 'users',
c: 'email',
},
}
expect(result).toEqual(expectedPayload)
})
it('should set custom schemaVersion and queryType values when provided', () => {
const result = createEqlPayload({
plaintext: 'test',
table: 'users',
column: 'email',
schemaVersion: 2,
queryType: 'match',
})
const expectedPayload: CsPlaintextV1Schema = {
v: 2,
k: 'pt',
p: 'test',
i: {
t: 'users',
c: 'email',
},
q: 'match',
}
expect(result).toEqual(expectedPayload)
})
it('should set plaintext to an empty string if undefined', () => {
const result = createEqlPayload({
plaintext: '',
table: 'users',
column: 'email',
})
expect(result.p).toBe('')
})
})
describe('getPlaintext', () => {
it('should return plaintext if payload is valid and key is "pt"', () => {
const payload: CsPlaintextV1Schema = {
v: 1,
k: 'pt',
p: 'test',
i: {
t: 'users',
c: 'email',
},
}
const result = getPlaintext(payload)
expect(result).toEqual({
failure: false,
plaintext: 'test',
})
})
it('should return an error if payload is missing "p" or key is not "pt"', () => {
const invalidPayload = {
v: 1,
k: 'ct',
c: 'ciphertext',
p: '',
i: {
t: 'users',
c: 'email',
},
}
const result = getPlaintext(
invalidPayload as unknown as CsPlaintextV1Schema,
)
expect(result).toEqual({
failure: true,
error: new Error('No plaintext data found in the EQL payload'),
})
})
it('should return an error and log if payload is invalid', () => {
const result = getPlaintext(null as unknown as CsPlaintextV1Schema)
expect(result).toEqual({
failure: true,
error: new Error('No plaintext data found in the EQL payload'),
})
})
})
describe('encryption and decryption', () => {
it('should have all required environment variables defined', () => {
expect(process.env.CS_CLIENT_ID).toBeDefined()
expect(process.env.CS_CLIENT_KEY).toBeDefined()
expect(process.env.CS_CLIENT_ACCESS_KEY).toBeDefined()
expect(process.env.CS_WORKSPACE_ID).toBeDefined()
})
it('should encrypt and decrypt a payload', async () => {
const eqlClient = await eql()
const ciphertext = await eqlClient.encrypt('plaintext', {
column: 'column_name',
table: 'users',
})
const plaintext = await eqlClient.decrypt(ciphertext)
expect(plaintext).toEqual('plaintext')
}, 30000)
it('should return null if plaintext is null', async () => {
const eqlClient = await eql()
const ciphertext = await eqlClient.encrypt(null, {
column: 'column_name',
table: 'users',
})
const plaintext = await eqlClient.decrypt(ciphertext)
expect(plaintext).toEqual(null)
}, 30000)
})
describe('bulk encryption', () => {
it('should bulk encrypt and decrypt a payload', async () => {
const eqlClient = await eql()
const ciphertexts = await eqlClient.bulkEncrypt(
[
{
plaintext: 'test',
id: '1',
},
{
plaintext: 'test2',
id: '2',
},
],
{
table: 'users',
column: 'column_name',
},
)
const plaintexts = await eqlClient.bulkDecrypt(ciphertexts)
expect(plaintexts).toEqual([
{
plaintext: 'test',
id: '1',
},
{
plaintext: 'test2',
id: '2',
},
])
}, 30000)
it('should return null if plaintexts is empty', async () => {
const eqlClient = await eql()
const ciphertexts = await eqlClient.bulkEncrypt([], {
table: 'users',
column: 'column_name',
})
expect(ciphertexts).toEqual(null)
}, 30000)
it('should return null if decrypting empty ciphertexts', async () => {
const eqlClient = await eql()
const ciphertexts = null
const plaintexts = await eqlClient.bulkDecrypt(ciphertexts)
expect(plaintexts).toEqual(null)
}, 30000)
})
// ------------------------
// TODO get bulk Encryption/Decryption working in CI.
// These tests pass locally, given you provide a valid JWT.
// To manually test locally, uncomment the following lines and provide a valid JWT in the userJwt variable.
// ------------------------
// const userJwt = ''
// describe('encryption and decryption with lock context', () => {
// it('should encrypt and decrypt a payload with lock context', async () => {
// const eqlClient = await eql()
// const lc = new LockContext()
// const lockContext = await lc.identify(userJwt)
// const ciphertext = await eqlClient
// .encrypt('plaintext', {
// column: 'column_name',
// table: 'users',
// })
// .withLockContext(lockContext)
// const plaintext = await eqlClient
// .decrypt(ciphertext)
// .withLockContext(lockContext)
// expect(plaintext).toEqual('plaintext')
// }, 30000)
// it('should encrypt with context and be unable to decrypt without context', async () => {
// const eqlClient = await eql()
// const lc = new LockContext()
// const lockContext = await lc.identify(userJwt)
// const ciphertext = await eqlClient
// .encrypt('plaintext', {
// column: 'column_name',
// table: 'users',
// })
// .withLockContext(lockContext)
// try {
// await eqlClient.decrypt(ciphertext)
// } catch (error) {
// const e = error as Error
// expect(e.message.startsWith('Failed to retrieve key')).toEqual(true)
// }
// }, 30000)
// it('should bulk encrypt and decrypt a payload with lock context', async () => {
// const eqlClient = await eql()
// const lc = new LockContext()
// const lockContext = await lc.identify(userJwt)
// const ciphertexts = await eqlClient
// .bulkEncrypt(
// [
// {
// plaintext: 'test',
// id: '1',
// },
// {
// plaintext: 'test2',
// id: '2',
// },
// ],
// {
// table: 'users',
// column: 'column_name',
// },
// )
// .withLockContext(lockContext)
// const plaintexts = await eqlClient
// .bulkDecrypt(ciphertexts)
// .withLockContext(lockContext)
// expect(plaintexts).toEqual([
// {
// plaintext: 'test',
// id: '1',
// },
// {
// plaintext: 'test2',
// id: '2',
// },
// ])
// }, 30000)
// })