@sync-in/server
Version:
The secure, open-source platform for file storage, sharing, collaboration, and sync
545 lines (544 loc) • 28.2 kB
JavaScript
/*
* Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>
* This file is part of Sync-in | The open source file sync and share solution
* See the LICENSE file for licensing details
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "WebDAVMethods", {
enumerable: true,
get: function() {
return WebDAVMethods;
}
});
const _common = require("@nestjs/common");
const _fastify = require("fastify");
const _shared = require("../../../common/shared");
const _fileerror = require("../../files/models/file-error");
const _filelockerror = require("../../files/models/file-lock-error");
const _fileslockmanagerservice = require("../../files/services/files-lock-manager.service");
const _filesmanagerservice = require("../../files/services/files-manager.service");
const _files = require("../../files/utils/files");
const _spaces = require("../../spaces/constants/spaces");
const _paths = require("../../spaces/utils/paths");
const _permissions = require("../../spaces/utils/permissions");
const _webdav = require("../constants/webdav");
const _ifheaderdecorator = require("../decorators/if-header.decorator");
const _webdavinterface = require("../interfaces/webdav.interface");
const _ifheader = require("../utils/if-header");
const _webdav1 = require("../utils/webdav");
const _xml = require("../utils/xml");
const _webdavspacesservice = require("./webdav-spaces.service");
function _ts_decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function _ts_metadata(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
}
let WebDAVMethods = class WebDAVMethods {
async headOrGet(req, res, repository) {
if (repository === _spaces.SPACE_REPOSITORY.FILES && !req.space.inSharesList) {
if (await (0, _files.isPathExists)(req.space.realPath) && await (0, _files.isPathIsDir)(req.space.realPath)) {
// Directory case
return res.header('DAV', _webdav.OPTIONS_HEADERS.DAV).header('Content-Type', 'httpd/unix-directory').header('Content-Length', '0').status(_common.HttpStatus.OK).send();
}
const sendFile = this.filesManager.sendFileFromSpace(req.space);
try {
await sendFile.checks();
return await sendFile.stream(req, res);
} catch (e) {
return this.handleError(req, res, e);
}
}
this.logger.warn(`Not allowed on this resource : ${repository}`);
return res.status(_common.HttpStatus.FORBIDDEN).send('Not allowed on this resource');
}
async lock(req, res) {
const isLockRefresh = !req.dav.body;
const rExists = await (0, _files.isPathExists)(req.space.realPath);
if (isLockRefresh) {
// if the body has no content, the request must refresh the lock
if (!rExists) {
this.logger.warn('Lock refresh must specify an existing resource');
return res.status(_common.HttpStatus.BAD_REQUEST).send('Lock refresh must specify an existing resource');
}
return this.lockRefresh(req, res, req.space.dbFile.path);
}
if (!rExists) {
if (!(0, _permissions.haveSpaceEnvPermissions)(req.space, _spaces.SPACE_OPERATION.ADD)) {
this.logger.warn(`is not allowed to create on this space : *${req.space.alias}* (${req.space.id}) : ${req.space.url}`);
return res.status(_common.HttpStatus.FORBIDDEN).send('You are not allowed to do this action');
}
if (!await (0, _files.isPathExists)((0, _files.dirName)(req.space.realPath))) {
return res.status(_common.HttpStatus.CONFLICT).send('Parent must exists');
}
}
const lockOptions = {
lockRoot: req.dav.url,
lockToken: this.filesLockManager.genDAVToken(),
lockScope: req.dav.lock.lockscope,
lockInfo: req.dav.lock?.owner
};
const [ok, fileLock] = await this.filesLockManager.create(req.user, req.space.dbFile, _webdav.WEBDAV_APP_LOCK, req.dav.depth, lockOptions, req.dav.lock.timeout);
if (ok) {
// Locking unmapped URLs: must create an empty resource (that is not a collection)
if (!rExists) {
// checkLocks set to false because the conflicts are already checked in the `filesLockManager.create` method
await this.filesManager.mkFile(req.user, req.space, false, false, false);
}
const lockProp = (0, _webdav1.LOCK_PROP)([
fileLock
]);
return res.header(_webdav.HEADER.LOCK_TOKEN, `<${lockOptions.lockToken}>`).type(_webdav.XML_CONTENT_TYPE).status(rExists ? _common.HttpStatus.OK : _common.HttpStatus.CREATED).send((0, _xml.xmlBuild)(lockProp));
}
if (fileLock) {
const lockProp = (0, _webdav1.LOCK_PROP)([
fileLock
]);
return res.type(_webdav.XML_CONTENT_TYPE).status(_common.HttpStatus.LOCKED).send((0, _xml.xmlBuild)(lockProp));
}
return (0, _webdav1.DAV_ERROR_RES)(_common.HttpStatus.LOCKED, _webdav.PRECONDITION.LOCK_CONFLICT, res, fileLock.options?.lockRoot || fileLock.dbFilePath);
}
async unlock(req, res) {
if (!await (0, _files.isPathExists)(req.space.realPath)) {
this.logger.warn(`Unable to unlock: ${req.dav.url} - resource does not exist`);
return res.status(_common.HttpStatus.NOT_FOUND).send(req.dav.url);
}
const lock = await this.filesLockManager.isLockedWithToken(req.dav.lock.token, req.space.dbFile.path);
if (!lock) {
this.logger.warn(`Lock token does not exist or not match URL : ${req.dav.lock.token}`);
return (0, _webdav1.DAV_ERROR_RES)(_common.HttpStatus.CONFLICT, _webdav.PRECONDITION.LOCK_TOKEN_MISMATCH, res);
}
if (req.user.id !== lock.owner.id) {
return res.status(_common.HttpStatus.FORBIDDEN).send('Token was created by another user');
}
await this.filesLockManager.removeLock(lock.key);
return res.status(_common.HttpStatus.NO_CONTENT).send();
}
async propfind(req, res, repository) {
if (repository === _spaces.SPACE_REPOSITORY.FILES && !req.space.inSharesList) {
if (!await (0, _files.isPathExists)(req.space.realPath)) {
return res.status(_common.HttpStatus.NOT_FOUND).send(req.dav.url);
}
}
const responses = [];
let requestedProps;
let locks = {};
if (req.dav.propfindMode === _webdav.PROPSTAT.PROP) {
// ignores all unknown properties (non-RFC compliant but avoids generating too much content, faster)
requestedProps = Object.keys(req.dav.body.propfind.prop).filter((prop)=>_webdav.STANDARD_PROPS.indexOf(prop) > -1);
} else {
requestedProps = _webdav.STANDARD_PROPS;
}
// Searches all child locks (only for real files) & ignores /webdav/shares endpoint (special case)
if (req.dav.propfindMode !== _webdav.PROPSTAT.PROPNAME && repository === _spaces.SPACE_REPOSITORY.FILES && !req.space.inSharesList) {
if (req.dav.depth === _webdav.DEPTH.RESOURCE) {
// match depth '0'
locks = await this.filesLockManager.browseLocks(req.space.dbFile);
} else {
// match depth '1' or 'infinity'
locks = await this.filesLockManager.browseParentChildLocks(req.space.dbFile);
}
}
for await (const f of this.webDAVHandler.propfind(req, repository)){
let prop;
if (req.dav.propfindMode === _webdav.PROPSTAT.PROPNAME) {
prop = {
...Object.fromEntries(requestedProps.map((x)=>[
`${_webdav.NS_PREFIX}:${x}`,
''
]))
};
} else {
prop = {};
for (const p of requestedProps){
let fP;
if (p === _webdav.LOCK_DISCOVERY_PROP) {
let lockDiscovery = null;
if (repository === _spaces.SPACE_REPOSITORY.FILES) {
if (f.name in locks) {
lockDiscovery = (0, _webdav1.LOCK_DISCOVERY)([
locks[f.name]
]);
} else {
// The lock name may correspond to the original file at the space root.
const fName = (0, _files.fileName)(req.space.dbFile.path);
if (fName in locks) {
lockDiscovery = (0, _webdav1.LOCK_DISCOVERY)([
locks[fName]
]);
}
}
}
fP = lockDiscovery;
} else {
fP = f[p];
}
if (fP !== undefined) prop[`${_webdav.NS_PREFIX}:${p}`] = fP;
}
}
responses.push((0, _webdav1.PROP_STAT)(f.href, (0, _webdav1.PROP)(prop, req.dav.httpVersion, _common.HttpStatus.OK)));
}
const propfind = (0, _xml.xmlBuild)((0, _webdav1.MULTI_STATUS)(responses));
return res.type(_webdav.XML_CONTENT_TYPE).status(_common.HttpStatus.MULTI_STATUS).send(propfind);
}
async put(req, res) {
let rExists;
try {
rExists = await this.filesManager.saveStream(req.user, req.space, req, {
dav: {
depth: req.dav.depth,
lockTokens: (0, _ifheader.extractAllTokens)(req.dav.ifHeaders)
}
});
} catch (e) {
return this.handleError(req, res, e);
}
return res.header('etag', (0, _files.genEtag)(null, req.space.realPath)).status(rExists ? _common.HttpStatus.NO_CONTENT : _common.HttpStatus.CREATED).send();
}
async delete(req, res) {
try {
await this.filesManager.delete(req.user, req.space, {
lockTokens: (0, _ifheader.extractAllTokens)(req.dav.ifHeaders)
});
} catch (e) {
return this.handleError(req, res, e);
}
return res.status(_common.HttpStatus.NO_CONTENT).send();
}
async proppatch(req, res) {
/* only support 'time modifications' */ if (!await (0, _files.isPathExists)(req.space.realPath)) {
return res.status(_common.HttpStatus.NOT_FOUND).send(req.dav.url);
}
// check locks
try {
await this.filesLockManager.checkConflicts(req.space.dbFile, req.dav.depth, {
userId: req.user.id,
lockTokens: (0, _ifheader.extractAllTokens)(req.dav.ifHeaders)
});
} catch (e) {
return this.handleError(req, res, e);
}
// evaluate props and return multistatus if errors
req.dav.proppatch = {
props: {},
errors: []
};
for (const action of Object.keys(req.dav.body[_webdav.PROPPATCH_PROP_UPDATE])){
if (Object.values(_webdav.PROPPATCH_METHOD).indexOf(action) === -1) {
const msg = `Unknown tag : expected ${_webdav.PROPPATCH_METHOD.SET} or ${_webdav.PROPPATCH_METHOD.REMOVE}`;
this.logger.debug(msg);
return res.status(_common.HttpStatus.BAD_REQUEST).send(msg);
}
if (Array.isArray(req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action])) {
if (Object.keys(req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action][0])[0] === _webdav.PROPSTAT.PROP) {
req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action] = {
[_webdav.PROPSTAT.PROP]: req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action].map((e)=>e[_webdav.PROPSTAT.PROP])
};
}
}
if (Object.keys(req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action])[0] !== _webdav.PROPSTAT.PROP) {
const msg = `Unknown tag : expected ${_webdav.PROPSTAT.PROP}`;
this.logger.debug(msg);
return res.status(_common.HttpStatus.BAD_REQUEST).send(msg);
}
if (!Array.isArray(req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action][_webdav.PROPSTAT.PROP])) {
req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action][_webdav.PROPSTAT.PROP] = [
req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action][_webdav.PROPSTAT.PROP]
];
}
for (const prop of req.dav.body[_webdav.PROPPATCH_PROP_UPDATE][action][_webdav.PROPSTAT.PROP]){
for (let [name, value] of Object.entries(prop)){
if (action === _webdav.PROPPATCH_METHOD.REMOVE) {
value = null;
this.logger.debug(`Proppatch remove method not handled : ${name} -> ${value}`);
}
if (_webdav.PROPPATCH_SUPPORTED_PROPS.indexOf(name) === -1) {
req.dav.proppatch.errors.push((0, _webdav1.PROP)({
[`${_webdav.NS_PREFIX}:${name}`]: null
}, req.dav.httpVersion, _common.HttpStatus.FORBIDDEN, _webdav.STANDARD_PROPS.indexOf(name) > -1 ? _webdav.PRECONDITION.PROTECTED_PROPERTY : undefined));
continue;
}
req.dav.proppatch.props[name] = value;
}
}
}
if (req.dav.proppatch.errors.length) {
// convert all passed props to failed dependency
for (const name of Object.keys(req.dav.proppatch.props)){
req.dav.proppatch.errors.push((0, _webdav1.PROP)({
[`${_webdav.NS_PREFIX}:${name}`]: null
}, req.dav.httpVersion, _common.HttpStatus.FAILED_DEPENDENCY));
}
const proppatch = (0, _xml.xmlBuild)((0, _webdav1.MULTI_STATUS)((0, _webdav1.PROP_STAT)((0, _shared.encodeUrl)(req.dav.url), req.dav.proppatch.errors)));
return res.status(_common.HttpStatus.MULTI_STATUS).type(_webdav.XML_CONTENT_TYPE).send(proppatch);
}
// apply modifications
let atLeastOneError = false;
const states = {};
for (const [name, value] of Object.entries(req.dav.proppatch.props)){
if (_webdav.PROPPATCH_MODIFIED_PROPS.indexOf(name) > -1) {
try {
await this.filesManager.touch(req.user, req.space, (0, _shared.currentTimeStamp)(new Date(value)), false);
} catch (e) {
this.logger.error(`${this.proppatch.name} - unable to modify mtime on ${req.dav.url} : ${e}`);
states[name] = false;
atLeastOneError = true;
}
}
// hook: we let the known Win32* properties pass to return a consistent result
states[name] = true;
}
const props = [];
for (const [name, state] of Object.entries(states)){
props.push((0, _webdav1.PROP)({
[`${_webdav.NS_PREFIX}:${name}`]: null
}, req.dav.httpVersion, state ? atLeastOneError ? _common.HttpStatus.FAILED_DEPENDENCY : _common.HttpStatus.OK : _common.HttpStatus.BAD_REQUEST));
}
const proppatch = (0, _xml.xmlBuild)((0, _webdav1.MULTI_STATUS)((0, _webdav1.PROP_STAT)((0, _shared.encodeUrl)(req.dav.url), props)));
return res.type(_webdav.XML_CONTENT_TYPE).status(_common.HttpStatus.MULTI_STATUS).send(proppatch);
}
async mkcol(req, res) {
try {
await this.filesManager.mkDir(req.user, req.space, false, {
depth: req.dav.depth,
lockTokens: (0, _ifheader.extractAllTokens)(req.dav.ifHeaders)
});
} catch (e) {
return this.handleError(req, res, e);
}
return res.status(_common.HttpStatus.CREATED).send();
}
async copyMove(req, res) {
const dstSpace = await this.webDAVHandler.spaceEnv(req.user, req.dav.copyMove.destination);
if (!dstSpace) {
this.logger.warn(`Space not found for destination : ${req.dav.copyMove.destination}`);
return res.status(_common.HttpStatus.NOT_FOUND).send(req.dav.copyMove.destination);
}
const dstExisted = await (0, _files.isPathExists)(dstSpace.realPath);
// We must evaluate the if-headers on the destination
const fakeDstReq = {
dav: {
...req.dav,
url: req.dav.copyMove.destination
},
user: req.user,
space: dstSpace
};
if (!await this.evaluateIfHeaders(fakeDstReq, res)) {
// if there is an error, the response is generated inside the `evaluateIfHeaders` function
return;
}
try {
await this.filesManager.copyMove(req.user, req.space, dstSpace, req.dav.copyMove.isMove, req.dav.copyMove.overwrite, false, {
depth: req.dav.depth,
lockTokens: (0, _ifheader.extractAllTokens)(req.dav.ifHeaders)
});
} catch (e) {
return this.handleError(req, res, e, dstSpace.url);
}
return res.status(dstExisted ? _common.HttpStatus.NO_CONTENT : _common.HttpStatus.CREATED).send();
}
async evaluateIfHeaders(req, res) {
if (!req.dav.ifHeaders) return true;
const errors = [];
let lastPath = null;
let lastSpaceEnv;
let lastRPath = undefined;
let lastEtag = undefined // for now, we only generate one etag type (weak)
;
let atLeastOneOk = false;
for (const condition of req.dav.ifHeaders){
if (condition.path) {
if (condition.path !== lastPath) {
lastPath = condition.path;
lastSpaceEnv = await this.webDAVHandler.spaceEnv(req.user, lastPath);
}
// the path will be the same across conditions
if (!lastSpaceEnv) {
this.logger.warn(`If Header : path mismatch (${condition.path})`);
return false;
}
} else {
lastPath = req.dav.url;
lastSpaceEnv = req.space;
}
if (condition.haveLock) {
try {
const dbFile = (0, _paths.dbFileFromSpace)(req.user.id, lastSpaceEnv);
const match = !!(await this.filesLockManager.getLocksByPath(dbFile)).length;
if (condition.haveLock.mustMatch !== match) {
errors.push(`have lock condition mismatch (${condition.haveLock.mustMatch} != ${match})`);
continue;
}
} catch (e) {
errors.push(`have lock condition mismatch : ${e.message}`);
continue;
}
}
if (condition.token) {
const token = await this.filesLockManager.getLockByToken(condition.token.value);
const match = token && lastPath.startsWith(token.options?.lockRoot);
if (condition.token.mustMatch !== match) {
if (!token) {
errors.push(`lock token not found`);
} else {
errors.push(`lock token url mismatch (${lastPath} is not a child of ${token.options?.lockRoot})`);
}
continue;
}
}
if (condition.etag) {
if (lastEtag === undefined) {
if (lastRPath === undefined) {
lastRPath = await (0, _files.isPathExists)(req.space.realPath) ? req.space.realPath : null;
}
lastEtag = lastRPath ? (0, _files.genEtag)(null, lastRPath) : null;
}
const match = lastEtag === condition.etag.value;
if (condition.etag.mustMatch !== match) {
errors.push(`etag mismatch (${condition.etag.value} != ${lastEtag})`);
continue;
}
}
atLeastOneOk = true;
break;
}
if (!atLeastOneOk) {
this.logger.warn(`If header condition failed : ${errors.join(', ')}`);
res.status(_common.HttpStatus.PRECONDITION_FAILED).send('If header condition failed');
}
return atLeastOneOk;
}
async lockRefresh(req, res, dbFilePath) {
if (req.dav?.ifHeaders?.length !== 1) {
this.logger.warn('Expected a lock token (only one lock may be refreshed at a time)');
return res.status(_common.HttpStatus.BAD_REQUEST).send('Expected a lock token (only one lock may be refreshed at a time)');
}
let token;
try {
token = (0, _ifheader.extractOneToken)(req.dav.ifHeaders);
} catch (e) {
this.logger.warn(`${this.lockRefresh.name} - unable to extract token : ${JSON.stringify(req.dav.ifHeaders)} (${e})`);
return res.status(_common.HttpStatus.BAD_REQUEST).send('Unable to extract token');
}
const lock = await this.filesLockManager.isLockedWithToken(token, dbFilePath);
if (!lock) {
this.logger.warn(`Lock token does not exist or not match URL : ${token}`);
return (0, _webdav1.DAV_ERROR_RES)(_common.HttpStatus.PRECONDITION_FAILED, _webdav.PRECONDITION.LOCK_TOKEN_MISMATCH, res);
}
if (lock.owner.id !== req.user.id) {
this.logger.warn(`Lock token does not match owner : ${lock.owner.login} != ${req.user.login}`);
return res.status(_common.HttpStatus.FORBIDDEN).send('Lock token does not match owner');
}
await this.filesLockManager.refreshLockTimeout(lock, req.dav.lock.timeout);
const lockProp = (0, _webdav1.LOCK_PROP)([
lock
]);
return res.type(_webdav.XML_CONTENT_TYPE).status(_common.HttpStatus.OK).send((0, _xml.xmlBuild)(lockProp));
}
handleError(req, res, e, toUrl) {
this.logger.error(`Unable to ${req.method} ${req.dav.url}${toUrl ? ` -> ${toUrl}` : ''} : ${e.message}`);
// Remove the last part to avoid exposing the path
const errorMsg = e.message.split(',')[0];
if (e instanceof _filelockerror.LockConflict) {
return (0, _webdav1.DAV_ERROR_RES)(_common.HttpStatus.LOCKED, _webdav.PRECONDITION.LOCK_CONFLICT, res, e.lock.options?.lockRoot || e.lock.dbFilePath);
} else if (e instanceof _fileerror.FileError) {
return res.status(e.httpCode).send(errorMsg);
}
throw new _common.HttpException(errorMsg, _common.HttpStatus.INTERNAL_SERVER_ERROR);
}
constructor(webDAVHandler, filesManager, filesLockManager){
this.webDAVHandler = webDAVHandler;
this.filesManager = filesManager;
this.filesLockManager = filesLockManager;
this.logger = new _common.Logger(WebDAVMethods.name);
}
};
_ts_decorate([
(0, _ifheaderdecorator.IfHeaderDecorator)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply
]),
_ts_metadata("design:returntype", Promise)
], WebDAVMethods.prototype, "lock", null);
_ts_decorate([
(0, _ifheaderdecorator.IfHeaderDecorator)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply
]),
_ts_metadata("design:returntype", Promise)
], WebDAVMethods.prototype, "unlock", null);
_ts_decorate([
(0, _ifheaderdecorator.IfHeaderDecorator)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply,
String
]),
_ts_metadata("design:returntype", Promise)
], WebDAVMethods.prototype, "propfind", null);
_ts_decorate([
(0, _ifheaderdecorator.IfHeaderDecorator)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply
]),
_ts_metadata("design:returntype", Promise)
], WebDAVMethods.prototype, "put", null);
_ts_decorate([
(0, _ifheaderdecorator.IfHeaderDecorator)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply
]),
_ts_metadata("design:returntype", Promise)
], WebDAVMethods.prototype, "delete", null);
_ts_decorate([
(0, _ifheaderdecorator.IfHeaderDecorator)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply
]),
_ts_metadata("design:returntype", Promise)
], WebDAVMethods.prototype, "proppatch", null);
_ts_decorate([
(0, _ifheaderdecorator.IfHeaderDecorator)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply
]),
_ts_metadata("design:returntype", Promise)
], WebDAVMethods.prototype, "mkcol", null);
_ts_decorate([
(0, _ifheaderdecorator.IfHeaderDecorator)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply
]),
_ts_metadata("design:returntype", Promise)
], WebDAVMethods.prototype, "copyMove", null);
WebDAVMethods = _ts_decorate([
(0, _common.Injectable)(),
_ts_metadata("design:type", Function),
_ts_metadata("design:paramtypes", [
typeof _webdavspacesservice.WebDAVSpaces === "undefined" ? Object : _webdavspacesservice.WebDAVSpaces,
typeof _filesmanagerservice.FilesManager === "undefined" ? Object : _filesmanagerservice.FilesManager,
typeof _fileslockmanagerservice.FilesLockManager === "undefined" ? Object : _fileslockmanagerservice.FilesLockManager
])
], WebDAVMethods);
//# sourceMappingURL=webdav-methods.service.js.map