openvibers/openvibe.directory Commits
Establish Directory session on signed-in arrival (#11)
Changes
@@@ -31,7 +31,13 @@ function createApp({store=createStore(),peopleStore=null,auth=createAuth()}={}){app.get('/robots.txt',(_q,r)=>r.type('text').send('User-agent: *\nAllow: /\nSitemap: https://openvibe.directory/sitemap.xml\n'));app.get('/llms.txt',(_q,r)=>r.type('text').send('# OpenVibe.Directory\n\nSource-linked listings with last checked dates.\n\n'+Object.entries(kinds).map(([id,name])=>`- [${name}](https://openvibe.directory/kinds/${id}): ${store.list(id).length} entries`).join('\n')+'\n\nJSON: https://openvibe.directory/api/v1/entries\n'));app.get('/sitemap.xml',(_q,r)=>{const paths=['/',...Object.keys(kinds).map(k=>`/kinds/${k}`),...all().map(v.entryPath)];r.type('application/xml').send('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'+paths.map(p=>`<url><loc>https://openvibe.directory${v.esc(p)}</loc></url>`).join('')+'</urlset>');});-- app.get('/',(q,r)=>r.send(v.page('Directories',v.home(kinds,counts(),all()),'/',[{'@context':'https://schema.org','@type':'WebSite',name:'OpenVibe.Directory',url:'https://openvibe.directory/',potentialAction:{'@type':'SearchAction',target:'https://openvibe.directory/search?q={search_term_string}','query-input':'required name=search_term_string'}}])));++ app.get('/',auth?auth.optionalAuth():(_q,_r,next)=>next(),(q,r)=>{++ r.set('Cache-Control','private, no-store');r.vary('Accept');r.vary('Cookie');++ const browser=/\btext\/html\b/.test(q.get('accept')||'')&&!/bot|crawl|spider|slurp/i.test(q.get('user-agent')||'');++ const guest=/(?:^|;\s*)ov_sso_hint=guest(?:;|$)/.test(q.get('cookie')||'');++ if(auth&&!q.user&&browser&&!guest&&q.query.sso!=='none')return r.redirect(302,'/auth/login?silent=1');++ return r.send(v.page('Directories',v.home(kinds,counts(),all()),'/',[{'@context':'https://schema.org','@type':'WebSite',name:'OpenVibe.Directory',url:'https://openvibe.directory/',potentialAction:{'@type':'SearchAction',target:'https://openvibe.directory/search?q={search_term_string}','query-input':'required name=search_term_string'}}]));++ });app.get('/search',(q,r)=>{const kind=String(q.query.kind||'');if(kind&&!kinds[kind])return r.sendStatus(404);const term=String(q.query.q||'').slice(0,120);const rows=search(term,kind).slice(0,200);r.send(v.page('Search directory',v.listing(kind||'all','Search directory',rows,term),`/search?q=${encodeURIComponent(term)}`));});app.get('/kinds/:kind',(q,r)=>{const kind=q.params.kind;if(!kinds[kind])return r.sendStatus(404);r.send(v.page(kinds[kind],v.listing(kind,kinds[kind],store.list(kind)),q.path));});app.get('/entries/:kind/:slug',(q,r)=>{const e=find(q.params.kind,q.params.slug);if(!e)return r.sendStatus(404);r.vary('Accept');if(q.accepts(['html','text/markdown'])==='text/markdown')return r.type('text/markdown').send(v.markdown(e));r.send(v.page(e.name,v.detail(e),q.path,[{'@context':'https://schema.org','@type':e.kind==='businesses'?'LocalBusiness':e.kind==='people'?'Person':'Thing',name:e.name,description:e.description,url:`https://openvibe.directory${q.path}`,dateModified:e.last_checked,sameAs:e.sources.map(s=>s.url)}]));});@@@ -48,3 +48,20 @@ test('directory and model searches use the shared composer and preserve the kindassert.equal(result.status,200);assert.match(await result.text(),/name="q"[^>]*>Gemini<\/textarea>/);}finally{server.close();}});++test('home silently checks Network only for an unrecognized browser visitor',async()=>{++ const store=createStore({fetchImpl:async()=>({ok:false,status:503})});store.start=()=>{};++ const auth={router:()=>((_q,_r,next)=>next()),optionalAuth:()=>((q,_r,next)=>{if((q.get('cookie')||'').includes('ov_token=known'))q.user={subject_id:'usr_12345678'};next();})};++ const server=createApp({store,auth}).listen(0,'127.0.0.1');await new Promise(resolve=>server.once('listening',resolve));++ const base=`http://127.0.0.1:${server.address().port}`;++ const get=(path,headers)=>fetch(base+path,{headers,redirect:'manual'});++ try{++ let r=await get('/',{accept:'text/html'});assert.equal(r.status,302);assert.equal(r.headers.get('location'),'/auth/login?silent=1');assert.match(r.headers.get('cache-control'),/no-store/);++ for(const [path,headers] of [++ ['/',{accept:'text/html',cookie:'ov_sso_hint=guest'}],++ ['/?sso=none',{accept:'text/html'}],++ ['/',{accept:'text/html',cookie:'ov_token=known'}],++ ['/',{accept:'text/html','user-agent':'A search crawler'}],++ ['/',{accept:'application/json'}],++ ]){r=await get(path,headers);assert.equal(r.status,200,JSON.stringify({path,headers}));}++ }finally{server.close();}++});
@@ -31,7 +31,13 @@ function createApp({store=createStore(),peopleStore=null,auth=createAuth()}={}){
@@ -31,7 +31,13 @@ function createApp({store=createStore(),peopleStore=null,auth=createAuth()}={}){
app.get('/robots.txt',(_q,r)=>r.type('text').send('User-agent: *\nAllow: /\nSitemap: https://openvibe.directory/sitemap.xml\n'));
app.get('/robots.txt',(_q,r)=>r.type('text').send('User-agent: *\nAllow: /\nSitemap: https://openvibe.directory/sitemap.xml\n'));
app.get('/llms.txt',(_q,r)=>r.type('text').send('# OpenVibe.Directory\n\nSource-linked listings with last checked dates.\n\n'+Object.entries(kinds).map(([id,name])=>`- [${name}](https://openvibe.directory/kinds/${id}): ${store.list(id).length} entries`).join('\n')+'\n\nJSON: https://openvibe.directory/api/v1/entries\n'));
app.get('/llms.txt',(_q,r)=>r.type('text').send('# OpenVibe.Directory\n\nSource-linked listings with last checked dates.\n\n'+Object.entries(kinds).map(([id,name])=>`- [${name}](https://openvibe.directory/kinds/${id}): ${store.list(id).length} entries`).join('\n')+'\n\nJSON: https://openvibe.directory/api/v1/entries\n'));
app.get('/sitemap.xml',(_q,r)=>{const paths=['/',...Object.keys(kinds).map(k=>`/kinds/${k}`),...all().map(v.entryPath)];r.type('application/xml').send('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'+paths.map(p=>`<url><loc>https://openvibe.directory${v.esc(p)}</loc></url>`).join('')+'</urlset>');});
app.get('/sitemap.xml',(_q,r)=>{const paths=['/',...Object.keys(kinds).map(k=>`/kinds/${k}`),...all().map(v.entryPath)];r.type('application/xml').send('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'+paths.map(p=>`<url><loc>https://openvibe.directory${v.esc(p)}</loc></url>`).join('')+'</urlset>');});
- app.get('/',(q,r)=>r.send(v.page('Directories',v.home(kinds,counts(),all()),'/',[{'@context':'https://schema.org','@type':'WebSite',name:'OpenVibe.Directory',url:'https://openvibe.directory/',potentialAction:{'@type':'SearchAction',target:'https://openvibe.directory/search?q={search_term_string}','query-input':'required name=search_term_string'}}])));
+ app.get('/',auth?auth.optionalAuth():(_q,_r,next)=>next(),(q,r)=>{
+ r.set('Cache-Control','private, no-store');r.vary('Accept');r.vary('Cookie');
+ const browser=/\btext\/html\b/.test(q.get('accept')||'')&&!/bot|crawl|spider|slurp/i.test(q.get('user-agent')||'');
+ const guest=/(?:^|;\s*)ov_sso_hint=guest(?:;|$)/.test(q.get('cookie')||'');
+ if(auth&&!q.user&&browser&&!guest&&q.query.sso!=='none')return r.redirect(302,'/auth/login?silent=1');
+ return r.send(v.page('Directories',v.home(kinds,counts(),all()),'/',[{'@context':'https://schema.org','@type':'WebSite',name:'OpenVibe.Directory',url:'https://openvibe.directory/',potentialAction:{'@type':'SearchAction',target:'https://openvibe.directory/search?q={search_term_string}','query-input':'required name=search_term_string'}}]));
+ });
app.get('/search',(q,r)=>{const kind=String(q.query.kind||'');if(kind&&!kinds[kind])return r.sendStatus(404);const term=String(q.query.q||'').slice(0,120);const rows=search(term,kind).slice(0,200);r.send(v.page('Search directory',v.listing(kind||'all','Search directory',rows,term),`/search?q=${encodeURIComponent(term)}`));});
app.get('/search',(q,r)=>{const kind=String(q.query.kind||'');if(kind&&!kinds[kind])return r.sendStatus(404);const term=String(q.query.q||'').slice(0,120);const rows=search(term,kind).slice(0,200);r.send(v.page('Search directory',v.listing(kind||'all','Search directory',rows,term),`/search?q=${encodeURIComponent(term)}`));});
app.get('/kinds/:kind',(q,r)=>{const kind=q.params.kind;if(!kinds[kind])return r.sendStatus(404);r.send(v.page(kinds[kind],v.listing(kind,kinds[kind],store.list(kind)),q.path));});
app.get('/kinds/:kind',(q,r)=>{const kind=q.params.kind;if(!kinds[kind])return r.sendStatus(404);r.send(v.page(kinds[kind],v.listing(kind,kinds[kind],store.list(kind)),q.path));});
app.get('/entries/:kind/:slug',(q,r)=>{const e=find(q.params.kind,q.params.slug);if(!e)return r.sendStatus(404);r.vary('Accept');if(q.accepts(['html','text/markdown'])==='text/markdown')return r.type('text/markdown').send(v.markdown(e));r.send(v.page(e.name,v.detail(e),q.path,[{'@context':'https://schema.org','@type':e.kind==='businesses'?'LocalBusiness':e.kind==='people'?'Person':'Thing',name:e.name,description:e.description,url:`https://openvibe.directory${q.path}`,dateModified:e.last_checked,sameAs:e.sources.map(s=>s.url)}]));});
app.get('/entries/:kind/:slug',(q,r)=>{const e=find(q.params.kind,q.params.slug);if(!e)return r.sendStatus(404);r.vary('Accept');if(q.accepts(['html','text/markdown'])==='text/markdown')return r.type('text/markdown').send(v.markdown(e));r.send(v.page(e.name,v.detail(e),q.path,[{'@context':'https://schema.org','@type':e.kind==='businesses'?'LocalBusiness':e.kind==='people'?'Person':'Thing',name:e.name,description:e.description,url:`https://openvibe.directory${q.path}`,dateModified:e.last_checked,sameAs:e.sources.map(s=>s.url)}]));});
@@ -48,3 +48,20 @@ test('directory and model searches use the shared composer and preserve the kind
@@ -48,3 +48,20 @@ test('directory and model searches use the shared composer and preserve the kind
assert.equal(result.status,200);assert.match(await result.text(),/name="q"[^>]*>Gemini<\/textarea>/);
assert.equal(result.status,200);assert.match(await result.text(),/name="q"[^>]*>Gemini<\/textarea>/);
}finally{server.close();}
}finally{server.close();}
});
});
+test('home silently checks Network only for an unrecognized browser visitor',async()=>{
+ const store=createStore({fetchImpl:async()=>({ok:false,status:503})});store.start=()=>{};
+ const auth={router:()=>((_q,_r,next)=>next()),optionalAuth:()=>((q,_r,next)=>{if((q.get('cookie')||'').includes('ov_token=known'))q.user={subject_id:'usr_12345678'};next();})};
+ const server=createApp({store,auth}).listen(0,'127.0.0.1');await new Promise(resolve=>server.once('listening',resolve));
+ const base=`http://127.0.0.1:${server.address().port}`;
+ const get=(path,headers)=>fetch(base+path,{headers,redirect:'manual'});
+ try{
+ let r=await get('/',{accept:'text/html'});assert.equal(r.status,302);assert.equal(r.headers.get('location'),'/auth/login?silent=1');assert.match(r.headers.get('cache-control'),/no-store/);
+ for(const [path,headers] of [
+ ['/',{accept:'text/html',cookie:'ov_sso_hint=guest'}],
+ ['/?sso=none',{accept:'text/html'}],
+ ['/',{accept:'text/html',cookie:'ov_token=known'}],
+ ['/',{accept:'text/html','user-agent':'A search crawler'}],
+ ['/',{accept:'application/json'}],
+ ]){r=await get(path,headers);assert.equal(r.status,200,JSON.stringify({path,headers}));}
+ }finally{server.close();}
+});