security: round 3 hardening (CSRF double-submit, TRX MITM, container hardening)
This commit is contained in:
@@ -20,6 +20,12 @@ export const WalletModel = {
|
||||
return db('wallets').where({ user_id: userId, chain }).first();
|
||||
},
|
||||
|
||||
/**
|
||||
* Insert wallets. UNIQUE(user_id, chain) на уровне DB предотвращает дубликаты —
|
||||
* на конфликт kicks transaction rollback.
|
||||
* Используется только из createWallet (custodial bootstrap, one-shot per user).
|
||||
* НЕ используем upsertMany — нет легитимного пути менять адрес после генерации.
|
||||
*/
|
||||
async createMany(
|
||||
wallets: { user_id: string; chain: string; address: string; derivation_path: string }[],
|
||||
trx?: Knex.Transaction,
|
||||
@@ -27,19 +33,4 @@ export const WalletModel = {
|
||||
const withIds = wallets.map((w) => ({ id: generateUlid(), ...w }));
|
||||
return (trx || db)('wallets').insert(withIds).returning('*');
|
||||
},
|
||||
|
||||
/**
|
||||
* Insert wallets, on conflict (user_id, chain) update address + derivation_path.
|
||||
* Used by POST /api/wallets — клиент шлёт массив адресов после регистрации в BITOK.
|
||||
*/
|
||||
async upsertMany(
|
||||
wallets: { user_id: string; chain: string; address: string; derivation_path: string }[]
|
||||
): Promise<WalletRow[]> {
|
||||
const withIds = wallets.map((w) => ({ id: generateUlid(), ...w }));
|
||||
return db('wallets')
|
||||
.insert(withIds)
|
||||
.onConflict(['user_id', 'chain'])
|
||||
.merge(['address', 'derivation_path'])
|
||||
.returning('*');
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user