diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index 005560848..63704de09 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -3,20 +3,21 @@ const BbPromise = require('bluebird'); const crypto = require('crypto'); const readline = require('readline'); -const opn = require('opn'); const fetch = require('node-fetch'); const jwtDecode = require('jwt-decode'); const chalk = require('chalk'); +const openBrowser = require('../../utils/openBrowser'); const getFrameworkId = require('../../utils/getFrameworkId'); const clearConsole = require('../../utils/clearConsole'); -// const segment = require('../../utils/segment'); +const userStats = require('../../utils/userStats'); const setConfig = require('../../utils/config').set; -// const getConfig = require('../../utils/config').getConfig; +// segment for future use +// const segment = require('../../utils/segment'); const config = { AUTH0_CLIENT_ID: 'iiEYK0KB30gj94mjB8HP9lhhTgae0Rg3', AUTH0_URL: 'https://serverlessinc.auth0.com', - AUTH0_CALLBACK_URL: 'https://serverless.com/welcome', + AUTH0_CALLBACK_URL: 'https://serverless.com/auth', }; function base64url(url) { @@ -44,42 +45,19 @@ class Login { 'login:login': () => BbPromise.bind(this).then(this.login), }; } - openBrowser(url) { - let browser = process.env.BROWSER; - if (browser === 'none') { - return false; - } - if (process.platform === 'darwin' && browser === 'open') { - browser = undefined; - } - try { - const options = { app: browser }; - opn(url, options).catch(() => {}); - return true; - } catch (err) { - // https://github.com/sindresorhus/log-symbols - console.log('---------------------------'); // eslint-disable-line - console.log(`🙈 ${chalk.red("Unable to open browser automatically")}`); // eslint-disable-line - console.log(chalk.green("Please open your browser & open the URL below to login:")); // eslint-disable-line - console.log(chalk.yellow(url)); // eslint-disable-line - console.log('---------------------------'); // eslint-disable-line - return false; - } - } login() { clearConsole(); this.serverless.cli.log('The Serverless login will open in your default browser...'); - // Generate the verifier, and the corresponding challenge const verifier = base64url(crypto.randomBytes(32)); const verifierChallenge = base64url(crypto.createHash('sha256').update(verifier).digest()); const frameworkId = getFrameworkId(); // eslint-disable-next-line prefer-template - const state = `id%3D${frameworkId}`; + const version = this.serverless.version; + const state = `id%3D${frameworkId}%26version%3D${version}%26platform%3D${process.platform}`; // refresh token docs https://auth0.com/docs/tokens/preview/refresh-token#get-a-refresh-token const authorizeUrl = - `${config.AUTH0_URL}/authorize?response_type=code` + - '&scope=openid%20email%20nickname%20offline_access' + + `${config.AUTH0_URL}/authorize?response_type=code&scope=openid%20profile%20offline_access` + `&client_id=${config.AUTH0_CLIENT_ID}&redirect_uri=${config.AUTH0_CALLBACK_URL}` + `&code_challenge=${verifierChallenge}&code_challenge_method=S256&state=${state}`; @@ -89,7 +67,7 @@ class Login { setTimeout(() => { // pop open default browser - this.openBrowser(authorizeUrl); + openBrowser(authorizeUrl); // wait for token const readlineInterface = readline.createInterface({ @@ -114,34 +92,65 @@ class Login { .then((response) => response.json()) .then((platformResponse) => { const decoded = jwtDecode(platformResponse.id_token); - this.serverless.cli.log('You are logged in'); - // alias for segment only works with mixpanel - // segment.alias({ - // previousId: frameworkId, - // userId: decoded.sub, - // }); - /* segment.identify({ - userId: decoded.sub, + // console.log('decoded', decoded); + this.serverless.cli.log('You are now logged in'); + console.log('Run `serverless` or `sls` to see a list of commands`'); // eslint-disable-line + + // because platform only support github + const id = decoded.original_user_id || decoded.sub; + + /* For future use + segment.identify({ + userId: id, traits: { email: profile.email, }, }) */ - // update .serverlessrc + const userConfig = { - userId: decoded.sub, + userId: id, frameworkId, users: {}, }; - // set user auth - userConfig.users[decoded.sub] = { - userId: decoded.sub, + // set user auth in global .serverlessrc file + userConfig.users[id] = { + userId: id, + name: decoded.name, + email: decoded.email, auth: platformResponse, }; + + // update .serverlessrc setConfig(userConfig); - process.exit(0); + + const userID = new Buffer(id).toString('base64'); + const email = new Buffer(decoded.email).toString('base64'); + const name = new Buffer(decoded.name).toString('base64'); + const loginCount = decoded.login_count; + const createdAt = decoded.created_at; + const successUrl = `https://serverless.com/success?u=${userID}&e=${email}&n=${name}&c=${loginCount}&v=${version}&d=${createdAt}&id=${frameworkId}`; // eslint-disable-line + + openBrowser(successUrl); + // identify user for better onboarding + userStats.identify({ + id, + frameworkId, + email: decoded.email, + // unix timestamp + created_at: Math.round(+new Date(createdAt) / 1000), + }).then(() => { + userStats.track('user_loggedIn', { + id, + email: decoded.email, + }).then(() => { + // console.log('login complete'); + // then exit process + process.exit(0); + }); + }); }) - .catch((e) => { - console.log(e); // eslint-disable-line + .catch(() => { + console.log(chalk.red('Incorrect token value supplied. Please run `serverless login` again')); // eslint-disable-line process.exit(0); }); });