File size: 2,899 Bytes
9df3c32
1dc8372
 
9df3c32
 
 
 
 
5db933c
9df3c32
 
3ad0250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9df3c32
 
 
 
 
 
 
 
 
 
1dc8372
9df3c32
 
 
 
1dc8372
9df3c32
 
 
 
 
 
 
1dc8372
 
9df3c32
 
 
 
 
 
1dc8372
9df3c32
 
 
 
 
 
 
 
1dc8372
 
9df3c32
 
 
1dc8372
9df3c32
 
 
 
 
1dc8372
9df3c32
 
 
 
 
 
1dc8372
9df3c32
 
 
 
 
 
 
 
 
 
 
 
1dc8372
9df3c32
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
const { db } = require('../db');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');

class User {
  constructor(userData) {
    Object.assign(this, userData);
    this.id = userData._id; // Alias _id to id
  }

  static findOne(query) {
    const chain = {
      select: function(fields) {
        return this;
      },
      then: function(resolve, reject) {
        return new Promise((res, rej) => {
          db.users.findOne(query, (err, doc) => {
            if (err) rej(err);
            else res(doc ? new User(doc) : null);
          });
        }).then(resolve, reject);
      },
      catch: function(reject) {
        return this.then(null, reject);
      }
    };
    return chain;
  }

  static async findById(id) {
    return new Promise((resolve, reject) => {
      db.users.findOne({ _id: id }, (err, doc) => {
        if (err) reject(err);
        else resolve(doc ? new User(doc) : null);
      });
    });
  }

  static async create(userData) {
    const salt = await bcrypt.genSalt(10);
    if (userData.password) {
      userData.password = await bcrypt.hash(userData.password, salt);
    }
    userData.usage = userData.usage || { requestsToday: 0, lastRequestDate: new Date() };
    userData.createdAt = userData.createdAt || new Date();
    userData.role = userData.role || 'user';
    
    const owners = ['johanvoncd7@gmail.com', 'codexai@mightysmp.online'];
    if (owners.includes(userData.email)) {
      userData.role = 'owner';
    }

    return new Promise((resolve, reject) => {
      db.users.insert(userData, (err, newDoc) => {
        if (err) reject(err);
        else resolve(new User(newDoc));
      });
    });
  }

  static async findByIdAndUpdate(id, update) {
    return new Promise((resolve, reject) => {
      db.users.update({ _id: id }, { $set: update }, { returnUpdatedDocs: true }, (err, numReplaced, affectedDoc) => {
        if (err) reject(err);
        else resolve(affectedDoc ? new User(affectedDoc) : null);
      });
    });
  }

  async matchPassword(enteredPassword) {
    return await bcrypt.compare(enteredPassword, this.password);
  }

  getSignedJwtToken() {
    return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {
      expiresIn: process.env.JWT_EXPIRE
    });
  }

  getResetPasswordToken() {
    const resetToken = crypto.randomBytes(20).toString('hex');
    this.resetPasswordToken = crypto.createHash('sha256').update(resetToken).digest('hex');
    this.resetPasswordExpire = Date.now() + 10 * 60 * 1000;
    return resetToken;
  }

  async save() {
    return new Promise((resolve, reject) => {
      const data = { ...this };
      const id = data._id;
      delete data._id;
      db.users.update({ _id: id }, { $set: data }, { upsert: true }, (err) => {
        if (err) reject(err);
        else resolve(this);
      });
    });
  }
}

module.exports = User;