Files
forkmessager/apps/server/prisma/encrypt-existing.ts
Халимов Рустам b4b4b8e0d3 Original
2026-03-10 21:11:59 +03:00

68 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Migrate existing plain-text messages to encrypted form.
*
* Run once after enabling ENCRYPTION_KEY:
* npx ts-node prisma/encrypt-existing.ts
*
* Safe to re-run — skips already-encrypted messages ("enc:v1:" prefix).
*/
import '../src/config'; // loads .env & initialises encryption
import { PrismaClient } from '@prisma/client';
import { encryptText, isEncryptionEnabled } from '../src/encrypt';
// Use raw PrismaClient to bypass the encryption middleware (avoid double-encryption)
const rawPrisma = new PrismaClient();
async function main() {
if (!isEncryptionEnabled()) {
console.error('❌ ENCRYPTION_KEY не задан в .env — сначала укажите ключ шифрования.');
process.exit(1);
}
console.log('🔒 Начало шифрования существующих сообщений…\n');
// We bypass the Prisma middleware by using $queryRawUnsafe for the SELECT,
// then use raw UPDATE to avoid double-encryption via middleware.
const messages: Array<{ id: string; content: string | null; quote: string | null }> =
await rawPrisma.$queryRaw`
SELECT id, content, quote FROM "Message"
WHERE (content IS NOT NULL AND content != '' AND content NOT LIKE 'enc:v1:%')
OR (quote IS NOT NULL AND quote != '' AND quote NOT LIKE 'enc:v1:%')
`;
console.log(`📝 Найдено ${messages.length} незашифрованных сообщений`);
let encrypted = 0;
const BATCH_SIZE = 500;
for (let i = 0; i < messages.length; i += BATCH_SIZE) {
const batch = messages.slice(i, i + BATCH_SIZE);
await rawPrisma.$transaction(
batch.map((msg) => {
const newContent = msg.content && !msg.content.startsWith('enc:v1:')
? encryptText(msg.content) : null;
const newQuote = msg.quote && !msg.quote.startsWith('enc:v1:')
? encryptText(msg.quote) : null;
return rawPrisma.$executeRaw`
UPDATE "Message"
SET content = COALESCE(${newContent}::text, content),
quote = COALESCE(${newQuote}::text, quote)
WHERE id = ${msg.id}
`;
})
);
encrypted += batch.length;
process.stdout.write(`${encrypted}/${messages.length}\r`);
}
console.log(`\n\n✅ Готово! Зашифровано ${encrypted} сообщений.`);
console.log('⚠ СОХРАНИТЕ КЛЮЧ ENCRYPTION_KEY В НАДЁЖНОМ МЕСТЕ — без него данные не восстановить!');
await rawPrisma.$disconnect();
}
main().catch((e) => {
console.error('Ошибка миграции:', e);
process.exit(1);
});