@@ -44,10 +44,12 @@ function patchHandler (req, res, next) {
4444 return next ( error ( 415 , `Unsupported patch content type: ${ patch . contentType } ` ) )
4545 }
4646
47- // Parse the target graph and the patch document
47+ // Parse the target graph and the patch document,
48+ // and verify permission for performing this specific patch
4849 Promise . all ( [
4950 readGraph ( target ) ,
5051 parsePatch ( target . uri , patch . uri , patch . text )
52+ . then ( patchObject => checkPermission ( target , req , patchObject ) )
5153 ] )
5254 // Patch the graph and write it back to the file
5355 . then ( ( [ graph , patchObject ] ) => applyPatch ( patchObject , graph , target ) )
@@ -96,6 +98,36 @@ function readGraph (resource) {
9698 } )
9799}
98100
101+ // Verifies whether the user is allowed to perform the patch on the target
102+ function checkPermission ( target , request , patchObject ) {
103+ // If no ACL object was passed down, assume permissions are okay.
104+ if ( ! request . acl ) return Promise . resolve ( patchObject )
105+ // At this point, we already assume append access,
106+ // as this can be checked upfront before parsing the patch.
107+ // Now that we know the details of the patch,
108+ // we might need to perform additional checks.
109+ var checks = [ ]
110+ // Read access is required for DELETE and WHERE.
111+ // If we would allows users without read access,
112+ // they could use DELETE or WHERE to trigger 200 or 409,
113+ // and thereby guess the existence of certain triples.
114+ // DELETE additionally requires write access.
115+ if ( patchObject . delete ) {
116+ checks = [ hasPermission ( 'Read' ) , hasPermission ( 'Write' ) ]
117+ } else if ( patchObject . where ) {
118+ checks = [ hasPermission ( 'Read' ) ]
119+ }
120+ return Promise . all ( checks ) . then ( ( ) => patchObject )
121+
122+ // Checks whether the user has the given permission on the target
123+ function hasPermission ( mode ) {
124+ return new Promise ( ( resolve , reject ) =>
125+ request . acl . can ( request . userId , mode , target . uri ,
126+ err => err ? reject ( err ) : resolve ( ) )
127+ )
128+ }
129+ }
130+
99131// Applies the patch to the RDF graph
100132function applyPatch ( patchObject , graph , target ) {
101133 debug ( 'PATCH -- Applying patch' )
0 commit comments