Skip to content

Instantly share code, notes, and snippets.

@jzellis
Last active January 24, 2024 06:50
Show Gist options
  • Save jzellis/41038ac461433b32174a8c556f5aff76 to your computer and use it in GitHub Desktop.
Save jzellis/41038ac461433b32174a8c556f5aff76 to your computer and use it in GitHub Desktop.
Boilerplate for simple Mongoose user schema
/*
I find myself recreating user models for Mongoose every time I start a new project, so I thought I'd create a generic schema for a user model that can be added to or modified as need be.
This is loosely based on the Meteor user model (using a "profile" sub-object for the user's personal information). It also includes an optional geolocation point for the user, and Mongoose timestamps, as well as a pre("save") function to bcrypt the user password and a comparePassword() function.
Just save this file wherever you store your models and do something like const Users = include('./models/userSchema.js') and you can just use it as a standard Mongoose user model.
The username/email address definitions were copied from this tutorial: https://thinkster.io/tutorials/node-json-api/creating-the-user-model
*/
const mongoose = require('mongoose'),
Schema = mongoose.Schema,
uniqueValidator = require('mongoose-unique-validator'),
bcrypt = require('bcrypt'),
SALT_WORK_FACTOR = 10;
const Email = new Schema({
address: {type: String, lowercase: true, required: [true, "can't be blank"], match: [/\S+@\S+\.\S+/, 'is invalid'], index: true},
// Change the default to true if you don't need to validate a new user's email address
validated: {type: Boolean, default: false}
});
const Point = new mongoose.Schema({
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
});
const UserSchema = new Schema({
username: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/^[a-zA-Z0-9]+$/, 'is invalid'], index: true},
//Our password is hashed with bcrypt
password: { type: String, required: true },
email: {type: Email, required: true},
profile: {
firstName: String,
lastName: String,
avatar: String,
bio: String,
address: {
street1: String,
street2: String,
city: String,
state: String,
country: String,
zip: String,
location: {
type: Point,
required: false
}
}
},
active: {type: Boolean, default: true}
},{
timestamps:true
});
UserSchema.plugin(uniqueValidator, {message: 'is already taken.'});
UserSchema.pre("save", function(next) {
if(!this.isModified("password")) {
return next();
}
this.password = bcrypt.hashSync(this.password, 10);
next();
});
UserSchema.methods.comparePassword = function(plaintext, callback) {
return callback(null, bcrypt.compareSync(plaintext, this.password));
};
module.exports = mongoose.model("User", UserSchema);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment