Skip to content
Open
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
44 changes: 35 additions & 9 deletions copy-pods-to-css.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env node --no-warnings
#!/usr/bin/env node
// #!/usr/bin/env node --no-warnings
// ©2023 Ruben Verborgh – MIT License

import assert from 'node:assert';
Expand Down Expand Up @@ -51,7 +52,10 @@ async function copyNssPodsToCSS(nssConfigPath, cssDataPath, cssUrl, emailPattern
print(`4️⃣ CSS: Copy ${accounts.length} pod contents on disk`);
await asyncMap(copyPodFiles, accounts, nss.hostname, nss.dataPath, cssDataPath);

print(`5️⃣ CSS: Check ${accounts.length} pods for known resources`);
print(`5️⃣ CSS: Copy ${accounts.length} WebID oidcIssuer on disk`);
await asyncMap(updateOidcIssuer, accounts, cssDataPath, cssUrl);

print(`6️⃣ CSS: Check ${accounts.length} pods for known resources`);
await asyncMap(testPod, accounts, cssUrl);
}

Expand Down Expand Up @@ -123,7 +127,7 @@ async function updateAccount(account, internalPath) {
checks.read = true;

// Update the password section
const passwordSections = Object.values(accountConfig['**password**']);
const passwordSections = Object.values(accountConfig['payload']['**password**']);
assert.equal(passwordSections.length, 1);
assert(account.hashedPassword.startsWith(passwordHashStart));
assert(passwordSections[0].password.startsWith(passwordHashStart));
Expand All @@ -132,7 +136,7 @@ async function updateAccount(account, internalPath) {

// Update the WebID section
if (account.webId) {
const webIdSections = Object.values(accountConfig['**webIdLink**']);
const webIdSections = Object.values(accountConfig['payload']['**webIdLink**']);
assert.equal(webIdSections.length, 1);
assert(webIdSections[0].webId.startsWith('http'));
assert(account.webId.startsWith('http'));
Expand Down Expand Up @@ -166,20 +170,42 @@ async function copyPodFiles({ username }, hostname, nssDataPath, cssDataPath) {
// Copy new contents from the source to the destination
await execFile('cp', ['-a', '--', source, destination]);
checks.copy = true;

}
finally {
assert(printChecks(username, checks), 'Pod copy failed');
}
}

// update oidcIssuer in webID document (add end '/')
async function updateOidcIssuer ({ username }, cssDataPath, cssUrl) {
const checks = { oidcIssuer: false };
const path = resolve(cssDataPath, username, 'profile/card$.ttl')
try {
var profile = await readFile(path, 'utf8')
if (profile.includes(`solid:oidcIssuer <${cssUrl.slice(0, -1)}>`)) {
const newProfile = profile.replace(new RegExp(`solid:oidcIssuer <${cssUrl.slice(0, -1)}>`), `solid:oidcIssuer <${cssUrl}>`)
await writeFile(path, newProfile)
checks.oidcIssuer = true
}
if (profile.includes(`oidcIssuer> <${cssUrl.slice(0, -1)}>`)) {
const newProfile = profile.replace(new RegExp(`oidcIssuer> <${cssUrl.slice(0, -1)}>`), `oidcIssuer> <${cssUrl}>`)
await writeFile(path, newProfile)
checks.oidcIssuer = true
}
}
finally {
assert(printChecks(username, checks), 'oidcIssuer update failed');
}
}

// Tests the given pod by trying to access typical resources
async function testPod({ username }, cssUrl) {
const checks = { publicProfile: false, privateInbox: false };

// Create URL for pod
const podUrl = new URL(cssUrl);
podUrl.hostname = `${username}.${podUrl.hostname}`;

try {
// Check presence of resources available in typical NSS pods
const profile = await localFetch(new URL('/profile/card', podUrl));
Expand All @@ -196,7 +222,7 @@ async function testPod({ username }, cssUrl) {
async function getAccountControls(cssUrl) {
try {
const body = await cssApiGet(new URL('.account/', cssUrl));
assert.equal(body.version, '0.5', 'Unsupported CSS account API');
// assert.equal(body.version, '0.5', 'Unsupported CSS account API');
return body.controls;
}
catch (cause) {
Expand Down Expand Up @@ -225,7 +251,7 @@ async function cssApiFetch(url, options = {}, authorization = '') {
headers: {
...options.headers,
accept: 'application/json',
authorization: `CSS-Account-Cookie ${authorization}`,
authorization: `CSS-Account-Token ${authorization}`,
},
});
const json = await response.json();
Expand All @@ -241,8 +267,8 @@ function localFetch(url, init = {}) {
// The `pod.localhost` pattern is common within NSS and CSS,
// but Node.js does not resolve this well by default
const host = url.host;
if (url.hostname.endsWith('.localhost'))
url.hostname = 'localhost';
/* if (url.hostname.endsWith('.localhost'))
url.hostname = 'localhost'; */

return fetch(url, { ...init, headers: { host } });
}
Expand Down