UNPKG

baqend

Version:

Baqend JavaScript SDK

386 lines 32.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getApps = exports.whoami = exports.listApps = exports.openDashboard = exports.openApp = exports.persistLogin = exports.logout = exports.login = exports.register = void 0; const open_1 = __importDefault(require("open")); const crypto_1 = __importDefault(require("crypto")); const http_1 = require("http"); const os_1 = __importDefault(require("os")); const inquirer_1 = __importDefault(require("inquirer")); const baqend_1 = require("baqend"); const helper = __importStar(require("./helper")); const helper_1 = require("./helper"); const { TokenStorage } = baqend_1.intersection; const { UserFactory } = baqend_1.binding; const fileName = `${os_1.default.homedir()}/.baqend`; const algorithm = 'aes-256-ctr'; const PROFILE_DEFAULT_KEY = 'N2Ki=za[8iy4ff4jYn/3,y;'; const bbqHost = 'bbq'; function getAppInfo(args) { const isCustomHost = args.app && /^https?:\/\//.test(args.app); return { isCustomHost: !!isCustomHost, host: isCustomHost ? args.app : bbqHost, app: isCustomHost ? null : args.app, }; } function getArgsCredentials(args) { if (args.username && args.password) { return { username: args.username, password: args.password, }; } if (args.token) { return { token: args.token }; } return null; } function getEnvCredentials() { const token = process.env.BAQEND_TOKEN || process.env.BAT; if (token) { return { token }; } return null; } function getProfileCredentials(appInfo) { return readProfileFile().then((json) => { const credentials = json[appInfo.host]; if (!credentials) { return null; } if ('password' in credentials) { console.log('Storing username/password in the baqend profile will not be supported in future version.'); console.log('Logout and login again to fix this issue.'); credentials.password = decrypt(credentials.password); } if ('token' in credentials) { const { createdAt, expireAt } = TokenStorage.parse(credentials.token); // validate token expiration if (createdAt + (24 * 60 * 60 * 1000) < Date.now()) { return null; } } return credentials; }).catch(() => null); } function getLocalCredentials(appInfo) { if (appInfo.isCustomHost) { return { username: 'root', password: 'root' }; } return null; } function getInputCredentials(appInfo, authProvider, showLoginInfo) { return __awaiter(this, void 0, void 0, function* () { if (!process.stdout.isTTY) { throw new Error('Can\'t interactive login into baqend, no tty session was detected.'); } if (showLoginInfo) { console.log('Baqend Login is required. You can skip this step by saving the Login credentials with "baqend login or baqend sso"'); } const options = ['password', 'google', 'facebook', 'github']; let result = authProvider || 'password'; if (!appInfo.isCustomHost && options.length > 1 && !authProvider) { const responses = yield inquirer_1.default.prompt([{ name: 'loginType', message: 'Choose how you want to login:', type: 'list', default: 'google', choices: options.map((op) => ({ name: op })), }]); result = responses.loginType; } if (!result) { throw new Error('No valid login option was chosen.'); } if (result === 'password') { return readInputCredentials(appInfo); } return requestSSOCredentials(appInfo, result); }); } function requestSSOCredentials(appInfo, oAuthProvider, oAuthOptions = {}) { // TODO: current workaround until our server pass this ids to the client dynamically const clientIds = { facebook: '976707865723719', google: '586076830320-0el1jebupjvbcmqf95vfaqjq7gbs0bdh.apps.googleusercontent.com', gitHub: '1311e3415ab415fda705', }; return appConnect(appInfo) .then((db) => { const host = '127.0.0.1'; const port = 9876; const provider = oAuthProvider.toLowerCase(); return Promise.all([ oAuthHandler(host, port), db.loginWithOAuth(oAuthProvider, Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, UserFactory.DefaultOptions[provider] || {}), (clientIds[provider] && { clientId: clientIds[provider] })), { open: open_1.default }), oAuthOptions), { redirect: `http://${host}:${port}` })), ]).then(([credentials, windowProcess]) => { windowProcess.kill('SIGHUP'); // seems not working on every platform return credentials; }); }); } function oAuthHandler(host, port) { return __awaiter(this, void 0, void 0, function* () { const htmlTemplate = yield (0, helper_1.readModuleFile)('./sso.html'); return new Promise((resolve, reject) => { const server = (0, http_1.createServer)((req, res) => { const url = new URL(req.url, `http://${host}:${port}`); const errorMessage = url.searchParams.get('errorMessage'); let text = null; if (errorMessage) { reject(new Error(errorMessage)); text = `<h1>An error has occurred</h1><p>${errorMessage}</p>`; } else if (url.searchParams.has('token')) { resolve({ token: url.searchParams.get('token') }); text = '<h1>Continue within the CLI</h1><p>You can close this window now.</p>'; } if (text) { // eslint-disable-next-line no-template-curly-in-string const html = htmlTemplate.replace('${content}', text); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(html); setTimeout(() => { server.close(); }); } else { res.writeHead(404); res.end(); } }); server.on('error', (err) => { reject(err); }); server.listen(port, host); }); }); } function getCredentials(appInfo, args) { let providers = Promise.resolve(null) .then((credentials) => credentials || getArgsCredentials(args)) .then((credentials) => credentials || getEnvCredentials()) .then((credentials) => credentials || getProfileCredentials(appInfo)) .then((credentials) => credentials || getLocalCredentials(appInfo)); if (!args.skipInput && process.stdout.isTTY) { providers = providers .then((credentials) => credentials || persistLogin(Object.assign(Object.assign({}, appInfo), args))); } return providers; } function register(args) { const appInfo = getAppInfo(args); return getInputCredentials(appInfo, args.auth) .then((credentials) => appConnect(appInfo) .then((db) => { if ('token' in credentials) { return db.User.loginWithToken(credentials.token).then(() => db); } return db.User.register(credentials.username, credentials.password).then(() => db); }) .then((db) => Promise.all([ getDefaultApp(db).then((name) => console.log(`Your app name is ${name}`)), saveCredentials(appInfo, { token: db.token }), ]))); } exports.register = register; function connect(args) { const appInfo = getAppInfo(args); return getCredentials(appInfo, args) .then((credentials) => { if (!credentials) throw new Error('Login information are missing. Login with baqend login or pass a baqend token via BAQEND_TOKEN environment variable'); return appConnect(appInfo, credentials); }); } function appConnect(appInfo, credentials) { // do not use the global token storage here, to prevent login collisions on the bbq app const factory = new baqend_1.EntityManagerFactory({ host: appInfo.host, secure: true, tokenStorageFactory: TokenStorage }); return factory.createEntityManager(true).ready().then((db) => { if (!credentials) return db; if ('token' in credentials) { return db.User.loginWithToken(credentials.token) .then((me) => { if (me) { return db; } throw new Error('Login with Baqend token failed.'); }); } return db.User.login(credentials.username, credentials.password).then(() => db); }); } function login(args) { const appInfo = getAppInfo(args); return connect(args) .then((db) => { if (appInfo.isCustomHost) { return db; } if (appInfo.app) { return bbqAppLogin(db, appInfo.app); } return getDefaultApp(db).then((appName) => bbqAppLogin(db, appName)); }).catch((e) => { // if the login failed try to directly login into the app if (appInfo.app && !appInfo.isCustomHost) { return login(Object.assign(Object.assign({}, args), { app: `https://${appInfo.app}.app.baqend.com/v1` })); } throw e; }); } exports.login = login; function bbqAppLogin(db, appName) { return __awaiter(this, void 0, void 0, function* () { const { token } = yield db.modules.get('token', { app: appName }); return appConnect({ host: appName, isCustomHost: false, app: appName }, { token }); }); } function logout(args) { const appInfo = getAppInfo(args); return readProfileFile().then((json) => { // eslint-disable-next-line no-param-reassign delete json[appInfo.host]; return writeProfileFile(json); }); } exports.logout = logout; function persistLogin(args) { return __awaiter(this, void 0, void 0, function* () { const appInfo = getAppInfo(args); let credentials = getArgsCredentials(args); if (!credentials) { credentials = yield getInputCredentials(appInfo, args.auth, false); } const db = yield appConnect(appInfo, credentials); const tokenCredentials = 'token' in credentials ? credentials : { token: db.token }; yield saveCredentials(appInfo, tokenCredentials); return tokenCredentials; }); } exports.persistLogin = persistLogin; function openApp(app) { if (app) { return (0, open_1.default)(`https://${app}.app.baqend.com`); } return login({}).then((db) => { (0, open_1.default)(`https://${db.connection.host}`); }); } exports.openApp = openApp; function openDashboard(args) { return connect(args).then((db) => { (0, open_1.default)(`https://dashboard.baqend.com/login?token=${db.token}`); }).catch(() => { (0, open_1.default)('https://dashboard.baqend.com'); }); } exports.openDashboard = openDashboard; function listApps(args) { return __awaiter(this, void 0, void 0, function* () { const db = yield connect(args); let apps = yield getApps(db); apps = apps.sort(); apps.forEach((app) => console.log(app)); }); } exports.listApps = listApps; function whoami(args) { return connect(Object.assign({ skipInput: true }, args)) .then((db) => console.log(db.User.me.username), () => console.log('You are not logged in.')); } exports.whoami = whoami; function getApps(db) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { let query = db.App.find() .eq('status', 'running'); if ((_b = (_a = db.User.me) === null || _a === void 0 ? void 0 : _a.username) === null || _b === void 0 ? void 0 : _b.endsWith('@baqend.com')) { query = query.eq('owner', db.User.me); } return (yield query.resultList()).map((app) => app.name); }); } exports.getApps = getApps; function getDefaultApp(db) { return getApps(db).then((apps) => { if (apps.length === 1) { return apps[0]; } throw new Error('Please add the name of your app as a parameter.'); }); } function readInputCredentials(appInfo) { return __awaiter(this, void 0, void 0, function* () { return inquirer_1.default.prompt([ { name: 'username', type: 'input', message: appInfo.isCustomHost ? 'Username:' : 'E-Mail:' }, { name: 'password', type: 'password', message: 'Password:' }, ]); }); } function decrypt(input) { // This is legacy and we will remove support for the username / password storage in the profile file // eslint-disable-next-line node/no-deprecated-api const decipher = crypto_1.default.createDecipher(algorithm, PROFILE_DEFAULT_KEY); let decrypted = decipher.update(input, 'base64', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } function writeProfileFile(json) { return helper.writeFile(fileName, JSON.stringify(json)).catch((e) => { console.warn('Baqend Profile file can\'t be written', e); throw e; }); } function readProfileFile() { return (0, helper_1.isFile)(fileName).then((exists) => { if (!exists) { return {}; } return (0, helper_1.readFile)(fileName, 'utf-8').then((data) => (data ? JSON.parse(data) : {})); }); } function saveCredentials(appInfo, credentials) { return readProfileFile().then((json) => { // eslint-disable-next-line no-param-reassign json[appInfo.host] = Object.assign(Object.assign({}, json[appInfo.host]), credentials); return writeProfileFile(json); }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjb3VudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFjY291bnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxnREFBd0I7QUFFeEIsb0RBQTRCO0FBQzVCLCtCQUFvQztBQUNwQyw0Q0FBb0I7QUFDcEIsd0RBQWdDO0FBQ2hDLG1DQUVnQjtBQUNoQixpREFBbUM7QUFDbkMscUNBRWtCO0FBRWxCLE1BQU0sRUFBRSxZQUFZLEVBQUUsR0FBRyxxQkFBWSxDQUFDO0FBQ3RDLE1BQU0sRUFBRSxXQUFXLEVBQUUsR0FBRyxnQkFBTyxDQUFDO0FBRWhDLE1BQU0sUUFBUSxHQUFHLEdBQUcsWUFBRSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUM7QUFDM0MsTUFBTSxTQUFTLEdBQUcsYUFBYSxDQUFDO0FBQ2hDLE1BQU0sbUJBQW1CLEdBQUcseUJBQXlCLENBQUM7QUFDdEQsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDO0FBa0N0QixTQUFTLFVBQVUsQ0FBQyxJQUFpQjtJQUNuQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRS9ELE9BQU87UUFDTCxZQUFZLEVBQUUsQ0FBQyxDQUFDLFlBQVk7UUFDNUIsSUFBSSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUksQ0FBQyxDQUFDLENBQUMsT0FBTztRQUN4QyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFJO0tBQ3JDLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxrQkFBa0IsQ0FBQyxJQUFpQjtJQUMzQyxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtRQUNsQyxPQUFPO1lBQ0wsUUFBUSxFQUFFLElB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