Viewing File: /usr/local/cpanel/base/frontend/jupiter/security/tls_status/views/ViewDomainsController.js
/*
* base/frontend/jupiter/security/tls_status/views/ViewDomainsController.js
* Copyright 2022 cPanel, L.L.C.
* All rights reserved.
* copyright@cpanel.net http://cpanel.net
* This code is subject to the cPanel license. Unauthorized copying is prohibited
*/
/* global define: false, PAGE: false */
/* jshint -W100, -W104 */
/* eslint-env es6 */
/* eslint camelcase: 0 */
define(
[
"angular",
"cjt/core",
"cjt/util/locale",
"cjt/util/query",
"cjt/services/fuzzy",
"uiBootstrap",
"cjt/modules",
"cjt/directives/cpanel/searchSettingsPanel",
"cjt/models/searchSettingsModel",
"app/services/DomainsService",
"cjt/directives/actionButtonDirective",
],
function(angular, CJT, LOCALE, QUERY, Fuzzy) {
"use strict";
var TLS_WIZ_URL = "security/tls_wizard/#/create";
var app = angular.module("App");
app.value("PAGE", PAGE);
var fuzzy = new Fuzzy();
app.controller("ViewDomainsController", [
"$scope",
"$timeout",
"$filter",
"$window",
"$location",
"DomainsService",
"$routeParams",
"SearchSettingsModel",
"user_domains",
"search_filter_settings",
"alertService",
"PAGE",
function ViewDomainsController($scope, $timeout, $filter, $window, $location, $service, $routeParams, SearchSettingsModel, user_domains, search_filter_settings, alertService, PAGE) {
$scope.domains = user_domains;
$scope.filteredDomains = $scope.domains;
$scope.selected_auto_ssl_domains = {
excluded: [],
included: [],
};
$scope.unsecuredDomains = [];
$scope.quickFilterValue = "";
$scope.showPager = true;
$scope.autossl_enabled = $service.is_autossl_enabled;
$scope.autoSSLErrorsExist = false;
$scope.meta = {
filterValue: "",
};
var last_descriptor = null;
$scope.datasource = {
get: function(descriptor, success) {
var result = $scope.filteredDomains.slice(Math.max(descriptor.index, 0), descriptor.index + descriptor.count);
success(result);
last_descriptor = descriptor;
last_descriptor.position = $window.pageYOffset;
},
};
// When scrolling up a lot, check number of items we are transitioning and "reload" if necessary
$scope.check_for_reload = function() {
if (!last_descriptor) {
return;
}
var new_first_item = -1;
var max_loaded = last_descriptor.index + last_descriptor.count;
if ($window.pageYOffset === 0) {
// reset to zero
new_first_item = 0;
} else {
var position = $window.pageYOffset;
var perc_scrolled = last_descriptor.position / position;
new_first_item = max_loaded * perc_scrolled;
}
// If we are skipping more than "n" items, reload
if (max_loaded - new_first_item > 200) {
// Gotta Math.max this because: Safari
new_first_item = Math.max(new_first_item, 0);
$scope.uiScrollAdapter.reload(new_first_item);
}
};
$scope.autossl_include_domains = function(domains) {
var flat_domains = domains.map(function(domain) {
domain.updating = true;
return domain.domain;
});
return $service.autossl_include_domains(flat_domains).then(function() {
alertService.add({
type: "success",
message: LOCALE.maketext("The following domains have had their [asis,AutoSSL] exclusion removed: [list_and_quoted,_1]", flat_domains),
closeable: true,
replace: false,
autoClose: 10000,
group: "tlsStatus",
});
domains.forEach(function(domain) {
domain.excluded_from_autossl = false;
domain.domain_autossl_status = "included";
domain.certificate_status_name = $service.get_certificate_status(domain);
});
}).finally(function() {
domains.forEach(function(domain) {
domain.updating = false;
});
$scope.update_auto_ssl_domains();
});
};
$scope.autossl_exclude_domains = function(domains) {
var flat_domains = domains.map(function(domain) {
domain.updating = true;
return domain.domain;
});
return $service.autossl_exclude_domains(flat_domains).then(function() {
alertService.add({
type: "success",
message: LOCALE.maketext("The following domains will now be excluded from the [asis,AutoSSL] process: [list_and_quoted,_1]", flat_domains),
closeable: true,
replace: false,
autoClose: 10000,
group: "tlsStatus",
});
domains.forEach(function(domain) {
domain.excluded_from_autossl = true;
domain.domain_autossl_status = "excluded";
domain.certificate_status_name = $service.get_certificate_status(domain);
});
}).finally(function() {
domains.forEach(function(domain) {
domain.updating = false;
});
$scope.update_auto_ssl_domains();
});
};
$scope.autossl_include_domain = function(domain) {
return $scope.autossl_include_domains([domain]);
};
$scope.autossl_exclude_domain = function(domain) {
return $scope.autossl_exclude_domains([domain]);
};
$scope.exclude_autossl_label = function(domains) {
if (domains.length === 0) {
return LOCALE.maketext("Exclude Domains from AutoSSL", domains.length);
} else {
return LOCALE.maketext("Exclude [quant,_1,Domain,Domains] from AutoSSL", domains.length);
}
};
$scope.include_autossl_label = function(domains) {
if (domains.length === 0) {
return LOCALE.maketext("Include Domains during AutoSSL", domains.length);
} else {
return LOCALE.maketext("Include [quant,_1,Domain,Domains] during AutoSSL", domains.length);
}
};
$scope.searchFilterOptions = new SearchSettingsModel(search_filter_settings);
/**
* Clears the search term
*
* @scope
* @method clearSearch
*/
$scope.clearSearch = function() {
$scope.meta.filterValue = "";
$scope.domainSearchFilterChanged();
};
$scope.filter_domains = function(domains) {
var filtered_domains = domains;
if ($scope.meta.filterValue) {
// using Fuzzy search here to not only search, but to utilize the ranked sorting.
var searchedDomains = [];
var domainMap = {};
var string_domains = domains.map(function(domain) {
domainMap[domain.domain] = domain;
return domain.domain;
});
fuzzy.loadSet(string_domains);
fuzzy.search($scope.meta.filterValue).filter(function(result) {
return result.distance < 3;
}).sort(function(a, b) {
// Re-sort using the distance AND the match
// So it's in alphabetical if they have the same distance
if (a.distance === b.distance) {
if (a.match === b.match) {
return 0;
}
return a.match < b.match ? -1 : 1;
}
return a.distance < b.distance ? -1 : 1;
}).forEach(function(fuzzyMatch) {
searchedDomains.push(domainMap[fuzzyMatch.match]);
});
filtered_domains = searchedDomains;
}
filtered_domains = $scope.searchFilterOptions.filter(filtered_domains);
return filtered_domains;
};
$scope.update_auto_ssl_domains = function() {
$scope.selected_auto_ssl_domains = {
excluded: [],
included: [],
};
angular.forEach($scope.filteredDomains, function(domain) {
if (!domain.can_autossl_exclude) {
return;
}
if (domain.selected) {
if (domain.excluded_from_autossl) {
$scope.selected_auto_ssl_domains.excluded.push(domain);
} else {
$scope.selected_auto_ssl_domains.included.push(domain);
}
}
}, $scope.selected_auto_ssl_domains);
};
$scope.searchSettingsPanelUpdated = function() {
$scope.fetch();
};
$scope.lastFetch = "";
$scope.fetch = function() {
var new_domains = $scope.domains;
new_domains = $scope.filter_domains(new_domains);
var newFetch = new_domains.map(function(domain) {
return domain.domain;
}).join("|");
// prevent some unnecessary flickering when it's showing all the domains
var domains_changed = $scope.filteredDomains.length !== $scope.domains.length || new_domains.length !== $scope.filteredDomains.length || $scope.lastFetch !== newFetch;
$scope.lastFetch = newFetch;
if (domains_changed) {
$scope.filteredDomains = new_domains;
if ($scope.uiScrollAdapter && angular.isFunction($scope.uiScrollAdapter.reload)) {
$scope.uiScrollAdapter.reload(0);
}
}
$scope.update_auto_ssl_domains();
$scope.update_showing_text();
};
$scope.no_results_msg = function() {
return LOCALE.maketext("No results found…");
};
$scope.get_advanced_filter_label = function(filterType) {
if (filterType === "displayAutoSubdomains") {
return $scope.advancedFilters.displayAutoSubdomains ? LOCALE.maketext("Yes") : LOCALE.maketext("No");
}
var filterOptions = $scope[filterType + "Options"];
if (filterOptions) {
for (var i = 0; i < filterOptions.length; i++) {
if (filterOptions[i].value === $scope.advancedFilters[filterType]) {
return filterOptions[i].label;
}
}
}
return "";
};
$scope.advanced_filters_set = function() {
if ($scope.advancedFilters.domainType !== "all" || $scope.advancedFilters.sslType !== "all" || $scope.advancedFilters.sslStatus !== "all" || !$scope.advancedFilters.displayAutoSubdomains) {
return true;
}
return false;
};
$scope.update_showing_text = function() {
$scope.showing_text = LOCALE.maketext("[output,strong,Showing] [numf,_1] of [quant,_2,domain,domains]", $scope.filteredDomains.length, $scope.domains.length);
};
$scope.get_showing_text = function() {
return $scope.showing_text;
};
$scope.view_certificate = function(domain) {
return $window.open(domain.view_crt_url);
};
$scope._get_tls_wizard_url = function(params) {
var url = TLS_WIZ_URL;
// same logic exists in _assets/MasterController.js
// exposing this as a service layer might be useful
if (url.search(/^http/i) === -1) {
if (url.search(/^\//) !== -1) {
url = CJT.getRootPath() + url;
} else {
url = CJT.buildFullPath(url);
}
}
url += "?" + QUERY.make_query_string(params);
return url;
};
// This accepts a domain object and, if the domain
// leads with “www.”, returns the object for the
// corresponding non-www domain. It falls back to the
// given domain object if there is no corresponding
// non-www domain.
//
$scope.get_root_domain = function(domain) {
var root_domain;
if (domain.domain.match(/^www\./)) {
root_domain = $scope.find_domain_by_domain(domain.domain.replace(/^www\./, ""));
}
return root_domain || domain;
};
$scope.upgrade_certificate_url = function(domain) {
if (domain) {
var params = {
domain: $scope.get_root_domain(domain).domain,
certificate_type: domain.available_upgrades,
};
return $scope._get_tls_wizard_url(params);
}
};
$scope.purchase_certificate = function(domains) {
var params = {
domain: domains.map(function(domain) {
var actual_domain = $scope.get_root_domain(domain);
return actual_domain.domain;
}),
certificate_type: ["dv", "ov", "ev"],
};
window.open($scope._get_tls_wizard_url(params), "_self");
return false;
};
$scope.domainSearchFilterChanged = function() {
if ($scope.meta.filterValue) {
$location.search("domain", $scope.meta.filterValue);
} else {
$location.search("domain", null);
}
$scope.fetch();
};
$scope.get_unsecured_domains_message = function(domains) {
return LOCALE.maketext("You have [numf,_1] unsecured parent [numerate,_1,domain,domains]. Would you like to purchase [numerate,_1,a certificate for that domain, certificates for those domains]?", domains.length);
};
$scope.getUnsecuredDomainsMessageNote = function() {
return PAGE.hasWebServerRole && LOCALE.maketext("[output,strong,Note:] The number of “parent” domains excludes the “[_1]” domains because the system automatically includes them during purchase if they pass [output,acronym,DCV,Domain Control Validation].", "www");
};
$scope.find_domain_by_domain = function(domain) {
for (var i = 0; i < $scope.domains.length; i++) {
if ($scope.domains[i].domain === domain) {
return $scope.domains[i];
}
}
};
$scope.get_domain_lock_tooltip = function(tooltip_type, is_autossl, domain_type) {
var validation_ranks = $service.get_validation_ranks();
if (validation_ranks[domain_type] > validation_ranks[tooltip_type]) {
// Hard coded "is_autossl" for tooltip purposes
return $service.get_validation_type_name(tooltip_type, false);
} else if (validation_ranks[domain_type] === validation_ranks[tooltip_type]) {
return $service.get_validation_type_name(tooltip_type, is_autossl);
}
// Hard coded "is_autossl" for tooltip purposes
if ($service.tls_wizard_can_do_validation_type(tooltip_type)) {
return LOCALE.maketext("Upgrade to [_1]", $service.get_validation_type_name(tooltip_type, false));
}
return "";
};
$scope.show_unsecured_domains = function() {
$scope.searchFilterOptions.show_only("sslType", "unsecured");
$scope.fetch();
};
$scope.get_upgrade_btn_title = function(domain) {
if (domain.upgrade_btn_title) {
return domain.upgrade_btn_title;
}
var root_domain = $scope.get_root_domain(domain);
domain.upgrade_btn_title = $service.get_upgrade_btn_title(root_domain.domain, domain.certificate);
return domain.upgrade_btn_title;
};
$scope.selectAllItems = function(allRowsSelected) {
angular.forEach($scope.filteredDomains, function(row) {
row.selected = allRowsSelected;
});
$scope.update_auto_ssl_domains();
};
$scope.getRawLogWarning = function() {
return LOCALE.maketext("Because some entries contain raw log data, the system may not translate it into the chosen language or locale.");
};
function _buildCheckCycle() {
var pollingInterval = 1000 * 60;
var messageTime = 5;
var messageTimeMs = messageTime * 1000;
$timeout(function() {
// Check the status of the AutoSSL check
$service.isAutoSSLCheckInProgress().then(function(inProgress) {
// If it's not in progress, notify and reload
if (!inProgress) {
$scope.autoSSLCheckActive = false;
alertService.add({
type: "success",
message: LOCALE.maketext("The [asis,AutoSSL] check has completed. The page will refresh in [quant,_1,second,seconds].", messageTime),
closeable: true,
replace: false,
autoClose: messageTimeMs,
group: "tlsStatus",
});
$timeout(function() {
$window.location.reload();
}, messageTimeMs);
} else {
_buildCheckCycle();
}
});
}, pollingInterval);
}
/**
* Get the label for the AutoSSL check button
*
* @method startUserAutoSSLLabel
*
* @return {String} returns the label for the current AutoSSL state
*
*/
$scope.startUserAutoSSLLabel = function() {
if ($scope.autoSSLCheckActive) {
return LOCALE.maketext("[asis,AutoSSL] is in progress …");
} else {
return LOCALE.maketext("Run [asis,AutoSSL]");
}
};
/**
* Start the AutoSSL run for this user
*
* @method startUserAutoSSL
*
* @return {Promise} returns promise, mostly for cpaction button to run for minutes
*
*/
$scope.startUserAutoSSL = function() {
$scope.autoSSLCheckActive = true;
$service.startUserAutoSSL().then(_buildCheckCycle);
};
$scope.init = function() {
if ($routeParams["domain"]) {
$scope.meta.filterValue = $routeParams["domain"];
}
angular.element($window).bind("scroll", $scope.check_for_reload);
var all_unsecured_domains = [];
$scope.domains.forEach(function(domain) {
domain.upgrade_btn_title = $scope.get_upgrade_btn_title(domain);
if (domain.certificate_type === "unsecured") {
all_unsecured_domains.push(domain);
}
});
var unsecuredActuals = [];
var uniqueDomains = {};
angular.forEach(all_unsecured_domains, function(domain) {
// Do not include DDNS subdomains
if (domain.isDDNS) {
return;
}
var actual_domain = $scope.get_root_domain(domain);
if (actual_domain.certificate_type !== "unsecured") {
return false;
}
if (actual_domain && !uniqueDomains[actual_domain.domain]) {
uniqueDomains[actual_domain.domain] = actual_domain;
unsecuredActuals.push(actual_domain);
}
});
$scope.market_products_available = $service.areMarketProductsAvailable();
$scope.unsecuredDomains = unsecuredActuals;
$scope.fetch();
if ( $service.is_autossl_enabled() ) {
$timeout(function() {
// Load AutoSSL Logs
$service.getAutoSSLStatuses().then(function(statuses) {
statuses.forEach(function(status) {
var domainObj = $scope.find_domain_by_domain(status.domain);
if (!domainObj) {
return;
}
domainObj.autoSSLStatus = status;
if (status.error) {
$scope.autoSSLErrorsExist = true;
domainObj.certificate_status = "has_autossl_problem";
domainObj.autoSSLStatus.lastRunMessage = LOCALE.maketext("An error occurred the last time [asis,AutoSSL] ran, on [local_datetime,_1]:", domainObj.autoSSLStatus.runTime.getTime() / 1000);
} else {
domainObj.autoSSLStatus.lastRunMessage = LOCALE.maketext("[asis,AutoSSL] last ran on [local_datetime,_1].", domainObj.autoSSLStatus.runTime.getTime() / 1000);
}
});
// Necessary because expired >> has_autossl_problem will continue to show if filtered as such until this is refreshed
$scope.fetch();
});
$service.isAutoSSLCheckInProgress().then(function(inProgress) {
$scope.initialAutoSSLCheckComplete = true;
$scope.autoSSLCheckActive = inProgress;
if ($scope.autoSSLCheckActive) {
_buildCheckCycle();
}
});
}, 50);
}
};
$scope.$on("$destroy", function() {
angular.element($window).unbind("scroll", $scope.check_for_reload);
});
$scope.init();
},
]);
});
Back to Directory
File Manager