Ver Fonte

Refactor from Promises to async/await

Jamie Curnow há 3 meses atrás
pai
commit
038de3e5f9

+ 349 - 414
backend/internal/access-list.js

@@ -21,88 +21,74 @@ const internalAccessList = {
 	 * @param   {Object}  data
 	 * @returns {Promise}
 	 */
-	create: (access, data) => {
-		return access
-			.can("access_lists:create", data)
-			.then((/*access_data*/) => {
-				return accessListModel
-					.query()
-					.insertAndFetch({
-						name: data.name,
-						satisfy_any: data.satisfy_any,
-						pass_auth: data.pass_auth,
-						owner_user_id: access.token.getUserId(1),
-					})
-					.then(utils.omitRow(omissions()));
+	create: async (access, data) => {
+		await access.can("access_lists:create", data);
+		const row = await accessListModel
+			.query()
+			.insertAndFetch({
+				name: data.name,
+				satisfy_any: data.satisfy_any,
+				pass_auth: data.pass_auth,
+				owner_user_id: access.token.getUserId(1),
 			})
-			.then((row) => {
-				data.id = row.id;
+			.then(utils.omitRow(omissions()));
+
+		data.id = row.id;
+
+		const promises = [];
+		// Items
+		data.items.map((item) => {
+			promises.push(
+				accessListAuthModel.query().insert({
+					access_list_id: row.id,
+					username: item.username,
+					password: item.password,
+				}),
+			);
+			return true;
+		});
 
-				const promises = [];
+		// Clients
+		data.clients?.map((client) => {
+			promises.push(
+				accessListClientModel.query().insert({
+					access_list_id: row.id,
+					address: client.address,
+					directive: client.directive,
+				}),
+			);
+			return true;
+		});
 
-				// Now add the items
-				data.items.map((item) => {
-					promises.push(
-						accessListAuthModel.query().insert({
-							access_list_id: row.id,
-							username: item.username,
-							password: item.password,
-						}),
-					);
-					return true;
-				});
-
-				// Now add the clients
-				if (typeof data.clients !== "undefined" && data.clients) {
-					data.clients.map((client) => {
-						promises.push(
-							accessListClientModel.query().insert({
-								access_list_id: row.id,
-								address: client.address,
-								directive: client.directive,
-							}),
-						);
-						return true;
-					});
-				}
+		await Promise.all(promises);
 
-				return Promise.all(promises);
-			})
-			.then(() => {
-				// re-fetch with expansions
-				return internalAccessList.get(
-					access,
-					{
-						id: data.id,
-						expand: ["owner", "items", "clients", "proxy_hosts.access_list.[clients,items]"],
-					},
-					true /* <- skip masking */,
-				);
-			})
-			.then((row) => {
-				// Audit log
-				data.meta = _.assign({}, data.meta || {}, row.meta);
-
-				return internalAccessList
-					.build(row)
-					.then(() => {
-						if (Number.parseInt(row.proxy_host_count, 10)) {
-							return internalNginx.bulkGenerateConfigs("proxy_host", row.proxy_hosts);
-						}
-					})
-					.then(() => {
-						// Add to audit log
-						return internalAuditLog.add(access, {
-							action: "created",
-							object_type: "access-list",
-							object_id: row.id,
-							meta: internalAccessList.maskItems(data),
-						});
-					})
-					.then(() => {
-						return internalAccessList.maskItems(row);
-					});
-			});
+		// re-fetch with expansions
+		const freshRow = await internalAccessList.get(
+			access,
+			{
+				id: data.id,
+				expand: ["owner", "items", "clients", "proxy_hosts.access_list.[clients,items]"],
+			},
+			true // skip masking
+		);
+
+		// Audit log
+		data.meta = _.assign({}, data.meta || {}, freshRow.meta);
+		await internalAccessList.build(freshRow);
+
+		if (Number.parseInt(freshRow.proxy_host_count, 10)) {
+			await internalNginx.bulkGenerateConfigs("proxy_host", freshRow.proxy_hosts);
+		}
+
+		// Add to audit log
+		await internalAuditLog.add(access, {
+			action: "created",
+			object_type: "access-list",
+			object_id: freshRow.id,
+			meta: internalAccessList.maskItems(data),
+		});
+
+		return internalAccessList.maskItems(freshRow);
 	},
 
 	/**
@@ -113,127 +99,107 @@ const internalAccessList = {
 	 * @param  {String}  [data.items]
 	 * @return {Promise}
 	 */
-	update: (access, data) => {
-		return access
-			.can("access_lists:update", data.id)
-			.then((/*access_data*/) => {
-				return internalAccessList.get(access, { id: data.id });
-			})
-			.then((row) => {
-				if (row.id !== data.id) {
-					// Sanity check that something crazy hasn't happened
-					throw new errs.InternalValidationError(
-						`Access List could not be updated, IDs do not match: ${row.id} !== ${data.id}`,
-					);
-				}
-			})
-			.then(() => {
-				// patch name if specified
-				if (typeof data.name !== "undefined" && data.name) {
-					return accessListModel.query().where({ id: data.id }).patch({
-						name: data.name,
-						satisfy_any: data.satisfy_any,
-						pass_auth: data.pass_auth,
-					});
-				}
-			})
-			.then(() => {
-				// Check for items and add/update/remove them
-				if (typeof data.items !== "undefined" && data.items) {
-					const promises = [];
-					const items_to_keep = [];
-
-					data.items.map((item) => {
-						if (item.password) {
-							promises.push(
-								accessListAuthModel.query().insert({
-									access_list_id: data.id,
-									username: item.username,
-									password: item.password,
-								}),
-							);
-						} else {
-							// This was supplied with an empty password, which means keep it but don't change the password
-							items_to_keep.push(item.username);
-						}
-						return true;
-					});
+	update: async (access, data) => {
+		await access.can("access_lists:update", data.id);
+		const row = await internalAccessList.get(access, { id: data.id });
+		if (row.id !== data.id) {
+			// Sanity check that something crazy hasn't happened
+			throw new errs.InternalValidationError(
+				`Access List could not be updated, IDs do not match: ${row.id} !== ${data.id}`,
+			);
+		}
 
-					const query = accessListAuthModel.query().delete().where("access_list_id", data.id);
+		// patch name if specified
+		if (typeof data.name !== "undefined" && data.name) {
+			await accessListModel.query().where({ id: data.id }).patch({
+				name: data.name,
+				satisfy_any: data.satisfy_any,
+				pass_auth: data.pass_auth,
+			});
+		}
 
-					if (items_to_keep.length) {
-						query.andWhere("username", "NOT IN", items_to_keep);
-					}
+		// Check for items and add/update/remove them
+		if (typeof data.items !== "undefined" && data.items) {
+			const promises = [];
+			const itemsToKeep = [];
 
-					return query.then(() => {
-						// Add new items
-						if (promises.length) {
-							return Promise.all(promises);
-						}
-					});
+			data.items.map((item) => {
+				if (item.password) {
+					promises.push(
+						accessListAuthModel.query().insert({
+							access_list_id: data.id,
+							username: item.username,
+							password: item.password,
+						}),
+					);
+				} else {
+					// This was supplied with an empty password, which means keep it but don't change the password
+					itemsToKeep.push(item.username);
 				}
-			})
-			.then(() => {
-				// Check for clients and add/update/remove them
-				if (typeof data.clients !== "undefined" && data.clients) {
-					const promises = [];
-
-					data.clients.map((client) => {
-						if (client.address) {
-							promises.push(
-								accessListClientModel.query().insert({
-									access_list_id: data.id,
-									address: client.address,
-									directive: client.directive,
-								}),
-							);
-						}
-						return true;
-					});
+				return true;
+			});
 
-					const query = accessListClientModel.query().delete().where("access_list_id", data.id);
+			const query = accessListAuthModel.query().delete().where("access_list_id", data.id);
 
-					return query.then(() => {
-						// Add new items
-						if (promises.length) {
-							return Promise.all(promises);
-						}
-					});
+			if (itemsToKeep.length) {
+				query.andWhere("username", "NOT IN", itemsToKeep);
+			}
+
+			await query;
+			// Add new items
+			if (promises.length) {
+				await Promise.all(promises);
+			}
+		}
+
+		// Check for clients and add/update/remove them
+		if (typeof data.clients !== "undefined" && data.clients) {
+			const clientPromises = [];
+			data.clients.map((client) => {
+				if (client.address) {
+					clientPromises.push(
+						accessListClientModel.query().insert({
+							access_list_id: data.id,
+							address: client.address,
+							directive: client.directive,
+						}),
+					);
 				}
-			})
-			.then(() => {
-				// Add to audit log
-				return internalAuditLog.add(access, {
-					action: "updated",
-					object_type: "access-list",
-					object_id: data.id,
-					meta: internalAccessList.maskItems(data),
-				});
-			})
-			.then(() => {
-				// re-fetch with expansions
-				return internalAccessList.get(
-					access,
-					{
-						id: data.id,
-						expand: ["owner", "items", "clients", "proxy_hosts.[certificate,access_list.[clients,items]]"],
-					},
-					true /* <- skip masking */,
-				);
-			})
-			.then((row) => {
-				return internalAccessList
-					.build(row)
-					.then(() => {
-						if (Number.parseInt(row.proxy_host_count, 10)) {
-							return internalNginx.bulkGenerateConfigs("proxy_host", row.proxy_hosts);
-						}
-					})
-					.then(internalNginx.reload)
-					.then(() => {
-						return internalAccessList.maskItems(row);
-					});
+				return true;
 			});
+
+			const query = accessListClientModel.query().delete().where("access_list_id", data.id);
+			await query;
+			// Add new clitens
+			if (clientPromises.length) {
+				await Promise.all(clientPromises);
+			}
+		}
+
+		// Add to audit log
+		await internalAuditLog.add(access, {
+			action: "updated",
+			object_type: "access-list",
+			object_id: data.id,
+			meta: internalAccessList.maskItems(data),
+		});
+
+		// re-fetch with expansions
+		const freshRow = await internalAccessList.get(
+			access,
+			{
+				id: data.id,
+				expand: ["owner", "items", "clients", "proxy_hosts.[certificate,access_list.[clients,items]]"],
+			},
+			true // skip masking
+		);
+
+		await internalAccessList.build(freshRow)
+		if (Number.parseInt(row.proxy_host_count, 10)) {
+			await internalNginx.bulkGenerateConfigs("proxy_host", row.proxy_hosts);
+		}
+		await internalNginx.reload();
+		return internalAccessList.maskItems(row);
 	},
 
 	/**
@@ -242,55 +208,50 @@ const internalAccessList = {
 	 * @param  {Integer}  data.id
 	 * @param  {Array}    [data.expand]
 	 * @param  {Array}    [data.omit]
-	 * @param  {Boolean}  [skip_masking]
+	 * @param  {Boolean}  [skipMasking]
 	 * @return {Promise}
 	 */
-	get: (access, data, skip_masking) => {
+	get: async (access, data, skipMasking) => {
 		const thisData = data || {};
+		const accessData = await access.can("access_lists:get", thisData.id)
+
+		const query = accessListModel
+			.query()
+			.select("access_list.*", accessListModel.raw("COUNT(proxy_host.id) as proxy_host_count"))
+			.leftJoin("proxy_host", function () {
+				this.on("proxy_host.access_list_id", "=", "access_list.id").andOn(
+					"proxy_host.is_deleted",
+					"=",
+					0,
+				);
+			})
+			.where("access_list.is_deleted", 0)
+			.andWhere("access_list.id", thisData.id)
+			.groupBy("access_list.id")
+			.allowGraph("[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]")
+			.first();
+
+		if (accessData.permission_visibility !== "all") {
+			query.andWhere("access_list.owner_user_id", access.token.getUserId(1));
+		}
 
-		return access
-			.can("access_lists:get", thisData.id)
-			.then((accessData) => {
-				const query = accessListModel
-					.query()
-					.select("access_list.*", accessListModel.raw("COUNT(proxy_host.id) as proxy_host_count"))
-					.leftJoin("proxy_host", function () {
-						this.on("proxy_host.access_list_id", "=", "access_list.id").andOn(
-							"proxy_host.is_deleted",
-							"=",
-							0,
-						);
-					})
-					.where("access_list.is_deleted", 0)
-					.andWhere("access_list.id", thisData.id)
-					.groupBy("access_list.id")
-					.allowGraph("[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]")
-					.first();
-
-				if (accessData.permission_visibility !== "all") {
-					query.andWhere("access_list.owner_user_id", access.token.getUserId(1));
-				}
+		if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
+			query.withGraphFetched(`[${thisData.expand.join(", ")}]`);
+		}
 
-				if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
-					query.withGraphFetched(`[${thisData.expand.join(", ")}]`);
-				}
+		let row = await query.then(utils.omitRow(omissions()));
 
-				return query.then(utils.omitRow(omissions()));
-			})
-			.then((row) => {
-				let thisRow = row;
-				if (!row || !row.id) {
-					throw new errs.ItemNotFoundError(thisData.id);
-				}
-				if (!skip_masking && typeof thisRow.items !== "undefined" && thisRow.items) {
-					thisRow = internalAccessList.maskItems(thisRow);
-				}
-				// Custom omissions
-				if (typeof data.omit !== "undefined" && data.omit !== null) {
-					thisRow = _.omit(thisRow, data.omit);
-				}
-				return thisRow;
-			});
+		if (!row || !row.id) {
+			throw new errs.ItemNotFoundError(thisData.id);
+		}
+		if (!skipMasking && typeof row.items !== "undefined" && row.items) {
+			row = internalAccessList.maskItems(row);
+		}
+		// Custom omissions
+		if (typeof data.omit !== "undefined" && data.omit !== null) {
+			row = _.omit(row, data.omit);
+		}
+		return row;
 	},
 
 	/**
@@ -300,75 +261,64 @@ const internalAccessList = {
 	 * @param   {String}  [data.reason]
 	 * @returns {Promise}
 	 */
-	delete: (access, data) => {
-		return access
-			.can("access_lists:delete", data.id)
-			.then(() => {
-				return internalAccessList.get(access, { id: data.id, expand: ["proxy_hosts", "items", "clients"] });
-			})
-			.then((row) => {
-				if (!row || !row.id) {
-					throw new errs.ItemNotFoundError(data.id);
-				}
+	delete: async (access, data) => {
+		await access.can("access_lists:delete", data.id);
+		const row = await internalAccessList.get(access, {
+			id: data.id,
+			expand: ["proxy_hosts", "items", "clients"],
+		});
 
-				// 1. update row to be deleted
-				// 2. update any proxy hosts that were using it (ignoring permissions)
-				// 3. reconfigure those hosts
-				// 4. audit log
-
-				// 1. update row to be deleted
-				return accessListModel
-					.query()
-					.where("id", row.id)
-					.patch({
-						is_deleted: 1,
-					})
-					.then(() => {
-						// 2. update any proxy hosts that were using it (ignoring permissions)
-						if (row.proxy_hosts) {
-							return proxyHostModel
-								.query()
-								.where("access_list_id", "=", row.id)
-								.patch({ access_list_id: 0 })
-								.then(() => {
-									// 3. reconfigure those hosts, then reload nginx
-
-									// set the access_list_id to zero for these items
-									row.proxy_hosts.map((_val, idx) => {
-										row.proxy_hosts[idx].access_list_id = 0;
-										return true;
-									});
-
-									return internalNginx.bulkGenerateConfigs("proxy_host", row.proxy_hosts);
-								})
-								.then(() => {
-									return internalNginx.reload();
-								});
-						}
-					})
-					.then(() => {
-						// delete the htpasswd file
-						const htpasswd_file = internalAccessList.getFilename(row);
-
-						try {
-							fs.unlinkSync(htpasswd_file);
-						} catch (_err) {
-							// do nothing
-						}
-					})
-					.then(() => {
-						// 4. audit log
-						return internalAuditLog.add(access, {
-							action: "deleted",
-							object_type: "access-list",
-							object_id: row.id,
-							meta: _.omit(internalAccessList.maskItems(row), ["is_deleted", "proxy_hosts"]),
-						});
-					});
-			})
-			.then(() => {
+		if (!row || !row.id) {
+			throw new errs.ItemNotFoundError(data.id);
+		}
+
+		// 1. update row to be deleted
+		// 2. update any proxy hosts that were using it (ignoring permissions)
+		// 3. reconfigure those hosts
+		// 4. audit log
+
+		// 1. update row to be deleted
+		await accessListModel
+			.query()
+			.where("id", row.id)
+			.patch({
+				is_deleted: 1,
+			});
+
+		// 2. update any proxy hosts that were using it (ignoring permissions)
+		if (row.proxy_hosts) {
+			await proxyHostModel
+				.query()
+				.where("access_list_id", "=", row.id)
+				.patch({ access_list_id: 0 });
+
+			// 3. reconfigure those hosts, then reload nginx
+			// set the access_list_id to zero for these items
+			row.proxy_hosts.map((_val, idx) => {
+				row.proxy_hosts[idx].access_list_id = 0;
 				return true;
 			});
+
+			await internalNginx.bulkGenerateConfigs("proxy_host", row.proxy_hosts);
+		}
+
+		await internalNginx.reload();
+
+		// delete the htpasswd file
+		try {
+			fs.unlinkSync(internalAccessList.getFilename(row));
+		} catch (_err) {
+			// do nothing
+		}
+
+		// 4. audit log
+		await internalAuditLog.add(access, {
+			action: "deleted",
+			object_type: "access-list",
+			object_id: row.id,
+			meta: _.omit(internalAccessList.maskItems(row), ["is_deleted", "proxy_hosts"]),
+		});
+		return true;
 	},
 
 	/**
@@ -376,76 +326,73 @@ const internalAccessList = {
 	 *
 	 * @param   {Access}  access
 	 * @param   {Array}   [expand]
-	 * @param   {String}  [search_query]
+	 * @param   {String}  [searchQuery]
 	 * @returns {Promise}
 	 */
-	getAll: (access, expand, search_query) => {
-		return access
-			.can("access_lists:list")
-			.then((access_data) => {
-				const query = accessListModel
-					.query()
-					.select("access_list.*", accessListModel.raw("COUNT(proxy_host.id) as proxy_host_count"))
-					.leftJoin("proxy_host", function () {
-						this.on("proxy_host.access_list_id", "=", "access_list.id").andOn(
-							"proxy_host.is_deleted",
-							"=",
-							0,
-						);
-					})
-					.where("access_list.is_deleted", 0)
-					.groupBy("access_list.id")
-					.allowGraph("[owner,items,clients]")
-					.orderBy("access_list.name", "ASC");
+	getAll: async (access, expand, searchQuery) => {
+		const accessData = await access.can("access_lists:list");
+
+		const query = accessListModel
+			.query()
+			.select("access_list.*", accessListModel.raw("COUNT(proxy_host.id) as proxy_host_count"))
+			.leftJoin("proxy_host", function () {
+				this.on("proxy_host.access_list_id", "=", "access_list.id").andOn(
+					"proxy_host.is_deleted",
+					"=",
+					0,
+				);
+			})
+			.where("access_list.is_deleted", 0)
+			.groupBy("access_list.id")
+			.allowGraph("[owner,items,clients]")
+			.orderBy("access_list.name", "ASC");
 
-				if (access_data.permission_visibility !== "all") {
-					query.andWhere("access_list.owner_user_id", access.token.getUserId(1));
-				}
+		if (accessData.permission_visibility !== "all") {
+			query.andWhere("access_list.owner_user_id", access.token.getUserId(1));
+		}
 
-				// Query is used for searching
-				if (typeof search_query === "string") {
-					query.where(function () {
-						this.where("name", "like", `%${search_query}%`);
-					});
-				}
+		// Query is used for searching
+		if (typeof searchQuery === "string") {
+			query.where(function () {
+				this.where("name", "like", `%${searchQuery}%`);
+			});
+		}
 
-				if (typeof expand !== "undefined" && expand !== null) {
-					query.withGraphFetched(`[${expand.join(", ")}]`);
-				}
+		if (typeof expand !== "undefined" && expand !== null) {
+			query.withGraphFetched(`[${expand.join(", ")}]`);
+		}
 
-				return query.then(utils.omitRows(omissions()));
-			})
-			.then((rows) => {
-				if (rows) {
-					rows.map((row, idx) => {
-						if (typeof row.items !== "undefined" && row.items) {
-							rows[idx] = internalAccessList.maskItems(row);
-						}
-						return true;
-					});
+		const rows = await query.then(utils.omitRows(omissions()));
+		if (rows) {
+			rows.map((row, idx) => {
+				if (typeof row.items !== "undefined" && row.items) {
+					rows[idx] = internalAccessList.maskItems(row);
 				}
-
-				return rows;
+				return true;
 			});
+		}
+		return rows;
 	},
 
 	/**
-	 * Report use
+	 * Count is used in reports
 	 *
-	 * @param   {Integer} user_id
+	 * @param   {Integer} userId
 	 * @param   {String}  visibility
 	 * @returns {Promise}
 	 */
-	getCount: (user_id, visibility) => {
-		const query = accessListModel.query().count("id as count").where("is_deleted", 0);
+	getCount: async (userId, visibility) => {
+		const query = accessListModel
+			.query()
+			.count("id as count")
+			.where("is_deleted", 0);
 
 		if (visibility !== "all") {
-			query.andWhere("owner_user_id", user_id);
+			query.andWhere("owner_user_id", userId);
 		}
 
-		return query.first().then((row) => {
-			return Number.parseInt(row.count, 10);
-		});
+		const row = await query.first();
+		return Number.parseInt(row.count, 10);
 	},
 
 	/**
@@ -455,20 +402,19 @@ const internalAccessList = {
 	maskItems: (list) => {
 		if (list && typeof list.items !== "undefined") {
 			list.items.map((val, idx) => {
-				let repeat_for = 8;
-				let first_char = "*";
+				let repeatFor = 8;
+				let firstChar = "*";
 
 				if (typeof val.password !== "undefined" && val.password) {
-					repeat_for = val.password.length - 1;
-					first_char = val.password.charAt(0);
+					repeatFor = val.password.length - 1;
+					firstChar = val.password.charAt(0);
 				}
 
-				list.items[idx].hint = first_char + "*".repeat(repeat_for);
+				list.items[idx].hint = firstChar + "*".repeat(repeatFor);
 				list.items[idx].password = "";
 				return true;
 			});
 		}
-
 		return list;
 	},
 
@@ -488,66 +434,55 @@ const internalAccessList = {
 	 * @param   {Array}   list.items
 	 * @returns {Promise}
 	 */
-	build: (list) => {
+	build: async (list) => {
 		logger.info(`Building Access file #${list.id} for: ${list.name}`);
 
-		return new Promise((resolve, reject) => {
-			const htpasswd_file = internalAccessList.getFilename(list);
+		const htpasswdFile = internalAccessList.getFilename(list);
 
-			// 1. remove any existing access file
-			try {
-				fs.unlinkSync(htpasswd_file);
-			} catch (_err) {
-				// do nothing
-			}
+		// 1. remove any existing access file
+		try {
+			fs.unlinkSync(htpasswdFile);
+		} catch (_err) {
+			// do nothing
+		}
 
-			// 2. create empty access file
-			try {
-				fs.writeFileSync(htpasswd_file, "", { encoding: "utf8" });
-				resolve(htpasswd_file);
-			} catch (err) {
-				reject(err);
-			}
-		}).then((htpasswd_file) => {
-			// 3. generate password for each user
-			if (list.items.length) {
-				return new Promise((resolve, reject) => {
-					batchflow(list.items)
-						.sequential()
-						.each((_i, item, next) => {
-							if (item.password?.length) {
-								logger.info(`Adding: ${item.username}`);
-
-								utils
-									.execFile("openssl", ["passwd", "-apr1", item.password])
-									.then((res) => {
-										try {
-											fs.appendFileSync(htpasswd_file, `${item.username}:${res}\n`, {
-												encoding: "utf8",
-											});
-										} catch (err) {
-											reject(err);
-										}
-										next();
-									})
-									.catch((err) => {
-										logger.error(err);
-										next(err);
-									});
-							}
-						})
-						.error((err) => {
-							logger.error(err);
-							reject(err);
-						})
-						.end((results) => {
-							logger.success(`Built Access file #${list.id} for: ${list.name}`);
-							resolve(results);
-						});
-				});
-			}
-		});
-	},
-};
+		// 2. create empty access file
+		fs.writeFileSync(htpasswdFile, '', {encoding: 'utf8'});
+
+		// 3. generate password for each user
+		if (list.items.length) {
+			await new Promise((resolve, reject) => {
+				batchflow(list.items).sequential()
+					.each((_i, item, next) => {
+						if (item.password?.length) {
+							logger.info(`Adding: ${item.username}`);
+
+							utils.execFile('openssl', ['passwd', '-apr1', item.password])
+								.then((res) => {
+									try {
+										fs.appendFileSync(htpasswdFile, `${item.username}:${res}\n`, {encoding: 'utf8'});
+									} catch (err) {
+										reject(err);
+									}
+									next();
+								})
+								.catch((err) => {
+									logger.error(err);
+									next(err);
+								});
+						}
+					})
+					.error((err) => {
+						logger.error(err);
+						reject(err);
+					})
+					.end((results) => {
+						logger.success(`Built Access file #${list.id} for: ${list.name}`);
+						resolve(results);
+					});
+			});
+		}
+	}
+}
 
 export default internalAccessList;

+ 35 - 40
backend/internal/audit-log.js

@@ -9,31 +9,31 @@ const internalAuditLog = {
 	 *
 	 * @param   {Access}  access
 	 * @param   {Array}   [expand]
-	 * @param   {String}  [search_query]
+	 * @param   {String}  [searchQuery]
 	 * @returns {Promise}
 	 */
-	getAll: (access, expand, search_query) => {
-		return access.can("auditlog:list").then(() => {
-			const query = auditLogModel
-				.query()
-				.orderBy("created_on", "DESC")
-				.orderBy("id", "DESC")
-				.limit(100)
-				.allowGraph("[user]");
+	getAll: async (access, expand, searchQuery) => {
+		await access.can("auditlog:list");
 
-			// Query is used for searching
-			if (typeof search_query === "string" && search_query.length > 0) {
-				query.where(function () {
-					this.where(castJsonIfNeed("meta"), "like", `%${search_query}`);
-				});
-			}
+		const query = auditLogModel
+			.query()
+			.orderBy("created_on", "DESC")
+			.orderBy("id", "DESC")
+			.limit(100)
+			.allowGraph("[user]");
 
-			if (typeof expand !== "undefined" && expand !== null) {
-				query.withGraphFetched(`[${expand.join(", ")}]`);
-			}
+		// Query is used for searching
+		if (typeof searchQuery === "string" && searchQuery.length > 0) {
+			query.where(function () {
+				this.where(castJsonIfNeed("meta"), "like", `%${searchQuery}`);
+			});
+		}
 
-			return query;
-		});
+		if (typeof expand !== "undefined" && expand !== null) {
+			query.withGraphFetched(`[${expand.join(", ")}]`);
+		}
+
+		return await query;
 	},
 
 	/**
@@ -50,27 +50,22 @@ const internalAuditLog = {
 	 * @param   {Object}   [data.meta]
 	 * @returns {Promise}
 	 */
-	add: (access, data) => {
-		return new Promise((resolve, reject) => {
-			// Default the user id
-			if (typeof data.user_id === "undefined" || !data.user_id) {
-				data.user_id = access.token.getUserId(1);
-			}
+	add: async (access, data) => {
+		if (typeof data.user_id === "undefined" || !data.user_id) {
+			data.user_id = access.token.getUserId(1);
+		}
+
+		if (typeof data.action === "undefined" || !data.action) {
+			throw new errs.InternalValidationError("Audit log entry must contain an Action");
+		}
 
-			if (typeof data.action === "undefined" || !data.action) {
-				reject(new errs.InternalValidationError("Audit log entry must contain an Action"));
-			} else {
-				// Make sure at least 1 of the IDs are set and action
-				resolve(
-					auditLogModel.query().insert({
-						user_id: data.user_id,
-						action: data.action,
-						object_type: data.object_type || "",
-						object_id: data.object_id || 0,
-						meta: data.meta || {},
-					}),
-				);
-			}
+		// Make sure at least 1 of the IDs are set and action
+		return await auditLogModel.query().insert({
+			user_id: data.user_id,
+			action: data.action,
+			object_type: data.object_type || "",
+			object_id: data.object_id || 0,
+			meta: data.meta || {},
 		});
 	},
 };

Diff do ficheiro suprimidas por serem muito extensas
+ 386 - 489
backend/internal/certificate.js


+ 259 - 351
backend/internal/dead-host.js

@@ -18,91 +18,72 @@ const internalDeadHost = {
 	 * @param   {Object}  data
 	 * @returns {Promise}
 	 */
-	create: (access, data) => {
+	create: async (access, data) => {
 		const createCertificate = data.certificate_id === "new";
 
 		if (createCertificate) {
 			delete data.certificate_id;
 		}
 
-		return access
-			.can("dead_hosts:create", data)
-			.then((/*access_data*/) => {
-				// Get a list of the domain names and check each of them against existing records
-				const domain_name_check_promises = [];
-
-				data.domain_names.map((domain_name) => {
-					domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
-					return true;
-				});
-
-				return Promise.all(domain_name_check_promises).then((check_results) => {
-					check_results.map((result) => {
-						if (result.is_taken) {
-							throw new errs.ValidationError(`${result.hostname} is already in use`);
-						}
-						return true;
-					});
-				});
-			})
-			.then(() => {
-				// At this point the domains should have been checked
-				data.owner_user_id = access.token.getUserId(1);
-				const thisData = internalHost.cleanSslHstsData(data);
-
-				// Fix for db field not having a default value
-				// for this optional field.
-				if (typeof data.advanced_config === "undefined") {
-					thisData.advanced_config = "";
-				}
+		await access.can("dead_hosts:create", data);
+
+		// Get a list of the domain names and check each of them against existing records
+		const domainNameCheckPromises = [];
+
+		data.domain_names.map((domain_name) => {
+			domainNameCheckPromises.push(internalHost.isHostnameTaken(domain_name));
+			return true;
+		});
 
-				return deadHostModel.query().insertAndFetch(thisData).then(utils.omitRow(omissions()));
-			})
-			.then((row) => {
-				if (createCertificate) {
-					return internalCertificate
-						.createQuickCertificate(access, data)
-						.then((cert) => {
-							// update host with cert id
-							return internalDeadHost.update(access, {
-								id: row.id,
-								certificate_id: cert.id,
-							});
-						})
-						.then(() => {
-							return row;
-						});
+		await Promise.all(domainNameCheckPromises).then((check_results) => {
+			check_results.map((result) => {
+				if (result.is_taken) {
+					throw new errs.ValidationError(`${result.hostname} is already in use`);
 				}
-				return row;
-			})
-			.then((row) => {
-				// re-fetch with cert
-				return internalDeadHost.get(access, {
-					id: row.id,
-					expand: ["certificate", "owner"],
-				});
-			})
-			.then((row) => {
-				// Configure nginx
-				return internalNginx.configure(deadHostModel, "dead_host", row).then(() => {
-					return row;
-				});
-			})
-			.then((row) => {
-				data.meta = _.assign({}, data.meta || {}, row.meta);
-
-				// Add to audit log
-				return internalAuditLog
-					.add(access, {
-						action: "created",
-						object_type: "dead-host",
-						object_id: row.id,
-						meta: data,
-					})
-					.then(() => {
-						return row;
-					});
+				return true;
+			});
+		});
+
+		// At this point the domains should have been checked
+		data.owner_user_id = access.token.getUserId(1);
+		const thisData = internalHost.cleanSslHstsData(data);
+
+		// Fix for db field not having a default value
+		// for this optional field.
+		if (typeof data.advanced_config === "undefined") {
+			thisData.advanced_config = "";
+		}
+
+		const row = await deadHostModel.query().insertAndFetch(thisData).then(utils.omitRow(omissions()));
+
+		if (createCertificate) {
+			const cert = await internalCertificate.createQuickCertificate(access, data);
+			// update host with cert id
+			await internalDeadHost.update(access, {
+				id: row.id,
+				certificate_id: cert.id,
 			});
+		}
+
+		// re-fetch with cert
+		const freshRow = await internalDeadHost.get(access, {
+			id: row.id,
+			expand: ["certificate", "owner"],
+		});
+
+		// Configure nginx
+		await internalNginx.configure(deadHostModel, "dead_host", freshRow);
+		data.meta = _.assign({}, data.meta || {}, freshRow.meta);
+
+		// Add to audit log
+		await internalAuditLog.add(access, {
+			action: "created",
+			object_type: "dead-host",
+			object_id: freshRow.id,
+			meta: data,
+		});
+
+		return freshRow;
 	},
 
 	/**
@@ -111,107 +92,79 @@ const internalDeadHost = {
 	 * @param  {Number}  data.id
 	 * @return {Promise}
 	 */
-	update: (access, data) => {
-		let thisData = data;
-		const createCertificate = thisData.certificate_id === "new";
+	update: async (access, data) => {
+		const createCertificate = data.certificate_id === "new";
 
 		if (createCertificate) {
-			delete thisData.certificate_id;
+			delete data.certificate_id;
 		}
 
-		return access
-			.can("dead_hosts:update", thisData.id)
-			.then((/*access_data*/) => {
-				// Get a list of the domain names and check each of them against existing records
-				const domain_name_check_promises = [];
-
-				if (typeof thisData.domain_names !== "undefined") {
-					thisData.domain_names.map((domain_name) => {
-						domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, "dead", data.id));
-						return true;
-					});
-
-					return Promise.all(domain_name_check_promises).then((check_results) => {
-						check_results.map((result) => {
-							if (result.is_taken) {
-								throw new errs.ValidationError(`${result.hostname} is already in use`);
-							}
-							return true;
-						});
-					});
-				}
-			})
-			.then(() => {
-				return internalDeadHost.get(access, { id: thisData.id });
-			})
-			.then((row) => {
-				if (row.id !== thisData.id) {
-					// Sanity check that something crazy hasn't happened
-					throw new errs.InternalValidationError(
-						`404 Host could not be updated, IDs do not match: ${row.id} !== ${thisData.id}`,
-					);
-				}
+		await access.can("dead_hosts:update", data.id);
+
+		// Get a list of the domain names and check each of them against existing records
+		const domainNameCheckPromises = [];
+		if (typeof data.domain_names !== "undefined") {
+			data.domain_names.map((domainName) => {
+				domainNameCheckPromises.push(internalHost.isHostnameTaken(domainName, "dead", data.id));
+				return true;
+			});
 
-				if (createCertificate) {
-					return internalCertificate
-						.createQuickCertificate(access, {
-							domain_names: thisData.domain_names || row.domain_names,
-							meta: _.assign({}, row.meta, thisData.meta),
-						})
-						.then((cert) => {
-							// update host with cert id
-							thisData.certificate_id = cert.id;
-						})
-						.then(() => {
-							return row;
-						});
+			const checkResults = await Promise.all(domainNameCheckPromises);
+			checkResults.map((result) => {
+				if (result.is_taken) {
+					throw new errs.ValidationError(`${result.hostname} is already in use`);
 				}
-				return row;
-			})
-			.then((row) => {
-				// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
-				thisData = _.assign(
-					{},
-					{
-						domain_names: row.domain_names,
-					},
-					data,
-				);
-
-				thisData = internalHost.cleanSslHstsData(thisData, row);
-
-				return deadHostModel
-					.query()
-					.where({ id: thisData.id })
-					.patch(thisData)
-					.then((saved_row) => {
-						// Add to audit log
-						return internalAuditLog
-							.add(access, {
-								action: "updated",
-								object_type: "dead-host",
-								object_id: row.id,
-								meta: thisData,
-							})
-							.then(() => {
-								return _.omit(saved_row, omissions());
-							});
-					});
-			})
-			.then(() => {
-				return internalDeadHost
-					.get(access, {
-						id: thisData.id,
-						expand: ["owner", "certificate"],
-					})
-					.then((row) => {
-						// Configure nginx
-						return internalNginx.configure(deadHostModel, "dead_host", row).then((new_meta) => {
-							row.meta = new_meta;
-							return _.omit(internalHost.cleanRowCertificateMeta(row), omissions());
-						});
-					});
+				return true;
 			});
+		}
+		const row = await internalDeadHost.get(access, { id: data.id });
+
+		if (row.id !== data.id) {
+			// Sanity check that something crazy hasn't happened
+			throw new errs.InternalValidationError(
+				`404 Host could not be updated, IDs do not match: ${row.id} !== ${data.id}`,
+			);
+		}
+
+		if (createCertificate) {
+			const cert = await internalCertificate.createQuickCertificate(access, {
+				domain_names: data.domain_names || row.domain_names,
+				meta: _.assign({}, row.meta, data.meta),
+			});
+
+			// update host with cert id
+			data.certificate_id = cert.id;
+		}
+
+		// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
+		let thisData = _.assign(
+			{},
+			{
+				domain_names: row.domain_names,
+			},
+			data,
+		);
+
+		thisData = internalHost.cleanSslHstsData(thisData, row);
+
+		// Add to audit log
+		await internalAuditLog.add(access, {
+			action: "updated",
+			object_type: "dead-host",
+			object_id: row.id,
+			meta: thisData,
+		});
+
+		const thisRow = await internalDeadHost
+			.get(access, {
+				id: thisData.id,
+				expand: ["owner", "certificate"],
+			});
+
+		// Configure nginx
+		const newMeta = await internalNginx.configure(deadHostModel, "dead_host", row);
+		row.meta = newMeta;
+		return _.omit(internalHost.cleanRowCertificateMeta(thisRow), omissions());
 	},
 
 	/**
@@ -222,39 +175,32 @@ const internalDeadHost = {
 	 * @param  {Array}    [data.omit]
 	 * @return {Promise}
 	 */
-	get: (access, data) => {
-		const thisData = data || {};
-
-		return access
-			.can("dead_hosts:get", thisData.id)
-			.then((access_data) => {
-				const query = deadHostModel
-					.query()
-					.where("is_deleted", 0)
-					.andWhere("id", dthisDataata.id)
-					.allowGraph("[owner,certificate]")
-					.first();
-
-				if (access_data.permission_visibility !== "all") {
-					query.andWhere("owner_user_id", access.token.getUserId(1));
-				}
+	get: async (access, data) => {
+		const accessData = await access.can("dead_hosts:get", data.id);
+		const query = deadHostModel
+			.query()
+			.where("is_deleted", 0)
+			.andWhere("id", data.id)
+			.allowGraph("[owner,certificate]")
+			.first();
+
+		if (accessData.permission_visibility !== "all") {
+			query.andWhere("owner_user_id", access.token.getUserId(1));
+		}
 
-				if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
-					query.withGraphFetched(`[${data.expand.join(", ")}]`);
-				}
+		if (typeof data.expand !== "undefined" && data.expand !== null) {
+			query.withGraphFetched(`[${data.expand.join(", ")}]`);
+		}
 
-				return query.then(utils.omitRow(omissions()));
-			})
-			.then((row) => {
-				if (!row || !row.id) {
-					throw new errs.ItemNotFoundError(thisData.id);
-				}
-				// Custom omissions
-				if (typeof thisData.omit !== "undefined" && thisData.omit !== null) {
-					return _.omit(row, thisData.omit);
-				}
-				return row;
-			});
+		const row = await query.then(utils.omitRow(omissions()));
+		if (!row || !row.id) {
+			throw new errs.ItemNotFoundError(data.id);
+		}
+		// Custom omissions
+		if (typeof data.omit !== "undefined" && data.omit !== null) {
+			return _.omit(row, data.omit);
+		}
+		return row;
 	},
 
 	/**
@@ -264,42 +210,30 @@ const internalDeadHost = {
 	 * @param {String}  [data.reason]
 	 * @returns {Promise}
 	 */
-	delete: (access, data) => {
-		return access
-			.can("dead_hosts:delete", data.id)
-			.then(() => {
-				return internalDeadHost.get(access, { id: data.id });
-			})
-			.then((row) => {
-				if (!row || !row.id) {
-					throw new errs.ItemNotFoundError(data.id);
-				}
+	delete: async (access, data) => {
+		await access.can("dead_hosts:delete", data.id)
+		const row = await internalDeadHost.get(access, { id: data.id });
+		if (!row || !row.id) {
+			throw new errs.ItemNotFoundError(data.id);
+		}
 
-				return deadHostModel
-					.query()
-					.where("id", row.id)
-					.patch({
-						is_deleted: 1,
-					})
-					.then(() => {
-						// Delete Nginx Config
-						return internalNginx.deleteConfig("dead_host", row).then(() => {
-							return internalNginx.reload();
-						});
-					})
-					.then(() => {
-						// Add to audit log
-						return internalAuditLog.add(access, {
-							action: "deleted",
-							object_type: "dead-host",
-							object_id: row.id,
-							meta: _.omit(row, omissions()),
-						});
-					});
-			})
-			.then(() => {
-				return true;
+		await deadHostModel
+			.query()
+			.where("id", row.id)
+			.patch({
+				is_deleted: 1,
 			});
+
+		// Delete Nginx Config
+		await internalNginx.deleteConfig("dead_host", row);
+		await internalNginx.reload();
+		// Add to audit log
+		await internalAuditLog.add(access, {
+			action: "deleted",
+			object_type: "dead-host",
+			object_id: row.id,
+			meta: _.omit(row, omissions()),
+		});
 	},
 
 	/**
@@ -309,48 +243,39 @@ const internalDeadHost = {
 	 * @param {String}  [data.reason]
 	 * @returns {Promise}
 	 */
-	enable: (access, data) => {
-		return access
-			.can("dead_hosts:update", data.id)
-			.then(() => {
-				return internalDeadHost.get(access, {
-					id: data.id,
-					expand: ["certificate", "owner"],
-				});
-			})
-			.then((row) => {
-				if (!row || !row.id) {
-					throw new errs.ItemNotFoundError(data.id);
-				}
-				if (row.enabled) {
-					throw new errs.ValidationError("Host is already enabled");
-				}
+	enable: async (access, data) => {
+		await access.can("dead_hosts:update", data.id)
+		const row = await internalDeadHost.get(access, {
+			id: data.id,
+			expand: ["certificate", "owner"],
+		});
+		if (!row || !row.id) {
+			throw new errs.ItemNotFoundError(data.id);
+		}
+		if (row.enabled) {
+			throw new errs.ValidationError("Host is already enabled");
+		}
 
-				row.enabled = 1;
-
-				return deadHostModel
-					.query()
-					.where("id", row.id)
-					.patch({
-						enabled: 1,
-					})
-					.then(() => {
-						// Configure nginx
-						return internalNginx.configure(deadHostModel, "dead_host", row);
-					})
-					.then(() => {
-						// Add to audit log
-						return internalAuditLog.add(access, {
-							action: "enabled",
-							object_type: "dead-host",
-							object_id: row.id,
-							meta: _.omit(row, omissions()),
-						});
-					});
-			})
-			.then(() => {
-				return true;
+		row.enabled = 1;
+
+		await deadHostModel
+			.query()
+			.where("id", row.id)
+			.patch({
+				enabled: 1,
 			});
+
+		// Configure nginx
+		await internalNginx.configure(deadHostModel, "dead_host", row);
+
+		// Add to audit log
+		await internalAuditLog.add(access, {
+			action: "enabled",
+			object_type: "dead-host",
+			object_id: row.id,
+			meta: _.omit(row, omissions()),
+		});
+		return true;
 	},
 
 	/**
@@ -360,47 +285,37 @@ const internalDeadHost = {
 	 * @param {String}  [data.reason]
 	 * @returns {Promise}
 	 */
-	disable: (access, data) => {
-		return access
-			.can("dead_hosts:update", data.id)
-			.then(() => {
-				return internalDeadHost.get(access, { id: data.id });
-			})
-			.then((row) => {
-				if (!row || !row.id) {
-					throw new errs.ItemNotFoundError(data.id);
-				}
-				if (!row.enabled) {
-					throw new errs.ValidationError("Host is already disabled");
-				}
+	disable: async (access, data) => {
+		await access.can("dead_hosts:update", data.id)
+		const row = await internalDeadHost.get(access, { id: data.id });
+		if (!row || !row.id) {
+			throw new errs.ItemNotFoundError(data.id);
+		}
+		if (!row.enabled) {
+			throw new errs.ValidationError("Host is already disabled");
+		}
 
-				row.enabled = 0;
-
-				return deadHostModel
-					.query()
-					.where("id", row.id)
-					.patch({
-						enabled: 0,
-					})
-					.then(() => {
-						// Delete Nginx Config
-						return internalNginx.deleteConfig("dead_host", row).then(() => {
-							return internalNginx.reload();
-						});
-					})
-					.then(() => {
-						// Add to audit log
-						return internalAuditLog.add(access, {
-							action: "disabled",
-							object_type: "dead-host",
-							object_id: row.id,
-							meta: _.omit(row, omissions()),
-						});
-					});
-			})
-			.then(() => {
-				return true;
+		row.enabled = 0;
+
+		await deadHostModel
+			.query()
+			.where("id", row.id)
+			.patch({
+				enabled: 0,
 			});
+
+		// Delete Nginx Config
+		await internalNginx.deleteConfig("dead_host", row);
+		await internalNginx.reload();
+
+		// Add to audit log
+		await internalAuditLog.add(access, {
+			action: "disabled",
+			object_type: "dead-host",
+			object_id: row.id,
+			meta: _.omit(row, omissions()),
+		});
+		return true;
 	},
 
 	/**
@@ -408,44 +323,38 @@ const internalDeadHost = {
 	 *
 	 * @param   {Access}  access
 	 * @param   {Array}   [expand]
-	 * @param   {String}  [search_query]
+	 * @param   {String}  [searchQuery]
 	 * @returns {Promise}
 	 */
-	getAll: (access, expand, search_query) => {
-		return access
-			.can("dead_hosts:list")
-			.then((access_data) => {
-				const query = deadHostModel
-					.query()
-					.where("is_deleted", 0)
-					.groupBy("id")
-					.allowGraph("[owner,certificate]")
-					.orderBy(castJsonIfNeed("domain_names"), "ASC");
-
-				if (access_data.permission_visibility !== "all") {
-					query.andWhere("owner_user_id", access.token.getUserId(1));
-				}
-
-				// Query is used for searching
-				if (typeof search_query === "string" && search_query.length > 0) {
-					query.where(function () {
-						this.where(castJsonIfNeed("domain_names"), "like", `%${search_query}%`);
-					});
-				}
+	getAll: async (access, expand, searchQuery) => {
+		const accessData = await access.can("dead_hosts:list")
+		const query = deadHostModel
+			.query()
+			.where("is_deleted", 0)
+			.groupBy("id")
+			.allowGraph("[owner,certificate]")
+			.orderBy(castJsonIfNeed("domain_names"), "ASC");
+
+		if (accessData.permission_visibility !== "all") {
+			query.andWhere("owner_user_id", access.token.getUserId(1));
+		}
 
-				if (typeof expand !== "undefined" && expand !== null) {
-					query.withGraphFetched(`[${expand.join(", ")}]`);
-				}
+		// Query is used for searching
+		if (typeof searchQuery === "string" && searchQuery.length > 0) {
+			query.where(function () {
+				this.where(castJsonIfNeed("domain_names"), "like", `%${searchQuery}%`);
+			});
+		}
 
-				return query.then(utils.omitRows(omissions()));
-			})
-			.then((rows) => {
-				if (typeof expand !== "undefined" && expand !== null && expand.indexOf("certificate") !== -1) {
-					return internalHost.cleanAllRowsCertificateMeta(rows);
-				}
+		if (typeof expand !== "undefined" && expand !== null) {
+			query.withGraphFetched(`[${expand.join(", ")}]`);
+		}
 
-				return rows;
-			});
+		const rows = await query.then(utils.omitRows(omissions()));
+		if (typeof expand !== "undefined" && expand !== null && expand.indexOf("certificate") !== -1) {
+			internalHost.cleanAllRowsCertificateMeta(rows);
+		}
+		return rows;
 	},
 
 	/**
@@ -455,16 +364,15 @@ const internalDeadHost = {
 	 * @param   {String}  visibility
 	 * @returns {Promise}
 	 */
-	getCount: (user_id, visibility) => {
+	getCount: async (user_id, visibility) => {
 		const query = deadHostModel.query().count("id as count").where("is_deleted", 0);
 
 		if (visibility !== "all") {
 			query.andWhere("owner_user_id", user_id);
 		}
 
-		return query.first().then((row) => {
-			return Number.parseInt(row.count, 10);
-		});
+		const row = await query.first();
+		return Number.parseInt(row.count, 10);
 	},
 };
 

+ 23 - 40
backend/internal/host.js

@@ -65,50 +65,33 @@ const internalHost = {
 	},
 
 	/**
-	 * This returns all the host types with any domain listed in the provided domain_names array.
+	 * 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}  domain_names
+	 * @param   {Array}  domainNames
 	 * @returns {Promise}
 	 */
-	getHostsWithDomains: (domain_names) => {
-		const promises = [
-			proxyHostModel.query().where("is_deleted", 0),
-			redirectionHostModel.query().where("is_deleted", 0),
-			deadHostModel.query().where("is_deleted", 0),
-		];
-
-		return Promise.all(promises).then((promises_results) => {
-			const response_object = {
-				total_count: 0,
-				dead_hosts: [],
-				proxy_hosts: [],
-				redirection_hosts: [],
-			};
-
-			if (promises_results[0]) {
-				// Proxy Hosts
-				response_object.proxy_hosts = internalHost._getHostsWithDomains(promises_results[0], domain_names);
-				response_object.total_count += response_object.proxy_hosts.length;
-			}
-
-			if (promises_results[1]) {
-				// Redirection Hosts
-				response_object.redirection_hosts = internalHost._getHostsWithDomains(
-					promises_results[1],
-					domain_names,
-				);
-				response_object.total_count += response_object.redirection_hosts.length;
-			}
-
-			if (promises_results[2]) {
-				// Dead Hosts
-				response_object.dead_hosts = internalHost._getHostsWithDomains(promises_results[2], domain_names);
-				response_object.total_count += response_object.dead_hosts.length;
-			}
-
-			return response_object;
-		});
+	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;
 	},
 
 	/**

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff