UNPKG

@adinsure-ops/ops-cli

Version:

Operations CLI for working with AdInsure

218 lines (217 loc) 8.74 kB
import { __awaiter } from "tslib"; import { Flags } from '@oclif/core'; import chalk from 'chalk'; import fs from 'fs'; import http from 'http'; import open from 'open'; import path from 'path'; import url from 'url'; import { execSync } from 'child_process'; import CommandBase from '../command.base.js'; import NpmRc from '../lib/npmrc.js'; import YarnRc from '../lib/yarnrc.js'; class Login extends CommandBase { constructor() { super(...arguments); this.npmRegistries = [ 'https://pkgs.dev.azure.com/adacta-fintech/adinsure/_packaging/feed/npm/registry/', 'https://pkgs.dev.azure.com/adinsure-test/_packaging/TestFeed/npm/registry/', ]; } /** * Get NPM token for adinsure npm repositories * * @returns [[Promise<string>]] */ setNPM() { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { try { const npmRc = new NpmRc(); const yarnRc = new YarnRc(); const token = yield this.security.getNPMToken(); for (const registry of this.npmRegistries) { const registryUrl = new url.URL(registry); npmRc.set(`//${registryUrl.hostname}${registryUrl.pathname}:_authToken`, token); yarnRc.set("npmAuthToken", token); } npmRc.save(); yarnRc.save(); this.log(`${chalk.green('NPM token generated!')}`); resolve(); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error) { reject(error); } })); }); } /** * Handle Docker login by: * 1. Checking if Docker is available. * 2. Ensuring user is logged in. * 3. Generating a Docker token for adinsure.azurecr.io. * 4. Running 'docker login' with the generated token. */ handleDockerLogin() { return __awaiter(this, void 0, void 0, function* () { // 1. Check if Docker command is available try { execSync('docker --version', { stdio: 'ignore' }); } catch (err) { this.error('Docker is not installed or not in PATH. Please install Docker first.', { exit: 1 }); } // 2. Ensure the user is logged in (using your existing token retrieval logic) try { yield this.security.getToken(); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err) { this.error('User is not logged in. Please run "ops login" without --docker first.', { exit: 1 }); } // 3. generate token from `adinsure.azurecr.io` this.log(chalk.yellow('Generating Docker authentication token for adinsure.azurecr.io...')); let acrToken; try { acrToken = yield this.security.getACRToken(); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err) { this.error('Failed to generate Docker token: ' + err.message, { exit: 1 }); } // 4. call docker login command this.log(chalk.yellow('Logging in to adinsure.azurecr.io via Docker...')); try { execSync(`docker login adinsure.azurecr.io -u 00000000-0000-0000-0000-000000000000 --password "${acrToken}" `); this.log(chalk.green('Docker login successful!')); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err) { this.error('Docker login failed: ' + err.message, { exit: 1 }); } }); } run() { const _super = Object.create(null, { run: { get: () => super.run } }); return __awaiter(this, void 0, void 0, function* () { _super.run.call(this); const { flags } = yield this.parse(Login); if (flags.docker) { yield this.handleDockerLogin(); return; } if (flags.force) { fs.unlink(path.resolve(this.security.getTokenPath()), () => { this.log(`${chalk.yellow('Note: We have launched a browser for you to login.')}`); }); } if (flags.skipCI && process.env[flags.skipCI]) { if (flags.force) this.error(new Error('Cannot skip login as the force login flag has been set')); this.log(`${chalk.yellow('Note: skipping login because variables was set for CI')}`); return; } if (flags.npm) { try { yield this.setNPM(); return; } catch (_a) { this.log(`${chalk.yellow('Note: Login is needed to get NPM token!')}`); } } if (flags.deviceFlow) { try { yield this.security.acquireTokenDeviceFlow(); this.log(`${chalk.green('Login Successful!')}`); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error) { this.error(error); } } else { this.log(`${chalk.yellow('Note: We have launched a browser for you to login.')}`); const loginUrl = yield this.security.getLoginUrl(); yield open(loginUrl); const server = http.createServer((req, res) => __awaiter(this, void 0, void 0, function* () { // First let the user know everything was OK res.writeHead(200, { 'Content-Type': 'text/html' }); res.write(Login.responsePageContent); res.end(); this.log(`${chalk.yellow('You have logged in successfully. Acquiring your access token...')}`); // Then let's acquire an authentication token from AAD try { const queryURL = new url.URL(req.url, 'http://localhost:3044').searchParams; const name = yield this.security.acquireToken(Object.fromEntries(Array.from(queryURL.entries()))); this.log(`Hello ${name}!`); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error) { this.error(error, { exit: false }); } if (flags.npm) { try { yield this.setNPM(); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error) { this.error(error, { exit: false }); } } server.close(); })); server.listen(3044); } }); } } Login.description = 'log in to use ops services with AzureAD'; Login.usage = 'login'; Login.examples = [ `$ ops login`, `$ ops login --npm`, `$ ops login --skipCi CI`, `$ ops login --deviceFlow`, ]; Login.flags = { deviceFlow: Flags.boolean({ description: 'authenticate using device flow', default: false, }), npm: Flags.boolean({ description: 'register also for npm', default: false, }), skipCI: Flags.string({ description: 'Skip login if environment variables is set', }), force: Flags.boolean({ description: 'Force a change of login token', default: false, }), docker: Flags.boolean({ description: 'Authenticate with adinsure.azurecr.io for Docker', default: false, }), }; Login.responsePageContent = ` <!DOCTYPE html> <html> <head> <title>ops-cli authenticate</title> <link rel='icon' href='data:;base64,iVBORw0KGgo='> </head> <body> <p><strong>Your login was successful!</strong></p> <p>This page will automatically close after 10 seconds OR you can close it yourself immediately.</p> <script type='text/javascript'> setTimeout('self.close()', 10000); </script> </body> </html>`; export default Login;