@internxt/cli 1.6.6 → 1.6.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 +36 -231
- package/dist/commands/create-folder.js +2 -6
- package/dist/commands/delete-permanently-file.js +1 -1
- package/dist/commands/delete-permanently-folder.js +1 -1
- package/dist/commands/download-file.js +3 -3
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.js +6 -4
- package/dist/commands/login.d.ts +0 -1
- package/dist/commands/login.js +1 -11
- package/dist/commands/move-file.d.ts +1 -0
- package/dist/commands/move-file.js +1 -1
- package/dist/commands/move-folder.js +1 -1
- package/dist/commands/rename-file.js +1 -1
- package/dist/commands/rename-folder.js +1 -1
- package/dist/commands/trash-file.js +1 -1
- package/dist/commands/trash-folder.js +1 -1
- package/dist/commands/trash-list.d.ts +2 -0
- package/dist/commands/trash-list.js +5 -3
- package/dist/commands/trash-restore-file.d.ts +1 -0
- package/dist/commands/trash-restore-file.js +1 -1
- package/dist/commands/trash-restore-folder.js +1 -1
- package/dist/commands/upload-file.d.ts +1 -0
- package/dist/commands/upload-file.js +22 -13
- package/dist/commands/whoami.js +6 -3
- package/dist/hooks/prerun/auth_check.js +2 -2
- package/dist/services/auth.service.d.ts +3 -3
- package/dist/services/auth.service.js +35 -44
- package/dist/services/crypto.service.d.ts +0 -4
- package/dist/services/crypto.service.js +1 -32
- package/dist/services/database/drive-item/drive-item.model.js +1 -0
- package/dist/services/database/drive-item/drive-item.repository.js +12 -2
- package/dist/services/drive/drive-file.service.d.ts +2 -0
- package/dist/services/drive/drive-file.service.js +48 -18
- package/dist/services/drive/drive-folder.service.d.ts +2 -0
- package/dist/services/drive/drive-folder.service.js +14 -46
- package/dist/services/drive/trash.service.d.ts +2 -0
- package/dist/services/drive/trash.service.js +14 -41
- package/dist/services/network/upload/upload-file.service.js +5 -9
- package/dist/services/network/upload/upload.types.d.ts +2 -1
- package/dist/services/sdk-manager.service.d.ts +0 -2
- package/dist/services/sdk-manager.service.js +0 -7
- package/dist/services/thumbnail.service.d.ts +4 -13
- package/dist/services/thumbnail.service.js +7 -21
- package/dist/services/universal-link.service.d.ts +1 -1
- package/dist/services/universal-link.service.js +2 -2
- package/dist/services/validation.service.d.ts +3 -13
- package/dist/services/validation.service.js +4 -28
- package/dist/types/command.types.d.ts +1 -29
- package/dist/types/command.types.js +1 -15
- package/dist/types/network.types.d.ts +3 -11
- package/dist/types/webdav.types.d.ts +0 -3
- package/dist/utils/cli.utils.js +9 -22
- package/dist/utils/drive.utils.d.ts +1 -0
- package/dist/utils/drive.utils.js +5 -1
- package/dist/utils/format.utils.js +6 -2
- package/dist/utils/logger.utils.js +9 -2
- package/dist/utils/network.utils.js +2 -2
- package/dist/utils/stream.utils.d.ts +2 -2
- package/dist/utils/stream.utils.js +7 -6
- package/dist/utils/thumbnail.utils.d.ts +1 -3
- package/dist/utils/thumbnail.utils.js +3 -13
- package/dist/utils/upload.utils.d.ts +1 -1
- package/dist/utils/upload.utils.js +2 -2
- package/dist/utils/webdav.utils.d.ts +2 -0
- package/dist/utils/webdav.utils.js +16 -0
- package/dist/webdav/handlers/GET.handler.js +4 -2
- package/dist/webdav/handlers/HEAD.handler.js +2 -0
- package/dist/webdav/handlers/MKCOL.handler.js +3 -3
- package/dist/webdav/handlers/PROPFIND.handler.js +8 -4
- package/dist/webdav/handlers/PUT.handler.js +24 -10
- package/dist/webdav/index.js +2 -2
- package/dist/webdav/middewares/auth.middleware.js +2 -1
- package/dist/webdav/middewares/errors.middleware.js +29 -5
- package/dist/webdav/middewares/webdav-auth.middleware.js +1 -0
- package/dist/webdav/webdav-server.js +2 -2
- package/oclif.manifest.json +9 -198
- package/package.json +23 -22
- package/dist/commands/workspaces-list.d.ts +0 -20
- package/dist/commands/workspaces-list.js +0 -68
- package/dist/commands/workspaces-unset.d.ts +0 -23
- package/dist/commands/workspaces-unset.js +0 -46
- package/dist/commands/workspaces-use.d.ts +0 -27
- package/dist/commands/workspaces-use.js +0 -114
- package/dist/services/drive/workspace.service.d.ts +0 -7
- package/dist/services/drive/workspace.service.js +0 -30
|
@@ -67,7 +67,7 @@ class MoveFile extends core_1.Command {
|
|
|
67
67
|
options: { type: 'input' },
|
|
68
68
|
},
|
|
69
69
|
}, {
|
|
70
|
-
validate: validation_service_1.ValidationService.instance.
|
|
70
|
+
validate: validation_service_1.ValidationService.instance.validateUUID,
|
|
71
71
|
error: new command_types_1.NotValidFileUuidError(),
|
|
72
72
|
}, this.log.bind(this));
|
|
73
73
|
return fileUuid;
|
|
@@ -69,7 +69,7 @@ class MoveFolder extends core_1.Command {
|
|
|
69
69
|
options: { type: 'input' },
|
|
70
70
|
},
|
|
71
71
|
}, {
|
|
72
|
-
validate: validation_service_1.ValidationService.instance.
|
|
72
|
+
validate: validation_service_1.ValidationService.instance.validateUUID,
|
|
73
73
|
error: new command_types_1.NotValidFolderUuidError(),
|
|
74
74
|
}, this.log.bind(this));
|
|
75
75
|
return folderUuid;
|
|
@@ -67,7 +67,7 @@ class RenameFile extends core_1.Command {
|
|
|
67
67
|
options: { type: 'input' },
|
|
68
68
|
},
|
|
69
69
|
}, {
|
|
70
|
-
validate: validation_service_1.ValidationService.instance.
|
|
70
|
+
validate: validation_service_1.ValidationService.instance.validateUUID,
|
|
71
71
|
error: new command_types_1.NotValidFileUuidError(),
|
|
72
72
|
}, this.log.bind(this));
|
|
73
73
|
return fileUuid;
|
|
@@ -60,7 +60,7 @@ class RenameFolder extends core_1.Command {
|
|
|
60
60
|
options: { type: 'input' },
|
|
61
61
|
},
|
|
62
62
|
}, {
|
|
63
|
-
validate: validation_service_1.ValidationService.instance.
|
|
63
|
+
validate: validation_service_1.ValidationService.instance.validateUUID,
|
|
64
64
|
error: new command_types_1.NotValidFolderUuidError(),
|
|
65
65
|
}, this.log.bind(this));
|
|
66
66
|
return folderUuid;
|
|
@@ -54,7 +54,7 @@ class TrashFile extends core_1.Command {
|
|
|
54
54
|
options: { type: 'input' },
|
|
55
55
|
},
|
|
56
56
|
}, {
|
|
57
|
-
validate: validation_service_1.ValidationService.instance.
|
|
57
|
+
validate: validation_service_1.ValidationService.instance.validateUUID,
|
|
58
58
|
error: new command_types_1.NotValidFileUuidError(),
|
|
59
59
|
}, this.log.bind(this));
|
|
60
60
|
return fileUuid;
|
|
@@ -54,7 +54,7 @@ class TrashFolder extends core_1.Command {
|
|
|
54
54
|
options: { type: 'input' },
|
|
55
55
|
},
|
|
56
56
|
}, {
|
|
57
|
-
validate: validation_service_1.ValidationService.instance.
|
|
57
|
+
validate: validation_service_1.ValidationService.instance.validateUUID,
|
|
58
58
|
error: new command_types_1.NotValidFolderUuidError(),
|
|
59
59
|
}, this.log.bind(this));
|
|
60
60
|
return folderUuid;
|
|
@@ -33,6 +33,7 @@ export default class TrashList extends Command {
|
|
|
33
33
|
status: "EXISTS" | "TRASHED" | "DELETED";
|
|
34
34
|
removed: boolean;
|
|
35
35
|
deleted: boolean;
|
|
36
|
+
isFavorite?: boolean;
|
|
36
37
|
}[];
|
|
37
38
|
files: {
|
|
38
39
|
id: number;
|
|
@@ -52,6 +53,7 @@ export default class TrashList extends Command {
|
|
|
52
53
|
updatedAt: string;
|
|
53
54
|
plainName: string;
|
|
54
55
|
status: "EXISTS" | "TRASHED" | "DELETED";
|
|
56
|
+
isFavorite?: boolean;
|
|
55
57
|
}[];
|
|
56
58
|
};
|
|
57
59
|
}>;
|
|
@@ -33,7 +33,8 @@ class TrashList extends core_1.Command {
|
|
|
33
33
|
name: folder.plainName,
|
|
34
34
|
id: folder.uuid,
|
|
35
35
|
size: '-',
|
|
36
|
-
|
|
36
|
+
created: format_utils_1.FormatUtils.formatDate(folder.creationTime ?? folder.createdAt),
|
|
37
|
+
modified: format_utils_1.FormatUtils.formatDate(folder.modificationTime ?? folder.updatedAt),
|
|
37
38
|
};
|
|
38
39
|
}),
|
|
39
40
|
...files.map((file) => {
|
|
@@ -42,7 +43,8 @@ class TrashList extends core_1.Command {
|
|
|
42
43
|
name: file.type && file.type.length > 0 ? `${file.plainName}.${file.type}` : file.plainName,
|
|
43
44
|
id: file.uuid,
|
|
44
45
|
size: format_utils_1.FormatUtils.humanFileSize(Number(file.size)),
|
|
45
|
-
|
|
46
|
+
created: format_utils_1.FormatUtils.formatDate(file.creationTime ?? file.createdAt),
|
|
47
|
+
modified: format_utils_1.FormatUtils.formatDate(file.modificationTime ?? file.updatedAt),
|
|
46
48
|
};
|
|
47
49
|
}),
|
|
48
50
|
];
|
|
@@ -52,7 +54,7 @@ class TrashList extends core_1.Command {
|
|
|
52
54
|
{ value: 'id', alias: 'Id' },
|
|
53
55
|
];
|
|
54
56
|
if (flags.extended) {
|
|
55
|
-
headers.push({ value: 'modified', alias: 'Modified' }, { value: 'size', alias: 'Size' });
|
|
57
|
+
headers.push({ value: 'created', alias: 'Created' }, { value: 'modified', alias: 'Modified' }, { value: 'size', alias: 'Size' });
|
|
56
58
|
}
|
|
57
59
|
cli_utils_1.CLIUtils.table(this.log.bind(this), headers, allItems);
|
|
58
60
|
return { success: true, list: { folders, files } };
|
|
@@ -67,7 +67,7 @@ class TrashRestoreFile extends core_1.Command {
|
|
|
67
67
|
options: { type: 'input' },
|
|
68
68
|
},
|
|
69
69
|
}, {
|
|
70
|
-
validate: validation_service_1.ValidationService.instance.
|
|
70
|
+
validate: validation_service_1.ValidationService.instance.validateUUID,
|
|
71
71
|
error: new command_types_1.NotValidFileUuidError(),
|
|
72
72
|
}, this.log.bind(this));
|
|
73
73
|
return fileUuid;
|
|
@@ -69,7 +69,7 @@ class TrashRestoreFolder extends core_1.Command {
|
|
|
69
69
|
options: { type: 'input' },
|
|
70
70
|
},
|
|
71
71
|
}, {
|
|
72
|
-
validate: validation_service_1.ValidationService.instance.
|
|
72
|
+
validate: validation_service_1.ValidationService.instance.validateUUID,
|
|
73
73
|
error: new command_types_1.NotValidFolderUuidError(),
|
|
74
74
|
}, this.log.bind(this));
|
|
75
75
|
return folderUuid;
|
|
@@ -7,6 +7,7 @@ export default class UploadFile extends Command {
|
|
|
7
7
|
static readonly flags: {
|
|
8
8
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
destination: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
overwrite: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
11
|
'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
12
|
debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
13
|
};
|
|
@@ -14,7 +14,6 @@ const command_types_1 = require("../types/command.types");
|
|
|
14
14
|
const validation_service_1 = require("../services/validation.service");
|
|
15
15
|
const types_1 = require("@internxt/sdk/dist/drive/storage/types");
|
|
16
16
|
const thumbnail_service_1 = require("../services/thumbnail.service");
|
|
17
|
-
const auth_service_1 = require("../services/auth.service");
|
|
18
17
|
const upload_utils_1 = require("../utils/upload.utils");
|
|
19
18
|
class UploadFile extends core_1.Command {
|
|
20
19
|
static args = {};
|
|
@@ -34,6 +33,12 @@ class UploadFile extends core_1.Command {
|
|
|
34
33
|
required: false,
|
|
35
34
|
parse: cli_utils_1.CLIUtils.parseEmpty,
|
|
36
35
|
}),
|
|
36
|
+
overwrite: core_1.Flags.boolean({
|
|
37
|
+
char: 'o',
|
|
38
|
+
description: 'Overwrite the file if a file with the same name already exists in the cloud destination folder.',
|
|
39
|
+
required: false,
|
|
40
|
+
default: false,
|
|
41
|
+
}),
|
|
37
42
|
};
|
|
38
43
|
static enableJsonFlag = true;
|
|
39
44
|
run = async () => {
|
|
@@ -54,6 +59,12 @@ class UploadFile extends core_1.Command {
|
|
|
54
59
|
reporter,
|
|
55
60
|
});
|
|
56
61
|
const destinationFolderUuid = await cli_utils_1.CLIUtils.fallbackToRootFolderIdIfEmpty(destinationFolderUuidFromFlag);
|
|
62
|
+
const existingFile = flags['overwrite']
|
|
63
|
+
? await drive_file_service_1.DriveFileService.instance.findExistentFile(destinationFolderUuid, {
|
|
64
|
+
plainName: fileInfo.name,
|
|
65
|
+
type: fileType,
|
|
66
|
+
})
|
|
67
|
+
: undefined;
|
|
57
68
|
const timings = {
|
|
58
69
|
networkUpload: 0,
|
|
59
70
|
driveUpload: 0,
|
|
@@ -69,18 +80,15 @@ class UploadFile extends core_1.Command {
|
|
|
69
80
|
}, flags['json']);
|
|
70
81
|
progressBar?.start(100, 0);
|
|
71
82
|
let fileId;
|
|
72
|
-
let thumbnailStream;
|
|
73
83
|
const fileSize = stats.size ?? 0;
|
|
74
84
|
if (fileSize > 0) {
|
|
75
85
|
const readStream = (0, node_fs_1.createReadStream)(filePath);
|
|
76
|
-
const preparedStreams = upload_utils_1.UploadUtils.prepareUploadStreams(readStream, fileType);
|
|
77
|
-
thumbnailStream = preparedStreams.thumbnailStream;
|
|
78
86
|
const progressCallback = (progress) => {
|
|
79
87
|
progressBar?.update(progress * 100 * 0.99);
|
|
80
88
|
};
|
|
81
89
|
const abortable = new AbortController();
|
|
82
90
|
fileId = await networkFacade.uploadFile({
|
|
83
|
-
from:
|
|
91
|
+
from: readStream,
|
|
84
92
|
size: fileSize,
|
|
85
93
|
bucketId: bucket,
|
|
86
94
|
progressCallback,
|
|
@@ -93,7 +101,7 @@ class UploadFile extends core_1.Command {
|
|
|
93
101
|
}
|
|
94
102
|
timings.networkUpload = networkUploadTimer.stop();
|
|
95
103
|
const driveUploadTimer = cli_utils_1.CLIUtils.timer();
|
|
96
|
-
const
|
|
104
|
+
const filePayload = {
|
|
97
105
|
plainName: fileInfo.name,
|
|
98
106
|
type: fileType,
|
|
99
107
|
size: fileSize,
|
|
@@ -103,11 +111,14 @@ class UploadFile extends core_1.Command {
|
|
|
103
111
|
encryptVersion: types_1.EncryptionVersion.Aes03,
|
|
104
112
|
creationTime: stats.birthtime?.toISOString(),
|
|
105
113
|
modificationTime: stats.mtime?.toISOString(),
|
|
106
|
-
}
|
|
114
|
+
};
|
|
115
|
+
const createdDriveFile = existingFile
|
|
116
|
+
? await drive_file_service_1.DriveFileService.instance.replaceFile(existingFile.uuid, filePayload)
|
|
117
|
+
: await drive_file_service_1.DriveFileService.instance.createFile(filePayload);
|
|
107
118
|
timings.driveUpload = driveUploadTimer.stop();
|
|
108
119
|
const thumbnailTimer = cli_utils_1.CLIUtils.timer();
|
|
109
120
|
await thumbnail_service_1.ThumbnailService.instance.tryUploadThumbnail({
|
|
110
|
-
|
|
121
|
+
input: filePath,
|
|
111
122
|
fileType,
|
|
112
123
|
bucket,
|
|
113
124
|
fileUuid: createdDriveFile.uuid,
|
|
@@ -121,11 +132,9 @@ class UploadFile extends core_1.Command {
|
|
|
121
132
|
if (flags['debug']) {
|
|
122
133
|
cli_utils_1.CLIUtils.log(reporter, timingBreakdown);
|
|
123
134
|
}
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
`${config_service_1.ConfigService.instance.get('DRIVE_WEB_URL')}/file/${createdDriveFile.uuid}` +
|
|
128
|
-
`${workspaceId ? `?workspaceid=${workspaceId}` : ''}`;
|
|
135
|
+
const uploadVerb = existingFile ? 'overwritten' : 'uploaded';
|
|
136
|
+
const message = `File ${uploadVerb} successfully in ${cli_utils_1.CLIUtils.formatDuration(totalTime)}, view it at ` +
|
|
137
|
+
`${config_service_1.ConfigService.instance.get('DRIVE_WEB_URL')}/file/${createdDriveFile.uuid}`;
|
|
129
138
|
cli_utils_1.CLIUtils.success(reporter, message);
|
|
130
139
|
return {
|
|
131
140
|
success: true,
|
package/dist/commands/whoami.js
CHANGED
|
@@ -5,6 +5,7 @@ const cli_utils_1 = require("../utils/cli.utils");
|
|
|
5
5
|
const config_service_1 = require("../services/config.service");
|
|
6
6
|
const validation_service_1 = require("../services/validation.service");
|
|
7
7
|
const auth_service_1 = require("../services/auth.service");
|
|
8
|
+
const lib_1 = require("@internxt/lib");
|
|
8
9
|
class Whoami extends core_1.Command {
|
|
9
10
|
static args = {};
|
|
10
11
|
static description = 'Display the current user logged into the Internxt CLI.';
|
|
@@ -15,6 +16,7 @@ class Whoami extends core_1.Command {
|
|
|
15
16
|
};
|
|
16
17
|
static enableJsonFlag = true;
|
|
17
18
|
run = async () => {
|
|
19
|
+
await this.parse(Whoami);
|
|
18
20
|
const userCredentials = await config_service_1.ConfigService.instance.readUser();
|
|
19
21
|
if (!userCredentials) {
|
|
20
22
|
const message = 'You are not logged in.';
|
|
@@ -59,10 +61,11 @@ class Whoami extends core_1.Command {
|
|
|
59
61
|
if (!(loginCreds?.token && loginCreds?.user?.mnemonic)) {
|
|
60
62
|
return { valid: false, refreshRequired: false };
|
|
61
63
|
}
|
|
62
|
-
const
|
|
64
|
+
const tokenStatus = validation_service_1.ValidationService.instance.validateTokenAndCheckExpiration(loginCreds.token);
|
|
63
65
|
const goodMnemonic = validation_service_1.ValidationService.instance.validateMnemonic(loginCreds.user.mnemonic);
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
+
const isRefreshRequired = tokenStatus === lib_1.TokenStatus.REFRESH_REQUIRED;
|
|
67
|
+
const isTokenValid = tokenStatus === lib_1.TokenStatus.VALID || isRefreshRequired;
|
|
68
|
+
return { valid: isTokenValid && goodMnemonic, refreshRequired: isRefreshRequired };
|
|
66
69
|
};
|
|
67
70
|
}
|
|
68
71
|
exports.default = Whoami;
|
|
@@ -29,8 +29,8 @@ const hook = async function (opts) {
|
|
|
29
29
|
!commandsToSkipIds.includes(Command.id?.toLowerCase())) {
|
|
30
30
|
cli_utils_1.CLIUtils.doing('Checking credentials', jsonFlag);
|
|
31
31
|
try {
|
|
32
|
-
const { token
|
|
33
|
-
sdk_manager_service_1.SdkManager.init({ token
|
|
32
|
+
const { token } = await auth_service_1.AuthService.instance.getAuthDetails();
|
|
33
|
+
sdk_manager_service_1.SdkManager.init({ token });
|
|
34
34
|
cli_utils_1.CLIUtils.done(jsonFlag);
|
|
35
35
|
cli_utils_1.CLIUtils.clearPreviousLine(jsonFlag);
|
|
36
36
|
await database_service_1.DatabaseService.instance.initialize();
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { LoginCredentials
|
|
1
|
+
import { LoginCredentials } from '../types/command.types';
|
|
2
2
|
export declare class AuthService {
|
|
3
3
|
static readonly instance: 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
|
+
private readonly shouldClearUserAfterRefreshError;
|
|
8
|
+
private readonly getHttpStatusFromError;
|
|
7
9
|
refreshUserToken: (oldToken: string, mnemonic: string, privateKey: string) => Promise<LoginCredentials>;
|
|
8
|
-
refreshWorkspaceCredentials: (loginCreds: LoginCredentials) => Promise<Workspace | undefined>;
|
|
9
|
-
getCurrentWorkspace: () => Promise<Workspace | undefined>;
|
|
10
10
|
getCurrentRootFolder: () => Promise<string>;
|
|
11
11
|
logout: () => Promise<void>;
|
|
12
12
|
}
|
|
@@ -7,7 +7,7 @@ const crypto_service_1 = require("./crypto.service");
|
|
|
7
7
|
const config_service_1 = require("./config.service");
|
|
8
8
|
const command_types_1 = require("../types/command.types");
|
|
9
9
|
const validation_service_1 = require("./validation.service");
|
|
10
|
-
const
|
|
10
|
+
const lib_1 = require("@internxt/lib");
|
|
11
11
|
class AuthService {
|
|
12
12
|
static instance = new AuthService();
|
|
13
13
|
doLogin = async (email, password, twoFactorCode) => {
|
|
@@ -46,36 +46,58 @@ class AuthService {
|
|
|
46
46
|
if (!loginCreds?.token || !loginCreds?.user?.mnemonic) {
|
|
47
47
|
throw new command_types_1.MissingCredentialsError();
|
|
48
48
|
}
|
|
49
|
-
const
|
|
49
|
+
const tokenStatus = validation_service_1.ValidationService.instance.validateTokenAndCheckExpiration(loginCreds.token);
|
|
50
50
|
const isValidMnemonic = validation_service_1.ValidationService.instance.validateMnemonic(loginCreds.user.mnemonic);
|
|
51
|
-
if (
|
|
51
|
+
if (tokenStatus === lib_1.TokenStatus.INVALID || !isValidMnemonic) {
|
|
52
52
|
throw new command_types_1.InvalidCredentialsError();
|
|
53
53
|
}
|
|
54
|
-
if (
|
|
54
|
+
if (tokenStatus === lib_1.TokenStatus.EXPIRED) {
|
|
55
55
|
throw new command_types_1.ExpiredCredentialsError();
|
|
56
56
|
}
|
|
57
57
|
let credentialsChanged = false;
|
|
58
|
-
if (
|
|
58
|
+
if (tokenStatus === lib_1.TokenStatus.REFRESH_REQUIRED) {
|
|
59
59
|
try {
|
|
60
60
|
loginCreds = await this.refreshUserToken(loginCreds.token, loginCreds.user.mnemonic, loginCreds.user.keys.ecc.privateKey);
|
|
61
61
|
credentialsChanged = true;
|
|
62
62
|
}
|
|
63
63
|
catch (error) {
|
|
64
|
-
|
|
64
|
+
if (this.shouldClearUserAfterRefreshError(error)) {
|
|
65
|
+
await config_service_1.ConfigService.instance.clearUser();
|
|
66
|
+
}
|
|
65
67
|
throw error;
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
if (workspaceCreds !== loginCreds.workspace) {
|
|
70
|
-
credentialsChanged = true;
|
|
71
|
-
}
|
|
72
|
-
loginCreds.workspace = workspaceCreds;
|
|
73
|
-
sdk_manager_service_1.SdkManager.init({ token: loginCreds.token, workspaceToken: workspaceCreds?.workspaceCredentials.token });
|
|
70
|
+
sdk_manager_service_1.SdkManager.init({ token: loginCreds.token });
|
|
74
71
|
if (credentialsChanged) {
|
|
75
72
|
await config_service_1.ConfigService.instance.saveUser(loginCreds);
|
|
76
73
|
}
|
|
77
74
|
return loginCreds;
|
|
78
75
|
};
|
|
76
|
+
shouldClearUserAfterRefreshError = (error) => {
|
|
77
|
+
if (error instanceof command_types_1.InvalidCredentialsError || error instanceof command_types_1.ExpiredCredentialsError) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
const status = this.getHttpStatusFromError(error);
|
|
81
|
+
if (status === undefined) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
return status >= 400 && status < 500 && status !== 408 && status !== 429;
|
|
85
|
+
};
|
|
86
|
+
getHttpStatusFromError = (error) => {
|
|
87
|
+
if (typeof error !== 'object' || error === null) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
const response = 'response' in error ? error.response : undefined;
|
|
91
|
+
if (typeof response?.status === 'number') {
|
|
92
|
+
return response.status;
|
|
93
|
+
}
|
|
94
|
+
const status = 'status' in error ? error.status : undefined;
|
|
95
|
+
if (typeof status === 'number') {
|
|
96
|
+
return status;
|
|
97
|
+
}
|
|
98
|
+
const statusCode = 'statusCode' in error ? error.statusCode : undefined;
|
|
99
|
+
return typeof statusCode === 'number' ? statusCode : undefined;
|
|
100
|
+
};
|
|
79
101
|
refreshUserToken = async (oldToken, mnemonic, privateKey) => {
|
|
80
102
|
sdk_manager_service_1.SdkManager.init({ token: oldToken });
|
|
81
103
|
const isValidMnemonic = validation_service_1.ValidationService.instance.validateMnemonic(mnemonic);
|
|
@@ -104,43 +126,12 @@ class AuthService {
|
|
|
104
126
|
};
|
|
105
127
|
return newLoginCreds;
|
|
106
128
|
};
|
|
107
|
-
refreshWorkspaceCredentials = async (loginCreds) => {
|
|
108
|
-
if (loginCreds.workspace?.workspaceCredentials && loginCreds.workspace?.workspaceData) {
|
|
109
|
-
const workspaceToken = loginCreds.workspace.workspaceCredentials.token;
|
|
110
|
-
const workspaceUuid = loginCreds.workspace.workspaceCredentials.id;
|
|
111
|
-
const workspaceTokenDetails = validation_service_1.ValidationService.instance.validateTokenAndCheckExpiration(workspaceToken);
|
|
112
|
-
if (!workspaceTokenDetails.isValid) {
|
|
113
|
-
throw new command_types_1.InvalidCredentialsError();
|
|
114
|
-
}
|
|
115
|
-
if (workspaceTokenDetails.expiration.expired) {
|
|
116
|
-
throw new command_types_1.ExpiredCredentialsError();
|
|
117
|
-
}
|
|
118
|
-
if (workspaceTokenDetails.expiration.refreshRequired) {
|
|
119
|
-
sdk_manager_service_1.SdkManager.init({ token: loginCreds.token, workspaceToken: loginCreds.workspace.workspaceCredentials.token });
|
|
120
|
-
const workspaceCredentials = await workspace_service_1.WorkspaceService.instance.getWorkspaceCredentials(workspaceUuid);
|
|
121
|
-
return {
|
|
122
|
-
workspaceCredentials,
|
|
123
|
-
workspaceData: loginCreds.workspace.workspaceData,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
return loginCreds.workspace;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
getCurrentWorkspace = async () => {
|
|
132
|
-
const loginCreds = await config_service_1.ConfigService.instance.readUser();
|
|
133
|
-
if (!loginCreds?.token || !loginCreds?.user?.mnemonic) {
|
|
134
|
-
throw new command_types_1.MissingCredentialsError();
|
|
135
|
-
}
|
|
136
|
-
return loginCreds.workspace;
|
|
137
|
-
};
|
|
138
129
|
getCurrentRootFolder = async () => {
|
|
139
130
|
const loginCreds = await config_service_1.ConfigService.instance.readUser();
|
|
140
131
|
if (!loginCreds?.token || !loginCreds?.user?.mnemonic) {
|
|
141
132
|
throw new command_types_1.MissingCredentialsError();
|
|
142
133
|
}
|
|
143
|
-
return loginCreds.
|
|
134
|
+
return loginCreds.user.rootFolderId;
|
|
144
135
|
};
|
|
145
136
|
logout = async () => {
|
|
146
137
|
cache_service_1.CacheService.instance.clearCaches();
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { CryptoProvider } from '@internxt/sdk';
|
|
2
|
-
import { LoginCredentials } from '../types/command.types';
|
|
3
|
-
import { WorkspaceData } from '@internxt/sdk/dist/workspaces';
|
|
4
2
|
export declare class CryptoService {
|
|
5
3
|
static readonly instance: CryptoService;
|
|
6
4
|
static readonly cryptoProvider: CryptoProvider;
|
|
@@ -17,7 +15,5 @@ export declare class CryptoService {
|
|
|
17
15
|
decryptTextWithKey: (encryptedText: string, secret: string) => string;
|
|
18
16
|
decryptStream: (inputSlices: ReadableStream<Uint8Array>[], key: Buffer, iv: Buffer, startOffsetByte?: number) => ReadableStream<any>;
|
|
19
17
|
private readonly getKeyAndIvFrom;
|
|
20
|
-
private readonly decryptWorkspaceMnemonic;
|
|
21
|
-
decryptWorkspacesMnemonic: (workspaces: WorkspaceData[], user: LoginCredentials["user"]) => Promise<WorkspaceData[]>;
|
|
22
18
|
decryptPrivateKey: (privateKey: string, password: string) => string;
|
|
23
19
|
}
|
|
@@ -15,11 +15,8 @@ class CryptoService {
|
|
|
15
15
|
return CryptoService.instance.encryptText(hashObj.hash);
|
|
16
16
|
},
|
|
17
17
|
async generateKeys(password) {
|
|
18
|
-
const { privateKeyArmoredEncrypted, publicKeyArmored
|
|
18
|
+
const { privateKeyArmoredEncrypted, publicKeyArmored } = await keys_service_1.KeysService.instance.generateNewKeysWithEncrypted(password);
|
|
19
19
|
const keys = {
|
|
20
|
-
privateKeyEncrypted: privateKeyArmoredEncrypted,
|
|
21
|
-
publicKey: publicKeyArmored,
|
|
22
|
-
revocationCertificate: revocationCertificate,
|
|
23
20
|
ecc: {
|
|
24
21
|
privateKeyEncrypted: privateKeyArmoredEncrypted,
|
|
25
22
|
publicKey: publicKeyArmored,
|
|
@@ -116,34 +113,6 @@ class CryptoService {
|
|
|
116
113
|
const iv = md5Hashes[2];
|
|
117
114
|
return { key, iv };
|
|
118
115
|
};
|
|
119
|
-
decryptWorkspaceMnemonic = async (encryptionKey, user) => {
|
|
120
|
-
const privateKeyInBase64 = user.keys?.ecc?.privateKey;
|
|
121
|
-
const privateKyberKeyInBase64 = user.keys?.kyber?.privateKey;
|
|
122
|
-
if (!privateKeyInBase64) {
|
|
123
|
-
throw new Error('Missing privateKey in user keys');
|
|
124
|
-
}
|
|
125
|
-
try {
|
|
126
|
-
return await keys_service_1.KeysService.instance.hybridDecryptMessageWithPrivateKey({
|
|
127
|
-
encryptedMessageInBase64: encryptionKey,
|
|
128
|
-
privateKeyInBase64,
|
|
129
|
-
privateKyberKeyInBase64,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
catch {
|
|
133
|
-
throw new Error('Failed to decrypt workspace mnemonic');
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
decryptWorkspacesMnemonic = async (workspaces, user) => {
|
|
137
|
-
return await Promise.all(workspaces.map(async (workspace) => {
|
|
138
|
-
return {
|
|
139
|
-
...workspace,
|
|
140
|
-
workspaceUser: {
|
|
141
|
-
...workspace.workspaceUser,
|
|
142
|
-
key: await this.decryptWorkspaceMnemonic(workspace.workspaceUser.key, user),
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
}));
|
|
146
|
-
};
|
|
147
116
|
decryptPrivateKey = (privateKey, password) => {
|
|
148
117
|
const MINIMAL_ENCRYPTED_KEY_LEN = 129;
|
|
149
118
|
if (!privateKey || privateKey.length <= MINIMAL_ENCRYPTED_KEY_LEN)
|
|
@@ -19,6 +19,7 @@ __decorate([
|
|
|
19
19
|
__metadata("design:type", String)
|
|
20
20
|
], DriveItemModel.prototype, "uuid", void 0);
|
|
21
21
|
__decorate([
|
|
22
|
+
(0, typeorm_1.Index)(),
|
|
22
23
|
(0, typeorm_1.Column)({ nullable: false, type: 'varchar' }),
|
|
23
24
|
__metadata("design:type", String)
|
|
24
25
|
], DriveItemModel.prototype, "path", void 0);
|
|
@@ -19,15 +19,25 @@ class DriveItemRepository {
|
|
|
19
19
|
.getMany();
|
|
20
20
|
const existingByUuid = new Map(existing.map((e) => [e.uuid, e]));
|
|
21
21
|
const existingByPath = new Map(existing.map((e) => [e.path, e]));
|
|
22
|
+
const itemsToInsert = [];
|
|
23
|
+
const itemsToUpdate = [];
|
|
22
24
|
for (const item of items) {
|
|
23
25
|
const match = existingByUuid.get(item.uuid) ?? existingByPath.get(item.path);
|
|
24
26
|
if (match) {
|
|
25
|
-
|
|
27
|
+
itemsToUpdate.push({ targetUuid: match.uuid, item });
|
|
26
28
|
}
|
|
27
29
|
else {
|
|
28
|
-
|
|
30
|
+
itemsToInsert.push(item);
|
|
29
31
|
}
|
|
30
32
|
}
|
|
33
|
+
await this.repository.manager.transaction(async (transactionalEntityManager) => {
|
|
34
|
+
if (itemsToInsert.length > 0) {
|
|
35
|
+
await transactionalEntityManager.insert(drive_item_model_1.DriveItemModel, itemsToInsert);
|
|
36
|
+
}
|
|
37
|
+
for (const { targetUuid, item } of itemsToUpdate) {
|
|
38
|
+
await transactionalEntityManager.update(drive_item_model_1.DriveItemModel, targetUuid, item);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
31
41
|
return items.map((item) => new drive_item_domain_1.DriveItemBD(item));
|
|
32
42
|
}
|
|
33
43
|
catch (error) {
|
|
@@ -3,6 +3,8 @@ import { DriveFileItem } from '../../types/drive.types';
|
|
|
3
3
|
export declare class DriveFileService {
|
|
4
4
|
static readonly instance: DriveFileService;
|
|
5
5
|
createFile: (payload: StorageTypes.FileEntryByUuid) => Promise<DriveFileItem>;
|
|
6
|
+
replaceFile: (uuid: string, payload: StorageTypes.FileEntryByUuid) => Promise<DriveFileItem>;
|
|
7
|
+
findExistentFile: (folderUuid: string, file: StorageTypes.FileStructure) => Promise<DriveFileItem | undefined>;
|
|
6
8
|
private readonly createDriveFileEntry;
|
|
7
9
|
getFileMetadata: (uuid: string) => Promise<DriveFileItem>;
|
|
8
10
|
getFileMetadataByPath: (path: string) => Promise<DriveFileItem>;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DriveFileService = void 0;
|
|
4
|
-
const drive_1 = require("@internxt/sdk/dist/drive");
|
|
5
4
|
const sdk_manager_service_1 = require("../sdk-manager.service");
|
|
6
5
|
const drive_utils_1 = require("../../utils/drive.utils");
|
|
7
|
-
const auth_service_1 = require("../auth.service");
|
|
8
6
|
const errors_utils_1 = require("../../utils/errors.utils");
|
|
9
7
|
const types_1 = require("@internxt/sdk/dist/drive/storage/types");
|
|
10
8
|
class DriveFileService {
|
|
@@ -28,23 +26,55 @@ class DriveFileService {
|
|
|
28
26
|
};
|
|
29
27
|
return driveFileItem;
|
|
30
28
|
};
|
|
29
|
+
replaceFile = async (uuid, payload) => {
|
|
30
|
+
const storageClient = sdk_manager_service_1.SdkManager.instance.getStorage();
|
|
31
|
+
const driveFile = await storageClient.replaceFile(uuid, {
|
|
32
|
+
fileId: payload.fileId ?? '',
|
|
33
|
+
size: payload.size,
|
|
34
|
+
});
|
|
35
|
+
const driveFileItem = {
|
|
36
|
+
itemType: 'file',
|
|
37
|
+
name: driveFile.plainName ?? driveFile.name,
|
|
38
|
+
uuid: driveFile.uuid,
|
|
39
|
+
size: driveFile.size,
|
|
40
|
+
bucket: driveFile.bucket,
|
|
41
|
+
createdAt: new Date(driveFile.createdAt),
|
|
42
|
+
updatedAt: new Date(driveFile.updatedAt),
|
|
43
|
+
fileId: driveFile.fileId ?? null,
|
|
44
|
+
type: driveFile.type ?? null,
|
|
45
|
+
status: driveFile.status,
|
|
46
|
+
folderUuid: driveFile.folderUuid,
|
|
47
|
+
creationTime: new Date(driveFile.creationTime ?? driveFile.createdAt),
|
|
48
|
+
modificationTime: new Date(driveFile.modificationTime ?? driveFile.updatedAt),
|
|
49
|
+
};
|
|
50
|
+
return driveFileItem;
|
|
51
|
+
};
|
|
52
|
+
findExistentFile = async (folderUuid, file) => {
|
|
53
|
+
const storageClient = sdk_manager_service_1.SdkManager.instance.getStorage();
|
|
54
|
+
const { existentFiles } = await storageClient.checkDuplicatedFiles({
|
|
55
|
+
folderUuid,
|
|
56
|
+
filesList: [file],
|
|
57
|
+
});
|
|
58
|
+
const existentFile = existentFiles[0];
|
|
59
|
+
if (!existentFile)
|
|
60
|
+
return undefined;
|
|
61
|
+
return {
|
|
62
|
+
itemType: 'file',
|
|
63
|
+
name: existentFile.plainName ?? existentFile.name,
|
|
64
|
+
uuid: existentFile.uuid,
|
|
65
|
+
size: existentFile.size,
|
|
66
|
+
bucket: existentFile.bucket,
|
|
67
|
+
createdAt: new Date(existentFile.createdAt),
|
|
68
|
+
updatedAt: new Date(existentFile.updatedAt),
|
|
69
|
+
fileId: existentFile.fileId ?? null,
|
|
70
|
+
type: existentFile.type ?? null,
|
|
71
|
+
status: existentFile.status,
|
|
72
|
+
folderUuid: existentFile.folderUuid,
|
|
73
|
+
creationTime: new Date(existentFile.creationTime ?? existentFile.createdAt),
|
|
74
|
+
modificationTime: new Date(existentFile.modificationTime ?? existentFile.updatedAt),
|
|
75
|
+
};
|
|
76
|
+
};
|
|
31
77
|
createDriveFileEntry = async (payload) => {
|
|
32
|
-
const currentWorkspace = await auth_service_1.AuthService.instance.getCurrentWorkspace();
|
|
33
|
-
if (currentWorkspace) {
|
|
34
|
-
const workspaceClient = sdk_manager_service_1.SdkManager.instance.getWorkspaces();
|
|
35
|
-
return workspaceClient.createFileEntry({
|
|
36
|
-
name: payload.plainName,
|
|
37
|
-
plainName: payload.plainName,
|
|
38
|
-
bucket: payload.bucket,
|
|
39
|
-
fileId: payload.fileId ?? '',
|
|
40
|
-
encryptVersion: drive_1.StorageTypes.EncryptionVersion.Aes03,
|
|
41
|
-
folderUuid: payload.folderUuid,
|
|
42
|
-
size: payload.size,
|
|
43
|
-
type: payload.type ?? '',
|
|
44
|
-
modificationTime: payload.modificationTime ?? new Date().toISOString(),
|
|
45
|
-
date: payload.date ?? new Date().toISOString(),
|
|
46
|
-
}, currentWorkspace.workspaceCredentials.id);
|
|
47
|
-
}
|
|
48
78
|
const storageClient = sdk_manager_service_1.SdkManager.instance.getStorage();
|
|
49
79
|
return storageClient.createFileEntryByUuid(payload);
|
|
50
80
|
};
|
|
@@ -28,6 +28,7 @@ export declare class DriveFolderService {
|
|
|
28
28
|
status: "EXISTS" | "TRASHED" | "DELETED";
|
|
29
29
|
removed: boolean;
|
|
30
30
|
deleted: boolean;
|
|
31
|
+
isFavorite?: boolean;
|
|
31
32
|
}[];
|
|
32
33
|
files: {
|
|
33
34
|
id: number;
|
|
@@ -47,6 +48,7 @@ export declare class DriveFolderService {
|
|
|
47
48
|
updatedAt: string;
|
|
48
49
|
plainName: string;
|
|
49
50
|
status: "EXISTS" | "TRASHED" | "DELETED";
|
|
51
|
+
isFavorite?: boolean;
|
|
50
52
|
}[];
|
|
51
53
|
}>;
|
|
52
54
|
getFolderSubfolders: (folderUuid: string) => Promise<FetchPaginatedFolder[]>;
|