import _ from "lodash"; import { castJsonIfNeed } from "../lib/helpers.js"; import deadHostModel from "../models/dead_host.js"; import proxyHostModel from "../models/proxy_host.js"; import redirectionHostModel from "../models/redirection_host.js"; const internalHost = { /** * Makes sure that the ssl_* and hsts_* fields play nicely together. * ie: if there is no cert, then force_ssl is off. * if force_ssl is off, then hsts_enabled is definitely off. * * @param {object} data * @param {object} [existing_data] * @returns {object} */ cleanSslHstsData: (data, existingData) => { const combinedData = _.assign({}, existingData || {}, data); if (!combinedData.certificate_id) { combinedData.ssl_forced = false; combinedData.http2_support = false; } if (!combinedData.ssl_forced) { combinedData.hsts_enabled = false; } if (!combinedData.hsts_enabled) { combinedData.hsts_subdomains = false; } return combinedData; }, /** * used by the getAll functions of hosts, this removes the certificate meta if present * * @param {Array} rows * @returns {Array} */ cleanAllRowsCertificateMeta: (rows) => { rows.map((_, idx) => { if (typeof rows[idx].certificate !== "undefined" && rows[idx].certificate) { rows[idx].certificate.meta = {}; } return true; }); return rows; }, /** * used by the get/update functions of hosts, this removes the certificate meta if present * * @param {Object} row * @returns {Object} */ cleanRowCertificateMeta: (row) => { if (typeof row.certificate !== "undefined" && row.certificate) { row.certificate.meta = {}; } return row; }, /** * This returns all the host types with any domain listed in the provided domainNames array. * This is used by the certificates to temporarily disable any host that is using the domain * * @param {Array} domainNames * @returns {Promise} */ getHostsWithDomains: async (domainNames) => { const responseObject = { total_count: 0, dead_hosts: [], proxy_hosts: [], redirection_hosts: [], }; const proxyRes = await proxyHostModel.query().where("is_deleted", 0); responseObject.proxy_hosts = internalHost._getHostsWithDomains(proxyRes, domainNames); responseObject.total_count += responseObject.proxy_hosts.length; const redirRes = await redirectionHostModel.query().where("is_deleted", 0); responseObject.redirection_hosts = internalHost._getHostsWithDomains(redirRes, domainNames); responseObject.total_count += responseObject.redirection_hosts.length; const deadRes = await deadHostModel.query().where("is_deleted", 0); responseObject.dead_hosts = internalHost._getHostsWithDomains(deadRes, domainNames); responseObject.total_count += responseObject.dead_hosts.length; return responseObject; }, /** * Internal use only, checks to see if the domain is already taken by any other record * * @param {String} hostname * @param {String} [ignore_type] 'proxy', 'redirection', 'dead' * @param {Integer} [ignore_id] Must be supplied if type was also supplied * @returns {Promise} */ isHostnameTaken: (hostname, ignore_type, ignore_id) => { const promises = [ proxyHostModel .query() .where("is_deleted", 0) .andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`), redirectionHostModel .query() .where("is_deleted", 0) .andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`), deadHostModel .query() .where("is_deleted", 0) .andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`), ]; return Promise.all(promises).then((promises_results) => { let is_taken = false; if (promises_results[0]) { // Proxy Hosts if ( internalHost._checkHostnameRecordsTaken( hostname, promises_results[0], ignore_type === "proxy" && ignore_id ? ignore_id : 0, ) ) { is_taken = true; } } if (promises_results[1]) { // Redirection Hosts if ( internalHost._checkHostnameRecordsTaken( hostname, promises_results[1], ignore_type === "redirection" && ignore_id ? ignore_id : 0, ) ) { is_taken = true; } } if (promises_results[2]) { // Dead Hosts if ( internalHost._checkHostnameRecordsTaken( hostname, promises_results[2], ignore_type === "dead" && ignore_id ? ignore_id : 0, ) ) { is_taken = true; } } return { hostname: hostname, is_taken: is_taken, }; }); }, /** * Private call only * * @param {String} hostname * @param {Array} existingRows * @param {Integer} [ignoreId] * @returns {Boolean} */ _checkHostnameRecordsTaken: (hostname, existingRows, ignoreId) => { let isTaken = false; if (existingRows?.length) { existingRows.map((existingRow) => { existingRow.domain_names.map((existingHostname) => { // Does this domain match? if (existingHostname.toLowerCase() === hostname.toLowerCase()) { if (!ignoreId || ignoreId !== existingRow.id) { isTaken = true; } } return true; }); return true; }); } return isTaken; }, /** * Private call only * * @param {Array} hosts * @param {Array} domainNames * @returns {Array} */ _getHostsWithDomains: (hosts, domainNames) => { const response = []; if (hosts?.length) { hosts.map((host) => { let hostMatches = false; domainNames.map((domainName) => { host.domain_names.map((hostDomainName) => { if (domainName.toLowerCase() === hostDomainName.toLowerCase()) { hostMatches = true; } return true; }); return true; }); if (hostMatches) { response.push(host); } return true; }); } return response; }, }; export default internalHost;