Skip to content

Commit d6f1bb4

Browse files
author
Tim Berners-Lee
committed
Refactored. modesAllowed() surfcaed. passed 28/28 tests.
1 parent 32ea780 commit d6f1bb4

File tree

3 files changed

+105
-40
lines changed

3 files changed

+105
-40
lines changed

Diff for: README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ let dirAclDoc = $rdf.sym('https://alice.example.com/stuff/')
2525
let agent = $rdf.sym('https://alice.example.com/card.ttl#me')
2626
let modesRequired = [ ACL('Read'), ACL('Write'), ACL('Control') ]
2727

28-
await fetcher.load([aclDoc, dirAclDoc]) // Load the ACL documents into kb
28+
await fetcher.load(aclDoc) // Load the ACL documents into kb
2929

30-
let allow = aclCheck.checkAccess(kb, doc, directory, aclDoc, agent, modesRequired, origin, trustedOrigins)
30+
let allow = aclCheck.checkAccess(kb, resource, null, aclDoc, agent, modesRequired, origin, trustedOrigins)
31+
32+
// When there is no direct ACL file, find the closest container ACL file in the tree above then...
33+
await fetcher.load(dirAclDoc) // Load the directory ACL documents into kb
34+
let allow = aclCheck.checkAccess(kb, resource, directory, dirAclDoc, agent, modesRequired, origin, trustedOrigins)
3135

3236
console.log('Access allowed? ' + allow)
3337
// OWTTE

Diff for: src/acl-check.js

+58-34
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,43 @@ function publisherTrustedApp (kb, doc, aclDoc, modesRequired, origin, docAuths)
2020
// modesRequired.every(mode => appAuths.some(auth => kb.holds(auth, ACL('mode'), mode, aclDoc)))
2121
}
2222

23+
/* Function checkAccess
24+
** @param kb A quadstore
25+
** @param doc the resource (A named node) or directory for which ACL applies
26+
*/
2327
function checkAccess (kb, doc, directory, aclDoc, agent, modesRequired, origin, trustedOrigins) {
24-
var auths = kb.each(null, ACL('accessTo'), doc, aclDoc)
25-
console.log(`checkAccess: checking access to ${doc} by ${agent}`)
26-
if (auths.length) console.log(` ${auths.length} authentications apply directly to doc`)
27-
if (directory) {
28-
auths = auths.concat(null, (ACL('defaultForNew'), directory)) // Deprecated but keep for ages
29-
auths = auths.concat(null, (ACL('default'), directory))
30-
if (auths.length) console.log(` ${auths.length} total relevant authentications`)
28+
let modeURIs = modesAllowed(kb, doc, directory, aclDoc, agent, origin, trustedOrigins)
29+
let ok = true
30+
console.log(`CheckAccess: modeURIs: ${modeURIs.size}`)
31+
modesRequired.forEach(mode => {
32+
console.log(` checking ` + mode)
33+
if (modeURIs.has(mode.uri)) {
34+
console.log(' Mode required and allowed:' + mode)
35+
} else if (mode.sameTerm(ACL('Append')) && modeURIs.has(ACL('Write').uri)) {
36+
console.log(' Append required and Write allowed. OK')
37+
} else {
38+
console.log(' MODE REQUIRED NOT ALLOWED:' + mode)
39+
ok = false
40+
}
41+
})
42+
return ok
43+
}
44+
45+
function modesAllowed (kb, doc, directory, aclDoc, agent, modesRequired, origin, trustedOrigins) {
46+
console.log(`modesAllowed: checking access to ${doc} by ${agent}`)
47+
var auths
48+
if (!directory) { // Normal case, ACL for a file
49+
auths = kb.each(null, ACL('accessTo'), doc, aclDoc)
50+
console.log(` ${auths.length} direct authentications about ${doc}`)
51+
} else {
52+
auths = kb.each(null, ACL('default'), directory, null)
53+
auths = auths.concat(kb.each(null, ACL('defaultForNew'), directory, null)) // Deprecated but keep for ages
54+
console.log(` ${auths.length} default authentications about ${directory} in ${aclDoc}`)
3155
}
3256
if (origin && trustedOrigins && trustedOrigins.includes(origin)) {
3357
console.log('Origin ' + origin + ' is trusted')
3458
origin = null // stop worrying about origin
35-
console.log(` checkAccess: Origin ${origin} is trusted.`)
59+
console.log(` modesAllowed: Origin ${origin} is trusted.`)
3660
}
3761
function agentOrGroupOK (auth, agent) {
3862
console.log(` Checking auth ${auth} with agent ${agent}`)
@@ -64,37 +88,37 @@ function checkAccess (kb, doc, directory, aclDoc, agent, modesRequired, origin,
6488
function originOK (auth, origin) {
6589
return kb.holds(auth, ACL('origin'), origin, aclDoc)
6690
}
67-
let allowed = modesRequired.every(mode => {
68-
console.log(' Checking needed mode ' + mode)
69-
let modeAuths = auths.filter(auth => kb.holds(auth, ACL('mode'), mode, aclDoc))
70-
if (mode.sameTerm(ACL('Append'))) { // If you want append, Write will work too.
71-
let writeAuths = auths.filter(auth => kb.holds(auth, ACL('mode'), ACL('Write'), aclDoc))
72-
console.log(` Authorizations that work with Write: ${writeAuths.length}`)
73-
modeAuths = modeAuths.concat(writeAuths)
91+
92+
function agentAndAppOK (auth) {
93+
if (!agentOrGroupOK(auth, agent)) {
94+
console.log(' The agent/group/public check fails')
95+
return false
7496
}
75-
console.log(` Authorizations that work with mode: ${modeAuths.length}`)
76-
let modeResult = modeAuths.some(auth => {
77-
if (!agentOrGroupOK(auth, agent)) {
78-
console.log(' The agent/group/public check fails')
79-
return false
80-
}
81-
if (!origin) {
82-
console.log(' Origin check not needed: no origin.')
83-
return true
84-
}
85-
if (originOK(auth, origin)) {
86-
console.log(' Origin check succeeded.')
87-
return true
88-
}
89-
console.log(' Origin check FAILED. Origin not tested.')
97+
if (!origin) {
98+
console.log(' Origin check not needed: no origin.')
9099
return true
100+
}
101+
if (originOK(auth, origin)) {
102+
console.log(' Origin check succeeded.')
103+
return true
104+
}
105+
console.log(' Origin check FAILED. Origin not trusted.')
106+
return false // @@ look for other trusted apps
107+
}
108+
109+
auths = auths.filter(agentAndAppOK)
110+
console.log(' auths with good who and what: ' + auths.length)
111+
var modeURIs = new Set()
112+
auths.forEach(auth => {
113+
let modes = kb.each(auth, ACL('mode'), null, aclDoc)
114+
modes.forEach(mode => {
115+
console.log(' Mode allowed: ' + mode)
116+
modeURIs.add(mode.uri)
91117
})
92-
console.log(' Mode result ' + modeResult)
93-
return modeResult
94118
})
95-
console.log('Overall result:' + allowed)
96-
return allowed
119+
return modeURIs
97120
}
98121

99122
module.exports.checkAccess = checkAccess
123+
module.exports.modesAllowed = modesAllowed
100124
module.exports.publisherTrustedApp = publisherTrustedApp

Diff for: test/unit/check-access-test.js

+41-4
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,14 @@ test('acl-check checkAccess() test - default/inherited', function (t) {
8080
let file2 = $rdf.sym('https://alice.example.com/docs/stuff/file2')
8181
var result
8282
const store = $rdf.graph()
83+
/*
8384
let ACLtext = prefixes + ` <#auth> a acl:Authorization;
8485
acl:mode acl:Read;
8586
acl:agent bob:me;
8687
acl:accessTo <${file1.uri}> .
8788
`
8889
$rdf.parse(ACLtext, store, containerAcl.uri, 'text/turtle')
89-
90+
*/
9091
let containerAclText = prefixes + ` <#auth> a acl:Authorization;
9192
acl:mode acl:Read;
9293
acl:agent alice:me;
@@ -106,6 +107,41 @@ test('acl-check checkAccess() test - default/inherited', function (t) {
106107
t.end()
107108
})
108109

110+
// Inheriting permissions from directory defaults -- OLD version defaultForNew
111+
test('acl-check checkAccess() test - default/inherited', function (t) {
112+
let container = $rdf.sym('https://alice.example.com/docs/')
113+
let containerAcl = $rdf.sym('https://alice.example.com/docs/.acl')
114+
let file1 = $rdf.sym('https://alice.example.com/docs/file1')
115+
let file2 = $rdf.sym('https://alice.example.com/docs/stuff/file2')
116+
var result
117+
const store = $rdf.graph()
118+
/*
119+
let ACLtext = prefixes + ` <#auth> a acl:Authorization;
120+
acl:mode acl:Read;
121+
acl:agent bob:me;
122+
acl:accessTo <${file1.uri}> .
123+
`
124+
$rdf.parse(ACLtext, store, containerAcl.uri, 'text/turtle')
125+
*/
126+
let containerAclText = prefixes + ` <#auth> a acl:Authorization;
127+
acl:mode acl:Read;
128+
acl:agent alice:me;
129+
acl:defaultForNew <${container.uri}> .
130+
`
131+
$rdf.parse(containerAclText, store, containerAcl.uri, 'text/turtle')
132+
133+
result = aclLogic.checkAccess(store, file1, container, containerAcl, alice, [ ACL('Read')])
134+
t.ok(result, 'Alice should have Read acces inherited')
135+
136+
result = aclLogic.checkAccess(store, file2, container, containerAcl, alice, [ ACL('Read')])
137+
t.ok(result, 'Alice should have Read acces inherited 2')
138+
139+
result = !aclLogic.checkAccess(store, file2, container, containerAcl, alice, [ ACL('Write')])
140+
t.ok(result, 'Alice should NOT have Write acces inherited')
141+
142+
t.end()
143+
})
144+
109145
///////////////////////////////////////// Public access VESRIONS OF THESE
110146
// Append access implied by Write acecss -PUBLIC
111147
test('aclCheck checkAccess() test - Append access implied by Public Write acecss', t => {
@@ -171,20 +207,21 @@ test('acl-check checkAccess() test - default/inherited', function (t) {
171207
let file2 = $rdf.sym('https://alice.example.com/docs/stuff/file2')
172208
var result
173209
const store = $rdf.graph()
210+
/*
174211
let ACLtext = prefixes + ` <#auth> a acl:Authorization;
175212
acl:mode acl:Read;
176213
acl:agent bob:me;
177214
acl:accessTo <${file1.uri}> .
178-
`
215+
`
179216
$rdf.parse(ACLtext, store, containerAcl.uri, 'text/turtle')
180-
217+
*/
181218
let containerAclText = prefixes + ` <#auth> a acl:Authorization;
182219
acl:mode acl:Read;
183220
acl:agentClass foaf:Agent;
184221
acl:default <${container.uri}> .
185222
`
186223
$rdf.parse(containerAclText, store, containerAcl.uri, 'text/turtle')
187-
224+
console.log('@@' + containerAclText + '@@@')
188225
result = aclLogic.checkAccess(store, file1, container, containerAcl, alice, [ ACL('Read')])
189226
t.ok(result, 'Alice should have Read acces inherited - Public')
190227

0 commit comments

Comments
 (0)