feat: add PGP encryption utilities with automatic decryption support
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:
60
backend/src/database/schemas/pgp.ts
Normal file
60
backend/src/database/schemas/pgp.ts
Normal 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>;
|
||||
}
|
||||
Reference in New Issue
Block a user