Files
CommunitySolidServer/templates/identity/account/resource.html.ejs
Joachim Van Herwegen a47f5236ef feat: Full rework of account management
Complete rewrite of the account management and related systems.
Makes the architecture more modular,
allowing for easier extensions and configurations.
2023-10-06 11:04:40 +02:00

142 lines
5.5 KiB
Plaintext

<h1>Your account</h1>
<p class="error" id="error"></p>
<div id="logins">
<h2>Logins</h2>
<p>The login methods that can be used to identify as this account.</p>
<div id="loginEntries"></div>
</div>
<div id="pods">
<h2>Pods</h2>
<p>The pods created by this account.</p>
<a id="createPod" href="" class="link">Create pod</a>
<ul id="podEntries"></ul>
</div>
<div id="webIds">
<h2>Registered Web IDs</h2>
<p>
These are the WebIDs you can authenticate as using this account.
These WebIDs also have full control access to the pods registered for this account.
</p>
<a id="linkWebId" href="" class="link">Link WebID</a>
<ul id="webIdEntries"></ul>
</div>
<div id="clientCredentials">
<h2>Credential tokens</h2>
<p>The tokens created by this account.</p>
<a id="createCredentials" href="" class="link">Create token</a>
<ul id="clientCredentialsEntries"></ul>
</div>
<p class="actions">
<button class="hidden" type="button" id="oidc">Continue authentication</button>
<button type="button" id="logout" name="logout">Log out</button>
</p>
<script>
const elements = getElements('loginEntries', 'podEntries', 'webIdEntries', 'clientCredentialsEntries', 'oidc', 'logout');
// Retrieve and display client information
(async() => {
const json = await fetchJson('', '<%= idpIndex %>');
// Button to continue OIDC session if there is one,
// in case someone needed to create/update the account during a session.
setVisibility('oidc', <%= authenticating %>);
elements.oidc.addEventListener('click', async() => {
const body = await fetchJson(json.controls.oidc.prompt);
location.href = body.location;
});
elements.logout.addEventListener('click', async() => {
await fetch(json.controls.account.logout, { method: 'POST' });
location.href = json.controls.html.main.login;
});
// Add data for all login options
for (const loginMethod of Object.keys(json.logins)) {
const url = json.controls.html[loginMethod]?.create;
elements.loginEntries.insertAdjacentHTML('beforeend', `<h3>${loginMethod}</h3>`);
// Making the assumption here that login controls use the same keys as those in the account and have an HTML create control
if (url) {
elements.loginEntries.insertAdjacentHTML('beforeend', `<a href="${url}">Add login</a>`);
}
const ul = document.createElement('ul');
elements.loginEntries.append(ul);
showAccountInfo(ul, loginMethod, json.logins, true, true,
'Are you sure you want to delete this login method? This will prevent you from logging in to your account with these credentials.');
}
// Update pod entries
if (!json.controls.html.account.createPod && Object.keys(json.pods).length === 0) {
setVisibility('pods', false);
} else {
updateElement('createPod', json.controls.html.account.createPod, { href: true });
showAccountInfo(elements.podEntries, 'pods', json, false, false);
}
// Update WebID entries
if (!json.controls.html.account.linkWebId && Object.keys(json.webIds).length === 0) {
setVisibility('webIds', false);
} else {
updateElement('linkWebId', json.controls.html.account.linkWebId, { href: true });
showAccountInfo(elements.webIdEntries, 'webIds', json, false, true,
'Are you sure you want to delete the registration of this WebID? ' +
'If you do so you will be unable to identify as this WebID using this server, which can potentially cause you to lose access to data restricted to this WebID.',
'Make sure to remove the relevant solid:oidcIssuer triple from the WebID to prevent existing access tokens from still being used.');
}
// Update Client Credentials entries
if (!json.controls.html.account.createClientCredentials && Object.keys(json.clientCredentials).length === 0) {
setVisibility('clientCredentials', false);
} else {
// Initial boolean is so the create button gets hidden if the account has no WebIDs.
// Currently, this does not get updated if the last WebID gets deleted, until the page is refreshed.
updateElement('createCredentials', Object.keys(json.webIds).length && json.controls.html.account.createClientCredentials, { href: true });
showAccountInfo(elements.clientCredentialsEntries, 'clientCredentials', json, false, true,
'Are you sure you want to delete this token? This will prevent this token from being used in the future.');
}
})();
// Adds account info to the UI
function showAccountInfo(rootElement, label, data, addLink, addDel, confirmMsg, finishMsg) {
for (const [ key, url ] of Object.entries(data[label])) {
const li = document.createElement('li');
if (addLink) {
li.insertAdjacentHTML('beforeend', `<a href="${url}">${key}</a>`);
} else {
li.append(key);
}
if (addDel) {
const del = document.createElement('a');
del.innerText = '(delete)';
del.href = '#';
del.addEventListener('click', async() => {
if (!confirm(confirmMsg)) {
return;
}
// Delete resource, show error if this fails
const res = await fetch(url, { method: 'DELETE' });
if (res.status >= 400) {
const error = await res.json();
setError(error.message);
} else {
li.remove();
if (finishMsg) {
setError(finishMsg);
}
}
});
li.append(' ');
li.append(del);
}
rootElement.append(li);
}
}
</script>