(request, patchObject, resourceExists)
| 145 | |
| 146 | // Verifies whether the user is allowed to perform the patch on the target |
| 147 | async function checkPermission (request, patchObject, resourceExists) { |
| 148 | // If no ACL object was passed down, assume permissions are okay. |
| 149 | if (!request.acl) return Promise.resolve(patchObject) |
| 150 | // At this point, we already assume append access, |
| 151 | // as this can be checked upfront before parsing the patch. |
| 152 | // Now that we know the details of the patch, |
| 153 | // we might need to perform additional checks. |
| 154 | let modes = [] |
| 155 | const { acl, session: { userId } } = request |
| 156 | // Read access is required for DELETE and WHERE. |
| 157 | // If we would allows users without read access, |
| 158 | // they could use DELETE or WHERE to trigger 200 or 409, |
| 159 | // and thereby guess the existence of certain triples. |
| 160 | // DELETE additionally requires write access. |
| 161 | if (patchObject.delete) { |
| 162 | // ACTUALLY Read not needed by solid/test-suite only Write |
| 163 | modes = ['Read', 'Write'] |
| 164 | // checks = [acl.can(userId, 'Read'), acl.can(userId, 'Write')] |
| 165 | } else if (patchObject.where) { |
| 166 | modes = modes.concat(['Read']) |
| 167 | // checks = [acl.can(userId, 'Read')] |
| 168 | } |
| 169 | const allowed = await Promise.all(modes.map(mode => acl.can(userId, mode, request.method, resourceExists))) |
| 170 | const allAllowed = allowed.reduce((memo, allowed) => memo && allowed, true) |
| 171 | if (!allAllowed) { |
| 172 | // check owner with Control |
| 173 | const ldp = request.app.locals.ldp |
| 174 | if (request.path.endsWith('.acl') && await ldp.isOwner(userId, request.hostname)) return Promise.resolve(patchObject) |
| 175 | |
| 176 | const errors = await Promise.all(modes.map(mode => acl.getError(userId, mode))) |
| 177 | const error = errors.filter(error => !!error) |
| 178 | .reduce((prevErr, err) => prevErr.status > err.status ? prevErr : err, { status: 0 }) |
| 179 | return Promise.reject(error) |
| 180 | } |
| 181 | return Promise.resolve(patchObject) |
| 182 | } |
| 183 | |
| 184 | // Applies the patch to the RDF graph |
| 185 | function applyPatch (patchObject, graph, url) { |
no test coverage detected