47ng/prisma-field-encryption

Hash annotations not doing anything when creating records

JJHDoubleD opened this issue · 3 comments

I've taken the schema straight out of the Readme:

model User {
  id String    @id(map: "user_pk") @unique(map: "user_uid_uindex") @db.Uuid
  email     String @unique /// @encrypted
  emailHash String @unique /// @encryption:hash(email) <- the name of the source field
}

Firstly, when creating a User, if I don't supply a value for the emailHash field it gives a TS error and doesn't compile as emailHash is a required property.

// Error:  Property 'emailHash' is missing
prisma.user.create({
    data: {
      id: 'b0429ab9-1299-474c-b7ba-b7f3176f0ff9',
      email: '1234567',
    //   emailHash: '13',
    },
  });

Secondly, if I do give a value to emailHash, that value gets written to the DB as-is. I.e. if I uncomment the emailHash line the row is created with value 13 in the emailHash column. I've tried making the emailHash column nullable but this didn't change anything.

What's the proper way to use this functionality?

It's only available in the next beta version (1.4.0-beta.4), the readme on GitHub shows what's on the next branch, but you can refer to the readme of your particular installed version on NPM for its documentation.

That being said, the TS error when not supplying the hash field on create is something I should look into. Ideally this field should be left out completely of the associated model, and only used by the middleware.

Makes perfect sense then, I was using 1.3.3, so it would get treated as a regular field, i.e. being included in the Prisma model so of course Prisma would require it when creating a row. If in 1.4.0 you're already using some kind of way to omit the hash column from the types output by Prisma generate, this won't be a problem. If not, I'm not sure if there is a way to do so, if not then maybe the easiest thing would be to instruct users to mark the hash columns as nullable.

Exactly. I've updated the documentation to recommend nullable hash fields.

The @ignore directive on a field can remove it from the Prisma API, but then the middleware doesn't have knowledge of it (it's omitted from the DMMF) and so the feature is not enabled. I don't see a way to remove fields from the user-side of the Prisma API while keeping it internally in the DMMF and within the middleware, unless using forbidden TypeScript black magic.

That being said, hiding it completely may be counterproductive, as it can be useful for GDPR or other privacy laws compliance to limit diffusion of PII (those being the encrypted field).

As an example, instead of verifying an account by its email address directly, I use the email hash field instead, since it's also possible to findUnique({ where: { emailHash: '...' } }).