File size: 3,437 Bytes
f8b5d42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
const { v4 } = require("uuid");
const prisma = require("../utils/prisma");
const bcrypt = require("bcrypt");

const RecoveryCode = {
  tablename: "recovery_codes",
  writable: [],
  create: async function (userId, code) {
    try {
      const codeHash = await bcrypt.hash(code, 10);
      const recoveryCode = await prisma.recovery_codes.create({
        data: { user_id: userId, code_hash: codeHash },
      });
      return { recoveryCode, error: null };
    } catch (error) {
      console.error("FAILED TO CREATE RECOVERY CODE.", error.message);
      return { recoveryCode: null, error: error.message };
    }
  },
  createMany: async function (data) {
    try {
      const recoveryCodes = await prisma.$transaction(
        data.map((recoveryCode) =>
          prisma.recovery_codes.create({ data: recoveryCode })
        )
      );
      return { recoveryCodes, error: null };
    } catch (error) {
      console.error("FAILED TO CREATE RECOVERY CODES.", error.message);
      return { recoveryCodes: null, error: error.message };
    }
  },
  findFirst: async function (clause = {}) {
    try {
      const recoveryCode = await prisma.recovery_codes.findFirst({
        where: clause,
      });
      return recoveryCode;
    } catch (error) {
      console.error("FAILED TO FIND RECOVERY CODE.", error.message);
      return null;
    }
  },
  findMany: async function (clause = {}) {
    try {
      const recoveryCodes = await prisma.recovery_codes.findMany({
        where: clause,
      });
      return recoveryCodes;
    } catch (error) {
      console.error("FAILED TO FIND RECOVERY CODES.", error.message);
      return null;
    }
  },
  deleteMany: async function (clause = {}) {
    try {
      await prisma.recovery_codes.deleteMany({ where: clause });
      return true;
    } catch (error) {
      console.error("FAILED TO DELETE RECOVERY CODES.", error.message);
      return false;
    }
  },
  hashesForUser: async function (userId = null) {
    if (!userId) return [];
    return (await this.findMany({ user_id: userId })).map(
      (recovery) => recovery.code_hash
    );
  },
};

const PasswordResetToken = {
  tablename: "password_reset_tokens",
  resetExpiryMs: 600_000, // 10 minutes in ms;
  writable: [],
  calcExpiry: function () {
    return new Date(Date.now() + this.resetExpiryMs);
  },
  create: async function (userId) {
    try {
      const passwordResetToken = await prisma.password_reset_tokens.create({
        data: { user_id: userId, token: v4(), expiresAt: this.calcExpiry() },
      });
      return { passwordResetToken, error: null };
    } catch (error) {
      console.error("FAILED TO CREATE PASSWORD RESET TOKEN.", error.message);
      return { passwordResetToken: null, error: error.message };
    }
  },
  findUnique: async function (clause = {}) {
    try {
      const passwordResetToken = await prisma.password_reset_tokens.findUnique({
        where: clause,
      });
      return passwordResetToken;
    } catch (error) {
      console.error("FAILED TO FIND PASSWORD RESET TOKEN.", error.message);
      return null;
    }
  },
  deleteMany: async function (clause = {}) {
    try {
      await prisma.password_reset_tokens.deleteMany({ where: clause });
      return true;
    } catch (error) {
      console.error("FAILED TO DELETE PASSWORD RESET TOKEN.", error.message);
      return false;
    }
  },
};

module.exports = {
  RecoveryCode,
  PasswordResetToken,
};