Files
memegoat/backend/src/database/schemas/users.ts
Avnyr dbfd14b57a
Some checks failed
Backend Tests / test (push) Has been cancelled
Lint / lint (push) Has been cancelled
Update user schema: modify password_hash to varchar(95)
2026-01-14 20:12:32 +01:00

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;