captainduckduck
Version:
CLI tool for CaptainDuckDuck. See CaptainDuckDuck.com for more details.
231 lines (201 loc) • 7.5 kB
text/typescript
import * as inquirer from 'inquirer';
import Constants from '../utils/Constants';
import StdOutUtil from '../utils/StdOutUtil';
import { isIpAddress } from '../utils/ValidationsHandler';
import { IMachine } from '../models/storage/StoredObjects';
import CliApiManager from '../api/CliApiManager';
import Utils from '../utils/Utils';
import CliHelper from '../utils/CliHelper';
import StorageHelper from '../utils/StorageHelper';
import ErrorFactory from '../utils/ErrorFactory';
import SpinnerHelper from '../utils/SpinnerHelper';
let newPasswordFirstTry: string | undefined = undefined;
let lastWorkingPassword: string = Constants.DEFAULT_PASSWORD;
let serverIpAddress = '';
let captainMachine: IMachine = {
authToken: '',
baseUrl: '',
name: ''
};
const questions = [
{
type: 'list',
name: 'hasInstalledCaptain',
message:
'Have you already installed Captain on your server by running the following line:' +
'\nmkdir /captain && docker run -p 80:80 -p 443:443 -p 3000:3000 -v /var/run/docker.sock:/var/run/docker.sock dockersaturn/captainduckduck ?',
default: 'Yes',
choices: [ 'Yes', 'No' ],
filter: (value: string) => {
const answerFromUser = value.trim();
if (answerFromUser === 'Yes') return answerFromUser;
StdOutUtil.printMessage('\n\nCannot start the setup process if Captain is not installed.');
StdOutUtil.printMessageAndExit(
'Please read tutorial on CaptainDuckDuck.com to learn how to install CaptainDuckDuck on a server.'
);
}
},
{
type: 'input',
default: Constants.SAMPLE_IP,
name: 'captainAddress',
message: 'Enter IP address of your captain server:',
filter: async (value: string) => {
const ipFromUser = value.trim();
if (ipFromUser === Constants.SAMPLE_IP || !isIpAddress(ipFromUser)) {
StdOutUtil.printError(`\nThis is an invalid IP Address: ${ipFromUser}`, true);
}
try {
// login using captain42. and set the ipAddressToServer
captainMachine.baseUrl = `http://${ipFromUser}:3000`;
await CliApiManager.get(captainMachine).getAuthToken(lastWorkingPassword);
serverIpAddress = ipFromUser;
} catch (e) {
// User may have used a different default password
if (e.captainStatus === ErrorFactory.STATUS_WRONG_PASSWORD) return '';
StdOutUtil.errorHandler(e);
}
return ipFromUser;
}
},
{
type: 'password',
name: 'captainOriginalPassword',
message: 'Enter your current password:',
when: () => !captainMachine.authToken, // The default password didn't work
filter: async (value: string) => {
try {
await CliApiManager.get(captainMachine).getAuthToken(value);
lastWorkingPassword = value;
return '';
} catch (e) {
StdOutUtil.errorHandler(e);
}
}
},
{
type: 'input',
name: 'captainRootDomain',
message:
'Enter a root domain for this Captain server. For example, enter test.yourdomain.com if you' +
' setup your DNS to point *.test.yourdomain.com to ip address of your server.',
filter: async (value: string) => {
const captainRootDomainFromUser = value.trim();
try {
await CliApiManager.get(captainMachine).updateRootDomain(captainRootDomainFromUser);
captainMachine = Utils.copyObject(captainMachine);
captainMachine.baseUrl = `http://captain.${captainRootDomainFromUser}`;
} catch (e) {
StdOutUtil.printError('\n\n');
if (e.captainStatus === ErrorFactory.VERIFICATION_FAILED) {
if (captainRootDomainFromUser.indexOf('/') >= 0) {
StdOutUtil.printError(
'DO NOT include http in your base domain, it should be just plain domain, e.g., test.domain.com'
);
}
if (captainRootDomainFromUser.indexOf('*') >= 0) {
StdOutUtil.printError(
'DO NOT include * in your base domain, it should be just plain domain, e.g., test.domain.com'
);
}
StdOutUtil.printError(
`\n\nCannot verify that http://captain.${captainRootDomainFromUser} points to your server IP.\n` +
`\nAre you sure that you set *.${captainRootDomainFromUser} points to ${serverIpAddress}\n\n` +
`Double check your DNS. If everything looks correct, note that, DNS changes take up to 24 hrs to work properly. Check with your Domain Provider.`
);
}
StdOutUtil.errorHandler(e);
}
return captainRootDomainFromUser;
}
},
{
type: 'password',
name: 'newPasswordFirstTry',
message: 'Enter a new password:',
filter: (value: string) => {
newPasswordFirstTry = value;
if (!newPasswordFirstTry) {
StdOutUtil.printError('Password empty.', true);
throw new Error('Password empty');
}
return value;
}
},
{
type: 'password',
name: 'newPassword',
message: 'Enter your new password again:',
filter: async (value: string) => {
const confirmPasswordValueFromUser = value;
if ((newPasswordFirstTry !== confirmPasswordValueFromUser)) {
StdOutUtil.printError('Passwords do not match. Try serversetup again.', true);
throw new Error('Password mismatch');
}
return '';
}
},
{
type: 'input',
name: 'emailAddress',
message: "Enter your 'valid' email address to enable HTTPS: ",
filter: async (value: string) => {
const emailAddressFromUser = value.trim();
let forcedSsl = false;
try {
SpinnerHelper.start('Enabling SSL... Takes a few seconds...');
await CliApiManager.get(captainMachine).enableRootSsl(emailAddressFromUser);
captainMachine = Utils.copyObject(captainMachine);
captainMachine.baseUrl = captainMachine.baseUrl.replace('http://', 'https://');
await CliApiManager.get(captainMachine).forceSsl(true);
forcedSsl = true;
await CliApiManager.get(captainMachine).changePass(lastWorkingPassword, newPasswordFirstTry!);
lastWorkingPassword = newPasswordFirstTry!;
await CliApiManager.get(captainMachine).getAuthToken(lastWorkingPassword);
SpinnerHelper.stop();
} catch (e) {
if (forcedSsl) {
StdOutUtil.printError(
'Server is setup, but password was not changed due to an error. You cannot use serversetup again.'
);
StdOutUtil.printError(
`Instead, go to ${captainMachine.baseUrl} and change your password on settings page.`
);
StdOutUtil.printError(
`Then, Use captainduckduck login on your local machine to connect to your server.`
);
}
SpinnerHelper.fail();
StdOutUtil.errorHandler(e);
}
return emailAddressFromUser;
}
},
{
type: 'input',
name: 'captainName',
message: 'Enter a name for this Captain machine:',
default: CliHelper.get().findDefaultCaptainName(),
validate: (value: string) => {
const newMachineName = value.trim();
let errorMessage = undefined;
if (StorageHelper.get().findMachine(newMachineName)) {
return `${newMachineName} already exist. If you want to replace the existing entry, you have to first use <logout> command, and then re-login.`;
}
if (CliHelper.get().isNameValid(newMachineName)) {
captainMachine.name = newMachineName;
return true;
}
return 'Please enter a valid Captain Name. Small letters, numbers, single hyphen.';
}
}
];
async function serversetup() {
StdOutUtil.printMessage('\nSetup your Captain server\n');
const answersIgnore = await inquirer.prompt(questions);
StorageHelper.get().saveMachine(captainMachine);
StdOutUtil.printMessage(`\n\nCaptain is available at ${captainMachine.baseUrl}`);
StdOutUtil.printMessage('\nFor more details and docs see http://www.captainduckduck.com\n\n');
}
export default serversetup;