@internxt/cli 1.5.8 → 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.
Files changed (38) hide show
  1. package/README.md +124 -94
  2. package/dist/commands/login-legacy.d.ts +24 -0
  3. package/dist/commands/login-legacy.js +175 -0
  4. package/dist/commands/login.d.ts +3 -9
  5. package/dist/commands/login.js +18 -132
  6. package/dist/commands/trash-file.js +1 -1
  7. package/dist/commands/trash-folder.js +1 -1
  8. package/dist/commands/upload-file.d.ts +2 -1
  9. package/dist/commands/whoami.js +1 -1
  10. package/dist/hooks/prerun/auth_check.js +2 -1
  11. package/dist/services/auth.service.d.ts +1 -2
  12. package/dist/services/auth.service.js +11 -26
  13. package/dist/services/crypto.service.js +1 -1
  14. package/dist/services/database/drive-file/drive-file.domain.js +1 -0
  15. package/dist/services/database/drive-folder/drive-folder.domain.js +1 -0
  16. package/dist/services/drive/drive-file.service.js +1 -0
  17. package/dist/services/universal-link.service.d.ts +10 -0
  18. package/dist/services/universal-link.service.js +85 -0
  19. package/dist/types/command.types.d.ts +0 -2
  20. package/dist/types/drive.types.d.ts +2 -0
  21. package/dist/types/webdav.types.d.ts +0 -1
  22. package/dist/utils/drive.utils.js +3 -0
  23. package/dist/utils/logger.utils.js +10 -0
  24. package/dist/utils/webdav.utils.d.ts +12 -10
  25. package/dist/utils/webdav.utils.js +39 -29
  26. package/dist/webdav/handlers/DELETE.handler.js +5 -5
  27. package/dist/webdav/handlers/GET.handler.js +6 -9
  28. package/dist/webdav/handlers/HEAD.handler.js +5 -10
  29. package/dist/webdav/handlers/MKCOL.handler.js +4 -4
  30. package/dist/webdav/handlers/MOVE.handler.js +19 -17
  31. package/dist/webdav/handlers/OPTIONS.handler.js +3 -3
  32. package/dist/webdav/handlers/PROPFIND.handler.js +7 -31
  33. package/dist/webdav/handlers/PUT.handler.d.ts +2 -0
  34. package/dist/webdav/handlers/PUT.handler.js +10 -8
  35. package/dist/webdav/services/webdav-folder.service.js +5 -4
  36. package/dist/webdav/webdav-server.js +1 -0
  37. package/oclif.manifest.json +60 -3
  38. package/package.json +23 -22
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const core_1 = require("@oclif/core");
37
+ const command_types_1 = require("../types/command.types");
38
+ const auth_service_1 = require("../services/auth.service");
39
+ const config_service_1 = require("../services/config.service");
40
+ const validation_service_1 = require("../services/validation.service");
41
+ const cli_utils_1 = require("../utils/cli.utils");
42
+ const sdk_manager_service_1 = require("../services/sdk-manager.service");
43
+ const OTPAuth = __importStar(require("otpauth"));
44
+ class LoginLegacy extends core_1.Command {
45
+ static args = {};
46
+ static description = '[Legacy] Logs into an Internxt account using user and password. ' +
47
+ 'If the account is two-factor protected, then an extra code will be required.';
48
+ static aliases = [];
49
+ static examples = ['<%= config.bin %> <%= command.id %>'];
50
+ static flags = {
51
+ ...cli_utils_1.CLIUtils.CommonFlags,
52
+ email: core_1.Flags.string({
53
+ char: 'e',
54
+ aliases: ['mail'],
55
+ env: 'INXT_USER',
56
+ description: 'The email to log in',
57
+ required: false,
58
+ }),
59
+ password: core_1.Flags.string({
60
+ char: 'p',
61
+ aliases: ['pass'],
62
+ env: 'INXT_PASSWORD',
63
+ description: 'The plain password to log in',
64
+ required: false,
65
+ }),
66
+ twofactor: core_1.Flags.string({
67
+ char: 'w',
68
+ aliases: ['two', 'two-factor'],
69
+ env: 'INXT_TWOFACTORCODE',
70
+ description: 'The two factor auth code (TOTP). ',
71
+ required: false,
72
+ helpValue: '123456',
73
+ }),
74
+ twofactortoken: core_1.Flags.string({
75
+ char: 't',
76
+ aliases: ['otp', 'otp-token'],
77
+ env: 'INXT_OTPTOKEN',
78
+ description: 'The TOTP secret token. It is used to generate a TOTP code if needed.' +
79
+ ' It has prority over the two factor code flag.',
80
+ required: false,
81
+ helpValue: 'token',
82
+ }),
83
+ };
84
+ static enableJsonFlag = true;
85
+ run = async () => {
86
+ const { flags } = await this.parse(LoginLegacy);
87
+ const nonInteractive = flags['non-interactive'];
88
+ const email = await this.getEmail(flags['email'], nonInteractive);
89
+ const password = await this.getPassword(flags['password'], nonInteractive);
90
+ const is2FANeeded = await auth_service_1.AuthService.instance.is2FANeeded(email);
91
+ let twoFactorCode;
92
+ if (is2FANeeded) {
93
+ const twoFactorToken = flags['twofactortoken'];
94
+ if (twoFactorToken && twoFactorToken.trim().length > 0) {
95
+ const totp = new OTPAuth.TOTP({
96
+ secret: twoFactorToken,
97
+ digits: 6,
98
+ });
99
+ twoFactorCode = totp.generate();
100
+ }
101
+ else {
102
+ twoFactorCode = await this.getTwoFactorCode(flags['twofactor'], nonInteractive);
103
+ }
104
+ }
105
+ const loginCredentials = await auth_service_1.AuthService.instance.doLogin(email, password, twoFactorCode);
106
+ sdk_manager_service_1.SdkManager.init({ token: loginCredentials.token });
107
+ await config_service_1.ConfigService.instance.saveUser(loginCredentials);
108
+ const message = `Succesfully logged in to: ${loginCredentials.user.email}`;
109
+ cli_utils_1.CLIUtils.success(this.log.bind(this), message);
110
+ return {
111
+ success: true,
112
+ message,
113
+ login: loginCredentials,
114
+ };
115
+ };
116
+ catch = async (error) => {
117
+ const { flags } = await this.parse(LoginLegacy);
118
+ cli_utils_1.CLIUtils.catchError({
119
+ error,
120
+ command: this.id,
121
+ logReporter: this.log.bind(this),
122
+ jsonFlag: flags['json'],
123
+ });
124
+ this.exit(1);
125
+ };
126
+ getEmail = async (emailFlag, nonInteractive) => {
127
+ const email = await cli_utils_1.CLIUtils.getValueFromFlag({
128
+ value: emailFlag,
129
+ name: LoginLegacy.flags['email'].name,
130
+ }, {
131
+ nonInteractive,
132
+ prompt: {
133
+ message: 'What is your email?',
134
+ options: { type: 'input' },
135
+ },
136
+ }, {
137
+ validate: validation_service_1.ValidationService.instance.validateEmail,
138
+ error: new command_types_1.NotValidEmailError(),
139
+ }, this.log.bind(this));
140
+ return email;
141
+ };
142
+ getPassword = async (passwordFlag, nonInteractive) => {
143
+ const password = await cli_utils_1.CLIUtils.getValueFromFlag({
144
+ value: passwordFlag,
145
+ name: LoginLegacy.flags['password'].name,
146
+ }, {
147
+ nonInteractive,
148
+ prompt: {
149
+ message: 'What is your password?',
150
+ options: { type: 'password' },
151
+ },
152
+ }, {
153
+ validate: validation_service_1.ValidationService.instance.validateStringIsNotEmpty,
154
+ error: new command_types_1.EmptyPasswordError(),
155
+ }, this.log.bind(this));
156
+ return password;
157
+ };
158
+ getTwoFactorCode = async (twoFactorFlag, nonInteractive) => {
159
+ const twoFactor = await cli_utils_1.CLIUtils.getValueFromFlag({
160
+ value: twoFactorFlag,
161
+ name: LoginLegacy.flags['twofactor'].name,
162
+ }, {
163
+ nonInteractive,
164
+ prompt: {
165
+ message: 'What is your two-factor code?',
166
+ options: { type: 'mask' },
167
+ },
168
+ }, {
169
+ validate: validation_service_1.ValidationService.instance.validate2FA,
170
+ error: new command_types_1.NotValidTwoFactorCodeError(),
171
+ }, this.log.bind(this));
172
+ return twoFactor;
173
+ };
174
+ }
175
+ exports.default = LoginLegacy;
@@ -1,15 +1,12 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class Login extends Command {
3
3
  static readonly args: {};
4
- static readonly description = "Logs into an Internxt account. If the account is two-factor protected, then an extra code will be required.";
4
+ static readonly description: string;
5
5
  static readonly aliases: never[];
6
6
  static readonly examples: string[];
7
7
  static readonly flags: {
8
- email: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
- password: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
- twofactor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
- twofactortoken: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
- 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
+ host: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ port: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
10
  };
14
11
  static readonly enableJsonFlag = true;
15
12
  run: () => Promise<{
@@ -18,7 +15,4 @@ export default class Login extends Command {
18
15
  login: import("../types/command.types").LoginCredentials;
19
16
  }>;
20
17
  catch: (error: Error) => Promise<never>;
21
- private getEmail;
22
- private getPassword;
23
- private getTwoFactorCode;
24
18
  }
@@ -1,107 +1,41 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  const core_1 = require("@oclif/core");
37
- const command_types_1 = require("../types/command.types");
38
- const auth_service_1 = require("../services/auth.service");
39
4
  const config_service_1 = require("../services/config.service");
40
- const validation_service_1 = require("../services/validation.service");
41
5
  const cli_utils_1 = require("../utils/cli.utils");
42
6
  const sdk_manager_service_1 = require("../services/sdk-manager.service");
43
- const OTPAuth = __importStar(require("otpauth"));
7
+ const universal_link_service_1 = require("../services/universal-link.service");
44
8
  class Login extends core_1.Command {
45
9
  static args = {};
46
- static description = 'Logs into an Internxt account. If the account is two-factor protected, then an extra code will be required.';
10
+ static description = 'Logs into your Internxt account using the web-based login flow. ' +
11
+ 'A temporary local server is started to securely receive the authentication response.';
47
12
  static aliases = [];
48
13
  static examples = ['<%= config.bin %> <%= command.id %>'];
49
14
  static flags = {
50
- ...cli_utils_1.CLIUtils.CommonFlags,
51
- email: core_1.Flags.string({
52
- char: 'e',
53
- aliases: ['mail'],
54
- env: 'INXT_USER',
55
- description: 'The email to log in',
15
+ host: core_1.Flags.string({
16
+ char: 'h',
17
+ aliases: ['host'],
18
+ env: 'INXT_LOGIN_SERVER_HOST',
19
+ description: 'IP address of the machine where the CLI is running. ' +
20
+ 'If you are opening the login page in a browser on another device, ' +
21
+ 'set this to the IP address of the machine running the CLI. Defaults to 127.0.0.1.',
56
22
  required: false,
57
23
  }),
58
- password: core_1.Flags.string({
24
+ port: core_1.Flags.integer({
59
25
  char: 'p',
60
- aliases: ['pass'],
61
- env: 'INXT_PASSWORD',
62
- description: 'The plain password to log in',
63
- required: false,
64
- }),
65
- twofactor: core_1.Flags.string({
66
- char: 'w',
67
- aliases: ['two', 'two-factor'],
68
- env: 'INXT_TWOFACTORCODE',
69
- description: 'The two factor auth code (TOTP). ',
26
+ aliases: ['port'],
27
+ env: 'INXT_LOGIN_SERVER_PORT',
28
+ description: 'Port used by the temporary local server to handle the login callback. ' +
29
+ 'If not specified, a random available port will be used automatically.',
70
30
  required: false,
71
- helpValue: '123456',
72
- }),
73
- twofactortoken: core_1.Flags.string({
74
- char: 't',
75
- aliases: ['otp', 'otp-token'],
76
- env: 'INXT_OTPTOKEN',
77
- description: 'The TOTP secret token. It is used to generate a TOTP code if needed.' +
78
- ' It has prority over the two factor code flag.',
79
- required: false,
80
- helpValue: 'token',
81
31
  }),
82
32
  };
83
33
  static enableJsonFlag = true;
84
34
  run = async () => {
85
35
  const { flags } = await this.parse(Login);
86
- const nonInteractive = flags['non-interactive'];
87
- const email = await this.getEmail(flags['email'], nonInteractive);
88
- const password = await this.getPassword(flags['password'], nonInteractive);
89
- const is2FANeeded = await auth_service_1.AuthService.instance.is2FANeeded(email);
90
- let twoFactorCode;
91
- if (is2FANeeded) {
92
- const twoFactorToken = flags['twofactortoken'];
93
- if (twoFactorToken && twoFactorToken.trim().length > 0) {
94
- const totp = new OTPAuth.TOTP({
95
- secret: twoFactorToken,
96
- digits: 6,
97
- });
98
- twoFactorCode = totp.generate();
99
- }
100
- else {
101
- twoFactorCode = await this.getTwoFactorCode(flags['twofactor'], nonInteractive);
102
- }
103
- }
104
- const loginCredentials = await auth_service_1.AuthService.instance.doLogin(email, password, twoFactorCode);
36
+ const host = flags['host'];
37
+ const port = flags['port'];
38
+ const loginCredentials = await universal_link_service_1.UniversalLinkService.instance.loginSSO(flags['json'] ?? false, this.log.bind(this), host, port);
105
39
  sdk_manager_service_1.SdkManager.init({ token: loginCredentials.token });
106
40
  await config_service_1.ConfigService.instance.saveUser(loginCredentials);
107
41
  const message = `Succesfully logged in to: ${loginCredentials.user.email}`;
@@ -122,53 +56,5 @@ class Login extends core_1.Command {
122
56
  });
123
57
  this.exit(1);
124
58
  };
125
- getEmail = async (emailFlag, nonInteractive) => {
126
- const email = await cli_utils_1.CLIUtils.getValueFromFlag({
127
- value: emailFlag,
128
- name: Login.flags['email'].name,
129
- }, {
130
- nonInteractive,
131
- prompt: {
132
- message: 'What is your email?',
133
- options: { type: 'input' },
134
- },
135
- }, {
136
- validate: validation_service_1.ValidationService.instance.validateEmail,
137
- error: new command_types_1.NotValidEmailError(),
138
- }, this.log.bind(this));
139
- return email;
140
- };
141
- getPassword = async (passwordFlag, nonInteractive) => {
142
- const password = await cli_utils_1.CLIUtils.getValueFromFlag({
143
- value: passwordFlag,
144
- name: Login.flags['password'].name,
145
- }, {
146
- nonInteractive,
147
- prompt: {
148
- message: 'What is your password?',
149
- options: { type: 'password' },
150
- },
151
- }, {
152
- validate: validation_service_1.ValidationService.instance.validateStringIsNotEmpty,
153
- error: new command_types_1.EmptyPasswordError(),
154
- }, this.log.bind(this));
155
- return password;
156
- };
157
- getTwoFactorCode = async (twoFactorFlag, nonInteractive) => {
158
- const twoFactor = await cli_utils_1.CLIUtils.getValueFromFlag({
159
- value: twoFactorFlag,
160
- name: Login.flags['twofactor'].name,
161
- }, {
162
- nonInteractive,
163
- prompt: {
164
- message: 'What is your two-factor code?',
165
- options: { type: 'mask' },
166
- },
167
- }, {
168
- validate: validation_service_1.ValidationService.instance.validate2FA,
169
- error: new command_types_1.NotValidTwoFactorCodeError(),
170
- }, this.log.bind(this));
171
- return twoFactor;
172
- };
173
59
  }
174
60
  exports.default = Login;
@@ -27,7 +27,7 @@ class TrashFile extends core_1.Command {
27
27
  if (!userCredentials)
28
28
  throw new command_types_1.MissingCredentialsError();
29
29
  const uuid = await this.getFileUuid(flags['id'], nonInteractive);
30
- await trash_service_1.TrashService.instance.trashItems({ items: [{ uuid, type: 'file', id: null }] });
30
+ await trash_service_1.TrashService.instance.trashItems({ items: [{ uuid, type: 'file' }] });
31
31
  const message = 'File trashed successfully.';
32
32
  cli_utils_1.CLIUtils.success(this.log.bind(this), message);
33
33
  return { success: true, message, file: { uuid } };
@@ -27,7 +27,7 @@ class TrashFolder extends core_1.Command {
27
27
  if (!userCredentials)
28
28
  throw new command_types_1.MissingCredentialsError();
29
29
  const uuid = await this.getFolderUuid(flags['id'], nonInteractive);
30
- await trash_service_1.TrashService.instance.trashItems({ items: [{ uuid, type: 'folder', id: null }] });
30
+ await trash_service_1.TrashService.instance.trashItems({ items: [{ uuid, type: 'folder' }] });
31
31
  const message = 'Folder trashed successfully.';
32
32
  cli_utils_1.CLIUtils.success(this.log.bind(this), message);
33
33
  return { success: true, message, folder: { uuid } };
@@ -17,12 +17,13 @@ export default class UploadFile extends Command {
17
17
  plainName: string;
18
18
  name: string;
19
19
  id: number;
20
- bucket: string;
21
20
  uuid: string;
21
+ bucket: string;
22
22
  folderUuid: string;
23
23
  folderId: number;
24
24
  status: "EXISTS" | "TRASHED" | "DELETED";
25
25
  fileId: string;
26
+ itemType: "file";
26
27
  size: number;
27
28
  createdAt: Date;
28
29
  updatedAt: Date;
@@ -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
  }
@@ -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');
@@ -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
- refreshUserDetails: (oldCreds: LoginCredentials) => Promise<LoginCredentials>;
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
- refreshUserDetails = async (oldCreds) => {
59
- sdk_manager_service_1.SdkManager.init({ token: oldCreds.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.getUserData({ userUuid: oldCreds.user.uuid });
62
- const loginCreds = {
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: oldCreds.user.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;
@@ -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, 'binary'), salt]);
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++) {
@@ -58,6 +58,7 @@ class DriveFile {
58
58
  }
59
59
  toItem() {
60
60
  return {
61
+ itemType: 'file',
61
62
  id: this.id,
62
63
  name: this.name,
63
64
  type: this.type,
@@ -40,6 +40,7 @@ class DriveFolder {
40
40
  }
41
41
  toItem() {
42
42
  return {
43
+ itemType: 'folder',
43
44
  id: this.id,
44
45
  name: this.name,
45
46
  uuid: this.uuid,
@@ -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,8 +26,6 @@ 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;