import {test} from 'node:test';import assert from 'node:assert/strict';import vm from 'node:vm';import {readFileSync} from 'node:fs';import {PGlite} from '@electric-sql/pglite'; const code=readFileSync(new URL('../cloud/account-security.js',import.meta.url),'utf8'); test('旧密码只允许显式首次迁移,已重置和历史不明账号拒绝且不调用旧系统',async()=>{ for(const state of [{},{legacyPasswordMigrationAllowed:false},{legacyPasswordMigrationAllowed:true,passwordResetRequired:true}]){ let verified=0,saved=0;const c=vm.createContext({migratedLoginTarget:async()=>({get:k=>state[k],save:async()=>saved++}),verifyLegacyPassword:async()=>verified++,fail:(status,msg)=>{throw Error(msg)}});vm.runInContext(code,c);await assert.rejects(c.migrateLegacyLogin('a','old'),/密码错误/);assert.equal(saved,0);assert.equal(verified,0); } }); test('一次性迁移核对身份并携带验证前密码版本,不能切换账号',async()=>{ const v={legacyPasswordMigrationAllowed:true,credentialRevision:3,username:'a'},sets={};const target={id:'a',get:k=>v[k],set:(k,x)=>sets[k]=x,setPassword:x=>sets.password=x,save:async()=>{}}; const c=vm.createContext({migratedLoginTarget:async()=>target,verifyLegacyPassword:async()=>({}),Parse:{User:{logIn:async()=>({ok:true})}},fail:(_,m)=>{throw Error(m)}});vm.runInContext(code,c);await c.migrateLegacyLogin('a','old');assert.equal(sets.credentialExpectedRevision,3);assert.equal(sets.credentialMigrationAttempt,true); let calls=0;c.migratedLoginTarget=async()=>++calls===1?target:{...target,id:'b'};await assert.rejects(c.migrateLegacyLogin('a','old'),/验证未通过/); }); test('数据库密码变化原子关闭回退、撤销会话,拒绝并发旧版本及客户端重新启用',async()=>{ const db=new PGlite();try{await db.exec(`CREATE TABLE "_User"("objectId" text primary key,company text,"_hashed_password" text,"createdAt" timestamptz default now());CREATE TABLE "_Session"("user" text);`);await db.exec(readFileSync(new URL('../sql/account-security.sql',import.meta.url),'utf8'));await db.exec(`INSERT INTO "_User"("objectId",company,"_hashed_password","legacyPasswordMigrationAllowed") VALUES('u','co','random',true);`);const one=async()=> (await db.query(`SELECT * FROM "_User"`)).rows[0];assert.equal((await one()).legacyPasswordMigrationAllowed,false);await db.query('SELECT xs_enable_initial_legacy_login($1,$2)',['co','u']);await db.exec(`INSERT INTO "_Session" VALUES('u');UPDATE "_User" SET "_hashed_password"='new',"passwordResetRequired"=true WHERE "objectId"='u';`);assert.equal((await one()).credentialRevision,1);assert.equal((await one()).legacyPasswordMigrationAllowed,false);assert.equal((await db.query('SELECT * FROM "_Session"')).rows.length,0);await assert.rejects(db.exec(`UPDATE "_User" SET "_hashed_password"='old',"credentialExpectedRevision"=0,"credentialMigrationAttempt"=true`),/密码已更新/);await assert.rejects(db.exec(`UPDATE "_User" SET "legacyPasswordMigrationAllowed"=true`),/禁止/);await assert.rejects(db.query('SELECT xs_enable_initial_legacy_login($1,$2)',['co','u']),/不符合/);assert.equal((await one())._hashed_password,'new');}finally{await db.close();} });