domain.queries.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. const redis = require("../redis");
  2. const utils = require("../utils");
  3. const knex = require("../knex");
  4. const env = require("../env");
  5. async function find(match) {
  6. if (match.address && env.REDIS_ENABLED) {
  7. const cachedDomain = await redis.client.get(redis.key.domain(match.address));
  8. if (cachedDomain) return JSON.parse(cachedDomain);
  9. }
  10. const domain = await knex("domains").where(match).first();
  11. if (domain && env.REDIS_ENABLED) {
  12. const key = redis.key.domain(domain.address);
  13. redis.client.set(key, JSON.stringify(domain), "EX", 60 * 15);
  14. }
  15. return domain;
  16. }
  17. function get(match) {
  18. return knex("domains").where(match);
  19. }
  20. async function add(params) {
  21. params.address = params.address.toLowerCase();
  22. const existingDomain = await knex("domains").where("address", params.address).first();
  23. let id = existingDomain?.id;
  24. const newDomain = {
  25. address: params.address,
  26. homepage: params.homepage,
  27. user_id: params.user_id,
  28. banned: !!params.banned,
  29. banned_by_id: params.banned_by_id
  30. };
  31. if (id) {
  32. await knex("domains").where("id", id).update({
  33. ...newDomain,
  34. updated_at: params.updated_at || utils.dateToUTC(new Date())
  35. });
  36. } else {
  37. // Mysql and sqlite don't support returning but return the inserted id by default
  38. const [createdDomain] = await knex("domains").insert(newDomain, "*");
  39. id = typeof createdDomain === "number" ? createdDomain : createdDomain.id;
  40. }
  41. // Query domain instead of using returning as sqlite and mysql don't support it
  42. const domain = await knex("domains").where("id", id).first();
  43. if (env.REDIS_ENABLED) {
  44. redis.remove.domain(existingDomain);
  45. redis.remove.domain(domain);
  46. }
  47. return domain;
  48. }
  49. async function update(match, update) {
  50. // if the domains' adddress is changed,
  51. // make sure to delete the original domains from cache
  52. let domains = []
  53. if (env.REDIS_ENABLED && update.address) {
  54. domains = await knex("domains").select("*").where(match);
  55. }
  56. await knex("domains")
  57. .where(match)
  58. .update({ ...update, updated_at: utils.dateToUTC(new Date()) });
  59. const updated_domains = await knex("domains").select("*").where(match);
  60. if (env.REDIS_ENABLED) {
  61. domains.forEach(redis.remove.domain);
  62. updated_domains.forEach(redis.remove.domain);
  63. }
  64. return updated_domains;
  65. }
  66. function normalizeMatch(match) {
  67. const newMatch = { ...match };
  68. if (newMatch.address) {
  69. newMatch["domains.address"] = newMatch.address;
  70. delete newMatch.address;
  71. }
  72. if (newMatch.user_id) {
  73. newMatch["domains.user_id"] = newMatch.user_id;
  74. delete newMatch.user_id;
  75. }
  76. if (newMatch.uuid) {
  77. newMatch["domains.uuid"] = newMatch.uuid;
  78. delete newMatch.uuid;
  79. }
  80. if (newMatch.banned !== undefined) {
  81. newMatch["domains.banned"] = newMatch.banned;
  82. delete newMatch.banned;
  83. }
  84. return newMatch;
  85. }
  86. const selectable_admin = [
  87. "domains.id",
  88. "domains.address",
  89. "domains.homepage",
  90. "domains.banned",
  91. "domains.created_at",
  92. "domains.updated_at",
  93. "domains.user_id",
  94. "domains.uuid",
  95. "users.email as email",
  96. "links_count"
  97. ];
  98. async function getAdmin(match, params) {
  99. const query = knex("domains").select(...selectable_admin);
  100. Object.entries(normalizeMatch(match)).forEach(([key, value]) => {
  101. query.andWhere(key, ...(Array.isArray(value) ? value : [value]));
  102. });
  103. query
  104. .offset(params.skip)
  105. .limit(params.limit)
  106. .fromRaw("domains")
  107. .orderBy("domains.id", "desc")
  108. .groupBy(1)
  109. .groupBy("l.links_count")
  110. .groupBy("users.email");
  111. if (params?.user) {
  112. const id = parseInt(params?.user);
  113. if (Number.isNaN(id)) {
  114. query[knex.compatibleILIKE]("users.email", "%" + params.user + "%");
  115. } else {
  116. query.andWhere("domains.user_id", id);
  117. }
  118. }
  119. if (params?.search) {
  120. query[knex.compatibleILIKE](
  121. knex.raw("concat_ws(' ', domains.address, domains.homepage)"),
  122. "%" + params.search + "%"
  123. );
  124. }
  125. if (params?.links !== undefined) {
  126. query.andWhere("links_count", params?.links ? "is not" : "is", null);
  127. }
  128. query.leftJoin(
  129. knex("links").select("domain_id").count("id as links_count").groupBy("domain_id").as("l"),
  130. "domains.id",
  131. "l.domain_id"
  132. );
  133. query.leftJoin("users", "domains.user_id", "users.id");
  134. return query;
  135. }
  136. async function totalAdmin(match, params) {
  137. const query = knex("domains");
  138. Object.entries(normalizeMatch(match)).forEach(([key, value]) => {
  139. query.andWhere(key, ...(Array.isArray(value) ? value : [value]));
  140. });
  141. if (params?.user) {
  142. const id = parseInt(params?.user);
  143. if (Number.isNaN(id)) {
  144. query[knex.compatibleILIKE]("users.email", "%" + params.user + "%");
  145. } else {
  146. query.andWhere("domains.user_id", id);
  147. }
  148. }
  149. if (params?.search) {
  150. query[knex.compatibleILIKE](
  151. knex.raw("concat_ws(' ', domains.address, domains.homepage)"),
  152. "%" + params.search + "%"
  153. );
  154. }
  155. if (params?.links !== undefined) {
  156. query.leftJoin(
  157. knex("links").select("domain_id").count("id as links_count").groupBy("domain_id").as("l"),
  158. "domains.id",
  159. "l.domain_id"
  160. );
  161. query.andWhere("links_count", params?.links ? "is not" : "is", null);
  162. }
  163. query.leftJoin("users", "domains.user_id", "users.id");
  164. query.count("domains.id as count");
  165. const [{ count }] = await query;
  166. return typeof count === "number" ? count : parseInt(count);
  167. }
  168. async function remove(domain) {
  169. const deletedDomain = await knex("domains").where("id", domain.id).delete();
  170. if (env.REDIS_ENABLED) {
  171. redis.remove.domain(domain);
  172. }
  173. return !!deletedDomain;
  174. }
  175. module.exports = {
  176. add,
  177. find,
  178. get,
  179. getAdmin,
  180. remove,
  181. totalAdmin,
  182. update,
  183. }