Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doesn't work with the Prisma fluent API #80

Open
hightail191 opened this issue Aug 30, 2023 · 5 comments
Open

Doesn't work with the Prisma fluent API #80

hightail191 opened this issue Aug 30, 2023 · 5 comments

Comments

@hightail191
Copy link

hightail191 commented Aug 30, 2023

Describe the Bug
I have trouble in using prisma-field-encryption middleware when using prisma fluent API. Not decrypted data are returned when I request data through prisma fluent API. To avoid N+1 problem, I want to use fluent API which can use prisma data loader.

To Reproduce
Add prisma-field-encryption middleware. Make schema which has parent-children relation model and @Encrypted field in children model. (see my code below)

Expected Behavior
I expect data which are requested through prisma fluent API to be decrypted.

Environment:

OS: ubuntu 22.04.1
Node 20.2.0
Prisma version 5.2.0
prisma-field-encryption 1.5.0
TypeScript version 5.2.2
Express 4.18.2

Additional Context

This is my github repository

Prisma schema

// schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

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

datasource db {
  provider = "postgresql"
  url      = "postgresql://postgres:postgres@db:5432/adgame?schema=public"
}

model User {
  id    Int     @id @default(autoincrement())
  email String
  name  String? /// @encrypted
  posts Post[]
}

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String? /// @encrypted
  published Boolean @default(false)
  author    User    @relation(fields: [authorId], references: [id])
  authorId  Int
}

Express Server

// server.ts

import express from "express";
import { PrismaClient } from "@prisma/client";
import { fieldEncryptionExtension } from "prisma-field-encryption";

const globalClient = new PrismaClient();

const client = globalClient.$extends(
  fieldEncryptionExtension({
    encryptionKey: "k1.aesgcm256.DbQoar8ZLuUsOHZNyrnjlskInHDYlzF3q6y1KGM7DUM=",
  })
);

const app = express();

const server = app.listen(3000, function () {
  console.log("start server");
});

// data are decrypted when using normal query
app.get("/userposts1", async (req, res, next) => {
  const user = await client.user.findFirst();
  const authorId = user?.id || 1;
  const posts = await client.post.findMany({
    where: {
      authorId: authorId,
    },
  });
  console.log(posts);
  res.send(posts);
});

// data are not decrypted when using fluent API
app.get("/userposts2", async (req, res, next) => {
  const posts = await client.user.findFirst().posts();
  console.log(posts);
  res.send(posts);
});
@franky47
Copy link
Member

Thanks for the reproduction repo, I'll have a look.

In the mean time, what do the debug logs say when you hit the fluent endpoint?

DEBUG="prisma-field-encryption:*" node your-server.js

@hightail191
Copy link
Author

hightail191 commented Aug 30, 2023

Thank you for your reply.
This is my debug logs when I hit fluent endpoint.

debug logs

2023-08-30T17:24:19.777Z prisma-field-encryption:encryption Clear-text input: {
args: { select: { posts: true } },
model: 'User',
action: 'findFirst',
dataPath: [],
runInTransaction: false
}
2023-08-30T17:24:19.779Z prisma-field-encryption:encryption Encrypted input: {
args: { select: { posts: true } },
model: 'User',
action: 'findFirst',
dataPath: [],
runInTransaction: false
}
2023-08-30T17:24:19.785Z prisma-field-encryption:decryption Raw result from database: [
{
id: 5,
title: 'Post1',
content: 'v1.aesgcm256.2fc1baee.BYsfYrU7k6ppBv0t.n_MIe9lb-jpIveEs3jfRVH2LJGxU4pvvvqECrFg=',
published: false,
authorId: 5
},
{
id: 6,
title: 'Post2',
content: 'v1.aesgcm256.2fc1baee.srH0TPxsXRm2DDz2.2U9FRykgqty9jiIlGQTLFlnA_EWRysmhUW41oSs=',
published: false,
authorId: 5
}
]
2023-08-30T17:24:19.787Z prisma-field-encryption:decryption Decrypted result: [
{
id: 5,
title: 'Post1',
content: 'v1.aesgcm256.2fc1baee.BYsfYrU7k6ppBv0t.n_MIe9lb-jpIveEs3jfRVH2LJGxU4pvvvqECrFg=',
published: false,
authorId: 5
},
{
id: 6,
title: 'Post2',
content: 'v1.aesgcm256.2fc1baee.srH0TPxsXRm2DDz2.2U9FRykgqty9jiIlGQTLFlnA_EWRysmhUW41oSs=',
published: false,
authorId: 5
}
]

@franky47
Copy link
Member

franky47 commented Aug 30, 2023

Thanks, I think I have an idea of what is going on.

The query coming into the extension asks for a user, with included posts:

{
  args: { select: { posts: true } },
  model: 'User',
  action: 'findFirst',
  dataPath: [],
  runInTransaction: false
}

However, the data coming back from the database (or rather from the client engine doing its thing) is a list of Posts:

[
  {
    id: 5,
    title: 'Post1',
    content: 'v1.aesgcm256.2fc1baee.BYsfYrU7k6ppBv0t.n_MIe9lb-jpIveEs3jfRVH2LJGxU4pvvvqECrFg=',
    published: false,
    authorId: 5
  },
  {
    id: 6,
    title: 'Post2',
    content: 'v1.aesgcm256.2fc1baee.srH0TPxsXRm2DDz2.2U9FRykgqty9jiIlGQTLFlnA_EWRysmhUW41oSs=',
    published: false,
    authorId: 5
  }
]

This throws the decryption engine off which was expecting a User model, with some connections to a list of Posts, not the posts themselves.

Since Prisma does this downstream and doesn't give us any info of this change (neither from the input arguments nor from the returned data), I don't see how we can handle this and differenciate it from a regular (non-Fluent) call.

@franky47
Copy link
Member

FYI, I have opened a discussion about this behaviour on the Prisma repo: prisma/prisma#20901

@franky47 franky47 changed the title Prisma fluent API not decrypt data Doesn't work with the Prisma fluent API Aug 30, 2023
franky47 added a commit that referenced this issue Aug 30, 2023
Test checks that it isn't actually supported.

See #80.
@hightail191
Copy link
Author

Thank you very much. I don't have any idea about solving this problem because there is no information on the Internet.
OK. I 'll follow the discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants