I am currently working on a project where i have to create solid pods for students and give them the pods access with temporary passwords. Is there any API available to talk to the solid node server to create solid PODs programatically? Or i have to modify the source code of the node server to achieve this? (P.S. We have our own solid server).
It is possible to do this with CSS and NSS, though I donāt think anyone has written a specific guide; itās mostly about putting the right data & files in place, as both servers are filesystem based (compared to ESS which is postgresql/mongodb + s3-like storage, iirc)
OK, so I have grabbed a clone of GitHub - nodeSolidServer/node-solid-server: Solid server on top of the file-system in NodeJS and am running a local bin/solid-test instance to check what data is saved where for multiple users and it looks like I just need to add a suitable entry in the
ā.db/oidc/users/usersā folder for each user, and add a folder in the /data directory for each user replicating the structure the ones already there.
I havenāt used this version yet, but looking at the documentation and trying it out a bit, here is how I created an account and setup a login via email+password. I guess you can use a similar approach to setup pods and authentication via OIDC or client credentials.
// get available endpoints
res = await fetch('http://localhost:3000/.account/')
data = await res.json()
controls = data.controls
// create an account (requires no parameters)
res = await fetch(controls.account.create, { method: 'POST' })
data = await res.json()
authorizationValue = data.authorization
// get available endpoints, but now for the fresh account (should also work via the cookie, authorization header is probably not necessary)
res = await fetch('http://localhost:3000/.account/', { headers: { authorization: `CSS-Account-Token ${authorizationValue}` } })
data = await res.json()
controls = data.controls
// get necessary fields for the POST request
res = await fetch(controls.password.create, { headers: { authorization: `CSS-Account-Token ${authorizationValue}` } })
data = await res.json()
console.log(data.fields) // tells us we need email+password parameters for the POST request
// setup a login via email+password for the current account
res = await fetch(controls.password.create, {
headers: {
authorization: `CSS-Account-Token ${authorizationValue}`,
'content-type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
email: 'test@example.org',
password: 'secret-12345',
}),
})
data = await res.json()
// now we can login with email+password
res = await fetch(controls.password.login, {
headers: {
'content-type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
email: 'test@example.org',
password: 'secret-12345',
}),
})
data = await res.json()
authorizationValue = data.authorization
// get available endpoints for current account
res = await fetch('http://localhost:3000/.account/', { headers: { authorization: `CSS-Account-Token ${authorizationValue}` } })
data = await res.json()
controls = data.controls
res = await fetch(controls.account.pod, {
headers: {
authorization: CSS-Account-Token ${authorizationValue},
ācontent-typeā: āapplication/jsonā
},
method: āPOSTā,
body: JSON.stringify({
name: uniqueID // POD NAME SET TO USERS UNIQUE ID FOR EASY REFERENCE
}),
})
data = await res.json()
console.log('Pod created: ā + JSON.stringify(data));
I just get error: TypeError: Invalid URL, guessing it does not recognise the ācontrols.account.podā
Yet when I login on UI instead, it allows me to create a new pod which assigns a webID, so the configuration must be correct, just not exposed to the API?
Iāve updated my code above slighly (replaced the second controls.password.create with controls.password.login and added the authorization header for the last api call).
When you execute this with your authorizationValue and origin (secure.agefix.space instead of localhost):
// get available endpoints for current account
res = await fetch('http://localhost:3000/.account/', { headers: { authorization: `CSS-Account-Token ${authorizationValue}` } })
data = await res.json()
controls = data.controls
console.log(controls.account.pod)
Thatās good to hear. The UI uses the same API (you can find the source here). You could also inspect the network requests in the browser dev tools to see which requests it makes to create the pod. Note that the UI seems to rely on cookies for authentication, in nodejs you should add the authorization header to authenticate.
You can save it as someScript.js locally and execute with node someScript.js
// baseUrl = 'http://localhost:3000'
baseUrl = 'https://secure.agefix.space'
indexUrl = baseUrl + '/.account/'
async function main() {
// get available endpoints
res = await fetch(indexUrl)
data = await res.json()
controls = data.controls
// create an account (requires no parameters)
res = await fetch(controls.account.create, { method: 'POST' })
data = await res.json()
authorizationValue = data.authorization
// get available endpoints, but now for the fresh account (should also work via the cookie, authorization header is probably not necessary)
res = await fetch(indexUrl, { headers: { authorization: `CSS-Account-Token ${authorizationValue}` } })
data = await res.json()
controls = data.controls
// setup a login via email+password for the current account
res = await fetch(controls.password.create, {
headers: {
authorization: `CSS-Account-Token ${authorizationValue}`,
'content-type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
email: 'test@example.org',
password: 'secret-12345',
}),
})
data = await res.json()
// now we can login with email+password
res = await fetch(controls.password.login, {
headers: {
'content-type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
email: 'test@example.org',
password: 'secret-12345',
}),
})
data = await res.json()
authorizationValue = data.authorization
// get available endpoints for current account
res = await fetch(indexUrl, { headers: { authorization: `CSS-Account-Token ${authorizationValue}` } })
data = await res.json()
controls = data.controls
console.log(controls.account.pod)
// setup a pod
res = await fetch(controls.account.pod, {
headers: {
authorization: `CSS-Account-Token ${authorizationValue}`,
'content-type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
name: 'testomate',
}),
})
data = await res.json()
console.log(`Created pod: ${JSON.stringify(data, undefined, 2)}`)
}
main()
Can this same approach be used to write and read RDF data to the pod and also physical files like documents? I am struggling to integrate. All examples I have found are doing it from the client not the server like above and using ESS not CSS. I want them to be private too, not publicly accessible.