reproduce-auth.cjs 3.2 KB

12345678910111213141516171819202122
  1. const {chromium}=require(process.env.PLAYWRIGHT_MODULE || 'playwright');const fs=require('fs');const vm=require('vm');
  2. (async()=>{
  3. const source=fs.readFileSync('scripts/deploy-admin-functions.mjs','utf8');const fn=source.split('\n').find(l=>l.startsWith('async function migrateLegacyLogin('));
  4. let resetCalls=0,saves=0,newPassword='new-password-fixture';const values={username:'fixture',passwordResetRequired:true,isDisabled:false,isDeleted:false};
  5. const target={get:k=>values[k],set:(k,v)=>values[k]=v,setPassword:p=>{newPassword=p;resetCalls++},save:async()=>{saves++}};
  6. const context={verifyLegacyPassword:async()=>({retcode:1}),migratedLoginTarget:async()=>target,fieldsOf:async()=>({passwordResetRequired:true}),Parse:{User:{logIn:async()=>({getSessionToken:()=> 'r:local-fixture'})}},fail:(s,m)=>{throw Error(m)}};
  7. vm.createContext(context);vm.runInContext(fn+';globalThis.run=migrateLegacyLogin',context);await context.run('fixture','legacy-password-fixture');
  8. const results={legacyPasswordFallback:{resetCalls,saves,newPasswordOverwritten:newPassword==='legacy-password-fixture',resetRequiredCleared:values.passwordResetRequired===false,mode:'local function with isolated in-memory adapters; no real account touched'}};
  9. const browser=await chromium.launch({headless:true,channel:'chrome'});const page=await browser.newPage({viewport:{width:390,height:844}});let calls=0,held;
  10. await page.route('**/cloud-functions/**',async route=>{calls++;if(route.request().postDataJSON()?.params?.action==='user_get'){held=route;return;}await route.fulfill({json:{retcode:0,result:{}}});});
  11. await page.goto('http://127.0.0.1:4200/pages/member/wxauth');await page.locator('app-login-page').waitFor();
  12. await page.evaluate(()=>{const c=ng.getComponent(document.querySelector('app-login-page'));c.account='local-fixture';c.password='a'.repeat(20);c.privacyChecked=true;c.submit()});
  13. results.longPassword={requestCount:calls,message:await page.locator('body').innerText()};
  14. await page.evaluate(()=>{const c=ng.getComponent(document.querySelector('app-login-page'));c.session.setLogin({userId:20,groupId:1,sessionToken:'r:old-fixture'});c.api.get('user_get').subscribe({error:()=>{}})});
  15. await page.waitForTimeout(100);if(!held)throw Error('No delayed request');
  16. await page.evaluate(()=>{const c=ng.getComponent(document.querySelector('app-login-page'));c.session.setLogin({userId:21,groupId:1,sessionToken:'r:new-fixture'})});
  17. await held.fulfill({status:401,json:{retcode:-1,retmsg:'旧会话已过期'}});await page.waitForTimeout(150);
  18. results.staleSession={stored:await page.evaluate(()=>JSON.parse(localStorage.getItem('xiaoshu.angular.session'))),url:page.url()};
  19. await page.evaluate(()=>localStorage.setItem('xiaoshu.angular.session',JSON.stringify({token:'r:local-fixture',user:{userId:20,groupId:1}})));
  20. await page.goto('http://127.0.0.1:4200/pages/member/acc_destory');await page.getByText('此功能暂未开放,请联系管理员处理。').waitFor();results.accountDeletion={body:await page.locator('body').innerText()};
  21. await browser.close();fs.writeFileSync('docs/qa/launch-audit-2026-10-13/auth-reproduction.json',JSON.stringify(results,null,2));console.log(JSON.stringify(results,null,2));
  22. })().catch(e=>{console.error(e);process.exit(1)});