Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions account.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Your account — Solid pod</title>
<style>
body{font:14px/1.6 system-ui,-apple-system,sans-serif;color:#222;background:#f3eee5;max-width:680px;margin:2em auto;padding:0 1em}
.card{background:#fff;border-radius:12px;box-shadow:0 2px 12px rgba(0,0,0,.08);padding:1.5em 2em}
h1{margin:0 0 .5em;font-weight:500;font-size:1.8em}
h2{margin:1.5em 0 .25em;font-weight:500;font-size:1.05em;color:#444}
.lede{color:#555;margin:0 0 1em}
.kv{background:#f3eee5;padding:.55em .9em;border-radius:8px;margin:.3em 0;font-family:"SFMono-Regular",Consolas,monospace;font-size:.9em;word-break:break-all}
.kv .label{font-family:system-ui,sans-serif;color:#555;display:inline-block;margin-right:.5em;font-size:.85em}
a{color:#0a66c2;text-decoration:none}
a:hover{text-decoration:underline}
.btn{display:inline-block;padding:.55em 1.2em;border-radius:6px;text-decoration:none;font-size:.95em;border:1px solid transparent;cursor:pointer;background:#0a66c2;color:#fff;font-family:inherit}
.btn:hover{background:#084e96;text-decoration:none}
.btn-secondary{background:#fff;color:#222;border-color:#ddd}
.btn-secondary:hover{background:#f0efeb}
.btn-danger{background:#fff;color:#a00;border-color:#fcc}
.btn-danger:hover{background:#fff0f0}
.actions{margin:.5em 0 0;display:flex;gap:.5em;flex-wrap:wrap}
[hidden]{display:none!important}
.error{background:#fff0f0;color:#a00;padding:.8em 1em;border-radius:8px;margin:1em 0;display:none;font-family:"SFMono-Regular",Consolas,monospace;font-size:.9em;word-break:break-word}
.error.show{display:block}
footer{margin-top:1.5em;padding-top:1em;border-top:1px solid #eee;color:#888;font-size:.85em;text-align:center}
</style>
</head>
<body>
<div class="card">
<h1>Your account</h1>
<p class="lede" id="status">Loading session…</p>

<div id="signed-in" hidden>
<h2>WebID</h2>
<div class="kv"><a id="webid-link" href="#"><span id="webid"></span></a></div>

<h2>Pod</h2>
<div class="kv"><span class="label">URL:</span><span id="pod-url"></span></div>

<h2>Explore</h2>
<div class="actions">
<a class="btn btn-secondary" id="profile-link" href="#">Profile</a>
<a class="btn btn-secondary" href="./public/">/public/</a>
<a class="btn btn-secondary" href="./private/">/private/</a>
<a class="btn btn-secondary" href="./inbox/">/inbox/</a>
<a class="btn btn-secondary" href="./settings/">/settings/</a>
</div>

<h2>Session</h2>
<div class="actions">
<button class="btn btn-danger" id="signout-btn" type="button">Sign out</button>
<a class="btn btn-secondary" href="./">Back to pod</a>
</div>
</div>

<div id="signed-out" hidden>
<p>You're not signed in to this pod.</p>
<div class="actions">
<a class="btn" href="./signin.html">Sign in</a>
<a class="btn btn-secondary" href="./">Back to pod</a>
</div>
</div>

<div class="error" id="error"></div>

<footer>Powered by <a href="https://github.com/JavaScriptSolidServer/jspod">jspod</a> · <a href="https://github.com/JavaScriptSolidServer/solid-oidc">solid-oidc</a></footer>
</div>
<script type="module">
import Session from 'https://cdn.jsdelivr.net/npm/solid-oidc@0.0.8/solid-oidc.js';

const statusEl = document.getElementById('status');
const errorEl = document.getElementById('error');
const signedInEl = document.getElementById('signed-in');
const signedOutEl = document.getElementById('signed-out');

function fail(msg) {
statusEl.style.display = 'none';
errorEl.textContent = msg;
errorEl.classList.add('show');
}

try {
const session = new Session();
let active = false;
try {
await session.restore();
active = session.isActive;
} catch {
active = false;
}

statusEl.style.display = 'none';

if (active) {
const podUrl = new URL('./', window.location.href).href;
const webid = session.webId || '(unknown)';
document.getElementById('webid').textContent = webid;
document.getElementById('webid-link').href = webid;
document.getElementById('pod-url').textContent = podUrl;
// Profile link strips the fragment (WebID typically ends with #me)
document.getElementById('profile-link').href = webid.replace(/#.*/, '');
signedInEl.hidden = false;
document.getElementById('signout-btn').addEventListener('click', async () => {
try {
await session.logout();
window.location.href = './';
} catch (e) {
fail('Sign-out failed: ' + (e.message || String(e)));
}
});
} else {
signedOutEl.hidden = false;
}
} catch (e) {
fail(e && e.message ? e.message : String(e));
}
</script>
</body>
</html>
23 changes: 23 additions & 0 deletions account.html.acl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"@context": {
"acl": "http://www.w3.org/ns/auth/acl#",
"foaf": "http://xmlns.com/foaf/0.1/"
},
"@graph": [
{
"@id": "#public",
"@type": "acl:Authorization",
"acl:agentClass": {
"@id": "foaf:Agent"
},
"acl:accessTo": {
"@id": "./account.html"
},
"acl:mode": [
{
"@id": "acl:Read"
}
]
}
]
}
11 changes: 11 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,17 @@ ready.then((ok) => {
const signinAclDst = join(options.root, 'signin.html.acl');
if (existsSync(signinAclSrc)) copyFileSync(signinAclSrc, signinAclDst);

// account.html — post-sign-in dashboard. Same overwrite + public-
// read pattern as signin.html. Both pages render their useful
// state from a restored solid-oidc session; signed-out visitors
// see a "sign in" prompt rather than a blank page.
const acctSrc = join(__dirname, 'account.html');
const acctDst = join(options.root, 'account.html');
if (existsSync(acctSrc)) copyFileSync(acctSrc, acctDst);
const acctAclSrc = join(__dirname, 'account.html.acl');
const acctAclDst = join(options.root, 'account.html.acl');
if (existsSync(acctAclSrc)) copyFileSync(acctAclSrc, acctAclDst);

const linksSrc = join(__dirname, 'links.jsonld');
const linksDst = join(options.root, 'public', 'links.jsonld');
if (existsSync(linksSrc) && !existsSync(linksDst)) {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jspod",
"version": "0.0.17",
"version": "0.0.18",
"description": "JavaScript Solid Pod - Just works, batteries included",
"type": "module",
"main": "index.js",
Expand All @@ -14,6 +14,8 @@
"welcome.html",
"signin.html",
"signin.html.acl",
"account.html",
"account.html.acl",
"links.jsonld"
],
"scripts": {
Expand Down
4 changes: 2 additions & 2 deletions signin.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ <h1 id="title">Signing in…</h1>
await session.handleRedirectFromLogin();
titleEl.textContent = 'Signed in';
ledeEl.textContent = 'WebID: ' + (session.webId || '(none)') + '. Redirecting…';
setTimeout(() => { window.location.href = './'; }, 800);
setTimeout(() => { window.location.href = './account.html'; }, 800);
} else {
// Try to restore a prior session. solid-oidc throws "Missing
// refresh data" on a clean first visit — that's fine, it just
Expand All @@ -86,7 +86,7 @@ <h1 id="title">Signing in…</h1>
if (restored) {
titleEl.textContent = 'Already signed in';
ledeEl.textContent = 'WebID: ' + session.webId + '. Redirecting…';
setTimeout(() => { window.location.href = './'; }, 400);
setTimeout(() => { window.location.href = './account.html'; }, 400);
} else {
await session.login(idp, redirectUri);
}
Expand Down
1 change: 1 addition & 0 deletions welcome.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ <h1>Your Solid pod</h1>

<div class="actions">
<a href="./signin.html" class="btn btn-primary" data-cond="login" hidden>Sign in</a>
<a href="./account.html" class="btn btn-secondary">Account</a>
<a href="./idp/register" class="btn btn-secondary" data-cond="register" hidden>Sign up</a>
</div>

Expand Down