Can we create a process that automatically transforms any integer field into a hashed string?

Is there a non-hacky way to hash all IDs before returning to the user? I have explored the documentation extensively but haven't found a solution that covers all scenarios.

I am working with Postgres and Prisma ORM, managing multiple models with relational fields. Ideally, I want to achieve this using Prisma.

I attempted Jordan's suggestion, resulting in the following code:

const getPrismaClient = () => {
  const client = new PrismaClient();
  client.$extends({
    result: {
      blog: {
        // Creating a virtual `hashedId` field
        hashedId: {
          needs: { id: true },
          compute(client) {
            return intToHashedString(client.id);
          },
        },
      },
    },
  });
  client.blog
    .findMany({
      select: { hashedId: true },
    })
    .then((r) => {
      console.log(r);
    });
  return client;
};

However, it resulted in the following error:

error - unhandledRejection: PrismaClientValidationError: 
Invalid `prisma.blog.findMany()` invocation:
{
  select: {
    hashedId: true,
    ~~~~~~~~
?   id?: true,
?   title?: true,
?   slug?: true,
?   image?: true,
?   description?: true,
?   views?: true,
?   authorId?: true,
  clientVersion: '4.11.0'
}

Answer №1

If you're looking to enhance your Prisma Client results, consider utilizing the Prisma Client results extension (Please note that this feature is still under a feature flag, so proceed with caution).

To get started, enable the feature by adding the following code to your schema.prisma file:

// schema.prisma
generator client {
  provider = "prisma-client-js"
  previewFeatures = ["clientExtensions"]
}

Once enabled, here's an example of how you can implement it:

import { PrismaClient } from '@prisma/client';
import { scrypt } from 'node:crypto';

const prisma = new PrismaClient();

const xprisma = prisma.$extends({
  result: {
    client: {
      // A virtual `hashedId` field is created here
      hashedId: {
        needs: { id: true },
        compute(client: { id: string }) {
          return new Promise<string>((resolve, reject) => {
            // In this example, I used scrypt
            scrypt(client.id, 'salt', 64, (err, hashed) => {
              if (err) return reject(err);
              return resolve(hashed.toString('hex'));
            })
          })
        }
      }
    }
  }
});

//                    ,--- Using xprisma instead of prisma
//                   v
const client = await xprisma.client.findFirst({
  where: { id: '092a5486-9ca2-4c4c-85e6-da7cedb281a5' },
  // Autocomplete for hashedId is available in fields
  select: { hashedId: true },
});

It's important to address performance concerns when implementing this solution, but it should fulfill your requirements.

UPDATE: Remember that prisma.$extends must return a new PrismaClient containing your extensions for successful compilation. This is why I followed the convention of using xprisma.

Answer №2

In the realm of Postgres database management, there exist hashing functions for every data type, though they are not officially documented. These functions are typically safe to use and serve various purposes such as hash partitioning and indexing. When it comes to integers, you can utilize the following functions:

hashint4(int) → int
hashint4extended(int, bigint) → bigint

The latter form, which was introduced in Postgres 12 or later, requires a seed as the second parameter. It generates a larger bigint hash in order to reduce the likelihood of collisions.

If you want to almost guarantee avoidance of hash collisions, consider using the trusty old md5() function, which yields strings consisting of 32 characters – similar to a UUID. For further information, check out:

  • What is the optimal data type for an MD5 field?

Note that md5() operates on text, so if your input is an integer, you'll need to perform a cast. See examples below:

SELECT hashint4(my_id)            AS my_id_int4_hash
     , hashint4extended(my_id, 0) AS my_id_int8_hash
     , hashint4(my_id)            AS my_id_md5_hash
FROM   tbl
LIMIT  10;

If you prefer working with textual results, ensure to cast numeric outcomes to text using ::text.

For additional insights, especially regarding the probability of hash collisions, explore:

  • Why doesn't my UNIQUE constraint trigger?

To streamline your workflow and conserve effort, contemplate creating a (MATERIALIZED) VIEW of your table with hashed values. This approach eliminates repetitive typing and computational tasks, even though the underlying functions exhibit exceptional performance.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transforming Form Input Fields into a Nested JSON Format with the Power of JQuery

I'm facing a challenge in converting the input fields below into a nested JSON file structure in my HTML page. Despite trying various methods, I haven't been successful yet. These inputs are retrieved through AngularJS ng-repeat. Any assistance o ...

Tips for effectively managing relationships in a RESTful API

Exploring the concept of REST architecture through the development of a RESTful service for an 'Issues Tracking Application'. In this application, users, projects, issues, and comments are integral components. The relationships are outlined as f ...

data is currently being uploaded to the storage, however, the grid is not displaying any

After loading JSON data into the store, I am unable to see any data in the grid. Can someone please point out what I might be doing wrong? Here's the code snippet for the grid: { xtype: 'gridpanel', ...

Packing third-party npm modules with Webpack for seamless integration

Description I am currently working on a project that involves nodejs, TypeScript, and express. The source files with a *.ts extension are being bundled using webpack, while the node_modules folder is excluded using webpack-node-externals. However, when I ...

What is the best way to emphasize a div depending on a query outcome?

A new application is in the works for a gaming project. This app is designed to display the location of a specific monster, utilizing a database containing information about monsters and their corresponding maps. Currently, the application functions almos ...

How can we determine the nL and nH values using an ESC/POS command?

Looking to adjust the printer's head position using ESC / pos commands: ESC $ command sets the absolute horizontal position ESC $ nL nH Trying to figure out how to calculate the values for nL and nH? ...

Unable to modify the name of an element's class due to restrictions in JavaScript

I am trying to switch the class of an element from score -box1 to score -box1.-active. I defined a constant $target in order to access the class score -box1, however it is not functioning as expected. const $target = document.getElementByClassname('sc ...

What is the method for incorporating parameters into an array filter?

Imagine having an array containing multiple duplicate objects. How can we create a condition to specifically identify objects with certain criteria, such as matching IDs, duplicate status, and duplicate dates? The goal is to only display the object with th ...

There seems to be an issue with the next function's functionality within a Nodejs middleware

Currently, I am delving into the world of Nodejs with expressjs. My focus is on understanding middleware functions and specifically, the role of "next". In the middleware concept, "next" simply moves on to the next middleware in line. So, what exactly is ...

Updating the row by substituting the content of two columns with the data retrieved from the action class

In my JSP page, there is a table with a refresh button on each row. Upon clicking the refresh button, a JavaScript/AJAX call is made to an action class to retrieve the values of status and number of records for that row, which are then displayed in the cor ...

JavaScript Navigation Bar Error: The value of 'undefined' is not recognized as an object

Having just started learning HTML, CSS, and JavaScript, I encountered an error message that reads: TypeError: 'undefined' is not an object. Despite my best efforts to troubleshoot the issue, I have been unable to resolve it. Is there anyone who c ...

Personalize the Loopback response following a successful save operation

I'm working on a Loopback 2.x application where I have models for Conversations and Messages, with a relationship of "Conversation has many messages." My goal is to receive a customized JSON response for the POST conversations/:id/messages endpoint, r ...

Express.js seems to be having trouble identifying static files

I am facing an issue with my nodejs app using expressjs. I have set up my static directory but it doesn't load when accessed. Here is how my express configuration looks: var app = express.createServer().listen(8001); app.configure(function(){ a ...

executing a series of jQuery ajax calls iteratively

In my Web Application, I have implemented "Spatial Selection" on a map that allows users to select multiple streets. Once selected, each street is assigned a unique Street Id through the use of a "Selection Handler". The next step in the process involves ...

Encountered a problem when incorporating delay functions into redux-saga testing using the Redux Saga Test Plan library

I am facing a challenge while trying to test my redux-saga functions using the Redux Saga Test Plan library. The issue arises due to delay functions present in my saga. All tests pass smoothly without any errors when I remove the line containing yield del ...

Create a custom overlay for an image that is centered horizontally and does not have a fixed width

I'm working with this HTML setup: <div class="container"> <img class="image" /> <div class="overlay"> <div class="insides">more content here</div> </div> &l ...

React does not allow _id to be used as a unique key

When I retrieve the categories from my allProducts array fetched from the database using redux-toolkit, I filter and then slice the array for pagination before mapping over it. However, I keep encountering a warning: Each child in a list should have a un ...

Invoking servlet using Ajax

I have created a JSP file with Javascript functions and AJAX calls to invoke a servlet (ReadprojectInfo). <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE ...

How can you shut down the server in the Express.js library?

Many individuals have attempted to use the .close() method in the Express library, however it appears that this method does not actually exist. ...

ajax is now blocking the use of Window.location

I am facing an issue with window.location while working on an ajax request. Here is the code snippet for my ajax request: function login(){ var u = document.getElementById("username").value; var p = document.getElementById("password").value; ...