@@ -4,16 +4,17 @@ const path = require('path')
44const PermissionSet = require ( 'solid-permissions' ) . PermissionSet
55const rdf = require ( 'rdflib' )
66const url = require ( 'url' )
7+ const debug = require ( './debug' ) . ACL
78const HTTPError = require ( './http-error' )
89
910const DEFAULT_ACL_SUFFIX = '.acl'
1011
12+ // An ACLChecker exposes the permissions on a specific resource
1113class ACLChecker {
1214 constructor ( resource , options = { } ) {
1315 this . resource = resource
1416 this . host = options . host
1517 this . origin = options . origin
16- this . debug = options . debug || console . log . bind ( console )
1718 this . fetch = options . fetch
1819 this . strictOrigin = options . strictOrigin
1920 this . suffix = options . suffix || DEFAULT_ACL_SUFFIX
@@ -22,7 +23,7 @@ class ACLChecker {
2223 // Returns a fulfilled promise when the user can access the resource
2324 // in the given mode, or a rejected promise otherwise
2425 can ( user , mode ) {
25- this . debug ( `Can ${ user || 'an agent' } ${ mode } ${ this . resource } ?` )
26+ debug ( `Can ${ user || 'an agent' } ${ mode } ${ this . resource } ?` )
2627 // If this is an ACL, Control mode must be present for any operations
2728 if ( this . isAcl ( this . resource ) ) {
2829 mode = 'Control'
@@ -34,16 +35,16 @@ class ACLChecker {
3435 . then ( acl => this . getPermissionSet ( acl ) )
3536 }
3637
37- // Check the permissions
38+ // Check the resource's permissions
3839 return this . _permissionSet . then ( acls => this . checkAccess ( acls , user , mode ) )
39- . then ( ( ) => { this . debug ( 'ACL policy found' ) } )
40+ . then ( ( ) => { debug ( 'ACL policy found' ) } )
4041 . catch ( err => {
41- this . debug ( `Error: ${ err . message } ` )
42+ debug ( `Error: ${ err . message } ` )
4243 if ( ! user ) {
43- this . debug ( 'Authentication required' )
44+ debug ( 'Authentication required' )
4445 throw new HTTPError ( 401 , `Access to ${ this . resource } requires authorization` )
4546 } else {
46- this . debug ( `${ mode } access denied for ${ user } ` )
47+ debug ( `${ mode } access denied for ${ user } ` )
4748 throw new HTTPError ( 403 , `Access to ${ this . resource } denied for ${ user } ` )
4849 }
4950 } )
@@ -52,13 +53,14 @@ class ACLChecker {
5253 // Gets the ACL that applies to the resource
5354 getNearestACL ( ) {
5455 let isContainer = false
56+ // Create a cascade of reject handlers (one for each possible ACL)
5557 let nearestACL = Promise . reject ( )
5658 for ( const acl of this . getPossibleACLs ( ) ) {
5759 nearestACL = nearestACL . catch ( ( ) => new Promise ( ( resolve , reject ) => {
58- this . debug ( `Check if ACL exists: ${ acl } ` )
60+ debug ( `Check if ACL exists: ${ acl } ` )
5961 this . fetch ( acl , ( err , graph ) => {
6062 if ( err || ! graph || ! graph . length ) {
61- if ( err ) this . debug ( `Error reading ${ acl } : ${ err } ` )
63+ if ( err ) debug ( `Error reading ${ acl } : ${ err } ` )
6264 isContainer = true
6365 reject ( err )
6466 } else {
@@ -70,26 +72,26 @@ class ACLChecker {
7072 return nearestACL . catch ( e => { throw new Error ( 'No ACL resource found' ) } )
7173 }
7274
73- // Get all possible ACL paths that apply to the resource
75+ // Gets all possible ACL paths that apply to the resource
7476 getPossibleACLs ( ) {
75- var uri = this . resource
76- var suffix = this . suffix
77- var first = uri . endsWith ( suffix ) ? uri : uri + suffix
78- var urls = [ first ]
79- var parsedUri = url . parse ( uri )
80- var baseUrl = ( parsedUri . protocol ? parsedUri . protocol + '//' : '' ) +
77+ let uri = this . resource
78+ const suffix = this . suffix
79+ const first = uri . endsWith ( suffix ) ? uri : uri + suffix
80+ const urls = [ first ]
81+ const parsedUri = url . parse ( uri )
82+ const baseUrl = ( parsedUri . protocol ? parsedUri . protocol + '//' : '' ) +
8183 ( parsedUri . host || '' )
8284 if ( baseUrl + '/' === uri ) {
8385 return urls
8486 }
8587
86- var times = parsedUri . pathname . split ( '/' ) . length
88+ let times = parsedUri . pathname . split ( '/' ) . length
8789 // TODO: improve temporary solution to stop recursive path walking above root
8890 if ( parsedUri . pathname . endsWith ( '/' ) ) {
8991 times --
9092 }
9193
92- for ( var i = 0 ; i < times - 1 ; i ++ ) {
94+ for ( let i = 0 ; i < times - 1 ; i ++ ) {
9395 uri = path . dirname ( uri )
9496 urls . push ( uri + ( uri [ uri . length - 1 ] === '/' ? suffix : '/' + suffix ) )
9597 }
@@ -101,23 +103,22 @@ class ACLChecker {
101103 return permissionSet . checkAccess ( this . resource , user , mode )
102104 . then ( hasAccess => {
103105 if ( hasAccess ) {
104- this . debug ( `${ mode } access permitted to ${ user } ` )
106+ debug ( `${ mode } access permitted to ${ user } ` )
105107 return true
106108 } else {
107- this . debug ( `${ mode } access NOT permitted to ${ user } ` )
109+ debug ( `${ mode } access NOT permitted to ${ user } ` )
108110 throw new Error ( 'ACL file found but no matching policy found' )
109111 }
110112 } )
111113 . catch ( err => {
112- this . debug ( `${ mode } access denied to ${ user } ` )
113- this . debug ( err )
114+ debug ( `${ mode } access denied to ${ user } ` )
115+ debug ( err )
114116 throw err
115117 } )
116118 }
117119
118120 // Gets the permission set for the given ACL
119121 getPermissionSet ( { acl, graph, isContainer } ) {
120- const debug = this . debug
121122 if ( ! graph || graph . length === 0 ) {
122123 debug ( 'ACL ' + acl + ' is empty' )
123124 throw new Error ( 'No policy found - empty ACL' )
@@ -136,19 +137,11 @@ class ACLChecker {
136137 }
137138
138139 aclUrlFor ( uri ) {
139- if ( this . isAcl ( uri ) ) {
140- return uri
141- } else {
142- return uri + this . suffix
143- }
140+ return this . isAcl ( uri ) ? uri : uri + this . suffix
144141 }
145142
146143 isAcl ( resource ) {
147- if ( typeof resource === 'string' ) {
148- return resource . endsWith ( this . suffix )
149- } else {
150- return false
151- }
144+ return resource . endsWith ( this . suffix )
152145 }
153146}
154147
0 commit comments