Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions javascript/apps/prisma/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema

# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings

DATABASE_URL="postgresql://johndoe:randompassword@localhost:6432/mydb?schema=public"
DIRECT_URL="postgresql://johndoe:randompassword@my.db.host:5432/mydb?schema=public"
5 changes: 5 additions & 0 deletions javascript/apps/prisma/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# prisma-eql

Init migrations:

bun prisma migrate dev --name init
22 changes: 22 additions & 0 deletions javascript/apps/prisma/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "prisma-eql",
"module": "index.ts",
"type": "module",
"devDependencies": {
"@types/bun": "latest",
"prisma": "^5.20.0",
"prisma-json-types-generator": "^3.1.1"
},
"scripts": {
"insert": "bun run src/insert.ts",
"select": "bun run src/select.ts"
},
"peerDependencies": {
"typescript": "^5.0.0",
"@cipherstash/eql": "workspace:*"
},
"dependencies": {
"@prisma/client": "^5.20.0",
"postgres": "^3.4.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"email" TEXT NOT NULL,
"email_encrypted" JSONB NOT NULL,

CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
3 changes: 3 additions & 0 deletions javascript/apps/prisma/prisma/migrations/migration_lock.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"
28 changes: 28 additions & 0 deletions javascript/apps/prisma/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
provider = "prisma-client-js"
}

/// Always after the prisma-client-js generator
generator json {
provider = "prisma-json-types-generator"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_URL")
}

model User {
id Int @id @default(autoincrement())
email String @unique

/// [CsEncryptedType]
email_encrypted Json
}
2 changes: 2 additions & 0 deletions javascript/apps/prisma/src/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { PrismaClient } from '@prisma/client'
export const prisma = new PrismaClient()
38 changes: 38 additions & 0 deletions javascript/apps/prisma/src/insert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { parseArgs } from 'node:util'
import { eqlPayload } from '@cipherstash/eql'
import type { InputJsonValue } from '@prisma/client/runtime/library'
import { prisma } from './db'

const { values, positionals } = parseArgs({
args: Bun.argv,
options: {
email: {
type: 'string',
},
},
strict: true,
allowPositionals: true,
})

const email = values.email

if (!email) {
throw new Error('[ERROR] the email command line argument is required')
}

await prisma.user.create({
data: {
email,
email_encrypted: eqlPayload({
plaintext: email,
table: 'users',
column: 'email_encrypted',
}),
},
})

console.log(
"[INFO] You've inserted a new user with an encrypted email from the plaintext",
email,
)
process.exit(0)
16 changes: 16 additions & 0 deletions javascript/apps/prisma/src/select.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { prisma } from './db'

const allUsers = await prisma.user.findMany()

console.log('[INFO] All emails have been decrypted by CipherStash Proxy')
console.log(
'Emails:',
JSON.stringify(
allUsers.map((row) => row.email_encrypted?.p),
null,
2,
),
)

await prisma.$disconnect()
process.exit(0)
30 changes: 30 additions & 0 deletions javascript/apps/prisma/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,

// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,

// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,

// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false,

// For Prisma custom types on JSON payloads
"typeRoots": ["../../node_modules/@types/", "./types"]
}
}
7 changes: 7 additions & 0 deletions javascript/apps/prisma/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { CsEncryptedV1Schema } from '@cipherstash/eql'

declare global {
namespace PrismaJson {
type CsEncryptedType = CsEncryptedV1Schema
}
}
Binary file modified javascript/bun.lockb
Binary file not shown.
182 changes: 91 additions & 91 deletions src/cs_encrypted_v1.schema.json
Original file line number Diff line number Diff line change
@@ -1,93 +1,93 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"s": {
"title": "Schema version",
"description": "The schema version of this json document",
"type": "integer",
"enum": [1]
},
"v": {
"title": "Configuration version",
"type": "integer"
},
"k": {
"title": "kind",
"type": "string",
"enum": ["pt", "ct", "en"]
},
"i": {
"title": "ident",
"type": "object",
"properties": {
"t": {
"title": "table",
"type": "string",
"pattern": "^[a-zA-Z_]{1}[0-9a-zA-Z_]*$"
},
"c": {
"title": "column",
"type": "string",
"pattern": "^[a-zA-Z_]{1}[0-9a-zA-Z_]*$"
}
},
"required": ["t", "c"]
},
"p": {
"title": "plaintext",
"type": "string"
},
"c": {
"title": "ciphertext",
"type": "string"
},
"u.1": {
"title": "unique index",
"type": "string"
},
"o.1": {
"title": "ore index",
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"m.1": {
"title": "match index",
"type": "array",
"minItems": 1,
"items": {
"type": "number"
}
}
},
"anyOf": [
{
"properties": {
"k": {
"const": "pt"
}
},
"required": ["p"]
},
{
"properties": {
"k": {
"const": "ct"
}
},
"required": ["c"]
},
{
"properties": {
"k": {
"const": "en"
}
},
"required": ["c", "p"]
}
],
"required": ["v", "k", "e"]
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"s": {
"title": "Schema version",
"description": "The schema version of this json document",
"type": "integer",
"enum": [1]
},
"v": {
"title": "Configuration version",
"type": "integer"
},
"k": {
"title": "kind",
"type": "string",
"enum": ["pt", "ct", "en"]
},
"i": {
"title": "ident",
"type": "object",
"properties": {
"t": {
"title": "table",
"type": "string",
"pattern": "^[a-zA-Z_]{1}[0-9a-zA-Z_]*$"
},
"c": {
"title": "column",
"type": "string",
"pattern": "^[a-zA-Z_]{1}[0-9a-zA-Z_]*$"
}
},
"required": ["t", "c"]
},
"p": {
"title": "plaintext",
"type": "string"
},
"c": {
"title": "ciphertext",
"type": "string"
},
"u.1": {
"title": "unique index",
"type": "string"
},
"o.1": {
"title": "ore index",
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"m.1": {
"title": "match index",
"type": "array",
"minItems": 1,
"items": {
"type": "number"
}
}
},
"anyOf": [
{
"properties": {
"k": {
"const": "pt"
}
},
"required": ["p"]
},
{
"properties": {
"k": {
"const": "ct"
}
},
"required": ["c"]
},
{
"properties": {
"k": {
"const": "en"
}
},
"required": ["c", "p"]
}
],
"required": ["v", "k", "e"]
}