@internxt/cli 1.5.7 → 1.5.8
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/README.md +37 -31
- package/dist/commands/add-cert.js +0 -1
- package/dist/commands/config.js +0 -1
- package/dist/commands/create-folder.js +0 -1
- package/dist/commands/delete-permanently-file.js +0 -1
- package/dist/commands/delete-permanently-folder.js +0 -1
- package/dist/commands/download-file.js +0 -1
- package/dist/commands/list.js +0 -1
- package/dist/commands/login.js +0 -1
- package/dist/commands/logout.js +0 -1
- package/dist/commands/logs.js +0 -1
- package/dist/commands/move-file.js +0 -1
- package/dist/commands/move-folder.js +0 -1
- package/dist/commands/rename-file.js +0 -1
- package/dist/commands/rename-folder.js +0 -1
- package/dist/commands/trash-clear.js +0 -1
- package/dist/commands/trash-file.js +0 -1
- package/dist/commands/trash-folder.js +0 -1
- package/dist/commands/trash-list.js +0 -1
- package/dist/commands/trash-restore-file.js +0 -1
- package/dist/commands/trash-restore-folder.js +0 -1
- package/dist/commands/upload-file.js +1 -2
- package/dist/commands/webdav-config.d.ts +1 -0
- package/dist/commands/webdav-config.js +10 -7
- package/dist/commands/webdav.js +0 -1
- package/dist/commands/whoami.js +0 -1
- package/dist/hooks/prerun/auth_check.js +0 -1
- package/dist/services/config.service.d.ts +1 -0
- package/dist/services/config.service.js +3 -0
- package/dist/types/command.types.d.ts +1 -0
- package/dist/types/drive.types.d.ts +1 -0
- package/dist/utils/cli.utils.d.ts +1 -2
- package/dist/utils/cli.utils.js +2 -2
- package/dist/utils/drive.utils.d.ts +2 -1
- package/dist/utils/drive.utils.js +14 -0
- package/dist/utils/errors.utils.d.ts +2 -1
- package/dist/utils/errors.utils.js +10 -4
- package/dist/utils/logger.utils.js +0 -10
- package/dist/utils/webdav.utils.d.ts +17 -5
- package/dist/utils/webdav.utils.js +15 -6
- package/dist/webdav/handlers/MKCOL.handler.d.ts +2 -0
- package/dist/webdav/handlers/MKCOL.handler.js +6 -16
- package/dist/webdav/handlers/MOVE.handler.d.ts +2 -0
- package/dist/webdav/handlers/MOVE.handler.js +3 -10
- package/dist/webdav/handlers/PUT.handler.d.ts +2 -2
- package/dist/webdav/handlers/PUT.handler.js +13 -18
- package/dist/webdav/middewares/auth.middleware.js +8 -2
- package/dist/webdav/middewares/errors.middleware.js +9 -2
- package/dist/webdav/services/webdav-folder.service.d.ts +17 -0
- package/dist/webdav/services/webdav-folder.service.js +51 -0
- package/dist/webdav/webdav-server.js +8 -1
- package/oclif.manifest.json +9 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ A CLI tool to interact with your Internxt encrypted files
|
|
|
10
10
|
* [Project Maintenance](#project-maintenance)
|
|
11
11
|
* [Installation](#installation)
|
|
12
12
|
* [Usage](#usage)
|
|
13
|
+
* [Docker](#docker)
|
|
13
14
|
* [Commands](#commands)
|
|
14
15
|
* [Current Limitations](#current-limitations)
|
|
15
16
|
<!-- tocstop -->
|
|
@@ -51,7 +52,7 @@ $ npm install -g @internxt/cli
|
|
|
51
52
|
$ internxt COMMAND
|
|
52
53
|
running command...
|
|
53
54
|
$ internxt (--version)
|
|
54
|
-
@internxt/cli/1.5.
|
|
55
|
+
@internxt/cli/1.5.8 linux-x64 node-v22.21.1
|
|
55
56
|
$ internxt --help [COMMAND]
|
|
56
57
|
USAGE
|
|
57
58
|
$ internxt COMMAND
|
|
@@ -59,6 +60,10 @@ USAGE
|
|
|
59
60
|
```
|
|
60
61
|
<!-- usagestop -->
|
|
61
62
|
|
|
63
|
+
# Docker
|
|
64
|
+
|
|
65
|
+
[`Internxt WebDAV (Docker Integration)`](docker/README.md)
|
|
66
|
+
|
|
62
67
|
# Commands
|
|
63
68
|
|
|
64
69
|
<!-- commands -->
|
|
@@ -120,7 +125,7 @@ EXAMPLES
|
|
|
120
125
|
$ internxt add-cert
|
|
121
126
|
```
|
|
122
127
|
|
|
123
|
-
_See code: [src/commands/add-cert.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
128
|
+
_See code: [src/commands/add-cert.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/add-cert.ts)_
|
|
124
129
|
|
|
125
130
|
## `internxt autocomplete [SHELL]`
|
|
126
131
|
|
|
@@ -171,7 +176,7 @@ EXAMPLES
|
|
|
171
176
|
$ internxt config
|
|
172
177
|
```
|
|
173
178
|
|
|
174
|
-
_See code: [src/commands/config.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
179
|
+
_See code: [src/commands/config.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/config.ts)_
|
|
175
180
|
|
|
176
181
|
## `internxt create-folder`
|
|
177
182
|
|
|
@@ -200,7 +205,7 @@ EXAMPLES
|
|
|
200
205
|
$ internxt create-folder
|
|
201
206
|
```
|
|
202
207
|
|
|
203
|
-
_See code: [src/commands/create-folder.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
208
|
+
_See code: [src/commands/create-folder.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/create-folder.ts)_
|
|
204
209
|
|
|
205
210
|
## `internxt delete-permanently-file`
|
|
206
211
|
|
|
@@ -230,7 +235,7 @@ EXAMPLES
|
|
|
230
235
|
$ internxt delete-permanently-file
|
|
231
236
|
```
|
|
232
237
|
|
|
233
|
-
_See code: [src/commands/delete-permanently-file.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
238
|
+
_See code: [src/commands/delete-permanently-file.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/delete-permanently-file.ts)_
|
|
234
239
|
|
|
235
240
|
## `internxt delete-permanently-folder`
|
|
236
241
|
|
|
@@ -260,7 +265,7 @@ EXAMPLES
|
|
|
260
265
|
$ internxt delete-permanently-folder
|
|
261
266
|
```
|
|
262
267
|
|
|
263
|
-
_See code: [src/commands/delete-permanently-folder.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
268
|
+
_See code: [src/commands/delete-permanently-folder.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/delete-permanently-folder.ts)_
|
|
264
269
|
|
|
265
270
|
## `internxt delete permanently file`
|
|
266
271
|
|
|
@@ -349,7 +354,7 @@ EXAMPLES
|
|
|
349
354
|
$ internxt download-file
|
|
350
355
|
```
|
|
351
356
|
|
|
352
|
-
_See code: [src/commands/download-file.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
357
|
+
_See code: [src/commands/download-file.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/download-file.ts)_
|
|
353
358
|
|
|
354
359
|
## `internxt download file`
|
|
355
360
|
|
|
@@ -408,7 +413,7 @@ EXAMPLES
|
|
|
408
413
|
$ internxt list
|
|
409
414
|
```
|
|
410
415
|
|
|
411
|
-
_See code: [src/commands/list.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
416
|
+
_See code: [src/commands/list.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/list.ts)_
|
|
412
417
|
|
|
413
418
|
## `internxt login`
|
|
414
419
|
|
|
@@ -439,7 +444,7 @@ EXAMPLES
|
|
|
439
444
|
$ internxt login
|
|
440
445
|
```
|
|
441
446
|
|
|
442
|
-
_See code: [src/commands/login.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
447
|
+
_See code: [src/commands/login.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/login.ts)_
|
|
443
448
|
|
|
444
449
|
## `internxt logout`
|
|
445
450
|
|
|
@@ -459,7 +464,7 @@ EXAMPLES
|
|
|
459
464
|
$ internxt logout
|
|
460
465
|
```
|
|
461
466
|
|
|
462
|
-
_See code: [src/commands/logout.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
467
|
+
_See code: [src/commands/logout.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/logout.ts)_
|
|
463
468
|
|
|
464
469
|
## `internxt logs`
|
|
465
470
|
|
|
@@ -479,7 +484,7 @@ EXAMPLES
|
|
|
479
484
|
$ internxt logs
|
|
480
485
|
```
|
|
481
486
|
|
|
482
|
-
_See code: [src/commands/logs.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
487
|
+
_See code: [src/commands/logs.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/logs.ts)_
|
|
483
488
|
|
|
484
489
|
## `internxt move-file`
|
|
485
490
|
|
|
@@ -511,7 +516,7 @@ EXAMPLES
|
|
|
511
516
|
$ internxt move-file
|
|
512
517
|
```
|
|
513
518
|
|
|
514
|
-
_See code: [src/commands/move-file.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
519
|
+
_See code: [src/commands/move-file.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/move-file.ts)_
|
|
515
520
|
|
|
516
521
|
## `internxt move-folder`
|
|
517
522
|
|
|
@@ -543,7 +548,7 @@ EXAMPLES
|
|
|
543
548
|
$ internxt move-folder
|
|
544
549
|
```
|
|
545
550
|
|
|
546
|
-
_See code: [src/commands/move-folder.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
551
|
+
_See code: [src/commands/move-folder.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/move-folder.ts)_
|
|
547
552
|
|
|
548
553
|
## `internxt move file`
|
|
549
554
|
|
|
@@ -634,7 +639,7 @@ EXAMPLES
|
|
|
634
639
|
$ internxt rename-file
|
|
635
640
|
```
|
|
636
641
|
|
|
637
|
-
_See code: [src/commands/rename-file.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
642
|
+
_See code: [src/commands/rename-file.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/rename-file.ts)_
|
|
638
643
|
|
|
639
644
|
## `internxt rename-folder`
|
|
640
645
|
|
|
@@ -665,7 +670,7 @@ EXAMPLES
|
|
|
665
670
|
$ internxt rename-folder
|
|
666
671
|
```
|
|
667
672
|
|
|
668
|
-
_See code: [src/commands/rename-folder.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
673
|
+
_See code: [src/commands/rename-folder.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/rename-folder.ts)_
|
|
669
674
|
|
|
670
675
|
## `internxt rename file`
|
|
671
676
|
|
|
@@ -753,7 +758,7 @@ EXAMPLES
|
|
|
753
758
|
$ internxt trash-clear
|
|
754
759
|
```
|
|
755
760
|
|
|
756
|
-
_See code: [src/commands/trash-clear.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
761
|
+
_See code: [src/commands/trash-clear.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/trash-clear.ts)_
|
|
757
762
|
|
|
758
763
|
## `internxt trash-file`
|
|
759
764
|
|
|
@@ -783,7 +788,7 @@ EXAMPLES
|
|
|
783
788
|
$ internxt trash-file
|
|
784
789
|
```
|
|
785
790
|
|
|
786
|
-
_See code: [src/commands/trash-file.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
791
|
+
_See code: [src/commands/trash-file.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/trash-file.ts)_
|
|
787
792
|
|
|
788
793
|
## `internxt trash-folder`
|
|
789
794
|
|
|
@@ -813,7 +818,7 @@ EXAMPLES
|
|
|
813
818
|
$ internxt trash-folder
|
|
814
819
|
```
|
|
815
820
|
|
|
816
|
-
_See code: [src/commands/trash-folder.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
821
|
+
_See code: [src/commands/trash-folder.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/trash-folder.ts)_
|
|
817
822
|
|
|
818
823
|
## `internxt trash-list`
|
|
819
824
|
|
|
@@ -839,7 +844,7 @@ EXAMPLES
|
|
|
839
844
|
$ internxt trash-list
|
|
840
845
|
```
|
|
841
846
|
|
|
842
|
-
_See code: [src/commands/trash-list.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
847
|
+
_See code: [src/commands/trash-list.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/trash-list.ts)_
|
|
843
848
|
|
|
844
849
|
## `internxt trash-restore-file`
|
|
845
850
|
|
|
@@ -870,7 +875,7 @@ EXAMPLES
|
|
|
870
875
|
$ internxt trash-restore-file
|
|
871
876
|
```
|
|
872
877
|
|
|
873
|
-
_See code: [src/commands/trash-restore-file.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
878
|
+
_See code: [src/commands/trash-restore-file.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/trash-restore-file.ts)_
|
|
874
879
|
|
|
875
880
|
## `internxt trash-restore-folder`
|
|
876
881
|
|
|
@@ -901,7 +906,7 @@ EXAMPLES
|
|
|
901
906
|
$ internxt trash-restore-folder
|
|
902
907
|
```
|
|
903
908
|
|
|
904
|
-
_See code: [src/commands/trash-restore-folder.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
909
|
+
_See code: [src/commands/trash-restore-folder.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/trash-restore-folder.ts)_
|
|
905
910
|
|
|
906
911
|
## `internxt trash clear`
|
|
907
912
|
|
|
@@ -1098,7 +1103,7 @@ EXAMPLES
|
|
|
1098
1103
|
$ internxt upload-file
|
|
1099
1104
|
```
|
|
1100
1105
|
|
|
1101
|
-
_See code: [src/commands/upload-file.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
1106
|
+
_See code: [src/commands/upload-file.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/upload-file.ts)_
|
|
1102
1107
|
|
|
1103
1108
|
## `internxt upload file`
|
|
1104
1109
|
|
|
@@ -1153,7 +1158,7 @@ EXAMPLES
|
|
|
1153
1158
|
$ internxt webdav status
|
|
1154
1159
|
```
|
|
1155
1160
|
|
|
1156
|
-
_See code: [src/commands/webdav.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
1161
|
+
_See code: [src/commands/webdav.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/webdav.ts)_
|
|
1157
1162
|
|
|
1158
1163
|
## `internxt webdav-config`
|
|
1159
1164
|
|
|
@@ -1161,14 +1166,15 @@ Edit the configuration of the Internxt CLI WebDav server as the port or the prot
|
|
|
1161
1166
|
|
|
1162
1167
|
```
|
|
1163
1168
|
USAGE
|
|
1164
|
-
$ internxt webdav-config [--json] [-l <value>] [-p <value>] [-s | -h] [-t <value>]
|
|
1169
|
+
$ internxt webdav-config [--json] [-l <value>] [-p <value>] [-s | -h] [-t <value>] [-c]
|
|
1165
1170
|
|
|
1166
1171
|
FLAGS
|
|
1167
|
-
-
|
|
1168
|
-
-
|
|
1169
|
-
-
|
|
1170
|
-
-
|
|
1171
|
-
-
|
|
1172
|
+
-c, --[no-]createFullPath Auto-create missing parent directories during file uploads.
|
|
1173
|
+
-h, --http Configures the WebDAV server to use insecure plain HTTP.
|
|
1174
|
+
-l, --host=<value> The listening host for the WebDAV server.
|
|
1175
|
+
-p, --port=<value> The new port for the WebDAV server.
|
|
1176
|
+
-s, --https Configures the WebDAV server to use HTTPS with self-signed certificates.
|
|
1177
|
+
-t, --timeout=<value> Configures the WebDAV server to use this timeout in minutes.
|
|
1172
1178
|
|
|
1173
1179
|
GLOBAL FLAGS
|
|
1174
1180
|
--json Format output as json.
|
|
@@ -1180,7 +1186,7 @@ EXAMPLES
|
|
|
1180
1186
|
$ internxt webdav-config
|
|
1181
1187
|
```
|
|
1182
1188
|
|
|
1183
|
-
_See code: [src/commands/webdav-config.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
1189
|
+
_See code: [src/commands/webdav-config.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/webdav-config.ts)_
|
|
1184
1190
|
|
|
1185
1191
|
## `internxt whoami`
|
|
1186
1192
|
|
|
@@ -1200,7 +1206,7 @@ EXAMPLES
|
|
|
1200
1206
|
$ internxt whoami
|
|
1201
1207
|
```
|
|
1202
1208
|
|
|
1203
|
-
_See code: [src/commands/whoami.ts](https://github.com/internxt/cli/blob/v1.5.
|
|
1209
|
+
_See code: [src/commands/whoami.ts](https://github.com/internxt/cli/blob/v1.5.8/src/commands/whoami.ts)_
|
|
1204
1210
|
<!-- commandsstop -->
|
|
1205
1211
|
|
|
1206
1212
|
# Current Limitations
|
package/dist/commands/config.js
CHANGED
package/dist/commands/list.js
CHANGED
package/dist/commands/login.js
CHANGED
package/dist/commands/logout.js
CHANGED
package/dist/commands/logs.js
CHANGED
|
@@ -121,7 +121,7 @@ class UploadFile extends core_1.Command {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
catch (error) {
|
|
124
|
-
errors_utils_1.ErrorUtils.report(
|
|
124
|
+
errors_utils_1.ErrorUtils.report(error, { command: this.id });
|
|
125
125
|
}
|
|
126
126
|
progressBar?.update(100);
|
|
127
127
|
progressBar?.stop();
|
|
@@ -144,7 +144,6 @@ class UploadFile extends core_1.Command {
|
|
|
144
144
|
error,
|
|
145
145
|
command: this.id,
|
|
146
146
|
logReporter: this.log.bind(this),
|
|
147
|
-
errorReporter: this.error.bind(this),
|
|
148
147
|
jsonFlag: flags['json'],
|
|
149
148
|
});
|
|
150
149
|
this.exit(1);
|
|
@@ -10,6 +10,7 @@ export default class WebDAVConfig extends Command {
|
|
|
10
10
|
https: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
http: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
12
|
timeout: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
createFullPath: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
14
|
};
|
|
14
15
|
static readonly enableJsonFlag = true;
|
|
15
16
|
run: () => Promise<{
|
|
@@ -39,16 +39,20 @@ class WebDAVConfig extends core_1.Command {
|
|
|
39
39
|
required: false,
|
|
40
40
|
min: 0,
|
|
41
41
|
}),
|
|
42
|
+
createFullPath: core_1.Flags.boolean({
|
|
43
|
+
char: 'c',
|
|
44
|
+
description: 'Auto-create missing parent directories during file uploads.',
|
|
45
|
+
required: false,
|
|
46
|
+
allowNo: true,
|
|
47
|
+
}),
|
|
42
48
|
};
|
|
43
49
|
static enableJsonFlag = true;
|
|
44
50
|
run = async () => {
|
|
45
|
-
const { flags } = await this.parse(WebDAVConfig);
|
|
51
|
+
const { flags: { host, port, http, https, timeout, createFullPath }, } = await this.parse(WebDAVConfig);
|
|
46
52
|
const webdavConfig = await config_service_1.ConfigService.instance.readWebdavConfig();
|
|
47
|
-
const host = flags['host'];
|
|
48
53
|
if (host) {
|
|
49
54
|
webdavConfig['host'] = host;
|
|
50
55
|
}
|
|
51
|
-
const port = flags['port'];
|
|
52
56
|
if (port) {
|
|
53
57
|
if (validation_service_1.ValidationService.instance.validateTCPIntegerPort(port)) {
|
|
54
58
|
webdavConfig['port'] = port;
|
|
@@ -57,18 +61,18 @@ class WebDAVConfig extends core_1.Command {
|
|
|
57
61
|
throw new command_types_1.NotValidPortError();
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
|
-
const http = flags['http'];
|
|
61
64
|
if (http) {
|
|
62
65
|
webdavConfig['protocol'] = 'http';
|
|
63
66
|
}
|
|
64
|
-
const https = flags['https'];
|
|
65
67
|
if (https) {
|
|
66
68
|
webdavConfig['protocol'] = 'https';
|
|
67
69
|
}
|
|
68
|
-
const timeout = flags['timeout'];
|
|
69
70
|
if (timeout !== undefined) {
|
|
70
71
|
webdavConfig['timeoutMinutes'] = timeout;
|
|
71
72
|
}
|
|
73
|
+
if (createFullPath !== undefined) {
|
|
74
|
+
webdavConfig['createFullPath'] = createFullPath;
|
|
75
|
+
}
|
|
72
76
|
await config_service_1.ConfigService.instance.saveWebdavConfig(webdavConfig);
|
|
73
77
|
const message = `On the next start, the WebDAV server will use the next config: ${JSON.stringify(webdavConfig)}`;
|
|
74
78
|
cli_utils_1.CLIUtils.success(this.log.bind(this), message);
|
|
@@ -80,7 +84,6 @@ class WebDAVConfig extends core_1.Command {
|
|
|
80
84
|
error,
|
|
81
85
|
command: this.id,
|
|
82
86
|
logReporter: this.log.bind(this),
|
|
83
|
-
errorReporter: this.error.bind(this),
|
|
84
87
|
jsonFlag: flags['json'],
|
|
85
88
|
});
|
|
86
89
|
this.exit(1);
|
package/dist/commands/webdav.js
CHANGED
package/dist/commands/whoami.js
CHANGED
|
@@ -12,6 +12,7 @@ export declare class ConfigService {
|
|
|
12
12
|
static readonly WEBDAV_DEFAULT_PORT = "3005";
|
|
13
13
|
static readonly WEBDAV_DEFAULT_PROTOCOL = "https";
|
|
14
14
|
static readonly WEBDAV_DEFAULT_TIMEOUT = 0;
|
|
15
|
+
static readonly WEBDAV_DEFAULT_CREATE_FULL_PATH = true;
|
|
15
16
|
static readonly instance: ConfigService;
|
|
16
17
|
get: (key: keyof ConfigKeys) => string;
|
|
17
18
|
saveUser: (loginCredentials: LoginCredentials) => Promise<void>;
|
|
@@ -20,6 +20,7 @@ class ConfigService {
|
|
|
20
20
|
static WEBDAV_DEFAULT_PORT = '3005';
|
|
21
21
|
static WEBDAV_DEFAULT_PROTOCOL = 'https';
|
|
22
22
|
static WEBDAV_DEFAULT_TIMEOUT = 0;
|
|
23
|
+
static WEBDAV_DEFAULT_CREATE_FULL_PATH = true;
|
|
23
24
|
static instance = new ConfigService();
|
|
24
25
|
get = (key) => {
|
|
25
26
|
const value = process.env[key];
|
|
@@ -64,6 +65,7 @@ class ConfigService {
|
|
|
64
65
|
port: configs?.port ?? ConfigService.WEBDAV_DEFAULT_PORT,
|
|
65
66
|
protocol: configs?.protocol ?? ConfigService.WEBDAV_DEFAULT_PROTOCOL,
|
|
66
67
|
timeoutMinutes: configs?.timeoutMinutes ?? ConfigService.WEBDAV_DEFAULT_TIMEOUT,
|
|
68
|
+
createFullPath: configs?.createFullPath ?? ConfigService.WEBDAV_DEFAULT_CREATE_FULL_PATH,
|
|
67
69
|
};
|
|
68
70
|
}
|
|
69
71
|
catch {
|
|
@@ -72,6 +74,7 @@ class ConfigService {
|
|
|
72
74
|
port: ConfigService.WEBDAV_DEFAULT_PORT,
|
|
73
75
|
protocol: ConfigService.WEBDAV_DEFAULT_PROTOCOL,
|
|
74
76
|
timeoutMinutes: ConfigService.WEBDAV_DEFAULT_TIMEOUT,
|
|
77
|
+
createFullPath: ConfigService.WEBDAV_DEFAULT_CREATE_FULL_PATH,
|
|
75
78
|
};
|
|
76
79
|
}
|
|
77
80
|
};
|
|
@@ -36,11 +36,10 @@ export declare class CLIUtils {
|
|
|
36
36
|
static readonly timer: () => {
|
|
37
37
|
stop: () => number;
|
|
38
38
|
};
|
|
39
|
-
static readonly catchError: ({ error, logReporter,
|
|
39
|
+
static readonly catchError: ({ error, logReporter, command, jsonFlag, }: {
|
|
40
40
|
error: Error;
|
|
41
41
|
command?: string;
|
|
42
42
|
logReporter: (message: string) => void;
|
|
43
|
-
errorReporter: (message: string) => void;
|
|
44
43
|
jsonFlag?: boolean;
|
|
45
44
|
}) => void;
|
|
46
45
|
static readonly parseEmpty: (input: string) => Promise<string>;
|
package/dist/utils/cli.utils.js
CHANGED
|
@@ -130,7 +130,7 @@ class CLIUtils {
|
|
|
130
130
|
},
|
|
131
131
|
};
|
|
132
132
|
};
|
|
133
|
-
static catchError = ({ error, logReporter,
|
|
133
|
+
static catchError = ({ error, logReporter, command, jsonFlag, }) => {
|
|
134
134
|
let message;
|
|
135
135
|
if ('message' in error && error.message.trim().length > 0) {
|
|
136
136
|
message = error.message;
|
|
@@ -143,7 +143,7 @@ class CLIUtils {
|
|
|
143
143
|
CLIUtils.consoleLog(JSON.stringify({ success: false, message }));
|
|
144
144
|
}
|
|
145
145
|
else {
|
|
146
|
-
errors_utils_1.ErrorUtils.report(
|
|
146
|
+
errors_utils_1.ErrorUtils.report(error, { command });
|
|
147
147
|
CLIUtils.error(logReporter, message);
|
|
148
148
|
}
|
|
149
149
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { FileMeta, FolderMeta } from '@internxt/sdk/dist/drive/storage/types';
|
|
1
|
+
import { FileMeta, FolderMeta, CreateFolderResponse } from '@internxt/sdk/dist/drive/storage/types';
|
|
2
2
|
import { DriveFileItem, DriveFolderItem } from '../types/drive.types';
|
|
3
3
|
export declare class DriveUtils {
|
|
4
4
|
static driveFileMetaToItem(fileMeta: FileMeta): DriveFileItem;
|
|
5
5
|
static driveFolderMetaToItem(folderMeta: FolderMeta): DriveFolderItem;
|
|
6
|
+
static createFolderResponseToItem(folderResponse: CreateFolderResponse): DriveFolderItem;
|
|
6
7
|
}
|
|
@@ -34,5 +34,19 @@ class DriveUtils {
|
|
|
34
34
|
updatedAt: new Date(folderMeta.updatedAt),
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
+
static createFolderResponseToItem(folderResponse) {
|
|
38
|
+
return {
|
|
39
|
+
uuid: folderResponse.uuid,
|
|
40
|
+
id: folderResponse.id,
|
|
41
|
+
bucket: folderResponse.bucket,
|
|
42
|
+
status: folderResponse.deleted || folderResponse.removed ? 'TRASHED' : 'EXISTS',
|
|
43
|
+
name: folderResponse.plainName ?? folderResponse.name,
|
|
44
|
+
encryptedName: folderResponse.name,
|
|
45
|
+
parentId: folderResponse.parentId,
|
|
46
|
+
parentUuid: folderResponse.parentUuid,
|
|
47
|
+
createdAt: new Date(folderResponse.createdAt),
|
|
48
|
+
updatedAt: new Date(folderResponse.updatedAt),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
37
51
|
}
|
|
38
52
|
exports.DriveUtils = DriveUtils;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export declare function isError(error: unknown): error is Error;
|
|
1
2
|
export declare class ErrorUtils {
|
|
2
|
-
static report(
|
|
3
|
+
static report(error: unknown, props?: Record<string, unknown>): void;
|
|
3
4
|
}
|
|
4
5
|
export declare class ConflictError extends Error {
|
|
5
6
|
statusCode: number;
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NotImplementedError = exports.MethodNotAllowed = exports.UnsupportedMediaTypeError = exports.BadRequestError = exports.NotFoundError = exports.ConflictError = exports.ErrorUtils = void 0;
|
|
4
|
+
exports.isError = isError;
|
|
5
|
+
const logger_utils_1 = require("./logger.utils");
|
|
6
|
+
const node_util_1 = require("node:util");
|
|
7
|
+
function isError(error) {
|
|
8
|
+
return node_util_1.types.isNativeError(error);
|
|
9
|
+
}
|
|
4
10
|
class ErrorUtils {
|
|
5
|
-
static report(
|
|
6
|
-
if (error
|
|
7
|
-
|
|
11
|
+
static report(error, props = {}) {
|
|
12
|
+
if (isError(error)) {
|
|
13
|
+
logger_utils_1.logger.error(`[REPORTED_ERROR]: ${error.message}\nProperties => ${JSON.stringify(props, null, 2)}\nStack => ${error.stack}`);
|
|
8
14
|
}
|
|
9
15
|
else {
|
|
10
|
-
|
|
16
|
+
logger_utils_1.logger.error(`[REPORTED_ERROR]: ${JSON.stringify(error)}\nProperties => ${JSON.stringify(props, null, 2)}\n`);
|
|
11
17
|
}
|
|
12
18
|
}
|
|
13
19
|
}
|
|
@@ -52,13 +52,3 @@ exports.webdavLogger = winston_1.default.createLogger({
|
|
|
52
52
|
}),
|
|
53
53
|
],
|
|
54
54
|
});
|
|
55
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
56
|
-
exports.webdavLogger.add(new winston_1.default.transports.Console({
|
|
57
|
-
format: winston_1.default.format.simple(),
|
|
58
|
-
}));
|
|
59
|
-
}
|
|
60
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
61
|
-
exports.logger.add(new winston_1.default.transports.Console({
|
|
62
|
-
format: winston_1.default.format.simple(),
|
|
63
|
-
}));
|
|
64
|
-
}
|
|
@@ -2,14 +2,26 @@ import { Request } from 'express';
|
|
|
2
2
|
import { WebDavRequestedResource } from '../types/webdav.types';
|
|
3
3
|
import { DriveFolderService } from '../services/drive/drive-folder.service';
|
|
4
4
|
import { DriveFileService } from '../services/drive/drive-file.service';
|
|
5
|
-
import { DriveFileItem, DriveFolderItem } from '../types/drive.types';
|
|
5
|
+
import { DriveFileItem, DriveFolderItem, DriveItem } from '../types/drive.types';
|
|
6
6
|
export declare class WebDavUtils {
|
|
7
7
|
static joinURL(...pathComponents: string[]): string;
|
|
8
8
|
static removeHostFromURL(completeURL: string): string;
|
|
9
|
+
static decodeUrl(requestUrl: string, decodeUri?: boolean): string;
|
|
10
|
+
static normalizeFolderPath(path: string): string;
|
|
9
11
|
static getRequestedResource(urlObject: string | Request, decodeUri?: boolean): Promise<WebDavRequestedResource>;
|
|
10
|
-
static getDriveItemFromResource(
|
|
12
|
+
static getDriveItemFromResource(params: {
|
|
11
13
|
resource: WebDavRequestedResource;
|
|
12
|
-
driveFolderService
|
|
13
|
-
driveFileService?:
|
|
14
|
-
}): Promise<
|
|
14
|
+
driveFolderService: DriveFolderService;
|
|
15
|
+
driveFileService?: never;
|
|
16
|
+
}): Promise<DriveFolderItem | undefined>;
|
|
17
|
+
static getDriveItemFromResource(params: {
|
|
18
|
+
resource: WebDavRequestedResource;
|
|
19
|
+
driveFolderService?: never;
|
|
20
|
+
driveFileService: DriveFileService;
|
|
21
|
+
}): Promise<DriveFileItem | undefined>;
|
|
22
|
+
static getDriveItemFromResource(params: {
|
|
23
|
+
resource: WebDavRequestedResource;
|
|
24
|
+
driveFolderService: DriveFolderService;
|
|
25
|
+
driveFileService: DriveFileService;
|
|
26
|
+
}): Promise<DriveItem | undefined>;
|
|
15
27
|
}
|
|
@@ -19,6 +19,19 @@ class WebDavUtils {
|
|
|
19
19
|
url = '/'.concat(url);
|
|
20
20
|
return url;
|
|
21
21
|
}
|
|
22
|
+
static decodeUrl(requestUrl, decodeUri = true) {
|
|
23
|
+
return (decodeUri ? decodeURIComponent(requestUrl) : requestUrl).replaceAll('/./', '/');
|
|
24
|
+
}
|
|
25
|
+
static normalizeFolderPath(path) {
|
|
26
|
+
let normalizedPath = path;
|
|
27
|
+
if (!normalizedPath.startsWith('/')) {
|
|
28
|
+
normalizedPath = `/${normalizedPath}`;
|
|
29
|
+
}
|
|
30
|
+
if (!normalizedPath.endsWith('/')) {
|
|
31
|
+
normalizedPath = `${normalizedPath}/`;
|
|
32
|
+
}
|
|
33
|
+
return normalizedPath;
|
|
34
|
+
}
|
|
22
35
|
static async getRequestedResource(urlObject, decodeUri = true) {
|
|
23
36
|
let requestUrl;
|
|
24
37
|
if (typeof urlObject === 'string') {
|
|
@@ -27,13 +40,9 @@ class WebDavUtils {
|
|
|
27
40
|
else {
|
|
28
41
|
requestUrl = urlObject.url;
|
|
29
42
|
}
|
|
30
|
-
const decodedUrl = (
|
|
43
|
+
const decodedUrl = this.decodeUrl(requestUrl, decodeUri);
|
|
31
44
|
const parsedPath = node_path_1.default.parse(decodedUrl);
|
|
32
|
-
|
|
33
|
-
if (!parentPath.startsWith('/'))
|
|
34
|
-
parentPath = '/'.concat(parentPath);
|
|
35
|
-
if (!parentPath.endsWith('/'))
|
|
36
|
-
parentPath = parentPath.concat('/');
|
|
45
|
+
const parentPath = this.normalizeFolderPath(node_path_1.default.dirname(decodedUrl));
|
|
37
46
|
const isFolder = requestUrl.endsWith('/');
|
|
38
47
|
if (isFolder) {
|
|
39
48
|
return {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { WebDavMethodHandler } from '../../types/webdav.types';
|
|
2
2
|
import { Request, Response } from 'express';
|
|
3
3
|
import { DriveFolderService } from '../../services/drive/drive-folder.service';
|
|
4
|
+
import { WebDavFolderService } from '../services/webdav-folder.service';
|
|
4
5
|
export declare class MKCOLRequestHandler implements WebDavMethodHandler {
|
|
5
6
|
private readonly dependencies;
|
|
6
7
|
constructor(dependencies: {
|
|
7
8
|
driveFolderService: DriveFolderService;
|
|
9
|
+
webDavFolderService: WebDavFolderService;
|
|
8
10
|
});
|
|
9
11
|
handle: (req: Request, res: Response) => Promise<void>;
|
|
10
12
|
}
|
|
@@ -4,7 +4,6 @@ exports.MKCOLRequestHandler = void 0;
|
|
|
4
4
|
const webdav_utils_1 = require("../../utils/webdav.utils");
|
|
5
5
|
const logger_utils_1 = require("../../utils/logger.utils");
|
|
6
6
|
const xml_utils_1 = require("../../utils/xml.utils");
|
|
7
|
-
const async_utils_1 = require("../../utils/async.utils");
|
|
8
7
|
const errors_utils_1 = require("../../utils/errors.utils");
|
|
9
8
|
class MKCOLRequestHandler {
|
|
10
9
|
dependencies;
|
|
@@ -12,18 +11,11 @@ class MKCOLRequestHandler {
|
|
|
12
11
|
this.dependencies = dependencies;
|
|
13
12
|
}
|
|
14
13
|
handle = async (req, res) => {
|
|
15
|
-
const { driveFolderService } = this.dependencies;
|
|
14
|
+
const { driveFolderService, webDavFolderService } = this.dependencies;
|
|
16
15
|
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
17
16
|
logger_utils_1.webdavLogger.info(`[MKCOL] Request received for ${resource.type} at ${resource.url}`);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
resource: parentResource,
|
|
21
|
-
driveFolderService,
|
|
22
|
-
});
|
|
23
|
-
if (!parentDriveItem) {
|
|
24
|
-
throw new errors_utils_1.ConflictError(`Parent folders not found on Internxt Drive at ${resource.url}`);
|
|
25
|
-
}
|
|
26
|
-
const parentFolderItem = parentDriveItem;
|
|
17
|
+
const parentDriveFolderItem = (await webDavFolderService.getDriveFolderItemFromPath(resource.parentPath)) ??
|
|
18
|
+
(await webDavFolderService.createParentPathOrThrow(resource.parentPath));
|
|
27
19
|
const driveFolderItem = await webdav_utils_1.WebDavUtils.getDriveItemFromResource({
|
|
28
20
|
resource,
|
|
29
21
|
driveFolderService,
|
|
@@ -33,13 +25,11 @@ class MKCOLRequestHandler {
|
|
|
33
25
|
logger_utils_1.webdavLogger.info(`[MKCOL] ❌ Folder '${resource.url}' already exists`);
|
|
34
26
|
throw new errors_utils_1.MethodNotAllowed('Folder already exists');
|
|
35
27
|
}
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
parentFolderUuid:
|
|
28
|
+
const newFolder = await webDavFolderService.createFolder({
|
|
29
|
+
folderName: resource.path.base,
|
|
30
|
+
parentFolderUuid: parentDriveFolderItem.uuid,
|
|
39
31
|
});
|
|
40
|
-
const newFolder = await createFolder;
|
|
41
32
|
logger_utils_1.webdavLogger.info(`[MKCOL] ✅ Folder created with UUID ${newFolder.uuid}`);
|
|
42
|
-
await async_utils_1.AsyncUtils.sleep(500);
|
|
43
33
|
res.status(201).send(xml_utils_1.XMLUtils.toWebDavXML({}, {}));
|
|
44
34
|
};
|
|
45
35
|
}
|
|
@@ -2,11 +2,13 @@ import { Request, Response } from 'express';
|
|
|
2
2
|
import { DriveFileService } from '../../services/drive/drive-file.service';
|
|
3
3
|
import { DriveFolderService } from '../../services/drive/drive-folder.service';
|
|
4
4
|
import { WebDavMethodHandler } from '../../types/webdav.types';
|
|
5
|
+
import { WebDavFolderService } from '../services/webdav-folder.service';
|
|
5
6
|
export declare class MOVERequestHandler implements WebDavMethodHandler {
|
|
6
7
|
private readonly dependencies;
|
|
7
8
|
constructor(dependencies: {
|
|
8
9
|
driveFolderService: DriveFolderService;
|
|
9
10
|
driveFileService: DriveFileService;
|
|
11
|
+
webDavFolderService: WebDavFolderService;
|
|
10
12
|
});
|
|
11
13
|
handle: (req: Request, res: Response) => Promise<void>;
|
|
12
14
|
}
|
|
@@ -10,7 +10,7 @@ class MOVERequestHandler {
|
|
|
10
10
|
this.dependencies = dependencies;
|
|
11
11
|
}
|
|
12
12
|
handle = async (req, res) => {
|
|
13
|
-
const { driveFolderService, driveFileService } = this.dependencies;
|
|
13
|
+
const { driveFolderService, driveFileService, webDavFolderService } = this.dependencies;
|
|
14
14
|
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
15
15
|
logger_utils_1.webdavLogger.info(`[MOVE] Request received for ${resource.type} at ${resource.url}`);
|
|
16
16
|
const destinationUrl = req.header('destination');
|
|
@@ -49,15 +49,8 @@ class MOVERequestHandler {
|
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
51
|
logger_utils_1.webdavLogger.info(`[MOVE] Moving ${resource.type} with UUID ${originalDriveItem.uuid} to ${destinationPath}`);
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
resource: destinationFolderResource,
|
|
55
|
-
driveFolderService,
|
|
56
|
-
});
|
|
57
|
-
if (!destinationDriveFolderItem) {
|
|
58
|
-
throw new errors_utils_1.NotFoundError(`Resource not found on Internxt Drive at ${resource.url}`);
|
|
59
|
-
}
|
|
60
|
-
const destinationFolderItem = destinationDriveFolderItem;
|
|
52
|
+
const destinationFolderItem = (await webDavFolderService.getDriveFolderItemFromPath(destinationResource.parentPath)) ??
|
|
53
|
+
(await webDavFolderService.createParentPathOrThrow(destinationResource.parentPath));
|
|
61
54
|
if (resource.type === 'folder') {
|
|
62
55
|
const folder = originalDriveItem;
|
|
63
56
|
await driveFolderService.moveFolder(folder.uuid, {
|
|
@@ -3,13 +3,13 @@ import { DriveFileService } from '../../services/drive/drive-file.service';
|
|
|
3
3
|
import { NetworkFacade } from '../../services/network/network-facade.service';
|
|
4
4
|
import { AuthService } from '../../services/auth.service';
|
|
5
5
|
import { WebDavMethodHandler } from '../../types/webdav.types';
|
|
6
|
-
import { DriveFolderService } from '../../services/drive/drive-folder.service';
|
|
7
6
|
import { TrashService } from '../../services/drive/trash.service';
|
|
7
|
+
import { WebDavFolderService } from '../services/webdav-folder.service';
|
|
8
8
|
export declare class PUTRequestHandler implements WebDavMethodHandler {
|
|
9
9
|
private readonly dependencies;
|
|
10
10
|
constructor(dependencies: {
|
|
11
11
|
driveFileService: DriveFileService;
|
|
12
|
-
|
|
12
|
+
webDavFolderService: WebDavFolderService;
|
|
13
13
|
trashService: TrashService;
|
|
14
14
|
authService: AuthService;
|
|
15
15
|
networkFacade: NetworkFacade;
|
|
@@ -10,13 +10,13 @@ const cli_utils_1 = require("../../utils/cli.utils");
|
|
|
10
10
|
const stream_utils_1 = require("../../utils/stream.utils");
|
|
11
11
|
const thumbnail_utils_1 = require("../../utils/thumbnail.utils");
|
|
12
12
|
const thumbnail_service_1 = require("../../services/thumbnail.service");
|
|
13
|
+
const async_utils_1 = require("../../utils/async.utils");
|
|
13
14
|
class PUTRequestHandler {
|
|
14
15
|
dependencies;
|
|
15
16
|
constructor(dependencies) {
|
|
16
17
|
this.dependencies = dependencies;
|
|
17
18
|
}
|
|
18
19
|
handle = async (req, res) => {
|
|
19
|
-
const { authService, networkFacade, driveFileService, driveFolderService, trashService } = this.dependencies;
|
|
20
20
|
const contentLength = Number(req.headers['content-length']);
|
|
21
21
|
if (!contentLength || isNaN(contentLength) || contentLength <= 0) {
|
|
22
22
|
throw new errors_utils_1.UnsupportedMediaTypeError('Empty files are not supported');
|
|
@@ -26,30 +26,23 @@ class PUTRequestHandler {
|
|
|
26
26
|
throw new errors_utils_1.NotFoundError('Folders cannot be created with PUT. Use MKCOL instead.');
|
|
27
27
|
logger_utils_1.webdavLogger.info(`[PUT] Request received for ${resource.type} at ${resource.url}`);
|
|
28
28
|
logger_utils_1.webdavLogger.info(`[PUT] Uploading '${resource.name}' to '${resource.parentPath}'`);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
resource: parentResource,
|
|
32
|
-
driveFolderService,
|
|
33
|
-
});
|
|
34
|
-
if (!parentDriveFolderItem) {
|
|
35
|
-
throw new errors_utils_1.ConflictError(`Parent folders not found on Internxt Drive at ${resource.url}`);
|
|
36
|
-
}
|
|
37
|
-
const parentFolderItem = parentDriveFolderItem;
|
|
29
|
+
const parentDriveFolderItem = (await this.dependencies.webDavFolderService.getDriveFolderItemFromPath(resource.parentPath)) ??
|
|
30
|
+
(await this.dependencies.webDavFolderService.createParentPathOrThrow(resource.parentPath));
|
|
38
31
|
try {
|
|
39
|
-
const driveFileItem =
|
|
32
|
+
const driveFileItem = await webdav_utils_1.WebDavUtils.getDriveItemFromResource({
|
|
40
33
|
resource: resource,
|
|
41
|
-
driveFileService,
|
|
42
|
-
})
|
|
34
|
+
driveFileService: this.dependencies.driveFileService,
|
|
35
|
+
});
|
|
43
36
|
if (driveFileItem && driveFileItem.status === 'EXISTS') {
|
|
44
37
|
logger_utils_1.webdavLogger.info(`[PUT] File '${resource.name}' already exists in '${resource.path.dir}', trashing it...`);
|
|
45
|
-
await trashService.trashItems({
|
|
38
|
+
await this.dependencies.trashService.trashItems({
|
|
46
39
|
items: [{ type: resource.type, uuid: driveFileItem.uuid, id: null }],
|
|
47
40
|
});
|
|
48
41
|
}
|
|
49
42
|
}
|
|
50
43
|
catch {
|
|
51
44
|
}
|
|
52
|
-
const { user } = await authService.getAuthDetails();
|
|
45
|
+
const { user } = await this.dependencies.authService.getAuthDetails();
|
|
53
46
|
const fileType = resource.path.ext.replace('.', '');
|
|
54
47
|
const timer = cli_utils_1.CLIUtils.timer();
|
|
55
48
|
let bufferStream;
|
|
@@ -66,7 +59,7 @@ class PUTRequestHandler {
|
|
|
66
59
|
}
|
|
67
60
|
};
|
|
68
61
|
const fileId = await new Promise((resolve, reject) => {
|
|
69
|
-
const state = networkFacade.uploadFile(fileStream, contentLength, user.bucket, (err, res) => {
|
|
62
|
+
const state = this.dependencies.networkFacade.uploadFile(fileStream, contentLength, user.bucket, (err, res) => {
|
|
70
63
|
if (err) {
|
|
71
64
|
aborted = true;
|
|
72
65
|
return reject(err);
|
|
@@ -87,7 +80,7 @@ class PUTRequestHandler {
|
|
|
87
80
|
plainName: resource.path.name,
|
|
88
81
|
type: fileType,
|
|
89
82
|
size: contentLength,
|
|
90
|
-
folderUuid:
|
|
83
|
+
folderUuid: parentDriveFolderItem.uuid,
|
|
91
84
|
fileId: fileId,
|
|
92
85
|
bucket: user.bucket,
|
|
93
86
|
encryptVersion: types_1.EncryptionVersion.Aes03,
|
|
@@ -96,7 +89,7 @@ class PUTRequestHandler {
|
|
|
96
89
|
if (isThumbnailable && bufferStream) {
|
|
97
90
|
const thumbnailBuffer = bufferStream.getBuffer();
|
|
98
91
|
if (thumbnailBuffer) {
|
|
99
|
-
await thumbnail_service_1.ThumbnailService.instance.uploadThumbnail(thumbnailBuffer, fileType, user.bucket, file.uuid, networkFacade);
|
|
92
|
+
await thumbnail_service_1.ThumbnailService.instance.uploadThumbnail(thumbnailBuffer, fileType, user.bucket, file.uuid, this.dependencies.networkFacade);
|
|
100
93
|
}
|
|
101
94
|
}
|
|
102
95
|
}
|
|
@@ -105,6 +98,8 @@ class PUTRequestHandler {
|
|
|
105
98
|
}
|
|
106
99
|
const uploadTime = timer.stop();
|
|
107
100
|
logger_utils_1.webdavLogger.info(`[PUT] ✅ File uploaded in ${uploadTime}ms to Internxt Drive`);
|
|
101
|
+
await async_utils_1.AsyncUtils.sleep(500);
|
|
102
|
+
logger_utils_1.webdavLogger.info(`[PUT] [RESPONSE-201] ${resource.url} - Returning 201 Created after ${uploadTime}ms (+ 500ms propagation delay)`);
|
|
108
103
|
res.status(201).send();
|
|
109
104
|
};
|
|
110
105
|
}
|
|
@@ -4,6 +4,7 @@ exports.AuthMiddleware = void 0;
|
|
|
4
4
|
const sdk_manager_service_1 = require("../../services/sdk-manager.service");
|
|
5
5
|
const logger_utils_1 = require("../../utils/logger.utils");
|
|
6
6
|
const xml_utils_1 = require("../../utils/xml.utils");
|
|
7
|
+
const errors_utils_1 = require("../../utils/errors.utils");
|
|
7
8
|
const AuthMiddleware = (authService) => {
|
|
8
9
|
return (_, res, next) => {
|
|
9
10
|
(async () => {
|
|
@@ -14,10 +15,15 @@ const AuthMiddleware = (authService) => {
|
|
|
14
15
|
}
|
|
15
16
|
catch (error) {
|
|
16
17
|
let message = 'Authentication required to access this resource.';
|
|
17
|
-
if (
|
|
18
|
+
if ((0, errors_utils_1.isError)(error)) {
|
|
18
19
|
message = error.message;
|
|
20
|
+
if (error.stack) {
|
|
21
|
+
logger_utils_1.webdavLogger.error(`Error from AuthMiddleware: ${message}\nStack: ${error.stack}`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
logger_utils_1.webdavLogger.error(`Error from AuthMiddleware: ${message}`);
|
|
25
|
+
}
|
|
19
26
|
}
|
|
20
|
-
logger_utils_1.webdavLogger.error('Error from AuthMiddleware: ' + message);
|
|
21
27
|
const errorBodyXML = xml_utils_1.XMLUtils.toWebDavXML({
|
|
22
28
|
[xml_utils_1.XMLUtils.addDefaultNamespace('responsedescription')]: message,
|
|
23
29
|
}, {}, 'error');
|
|
@@ -3,10 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ErrorHandlingMiddleware = void 0;
|
|
4
4
|
const logger_utils_1 = require("../../utils/logger.utils");
|
|
5
5
|
const xml_utils_1 = require("../../utils/xml.utils");
|
|
6
|
+
const errors_utils_1 = require("../../utils/errors.utils");
|
|
6
7
|
const ErrorHandlingMiddleware = (err, req, res, _) => {
|
|
7
|
-
|
|
8
|
+
const message = (0, errors_utils_1.isError)(err) ? err.message : 'Something went wrong';
|
|
9
|
+
if ((0, errors_utils_1.isError)(err) && err.stack) {
|
|
10
|
+
logger_utils_1.webdavLogger.error(`[ERROR MIDDLEWARE] [${req.method.toUpperCase()} - ${req.url}] ${message}\nStack: ${err.stack}`);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
logger_utils_1.webdavLogger.error(`[ERROR MIDDLEWARE] [${req.method.toUpperCase()} - ${req.url}] ${message}`);
|
|
14
|
+
}
|
|
8
15
|
const errorBodyXML = xml_utils_1.XMLUtils.toWebDavXML({
|
|
9
|
-
[xml_utils_1.XMLUtils.addDefaultNamespace('responsedescription')]:
|
|
16
|
+
[xml_utils_1.XMLUtils.addDefaultNamespace('responsedescription')]: message,
|
|
10
17
|
}, {}, 'error');
|
|
11
18
|
let statusCode = 500;
|
|
12
19
|
if ('statusCode' in err && !isNaN(err.statusCode)) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ConfigService } from '../../services/config.service';
|
|
2
|
+
import { DriveFolderService } from '../../services/drive/drive-folder.service';
|
|
3
|
+
import { DriveFolderItem } from '../../types/drive.types';
|
|
4
|
+
export declare class WebDavFolderService {
|
|
5
|
+
private readonly dependencies;
|
|
6
|
+
constructor(dependencies: {
|
|
7
|
+
driveFolderService: DriveFolderService;
|
|
8
|
+
configService: ConfigService;
|
|
9
|
+
});
|
|
10
|
+
getDriveFolderItemFromPath: (path: string) => Promise<DriveFolderItem | undefined>;
|
|
11
|
+
createFolder: ({ folderName, parentFolderUuid, }: {
|
|
12
|
+
folderName: string;
|
|
13
|
+
parentFolderUuid: string;
|
|
14
|
+
}) => Promise<DriveFolderItem>;
|
|
15
|
+
createParentPathOrThrow: (parentPath: string) => Promise<DriveFolderItem>;
|
|
16
|
+
private createFolderRecursively;
|
|
17
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebDavFolderService = void 0;
|
|
4
|
+
const errors_utils_1 = require("../../utils/errors.utils");
|
|
5
|
+
const webdav_utils_1 = require("../../utils/webdav.utils");
|
|
6
|
+
const async_utils_1 = require("../../utils/async.utils");
|
|
7
|
+
const auth_service_1 = require("../../services/auth.service");
|
|
8
|
+
const drive_utils_1 = require("../../utils/drive.utils");
|
|
9
|
+
class WebDavFolderService {
|
|
10
|
+
dependencies;
|
|
11
|
+
constructor(dependencies) {
|
|
12
|
+
this.dependencies = dependencies;
|
|
13
|
+
}
|
|
14
|
+
getDriveFolderItemFromPath = async (path) => {
|
|
15
|
+
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(path, false);
|
|
16
|
+
return await webdav_utils_1.WebDavUtils.getDriveItemFromResource({
|
|
17
|
+
resource,
|
|
18
|
+
driveFolderService: this.dependencies.driveFolderService,
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
createFolder = async ({ folderName, parentFolderUuid, }) => {
|
|
22
|
+
const [createFolderPromise] = this.dependencies.driveFolderService.createFolder({
|
|
23
|
+
plainName: folderName,
|
|
24
|
+
parentFolderUuid: parentFolderUuid,
|
|
25
|
+
});
|
|
26
|
+
const newFolder = await createFolderPromise;
|
|
27
|
+
await async_utils_1.AsyncUtils.sleep(500);
|
|
28
|
+
return drive_utils_1.DriveUtils.createFolderResponseToItem(newFolder);
|
|
29
|
+
};
|
|
30
|
+
createParentPathOrThrow = async (parentPath) => {
|
|
31
|
+
const { createFullPath } = await this.dependencies.configService.readWebdavConfig();
|
|
32
|
+
if (!createFullPath) {
|
|
33
|
+
throw new errors_utils_1.ConflictError(`Parent folders not found on Internxt Drive at ${webdav_utils_1.WebDavUtils.decodeUrl(parentPath, false)}`);
|
|
34
|
+
}
|
|
35
|
+
const folders = parentPath.split('/').filter((f) => f.length > 0);
|
|
36
|
+
const { user } = await auth_service_1.AuthService.instance.getAuthDetails();
|
|
37
|
+
return await this.createFolderRecursively(folders, user.rootFolderId);
|
|
38
|
+
};
|
|
39
|
+
async createFolderRecursively(remainingFolders, parentFolderUuid, accumulatedPath = '') {
|
|
40
|
+
const [currentFolderName, ...rest] = remainingFolders;
|
|
41
|
+
const newPath = webdav_utils_1.WebDavUtils.joinURL(accumulatedPath, currentFolderName);
|
|
42
|
+
const folderPath = webdav_utils_1.WebDavUtils.normalizeFolderPath(newPath);
|
|
43
|
+
const folder = (await this.getDriveFolderItemFromPath(folderPath)) ??
|
|
44
|
+
(await this.createFolder({ folderName: currentFolderName, parentFolderUuid }));
|
|
45
|
+
if (rest.length === 0) {
|
|
46
|
+
return folder;
|
|
47
|
+
}
|
|
48
|
+
return await this.createFolderRecursively(rest, folder.uuid, newPath);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.WebDavFolderService = WebDavFolderService;
|
|
@@ -31,6 +31,7 @@ const MOVE_handler_1 = require("./handlers/MOVE.handler");
|
|
|
31
31
|
const COPY_handler_1 = require("./handlers/COPY.handler");
|
|
32
32
|
const inxt_js_1 = require("@internxt/inxt-js");
|
|
33
33
|
const mkcol_middleware_1 = require("./middewares/mkcol.middleware");
|
|
34
|
+
const webdav_folder_service_1 = require("./services/webdav-folder.service");
|
|
34
35
|
class WebDavServer {
|
|
35
36
|
app;
|
|
36
37
|
configService;
|
|
@@ -82,6 +83,10 @@ class WebDavServer {
|
|
|
82
83
|
registerHandlers = async () => {
|
|
83
84
|
const serverListenPath = /(.*)/;
|
|
84
85
|
const networkFacade = await this.getNetworkFacade();
|
|
86
|
+
const webDavFolderService = new webdav_folder_service_1.WebDavFolderService({
|
|
87
|
+
driveFolderService: this.driveFolderService,
|
|
88
|
+
configService: this.configService,
|
|
89
|
+
});
|
|
85
90
|
this.app.head(serverListenPath, (0, express_async_handler_1.default)(new HEAD_handler_1.HEADRequestHandler({
|
|
86
91
|
driveFileService: this.driveFileService,
|
|
87
92
|
}).handle));
|
|
@@ -99,13 +104,14 @@ class WebDavServer {
|
|
|
99
104
|
}).handle));
|
|
100
105
|
this.app.put(serverListenPath, (0, express_async_handler_1.default)(new PUT_handler_1.PUTRequestHandler({
|
|
101
106
|
driveFileService: this.driveFileService,
|
|
102
|
-
|
|
107
|
+
webDavFolderService: webDavFolderService,
|
|
103
108
|
authService: this.authService,
|
|
104
109
|
trashService: this.trashService,
|
|
105
110
|
networkFacade: networkFacade,
|
|
106
111
|
}).handle));
|
|
107
112
|
this.app.mkcol(serverListenPath, (0, express_async_handler_1.default)(new MKCOL_handler_1.MKCOLRequestHandler({
|
|
108
113
|
driveFolderService: this.driveFolderService,
|
|
114
|
+
webDavFolderService: webDavFolderService,
|
|
109
115
|
}).handle));
|
|
110
116
|
this.app.delete(serverListenPath, (0, express_async_handler_1.default)(new DELETE_handler_1.DELETERequestHandler({
|
|
111
117
|
trashService: this.trashService,
|
|
@@ -116,6 +122,7 @@ class WebDavServer {
|
|
|
116
122
|
this.app.move(serverListenPath, (0, express_async_handler_1.default)(new MOVE_handler_1.MOVERequestHandler({
|
|
117
123
|
driveFolderService: this.driveFolderService,
|
|
118
124
|
driveFileService: this.driveFileService,
|
|
125
|
+
webDavFolderService,
|
|
119
126
|
}).handle));
|
|
120
127
|
this.app.copy(serverListenPath, (0, express_async_handler_1.default)(new COPY_handler_1.COPYRequestHandler().handle));
|
|
121
128
|
};
|
package/oclif.manifest.json
CHANGED
|
@@ -1196,6 +1196,14 @@
|
|
|
1196
1196
|
"hasDynamicHelp": false,
|
|
1197
1197
|
"multiple": false,
|
|
1198
1198
|
"type": "option"
|
|
1199
|
+
},
|
|
1200
|
+
"createFullPath": {
|
|
1201
|
+
"char": "c",
|
|
1202
|
+
"description": "Auto-create missing parent directories during file uploads.",
|
|
1203
|
+
"name": "createFullPath",
|
|
1204
|
+
"required": false,
|
|
1205
|
+
"allowNo": true,
|
|
1206
|
+
"type": "boolean"
|
|
1199
1207
|
}
|
|
1200
1208
|
},
|
|
1201
1209
|
"hasDynamicHelp": false,
|
|
@@ -1290,5 +1298,5 @@
|
|
|
1290
1298
|
]
|
|
1291
1299
|
}
|
|
1292
1300
|
},
|
|
1293
|
-
"version": "1.5.
|
|
1301
|
+
"version": "1.5.8"
|
|
1294
1302
|
}
|