Skip to content

Commit 831557c

Browse files
feat: welcome.html is auth-aware (completes MVP) (#19)
The welcome page now reflects sign-in state instead of looking identical regardless of whether the user is authenticated. Behaviour change on first paint: Signed out (unchanged from before): - "Sign in" button revealed by HEAD probe to /idp/register - "Default sign-in: me / me" credentials block visible - Tiles probed with plain fetch — /private/, /inbox/, /settings/ 401 → dimmed and rerouted to /signin.html Signed in (new): - "Sign in" button stays hidden - Credentials block hidden (the user has already climbed past it) - Green "signed in as <webid>" note pointing to /account.html - All tiles probed via session.authFetch — DPoP-bound bearer attached, /private/ etc. return 200 → tiles stay lit and navigate correctly Implementation: solid-oidc imported as an ES module, same version-pinned jsdelivr URL as the other auth-aware pages. session.restore() on load decides which branch to render. The familiar "Missing refresh data" throw on a clean first visit is caught and treated as "not signed in." Locked-tile fallback link changed from ./idp (which 403s in single-user mode) to ./signin.html (which actually starts a flow). Bumps jspod to 0.0.21. Refs #1
1 parent fbb3d28 commit 831557c

2 files changed

Lines changed: 83 additions & 29 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jspod",
3-
"version": "0.0.20",
3+
"version": "0.0.21",
44
"description": "JavaScript Solid Pod - Just works, batteries included",
55
"type": "module",
66
"main": "index.js",

welcome.html

Lines changed: 82 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
.btn-secondary{background:#fff;color:#222;border-color:#ddd}
2222
.btn-secondary:hover{background:#f0efeb}
2323
[hidden]{display:none!important}
24+
.signed-in-note{background:#e8f5e9;color:#1b5e20;padding:.6em 1em;border-radius:8px;margin:1em 0;font-size:.95em}
2425
.dirs{list-style:none;padding:0;margin:1em 0 0;display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:.5em}
2526
.dirs li a{display:block;padding:.7em .9em;background:#f3eee5;border-radius:8px;color:#222}
2627
.dirs li a:hover{background:#ebe5d8}
@@ -40,11 +41,15 @@ <h1>Your Solid pod</h1>
4041
<a href="./idp/register" class="btn btn-secondary" data-cond="register" hidden>Sign up</a>
4142
</div>
4243

43-
<div class="creds">
44+
<div class="creds" id="creds-block">
4445
<span class="label">Default sign-in:</span> me <span class="label">/</span> me
4546
</div>
4647

47-
<p>Then point a Solid app (e.g. <a href="https://solid-apps.github.io/pilot/">Pilot</a>) at this server and sign in. Or explore your pod directly:</p>
48+
<p id="signed-in-note" class="signed-in-note" hidden>
49+
You're signed in as <strong id="signed-in-webid">me</strong>. Visit your <a href="./account.html">account</a> to manage password, sign out, etc.
50+
</p>
51+
52+
<p id="explore-hint">Then point a Solid app (e.g. <a href="https://solid-apps.github.io/pilot/">Pilot</a>) at this server and sign in. Or explore your pod directly:</p>
4853

4954
<ul class="dirs">
5055
<li><a href="./profile/">📇 /profile/</a></li>
@@ -57,36 +62,85 @@ <h1>Your Solid pod</h1>
5762
<footer>Powered by <a href="https://github.com/JavaScriptSolidServer/jspod">jspod</a></footer>
5863
</div>
5964

60-
<script>
61-
(function(){
62-
// Render the server URL the visitor actually used
63-
var el=document.getElementById('server-url');
64-
if(!el)return;
65-
el.textContent=el.href=new URL('./',window.location.href).href;
66-
})();
67-
(function(){
68-
// HEAD-adaptive Sign in / Sign up — same contract as JSS's default
69-
fetch('./idp/register',{method:'HEAD',cache:'no-store'}).then(function(res){
70-
var r=document.querySelector('[data-cond="register"]'),l=document.querySelector('[data-cond="login"]');
71-
if(res.status===200){if(r)r.hidden=false;if(l)l.hidden=false;}
72-
else if(res.status===403){if(l)l.hidden=false;}
73-
}).catch(function(){});
65+
<script type="module">
66+
import Session from 'https://cdn.jsdelivr.net/npm/solid-oidc@0.0.8/solid-oidc.js';
67+
68+
// Render the server URL the visitor actually used
69+
(function () {
70+
const el = document.getElementById('server-url');
71+
if (!el) return;
72+
el.textContent = el.href = new URL('./', window.location.href).href;
7473
})();
75-
(function(){
76-
// Probe each directory tile. If unauthenticated (401/403), dim it
77-
// and redirect its click to the sign-in flow instead of letting the
78-
// browser navigate into a blank 401 response body.
79-
document.querySelectorAll('.dirs a').forEach(function(a){
80-
var href=a.getAttribute('href');
81-
fetch(href,{method:'HEAD',cache:'no-store'}).then(function(res){
82-
if(res.status===401||res.status===403){
74+
75+
const credsBlock = document.getElementById('creds-block');
76+
const exploreHint = document.getElementById('explore-hint');
77+
const signedInNote = document.getElementById('signed-in-note');
78+
const signinBtn = document.querySelector('[data-cond="login"]');
79+
const signupBtn = document.querySelector('[data-cond="register"]');
80+
81+
// Try to restore a prior session. The same "Missing refresh data"
82+
// catch as on the other pages: a clean first visit throws, we
83+
// treat that as "not signed in" and fall through to the unauth UI.
84+
let session = null;
85+
let active = false;
86+
try {
87+
session = new Session();
88+
await session.restore();
89+
active = session.isActive;
90+
} catch {
91+
active = false;
92+
}
93+
94+
if (active && session) {
95+
// Signed-in: hide the sign-in CTAs and the rung-1 hint; show a
96+
// small note about where to manage the session.
97+
if (signinBtn) signinBtn.hidden = true;
98+
if (signupBtn) signupBtn.hidden = true;
99+
if (credsBlock) credsBlock.hidden = true;
100+
if (exploreHint) exploreHint.hidden = true;
101+
if (signedInNote) {
102+
const w = session.webId || 'me';
103+
document.getElementById('signed-in-webid').textContent = w;
104+
signedInNote.hidden = false;
105+
}
106+
107+
// Auth-aware tile probes — use session.authFetch so private dirs
108+
// unlock when we actually have access.
109+
document.querySelectorAll('.dirs a').forEach((a) => {
110+
const href = a.getAttribute('href');
111+
session.authFetch(href, { method: 'HEAD', cache: 'no-store' }).then((res) => {
112+
if (res.status === 401 || res.status === 403) {
83113
a.classList.add('locked');
84-
a.title='Sign in to view '+href;
85-
a.setAttribute('href','./idp');
114+
a.title = 'No access to ' + href;
115+
a.setAttribute('href', './account.html');
86116
}
87-
}).catch(function(){});
117+
}).catch(() => {});
88118
});
89-
})();
119+
} else {
120+
// Signed-out: original behaviour.
121+
// HEAD-adaptive Sign in / Sign up — same contract as JSS's default.
122+
fetch('./idp/register', { method: 'HEAD', cache: 'no-store' }).then((res) => {
123+
if (res.status === 200) {
124+
if (signupBtn) signupBtn.hidden = false;
125+
if (signinBtn) signinBtn.hidden = false;
126+
} else if (res.status === 403) {
127+
if (signinBtn) signinBtn.hidden = false;
128+
}
129+
}).catch(() => {});
130+
131+
// Plain fetch tile probes — auth-gated tiles 401, get dimmed and
132+
// routed to the sign-in app.
133+
document.querySelectorAll('.dirs a').forEach((a) => {
134+
const href = a.getAttribute('href');
135+
fetch(href, { method: 'HEAD', cache: 'no-store' }).then((res) => {
136+
if (res.status === 401 || res.status === 403) {
137+
a.classList.add('locked');
138+
a.title = 'Sign in to view ' + href;
139+
a.setAttribute('href', './signin.html');
140+
}
141+
}).catch(() => {});
142+
});
143+
}
90144
</script>
91145
</body>
92146
</html>

0 commit comments

Comments
 (0)