host.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import _ from "lodash";
  2. import { castJsonIfNeed } from "../lib/helpers.js";
  3. import deadHostModel from "../models/dead_host.js";
  4. import proxyHostModel from "../models/proxy_host.js";
  5. import redirectionHostModel from "../models/redirection_host.js";
  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: (data, existingData) => {
  17. const combinedData = _.assign({}, existingData || {}, data);
  18. if (!combinedData.certificate_id) {
  19. combinedData.ssl_forced = false;
  20. combinedData.http2_support = false;
  21. }
  22. if (!combinedData.ssl_forced) {
  23. combinedData.hsts_enabled = false;
  24. }
  25. if (!combinedData.hsts_enabled) {
  26. combinedData.hsts_subdomains = false;
  27. }
  28. return combinedData;
  29. },
  30. /**
  31. * used by the getAll functions of hosts, this removes the certificate meta if present
  32. *
  33. * @param {Array} rows
  34. * @returns {Array}
  35. */
  36. cleanAllRowsCertificateMeta: (rows) => {
  37. rows.map((_, idx) => {
  38. if (typeof rows[idx].certificate !== "undefined" && rows[idx].certificate) {
  39. rows[idx].certificate.meta = {};
  40. }
  41. return true;
  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: (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: (domain_names) => {
  65. const promises = [
  66. proxyHostModel.query().where("is_deleted", 0),
  67. redirectionHostModel.query().where("is_deleted", 0),
  68. deadHostModel.query().where("is_deleted", 0),
  69. ];
  70. return Promise.all(promises).then((promises_results) => {
  71. const response_object = {
  72. total_count: 0,
  73. dead_hosts: [],
  74. proxy_hosts: [],
  75. redirection_hosts: [],
  76. };
  77. if (promises_results[0]) {
  78. // Proxy Hosts
  79. response_object.proxy_hosts = internalHost._getHostsWithDomains(promises_results[0], domain_names);
  80. response_object.total_count += response_object.proxy_hosts.length;
  81. }
  82. if (promises_results[1]) {
  83. // Redirection Hosts
  84. response_object.redirection_hosts = internalHost._getHostsWithDomains(
  85. promises_results[1],
  86. domain_names,
  87. );
  88. response_object.total_count += response_object.redirection_hosts.length;
  89. }
  90. if (promises_results[2]) {
  91. // Dead Hosts
  92. response_object.dead_hosts = internalHost._getHostsWithDomains(promises_results[2], domain_names);
  93. response_object.total_count += response_object.dead_hosts.length;
  94. }
  95. return response_object;
  96. });
  97. },
  98. /**
  99. * Internal use only, checks to see if the domain is already taken by any other record
  100. *
  101. * @param {String} hostname
  102. * @param {String} [ignore_type] 'proxy', 'redirection', 'dead'
  103. * @param {Integer} [ignore_id] Must be supplied if type was also supplied
  104. * @returns {Promise}
  105. */
  106. isHostnameTaken: (hostname, ignore_type, ignore_id) => {
  107. const promises = [
  108. proxyHostModel
  109. .query()
  110. .where("is_deleted", 0)
  111. .andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`),
  112. redirectionHostModel
  113. .query()
  114. .where("is_deleted", 0)
  115. .andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`),
  116. deadHostModel
  117. .query()
  118. .where("is_deleted", 0)
  119. .andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`),
  120. ];
  121. return Promise.all(promises).then((promises_results) => {
  122. let is_taken = false;
  123. if (promises_results[0]) {
  124. // Proxy Hosts
  125. if (
  126. internalHost._checkHostnameRecordsTaken(
  127. hostname,
  128. promises_results[0],
  129. ignore_type === "proxy" && ignore_id ? ignore_id : 0,
  130. )
  131. ) {
  132. is_taken = true;
  133. }
  134. }
  135. if (promises_results[1]) {
  136. // Redirection Hosts
  137. if (
  138. internalHost._checkHostnameRecordsTaken(
  139. hostname,
  140. promises_results[1],
  141. ignore_type === "redirection" && ignore_id ? ignore_id : 0,
  142. )
  143. ) {
  144. is_taken = true;
  145. }
  146. }
  147. if (promises_results[2]) {
  148. // Dead Hosts
  149. if (
  150. internalHost._checkHostnameRecordsTaken(
  151. hostname,
  152. promises_results[2],
  153. ignore_type === "dead" && ignore_id ? ignore_id : 0,
  154. )
  155. ) {
  156. is_taken = true;
  157. }
  158. }
  159. return {
  160. hostname: hostname,
  161. is_taken: is_taken,
  162. };
  163. });
  164. },
  165. /**
  166. * Private call only
  167. *
  168. * @param {String} hostname
  169. * @param {Array} existingRows
  170. * @param {Integer} [ignoreId]
  171. * @returns {Boolean}
  172. */
  173. _checkHostnameRecordsTaken: (hostname, existingRows, ignoreId) => {
  174. let isTaken = false;
  175. if (existingRows?.length) {
  176. existingRows.map((existingRow) => {
  177. existingRow.domain_names.map((existingHostname) => {
  178. // Does this domain match?
  179. if (existingHostname.toLowerCase() === hostname.toLowerCase()) {
  180. if (!ignoreId || ignoreId !== existingRow.id) {
  181. isTaken = true;
  182. }
  183. }
  184. return true;
  185. });
  186. return true;
  187. });
  188. }
  189. return isTaken;
  190. },
  191. /**
  192. * Private call only
  193. *
  194. * @param {Array} hosts
  195. * @param {Array} domainNames
  196. * @returns {Array}
  197. */
  198. _getHostsWithDomains: (hosts, domainNames) => {
  199. const response = [];
  200. if (hosts?.length) {
  201. hosts.map((host) => {
  202. let hostMatches = false;
  203. domainNames.map((domainName) => {
  204. host.domain_names.map((hostDomainName) => {
  205. if (domainName.toLowerCase() === hostDomainName.toLowerCase()) {
  206. hostMatches = true;
  207. }
  208. return true;
  209. });
  210. return true;
  211. });
  212. if (hostMatches) {
  213. response.push(host);
  214. }
  215. return true;
  216. });
  217. }
  218. return response;
  219. },
  220. };
  221. export default internalHost;