Untitled

 avatar
unknown
plain_text
a year ago
4.3 kB
6
Indexable
// Import required modules
const crypto = require('crypto');
const mongoose = require('mongoose');
const validator = require('validator');
const bcrypt = require('bcryptjs');
const { type } = require('os');

// Define user schema
const userSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: [true, 'Please, tell us your name!'],
      unique: true
    },
    email: {
      type: String,
      required: [true, 'Please provide your email!'],
      unique: true,
      lowercase: true,
      validate: [validator.default.isEmail, 'Please provide a valid email address!']
    },
    phone: {
      type: String,
      required: [true, 'Please type your phone!']
    },
    password: {
      type: String,
      required: [true, 'Please provide a password'],
      minlength: 8,
      select: false
    },
    passwordConfirm: {
      type: String,
      required: [true, 'Please confirm your password'],
      validate: {
        // This only works on CREATE and SAVE
        validator: function (el) {
          return el === this.password;
        },
        message: 'Passwords are not the same'
      }
    },
    profile: {
      type: mongoose.Schema.Types.ObjectId,
      refPath: 'role'
    },
    passwordChangedAt: Date,
    passwordResetToken: String,
    passwordResetExpires: Date,
    profileImage: {
      type: String,
      default: 'default.jpg'
    },
    role: {
      type: String,
      enum: ['admin', 'partner', 'owner', 'agent']
    },
    commissionDetails:{
      type: mongoose.Schema.Types.Mixed
    },
    active: {
      type: Boolean,
      default: false,
      select: false
    }
  },
  {
    toJSON: { virtuals: true },
    toObject: { virtuals: true }
  }
);

// Middleware to hash password before saving to database
userSchema.pre('save', async function (next) {
  // Only run if password is modified
  if (!this.isModified('password')) return next();

  // Hash new password
  this.password = await bcrypt.hash(this.password, 12);

  // Delete passwordConfirm field
  this.passwordConfirm = undefined;
  next();
});

// Middleware to update passwordChangedAt field when password is changed
userSchema.pre('save', function (next) {
  if (!this.isModified('password') || this.isNew) return next();

  this.passwordChangedAt = Date.now() - 1000;
  next();
});

// Middleware to eliminate inactive users from find queries
userSchema.pre(/^find/, function (next) {
  this.find({ active: { $ne: true } });
  next();
});

// Method to verify if passwords match
userSchema.methods.correctPassword = async function (candidatePassword, userPassword) {
  return await bcrypt.compare(candidatePassword, userPassword);
};

// Method to check if password was changed after token was issued
userSchema.methods.changedPasswordAfter = function (JWTTimestamp) {
  if (this.passwordChangedAt) {
    const changedTimeStamp = parseInt(this.passwordChangedAt.getTime() / 1000, 10);
    return changedTimeStamp > JWTTimestamp;
  }

  // False means NOT changed
  return false;
};

// Method to create password reset token
userSchema.methods.createPasswordResetToken = function () {
  const resetToken = crypto.randomBytes(32).toString('hex');
  this.passwordResetToken = crypto.createHash('sha256').update(resetToken).digest('hex');

  // valid for 10 minutes
  this.passwordResetExpires = Date.now() + 10 * 60 * 1000;

  return resetToken;
};

//Handling Different User Roles
userSchema.pre('save', function(next) {
  if (this.role === 'agent') {
    // Set roleData to the agent role data structure
    this.commissionDetails = {
      commission: {
        type: Number,
        required: [true, 'Please provide commission percentage!']
      },
      currency: {
        type: String,
        required: [true, 'Please provide Currency']
      },
      target: {
        type: Number,
        required: [true, 'Please provide a target']
      },
      invoiceTime: {
        type: String,
        required: [true, 'Please provide an invoice time']
      }
    };
  }
  next();
});


// Create User model from schema
const User = mongoose.model('User', userSchema);
// Export User model
module.exports = User;
Editor is loading...
Leave a Comment