67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import {
|
|
boolean,
|
|
index,
|
|
pgEnum,
|
|
pgTable,
|
|
timestamp,
|
|
uuid,
|
|
varchar,
|
|
} from "drizzle-orm/pg-core";
|
|
import { pgpEncrypted, withAutomaticPgpDecrypt } from "./pgp";
|
|
|
|
export const userStatus = pgEnum("user_status", [
|
|
"active",
|
|
"verification",
|
|
"suspended",
|
|
"pending",
|
|
"deleted",
|
|
]);
|
|
|
|
export const users = pgTable(
|
|
"users",
|
|
{
|
|
uuid: uuid().primaryKey().defaultRandom(),
|
|
status: userStatus("status").default("pending").notNull(),
|
|
|
|
// Données Personnelles (PII) - Chiffrées nativement
|
|
email: pgpEncrypted("email").notNull(),
|
|
emailHash: varchar("email_hash", { length: 64 }).notNull().unique(), // Indexé pour recherche rapide et unicité
|
|
displayName: varchar("display_name", { length: 32 }),
|
|
|
|
username: varchar("username", { length: 32 }).notNull().unique(),
|
|
passwordHash: varchar("password_hash", { length: 95 }).notNull(),
|
|
|
|
// Sécurité
|
|
twoFactorSecret: pgpEncrypted("two_factor_secret"),
|
|
isTwoFactorEnabled: boolean("is_two_factor_enabled").notNull().default(false),
|
|
|
|
// RGPD & Conformité
|
|
termsVersion: varchar("terms_version", { length: 16 }), // Version des CGU acceptées
|
|
privacyVersion: varchar("privacy_version", { length: 16 }), // Version de la Privacy Policy acceptée
|
|
gdprAcceptedAt: timestamp("gdpr_accepted_at", { withTimezone: true }),
|
|
|
|
// Dates de cycle de vie (Standards Entreprise)
|
|
lastLoginAt: timestamp("last_login_at", { withTimezone: true }),
|
|
createdAt: timestamp("created_at", { withTimezone: true })
|
|
.notNull()
|
|
.defaultNow(),
|
|
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
.notNull()
|
|
.defaultNow(),
|
|
deletedAt: timestamp("deleted_at", { withTimezone: true }), // Soft delete (Droit à l'oubli)
|
|
},
|
|
(table) => ({
|
|
uuidIdx: index("users_uuid_idx").on(table.uuid),
|
|
emailHashIdx: index("users_email_hash_idx").on(table.emailHash),
|
|
usernameIdx: index("users_username_idx").on(table.username),
|
|
statusIdx: index("users_status_idx").on(table.status),
|
|
}),
|
|
);
|
|
|
|
// Application du déchiffrement automatique pour les colonnes PGP
|
|
withAutomaticPgpDecrypt(users.email);
|
|
withAutomaticPgpDecrypt(users.twoFactorSecret);
|
|
|
|
export type UserInDb = typeof users.$inferSelect;
|
|
export type NewUserInDb = typeof users.$inferInsert;
|