@internxt/cli 1.5.7 → 1.6.0
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 +136 -100
- 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-legacy.d.ts +24 -0
- package/dist/commands/login-legacy.js +175 -0
- package/dist/commands/login.d.ts +3 -9
- package/dist/commands/login.js +18 -133
- 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 +1 -2
- package/dist/commands/trash-folder.js +1 -2
- 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.d.ts +2 -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 +1 -2
- package/dist/hooks/prerun/auth_check.js +2 -2
- package/dist/services/auth.service.d.ts +1 -2
- package/dist/services/auth.service.js +11 -26
- package/dist/services/config.service.d.ts +1 -0
- package/dist/services/config.service.js +3 -0
- package/dist/services/crypto.service.js +1 -1
- package/dist/services/database/drive-file/drive-file.domain.js +1 -0
- package/dist/services/database/drive-folder/drive-folder.domain.js +1 -0
- package/dist/services/drive/drive-file.service.js +1 -0
- package/dist/services/universal-link.service.d.ts +10 -0
- package/dist/services/universal-link.service.js +85 -0
- package/dist/types/command.types.d.ts +1 -2
- package/dist/types/drive.types.d.ts +3 -0
- package/dist/types/webdav.types.d.ts +0 -1
- 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 +17 -0
- package/dist/utils/errors.utils.d.ts +2 -1
- package/dist/utils/errors.utils.js +10 -4
- package/dist/utils/webdav.utils.d.ts +20 -6
- package/dist/utils/webdav.utils.js +52 -33
- package/dist/webdav/handlers/DELETE.handler.js +5 -5
- package/dist/webdav/handlers/GET.handler.js +6 -9
- package/dist/webdav/handlers/HEAD.handler.js +5 -10
- package/dist/webdav/handlers/MKCOL.handler.d.ts +2 -0
- package/dist/webdav/handlers/MKCOL.handler.js +10 -20
- package/dist/webdav/handlers/MOVE.handler.d.ts +2 -0
- package/dist/webdav/handlers/MOVE.handler.js +22 -27
- package/dist/webdav/handlers/OPTIONS.handler.js +3 -3
- package/dist/webdav/handlers/PROPFIND.handler.js +7 -31
- package/dist/webdav/handlers/PUT.handler.d.ts +3 -1
- package/dist/webdav/handlers/PUT.handler.js +20 -23
- 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 +52 -0
- package/dist/webdav/webdav-server.js +8 -0
- package/oclif.manifest.json +68 -3
- package/package.json +23 -22
|
@@ -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
|
@@ -30,7 +30,7 @@ class Whoami extends core_1.Command {
|
|
|
30
30
|
else {
|
|
31
31
|
if (validCreds.refreshRequired) {
|
|
32
32
|
try {
|
|
33
|
-
await auth_service_1.AuthService.instance.refreshUserToken(userCredentials);
|
|
33
|
+
await auth_service_1.AuthService.instance.refreshUserToken(userCredentials.token, userCredentials.user.mnemonic);
|
|
34
34
|
}
|
|
35
35
|
catch {
|
|
36
36
|
}
|
|
@@ -47,7 +47,6 @@ class Whoami extends core_1.Command {
|
|
|
47
47
|
error,
|
|
48
48
|
command: this.id,
|
|
49
49
|
logReporter: this.log.bind(this),
|
|
50
|
-
errorReporter: this.error.bind(this),
|
|
51
50
|
jsonFlag: flags['json'],
|
|
52
51
|
});
|
|
53
52
|
this.exit(1);
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const whoami_1 = __importDefault(require("../../commands/whoami"));
|
|
7
7
|
const login_1 = __importDefault(require("../../commands/login"));
|
|
8
|
+
const login_legacy_1 = __importDefault(require("../../commands/login-legacy"));
|
|
8
9
|
const logout_1 = __importDefault(require("../../commands/logout"));
|
|
9
10
|
const logs_1 = __importDefault(require("../../commands/logs"));
|
|
10
11
|
const cli_utils_1 = require("../../utils/cli.utils");
|
|
@@ -12,7 +13,7 @@ const sdk_manager_service_1 = require("../../services/sdk-manager.service");
|
|
|
12
13
|
const auth_service_1 = require("../../services/auth.service");
|
|
13
14
|
const webdav_1 = __importDefault(require("../../commands/webdav"));
|
|
14
15
|
const webdav_config_1 = __importDefault(require("../../commands/webdav-config"));
|
|
15
|
-
const CommandsToSkip = [whoami_1.default, login_1.default, logout_1.default, logs_1.default, webdav_1.default, webdav_config_1.default];
|
|
16
|
+
const CommandsToSkip = [whoami_1.default, login_1.default, login_legacy_1.default, logout_1.default, logs_1.default, webdav_1.default, webdav_config_1.default];
|
|
16
17
|
const hook = async function (opts) {
|
|
17
18
|
const { Command, argv } = opts;
|
|
18
19
|
const jsonFlag = argv.includes('--json');
|
|
@@ -30,7 +31,6 @@ const hook = async function (opts) {
|
|
|
30
31
|
error: err,
|
|
31
32
|
command: Command.id,
|
|
32
33
|
logReporter: this.log.bind(this),
|
|
33
|
-
errorReporter: this.error.bind(this),
|
|
34
34
|
jsonFlag,
|
|
35
35
|
});
|
|
36
36
|
opts.context.exit(1);
|
|
@@ -4,7 +4,6 @@ export declare class AuthService {
|
|
|
4
4
|
doLogin: (email: string, password: string, twoFactorCode?: string) => Promise<LoginCredentials>;
|
|
5
5
|
is2FANeeded: (email: string) => Promise<boolean>;
|
|
6
6
|
getAuthDetails: () => Promise<LoginCredentials>;
|
|
7
|
-
|
|
8
|
-
refreshUserToken: (oldCreds: LoginCredentials) => Promise<LoginCredentials>;
|
|
7
|
+
refreshUserToken: (oldToken: string, mnemonic: string) => Promise<LoginCredentials>;
|
|
9
8
|
logout: () => Promise<void>;
|
|
10
9
|
}
|
|
@@ -25,8 +25,6 @@ class AuthService {
|
|
|
25
25
|
return {
|
|
26
26
|
user: clearUser,
|
|
27
27
|
token: newToken,
|
|
28
|
-
lastLoggedInAt: new Date().toISOString(),
|
|
29
|
-
lastTokenRefreshAt: new Date().toISOString(),
|
|
30
28
|
};
|
|
31
29
|
};
|
|
32
30
|
is2FANeeded = async (email) => {
|
|
@@ -51,38 +49,25 @@ class AuthService {
|
|
|
51
49
|
}
|
|
52
50
|
const refreshToken = tokenDetails.expiration.refreshRequired;
|
|
53
51
|
if (refreshToken) {
|
|
54
|
-
loginCreds = await this.refreshUserToken(loginCreds);
|
|
52
|
+
loginCreds = await this.refreshUserToken(loginCreds.token, loginCreds.user.mnemonic);
|
|
55
53
|
}
|
|
56
54
|
return loginCreds;
|
|
57
55
|
};
|
|
58
|
-
|
|
59
|
-
sdk_manager_service_1.SdkManager.init({ token:
|
|
56
|
+
refreshUserToken = async (oldToken, mnemonic) => {
|
|
57
|
+
sdk_manager_service_1.SdkManager.init({ token: oldToken });
|
|
58
|
+
const isValidMnemonic = validation_service_1.ValidationService.instance.validateMnemonic(mnemonic);
|
|
59
|
+
if (!isValidMnemonic) {
|
|
60
|
+
throw new command_types_1.InvalidCredentialsError();
|
|
61
|
+
}
|
|
60
62
|
const usersClient = sdk_manager_service_1.SdkManager.instance.getUsers();
|
|
61
|
-
const newCreds = await usersClient.
|
|
62
|
-
|
|
63
|
+
const newCreds = await usersClient.refreshUserCredentials();
|
|
64
|
+
sdk_manager_service_1.SdkManager.init({ token: newCreds.newToken });
|
|
65
|
+
const newLoginCreds = {
|
|
63
66
|
user: {
|
|
64
67
|
...newCreds.user,
|
|
65
|
-
mnemonic:
|
|
66
|
-
createdAt: new Date(newCreds.user.createdAt).toISOString(),
|
|
68
|
+
mnemonic: mnemonic,
|
|
67
69
|
},
|
|
68
70
|
token: newCreds.newToken,
|
|
69
|
-
lastLoggedInAt: oldCreds.lastLoggedInAt,
|
|
70
|
-
lastTokenRefreshAt: new Date().toISOString(),
|
|
71
|
-
};
|
|
72
|
-
sdk_manager_service_1.SdkManager.init({ token: newCreds.newToken });
|
|
73
|
-
await config_service_1.ConfigService.instance.saveUser(loginCreds);
|
|
74
|
-
return loginCreds;
|
|
75
|
-
};
|
|
76
|
-
refreshUserToken = async (oldCreds) => {
|
|
77
|
-
sdk_manager_service_1.SdkManager.init({ token: oldCreds.token });
|
|
78
|
-
const usersClient = sdk_manager_service_1.SdkManager.instance.getUsers();
|
|
79
|
-
const newCreds = await usersClient.refreshUser();
|
|
80
|
-
sdk_manager_service_1.SdkManager.init({ token: newCreds.newToken });
|
|
81
|
-
const newLoginCreds = {
|
|
82
|
-
...oldCreds,
|
|
83
|
-
token: newCreds.newToken,
|
|
84
|
-
lastLoggedInAt: oldCreds.lastLoggedInAt,
|
|
85
|
-
lastTokenRefreshAt: new Date().toISOString(),
|
|
86
71
|
};
|
|
87
72
|
await config_service_1.ConfigService.instance.saveUser(newLoginCreds);
|
|
88
73
|
return newLoginCreds;
|
|
@@ -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
|
};
|
|
@@ -104,7 +104,7 @@ class CryptoService {
|
|
|
104
104
|
};
|
|
105
105
|
getKeyAndIvFrom = (secret, salt) => {
|
|
106
106
|
const TRANSFORM_ROUNDS = 3;
|
|
107
|
-
const password = Buffer.concat([Buffer.from(secret, '
|
|
107
|
+
const password = Buffer.concat([Buffer.from(secret, 'utf8'), salt]);
|
|
108
108
|
const md5Hashes = [];
|
|
109
109
|
let digest = password;
|
|
110
110
|
for (let i = 0; i < TRANSFORM_ROUNDS; i++) {
|
|
@@ -9,6 +9,7 @@ class DriveFileService {
|
|
|
9
9
|
const storageClient = sdk_manager_service_1.SdkManager.instance.getStorage();
|
|
10
10
|
const driveFile = await storageClient.createFileEntryByUuid(payload);
|
|
11
11
|
return {
|
|
12
|
+
itemType: 'file',
|
|
12
13
|
name: payload.plainName,
|
|
13
14
|
id: driveFile.id,
|
|
14
15
|
uuid: driveFile.uuid,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LoginCredentials } from '../types/command.types';
|
|
2
|
+
export declare class UniversalLinkService {
|
|
3
|
+
static readonly instance: UniversalLinkService;
|
|
4
|
+
getUserCredentials: (userSession: {
|
|
5
|
+
mnemonic: string;
|
|
6
|
+
token: string;
|
|
7
|
+
}) => Promise<LoginCredentials>;
|
|
8
|
+
buildLoginUrl: (redirectUri: string) => string;
|
|
9
|
+
loginSSO: (jsonFlag: boolean, reporter: (message: string) => void, hostIp?: string, forcedPort?: number) => Promise<LoginCredentials>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
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.UniversalLinkService = void 0;
|
|
7
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
8
|
+
const open_1 = __importDefault(require("open"));
|
|
9
|
+
const config_service_1 = require("./config.service");
|
|
10
|
+
const auth_service_1 = require("./auth.service");
|
|
11
|
+
const cli_utils_1 = require("../utils/cli.utils");
|
|
12
|
+
class UniversalLinkService {
|
|
13
|
+
static instance = new UniversalLinkService();
|
|
14
|
+
getUserCredentials = async (userSession) => {
|
|
15
|
+
const clearMnemonic = Buffer.from(userSession.mnemonic, 'base64').toString('utf-8');
|
|
16
|
+
const clearToken = Buffer.from(userSession.token, 'base64').toString('utf-8');
|
|
17
|
+
const loginCredentials = await auth_service_1.AuthService.instance.refreshUserToken(clearToken, clearMnemonic);
|
|
18
|
+
return {
|
|
19
|
+
user: {
|
|
20
|
+
...loginCredentials.user,
|
|
21
|
+
mnemonic: clearMnemonic,
|
|
22
|
+
},
|
|
23
|
+
token: clearToken,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
buildLoginUrl = (redirectUri) => {
|
|
27
|
+
const loginURL = `${config_service_1.ConfigService.instance.get('DRIVE_WEB_URL')}/login`;
|
|
28
|
+
const params = new URLSearchParams({
|
|
29
|
+
universalLink: 'true',
|
|
30
|
+
redirectUri: redirectUri,
|
|
31
|
+
});
|
|
32
|
+
return `${loginURL}?${params.toString()}`;
|
|
33
|
+
};
|
|
34
|
+
loginSSO = async (jsonFlag, reporter, hostIp = '127.0.0.1', forcedPort = 0) => {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const server = node_http_1.default.createServer(async (req, res) => {
|
|
37
|
+
if (!req.url)
|
|
38
|
+
return;
|
|
39
|
+
const parsedUrl = new URL(req.url, `http://${req.headers.host}`);
|
|
40
|
+
const driveUrl = config_service_1.ConfigService.instance.get('DRIVE_WEB_URL');
|
|
41
|
+
try {
|
|
42
|
+
const mnemonic = parsedUrl.searchParams.get('mnemonic');
|
|
43
|
+
const token = parsedUrl.searchParams.get('newToken');
|
|
44
|
+
if (!mnemonic || !token) {
|
|
45
|
+
throw new Error('Login has failed, please try again');
|
|
46
|
+
}
|
|
47
|
+
const loginCredentials = await this.getUserCredentials({ mnemonic, token });
|
|
48
|
+
res.writeHead(302, {
|
|
49
|
+
Location: `${driveUrl}/auth-link-ok`,
|
|
50
|
+
});
|
|
51
|
+
res.end();
|
|
52
|
+
resolve(loginCredentials);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
res.writeHead(302, {
|
|
56
|
+
Location: `${driveUrl}/auth-link-error`,
|
|
57
|
+
});
|
|
58
|
+
res.end();
|
|
59
|
+
reject(error);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
server.closeAllConnections();
|
|
63
|
+
server.close();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
server.listen(forcedPort, async () => {
|
|
67
|
+
const { port } = server.address();
|
|
68
|
+
const redirectUri = Buffer.from(`http://${hostIp}:${port}/callback`).toString('base64');
|
|
69
|
+
const loginUrl = this.buildLoginUrl(redirectUri);
|
|
70
|
+
cli_utils_1.CLIUtils.log(reporter, 'Opening browser for login...');
|
|
71
|
+
cli_utils_1.CLIUtils.log(reporter, 'If the browser doesn’t open automatically, visit:');
|
|
72
|
+
const printLoginUrl = jsonFlag ? `{ "loginUrl": "${loginUrl}" }` : loginUrl;
|
|
73
|
+
cli_utils_1.CLIUtils.consoleLog(printLoginUrl);
|
|
74
|
+
try {
|
|
75
|
+
await (0, open_1.default)(loginUrl);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
cli_utils_1.CLIUtils.warning(reporter, 'Could not open browser automatically.');
|
|
79
|
+
}
|
|
80
|
+
cli_utils_1.CLIUtils.log(reporter, 'Waiting for authentication...');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
exports.UniversalLinkService = UniversalLinkService;
|
|
@@ -26,14 +26,13 @@ export interface LoginUserDetails {
|
|
|
26
26
|
export interface LoginCredentials {
|
|
27
27
|
user: LoginUserDetails;
|
|
28
28
|
token: string;
|
|
29
|
-
lastLoggedInAt: string;
|
|
30
|
-
lastTokenRefreshAt: string;
|
|
31
29
|
}
|
|
32
30
|
export interface WebdavConfig {
|
|
33
31
|
host: string;
|
|
34
32
|
port: string;
|
|
35
33
|
protocol: 'http' | 'https';
|
|
36
34
|
timeoutMinutes: number;
|
|
35
|
+
createFullPath: boolean;
|
|
37
36
|
}
|
|
38
37
|
export declare class NotValidEmailError extends Error {
|
|
39
38
|
constructor();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DriveFolderData, FileMeta } from '@internxt/sdk/dist/drive/storage/types';
|
|
2
2
|
export type DriveFileItem = Omit<FileMeta, 'plainName' | 'userId' | 'encryptVersion' | 'size' | 'createdAt' | 'updatedAt' | 'creationTime' | 'modificationTime' | 'type'> & {
|
|
3
|
+
itemType: 'file';
|
|
3
4
|
size: number;
|
|
4
5
|
createdAt: Date;
|
|
5
6
|
updatedAt: Date;
|
|
@@ -8,6 +9,7 @@ export type DriveFileItem = Omit<FileMeta, 'plainName' | 'userId' | 'encryptVers
|
|
|
8
9
|
type?: string | null;
|
|
9
10
|
};
|
|
10
11
|
export type DriveFolderItem = Pick<DriveFolderData, 'name' | 'bucket' | 'id' | 'parentId'> & {
|
|
12
|
+
itemType: 'folder';
|
|
11
13
|
encryptedName: string;
|
|
12
14
|
uuid: string;
|
|
13
15
|
createdAt: Date;
|
|
@@ -15,3 +17,4 @@ export type DriveFolderItem = Pick<DriveFolderData, 'name' | 'bucket' | 'id' | '
|
|
|
15
17
|
status: 'EXISTS' | 'TRASHED';
|
|
16
18
|
parentUuid: string | null;
|
|
17
19
|
};
|
|
20
|
+
export type DriveItem = DriveFileItem | DriveFolderItem;
|
|
@@ -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
|
}
|
|
@@ -4,6 +4,7 @@ exports.DriveUtils = void 0;
|
|
|
4
4
|
class DriveUtils {
|
|
5
5
|
static driveFileMetaToItem(fileMeta) {
|
|
6
6
|
return {
|
|
7
|
+
itemType: 'file',
|
|
7
8
|
uuid: fileMeta.uuid ?? '',
|
|
8
9
|
status: fileMeta.status,
|
|
9
10
|
folderId: fileMeta.folderId,
|
|
@@ -22,6 +23,7 @@ class DriveUtils {
|
|
|
22
23
|
}
|
|
23
24
|
static driveFolderMetaToItem(folderMeta) {
|
|
24
25
|
return {
|
|
26
|
+
itemType: 'folder',
|
|
25
27
|
uuid: folderMeta.uuid,
|
|
26
28
|
id: folderMeta.id,
|
|
27
29
|
bucket: folderMeta.bucket,
|
|
@@ -34,5 +36,20 @@ class DriveUtils {
|
|
|
34
36
|
updatedAt: new Date(folderMeta.updatedAt),
|
|
35
37
|
};
|
|
36
38
|
}
|
|
39
|
+
static createFolderResponseToItem(folderResponse) {
|
|
40
|
+
return {
|
|
41
|
+
itemType: 'folder',
|
|
42
|
+
uuid: folderResponse.uuid,
|
|
43
|
+
id: folderResponse.id,
|
|
44
|
+
bucket: folderResponse.bucket,
|
|
45
|
+
status: folderResponse.deleted || folderResponse.removed ? 'TRASHED' : 'EXISTS',
|
|
46
|
+
name: folderResponse.plainName ?? folderResponse.name,
|
|
47
|
+
encryptedName: folderResponse.name,
|
|
48
|
+
parentId: folderResponse.parentId,
|
|
49
|
+
parentUuid: folderResponse.parentUuid,
|
|
50
|
+
createdAt: new Date(folderResponse.createdAt),
|
|
51
|
+
updatedAt: new Date(folderResponse.updatedAt),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
37
54
|
}
|
|
38
55
|
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
|
}
|
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
import { Request } from 'express';
|
|
2
1
|
import { WebDavRequestedResource } from '../types/webdav.types';
|
|
3
2
|
import { DriveFolderService } from '../services/drive/drive-folder.service';
|
|
4
3
|
import { DriveFileService } from '../services/drive/drive-file.service';
|
|
5
|
-
import { DriveFileItem, DriveFolderItem } from '../types/drive.types';
|
|
4
|
+
import { DriveFileItem, DriveFolderItem, DriveItem } from '../types/drive.types';
|
|
6
5
|
export declare class WebDavUtils {
|
|
7
6
|
static joinURL(...pathComponents: string[]): string;
|
|
8
7
|
static removeHostFromURL(completeURL: string): string;
|
|
9
|
-
static
|
|
8
|
+
static decodeUrl(requestUrl: string, decodeUri?: boolean): string;
|
|
9
|
+
static normalizeFolderPath(path: string): string;
|
|
10
|
+
static getRequestedResource(requestUrl: string, decodeUri?: boolean): Promise<WebDavRequestedResource>;
|
|
11
|
+
static tryGetFileOrFolderMetadata({ url, driveFileService, driveFolderService, }: {
|
|
12
|
+
url: string;
|
|
13
|
+
driveFolderService: DriveFolderService;
|
|
14
|
+
driveFileService: DriveFileService;
|
|
15
|
+
}): Promise<DriveItem | undefined>;
|
|
16
|
+
static getDriveFileFromResource({ url, driveFileService, }: {
|
|
17
|
+
url: string;
|
|
18
|
+
driveFileService: DriveFileService;
|
|
19
|
+
}): Promise<DriveFileItem | undefined>;
|
|
20
|
+
static getDriveFolderFromResource({ url, driveFolderService, }: {
|
|
21
|
+
url: string;
|
|
22
|
+
driveFolderService: DriveFolderService;
|
|
23
|
+
}): Promise<DriveFolderItem | undefined>;
|
|
10
24
|
static getDriveItemFromResource({ resource, driveFolderService, driveFileService, }: {
|
|
11
25
|
resource: WebDavRequestedResource;
|
|
12
|
-
driveFolderService
|
|
13
|
-
driveFileService
|
|
14
|
-
}): Promise<
|
|
26
|
+
driveFolderService: DriveFolderService;
|
|
27
|
+
driveFileService: DriveFileService;
|
|
28
|
+
}): Promise<DriveItem | undefined>;
|
|
15
29
|
}
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.WebDavUtils = void 0;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const logger_utils_1 = require("./logger.utils");
|
|
8
9
|
class WebDavUtils {
|
|
9
10
|
static joinURL(...pathComponents) {
|
|
10
11
|
return node_path_1.default.posix.join(...pathComponents);
|
|
@@ -19,49 +20,67 @@ class WebDavUtils {
|
|
|
19
20
|
url = '/'.concat(url);
|
|
20
21
|
return url;
|
|
21
22
|
}
|
|
22
|
-
static
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
static decodeUrl(requestUrl, decodeUri = true) {
|
|
24
|
+
return (decodeUri ? decodeURIComponent(requestUrl) : requestUrl).replaceAll('/./', '/');
|
|
25
|
+
}
|
|
26
|
+
static normalizeFolderPath(path) {
|
|
27
|
+
let normalizedPath = path;
|
|
28
|
+
if (!normalizedPath.startsWith('/')) {
|
|
29
|
+
normalizedPath = `/${normalizedPath}`;
|
|
26
30
|
}
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
if (!normalizedPath.endsWith('/')) {
|
|
32
|
+
normalizedPath = `${normalizedPath}/`;
|
|
29
33
|
}
|
|
30
|
-
|
|
34
|
+
return normalizedPath;
|
|
35
|
+
}
|
|
36
|
+
static async getRequestedResource(requestUrl, decodeUri = true) {
|
|
37
|
+
const decodedUrl = this.decodeUrl(requestUrl, decodeUri);
|
|
31
38
|
const parsedPath = node_path_1.default.parse(decodedUrl);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
const parentPath = this.normalizeFolderPath(node_path_1.default.dirname(decodedUrl));
|
|
40
|
+
return {
|
|
41
|
+
url: decodedUrl,
|
|
42
|
+
name: parsedPath.base,
|
|
43
|
+
path: parsedPath,
|
|
44
|
+
parentPath,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
static async tryGetFileOrFolderMetadata({ url, driveFileService, driveFolderService, }) {
|
|
48
|
+
try {
|
|
49
|
+
return await driveFileService.getFileMetadataByPath(url);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return await driveFolderService.getFolderMetadataByPath(url);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
static async getDriveFileFromResource({ url, driveFileService, }) {
|
|
56
|
+
try {
|
|
57
|
+
return await driveFileService.getFileMetadataByPath(url);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
logger_utils_1.webdavLogger.error('Exception while getting the file metadata by path', err);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
static async getDriveFolderFromResource({ url, driveFolderService, }) {
|
|
64
|
+
try {
|
|
65
|
+
return await driveFolderService.getFolderMetadataByPath(url);
|
|
46
66
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
type: 'file',
|
|
50
|
-
url: decodedUrl,
|
|
51
|
-
name: parsedPath.name,
|
|
52
|
-
path: parsedPath,
|
|
53
|
-
parentPath,
|
|
54
|
-
};
|
|
67
|
+
catch (err) {
|
|
68
|
+
logger_utils_1.webdavLogger.error('Exception while getting the folder metadata by path', err);
|
|
55
69
|
}
|
|
56
70
|
}
|
|
57
71
|
static async getDriveItemFromResource({ resource, driveFolderService, driveFileService, }) {
|
|
58
72
|
let item = undefined;
|
|
73
|
+
const isFolder = resource.url.endsWith('/');
|
|
59
74
|
try {
|
|
60
|
-
if (
|
|
61
|
-
item = await driveFolderService
|
|
75
|
+
if (isFolder) {
|
|
76
|
+
item = await driveFolderService.getFolderMetadataByPath(resource.url);
|
|
62
77
|
}
|
|
63
|
-
|
|
64
|
-
item = await
|
|
78
|
+
else {
|
|
79
|
+
item = await this.tryGetFileOrFolderMetadata({
|
|
80
|
+
url: resource.url,
|
|
81
|
+
driveFileService,
|
|
82
|
+
driveFolderService,
|
|
83
|
+
});
|
|
65
84
|
}
|
|
66
85
|
}
|
|
67
86
|
catch {
|