login.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.LoginCommand = void 0;
  4. const tslib_1 = require("tslib");
  5. const cli_framework_1 = require("@ionic/cli-framework");
  6. const chalk_1 = tslib_1.__importDefault(require("chalk"));
  7. const readline = tslib_1.__importStar(require("readline"));
  8. const color_1 = require("../lib/color");
  9. const command_1 = require("../lib/command");
  10. const errors_1 = require("../lib/errors");
  11. const uuid_1 = require("../lib/utils/uuid");
  12. class LoginCommand extends command_1.Command {
  13. async getMetadata() {
  14. return {
  15. name: 'login',
  16. type: 'global',
  17. summary: 'Log in to Ionic',
  18. description: `
  19. Authenticate with Ionic and retrieve a user token, which is stored in the CLI config. Running ${(0, color_1.input)('ionic login')} will open a browser where you can submit your credentials.
  20. If the ${(0, color_1.input)('IONIC_TOKEN')} environment variable is set, the CLI will automatically authenticate you. Use the Dashboard to generate a Personal Access Token.
  21. If you need to create an Ionic account, use ${(0, color_1.input)('ionic signup')} or the Ionic Website[^signup].
  22. If you are having issues logging in, please get in touch with our Support[^support-request].
  23. `,
  24. footnotes: [
  25. {
  26. id: 'signup',
  27. url: 'https://ionicframework.com/signup',
  28. },
  29. {
  30. id: 'support-request',
  31. url: 'https://ion.link/support-request',
  32. },
  33. ],
  34. exampleCommands: [''],
  35. inputs: [
  36. {
  37. name: 'email',
  38. summary: 'Your email address (deprecated)',
  39. private: true,
  40. },
  41. {
  42. name: 'password',
  43. summary: 'Your password (deprecated)',
  44. private: true,
  45. },
  46. ],
  47. };
  48. }
  49. async preRun(inputs, options) {
  50. if (options['email'] || options['password']) {
  51. throw new errors_1.FatalException(`${(0, color_1.input)('email')} and ${(0, color_1.input)('password')} are command arguments, not options. Please try this:\n` +
  52. `${(0, color_1.input)('ionic login <email> <password>')}\n`);
  53. }
  54. if (options['sso']) {
  55. this.env.log.warn(`The ${(0, color_1.strong)('--sso')} flag is no longer necessary.\n` +
  56. `SSO login has been upgraded to OpenID login, which is now the new default authentication flow of ${(0, color_1.input)('ionic login')}. Refresh tokens are used to automatically re-authenticate sessions.`);
  57. this.env.log.nl();
  58. }
  59. if (!!inputs[0]) {
  60. this.env.log.warn('Authenticating using email and password is deprecated. ' +
  61. (this.env.flags.interactive
  62. ? `Please run ${(0, color_1.input)('ionic login')} without arguments to log in.`
  63. : `Please generate a Personal Access Token and set the ${(0, color_1.input)('IONIC_TOKEN')} environment variable.`));
  64. this.env.log.nl();
  65. }
  66. // ask for password only if the user specifies an email
  67. const validateEmail = !!inputs[0];
  68. const askForPassword = inputs[0] && !inputs[1];
  69. if (this.env.session.isLoggedIn()) {
  70. const email = this.env.config.get('user.email');
  71. const extra = askForPassword
  72. ? (this.env.flags.interactive ? `Prompting for new credentials.\n\nUse ${chalk_1.default.yellow('Ctrl+C')} to cancel and remain logged in.` : '')
  73. : 'You will be logged out beforehand.';
  74. if (this.env.flags.interactive) {
  75. this.env.log.warn('You will be logged out.\n' +
  76. `You are already logged in${email ? ' as ' + (0, color_1.strong)(email) : ''}! ${extra}`);
  77. this.env.log.nl();
  78. }
  79. }
  80. else {
  81. if (this.env.flags.interactive) {
  82. this.env.log.info(`Log into your Ionic account!\n` +
  83. `If you don't have one yet, create yours by running: ${(0, color_1.input)(`ionic signup`)}`);
  84. this.env.log.nl();
  85. }
  86. }
  87. // TODO: combine with promptToLogin ?
  88. if (validateEmail) {
  89. const validatedEmail = cli_framework_1.validators.email(inputs[0]);
  90. if (validatedEmail !== true) {
  91. this.env.log.warn(`${validatedEmail}. \n Please enter a valid email address.`);
  92. if (this.env.flags.interactive) {
  93. const email = await this.env.prompt({
  94. type: 'input',
  95. name: 'email',
  96. message: 'Email:',
  97. validate: v => (0, cli_framework_1.combine)(cli_framework_1.validators.required, cli_framework_1.validators.email)(v),
  98. });
  99. inputs[0] = email;
  100. }
  101. else {
  102. throw new errors_1.FatalException('Invalid email');
  103. }
  104. }
  105. }
  106. if (askForPassword) {
  107. if (this.env.flags.interactive) {
  108. const password = await this.env.prompt({
  109. type: 'password',
  110. name: 'password',
  111. message: 'Password:',
  112. mask: '*',
  113. validate: v => cli_framework_1.validators.required(v),
  114. });
  115. inputs[1] = password;
  116. }
  117. else {
  118. inputs[1] = await this.getPasswordFromStdin();
  119. }
  120. }
  121. }
  122. getPasswordFromStdin() {
  123. return new Promise(resolve => {
  124. const rl = readline.createInterface({
  125. input: process.stdin,
  126. terminal: false,
  127. });
  128. rl.on('line', line => {
  129. resolve(line);
  130. rl.close();
  131. });
  132. });
  133. }
  134. async run(inputs, options) {
  135. const [email, password] = inputs;
  136. if (email && password) {
  137. await this.logout();
  138. await this.env.session.login(email, password);
  139. }
  140. else {
  141. if (!this.env.flags.interactive && !this.env.flags.confirm) {
  142. throw new errors_1.FatalException('Refusing to attempt browser login in non-interactive mode.\n' +
  143. `If you are attempting to log in, make sure you are using a modern, interactive terminal. Otherwise, you can log in using inline username and password with ${(0, color_1.input)('ionic login <email> <password>')}. See ${(0, color_1.input)('ionic login --help')} for more details.`);
  144. }
  145. this.env.log.info(`During this process, a browser window will open to authenticate you. Please leave this process running until authentication is complete.`);
  146. this.env.log.nl();
  147. const login = await this.env.prompt({
  148. type: 'confirm',
  149. name: 'continue',
  150. message: 'Open the browser to log in to your Ionic account?',
  151. default: true,
  152. });
  153. if (login) {
  154. await this.logout();
  155. await this.env.session.webLogin();
  156. }
  157. else {
  158. return;
  159. }
  160. }
  161. this.env.log.ok((0, color_1.success)((0, color_1.strong)('You are logged in!')));
  162. }
  163. async logout() {
  164. if (this.env.session.isLoggedIn()) {
  165. await this.env.session.logout();
  166. this.env.config.set('tokens.telemetry', (0, uuid_1.generateUUID)());
  167. }
  168. }
  169. }
  170. exports.LoginCommand = LoginCommand;