feat: add PGP encryption utilities with automatic decryption support
Some checks failed
Lint / lint (push) Has been cancelled
Backend Tests / test (push) Successful in 9m39s

Introduce modular PGP encryption utilities (`pgpEncrypted` type) for seamless handling of sensitive data in Postgres. Added utility `withAutomaticPgpDecrypt` to enable automatic decryption for selective columns, simplifying schema definitions.
This commit is contained in:
Mathis HERRIOT
2026-01-08 17:15:34 +01:00
parent a5a8626f5d
commit 9654553940

View File

@@ -0,0 +1,60 @@
import { SQL, sql } from "drizzle-orm";
import { AnyPgColumn, customType } from "drizzle-orm/pg-core";
// Clé de chiffrement PGP récupérée depuis l'environnement
const getPgpKey = () => process.env.PGP_ENCRYPTION_KEY || "default-pgp-key";
/**
* Type personnalisé pour les données chiffrées PGP (stockées en bytea dans Postgres).
* Le chiffrement est géré automatiquement à l'écriture (INSERT/UPDATE) via `toDriver`.
*
* **Pour que le déchiffrement soit automatique à la lecture (SELECT), il faut impérativement utiliser l'utilitaire
* `withAutomaticPgpDecrypt` sur la colonne après la définition de la table. Attention à la consommation CPU et mémoire**
*
* @example
* ```ts
* export const users = pgTable('users', {
* email: pgpEncrypted('email').notNull(),
* });
*
* // Activation du déchiffrement automatique
* withAutomaticPgpDecrypt(users.email);
* ```
*/
export const pgpEncrypted = customType<{ data: string; driverData: Buffer }>({
dataType() {
return "bytea";
},
toDriver(value: string): SQL {
return sql`pgp_sym_encrypt(${value}, ${getPgpKey()})`;
},
fromDriver(value: Buffer | string): string {
if (typeof value === "string") return value;
return value.toString();
},
});
/**
* Utilitaire pour injecter le déchiffrement automatique dans une colonne.
* Modifie la méthode getSQL de la colonne pour inclure pgp_sym_decrypt.
*/
export function withAutomaticPgpDecrypt<T extends AnyPgColumn>(column: T): T {
const originalGetSQL = column.getSQL.bind(column);
column.getSQL = () =>
sql`pgp_sym_decrypt(${originalGetSQL()}, ${getPgpKey()})`.mapWith(column);
return column;
}
/**
* @deprecated Utiliser directement les colonnes de type pgpEncrypted qui gèrent maintenant le chiffrement automatiquement.
*/
export function pgpSymEncrypt(value: string | SQL, key: string | SQL) {
return sql`pgp_sym_encrypt(${value}, ${key})`;
}
/**
* @deprecated Utiliser directement les colonnes de type pgpEncrypted qui gèrent maintenant le déchiffrement automatiquement.
*/
export function pgpSymDecrypt(column: AnyPgColumn, key: string | SQL): SQL<string> {
return sql`pgp_sym_decrypt(${column}, ${key})`.mapWith(column) as SQL<string>;
}