Skip to content

Instantly share code, notes, and snippets.

@mrkvon
Created May 10, 2025 04:37
Show Gist options
  • Save mrkvon/1596ca0b95983a4e1a057357ae5b61ce to your computer and use it in GitHub Desktop.
Save mrkvon/1596ca0b95983a4e1a057357ae5b61ce to your computer and use it in GitHub Desktop.
// src/index.ts
import { v7 } from 'css-authn'
import { randomUUID } from 'node:crypto'
// create three users
const users = await Promise.all(
Array(3)
.fill(null)
.map(() =>
v7.createAccount({
username: randomUUID(),
get email() {
return this.username + '@example'
},
password: randomUUID(),
provider: 'http://localhost:3000',
}),
),
)
// authenticate them
const authFetches = await Promise.all(
users.map(user => v7.getAuthenticatedFetch({ ...user, provider: user.idp })),
)
// create a container for users[0]
const container = new URL('test/append/', users[0].podUrl)
const r1 = await authFetches[0](container, { method: 'PUT' })
console.log(r1.status)
// create acl with users[0] owner and users[1] append rights
const r1acl = await authFetches[0](new URL('.acl', container), {
method: 'PUT',
body: `
@prefix acl: <http://www.w3.org/ns/auth/acl#>.
<#owner> a acl:Authorization;
acl:accessTo <./>;
acl:default <./>;
acl:agent <${users[0].webId}>;
acl:mode acl:Read, acl:Write, acl:Control.
<#appendDefault> a acl:Authorization;
acl:accessTo <./>;
acl:default <./>;
acl:agent <${users[1].webId}>;
acl:mode acl:Append.
<#append> a acl:Authorization;
acl:accessTo <./>;
acl:agent <${users[2].webId}>;
acl:mode acl:Append.
`,
headers: { 'content-type': 'text/turtle' },
})
// users[1] POSTs a new resource
const user1post = await authFetches[1](container, {
method: 'POST',
body: '<#this> a <#test>.',
headers: { 'content-type': 'text/turtle' },
})
// users[1] PUTs a new resource
const user1put1 = await authFetches[1](new URL('hello.ttl', container), {
method: 'PUT',
body: '<#this> a <#test>.',
headers: { 'content-type': 'text/turtle' },
})
// users[1] PUTs the resource second time
const user1put2 = await authFetches[1](new URL('hello.ttl', container), {
method: 'PUT',
body: `<#this> a <#test>.`,
headers: { 'content-type': 'text/turtle' },
})
console.log(user1post.status, user1post.headers.get('location')) // 201
console.log(user1put1.status, user1put1.headers.get('location')) // 201
console.log(user1put2.status, user1put2.headers.get('location')) // 403
// users[2] POSTs a new resource
const user2post = await authFetches[2](container, {
method: 'POST',
body: '<#this> a <#test>.',
headers: { 'content-type': 'text/turtle', slug: 'tada' },
})
// users[2] PUTs a new resource
const user2put1 = await authFetches[2](new URL('hello2.ttl', container), {
method: 'PUT',
body: '<#this> a <#test>.',
headers: { 'content-type': 'text/turtle' },
})
// users[2] PUTs the resource second time
const user2put2 = await authFetches[2](new URL('hello2.ttl', container), {
method: 'PUT',
body: `<#this> a <#test>.`,
headers: { 'content-type': 'text/turtle' },
})
console.log(user2post.status, user2post.headers.get('location')) // 201
console.log(user2put1.status, user2put1.headers.get('location')) // 403
console.log(user2put2.status, user2put2.headers.get('location')) // 403
{
"name": "css-test",
"type": "module",
"scripts": {
"start": "node --import tsx src/index.ts"
},
"dependencies": {
"css-authn": "^0.2.1"
},
"devDependencies": {
"@types/node": "^22.15.17",
"tsx": "^4.19.4",
"typescript": "^5.8.3"
}
}
{
"compilerOptions": {
"module": "nodenext"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment