32 lines
5.9 KiB
JavaScript
32 lines
5.9 KiB
JavaScript
const {app,BrowserWindow}=require('electron');
|
|
const assert=require('node:assert/strict');
|
|
app.setPath('userData',process.env.SAFETYNET_BOOKMARK_PROFILE);app.setPath('sessionData',process.env.SAFETYNET_BOOKMARK_PROFILE);app.disableHardwareAcceleration();process.env.SAFETYNET_SMOKE_USERDATA=process.env.SAFETYNET_BOOKMARK_PROFILE;
|
|
require('../apps/browser/main.cjs');
|
|
const wait=ms=>new Promise(r=>setTimeout(r,ms)),deadline=setTimeout(()=>app.exit(1),110000);
|
|
app.whenReady().then(async()=>{try{
|
|
let win;for(let i=0;i<150;i++){win=BrowserWindow.getAllWindows()[0];if(win&&!win.webContents.isLoading()&&win.webContents.getURL().endsWith('index.html'))break;await wait(100);}assert.ok(win);
|
|
const call=(name,input)=>win.webContents.executeJavaScript(`window.safetynet[${JSON.stringify(name)}](${JSON.stringify(input)??''})`),state=async()=>(await call('state')).data;
|
|
const result=await call('enroll',{server:process.env.SAFETYNET_BOOKMARK_SERVER,code:process.env.SAFETYNET_BOOKMARK_CODE});assert.equal(result.ok,true,result.error);assert.equal(result.data.ready,true);
|
|
const id=result.data.deviceId,headers={authorization:`Bearer ${process.env.SAFETYNET_BOOKMARK_ADMIN}`,'content-type':'application/json'},base=process.env.SAFETYNET_BOOKMARK_SERVER;
|
|
async function api(route,body,method=body?'POST':'GET'){const r=await fetch(base+route,{method,headers,body:body?JSON.stringify(body):undefined});return {status:r.status,body:await r.json()};}
|
|
async function until(fn){for(let i=0;i<200;i++){if(await fn())return;await wait(100);}throw Error('Bookmark refresh timed out');}
|
|
async function mutate(action,bookmark){for(let i=0;i<20;i++){const s=await state();const r=await call('mutateBookmarks',{action,bookmark,expectedRevision:s.bookmarks.personal.revision,policyVersion:s.policyVersion});if(r.ok)return r;if(!/Management update in progress/.test(r.error||''))return r;await wait(100);}throw Error('Bookmark mutation unavailable');}
|
|
const initial=await state();assert.equal(initial.bookmarks.managed[0].id,'company-intranet');assert.equal(initial.bookmarks.personal.items.length,0);
|
|
assert.equal((await mutate('update',{...initial.bookmarks.managed[0],title:'User tamper'})).ok,false);
|
|
const personal={id:'personal-fixture',title:'Personal work link',url:process.env.SAFETYNET_BOOKMARK_ORIGIN+'personal',folder:'Work'};const added=await mutate('add',personal);assert.equal(added.ok,true,added.error);assert.equal(added.data.policyVersion,initial.policyVersion);assert.equal(added.data.bookmarks.personal.revision,1);
|
|
let adminRead=await api(`/api/admin/devices/${id}/bookmarks`);assert.equal(adminRead.status,200);assert.equal(adminRead.body.items[0].title,personal.title);
|
|
const otherCode=(await api('/api/admin/enrollments',{user:'public-other-user'})).body.code;
|
|
const other=(await api('/api/device/enroll',{code:otherCode,name:'Public other device',platform:'win32'})).body;
|
|
const edited={...personal,title:'Administrator edited work link',url:process.env.SAFETYNET_BOOKMARK_ORIGIN+'admin-edited'};const changed=await api(`/api/admin/devices/${id}/bookmarks`,{expectedRevision:adminRead.body.revision,policyVersion:initial.policyVersion,items:[edited]},'PUT');assert.equal(changed.status,200);
|
|
await until(async()=>{const s=await state();return s.ready&&s.bookmarks.personal.revision===2;});assert.equal((await state()).policyVersion,initial.policyVersion);assert.equal((await state()).bookmarks.personal.items[0].title,edited.title);
|
|
const otherBookmarks=await api(`/api/admin/devices/${other.id}/bookmarks`);assert.equal(otherBookmarks.status,200);assert.deepEqual(otherBookmarks.body.items,[]);assert.equal(otherBookmarks.body.revision,0);
|
|
const ui=await win.webContents.executeJavaScript("({company:document.getElementById('library-company')?.textContent,personal:document.getElementById('library-bookmarks')?.textContent})");assert.ok(JSON.stringify(ui).includes(edited.title),'Live authoritative bookmark missing from UI');
|
|
async function publish(mutator){const current=(await api('/api/admin/overview')).body.policy;mutator(current);current.version++;assert.equal((await api('/api/admin/policy',current,'PUT')).status,200);await until(async()=>{const s=await state();return s.ready&&s.policyVersion===current.version;});return current.version;}
|
|
const lockedVersion=await publish(p=>{p.browser.bookmarks.allowUserAdd=false;p.browser.bookmarks.allowUserEdit=false;p.browser.bookmarks.allowUserDelete=false;});assert.equal((await mutate('update',personal)).ok,false);const s=await state();assert.equal((await call('mutateBookmarks',{action:'delete',id:personal.id,expectedRevision:s.bookmarks.personal.revision,policyVersion:lockedVersion})).ok,false);
|
|
adminRead=await api(`/api/admin/devices/${id}/bookmarks`);assert.equal((await api(`/api/admin/devices/${id}/bookmarks`,{expectedRevision:adminRead.body.revision,policyVersion:lockedVersion,items:[]},'PUT')).status,200);await until(async()=>(await state()).bookmarks.personal.revision===3);
|
|
await publish(p=>p.browser.settings.visible=false);assert.equal((await state()).bookmarks.managed[0].id,'company-intranet','Hiding settings removed required company links');assert.equal((await state()).bookmarks.allowUserAdd,false);
|
|
await publish(p=>p.browser.bookmarks.adminReadUserBookmarks=false);assert.equal((await api(`/api/admin/devices/${id}/bookmarks`)).status,403);assert.equal((await api(`/api/admin/devices/${id}/bookmarks`,{expectedRevision:3,policyVersion:(await state()).policyVersion,items:[personal]},'PUT')).status,403);
|
|
const events=(await api('/api/admin/overview')).body.events;assert.equal(JSON.stringify(events).includes(edited.title),false);assert.equal(JSON.stringify(events).includes(personal.url),false);
|
|
console.log(JSON.stringify({nativeBookmarks:true,managedReadOnly:true,personalRemoteEdit:true,revisionStablePolicy:true,permissionLocks:true}));clearTimeout(deadline);app.quit();
|
|
}catch(error){console.error(JSON.stringify({nativeBookmarks:false,error:error.message}));clearTimeout(deadline);app.exit(1);}});
|