feat(admin): remember login for 90 days and support REG SSH limits
deploy-preland / deploy zoomstage.online (push) Successful in 57s

This commit is contained in:
Panfilov Konstantin committed 2026-10-25 19:17:51 +03:00
1 parent d04b40519e
commit 522aaf8554
13 files changed
+316 -27

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
/* preland#22/comment3770. Real local Docker HTTP + persistent Chromium profile.
* Cookie values/passwords are never written to evidence. */
const {chromium}=require('playwright-core');
const assert=require('node:assert/strict');
const fs=require('node:fs');const os=require('node:os');const path=require('node:path');
(async()=>{
const profile=fs.mkdtempSync(path.join(os.tmpdir(),'preland-remember-'));
const origin=process.env.ADMIN_URL||'http://admin',output=process.env.UI_OUTPUT||'/tmp';
const launch=()=>chromium.launchPersistentContext(profile,{executablePath:process.env.CHROMIUM_PATH||'/usr/bin/chromium',args:['--no-sandbox'],baseURL:origin,viewport:{width:1440,height:1000}});
let context=await launch();const errors=[];let page=await context.newPage();page.on('pageerror',e=>errors.push(e.message));
try{
await page.goto(origin);
const remember=page.getByLabel('Запомнить меня на 90 дней',{exact:true});
assert.equal(await remember.count(),1,'remember checkbox exists');assert.equal(await remember.isChecked(),false,'unchecked HTML default');
await page.getByLabel('Логин',{exact:true}).fill(process.env.ADMIN_USER||'admin');await page.getByLabel('Пароль',{exact:true}).fill(process.env.ADMIN_PASSWORD||'test-password');await remember.check();
const loginRequest=page.waitForRequest(r=>r.url().endsWith('/api/login')&&r.method()==='POST');await page.getByRole('button',{name:'Войти',exact:true}).click();assert.equal((await loginRequest).postDataJSON().remember,true,'explicit boolean true');
await page.locator('#workspace').waitFor({state:'visible'});
const cookies=await context.cookies(origin),now=Date.now()/1000;
const durable=cookies.find(c=>process.env.REMEMBER_COOKIE?c.name===process.env.REMEMBER_COOKIE:c.httpOnly&&c.expires>now+86400*60);
assert.ok(durable,'persistent HttpOnly remember cookie');assert.ok(Math.abs((durable.expires-now)-90*86400)<600,'expires approximately 90 days');assert.equal(durable.httpOnly,true);assert.equal(durable.sameSite,'Strict');
const target=process.env.TARGET_ID||'a';
const read=async()=>{const r=await page.request.get('/api/config?target='+target).then(r=>r.json());assert.ok(r.ok,r.error);return r;};const before=await read();
assert.ok(Array.isArray(before.config.requisites)&&before.config.requisites.length,'fixture requisites required');
await page.locator('#overview-table tr[data-overview-extra=requisites]').getByText(before.config.requisites[0],{exact:false}).first().waitFor();
await page.locator('#source-target').selectOption(target);await page.getByLabel('Основной сайт',{exact:true}).waitFor();
assert.equal(await page.locator('#config-fields').getByLabel('Реквизиты',{exact:true}).count(),0,'requisites editor hidden');
assert.equal(await page.locator('#config-fields input[aria-label^="Применить поле requisites"]').count(),0,'requisites absent from editable fields');
await page.getByRole('button',{name:'Выбрать все поля формы',exact:true}).click();assert.doesNotMatch(await page.locator('#change-summary').innerText(),/requisites/);await page.getByRole('button',{name:'Снять выбор полей',exact:true}).click();
const after=await read();assert.equal(after.version,before.version);assert.deepEqual(after.config,before.config,'runtime unchanged');
await page.screenshot({path:output+'/remember-requisites-editor.png',fullPage:true});
await context.close();context=await launch();page=await context.newPage();page.on('pageerror',e=>errors.push(e.message));await page.goto(origin);await page.locator('#workspace').waitFor({state:'visible'});assert.equal(await page.locator('#login-panel').isVisible(),false,'reopen authenticates without password');
await page.getByRole('button',{name:'Выйти',exact:true}).click();await page.locator('#login-panel').waitFor({state:'visible'});
await page.getByLabel('Логин',{exact:true}).fill(process.env.ADMIN_USER||'admin');await page.getByLabel('Пароль',{exact:true}).fill(process.env.ADMIN_PASSWORD||'test-password');await page.getByLabel('Запомнить меня на 90 дней',{exact:true}).uncheck();
const shortRequest=page.waitForRequest(r=>r.url().endsWith('/api/login')&&r.method()==='POST');await page.getByRole('button',{name:'Войти',exact:true}).click();assert.equal((await shortRequest).postDataJSON().remember,false,'explicit boolean false');await page.locator('#workspace').waitFor({state:'visible'});
const shortCookies=await context.cookies(origin);assert.ok(!shortCookies.some(c=>c.name===durable.name&&c.expires>Date.now()/1000+86400),'unchecked login does not retain 90-day cookie');
assert.deepEqual(errors,[]);fs.writeFileSync(output+'/remember-evidence.json',JSON.stringify({cookie:{name:durable.name,expires:durable.expires,httpOnly:durable.httpOnly,sameSite:durable.sameSite,secure:durable.secure},configVersion:after.version,pageErrors:errors,reopenAuthenticated:true,uncheckedRememberFalse:true},null,2));
console.log('PASS actual remember90 checkbox/boolean/cookie/persistent reopen + session login + readonly requisites/overview/config unchanged');
}finally{await context.close();}
})().catch(error=>{console.error(error);process.exit(1);});