mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-11-04 01:15:14 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			235 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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;
 |