1 | var async = require('async');
|
2 | var _ = require('lodash');
|
3 | var fs = require('fs');
|
4 | var api = require('./api');
|
5 | var log = require('./log');
|
6 | var parseUrl = require('url').parse;
|
7 | var manifest = require('./manifest');
|
8 | var debug = require('debug')('4front:cli:init');
|
9 | var inquirer = require('inquirer');
|
10 |
|
11 | require('simple-errors');
|
12 |
|
13 |
|
14 | module.exports = function(program, options, callback) {
|
15 | log.debug("initiliazing CLI");
|
16 |
|
17 | _.defaults(options, {
|
18 | requireAuth: false,
|
19 | loadManifest: false,
|
20 | loadVirtualApp: false
|
21 | });
|
22 |
|
23 | var initTasks = [];
|
24 |
|
25 | initTasks.push(ensure4frontConfigExists);
|
26 |
|
27 | if (options.requireAuth === true) {
|
28 | initTasks.push(ensureProfileExists);
|
29 | initTasks.push(selectProfile);
|
30 | initTasks.push(checkForJwt);
|
31 | initTasks.push(promptForCredentials);
|
32 | initTasks.push(updateProfileConfig);
|
33 | }
|
34 |
|
35 | if (options.loadManifest === true) {
|
36 | initTasks.push(loadManifest);
|
37 | }
|
38 |
|
39 | if (options.loadManifest && options.loadVirtualApp) {
|
40 | initTasks.push(loadVirtualApp);
|
41 | }
|
42 |
|
43 | async.series(initTasks, callback);
|
44 |
|
45 | function ensureProfileExists(cb) {
|
46 | debug("prompt for profile");
|
47 |
|
48 |
|
49 | if (_.isEmpty(program.globalConfig.profiles) === false)
|
50 | return cb();
|
51 |
|
52 |
|
53 | log.messageBox("No 4front instances have been configured. \n" +
|
54 | "Please enter the URL of your instance:");
|
55 |
|
56 | debug("no configured profiles, prompt for one");
|
57 | inquirer.prompt([{
|
58 | type: "input",
|
59 | name: "endpoint",
|
60 | message: "Endpoint URL:"
|
61 | }, {
|
62 | type: "input",
|
63 | name: "identityProvider",
|
64 | message: "Identity provider:"
|
65 | }], function(answers) {
|
66 |
|
67 | program.globalConfig.profiles = [{
|
68 | endpoint: answers.endpoint,
|
69 | name: 'default',
|
70 | default: true,
|
71 | identityProvider: answers.identityProvider
|
72 | }];
|
73 |
|
74 | cb();
|
75 | });
|
76 | }
|
77 |
|
78 |
|
79 | function selectProfile(cb) {
|
80 | if (program.profile) {
|
81 | program.profile = _.find(program.globalConfig.profiles, {
|
82 | name: program.profile
|
83 | });
|
84 | }
|
85 |
|
86 |
|
87 | var envVarProfile = process.env.FF_PROFILE;
|
88 | if (_.isEmpty(envVarProfile) === false) {
|
89 | program.profile = _.find(program.globalConfig.profiles, {name: envVarProfile});
|
90 | if (!program.profile)
|
91 | cb(new Error("Environment variable FF_PROFILE refers to to an invalid 4front profile."));
|
92 | }
|
93 |
|
94 |
|
95 | if (!program.profile)
|
96 | program.profile = _.find(program.globalConfig.profiles, {
|
97 | default: true
|
98 | }) || program.globalConfig.profiles[0];
|
99 |
|
100 | var endpointUrl = parseUrl(program.profile.endpoint);
|
101 | program.virtualHost = endpointUrl.host;
|
102 |
|
103 | debug("using profile: %o", _.pick(program.profile, 'name', 'url'));
|
104 |
|
105 | cb();
|
106 | }
|
107 |
|
108 |
|
109 | function checkForJwt(cb) {
|
110 | debug("check for existing jwt");
|
111 |
|
112 |
|
113 | if (_.isObject(program.profile.jwt) === false)
|
114 | return cb();
|
115 |
|
116 |
|
117 | if (options.forceLogin) {
|
118 | program.profile.jwt = null;
|
119 | return cb();
|
120 | }
|
121 |
|
122 |
|
123 | if (_.isNumber(program.profile.jwt.expires) === false ||
|
124 | Date.now() > program.profile.jwt.expires) {
|
125 | program.profile.jwt = null;
|
126 | }
|
127 |
|
128 | cb();
|
129 | }
|
130 |
|
131 | function promptForCredentials(cb) {
|
132 |
|
133 |
|
134 | if (program.profile.jwt) {
|
135 | debug("using existing jwt");
|
136 | return cb();
|
137 | }
|
138 |
|
139 | debug("prompt for credentials");
|
140 |
|
141 |
|
142 | inquirer.prompt([{
|
143 | type: 'input',
|
144 | name: 'username',
|
145 | message: 'Username:',
|
146 | }, {
|
147 | type: 'password',
|
148 | name: 'password',
|
149 | message: 'Password:'
|
150 | }], function(answers) {
|
151 | answers.identityProvider = program.profile.identityProvider;
|
152 |
|
153 | var apiOptions = {
|
154 | method: 'POST',
|
155 | path: '/profile/login',
|
156 | json: answers,
|
157 | authenticate: false
|
158 | };
|
159 |
|
160 | api(program, apiOptions, function(err, user) {
|
161 | if (err) return cb(err);
|
162 |
|
163 | debug("setting jwt for profile %s: %s", program.profile.name, JSON.stringify(user.jwt));
|
164 |
|
165 |
|
166 | program.profile.jwt = user.jwt;
|
167 | cb();
|
168 | });
|
169 | });
|
170 | }
|
171 |
|
172 | function updateProfileConfig(cb) {
|
173 | debug("writing to %s", program.globalConfigPath);
|
174 | var configJson = JSON.stringify(program.globalConfig, null, 2);
|
175 | fs.writeFile(program.globalConfigPath, configJson, cb);
|
176 | }
|
177 |
|
178 | function loadManifest(cb) {
|
179 | log.debug("loading virtual app config from package.json");
|
180 |
|
181 | manifest.load(program, function(err, config) {
|
182 | if (err) return cb(err);
|
183 |
|
184 | program.virtualAppManifest = config;
|
185 | cb();
|
186 | });
|
187 | }
|
188 |
|
189 | function loadVirtualApp(cb) {
|
190 | if (!program.virtualAppManifest)
|
191 | return cb();
|
192 |
|
193 | log.debug("invoking api to fetch the virtual app");
|
194 | api(program, {method: 'GET', path: '/apps/' + program.virtualAppManifest.appId}, function(err, app) {
|
195 | if (err) return cb(err);
|
196 | if (!app)
|
197 | return cb("Application " + program.virtualAppManifest.appId + " could not be found.");
|
198 |
|
199 | debug("virtual app loaded from API");
|
200 | program.virtualApp = app;
|
201 | cb();
|
202 | });
|
203 | }
|
204 |
|
205 | function ensure4frontConfigExists(cb) {
|
206 | fs.exists(program.globalConfigPath, function(exists) {
|
207 | if (!exists)
|
208 | return createEmptyConfig();
|
209 |
|
210 |
|
211 | fs.readFile(program.globalConfigPath, function(err, data) {
|
212 | if (err) return cb(err);
|
213 |
|
214 | try {
|
215 | program.globalConfig = JSON.parse(data.toString());
|
216 | }
|
217 | catch (jsonErr) {
|
218 | debug("Config file %s is corrupt", program.globalConfigPath);
|
219 | return createEmptyConfig();
|
220 | }
|
221 | cb();
|
222 | });
|
223 | });
|
224 |
|
225 | function createEmptyConfig() {
|
226 | program.globalConfig = {profiles: []};
|
227 |
|
228 | fs.writeFile(program.globalConfigPath,
|
229 | JSON.stringify(program.globalConfig, null, 2), cb);
|
230 | }
|
231 | }
|
232 | };
|