@internxt/cli 1.4.2 → 1.5.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/README.md +27 -27
- package/dist/commands/download-file.js +13 -5
- package/dist/commands/upload-file.js +51 -17
- package/dist/commands/webdav.js +4 -0
- package/dist/services/crypto.service.d.ts +1 -3
- package/dist/services/crypto.service.js +17 -7
- package/dist/services/drive/drive-file.service.d.ts +1 -0
- package/dist/services/drive/drive-file.service.js +4 -0
- package/dist/services/network/download.service.d.ts +3 -1
- package/dist/services/network/download.service.js +5 -3
- package/dist/services/network/network-facade.service.d.ts +8 -9
- package/dist/services/network/network-facade.service.js +39 -50
- package/dist/services/thumbnail.service.d.ts +7 -0
- package/dist/services/thumbnail.service.js +55 -0
- package/dist/types/network.types.d.ts +11 -2
- package/dist/utils/errors.utils.d.ts +4 -0
- package/dist/utils/errors.utils.js +10 -1
- package/dist/utils/logger.utils.js +16 -2
- package/dist/utils/network.utils.d.ts +11 -0
- package/dist/utils/network.utils.js +36 -0
- package/dist/utils/stream.utils.d.ts +8 -10
- package/dist/utils/stream.utils.js +18 -17
- package/dist/utils/thumbnail.utils.d.ts +9 -0
- package/dist/utils/thumbnail.utils.js +44 -0
- package/dist/webdav/handlers/DELETE.handler.js +4 -3
- package/dist/webdav/handlers/GET.handler.d.ts +0 -2
- package/dist/webdav/handlers/GET.handler.js +21 -19
- package/dist/webdav/handlers/HEAD.handler.d.ts +9 -2
- package/dist/webdav/handlers/HEAD.handler.js +34 -2
- package/dist/webdav/handlers/MKCOL.handler.js +3 -3
- package/dist/webdav/handlers/MOVE.handler.js +2 -2
- package/dist/webdav/handlers/OPTIONS.handler.d.ts +1 -1
- package/dist/webdav/handlers/OPTIONS.handler.js +29 -4
- package/dist/webdav/handlers/PROPFIND.handler.js +1 -1
- package/dist/webdav/handlers/PUT.handler.js +55 -15
- package/dist/webdav/index.js +10 -2
- package/dist/webdav/middewares/auth.middleware.d.ts +2 -2
- package/dist/webdav/middewares/auth.middleware.js +8 -8
- package/dist/webdav/webdav-server.d.ts +1 -3
- package/dist/webdav/webdav-server.js +20 -8
- package/oclif.manifest.json +1 -1
- package/package.json +25 -22
- package/scripts/restart-webdav.js +16 -0
- package/dist/services/network/upload.service.d.ts +0 -8
- package/dist/services/network/upload.service.js +0 -24
- package/dist/utils/hash.utils.d.ts +0 -12
- package/dist/utils/hash.utils.js +0 -37
- package/scripts/skip-in-ci.js +0 -5
|
@@ -1,9 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HEADRequestHandler = void 0;
|
|
4
|
+
const webdav_utils_1 = require("../../utils/webdav.utils");
|
|
5
|
+
const logger_utils_1 = require("../../utils/logger.utils");
|
|
6
|
+
const network_utils_1 = require("../../utils/network.utils");
|
|
4
7
|
class HEADRequestHandler {
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
dependencies;
|
|
9
|
+
constructor(dependencies) {
|
|
10
|
+
this.dependencies = dependencies;
|
|
11
|
+
}
|
|
12
|
+
handle = async (req, res) => {
|
|
13
|
+
const { driveDatabaseManager, driveFileService } = this.dependencies;
|
|
14
|
+
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
15
|
+
if (resource.type === 'folder') {
|
|
16
|
+
res.status(200).send();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
logger_utils_1.webdavLogger.info(`[HEAD] Request received for ${resource.type} at ${resource.url}`);
|
|
20
|
+
const driveFile = (await webdav_utils_1.WebDavUtils.getAndSearchItemFromResource({
|
|
21
|
+
resource,
|
|
22
|
+
driveDatabaseManager,
|
|
23
|
+
driveFileService,
|
|
24
|
+
}));
|
|
25
|
+
logger_utils_1.webdavLogger.info(`[HEAD] [${driveFile.uuid}] Found Drive File`);
|
|
26
|
+
const range = req.headers['range'];
|
|
27
|
+
const rangeOptions = network_utils_1.NetworkUtils.parseRangeHeader({
|
|
28
|
+
range,
|
|
29
|
+
totalFileSize: driveFile.size,
|
|
30
|
+
});
|
|
31
|
+
let contentLength = driveFile.size;
|
|
32
|
+
if (rangeOptions) {
|
|
33
|
+
logger_utils_1.webdavLogger.info(`[HEAD] [${driveFile.uuid}] Range request received:`, { rangeOptions });
|
|
34
|
+
contentLength = rangeOptions.rangeSize;
|
|
35
|
+
}
|
|
36
|
+
res.header('Content-Type', 'application/octet-stream');
|
|
37
|
+
res.header('Content-length', contentLength.toString());
|
|
38
|
+
res.status(200).send();
|
|
7
39
|
};
|
|
8
40
|
}
|
|
9
41
|
exports.HEADRequestHandler = HEADRequestHandler;
|
|
@@ -13,7 +13,7 @@ class MKCOLRequestHandler {
|
|
|
13
13
|
handle = async (req, res) => {
|
|
14
14
|
const { driveDatabaseManager, driveFolderService } = this.dependencies;
|
|
15
15
|
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
16
|
-
logger_utils_1.webdavLogger.info(
|
|
16
|
+
logger_utils_1.webdavLogger.info(`[MKCOL] Request received for ${resource.type} at ${resource.url}`);
|
|
17
17
|
const parentResource = await webdav_utils_1.WebDavUtils.getRequestedResource(resource.parentPath);
|
|
18
18
|
const parentFolderItem = (await webdav_utils_1.WebDavUtils.getAndSearchItemFromResource({
|
|
19
19
|
resource: parentResource,
|
|
@@ -21,11 +21,11 @@ class MKCOLRequestHandler {
|
|
|
21
21
|
driveFolderService,
|
|
22
22
|
}));
|
|
23
23
|
const [createFolder] = driveFolderService.createFolder({
|
|
24
|
-
plainName: resource.
|
|
24
|
+
plainName: resource.path.base,
|
|
25
25
|
parentFolderUuid: parentFolderItem.uuid,
|
|
26
26
|
});
|
|
27
27
|
const newFolder = await createFolder;
|
|
28
|
-
logger_utils_1.webdavLogger.info(
|
|
28
|
+
logger_utils_1.webdavLogger.info(`[MKCOL] ✅ Folder created with UUID ${newFolder.uuid}`);
|
|
29
29
|
await driveDatabaseManager.createFolder({
|
|
30
30
|
name: newFolder.plainName,
|
|
31
31
|
status: 'EXISTS',
|
|
@@ -12,10 +12,10 @@ class MOVERequestHandler {
|
|
|
12
12
|
handle = async (req, res) => {
|
|
13
13
|
const { driveDatabaseManager, driveFolderService, driveFileService } = this.dependencies;
|
|
14
14
|
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
15
|
-
logger_utils_1.webdavLogger.info(
|
|
15
|
+
logger_utils_1.webdavLogger.info(`[MOVE] Request received for ${resource.type} at ${resource.url}`);
|
|
16
16
|
const destinationUrl = req.header('destination');
|
|
17
17
|
if (!destinationUrl) {
|
|
18
|
-
throw new errors_utils_1.NotFoundError('Destination folder not received');
|
|
18
|
+
throw new errors_utils_1.NotFoundError('[MOVE] Destination folder not received');
|
|
19
19
|
}
|
|
20
20
|
const destinationPath = webdav_utils_1.WebDavUtils.removeHostFromURL(destinationUrl);
|
|
21
21
|
const destinationResource = await webdav_utils_1.WebDavUtils.getRequestedResource(destinationPath);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebDavMethodHandler } from '../../types/webdav.types';
|
|
2
2
|
import { Request, Response } from 'express';
|
|
3
3
|
export declare class OPTIONSRequestHandler implements WebDavMethodHandler {
|
|
4
|
-
handle: (
|
|
4
|
+
handle: (req: Request, res: Response) => Promise<void>;
|
|
5
5
|
}
|
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OPTIONSRequestHandler = void 0;
|
|
4
|
+
const webdav_utils_1 = require("../../utils/webdav.utils");
|
|
5
|
+
const logger_utils_1 = require("../../utils/logger.utils");
|
|
4
6
|
class OPTIONSRequestHandler {
|
|
5
|
-
handle = async (
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
handle = async (req, res) => {
|
|
8
|
+
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
9
|
+
logger_utils_1.webdavLogger.info(`[OPTIONS] Request received for ${resource.type} at ${resource.url}`);
|
|
10
|
+
if (resource.url === '/' || resource.url === '') {
|
|
11
|
+
const allowedMethods = 'DELETE, GET, HEAD, MKCOL, MOVE, OPTIONS, PROPFIND, PUT';
|
|
12
|
+
logger_utils_1.webdavLogger.info(`[OPTIONS] Returning Allowed Options: ${allowedMethods}`);
|
|
13
|
+
res.header('Allow', 'DELETE, GET, HEAD, MKCOL, MOVE, OPTIONS, PROPFIND, PUT');
|
|
14
|
+
res.header('DAV', '1, 2, ordered-collections');
|
|
15
|
+
res.status(200).send();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (resource.type === 'folder') {
|
|
19
|
+
const allowedMethods = 'DELETE, HEAD, MKCOL, MOVE, OPTIONS, PROPFIND';
|
|
20
|
+
logger_utils_1.webdavLogger.info(`[OPTIONS] Returning Allowed Options: ${allowedMethods}`);
|
|
21
|
+
res.header('Allow', allowedMethods);
|
|
22
|
+
res.header('DAV', '1, 2, ordered-collections');
|
|
23
|
+
res.status(200).send();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (resource.type === 'file') {
|
|
27
|
+
const allowedMethods = 'DELETE, GET, HEAD, MOVE, OPTIONS, PROPFIND, PUT';
|
|
28
|
+
logger_utils_1.webdavLogger.info(`[OPTIONS] Returning Allowed Options: ${allowedMethods}`);
|
|
29
|
+
res.header('Allow', allowedMethods);
|
|
30
|
+
res.header('DAV', '1, 2, ordered-collections');
|
|
31
|
+
res.status(200).send();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
9
34
|
};
|
|
10
35
|
}
|
|
11
36
|
exports.OPTIONSRequestHandler = OPTIONSRequestHandler;
|
|
@@ -19,7 +19,7 @@ class PROPFINDRequestHandler {
|
|
|
19
19
|
handle = async (req, res) => {
|
|
20
20
|
const { driveDatabaseManager, driveFolderService, driveFileService } = this.dependencies;
|
|
21
21
|
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
22
|
-
logger_utils_1.webdavLogger.info(
|
|
22
|
+
logger_utils_1.webdavLogger.info(`[PROPFIND] Request received for ${resource.type} at ${resource.url}`);
|
|
23
23
|
const driveItem = await webdav_utils_1.WebDavUtils.getAndSearchItemFromResource({
|
|
24
24
|
resource,
|
|
25
25
|
driveDatabaseManager,
|
|
@@ -6,6 +6,10 @@ const errors_utils_1 = require("../../utils/errors.utils");
|
|
|
6
6
|
const webdav_utils_1 = require("../../utils/webdav.utils");
|
|
7
7
|
const logger_utils_1 = require("../../utils/logger.utils");
|
|
8
8
|
const types_1 = require("@internxt/sdk/dist/drive/storage/types");
|
|
9
|
+
const cli_utils_1 = require("../../utils/cli.utils");
|
|
10
|
+
const stream_utils_1 = require("../../utils/stream.utils");
|
|
11
|
+
const thumbnail_utils_1 = require("../../utils/thumbnail.utils");
|
|
12
|
+
const thumbnail_service_1 = require("../../services/thumbnail.service");
|
|
9
13
|
class PUTRequestHandler {
|
|
10
14
|
dependencies;
|
|
11
15
|
constructor(dependencies) {
|
|
@@ -18,7 +22,10 @@ class PUTRequestHandler {
|
|
|
18
22
|
throw new errors_utils_1.UnsupportedMediaTypeError('Empty files are not supported');
|
|
19
23
|
}
|
|
20
24
|
const resource = await webdav_utils_1.WebDavUtils.getRequestedResource(req);
|
|
21
|
-
|
|
25
|
+
if (resource.type === 'folder')
|
|
26
|
+
throw new errors_utils_1.NotFoundError('Folders cannot be created with PUT. Use MKCOL instead.');
|
|
27
|
+
logger_utils_1.webdavLogger.info(`[PUT] Request received for ${resource.type} at ${resource.url}`);
|
|
28
|
+
logger_utils_1.webdavLogger.info(`[PUT] Uploading '${resource.name}' to '${resource.parentPath}'`);
|
|
22
29
|
const parentResource = await webdav_utils_1.WebDavUtils.getRequestedResource(resource.parentPath);
|
|
23
30
|
const parentFolderItem = (await webdav_utils_1.WebDavUtils.getAndSearchItemFromResource({
|
|
24
31
|
resource: parentResource,
|
|
@@ -32,7 +39,7 @@ class PUTRequestHandler {
|
|
|
32
39
|
driveFileService,
|
|
33
40
|
}));
|
|
34
41
|
if (driveFileItem && driveFileItem.status === 'EXISTS') {
|
|
35
|
-
logger_utils_1.webdavLogger.info(`File '${resource.name}' already exists in '${resource.path.dir}', trashing it
|
|
42
|
+
logger_utils_1.webdavLogger.info(`[PUT] File '${resource.name}' already exists in '${resource.path.dir}', trashing it...`);
|
|
36
43
|
await driveDatabaseManager.deleteFileById(driveFileItem.id);
|
|
37
44
|
await trashService.trashItems({
|
|
38
45
|
items: [{ type: resource.type, uuid: driveFileItem.uuid }],
|
|
@@ -42,29 +49,62 @@ class PUTRequestHandler {
|
|
|
42
49
|
catch {
|
|
43
50
|
}
|
|
44
51
|
const { user } = await authService.getAuthDetails();
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
const fileType = resource.path.ext.replace('.', '');
|
|
53
|
+
const timer = cli_utils_1.CLIUtils.timer();
|
|
54
|
+
let bufferStream;
|
|
55
|
+
let fileStream = req;
|
|
56
|
+
const isThumbnailable = (0, thumbnail_utils_1.isFileThumbnailable)(fileType);
|
|
57
|
+
if (isThumbnailable) {
|
|
58
|
+
bufferStream = new stream_utils_1.BufferStream();
|
|
59
|
+
fileStream = req.pipe(bufferStream);
|
|
60
|
+
}
|
|
61
|
+
let uploaded = false, aborted = false;
|
|
62
|
+
const progressCallback = (progress) => {
|
|
63
|
+
if (!uploaded && !aborted) {
|
|
64
|
+
logger_utils_1.webdavLogger.info(`[PUT] Upload progress for file ${resource.name}: ${(progress * 100).toFixed(2)}%`);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const fileId = await new Promise((resolve, reject) => {
|
|
68
|
+
const state = networkFacade.uploadFile(fileStream, contentLength, user.bucket, (err, res) => {
|
|
69
|
+
if (err) {
|
|
70
|
+
aborted = true;
|
|
71
|
+
return reject(err);
|
|
52
72
|
}
|
|
53
|
-
|
|
73
|
+
resolve(res);
|
|
74
|
+
}, progressCallback);
|
|
75
|
+
res.on('close', async () => {
|
|
76
|
+
aborted = true;
|
|
77
|
+
if (!uploaded) {
|
|
78
|
+
logger_utils_1.webdavLogger.info('[PUT] ❌ HTTP Client has been disconnected, res has been closed.');
|
|
79
|
+
state.stop();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
54
82
|
});
|
|
55
|
-
|
|
56
|
-
logger_utils_1.webdavLogger.info('✅ File uploaded to network');
|
|
83
|
+
uploaded = true;
|
|
84
|
+
logger_utils_1.webdavLogger.info('[PUT] ✅ File uploaded to network');
|
|
57
85
|
const file = await drive_file_service_1.DriveFileService.instance.createFile({
|
|
58
86
|
plain_name: resource.path.name,
|
|
59
|
-
type:
|
|
87
|
+
type: fileType,
|
|
60
88
|
size: contentLength,
|
|
61
89
|
folder_id: parentFolderItem.uuid,
|
|
62
|
-
id:
|
|
90
|
+
id: fileId,
|
|
63
91
|
bucket: user.bucket,
|
|
64
92
|
encrypt_version: types_1.EncryptionVersion.Aes03,
|
|
65
93
|
name: '',
|
|
66
94
|
});
|
|
67
|
-
|
|
95
|
+
try {
|
|
96
|
+
if (isThumbnailable && bufferStream) {
|
|
97
|
+
const thumbnailBuffer = bufferStream.getBuffer();
|
|
98
|
+
if (thumbnailBuffer) {
|
|
99
|
+
await thumbnail_service_1.ThumbnailService.instance.uploadThumbnail(thumbnailBuffer, fileType, user.bucket, file.id, networkFacade);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
logger_utils_1.webdavLogger.info(`[PUT] ❌ File thumbnail upload failed ${error.message}`);
|
|
105
|
+
}
|
|
106
|
+
const uploadTime = timer.stop();
|
|
107
|
+
logger_utils_1.webdavLogger.info(`[PUT] ✅ File uploaded in ${uploadTime}ms to Internxt Drive`);
|
|
68
108
|
await driveDatabaseManager.createFile(file, resource.path.dir + '/');
|
|
69
109
|
res.status(200).send();
|
|
70
110
|
};
|
package/dist/webdav/index.js
CHANGED
|
@@ -12,21 +12,29 @@ const drive_database_manager_service_1 = require("../services/database/drive-dat
|
|
|
12
12
|
const drive_file_repository_1 = require("../services/database/drive-file/drive-file.repository");
|
|
13
13
|
const drive_folder_repository_1 = require("../services/database/drive-folder/drive-folder.repository");
|
|
14
14
|
const drive_file_service_1 = require("../services/drive/drive-file.service");
|
|
15
|
-
const upload_service_1 = require("../services/network/upload.service");
|
|
16
15
|
const download_service_1 = require("../services/network/download.service");
|
|
17
16
|
const auth_service_1 = require("../services/auth.service");
|
|
18
17
|
const crypto_service_1 = require("../services/crypto.service");
|
|
19
18
|
const trash_service_1 = require("../services/drive/trash.service");
|
|
20
19
|
const logger_utils_1 = require("../utils/logger.utils");
|
|
20
|
+
const sdk_manager_service_1 = require("../services/sdk-manager.service");
|
|
21
21
|
dotenv_1.default.config();
|
|
22
22
|
const init = async () => {
|
|
23
23
|
await config_service_1.ConfigService.instance.ensureInternxtCliDataDirExists();
|
|
24
24
|
await config_service_1.ConfigService.instance.ensureWebdavCertsDirExists();
|
|
25
25
|
await config_service_1.ConfigService.instance.ensureInternxtLogsDirExists();
|
|
26
26
|
await drive_database_manager_service_1.DriveDatabaseManager.init();
|
|
27
|
-
|
|
27
|
+
const { token, newToken } = await auth_service_1.AuthService.instance.getAuthDetails();
|
|
28
|
+
sdk_manager_service_1.SdkManager.init({
|
|
29
|
+
token,
|
|
30
|
+
newToken,
|
|
31
|
+
});
|
|
32
|
+
new webdav_server_1.WebDavServer((0, express_1.default)(), config_service_1.ConfigService.instance, drive_file_service_1.DriveFileService.instance, drive_folder_service_1.DriveFolderService.instance, new drive_database_manager_service_1.DriveDatabaseManager(new drive_file_repository_1.DriveFileRepository(), new drive_folder_repository_1.DriveFolderRepository()), download_service_1.DownloadService.instance, auth_service_1.AuthService.instance, crypto_service_1.CryptoService.instance, trash_service_1.TrashService.instance)
|
|
28
33
|
.start()
|
|
29
34
|
.then()
|
|
30
35
|
.catch((err) => logger_utils_1.webdavLogger.error('Failed to start WebDAV server', err));
|
|
31
36
|
};
|
|
37
|
+
process.on('uncaughtException', (err) => {
|
|
38
|
+
logger_utils_1.webdavLogger.error('Unhandled exception:', err);
|
|
39
|
+
});
|
|
32
40
|
init();
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { RequestHandler } from 'express';
|
|
2
|
-
import {
|
|
3
|
-
export declare const AuthMiddleware: (
|
|
2
|
+
import { AuthService } from '../../services/auth.service';
|
|
3
|
+
export declare const AuthMiddleware: (authService: AuthService) => RequestHandler;
|
|
@@ -2,24 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AuthMiddleware = void 0;
|
|
4
4
|
const sdk_manager_service_1 = require("../../services/sdk-manager.service");
|
|
5
|
-
const
|
|
5
|
+
const logger_utils_1 = require("../../utils/logger.utils");
|
|
6
|
+
const AuthMiddleware = (authService) => {
|
|
6
7
|
return (req, res, next) => {
|
|
7
8
|
(async () => {
|
|
8
9
|
try {
|
|
9
|
-
const
|
|
10
|
-
if (!credentials)
|
|
11
|
-
throw new Error('Unauthorized');
|
|
10
|
+
const { token, newToken, user } = await authService.getAuthDetails();
|
|
12
11
|
sdk_manager_service_1.SdkManager.init({
|
|
13
|
-
token
|
|
14
|
-
newToken
|
|
12
|
+
token,
|
|
13
|
+
newToken,
|
|
15
14
|
});
|
|
16
15
|
req.user = {
|
|
17
|
-
uuid:
|
|
18
|
-
rootFolderId:
|
|
16
|
+
uuid: user.uuid,
|
|
17
|
+
rootFolderId: user.root_folder_id,
|
|
19
18
|
};
|
|
20
19
|
next();
|
|
21
20
|
}
|
|
22
21
|
catch (error) {
|
|
22
|
+
logger_utils_1.webdavLogger.error('Error from AuthMiddleware: ' + error.message);
|
|
23
23
|
res.status(401).send({ error: error.message });
|
|
24
24
|
}
|
|
25
25
|
})();
|
|
@@ -3,7 +3,6 @@ import { ConfigService } from '../services/config.service';
|
|
|
3
3
|
import { DriveFolderService } from '../services/drive/drive-folder.service';
|
|
4
4
|
import { DriveDatabaseManager } from '../services/database/drive-database-manager.service';
|
|
5
5
|
import { DriveFileService } from '../services/drive/drive-file.service';
|
|
6
|
-
import { UploadService } from '../services/network/upload.service';
|
|
7
6
|
import { DownloadService } from '../services/network/download.service';
|
|
8
7
|
import { AuthService } from '../services/auth.service';
|
|
9
8
|
import { CryptoService } from '../services/crypto.service';
|
|
@@ -14,12 +13,11 @@ export declare class WebDavServer {
|
|
|
14
13
|
private readonly driveFileService;
|
|
15
14
|
private readonly driveFolderService;
|
|
16
15
|
private readonly driveDatabaseManager;
|
|
17
|
-
private readonly uploadService;
|
|
18
16
|
private readonly downloadService;
|
|
19
17
|
private readonly authService;
|
|
20
18
|
private readonly cryptoService;
|
|
21
19
|
private readonly trashService;
|
|
22
|
-
constructor(app: Express, configService: ConfigService, driveFileService: DriveFileService, driveFolderService: DriveFolderService, driveDatabaseManager: DriveDatabaseManager,
|
|
20
|
+
constructor(app: Express, configService: ConfigService, driveFileService: DriveFileService, driveFolderService: DriveFolderService, driveDatabaseManager: DriveDatabaseManager, downloadService: DownloadService, authService: AuthService, cryptoService: CryptoService, trashService: TrashService);
|
|
23
21
|
private readonly getNetworkFacade;
|
|
24
22
|
private readonly registerMiddlewares;
|
|
25
23
|
private readonly registerHandlers;
|
|
@@ -15,6 +15,9 @@ const auth_middleware_1 = require("./middewares/auth.middleware");
|
|
|
15
15
|
const request_logger_middleware_1 = require("./middewares/request-logger.middleware");
|
|
16
16
|
const GET_handler_1 = require("./handlers/GET.handler");
|
|
17
17
|
const HEAD_handler_1 = require("./handlers/HEAD.handler");
|
|
18
|
+
const download_service_1 = require("../services/network/download.service");
|
|
19
|
+
const auth_service_1 = require("../services/auth.service");
|
|
20
|
+
const crypto_service_1 = require("../services/crypto.service");
|
|
18
21
|
const errors_middleware_1 = require("./middewares/errors.middleware");
|
|
19
22
|
const express_async_handler_1 = __importDefault(require("express-async-handler"));
|
|
20
23
|
const sdk_manager_service_1 = require("../services/sdk-manager.service");
|
|
@@ -26,24 +29,23 @@ const DELETE_handler_1 = require("./handlers/DELETE.handler");
|
|
|
26
29
|
const PROPPATCH_handler_1 = require("./handlers/PROPPATCH.handler");
|
|
27
30
|
const MOVE_handler_1 = require("./handlers/MOVE.handler");
|
|
28
31
|
const COPY_handler_1 = require("./handlers/COPY.handler");
|
|
32
|
+
const inxt_js_1 = require("@internxt/inxt-js");
|
|
29
33
|
class WebDavServer {
|
|
30
34
|
app;
|
|
31
35
|
configService;
|
|
32
36
|
driveFileService;
|
|
33
37
|
driveFolderService;
|
|
34
38
|
driveDatabaseManager;
|
|
35
|
-
uploadService;
|
|
36
39
|
downloadService;
|
|
37
40
|
authService;
|
|
38
41
|
cryptoService;
|
|
39
42
|
trashService;
|
|
40
|
-
constructor(app, configService, driveFileService, driveFolderService, driveDatabaseManager,
|
|
43
|
+
constructor(app, configService, driveFileService, driveFolderService, driveDatabaseManager, downloadService, authService, cryptoService, trashService) {
|
|
41
44
|
this.app = app;
|
|
42
45
|
this.configService = configService;
|
|
43
46
|
this.driveFileService = driveFileService;
|
|
44
47
|
this.driveFolderService = driveFolderService;
|
|
45
48
|
this.driveDatabaseManager = driveDatabaseManager;
|
|
46
|
-
this.uploadService = uploadService;
|
|
47
49
|
this.downloadService = downloadService;
|
|
48
50
|
this.authService = authService;
|
|
49
51
|
this.cryptoService = cryptoService;
|
|
@@ -57,23 +59,32 @@ class WebDavServer {
|
|
|
57
59
|
user: credentials.user.bridgeUser,
|
|
58
60
|
pass: credentials.user.userId,
|
|
59
61
|
});
|
|
60
|
-
|
|
62
|
+
const environment = new inxt_js_1.Environment({
|
|
63
|
+
bridgeUser: credentials.user.bridgeUser,
|
|
64
|
+
bridgePass: credentials.user.userId,
|
|
65
|
+
bridgeUrl: config_service_1.ConfigService.instance.get('NETWORK_URL'),
|
|
66
|
+
encryptionKey: credentials.user.mnemonic,
|
|
67
|
+
});
|
|
68
|
+
const networkFacade = new network_facade_service_1.NetworkFacade(networkModule, environment, download_service_1.DownloadService.instance, crypto_service_1.CryptoService.instance);
|
|
69
|
+
return networkFacade;
|
|
61
70
|
};
|
|
62
71
|
registerMiddlewares = async () => {
|
|
63
72
|
this.app.use(body_parser_1.default.text({ type: ['application/xml', 'text/xml'] }));
|
|
64
73
|
this.app.use(errors_middleware_1.ErrorHandlingMiddleware);
|
|
65
|
-
this.app.use((0, auth_middleware_1.AuthMiddleware)(
|
|
74
|
+
this.app.use((0, auth_middleware_1.AuthMiddleware)(auth_service_1.AuthService.instance));
|
|
66
75
|
this.app.use((0, request_logger_middleware_1.RequestLoggerMiddleware)({
|
|
67
76
|
enable: true,
|
|
68
77
|
}));
|
|
69
78
|
};
|
|
70
79
|
registerHandlers = async () => {
|
|
71
80
|
const networkFacade = await this.getNetworkFacade();
|
|
72
|
-
this.app.head('*', (0, express_async_handler_1.default)(new HEAD_handler_1.HEADRequestHandler(
|
|
81
|
+
this.app.head('*', (0, express_async_handler_1.default)(new HEAD_handler_1.HEADRequestHandler({
|
|
82
|
+
driveFileService: this.driveFileService,
|
|
83
|
+
driveDatabaseManager: this.driveDatabaseManager,
|
|
84
|
+
}).handle));
|
|
73
85
|
this.app.get('*', (0, express_async_handler_1.default)(new GET_handler_1.GETRequestHandler({
|
|
74
86
|
driveFileService: this.driveFileService,
|
|
75
87
|
driveDatabaseManager: this.driveDatabaseManager,
|
|
76
|
-
uploadService: this.uploadService,
|
|
77
88
|
downloadService: this.downloadService,
|
|
78
89
|
cryptoService: this.cryptoService,
|
|
79
90
|
authService: this.authService,
|
|
@@ -127,7 +138,8 @@ class WebDavServer {
|
|
|
127
138
|
}
|
|
128
139
|
server.requestTimeout = 15 * 60 * 1000;
|
|
129
140
|
server.listen(configs.port, () => {
|
|
130
|
-
logger_utils_1.webdavLogger.info(`Internxt
|
|
141
|
+
logger_utils_1.webdavLogger.info(`Internxt ${sdk_manager_service_1.SdkManager.getAppDetails().clientVersion} WebDav server ` +
|
|
142
|
+
`listening at ${configs.protocol}://${config_service_1.ConfigService.WEBDAV_LOCAL_URL}:${configs.port}`);
|
|
131
143
|
});
|
|
132
144
|
};
|
|
133
145
|
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Internxt <hello@internxt.com>",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Internxt CLI to manage your encrypted storage",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "yarn clean && tsc",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"migrate:undo": "sequelize db:migrate:undo",
|
|
21
21
|
"publish:npm": "npm run build && npm publish --scope=@internxt --registry=https://registry.npmjs.org/ --access public",
|
|
22
22
|
"publish:github": "npm run build && npm publish --scope=@internxt --registry=https://npm.pkg.github.com",
|
|
23
|
-
"postinstall": "node ./scripts/
|
|
23
|
+
"postinstall": "node ./scripts/restart-webdav.js"
|
|
24
24
|
},
|
|
25
25
|
"homepage": "https://github.com/internxt/cli",
|
|
26
26
|
"license": "MIT",
|
|
@@ -37,13 +37,14 @@
|
|
|
37
37
|
"/oclif.manifest.json"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@inquirer/prompts": "7.2
|
|
41
|
-
"@internxt/inxt-js": "2.0
|
|
40
|
+
"@inquirer/prompts": "7.3.2",
|
|
41
|
+
"@internxt/inxt-js": "2.1.0",
|
|
42
42
|
"@internxt/lib": "1.2.1",
|
|
43
43
|
"@internxt/sdk": "1.7.0",
|
|
44
|
-
"@oclif/core": "4.
|
|
44
|
+
"@oclif/core": "4.2.8",
|
|
45
45
|
"@types/validator": "13.12.2",
|
|
46
|
-
"
|
|
46
|
+
"async": "3.2.6",
|
|
47
|
+
"axios": "1.8.1",
|
|
47
48
|
"bip39": "3.1.0",
|
|
48
49
|
"body-parser": "1.20.3",
|
|
49
50
|
"cli-progress": "3.12.0",
|
|
@@ -52,15 +53,16 @@
|
|
|
52
53
|
"express": "4.21.2",
|
|
53
54
|
"express-async-handler": "1.2.0",
|
|
54
55
|
"express-basic-auth": "1.2.1",
|
|
55
|
-
"fast-xml-parser": "
|
|
56
|
+
"fast-xml-parser": "5.0.8",
|
|
56
57
|
"mime-types": "2.1.35",
|
|
57
|
-
"node-fetch": "2.7.0",
|
|
58
58
|
"openpgp": "5.11.2",
|
|
59
59
|
"pm2": "5.4.3",
|
|
60
|
+
"range-parser": "1.2.1",
|
|
60
61
|
"reflect-metadata": "0.2.2",
|
|
61
62
|
"selfsigned": "2.4.1",
|
|
62
63
|
"sequelize": "6.37.5",
|
|
63
64
|
"sequelize-typescript": "2.1.6",
|
|
65
|
+
"sharp": "0.33.5",
|
|
64
66
|
"sqlite3": "5.1.7",
|
|
65
67
|
"tty-table": "4.2.3",
|
|
66
68
|
"winston": "3.17.0"
|
|
@@ -68,31 +70,32 @@
|
|
|
68
70
|
"devDependencies": {
|
|
69
71
|
"@internxt/eslint-config-internxt": "2.0.0",
|
|
70
72
|
"@internxt/prettier-config": "internxt/prettier-config#v1.0.2",
|
|
71
|
-
"@oclif/test": "4.1.
|
|
72
|
-
"@openpgp/web-stream-tools": "0.0.11-patch-
|
|
73
|
+
"@oclif/test": "4.1.11",
|
|
74
|
+
"@openpgp/web-stream-tools": "0.0.11-patch-1",
|
|
75
|
+
"@types/async": "3.2.24",
|
|
73
76
|
"@types/cli-progress": "3.11.6",
|
|
74
77
|
"@types/express": "5.0.0",
|
|
75
78
|
"@types/mime-types": "2.1.4",
|
|
76
|
-
"@types/node": "22.10.
|
|
77
|
-
"@types/
|
|
78
|
-
"@vitest/coverage-istanbul": "
|
|
79
|
-
"@vitest/spy": "
|
|
80
|
-
"eslint": "9.
|
|
79
|
+
"@types/node": "22.10.7",
|
|
80
|
+
"@types/range-parser": "1.2.7",
|
|
81
|
+
"@vitest/coverage-istanbul": "3.0.7",
|
|
82
|
+
"@vitest/spy": "3.0.7",
|
|
83
|
+
"eslint": "9.21.0",
|
|
81
84
|
"husky": "9.1.7",
|
|
82
|
-
"lint-staged": "15.
|
|
83
|
-
"nock": "
|
|
85
|
+
"lint-staged": "15.4.3",
|
|
86
|
+
"nock": "14.0.1",
|
|
84
87
|
"nodemon": "3.1.9",
|
|
85
|
-
"oclif": "4.
|
|
86
|
-
"prettier": "3.
|
|
88
|
+
"oclif": "4.17.34",
|
|
89
|
+
"prettier": "3.5.3",
|
|
87
90
|
"rimraf": "6.0.1",
|
|
88
91
|
"sequelize-cli": "6.6.2",
|
|
89
92
|
"ts-node": "10.9.2",
|
|
90
|
-
"typescript": "5.
|
|
91
|
-
"vitest": "
|
|
93
|
+
"typescript": "5.8.2",
|
|
94
|
+
"vitest": "3.0.7",
|
|
92
95
|
"vitest-mock-express": "2.2.0"
|
|
93
96
|
},
|
|
94
97
|
"engines": {
|
|
95
|
-
"node": ">=20.
|
|
98
|
+
"node": ">=20.12.1"
|
|
96
99
|
},
|
|
97
100
|
"bin": {
|
|
98
101
|
"internxt": "./bin/run.js"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const { exec } = require('child_process');
|
|
2
|
+
|
|
3
|
+
async function runCommand() {
|
|
4
|
+
await new Promise((resolve, reject) => {
|
|
5
|
+
exec('node ./bin/run.js webdav restart', (error, stdout, stderr) => {
|
|
6
|
+
if (error) {
|
|
7
|
+
reject(error);
|
|
8
|
+
}
|
|
9
|
+
resolve(stdout || stderr);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
runCommand().finally(() => {
|
|
15
|
+
process.exit(0);
|
|
16
|
+
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Readable } from 'node:stream';
|
|
2
|
-
import { UploadOptions } from '../../types/network.types';
|
|
3
|
-
export declare class UploadService {
|
|
4
|
-
static readonly instance: UploadService;
|
|
5
|
-
uploadFile(url: string, from: Readable, options: UploadOptions): Promise<{
|
|
6
|
-
etag: string;
|
|
7
|
-
}>;
|
|
8
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.UploadService = void 0;
|
|
7
|
-
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
8
|
-
class UploadService {
|
|
9
|
-
static instance = new UploadService();
|
|
10
|
-
async uploadFile(url, from, options) {
|
|
11
|
-
const response = await (0, node_fetch_1.default)(url, {
|
|
12
|
-
method: 'PUT',
|
|
13
|
-
body: from,
|
|
14
|
-
signal: options.abortController?.signal,
|
|
15
|
-
});
|
|
16
|
-
const etag = response.headers.get('etag');
|
|
17
|
-
options.progressCallback(1);
|
|
18
|
-
if (!etag) {
|
|
19
|
-
throw new Error('Missing Etag in response when uploading file');
|
|
20
|
-
}
|
|
21
|
-
return { etag };
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
exports.UploadService = UploadService;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Hash } from 'node:crypto';
|
|
2
|
-
import { Transform, TransformCallback, TransformOptions } from 'node:stream';
|
|
3
|
-
export declare class HashStream extends Transform {
|
|
4
|
-
hasher: Hash;
|
|
5
|
-
finalHash: Buffer;
|
|
6
|
-
constructor(opts?: TransformOptions);
|
|
7
|
-
_transform(chunk: Buffer, enc: BufferEncoding, cb: TransformCallback): void;
|
|
8
|
-
_flush(cb: (err: Error | null) => void): Hash;
|
|
9
|
-
reset(): void;
|
|
10
|
-
readHash(): Buffer<ArrayBufferLike>;
|
|
11
|
-
getHash(): Buffer<ArrayBufferLike>;
|
|
12
|
-
}
|