UNPKG

nephele

Version:

Highly customizable and extensible WebDAV server for Node.js and Express.

156 lines 6.62 kB
import { ForbiddenError, LockedError, MediaTypeNotSupportedError, NotAcceptableError, UnauthorizedError, } from '../Errors/index.js'; import { catchErrors } from '../catchErrors.js'; import { MultiStatus, Status } from '../MultiStatus.js'; import { Method } from './Method.js'; export class DELETE extends Method { async run(request, response) { const { url, encoding } = this.getRequestData(request, response); if (await this.runPlugins(request, response, 'beginDelete', { method: this, url, })) { return; } if (await this.isAdapterRoot(request, response, url)) { throw new ForbiddenError('This collection cannot be deleted.'); } await this.checkAuthorization(request, response, 'DELETE'); const contentType = request.accepts('application/xml', 'text/xml'); if (!contentType) { throw new NotAcceptableError('Requested content type is not supported.'); } const resource = await response.locals.adapter.getResource(url, response.locals.baseUrl); if (await this.runPlugins(request, response, 'preDelete', { method: this, resource, })) { return; } let stream = await this.getBodyStream(request, response); let providedBody = false; stream.on('data', (data) => { if (data.toString().trim()) { providedBody = true; } }); await new Promise((resolve, _reject) => { stream.on('end', () => { resolve(); }); }); if (providedBody) { response.locals.debug('Provided body to DELETE.'); throw new MediaTypeNotSupportedError("This server doesn't understand the body sent in the request."); } const lockPermission = await this.getLockPermission(request, response, resource, response.locals.user); if (lockPermission === 1) { throw new LockedError('The user does not have permission to remove a resource from the locked collection.'); } if (lockPermission === 0) { throw new LockedError('The user does not have permission to delete the locked resource.'); } await this.checkConditionalHeaders(request, response); if (await this.runPlugins(request, response, 'beforeDelete', { method: this, resource, })) { return; } response.set({ 'Cache-Control': 'private, no-cache', Date: new Date().toUTCString(), }); if (await resource.isCollection()) { const multiStatus = new MultiStatus(); await this.recursivelyDelete(resource, request, response, multiStatus); if (multiStatus.statuses.length === 0) { const locks = await this.getCurrentResourceLocks(resource); for (let lock of locks) { await lock.delete(); } await resource.delete(response.locals.user); response.status(204); response.end(); } else { const responseXml = await this.renderXml(multiStatus.render()); response.status(207); response.set({ 'Content-Type': `${contentType}; charset=utf-8`, }); this.sendBodyContent(response, responseXml, encoding); } } else { const locks = await this.getCurrentResourceLocks(resource); for (let lock of locks) { await lock.delete(); } await resource.delete(response.locals.user); response.status(204); response.end(); } await this.runPlugins(request, response, 'afterDelete', { method: this, resource, }); } async recursivelyDelete(collection, request, response, multiStatus) { try { const children = await collection.getInternalMembers(response.locals.user); let allDeleted = true; for (let child of children) { const run = catchErrors(async () => { if (await this.isAdapterRoot(request, response, await child.getCanonicalUrl())) { throw new ForbiddenError('This collection cannot be deleted.'); } const lockPermission = await this.getLockPermission(request, response, child, response.locals.user); if (lockPermission !== 2) { throw new LockedError('This resource is locked.'); } if (await child.isCollection()) { allDeleted = allDeleted && (await this.recursivelyDelete(child, request, response, multiStatus)); } const locks = await this.getCurrentResourceLocks(child); for (let lock of locks) { await lock.delete(); } await child.delete(response.locals.user); }, async (code, message, error) => { if (code === 500 && error) { response.locals.debug('Unknown Error: %o', error); } const url = await child.getCanonicalUrl(); let status = new Status(url, code); if (message) { status.description = message; } if (error instanceof LockedError) { status.setBody({ error: [{ 'lock-token-submitted': {} }] }); } response.locals.errors.push(status); multiStatus.addStatus(status); allDeleted = false; }); await run(); } return allDeleted; } catch (e) { const url = await collection.getCanonicalUrl(); let error = new Status(url, 500); if (e instanceof UnauthorizedError) { error = new Status(url, 401); } if (e.message) { error.description = e.message; } response.locals.errors.push(error); multiStatus.addStatus(error); return false; } } } //# sourceMappingURL=DELETE.js.map