user.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import bcrypt from "bcryptjs";
  2. import nanoid from "nanoid";
  3. import uuid from "uuid/v4";
  4. import { addMinutes } from "date-fns";
  5. import knex from "../../knex";
  6. import * as redis from "../../redis";
  7. import { getRedisKey } from "../../utils";
  8. export const getUser = async (emailOrKey = ""): Promise<User> => {
  9. const redisKey = getRedisKey.user(emailOrKey);
  10. const cachedUser = await redis.get(redisKey);
  11. if (cachedUser) return JSON.parse(cachedUser);
  12. const user = await knex<UserJoined>("users")
  13. .select(
  14. "users.id",
  15. "users.apikey",
  16. "users.banned",
  17. "users.banned_by_id",
  18. "users.cooldowns",
  19. "users.created_at",
  20. "users.email",
  21. "users.password",
  22. "users.updated_at",
  23. "users.verified",
  24. "domains.id as domain_id",
  25. "domains.homepage as homepage",
  26. "domains.address as domain"
  27. )
  28. .where("email", "ILIKE", emailOrKey)
  29. .orWhere({ apikey: emailOrKey })
  30. .leftJoin("domains", "users.id", "domains.user_id")
  31. .first();
  32. if (user) {
  33. redis.set(redisKey, JSON.stringify(user), "EX", 60 * 60 * 1);
  34. }
  35. return user;
  36. };
  37. export const createUser = async (
  38. emailToCreate: string,
  39. password: string,
  40. user?: User
  41. ) => {
  42. const email = emailToCreate.toLowerCase();
  43. const salt = await bcrypt.genSalt(12);
  44. const hashedPassword = await bcrypt.hash(password, salt);
  45. const data = {
  46. email,
  47. password: hashedPassword,
  48. verification_token: uuid(),
  49. verification_expires: addMinutes(new Date(), 60).toISOString()
  50. };
  51. if (user) {
  52. await knex<User>("users")
  53. .where({ email })
  54. .update({ ...data, updated_at: new Date().toISOString() });
  55. } else {
  56. await knex<User>("users").insert(data);
  57. }
  58. redis.del(getRedisKey.user(email));
  59. return {
  60. ...user,
  61. ...data
  62. };
  63. };
  64. export const verifyUser = async (verification_token: string) => {
  65. const [user]: User[] = await knex<User>("users")
  66. .where({ verification_token })
  67. .andWhere("verification_expires", ">", new Date().toISOString())
  68. .update(
  69. {
  70. verified: true,
  71. verification_token: undefined,
  72. verification_expires: undefined,
  73. updated_at: new Date().toISOString()
  74. },
  75. "*"
  76. );
  77. if (user) {
  78. redis.del(getRedisKey.user(user.email));
  79. }
  80. return user;
  81. };
  82. export const changePassword = async (id: number, newPassword: string) => {
  83. const salt = await bcrypt.genSalt(12);
  84. const password = await bcrypt.hash(newPassword, salt);
  85. const [user]: User[] = await knex<User>("users")
  86. .where({ id })
  87. .update({ password, updated_at: new Date().toISOString() }, "*");
  88. if (user) {
  89. redis.del(getRedisKey.user(user.email));
  90. redis.del(getRedisKey.user(user.apikey));
  91. }
  92. return user;
  93. };
  94. export const generateApiKey = async (id: number) => {
  95. const apikey = nanoid(40);
  96. const [user]: User[] = await knex<User>("users")
  97. .where({ id })
  98. .update({ apikey, updated_at: new Date().toISOString() }, "*");
  99. if (user) {
  100. redis.del(getRedisKey.user(user.email));
  101. redis.del(getRedisKey.user(user.apikey));
  102. }
  103. return user && apikey;
  104. };
  105. export const requestPasswordReset = async (emailToMatch: string) => {
  106. const email = emailToMatch.toLowerCase();
  107. const reset_password_token = uuid();
  108. const [user]: User[] = await knex<User>("users")
  109. .where({ email })
  110. .update(
  111. {
  112. reset_password_token,
  113. reset_password_expires: addMinutes(new Date(), 30).toISOString(),
  114. updated_at: new Date().toISOString()
  115. },
  116. "*"
  117. );
  118. if (user) {
  119. redis.del(getRedisKey.user(user.email));
  120. redis.del(getRedisKey.user(user.apikey));
  121. }
  122. return user;
  123. };
  124. export const resetPassword = async (reset_password_token: string) => {
  125. const [user]: User[] = await knex<User>("users")
  126. .where({ reset_password_token })
  127. .andWhere("reset_password_expires", ">", new Date().toISOString())
  128. .update(
  129. {
  130. reset_password_expires: null,
  131. reset_password_token: null,
  132. updated_at: new Date().toISOString()
  133. },
  134. "*"
  135. );
  136. if (user) {
  137. redis.del(getRedisKey.user(user.email));
  138. redis.del(getRedisKey.user(user.apikey));
  139. }
  140. return user;
  141. };
  142. export const addCooldown = async (id: number) => {
  143. const [user]: User[] = await knex("users")
  144. .where({ id })
  145. .update(
  146. {
  147. cooldowns: knex.raw("array_append(cooldowns, ?)", [
  148. new Date().toISOString()
  149. ]),
  150. updated_at: new Date().toISOString()
  151. },
  152. "*"
  153. );
  154. if (user) {
  155. redis.del(getRedisKey.user(user.email));
  156. redis.del(getRedisKey.user(user.apikey));
  157. }
  158. return user;
  159. };
  160. export const banUser = async (id: number, banned_by_id?: number) => {
  161. const [user]: User[] = await knex<User>("users")
  162. .where({ id })
  163. .update(
  164. { banned: true, banned_by_id, updated_at: new Date().toISOString() },
  165. "*"
  166. );
  167. if (user) {
  168. redis.del(getRedisKey.user(user.email));
  169. redis.del(getRedisKey.user(user.apikey));
  170. }
  171. return user;
  172. };