aboutsummaryrefslogtreecommitdiffstats
path: root/models/User.js
blob: 44d96194a7057eb8238f83bc9389eaa90303632e (plain) (blame)
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
117
118
119
120
121
122
123
124
125
126
127
const mongoose = require("mongoose")
const bcrypt = require('bcryptjs')
const {nanoid} = require('nanoid')

const userResponse = u => ({
  _id: u._id,
  email: u.email,
  isVerified: u.isVerified,
  noteList: u.noteList,
  theme: u.theme,
  language: u.language
})

const userSchema = new mongoose.Schema({
  email: {
    type: String,
    trim: true,
    lowercase: true,
    unique: true,
    required: true,
    minlength: 6,
    maxlength: 255,
    validate(value) {
      if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
        throw new Error('Wrong email address')
      }
    }
  },
  password: {
    type: String,
    required: true,
    minlength: 6,
    maxlength: 1024,
  },
  isVerified: {
    type: Boolean,
    default: false,
  },
  verificationKey: {
    type: String,
    default: () => nanoid(6),
  },
  noteList: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "NoteList",
    required: true,
  },
  theme: {type: String, default: () => 'green'},
  language: {type: String, default: () => 'en'},
  created_at: {type: Date, default: Date.now},
  updated_at: {type: Date, default: Date.now}
})

userSchema.statics.findByCredentials = async function (email, password){
  const user = await User.findOne({email})

  if (!user) {
    throw new Error('Unable to login')
  }

  const isMatch = await bcrypt.compare(password, user.password)

  if (!isMatch) {
    throw new Error('Unable to login')
  }

  return userResponse(user)
}

userSchema.statics.getVerificationKey = async function (email){
  const {verificationKey: key} = await User.findOne({email})

  if (!key) {
    throw new Error('Could not verify user')
  }

  return key
}

userSchema.statics.verifyUser = async function (_id, key){
  const user = await User.findOneAndUpdate({_id, verificationKey: key}, {isVerified: true, verificationKey: nanoid(10)}, {new: true})

  if (!user) {
    throw new Error('Could not verify user')
  }

  return userResponse(user)
}

userSchema.statics.saveSettings = async function ({_id, theme, language}){
  const user = await User.findOneAndUpdate({_id}, {theme, language}, {new: true})

  if (!user) {
    throw new Error('Could not save settings')
  }

  return userResponse(user)
}

userSchema.statics.state = async function (_id){
  const user = await User.findOne({_id})

  if (!user) {
    return {isLoggedIn: false}
  } else if (!user.isVerified) {
    return {isVerified: false}
  }

  return {}
}


userSchema.pre('save', async function(next){
  const user = this;

  if (user.isModified('password')) {
    user.password = await bcrypt.hash(user.password, 8);
  }

  user.updated_at = Date.now()

  next()
})

const User = mongoose.models.User || mongoose.model('User', userSchema)

export default User