host.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. const _ = require('lodash');
  2. const proxyHostModel = require('../models/proxy_host');
  3. const redirectionHostModel = require('../models/redirection_host');
  4. const deadHostModel = require('../models/dead_host');
  5. const sslPassthroughHostModel = require('../models/ssl_passthrough_host');
  6. const internalHost = {
  7. /**
  8. * Makes sure that the ssl_* and hsts_* fields play nicely together.
  9. * ie: if there is no cert, then force_ssl is off.
  10. * if force_ssl is off, then hsts_enabled is definitely off.
  11. *
  12. * @param {object} data
  13. * @param {object} [existing_data]
  14. * @returns {object}
  15. */
  16. cleanSslHstsData: function (data, existing_data) {
  17. existing_data = existing_data === undefined ? {} : existing_data;
  18. let combined_data = _.assign({}, existing_data, data);
  19. if (!combined_data.certificate_id) {
  20. combined_data.ssl_forced = false;
  21. combined_data.http2_support = false;
  22. }
  23. if (!combined_data.ssl_forced) {
  24. combined_data.hsts_enabled = false;
  25. }
  26. if (!combined_data.hsts_enabled) {
  27. combined_data.hsts_subdomains = false;
  28. }
  29. return combined_data;
  30. },
  31. /**
  32. * used by the getAll functions of hosts, this removes the certificate meta if present
  33. *
  34. * @param {Array} rows
  35. * @returns {Array}
  36. */
  37. cleanAllRowsCertificateMeta: function (rows) {
  38. rows.map(function (row, idx) {
  39. if (typeof rows[idx].certificate !== 'undefined' && rows[idx].certificate) {
  40. rows[idx].certificate.meta = {};
  41. }
  42. });
  43. return rows;
  44. },
  45. /**
  46. * used by the get/update functions of hosts, this removes the certificate meta if present
  47. *
  48. * @param {Object} row
  49. * @returns {Object}
  50. */
  51. cleanRowCertificateMeta: function (row) {
  52. if (typeof row.certificate !== 'undefined' && row.certificate) {
  53. row.certificate.meta = {};
  54. }
  55. return row;
  56. },
  57. /**
  58. * This returns all the host types with any domain listed in the provided domain_names array.
  59. * This is used by the certificates to temporarily disable any host that is using the domain
  60. *
  61. * @param {Array} domain_names
  62. * @returns {Promise}
  63. */
  64. getHostsWithDomains: function (domain_names) {
  65. let promises = [
  66. proxyHostModel
  67. .query()
  68. .where('is_deleted', 0),
  69. redirectionHostModel
  70. .query()
  71. .where('is_deleted', 0),
  72. deadHostModel
  73. .query()
  74. .where('is_deleted', 0),
  75. sslPassthroughHostModel
  76. .query()
  77. .where('is_deleted', 0)
  78. ];
  79. return Promise.all(promises)
  80. .then((promises_results) => {
  81. let response_object = {
  82. total_count: 0,
  83. dead_hosts: [],
  84. proxy_hosts: [],
  85. redirection_hosts: []
  86. };
  87. if (promises_results[0]) {
  88. // Proxy Hosts
  89. response_object.proxy_hosts = internalHost._getHostsWithDomains(promises_results[0], domain_names);
  90. response_object.total_count += response_object.proxy_hosts.length;
  91. }
  92. if (promises_results[1]) {
  93. // Redirection Hosts
  94. response_object.redirection_hosts = internalHost._getHostsWithDomains(promises_results[1], domain_names);
  95. response_object.total_count += response_object.redirection_hosts.length;
  96. }
  97. if (promises_results[2]) {
  98. // Dead Hosts
  99. response_object.dead_hosts = internalHost._getHostsWithDomains(promises_results[2], domain_names);
  100. response_object.total_count += response_object.dead_hosts.length;
  101. }
  102. if (promises_results[3]) {
  103. // SSL Passthrough Hosts
  104. response_object.ssl_passthrough_hosts = internalHost._getHostsWithDomains(promises_results[3], domain_names);
  105. response_object.total_count += response_object.ssl_passthrough_hosts.length;
  106. }
  107. return response_object;
  108. });
  109. },
  110. /**
  111. * Internal use only, checks to see if the domain is already taken by any other record
  112. *
  113. * @param {String} hostname
  114. * @param {String} [ignore_type] 'proxy', 'redirection', 'dead'
  115. * @param {Integer} [ignore_id] Must be supplied if type was also supplied
  116. * @returns {Promise}
  117. */
  118. isHostnameTaken: function (hostname, ignore_type, ignore_id) {
  119. let promises = [
  120. proxyHostModel
  121. .query()
  122. .where('is_deleted', 0)
  123. .andWhere('domain_names', 'like', '%' + hostname + '%'),
  124. redirectionHostModel
  125. .query()
  126. .where('is_deleted', 0)
  127. .andWhere('domain_names', 'like', '%' + hostname + '%'),
  128. deadHostModel
  129. .query()
  130. .where('is_deleted', 0)
  131. .andWhere('domain_names', 'like', '%' + hostname + '%'),
  132. sslPassthroughHostModel
  133. .query()
  134. .where('is_deleted', 0)
  135. .andWhere('domain_name', '=', hostname),
  136. ];
  137. return Promise.all(promises)
  138. .then((promises_results) => {
  139. let is_taken = false;
  140. if (promises_results[0]) {
  141. // Proxy Hosts
  142. if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[0], ignore_type === 'proxy' && ignore_id ? ignore_id : 0)) {
  143. is_taken = true;
  144. }
  145. }
  146. if (promises_results[1]) {
  147. // Redirection Hosts
  148. if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[1], ignore_type === 'redirection' && ignore_id ? ignore_id : 0)) {
  149. is_taken = true;
  150. }
  151. }
  152. if (promises_results[2]) {
  153. // Dead Hosts
  154. if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[2], ignore_type === 'dead' && ignore_id ? ignore_id : 0)) {
  155. is_taken = true;
  156. }
  157. }
  158. if (promises_results[3]) {
  159. // SSL Passthrough Hosts
  160. if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[3], ignore_type === 'ssl_passthrough' && ignore_id ? ignore_id : 0)) {
  161. is_taken = true;
  162. }
  163. }
  164. return {
  165. hostname: hostname,
  166. is_taken: is_taken
  167. };
  168. });
  169. },
  170. /**
  171. * Private call only
  172. *
  173. * @param {String} hostname
  174. * @param {Array} existing_rows
  175. * @param {Integer} [ignore_id]
  176. * @returns {Boolean}
  177. */
  178. _checkHostnameRecordsTaken: function (hostname, existing_rows, ignore_id) {
  179. let is_taken = false;
  180. if (existing_rows && existing_rows.length) {
  181. existing_rows.map(function (existing_row) {
  182. function checkHostname(existing_hostname) {
  183. // Does this domain match?
  184. if (existing_hostname.toLowerCase() === hostname.toLowerCase()) {
  185. if (!ignore_id || ignore_id !== existing_row.id) {
  186. is_taken = true;
  187. }
  188. }
  189. }
  190. if (existing_row.domain_names) {
  191. existing_row.domain_names.map(checkHostname);
  192. } else if (existing_row.domain_name) {
  193. checkHostname(existing_row.domain_name);
  194. }
  195. });
  196. }
  197. return is_taken;
  198. },
  199. /**
  200. * Private call only
  201. *
  202. * @param {Array} hosts
  203. * @param {Array} domain_names
  204. * @returns {Array}
  205. */
  206. _getHostsWithDomains: function (hosts, domain_names) {
  207. let response = [];
  208. if (hosts && hosts.length) {
  209. hosts.map(function (host) {
  210. let host_matches = false;
  211. domain_names.map(function (domain_name) {
  212. host.domain_names.map(function (host_domain_name) {
  213. if (domain_name.toLowerCase() === host_domain_name.toLowerCase()) {
  214. host_matches = true;
  215. }
  216. });
  217. });
  218. if (host_matches) {
  219. response.push(host);
  220. }
  221. });
  222. }
  223. return response;
  224. }
  225. };
  226. module.exports = internalHost;