Skip to content

Commit 3b70e3a

Browse files
author
Tim Berners-Lee
committed
pass 6 out of 16
1 parent 260e566 commit 3b70e3a

File tree

2 files changed

+111
-95
lines changed

2 files changed

+111
-95
lines changed

src/acl-check.js

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -22,76 +22,79 @@ function publisherTrustedApp (kb, doc, aclDoc, modesRequired, origin, docAuths)
2222

2323
function checkAccess (kb, doc, directory, aclDoc, agent, modesRequired, origin, trustedOrigins) {
2424
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`)
2527
if (directory) {
2628
auths = auths.concat(null, (ACL('defaultForNew'), directory)) // Deprecated but keep for ages
2729
auths = auths.concat(null, (ACL('default'), directory))
30+
if (auths.length) console.log(` ${auths.length} total relevant authentications`)
2831
}
2932
if (origin && trustedOrigins && trustedOrigins.includes(origin)) {
3033
console.log('Origin ' + origin + ' is trusted')
3134
origin = null // stop worrying about origin
35+
console.log(` checkAccess: Origin ${origin} is trusted.`)
3236
}
3337
function agentOrGroupOK (auth, agent) {
34-
if (kb.holds(auth, ACL('accessToClass'), FOAF('Agent'), aclDoc)) return true
35-
if (!agent) return false
36-
return kb.holds(auth, ACL('accessToClass'), ACL('AuthenticatedAgent'), aclDoc) ||
37-
kb.holds(auth, ACL('agent'), agent, aclDoc) ||
38-
kb.each(auth, ACL('accessToGroup'), null, aclDoc).some(group => kb.holds(agent, VCARD('member'), group, group.doc()))
39-
}
40-
function originOK (auth, origin) {
41-
return kb.holds(auth, ACL('origin'), origin, aclDoc)
42-
}
43-
return modesRequired.every(mode =>
44-
auths.filter(auth => kb.holds(auth, ACL('mode'), mode, aclDoc)).some(
45-
auth => (agentOrGroupOK(auth, agent)) && (!origin || originOK(auth, origin)))
46-
)
47-
}
38+
console.log(` Checking auth ${auth} with agent ${agent}`)
39+
if (kb.holds(auth, ACL('accessToClass'), FOAF('Agent'), aclDoc)) {
40+
console.log(` Agent or group: Ok, its public.`)
41+
return true
42+
}
43+
if (!agent) {
44+
console.log(` Agent or group: Fail: not public and not logged on.`)
45+
return false
46+
}
47+
if (kb.holds(auth, ACL('accessToClass'), ACL('AuthenticatedAgent'), aclDoc)) {
48+
console.log(' AuthenticatedAgent: logged in, looks good')
49+
return true
50+
}
51+
if (kb.holds(auth, ACL('agent'), agent, aclDoc) ) {
52+
console.log(' Agent explicitly authenticated.')
53+
return true
54+
}
55+
if (kb.each(auth, ACL('accessToGroup'), null, aclDoc).some(
56+
group => kb.holds(agent, VCARD('member'), group, group.doc()))) {
57+
console.log(' Agent is member of group which has accees.')
58+
return true
59+
}
60+
console.log(' Agent or group access fails for this authentication.')
61+
return false
62+
} // Agent or group
4863

49-
function checkAccess1 (kb, doc, directory, aclDoc, agent, modesRequired, origin, trustedOrigins) {
50-
var auths = kb.each(null, ACL('accessTo'), doc, aclDoc)
51-
if (directory) {
52-
auths = auths.concat(null, (ACL('defaultForNew'), doc)) // Deprecated but keep for ages
53-
auths = auths.concat(null, (ACL('default'), doc))
54-
}
55-
if (origin && trustedOrigins && trustedOrigins.includes(origin)) {
56-
console.log('Origin ' + origin + ' is trusted')
57-
origin = null // stop worrying about origin
58-
}
59-
function agentOrGroupOK (auth, agent) {
60-
if (kb.holds(auth, ACL('accessToClass'), FOAF('Agent'), aclDoc)) return true
61-
if (!agent) return false
62-
return kb.holds(auth, ACL('accessToClass'), ACL('AuthenticatedAgent'), aclDoc) ||
63-
kb.holds(auth, ACL('agent'), agent, aclDoc) ||
64-
kb.each(auth, ACL('accessToGroup'), null, aclDoc).some(group => kb.holds(agent, VCARD('member'), group, group.doc()))
65-
}
6664
function originOK (auth, origin) {
6765
return kb.holds(auth, ACL('origin'), origin, aclDoc)
6866
}
69-
return modesRequired.every(mode =>
70-
auths.filter(auth => kb.holds(auth, ACL('mode'), mode, aclDoc)).some(
71-
auth => (agentOrGroupOK(auth, agent)) && (!origin || originOK(auth, origin)))
72-
)
73-
}
74-
75-
function checkAccess0 (kb, doc, directory, aclDoc, agent, modesRequired, origin, trustedOrigins) {
76-
var auths = kb.each(null, ACL('accessTo'), doc)
77-
if (directory) {
78-
auths = auths.concat(null, (ACL('defaultForNew'), doc)) // Deprecated but keep for ages
79-
auths = auths.concat(null, (ACL('default'), doc))
80-
}
81-
if (origin && trustedOrigins && trustedOrigins.includes(origin)) {
82-
console.log('Origin ' + origin + ' is trusted')
83-
origin = null // stop worrying about origin
84-
}
85-
return modesRequired.every(mode =>
86-
auths.some(auth =>
87-
kb.holds(auth, ACL('agent'), agent) && kb.holds(auth, ACL('mode'), mode)) &&
88-
(!origin ||
89-
auths.some(auth => kb.holds(auth, ACL('origin'), origin) && kb.holds(auth, ACL('mode'), mode))
90-
)
91-
)
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)
74+
}
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.')
90+
return true
91+
})
92+
console.log(' Mode result ' + modeResult)
93+
return modeResult
94+
})
95+
console.log('Overall result:' + allowed)
96+
return allowed
9297
}
9398

9499
module.exports.checkAccess = checkAccess
95-
module.exports.checkAccess0 = checkAccess0
96-
module.exports.checkAccess1 = checkAccess1
97100
module.exports.publisherTrustedApp = publisherTrustedApp

test/unit/check-access-test.js

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ const FOAF = $rdf.Namespace('http://xmlns.com/foaf/0.1/')
1212

1313
const prefixes = `@prefix acl: <http://www.w3.org/ns/auth/acl#> .
1414
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
15-
@prefix alice: <https://alice.example.com/>.
15+
@prefix alice: <https://alice.example.com/#>.
1616
@prefix bob: <https://bob.example.com/#>.
1717
`
18-
const aliceWebId = 'https://alice.example.com/#me'
1918
const alice = $rdf.sym('https://alice.example.com/#me')
2019
const bob = $rdf.sym('https://bob.example.com/#me')
2120
const malory = $rdf.sym('https://someone.else.example.com/')
@@ -26,22 +25,22 @@ test('aclCheck checkAccess() test - Append access implied by Write acecss', t =>
2625
let aclUrl = 'https://alice.example.com/docs/.acl'
2726
let aclDoc = $rdf.sym(aclUrl)
2827

29-
const kb = $rdf.graph() // Quad store
28+
const store = $rdf.graph() // Quad store
3029
const ACLtext = prefixes +
3130
` <#auth> a acl:Authorization;
32-
acl:mode acl:Read;
31+
acl:mode acl:Write;
3332
acl:agent alice:me;
3433
acl:accessTo <${resource.uri}> .
3534
`
36-
$rdf.parse(ACLtext, kb, aclUrl, 'text/turtle')
35+
$rdf.parse(ACLtext, store, aclUrl, 'text/turtle')
3736

3837
const agent = alice
3938
const directory = null
4039
const modesRequired = [ ACL('Append')]
4140
const trustedOrigins = null
4241
const origin = null
4342

44-
const result = aclLogic.checkAccess(kb, resource, directory, aclDoc, agent, modesRequired, origin, trustedOrigins)
43+
const result = aclLogic.checkAccess(store, resource, directory, aclDoc, agent, modesRequired, origin, trustedOrigins)
4544
if (result) {
4645
t.ok(result, 'Alice should have Append access implied by Write access')
4746
} else {
@@ -56,30 +55,30 @@ test('acl-check checkAccess() test - accessTo', function (t) {
5655
let containerAclUrl = 'https://alice.example.com/docs/.acl'
5756
let containerAcl = $rdf.sym(containerAclUrl)
5857

59-
const kb = $rdf.graph() // Quad store
58+
const store = $rdf.graph() // Quad store
6059
const ACLtext = prefixes +
6160
` <#auth> a acl:Authorization;
6261
acl:mode acl:Read, acl:Write;
6362
acl:agent alice:me;
6463
acl:accessTo <${container.uri}> .
6564
`
66-
$rdf.parse(ACLtext, kb, containerAclUrl, 'text/turtle')
65+
$rdf.parse(ACLtext, store, containerAclUrl, 'text/turtle')
6766

68-
var result = aclLogic.checkAccess(kb, container, null, containerAcl, alice, [ ACL('Read')])
67+
var result = aclLogic.checkAccess(store, container, null, containerAcl, alice, [ ACL('Read')])
6968
if (result) {
7069
t.ok(result, 'Alice should have Read acces')
7170
} else {
7271
t.fail('Alice s....')
7372
}
7473

75-
result = aclLogic.checkAccess(kb, container, null, containerAcl, alice, [ ACL('Write')])
74+
result = aclLogic.checkAccess(store, container, null, containerAcl, alice, [ ACL('Write')])
7675
if (result) {
7776
t.ok(result, 'Alice should have Write acces')
7877
} else {
7978
t.fail('Alice s....')
8079
}
8180

82-
result = aclLogic.checkAccess(kb, container, null, containerAcl, bob, [ ACL('Write')])
81+
result = aclLogic.checkAccess(store, container, null, containerAcl, bob, [ ACL('Write')])
8382
if (!result) {
8483
t.ok(result, 'Bob should not have Write acces')
8584
} else {
@@ -96,36 +95,36 @@ test('acl-check checkAccess() test - default/inherited', function (t) {
9695
let file1 = $rdf.sym('https://alice.example.com/docs/file1')
9796
let file2 = $rdf.sym('https://alice.example.com/docs/stuff/file2')
9897
var result
99-
const kb = $rdf.graph()
98+
const store = $rdf.graph()
10099
let ACLtext = prefixes + ` <#auth> a acl:Authorization;
101100
acl:mode acl:Read;
102101
acl:agent bob:me;
103102
acl:accessTo <${file1.uri}> .
104103
`
105-
$rdf.parse(ACLtext, kb, containerAcl.uri, 'text/turtle')
104+
$rdf.parse(ACLtext, store, containerAcl.uri, 'text/turtle')
106105

107106
let containerAclText = prefixes + ` <#auth> a acl:Authorization;
108107
acl:mode acl:Read;
109108
acl:agent alice:me;
110109
acl:default <${container.uri}> .
111110
`
112-
$rdf.parse(containerAclText, kb, containerAcl.uri, 'text/turtle')
111+
$rdf.parse(containerAclText, store, containerAcl.uri, 'text/turtle')
113112

114-
result = aclLogic.checkAccess(kb, file1, container, containerAcl, alice, [ ACL('Read')])
113+
result = aclLogic.checkAccess(store, file1, container, containerAcl, alice, [ ACL('Read')])
115114
if (result) {
116115
t.ok(result, 'Alice should have Read acces inherited')
117116
} else {
118117
t.fail('Alice s....')
119118
}
120119

121-
result = aclLogic.checkAccess(kb, file2, container, containerAcl, alice, [ ACL('Read')])
120+
result = aclLogic.checkAccess(store, file2, container, containerAcl, alice, [ ACL('Read')])
122121
if (result) {
123122
t.ok(result, 'Alice should have Read acces inherited 2')
124123
} else {
125124
t.fail('Alice s....')
126125
}
127126

128-
result = aclLogic.checkAccess(kb, file2, container, containerAcl, alice, [ ACL('Read')])
127+
result = aclLogic.checkAccess(store, file2, container, containerAcl, alice, [ ACL('Read')])
129128
if (result) {
130129
t.ok(result, 'Mallory should NOT have Read acces inherited')
131130
} else {
@@ -142,26 +141,26 @@ test('aclCheck checkAccess() test - Append access implied by Public Write acecss
142141
let aclUrl = 'https://alice.example.com/docs/.acl'
143142
let aclDoc = $rdf.sym(aclUrl)
144143

145-
const kb = $rdf.graph() // Quad store
144+
const store = $rdf.graph() // Quad store
146145
const ACLtext = prefixes +
147146
` <#auth> a acl:Authorization;
148147
acl:mode acl:Read;
149148
acl:agentClass foaf:Agent;
150149
acl:accessTo <${resource.uri}> .
151150
`
152-
$rdf.parse(ACLtext, kb, aclUrl, 'text/turtle')
151+
$rdf.parse(ACLtext, store, aclUrl, 'text/turtle')
153152

154153
const agent = alice
155154
const directory = null
156155
const modesRequired = [ ACL('Append')]
157156
const trustedOrigins = null
158157
const origin = null
159158

160-
const result = aclLogic.checkAccess(kb, resource, directory, aclDoc, agent, modesRequired, origin, trustedOrigins)
159+
const result = aclLogic.checkAccess(store, resource, directory, aclDoc, agent, modesRequired, origin, trustedOrigins)
161160
if (result) {
162-
t.ok(result, 'Alice should have Append access implied by Write access')
161+
t.ok(result, 'Alice should have Append access implied by Write access - Public')
163162
} else {
164-
t.fail('Alice should have Append access implied by Write access')
163+
t.fail('Alice should have Append access implied by Write access - Public')
165164
}
166165
t.end()
167166
})
@@ -172,32 +171,46 @@ test('acl-check checkAccess() test - accessTo', function (t) {
172171
let containerAclUrl = 'https://alice.example.com/docs/.acl'
173172
let containerAcl = $rdf.sym(containerAclUrl)
174173

175-
const kb = $rdf.graph() // Quad store
174+
const store = $rdf.graph() // Quad store
176175
const ACLtext = prefixes +
177176
` <#auth> a acl:Authorization;
178177
acl:mode acl:Read, acl:Write;
179178
acl:agentClass foaf:Agent;
180179
acl:accessTo <${container.uri}> .
181180
`
182-
$rdf.parse(ACLtext, kb, containerAclUrl, 'text/turtle')
181+
$rdf.parse(ACLtext, store, containerAclUrl, 'text/turtle')
183182

184-
var result = aclLogic.checkAccess(kb, container, null, containerAcl, alice, [ ACL('Read')])
183+
var result = aclLogic.checkAccess(store, container, null, containerAcl, alice, [ ACL('Read')])
185184
if (result) {
186-
t.ok(result, 'Alice should have Read acces')
185+
t.ok(result, 'Alice should have Read acces - Public')
187186
} else {
188187
t.fail('Alice s....')
189188
}
190189

191-
result = aclLogic.checkAccess(kb, container, null, containerAcl, alice, [ ACL('Write')])
190+
result = aclLogic.checkAccess(store, container, null, containerAcl, alice, [ ACL('Write')])
192191
if (result) {
193192
t.ok(result, 'Alice should have Write acces')
194193
} else {
195194
t.fail('Alice s....')
196195
}
197196

198-
result = aclLogic.checkAccess(kb, container, null, containerAcl, bob, [ ACL('Write')])
199-
if (!result) {
200-
t.ok(result, 'Bob should not have Write acces')
197+
var result = aclLogic.checkAccess(store, container, null, containerAcl, null, [ ACL('Read')])
198+
if (result) {
199+
t.ok(result, 'Anonymous should have Read acces to public thing - Public')
200+
} else {
201+
t.fail('Alice s....')
202+
}
203+
204+
result = aclLogic.checkAccess(store, container, null, containerAcl, null, [ ACL('Write')])
205+
if (result) {
206+
t.ok(result, 'Anonymous should have Write acces - Public')
207+
} else {
208+
t.fail('Alice s....')
209+
}
210+
211+
result = aclLogic.checkAccess(store, container, null, containerAcl, bob, [ ACL('Write')])
212+
if (result) {
213+
t.ok(result, 'Bob should have Write acces to public write - Public')
201214
} else {
202215
t.fail('Alice s....')
203216
}
@@ -212,38 +225,38 @@ test('acl-check checkAccess() test - default/inherited', function (t) {
212225
let file1 = $rdf.sym('https://alice.example.com/docs/file1')
213226
let file2 = $rdf.sym('https://alice.example.com/docs/stuff/file2')
214227
var result
215-
const kb = $rdf.graph()
228+
const store = $rdf.graph()
216229
let ACLtext = prefixes + ` <#auth> a acl:Authorization;
217230
acl:mode acl:Read;
218231
acl:agent bob:me;
219232
acl:accessTo <${file1.uri}> .
220233
`
221-
$rdf.parse(ACLtext, kb, containerAcl.uri, 'text/turtle')
234+
$rdf.parse(ACLtext, store, containerAcl.uri, 'text/turtle')
222235

223236
let containerAclText = prefixes + ` <#auth> a acl:Authorization;
224237
acl:mode acl:Read;
225238
acl:agentClass foaf:Agent;
226239
acl:default <${container.uri}> .
227240
`
228-
$rdf.parse(containerAclText, kb, containerAcl.uri, 'text/turtle')
241+
$rdf.parse(containerAclText, store, containerAcl.uri, 'text/turtle')
229242

230-
result = aclLogic.checkAccess(kb, file1, container, containerAcl, alice, [ ACL('Read')])
243+
result = aclLogic.checkAccess(store, file1, container, containerAcl, alice, [ ACL('Read')])
231244
if (result) {
232-
t.ok(result, 'Alice should have Read acces inherited')
245+
t.ok(result, 'Alice should have Read acces inherited - Public')
233246
} else {
234247
t.fail('Alice s....')
235248
}
236249

237-
result = aclLogic.checkAccess(kb, file2, container, containerAcl, alice, [ ACL('Read')])
250+
result = aclLogic.checkAccess(store, file2, container, containerAcl, alice, [ ACL('Read')])
238251
if (result) {
239-
t.ok(result, 'Alice should have Read acces inherited 2')
252+
t.ok(result, 'Alice should have Read acces inherited 2 - Public')
240253
} else {
241254
t.fail('Alice s....')
242255
}
243256

244-
result = aclLogic.checkAccess(kb, file2, container, containerAcl, alice, [ ACL('Read')])
257+
result = aclLogic.checkAccess(store, file2, container, containerAcl, alice, [ ACL('Read')])
245258
if (result) {
246-
t.ok(result, 'Mallory should NOT have Read acces inherited')
259+
t.ok(result, 'Mallory should NOT have Read acces inherited - Public')
247260
} else {
248261
t.fail('Alice s....')
249262
}

0 commit comments

Comments
 (0)