@@ -20,9 +20,9 @@ function publisherTrustedApp (kb, doc, aclDoc, modesRequired, origin, docAuths)
20
20
// modesRequired.every(mode => appAuths.some(auth => kb.holds(auth, ACL('mode'), mode, aclDoc)))
21
21
}
22
22
23
- function accessDenied ( kb , doc , directory , aclDoc , agent , modesRequired , origin , trustedOrigins ) {
23
+ function accessDenied ( kb , doc , directory , aclDoc , agent , modesRequired , origin , trustedOrigins , originTrustedModes = [ ] ) {
24
24
log ( `accessDenied: checking access to ${ doc } by ${ agent } and origin ${ origin } ` )
25
- let modeURIorReasons = modesAllowed ( kb , doc , directory , aclDoc , agent , origin , trustedOrigins )
25
+ const modeURIorReasons = modesAllowed ( kb , doc , directory , aclDoc , agent , origin , trustedOrigins , originTrustedModes )
26
26
let ok = false
27
27
log ( 'accessDenied: modeURIorReasons: ' + JSON . stringify ( Array . from ( modeURIorReasons ) ) )
28
28
modesRequired . forEach ( mode => {
@@ -44,15 +44,70 @@ function accessDenied (kb, doc, directory, aclDoc, agent, modesRequired, origin,
44
44
return ok
45
45
}
46
46
47
+ async function getTrustedModesForOrigin ( kb , doc , directory , aclDoc , origin , fetch ) {
48
+ // FIXME: this is duplicate code from the modesAllowed function, will refactor,
49
+ // see https://github.com/solid/acl-check/issues/22
50
+ var auths
51
+ if ( ! directory ) { // Normal case, ACL for a file
52
+ auths = kb . each ( null , ACL ( 'accessTo' ) , doc , aclDoc )
53
+ log ( ` ${ auths . length } direct authentications about ${ doc } ` )
54
+ } else {
55
+ auths = kb . each ( null , ACL ( 'default' ) , directory , null )
56
+ auths = auths . concat ( kb . each ( null , ACL ( 'defaultForNew' ) , directory , null ) ) // Deprecated but keep for ages
57
+ log ( ` ${ auths . length } default authentications about ${ directory } in ${ aclDoc } ` )
58
+ }
59
+ const ownerAuths = auths . filter ( auth => kb . holds ( auth , ACL ( 'mode' ) , ACL ( 'Control' ) , aclDoc ) )
60
+ const owners = ownerAuths . reduce ( ( acc , auth ) => acc . concat ( kb . each ( auth , ACL ( 'agent' ) ) ) , [ ] ) // owners
61
+ let result
62
+ try {
63
+ result = await Promise . all ( owners . map ( owner => {
64
+ return fetch ( owner ) . then ( ( ) => {
65
+ const q = `
66
+ SELECT ?mode WHERE {
67
+ ${ owner } ${ ACL ( 'trustedApp' ) } ?trustedOrigin.
68
+ ?trustedOrigin ${ ACL ( 'origin' ) } ${ origin } ;
69
+ ${ ACL ( 'mode' ) } ?mode .
70
+ }`
71
+ return query ( q , kb )
72
+ } ) . catch ( e => {
73
+ log ( 'could not fetch owner doc' , owner , e . message )
74
+ } )
75
+ } ) )
76
+ } catch ( e ) {
77
+ log ( 'error checking owner profiles' , e . message )
78
+ }
79
+ let trustedModes = [ ]
80
+ result . map ( ownerResults => ownerResults . map ( entry => {
81
+ trustedModes . push ( entry [ '?mode' ] )
82
+ } ) )
83
+ return Promise . resolve ( trustedModes )
84
+ }
85
+
86
+ async function query ( queryString , store ) {
87
+ return new Promise ( ( resolve , reject ) => {
88
+ try {
89
+ const query = $rdf . SPARQLToQuery ( queryString , true , store )
90
+ const results = [ ]
91
+ store . query ( query , ( result ) => {
92
+ results . push ( result )
93
+ } , null , ( ) => {
94
+ resolve ( results )
95
+ } )
96
+ } catch ( err ) {
97
+ reject ( err )
98
+ }
99
+ } )
100
+ }
101
+
47
102
/* Function checkAccess
48
103
** @param kb A quadstore
49
104
** @param doc the resource (A named node) or directory for which ACL applies
50
105
*/
51
- function checkAccess ( kb , doc , directory , aclDoc , agent , modesRequired , origin , trustedOrigins ) {
52
- return ! accessDenied ( kb , doc , directory , aclDoc , agent , modesRequired , origin , trustedOrigins )
106
+ function checkAccess ( kb , doc , directory , aclDoc , agent , modesRequired , origin , trustedOrigins , originTrustedModes ) {
107
+ return ! accessDenied ( kb , doc , directory , aclDoc , agent , modesRequired , origin , trustedOrigins , originTrustedModes )
53
108
}
54
109
55
- function modesAllowed ( kb , doc , directory , aclDoc , agent , origin , trustedOrigins ) {
110
+ function modesAllowed ( kb , doc , directory , aclDoc , agent , origin , trustedOrigins , originTrustedModes = [ ] ) {
56
111
var auths
57
112
if ( ! directory ) { // Normal case, ACL for a file
58
113
auths = kb . each ( null , ACL ( 'accessTo' ) , doc , aclDoc )
@@ -62,7 +117,7 @@ function modesAllowed (kb, doc, directory, aclDoc, agent, origin, trustedOrigins
62
117
auths = auths . concat ( kb . each ( null , ACL ( 'defaultForNew' ) , directory , null ) ) // Deprecated but keep for ages
63
118
log ( ` ${ auths . length } default authentications about ${ directory } in ${ aclDoc } ` )
64
119
}
65
- if ( origin && trustedOrigins && trustedOriginsIncludeOrigin ( trustedOrigins , origin ) ) {
120
+ if ( origin && trustedOrigins && nodesIncludeNode ( trustedOrigins , origin ) ) {
66
121
log ( 'Origin ' + origin + ' is trusted' )
67
122
origin = null // stop worrying about origin
68
123
log ( ` modesAllowed: Origin ${ origin } is trusted.` )
@@ -108,6 +163,10 @@ function modesAllowed (kb, doc, directory, aclDoc, agent, origin, trustedOrigins
108
163
log ( ' Origin check not needed: no origin.' )
109
164
return false
110
165
}
166
+ if ( originTrustedModes && originTrustedModes . length > 0 ) {
167
+ log ( ` Origin might have access (${ originTrustedModes . join ( ', ' ) } )` )
168
+ return false
169
+ }
111
170
if ( originOK ( auth , origin ) ) {
112
171
log ( ' Origin check succeeded.' )
113
172
return false
@@ -125,6 +184,9 @@ function modesAllowed (kb, doc, directory, aclDoc, agent, origin, trustedOrigins
125
184
modeURIorReasons . add ( agentAndAppStatus )
126
185
} else {
127
186
let modes = kb . each ( auth , ACL ( 'mode' ) , null , aclDoc )
187
+ if ( originTrustedModes && originTrustedModes . length > 0 ) {
188
+ modes = modes . filter ( mode => nodesIncludeNode ( originTrustedModes , mode ) )
189
+ }
128
190
modes . forEach ( mode => {
129
191
log ( ' Mode allowed: ' + mode )
130
192
modeURIorReasons . add ( mode . uri )
@@ -134,9 +196,8 @@ function modesAllowed (kb, doc, directory, aclDoc, agent, origin, trustedOrigins
134
196
return modeURIorReasons
135
197
}
136
198
137
- function trustedOriginsIncludeOrigin ( trustedOrigins , origin ) {
138
- return trustedOrigins . filter (
139
- trustedOrigin => trustedOrigin . termType === origin . termType && trustedOrigin . value === origin . value ) . length > 0
199
+ function nodesIncludeNode ( nodes , node ) {
200
+ return nodes . some ( trustedOrigin => trustedOrigin . termType === node . termType && trustedOrigin . value === node . value )
140
201
}
141
202
142
203
function configureLogger ( logger ) {
@@ -147,9 +208,10 @@ function log (...msgs) {
147
208
return ( _logger || console . log ) . apply ( _logger , msgs )
148
209
}
149
210
211
+ module . exports . accessDenied = accessDenied
150
212
module . exports . checkAccess = checkAccess
151
213
module . exports . configureLogger = configureLogger
214
+ module . exports . getTrustedModesForOrigin = getTrustedModesForOrigin
152
215
module . exports . log = log
153
- module . exports . accessDenied = accessDenied
154
216
module . exports . modesAllowed = modesAllowed
155
217
module . exports . publisherTrustedApp = publisherTrustedApp
0 commit comments