link.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import bcrypt from "bcryptjs";
  2. import { getRedisKey, generateShortLink } from "../utils";
  3. import * as redis from "../redis";
  4. import knex from "../knex";
  5. interface GetTotal {
  6. all: boolean;
  7. userId: number;
  8. search?: string;
  9. }
  10. export const getTotalQuery = async ({ all, search, userId }: GetTotal) => {
  11. const query = knex<Link>("links").count("id");
  12. if (!all) {
  13. query.where("user_id", userId);
  14. }
  15. if (search) {
  16. query.andWhereRaw("links.address || ' ' || target ILIKE '%' || ? || '%'", [
  17. search
  18. ]);
  19. }
  20. const [{ count }] = await query;
  21. return typeof count === "number" ? count : parseInt(count);
  22. };
  23. interface GetLinks {
  24. all: boolean;
  25. limit: number;
  26. search?: string;
  27. skip: number;
  28. userId: number;
  29. }
  30. export const getLinksQuery = async ({
  31. all,
  32. limit,
  33. search,
  34. skip,
  35. userId
  36. }: GetLinks) => {
  37. const query = knex<LinkJoinedDomain>("links")
  38. .select(
  39. "links.id",
  40. "links.address",
  41. "links.banned",
  42. "links.created_at",
  43. "links.domain_id",
  44. "links.updated_at",
  45. "links.password",
  46. "links.target",
  47. "links.visit_count",
  48. "links.user_id",
  49. "links.uuid",
  50. "domains.address as domain"
  51. )
  52. .offset(skip)
  53. .limit(limit)
  54. .orderBy("created_at", "desc");
  55. if (!all) {
  56. query.where("links.user_id", userId);
  57. }
  58. if (search) {
  59. query.andWhereRaw("links.address || ' ' || target ILIKE '%' || ? || '%'", [
  60. search
  61. ]);
  62. }
  63. query.leftJoin("domains", "links.domain_id", "domains.id");
  64. const links: LinkJoinedDomain[] = await query;
  65. return links;
  66. };
  67. interface FindLink {
  68. address?: string;
  69. domainId?: number;
  70. userId?: number;
  71. target?: string;
  72. }
  73. export const findLinkQuery = async ({
  74. address,
  75. domainId,
  76. userId,
  77. target
  78. }: FindLink): Promise<Link> => {
  79. const redisKey = getRedisKey.link(address, domainId, userId);
  80. const cachedLink = await redis.get(redisKey);
  81. if (cachedLink) return JSON.parse(cachedLink);
  82. const link = await knex<Link>("links")
  83. .where({
  84. ...(address && { address }),
  85. ...(domainId && { domain_id: domainId }),
  86. ...(userId && { user_id: userId }),
  87. ...(target && { target })
  88. })
  89. .first();
  90. if (link) {
  91. redis.set(redisKey, JSON.stringify(link), "EX", 60 * 60 * 2);
  92. }
  93. return link;
  94. };
  95. interface CreateLink {
  96. userId?: number;
  97. domainAddress?: string;
  98. domainId?: number;
  99. password?: string;
  100. address: string;
  101. target: string;
  102. }
  103. export const createLinkQuery = async ({
  104. password,
  105. address,
  106. target,
  107. domainAddress,
  108. domainId = null,
  109. userId = null
  110. }: CreateLink) => {
  111. let encryptedPassword;
  112. if (password) {
  113. const salt = await bcrypt.genSalt(12);
  114. encryptedPassword = await bcrypt.hash(password, salt);
  115. }
  116. const [link]: Link[] = await knex<Link>("links").insert(
  117. {
  118. password: encryptedPassword,
  119. domain_id: domainId,
  120. user_id: userId,
  121. address,
  122. target
  123. },
  124. "*"
  125. );
  126. return {
  127. ...link,
  128. id: link.uuid,
  129. password: !!password,
  130. link: generateShortLink(address, domainAddress)
  131. };
  132. };