'use strict'; /* global $, angular, Clipboard, ENDPOINTS_OVH, redirectIfNeeded */ // create main application module var app = angular.module('Application', ['pascalprecht.translate', 'ngCookies', 'angular-md5', 'ui-notification', 'ui.bootstrap']); app.controller('SetupDNSController', ['$scope', '$http', '$timeout', 'Client', function ($scope, $http, $timeout, Client) { var search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {}); $scope.state = null; // 'initialized', 'waitingForDnsSetup', 'waitingForBox' $scope.error = {}; $scope.provider = ''; $scope.showDNSSetup = false; $scope.instanceId = ''; $scope.advancedVisible = false; $scope.clipboardDone = false; $scope.search = window.location.search; $scope.setupToken = ''; $scope.taskMinutesActive = null; $scope.tlsProvider = [ { name: 'Let\'s Encrypt Prod', value: 'letsencrypt-prod' }, { name: 'Let\'s Encrypt Prod - Wildcard', value: 'letsencrypt-prod-wildcard' }, { name: 'Let\'s Encrypt Staging', value: 'letsencrypt-staging' }, { name: 'Let\'s Encrypt Staging - Wildcard', value: 'letsencrypt-staging-wildcard' }, { name: 'Self-Signed', value: 'fallback' }, // this is not 'Custom' because we don't allow user to upload certs during setup phase ]; $scope.ipv4Config = { provider: 'generic', ip: '', ifname: '' }; $scope.ipv6Config = { provider: 'generic', ip: '', ifname: '' }; $scope.ipProviders = [ { name: 'Disabled', value: 'noop' }, { name: 'Public IP', value: 'generic' }, { name: 'Static IP Address', value: 'fixed' }, { name: 'Network Interface', value: 'network-interface' } ]; $scope.ovhEndpoints = ENDPOINTS_OVH; $scope.needsPort80 = function (dnsProvider, tlsProvider) { return ((dnsProvider === 'manual' || dnsProvider === 'noop' || dnsProvider === 'wildcard') && (tlsProvider === 'letsencrypt-prod' || tlsProvider === 'letsencrypt-staging')); }; // If we migrate the api origin we have to poll the new location if (search.admin_fqdn) Client.apiOrigin = 'https://' + search.admin_fqdn; // keep in sync with domains.js $scope.dnsProvider = [ { name: 'AWS Route53', value: 'route53' }, { name: 'Bunny', value: 'bunny' }, { name: 'Cloudflare', value: 'cloudflare' }, { name: 'deSEC', value: 'desec' }, { name: 'DigitalOcean', value: 'digitalocean' }, { name: 'DNSimple', value: 'dnsimple' }, { name: 'Gandi LiveDNS', value: 'gandi' }, { name: 'GoDaddy', value: 'godaddy' }, { name: 'Google Cloud DNS', value: 'gcdns' }, { name: 'Hetzner', value: 'hetzner' }, { name: 'INWX', value: 'inwx' }, { name: 'Linode', value: 'linode' }, { name: 'Name.com', value: 'namecom' }, { name: 'Namecheap', value: 'namecheap' }, { name: 'Netcup', value: 'netcup' }, { name: 'OVH', value: 'ovh' }, { name: 'Porkbun', value: 'porkbun' }, { name: 'Vultr', value: 'vultr' }, { name: 'Wildcard', value: 'wildcard' }, { name: 'Manual (not recommended)', value: 'manual' }, { name: 'No-op (only for development)', value: 'noop' } ]; $scope.dnsCredentials = { busy: false, domain: '', accessKeyId: '', secretAccessKey: '', gcdnsKey: { keyFileName: '', content: '' }, digitalOceanToken: '', gandiApiKey: '', gandiTokenType: 'PAT', cloudflareEmail: '', cloudflareToken: '', cloudflareTokenType: 'GlobalApiKey', cloudflareDefaultProxyStatus: false, godaddyApiKey: '', godaddyApiSecret: '', linodeToken: '', bunnyAccessKey: '', dnsimpleAccessToken: '', hetznerToken: '', inwxUsername: '', inwxPassword: '', vultrToken: '', deSecToken: '', nameComUsername: '', nameComToken: '', namecheapUsername: '', namecheapApiKey: '', netcupCustomerNumber: '', netcupApiKey: '', netcupApiPassword: '', ovhEndpoint: 'ovh-eu', ovhConsumerKey: '', ovhAppKey: '', ovhAppSecret: '', porkbunSecretapikey: '', porkbunApikey: '', provider: 'route53', zoneName: '', tlsConfig: { provider: 'letsencrypt-prod-wildcard' } }; $scope.setDefaultTlsProvider = function () { var dnsProvider = $scope.dnsCredentials.provider; // wildcard LE won't work without automated DNS if (dnsProvider === 'manual' || dnsProvider === 'noop' || dnsProvider === 'wildcard') { $scope.dnsCredentials.tlsConfig.provider = 'letsencrypt-prod'; } else { $scope.dnsCredentials.tlsConfig.provider = 'letsencrypt-prod-wildcard'; } }; function readFileLocally(obj, file, fileName) { return function (event) { $scope.$apply(function () { obj[file] = null; obj[fileName] = event.target.files[0].name; var reader = new FileReader(); reader.onload = function (result) { if (!result.target || !result.target.result) return console.error('Unable to read local file'); obj[file] = result.target.result; }; reader.readAsText(event.target.files[0]); }); }; } document.getElementById('gcdnsKeyFileInput').onchange = readFileLocally($scope.dnsCredentials.gcdnsKey, 'content', 'keyFileName'); $scope.setDnsCredentials = function () { $scope.dnsCredentials.busy = true; $scope.error = {}; var provider = $scope.dnsCredentials.provider; var config = {}; if (provider === 'route53') { config.accessKeyId = $scope.dnsCredentials.accessKeyId; config.secretAccessKey = $scope.dnsCredentials.secretAccessKey; } else if (provider === 'gcdns') { try { var serviceAccountKey = JSON.parse($scope.dnsCredentials.gcdnsKey.content); config.projectId = serviceAccountKey.project_id; config.credentials = { client_email: serviceAccountKey.client_email, private_key: serviceAccountKey.private_key }; if (!config.projectId || !config.credentials || !config.credentials.client_email || !config.credentials.private_key) { throw new Error('One or more fields are missing in the JSON'); } } catch (e) { $scope.error.dnsCredentials = 'Cannot parse Google Service Account Key: ' + e.message; $scope.dnsCredentials.busy = false; return; } } else if (provider === 'digitalocean') { config.token = $scope.dnsCredentials.digitalOceanToken; } else if (provider === 'gandi') { config.token = $scope.dnsCredentials.gandiApiKey; config.tokenType = $scope.dnsCredentials.gandiTokenType; } else if (provider === 'godaddy') { config.apiKey = $scope.dnsCredentials.godaddyApiKey; config.apiSecret = $scope.dnsCredentials.godaddyApiSecret; } else if (provider === 'cloudflare') { config.email = $scope.dnsCredentials.cloudflareEmail; config.token = $scope.dnsCredentials.cloudflareToken; config.tokenType = $scope.dnsCredentials.cloudflareTokenType; config.defaultProxyStatus = $scope.dnsCredentials.cloudflareDefaultProxyStatus; } else if (provider === 'linode') { config.token = $scope.dnsCredentials.linodeToken; } else if (provider === 'bunny') { config.accessKey = $scope.dnsCredentials.bunnyAccessKey; } else if (provider === 'dnsimple') { config.accessToken = $scope.dnsCredentials.dnsimpleAccessToken; } else if (provider === 'hetzner') { config.token = $scope.dnsCredentials.hetznerToken; } else if (provider === 'inwx') { config.username = $scope.dnsCredentials.inwxUsername; config.password = $scope.dnsCredentials.inwxPassword; } else if (provider === 'vultr') { config.token = $scope.dnsCredentials.vultrToken; } else if (provider === 'desec') { config.token = $scope.dnsCredentials.deSecToken; } else if (provider === 'namecom') { config.username = $scope.dnsCredentials.nameComUsername; config.token = $scope.dnsCredentials.nameComToken; } else if (provider === 'namecheap') { config.token = $scope.dnsCredentials.namecheapApiKey; config.username = $scope.dnsCredentials.namecheapUsername; } else if (provider === 'netcup') { config.customerNumber = $scope.dnsCredentials.netcupCustomerNumber; config.apiKey = $scope.dnsCredentials.netcupApiKey; config.apiPassword = $scope.dnsCredentials.netcupApiPassword; } else if (provider === 'ovh') { config.endpoint = $scope.dnsCredentials.ovhEndpoint; config.consumerKey = $scope.dnsCredentials.ovhConsumerKey; config.appKey = $scope.dnsCredentials.ovhAppKey; config.appSecret = $scope.dnsCredentials.ovhAppSecret; } else if (provider === 'porkbun') { config.apikey = $scope.dnsCredentials.porkbunApikey; config.secretapikey = $scope.dnsCredentials.porkbunSecretapikey; } var tlsConfig = { provider: $scope.dnsCredentials.tlsConfig.provider, wildcard: false }; if ($scope.dnsCredentials.tlsConfig.provider.indexOf('-wildcard') !== -1) { tlsConfig.provider = tlsConfig.provider.replace('-wildcard', ''); tlsConfig.wildcard = true; } var data = { domainConfig: { domain: $scope.dnsCredentials.domain, zoneName: $scope.dnsCredentials.zoneName, provider: provider, config: config, tlsConfig: tlsConfig }, ipv4Config: $scope.ipv4Config, ipv6Config: $scope.ipv6Config, providerToken: $scope.instanceId, setupToken: $scope.setupToken }; Client.setup(data, function (error) { if (error) { $scope.dnsCredentials.busy = false; if (error.statusCode === 422) { if (provider === 'ami') { $scope.error.ami = error.message; } else { $scope.error.setup = error.message; } } else { $scope.error.dnsCredentials = error.message; } return; } waitForDnsSetup(); }); }; function waitForDnsSetup() { $scope.state = 'waitingForDnsSetup'; Client.getProvisionStatus(function (error, status) { if (!error && !status.setup.active) { if (!status.adminFqdn || status.setup.errorMessage) { // setup reset or errored. start over $scope.error.setup = status.setup.errorMessage; $scope.state = 'initialized'; $scope.dnsCredentials.busy = false; } else { // proceed to activation window.location.href = 'https://' + status.adminFqdn + '/activation.html' + (window.location.search); } return; } if (!error) { $scope.message = status.setup.message; $scope.taskMinutesActive = (new Date() - new Date(status.setup.startTime)) / 60000; } setTimeout(waitForDnsSetup, 5000); }); } function init() { Client.getProvisionStatus(function (error, status) { $scope.state = 'waitingForBox'; if (error) return Client.initError(error, init); if (redirectIfNeeded(status, 'setup')) return; // redirected to some other view... if (status.setup.active) return waitForDnsSetup(); $scope.error.setup = status.setup.errorMessage; // show any previous error if (status.provider === 'digitalocean' || status.provider === 'digitalocean-mp') { $scope.dnsCredentials.provider = 'digitalocean'; } else if (status.provider === 'linode' || status.provider === 'linode-oneclick' || status.provider === 'linode-stackscript') { $scope.dnsCredentials.provider = 'linode'; } else if (status.provider === 'vultr' || status.provider === 'vultr-mp') { $scope.dnsCredentials.provider = 'vultr'; } else if (status.provider === 'gce') { $scope.dnsCredentials.provider = 'gcdns'; } else if (status.provider === 'ami') { // aws marketplace made a policy change that they one cannot provide route53 IAM credentials $scope.dnsCredentials.provider = 'wildcard'; } $scope.instanceId = search.instanceId; $scope.setupToken = search.setupToken; $scope.provider = status.provider; Client.detectIp(function (error, ip) { // this is never supposed to error if (!error) $scope.ipv4Config.provider = ip.ipv4 ? 'generic' : 'noop'; if (!error) $scope.ipv6Config.provider = ip.ipv6 ? 'generic' : 'noop'; $scope.state = 'initialized'; setTimeout(function () { $("[autofocus]:first").focus(); }, 100); }); }); } var clipboard = new Clipboard('.clipboard'); clipboard.on('success', function () { $scope.$apply(function () { $scope.clipboardDone = true; }); $timeout(function () { $scope.clipboardDone = false; }, 5000); }); init(); }]);