@internxt/cli 1.2.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +3 -1
- package/README.md +405 -26
- package/dist/commands/config.js +1 -1
- package/dist/commands/create-folder.js +1 -1
- package/dist/commands/list.js +1 -2
- package/dist/commands/{move.d.ts → move-file.d.ts} +5 -4
- package/dist/commands/move-file.js +84 -0
- package/dist/commands/move-folder.d.ts +19 -0
- package/dist/commands/move-folder.js +84 -0
- package/dist/commands/rename.d.ts +18 -0
- package/dist/commands/{move.js → rename.js} +29 -29
- package/dist/commands/trash-clear.d.ts +15 -0
- package/dist/commands/trash-clear.js +64 -0
- package/dist/commands/trash-list.d.ts +20 -0
- package/dist/commands/trash-list.js +95 -0
- package/dist/commands/trash-restore-file.d.ts +19 -0
- package/dist/commands/trash-restore-file.js +87 -0
- package/dist/commands/trash-restore-folder.d.ts +19 -0
- package/dist/commands/trash-restore-folder.js +87 -0
- package/dist/commands/webdav-config.d.ts +17 -0
- package/dist/commands/webdav-config.js +91 -0
- package/dist/commands/webdav.d.ts +1 -1
- package/dist/commands/webdav.js +5 -2
- package/dist/database/migrations/20241018114828-add-parent-column.d.ts +1 -0
- package/dist/database/migrations/20241018114828-add-parent-column.js +24 -0
- package/dist/hooks/prerun/auth_check.js +2 -1
- package/dist/services/analytics.service.d.ts +9 -6
- package/dist/services/analytics.service.js +2 -35
- package/dist/services/config.service.d.ts +6 -1
- package/dist/services/config.service.js +24 -0
- package/dist/services/crypto.service.js +9 -1
- package/dist/services/database/drive-database-manager.service.d.ts +10 -7
- package/dist/services/database/drive-database-manager.service.js +34 -24
- package/dist/services/database/drive-file/drive-file.attributes.d.ts +1 -0
- package/dist/services/database/drive-file/drive-file.domain.d.ts +4 -1
- package/dist/services/database/drive-file/drive-file.domain.js +21 -1
- package/dist/services/database/drive-file/drive-file.model.d.ts +1 -0
- package/dist/services/database/drive-file/drive-file.model.js +4 -0
- package/dist/services/database/drive-folder/drive-folder.attributes.d.ts +1 -0
- package/dist/services/database/drive-folder/drive-folder.domain.d.ts +4 -1
- package/dist/services/database/drive-folder/drive-folder.domain.js +18 -1
- package/dist/services/database/drive-folder/drive-folder.model.d.ts +1 -0
- package/dist/services/database/drive-folder/drive-folder.model.js +5 -0
- package/dist/services/drive/drive-file.service.d.ts +5 -0
- package/dist/services/drive/drive-file.service.js +10 -0
- package/dist/services/drive/drive-folder.service.d.ts +7 -2
- package/dist/services/drive/drive-folder.service.js +16 -0
- package/dist/services/drive/trash.service.d.ts +7 -0
- package/dist/services/drive/trash.service.js +30 -0
- package/dist/services/network/upload.service.js +5 -1
- package/dist/services/sdk-manager.service.d.ts +1 -2
- package/dist/services/sdk-manager.service.js +0 -5
- package/dist/services/usage.service.d.ts +2 -1
- package/dist/services/usage.service.js +3 -7
- package/dist/services/validation.service.d.ts +2 -0
- package/dist/services/validation.service.js +6 -0
- package/dist/types/command.types.d.ts +16 -0
- package/dist/types/command.types.js +29 -1
- package/dist/types/config.types.d.ts +0 -1
- package/dist/types/drive.types.d.ts +2 -1
- package/dist/types/network.types.d.ts +5 -0
- package/dist/types/webdav.types.d.ts +1 -0
- package/dist/utils/cli.utils.d.ts +1 -1
- package/dist/utils/drive.utils.js +3 -1
- package/dist/utils/network.utils.d.ts +3 -9
- package/dist/utils/network.utils.js +21 -7
- package/dist/utils/webdav.utils.d.ts +16 -2
- package/dist/utils/webdav.utils.js +70 -19
- package/dist/utils/xml.utils.d.ts +1 -0
- package/dist/utils/xml.utils.js +3 -0
- package/dist/webdav/handlers/DELETE.handler.d.ts +5 -1
- package/dist/webdav/handlers/DELETE.handler.js +15 -12
- package/dist/webdav/handlers/GET.handler.d.ts +1 -2
- package/dist/webdav/handlers/GET.handler.js +10 -13
- package/dist/webdav/handlers/HEAD.handler.d.ts +1 -1
- package/dist/webdav/handlers/HEAD.handler.js +2 -2
- package/dist/webdav/handlers/MKCOL.handler.d.ts +1 -1
- package/dist/webdav/handlers/MKCOL.handler.js +15 -16
- package/dist/webdav/handlers/MOVE.handler.d.ts +11 -1
- package/dist/webdav/handlers/MOVE.handler.js +73 -2
- package/dist/webdav/handlers/OPTIONS.handler.d.ts +1 -1
- package/dist/webdav/handlers/OPTIONS.handler.js +2 -2
- package/dist/webdav/handlers/PROPFIND.handler.d.ts +11 -12
- package/dist/webdav/handlers/PROPFIND.handler.js +62 -76
- package/dist/webdav/handlers/PUT.handler.d.ts +5 -8
- package/dist/webdav/handlers/PUT.handler.js +34 -18
- package/dist/webdav/middewares/request-logger.middleware.js +1 -1
- package/dist/webdav/webdav-server.d.ts +14 -14
- package/dist/webdav/webdav-server.js +31 -14
- package/oclif.manifest.json +441 -8
- package/package.json +22 -26
- package/scripts/add-cert.sh +19 -5
|
@@ -9,53 +9,38 @@ const format_utils_1 = require("../../utils/format.utils");
|
|
|
9
9
|
const crypto_1 = require("crypto");
|
|
10
10
|
const mime_types_1 = __importDefault(require("mime-types"));
|
|
11
11
|
const webdav_utils_1 = require("../../utils/webdav.utils");
|
|
12
|
-
const
|
|
12
|
+
const logger_utils_1 = require("../../utils/logger.utils");
|
|
13
|
+
const usage_service_1 = require("../../services/usage.service");
|
|
13
14
|
class PROPFINDRequestHandler {
|
|
14
|
-
options;
|
|
15
15
|
dependencies;
|
|
16
|
-
constructor(
|
|
17
|
-
this.options = options;
|
|
16
|
+
constructor(dependencies) {
|
|
18
17
|
this.dependencies = dependencies;
|
|
19
18
|
}
|
|
20
19
|
handle = async (req, res) => {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
20
|
+
const { driveDatabaseManager, driveFolderService, driveFileService } = this.dependencies;
|
|
21
|
+
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
22
|
+
logger_utils_1.webdavLogger.info('[PROPFIND] Request received', { resource });
|
|
23
|
+
const driveItem = await webdav_utils_1.WebDavUtils.getAndSearchItemFromResource({
|
|
24
|
+
resource,
|
|
25
|
+
driveDatabaseManager,
|
|
26
|
+
driveFolderService,
|
|
27
|
+
driveFileService,
|
|
28
|
+
});
|
|
23
29
|
switch (resource.type) {
|
|
24
30
|
case 'file': {
|
|
25
|
-
|
|
31
|
+
const fileMetaXML = await this.getFileMetaXML(resource, driveItem);
|
|
32
|
+
res.status(207).send(fileMetaXML);
|
|
26
33
|
break;
|
|
27
34
|
}
|
|
28
35
|
case 'folder': {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
name: '',
|
|
33
|
-
status: 'EXISTS',
|
|
34
|
-
encryptedName: rootFolder.name,
|
|
35
|
-
bucket: rootFolder.bucket,
|
|
36
|
-
id: rootFolder.id,
|
|
37
|
-
parentId: rootFolder.parentId,
|
|
38
|
-
uuid: rootFolder.uuid,
|
|
39
|
-
createdAt: new Date(rootFolder.createdAt),
|
|
40
|
-
updatedAt: new Date(rootFolder.updatedAt),
|
|
41
|
-
});
|
|
42
|
-
res.status(207).send(await this.getFolderContentXML('/', rootFolder.uuid, depth, true));
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
const driveParentFolder = await this.dependencies.driveDatabaseManager.findByRelativePath(resource.url);
|
|
46
|
-
if (!driveParentFolder) {
|
|
47
|
-
res.status(404).send();
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
res.status(207).send(await this.getFolderContentXML(resource.url, driveParentFolder.uuid, depth));
|
|
36
|
+
const depth = req.header('depth') ?? '1';
|
|
37
|
+
const folderMetaXML = await this.getFolderContentXML(resource, driveItem, depth);
|
|
38
|
+
res.status(207).send(folderMetaXML);
|
|
51
39
|
break;
|
|
52
40
|
}
|
|
53
41
|
}
|
|
54
42
|
};
|
|
55
|
-
async
|
|
56
|
-
const driveFileItem = await this.dependencies.driveDatabaseManager.findByRelativePath(resource.url);
|
|
57
|
-
if (!driveFileItem || !('size' in driveFileItem))
|
|
58
|
-
throw new errors_utils_1.NotFoundError('File not found');
|
|
43
|
+
getFileMetaXML = async (resource, driveFileItem) => {
|
|
59
44
|
const driveFile = this.driveFileItemToXMLNode({
|
|
60
45
|
name: driveFileItem.name,
|
|
61
46
|
type: driveFileItem.type,
|
|
@@ -69,32 +54,35 @@ class PROPFINDRequestHandler {
|
|
|
69
54
|
updatedAt: driveFileItem.updatedAt,
|
|
70
55
|
status: driveFileItem.status,
|
|
71
56
|
folderId: driveFileItem.folderId,
|
|
72
|
-
|
|
57
|
+
folderUuid: driveFileItem.folderUuid,
|
|
58
|
+
}, resource.url);
|
|
73
59
|
const xml = xml_utils_1.XMLUtils.toWebDavXML([driveFile], {
|
|
74
60
|
arrayNodeName: xml_utils_1.XMLUtils.addDefaultNamespace('response'),
|
|
75
61
|
});
|
|
76
62
|
return xml;
|
|
77
|
-
}
|
|
78
|
-
async
|
|
63
|
+
};
|
|
64
|
+
getFolderContentXML = async (resource, folderItem, depth) => {
|
|
65
|
+
const relativePath = resource.url;
|
|
66
|
+
const isRootFolder = resource.url === '/';
|
|
79
67
|
let XMLNodes = [];
|
|
80
68
|
switch (depth) {
|
|
81
69
|
case '0':
|
|
82
70
|
if (isRootFolder) {
|
|
83
|
-
XMLNodes.push(await this.
|
|
71
|
+
XMLNodes.push(await this.driveFolderRootStatsToXMLNode(folderItem, relativePath));
|
|
84
72
|
}
|
|
85
73
|
else {
|
|
86
|
-
XMLNodes.push(
|
|
74
|
+
XMLNodes.push(this.driveFolderItemToXMLNode(folderItem, relativePath));
|
|
87
75
|
}
|
|
88
76
|
break;
|
|
89
77
|
case '1':
|
|
90
78
|
default:
|
|
91
79
|
if (isRootFolder) {
|
|
92
|
-
XMLNodes.push(await this.
|
|
93
|
-
XMLNodes = XMLNodes.concat(await this.getFolderChildsXMLNode(relativePath,
|
|
80
|
+
XMLNodes.push(await this.driveFolderRootStatsToXMLNode(folderItem, relativePath));
|
|
81
|
+
XMLNodes = XMLNodes.concat(await this.getFolderChildsXMLNode(relativePath, folderItem.uuid));
|
|
94
82
|
}
|
|
95
83
|
else {
|
|
96
|
-
XMLNodes.push(
|
|
97
|
-
XMLNodes = XMLNodes.concat(await this.getFolderChildsXMLNode(relativePath,
|
|
84
|
+
XMLNodes.push(this.driveFolderItemToXMLNode(folderItem, relativePath));
|
|
85
|
+
XMLNodes = XMLNodes.concat(await this.getFolderChildsXMLNode(relativePath, folderItem.uuid));
|
|
98
86
|
}
|
|
99
87
|
break;
|
|
100
88
|
}
|
|
@@ -104,8 +92,8 @@ class PROPFINDRequestHandler {
|
|
|
104
92
|
suppressEmptyNode: true,
|
|
105
93
|
});
|
|
106
94
|
return xml;
|
|
107
|
-
}
|
|
108
|
-
async
|
|
95
|
+
};
|
|
96
|
+
getFolderChildsXMLNode = async (relativePath, folderUuid) => {
|
|
109
97
|
const { driveFolderService, driveDatabaseManager } = this.dependencies;
|
|
110
98
|
const folderContent = await driveFolderService.getFolderContent(folderUuid);
|
|
111
99
|
const foldersXML = folderContent.folders.map((folder) => {
|
|
@@ -120,14 +108,18 @@ class PROPFINDRequestHandler {
|
|
|
120
108
|
encryptedName: folder.name,
|
|
121
109
|
uuid: folder.uuid,
|
|
122
110
|
parentId: null,
|
|
123
|
-
|
|
111
|
+
parentUuid: null,
|
|
112
|
+
}, folderRelativePath);
|
|
124
113
|
});
|
|
125
|
-
await Promise.all(folderContent.folders.map((folder) =>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
114
|
+
await Promise.all(folderContent.folders.map((folder) => {
|
|
115
|
+
const folderRelativePath = webdav_utils_1.WebDavUtils.joinURL(relativePath, folder.plainName, '/');
|
|
116
|
+
return driveDatabaseManager.createFolder({
|
|
117
|
+
...folder,
|
|
118
|
+
name: folder.plainName,
|
|
119
|
+
encryptedName: folder.name,
|
|
120
|
+
status: folder.deleted || folder.removed ? 'TRASHED' : 'EXISTS',
|
|
121
|
+
}, folderRelativePath);
|
|
122
|
+
}));
|
|
131
123
|
const filesXML = folderContent.files.map((file) => {
|
|
132
124
|
const fileRelativePath = webdav_utils_1.WebDavUtils.joinURL(relativePath, file.type ? `${file.plainName}.${file.type}` : file.plainName);
|
|
133
125
|
return this.driveFileItemToXMLNode({
|
|
@@ -142,35 +134,27 @@ class PROPFINDRequestHandler {
|
|
|
142
134
|
encryptedName: file.name,
|
|
143
135
|
status: file.status,
|
|
144
136
|
folderId: file.folderId,
|
|
137
|
+
folderUuid: file.folderUuid,
|
|
145
138
|
size: Number(file.size),
|
|
146
|
-
},
|
|
139
|
+
}, fileRelativePath);
|
|
147
140
|
});
|
|
148
141
|
await Promise.all(folderContent.files.map((file) => {
|
|
149
|
-
|
|
142
|
+
const fileRelativePath = webdav_utils_1.WebDavUtils.joinURL(relativePath, file.type ? `${file.plainName}.${file.type}` : file.plainName);
|
|
143
|
+
return driveDatabaseManager.createFile({
|
|
150
144
|
...file,
|
|
151
145
|
name: file.plainName,
|
|
152
146
|
fileId: file.fileId,
|
|
153
147
|
size: Number(file.size),
|
|
154
148
|
encryptedName: file.name,
|
|
155
|
-
});
|
|
149
|
+
}, fileRelativePath);
|
|
156
150
|
}));
|
|
157
151
|
return foldersXML.concat(filesXML);
|
|
158
|
-
}
|
|
159
|
-
async
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
const folderXML = this.driveFolderRootStatsToXMLNode(folderMeta, encodeURI(relativePath));
|
|
163
|
-
return folderXML;
|
|
164
|
-
}
|
|
165
|
-
async getFolderXMLNode(relativePath, folderUuid) {
|
|
166
|
-
const { driveFolderService } = this.dependencies;
|
|
167
|
-
const folderMeta = await driveFolderService.getFolderMetaByUuid(folderUuid);
|
|
168
|
-
const folderXML = this.driveFolderItemToXMLNode(folderMeta, encodeURI(relativePath));
|
|
169
|
-
return folderXML;
|
|
170
|
-
}
|
|
171
|
-
driveFolderRootStatsToXMLNode(driveFolderItem, relativePath) {
|
|
152
|
+
};
|
|
153
|
+
driveFolderRootStatsToXMLNode = async (driveFolderItem, relativePath) => {
|
|
154
|
+
const totalUsage = (await usage_service_1.UsageService.instance.fetchUsage()).total;
|
|
155
|
+
const spaceLimit = await usage_service_1.UsageService.instance.fetchSpaceLimit();
|
|
172
156
|
const driveFolderXML = {
|
|
173
|
-
[xml_utils_1.XMLUtils.addDefaultNamespace('href')]: relativePath,
|
|
157
|
+
[xml_utils_1.XMLUtils.addDefaultNamespace('href')]: xml_utils_1.XMLUtils.encodeWebDavUri(relativePath),
|
|
174
158
|
[xml_utils_1.XMLUtils.addDefaultNamespace('propstat')]: {
|
|
175
159
|
[xml_utils_1.XMLUtils.addDefaultNamespace('status')]: 'HTTP/1.1 200 OK',
|
|
176
160
|
[xml_utils_1.XMLUtils.addDefaultNamespace('prop')]: {
|
|
@@ -187,6 +171,8 @@ class PROPFINDRequestHandler {
|
|
|
187
171
|
'#text': '00000030',
|
|
188
172
|
'@_xmlns:x3': 'urn:schemas-microsoft-com:',
|
|
189
173
|
},
|
|
174
|
+
[xml_utils_1.XMLUtils.addDefaultNamespace('quota-available-bytes')]: spaceLimit - totalUsage,
|
|
175
|
+
[xml_utils_1.XMLUtils.addDefaultNamespace('quota-used-bytes')]: totalUsage,
|
|
190
176
|
[xml_utils_1.XMLUtils.addDefaultNamespace('resourcetype')]: {
|
|
191
177
|
[xml_utils_1.XMLUtils.addDefaultNamespace('collection')]: '',
|
|
192
178
|
},
|
|
@@ -194,11 +180,11 @@ class PROPFINDRequestHandler {
|
|
|
194
180
|
},
|
|
195
181
|
};
|
|
196
182
|
return driveFolderXML;
|
|
197
|
-
}
|
|
198
|
-
driveFolderItemToXMLNode(driveFolderItem, relativePath) {
|
|
183
|
+
};
|
|
184
|
+
driveFolderItemToXMLNode = (driveFolderItem, relativePath) => {
|
|
199
185
|
const displayName = `${driveFolderItem.name}`;
|
|
200
186
|
const driveFolderXML = {
|
|
201
|
-
[xml_utils_1.XMLUtils.addDefaultNamespace('href')]: relativePath,
|
|
187
|
+
[xml_utils_1.XMLUtils.addDefaultNamespace('href')]: xml_utils_1.XMLUtils.encodeWebDavUri(relativePath),
|
|
202
188
|
[xml_utils_1.XMLUtils.addDefaultNamespace('propstat')]: {
|
|
203
189
|
[xml_utils_1.XMLUtils.addDefaultNamespace('status')]: 'HTTP/1.1 200 OK',
|
|
204
190
|
[xml_utils_1.XMLUtils.addDefaultNamespace('prop')]: {
|
|
@@ -212,11 +198,11 @@ class PROPFINDRequestHandler {
|
|
|
212
198
|
},
|
|
213
199
|
};
|
|
214
200
|
return driveFolderXML;
|
|
215
|
-
}
|
|
216
|
-
driveFileItemToXMLNode(driveFileItem, relativePath) {
|
|
201
|
+
};
|
|
202
|
+
driveFileItemToXMLNode = (driveFileItem, relativePath) => {
|
|
217
203
|
const displayName = driveFileItem.type ? `${driveFileItem.name}.${driveFileItem.type}` : driveFileItem.name;
|
|
218
204
|
const driveFileXML = {
|
|
219
|
-
[xml_utils_1.XMLUtils.addDefaultNamespace('href')]: relativePath,
|
|
205
|
+
[xml_utils_1.XMLUtils.addDefaultNamespace('href')]: xml_utils_1.XMLUtils.encodeWebDavUri(relativePath),
|
|
220
206
|
[xml_utils_1.XMLUtils.addDefaultNamespace('propstat')]: {
|
|
221
207
|
[xml_utils_1.XMLUtils.addDefaultNamespace('status')]: 'HTTP/1.1 200 OK',
|
|
222
208
|
[xml_utils_1.XMLUtils.addDefaultNamespace('prop')]: {
|
|
@@ -230,6 +216,6 @@ class PROPFINDRequestHandler {
|
|
|
230
216
|
},
|
|
231
217
|
};
|
|
232
218
|
return driveFileXML;
|
|
233
|
-
}
|
|
219
|
+
};
|
|
234
220
|
}
|
|
235
221
|
exports.PROPFINDRequestHandler = PROPFINDRequestHandler;
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import { Request, Response } from 'express';
|
|
2
2
|
import { DriveFileService } from '../../services/drive/drive-file.service';
|
|
3
3
|
import { NetworkFacade } from '../../services/network/network-facade.service';
|
|
4
|
-
import { UploadService } from '../../services/network/upload.service';
|
|
5
|
-
import { DownloadService } from '../../services/network/download.service';
|
|
6
|
-
import { CryptoService } from '../../services/crypto.service';
|
|
7
4
|
import { AuthService } from '../../services/auth.service';
|
|
8
5
|
import { WebDavMethodHandler } from '../../types/webdav.types';
|
|
9
6
|
import { DriveDatabaseManager } from '../../services/database/drive-database-manager.service';
|
|
7
|
+
import { DriveFolderService } from '../../services/drive/drive-folder.service';
|
|
8
|
+
import { TrashService } from '../../services/drive/trash.service';
|
|
10
9
|
export declare class PUTRequestHandler implements WebDavMethodHandler {
|
|
11
|
-
private dependencies;
|
|
10
|
+
private readonly dependencies;
|
|
12
11
|
constructor(dependencies: {
|
|
13
12
|
driveFileService: DriveFileService;
|
|
13
|
+
driveFolderService: DriveFolderService;
|
|
14
14
|
driveDatabaseManager: DriveDatabaseManager;
|
|
15
|
-
|
|
16
|
-
downloadService: DownloadService;
|
|
17
|
-
cryptoService: CryptoService;
|
|
15
|
+
trashService: TrashService;
|
|
18
16
|
authService: AuthService;
|
|
19
17
|
networkFacade: NetworkFacade;
|
|
20
18
|
});
|
|
21
19
|
handle: (req: Request, res: Response) => Promise<void>;
|
|
22
|
-
private getDriveFolderRealmObject;
|
|
23
20
|
}
|
|
@@ -11,41 +11,57 @@ class PUTRequestHandler {
|
|
|
11
11
|
this.dependencies = dependencies;
|
|
12
12
|
}
|
|
13
13
|
handle = async (req, res) => {
|
|
14
|
+
const { driveDatabaseManager, authService, networkFacade, driveFileService, driveFolderService, trashService } = this.dependencies;
|
|
14
15
|
const contentLength = Number(req.headers['content-length']);
|
|
15
16
|
if (!contentLength || isNaN(contentLength) || contentLength <= 0) {
|
|
16
17
|
throw new errors_utils_1.UnsupportedMediaTypeError('Empty files are not supported');
|
|
17
18
|
}
|
|
18
|
-
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
20
|
+
logger_utils_1.webdavLogger.info(`PUT request received for uploading file '${resource.name}' to '${resource.parentPath}'`);
|
|
21
|
+
const parentResource = await webdav_utils_1.WebDavUtils.getRequestedResource(resource.parentPath);
|
|
22
|
+
const parentFolderItem = (await webdav_utils_1.WebDavUtils.getAndSearchItemFromResource({
|
|
23
|
+
resource: parentResource,
|
|
24
|
+
driveDatabaseManager,
|
|
25
|
+
driveFolderService,
|
|
26
|
+
}));
|
|
27
|
+
if (!parentFolderItem) {
|
|
28
|
+
throw new errors_utils_1.ConflictError(`Parent resource not found for parent path ${resource.parentPath}`);
|
|
23
29
|
}
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
try {
|
|
31
|
+
const driveFileItem = (await webdav_utils_1.WebDavUtils.getAndSearchItemFromResource({
|
|
32
|
+
resource: resource,
|
|
33
|
+
driveDatabaseManager,
|
|
34
|
+
driveFileService,
|
|
35
|
+
}));
|
|
36
|
+
if (driveFileItem && driveFileItem.status === 'EXISTS') {
|
|
37
|
+
logger_utils_1.webdavLogger.info(`File '${resource.name}' already exists in '${resource.path.dir}', trashing it before PUT`);
|
|
38
|
+
await driveDatabaseManager.deleteFileById(driveFileItem.id);
|
|
39
|
+
await trashService.trashItems({
|
|
40
|
+
items: [{ type: resource.type, uuid: driveFileItem.uuid }],
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
}
|
|
46
|
+
const { user, mnemonic } = await authService.getAuthDetails();
|
|
47
|
+
const [uploadPromise] = await networkFacade.uploadFromStream(user.bucket, mnemonic, contentLength, req, {
|
|
26
48
|
progressCallback: (progress) => {
|
|
27
|
-
logger_utils_1.webdavLogger.info(`Upload progress for file ${resource.name}: ${progress}%`);
|
|
49
|
+
logger_utils_1.webdavLogger.info(`Upload progress for file ${resource.name}: ${(100 * progress).toFixed(2)}%`);
|
|
28
50
|
},
|
|
29
51
|
});
|
|
30
52
|
const uploadResult = await uploadPromise;
|
|
31
53
|
logger_utils_1.webdavLogger.info('✅ File uploaded to network');
|
|
32
54
|
const file = await drive_file_service_1.DriveFileService.instance.createFile({
|
|
33
55
|
name: resource.path.name,
|
|
34
|
-
type: resource.path.ext.
|
|
56
|
+
type: resource.path.ext.replace('.', ''),
|
|
35
57
|
size: contentLength,
|
|
36
|
-
folderId:
|
|
58
|
+
folderId: parentFolderItem.id,
|
|
37
59
|
fileId: uploadResult.fileId,
|
|
38
60
|
bucket: user.bucket,
|
|
39
61
|
});
|
|
40
62
|
logger_utils_1.webdavLogger.info('✅ File uploaded to internxt drive');
|
|
41
|
-
await
|
|
42
|
-
res.status(200);
|
|
43
|
-
res.send();
|
|
63
|
+
await driveDatabaseManager.createFile(file, resource.path.dir + '/');
|
|
64
|
+
res.status(200).send();
|
|
44
65
|
};
|
|
45
|
-
async getDriveFolderRealmObject(resource) {
|
|
46
|
-
const { driveDatabaseManager } = this.dependencies;
|
|
47
|
-
const result = await driveDatabaseManager.findByRelativePath(resource.path.dir);
|
|
48
|
-
return result;
|
|
49
|
-
}
|
|
50
66
|
}
|
|
51
67
|
exports.PUTRequestHandler = PUTRequestHandler;
|
|
@@ -11,7 +11,7 @@ const RequestLoggerMiddleware = (config, analytics) => {
|
|
|
11
11
|
return next();
|
|
12
12
|
if (config.methods && !config.methods.includes(req.method))
|
|
13
13
|
return next();
|
|
14
|
-
logger_utils_1.webdavLogger.info(`WebDav request received\nMethod: ${req.method}\nURL: ${req.url}\nBody: ${req.body}\nHeaders: ${JSON.stringify(req.headers)}`);
|
|
14
|
+
logger_utils_1.webdavLogger.info(`WebDav request received\nMethod: ${req.method}\nURL: ${req.url}\nBody: ${JSON.stringify(req.body)}\nHeaders: ${JSON.stringify(req.headers)}`);
|
|
15
15
|
next();
|
|
16
16
|
};
|
|
17
17
|
};
|
|
@@ -9,19 +9,19 @@ import { AuthService } from '../services/auth.service';
|
|
|
9
9
|
import { CryptoService } from '../services/crypto.service';
|
|
10
10
|
import { TrashService } from '../services/drive/trash.service';
|
|
11
11
|
export declare class WebDavServer {
|
|
12
|
-
private app;
|
|
13
|
-
private configService;
|
|
14
|
-
private driveFileService;
|
|
15
|
-
private driveFolderService;
|
|
16
|
-
private driveDatabaseManager;
|
|
17
|
-
private uploadService;
|
|
18
|
-
private downloadService;
|
|
19
|
-
private authService;
|
|
20
|
-
private cryptoService;
|
|
21
|
-
private trashService;
|
|
12
|
+
private readonly app;
|
|
13
|
+
private readonly configService;
|
|
14
|
+
private readonly driveFileService;
|
|
15
|
+
private readonly driveFolderService;
|
|
16
|
+
private readonly driveDatabaseManager;
|
|
17
|
+
private readonly uploadService;
|
|
18
|
+
private readonly downloadService;
|
|
19
|
+
private readonly authService;
|
|
20
|
+
private readonly cryptoService;
|
|
21
|
+
private readonly trashService;
|
|
22
22
|
constructor(app: Express, configService: ConfigService, driveFileService: DriveFileService, driveFolderService: DriveFolderService, driveDatabaseManager: DriveDatabaseManager, uploadService: UploadService, downloadService: DownloadService, authService: AuthService, cryptoService: CryptoService, trashService: TrashService);
|
|
23
|
-
private getNetworkFacade;
|
|
24
|
-
private registerMiddlewares;
|
|
25
|
-
private registerHandlers;
|
|
26
|
-
start()
|
|
23
|
+
private readonly getNetworkFacade;
|
|
24
|
+
private readonly registerMiddlewares;
|
|
25
|
+
private readonly registerHandlers;
|
|
26
|
+
start: () => Promise<void>;
|
|
27
27
|
}
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.WebDavServer = void 0;
|
|
7
7
|
const https_1 = __importDefault(require("https"));
|
|
8
|
+
const http_1 = __importDefault(require("http"));
|
|
8
9
|
const config_service_1 = require("../services/config.service");
|
|
9
10
|
const OPTIONS_handler_1 = require("./handlers/OPTIONS.handler");
|
|
10
11
|
const PROPFIND_handler_1 = require("./handlers/PROPFIND.handler");
|
|
@@ -49,22 +50,22 @@ class WebDavServer {
|
|
|
49
50
|
this.cryptoService = cryptoService;
|
|
50
51
|
this.trashService = trashService;
|
|
51
52
|
}
|
|
52
|
-
async
|
|
53
|
+
getNetworkFacade = async () => {
|
|
53
54
|
const credentials = await this.configService.readUser();
|
|
54
55
|
if (!credentials)
|
|
55
|
-
throw new Error('Credentials not found in Config service,
|
|
56
|
+
throw new Error('Credentials not found in Config service, do login first');
|
|
56
57
|
const networkModule = sdk_manager_service_1.SdkManager.instance.getNetwork({
|
|
57
58
|
user: credentials.user.bridgeUser,
|
|
58
59
|
pass: credentials.user.userId,
|
|
59
60
|
});
|
|
60
61
|
return new network_facade_service_1.NetworkFacade(networkModule, this.uploadService, this.downloadService, this.cryptoService);
|
|
61
|
-
}
|
|
62
|
+
};
|
|
62
63
|
registerMiddlewares = async () => {
|
|
63
64
|
this.app.use(body_parser_1.default.text({ type: ['application/xml', 'text/xml'] }));
|
|
64
65
|
this.app.use(errors_middleware_1.ErrorHandlingMiddleware);
|
|
65
66
|
this.app.use((0, auth_middleware_1.AuthMiddleware)(config_service_1.ConfigService.instance));
|
|
66
67
|
this.app.use((0, request_logger_middleware_1.RequestLoggerMiddleware)({
|
|
67
|
-
enable:
|
|
68
|
+
enable: true,
|
|
68
69
|
}, analytics_service_1.AnalyticsService.instance));
|
|
69
70
|
};
|
|
70
71
|
registerHandlers = async () => {
|
|
@@ -80,17 +81,17 @@ class WebDavServer {
|
|
|
80
81
|
networkFacade: networkFacade,
|
|
81
82
|
}).handle));
|
|
82
83
|
this.app.options('*', (0, express_async_handler_1.default)(new OPTIONS_handler_1.OPTIONSRequestHandler().handle));
|
|
83
|
-
this.app.propfind('*', (0, express_async_handler_1.default)(new PROPFIND_handler_1.PROPFINDRequestHandler({
|
|
84
|
+
this.app.propfind('*', (0, express_async_handler_1.default)(new PROPFIND_handler_1.PROPFINDRequestHandler({
|
|
85
|
+
driveFileService: this.driveFileService,
|
|
84
86
|
driveFolderService: this.driveFolderService,
|
|
85
87
|
driveDatabaseManager: this.driveDatabaseManager,
|
|
86
88
|
}).handle));
|
|
87
89
|
this.app.put('*', (0, express_async_handler_1.default)(new PUT_handler_1.PUTRequestHandler({
|
|
88
90
|
driveFileService: this.driveFileService,
|
|
91
|
+
driveFolderService: this.driveFolderService,
|
|
89
92
|
driveDatabaseManager: this.driveDatabaseManager,
|
|
90
|
-
uploadService: this.uploadService,
|
|
91
|
-
downloadService: this.downloadService,
|
|
92
|
-
cryptoService: this.cryptoService,
|
|
93
93
|
authService: this.authService,
|
|
94
|
+
trashService: this.trashService,
|
|
94
95
|
networkFacade: networkFacade,
|
|
95
96
|
}).handle));
|
|
96
97
|
this.app.mkcol('*', (0, express_async_handler_1.default)(new MKCOL_handler_1.MKCOLRequestHandler({
|
|
@@ -100,19 +101,35 @@ class WebDavServer {
|
|
|
100
101
|
this.app.delete('*', (0, express_async_handler_1.default)(new DELETE_handler_1.DELETERequestHandler({
|
|
101
102
|
driveDatabaseManager: this.driveDatabaseManager,
|
|
102
103
|
trashService: this.trashService,
|
|
104
|
+
driveFileService: this.driveFileService,
|
|
105
|
+
driveFolderService: this.driveFolderService,
|
|
103
106
|
}).handle));
|
|
104
107
|
this.app.proppatch('*', (0, express_async_handler_1.default)(new PROPPATCH_handler_1.PROPPATCHRequestHandler().handle));
|
|
105
|
-
this.app.move('*', (0, express_async_handler_1.default)(new MOVE_handler_1.MOVERequestHandler(
|
|
108
|
+
this.app.move('*', (0, express_async_handler_1.default)(new MOVE_handler_1.MOVERequestHandler({
|
|
109
|
+
driveDatabaseManager: this.driveDatabaseManager,
|
|
110
|
+
driveFolderService: this.driveFolderService,
|
|
111
|
+
driveFileService: this.driveFileService,
|
|
112
|
+
}).handle));
|
|
106
113
|
this.app.copy('*', (0, express_async_handler_1.default)(new COPY_handler_1.COPYRequestHandler().handle));
|
|
107
114
|
};
|
|
108
|
-
async
|
|
109
|
-
const
|
|
115
|
+
start = async () => {
|
|
116
|
+
const configs = await this.configService.readWebdavConfig();
|
|
110
117
|
this.app.disable('x-powered-by');
|
|
111
118
|
await this.registerMiddlewares();
|
|
112
119
|
await this.registerHandlers();
|
|
113
|
-
|
|
114
|
-
|
|
120
|
+
const plainHttp = configs.protocol === 'http';
|
|
121
|
+
let server;
|
|
122
|
+
if (plainHttp) {
|
|
123
|
+
server = http_1.default.createServer(this.app);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const httpsCerts = network_utils_1.NetworkUtils.getWebdavSSLCerts();
|
|
127
|
+
server = https_1.default.createServer(httpsCerts, this.app);
|
|
128
|
+
}
|
|
129
|
+
server.requestTimeout = 15 * 60 * 1000;
|
|
130
|
+
server.listen(configs.port, () => {
|
|
131
|
+
logger_utils_1.webdavLogger.info(`Internxt WebDav server listening at ${configs.protocol}://${config_service_1.ConfigService.WEBDAV_LOCAL_URL}:${configs.port}`);
|
|
115
132
|
});
|
|
116
|
-
}
|
|
133
|
+
};
|
|
117
134
|
}
|
|
118
135
|
exports.WebDavServer = WebDavServer;
|