import bcrypt from "bcrypt-nodejs" ; import mongoose , { Model , Schema } from "mongoose" ; import UserDocument , { ComparePasswordFunction } from "./UserDocument" ; import storage , { CONTAINER_AVATAR } from "../../repository/storage" ; import { getBlobNameFromUrl } from "../../repository/utils" ; export const userSchema = new mongoose . Schema ( { email : { type : String , unique : true } , password : String , name : { type : String , unique : true } , gender : String , address : String , website : String , avatarUrl : String , preferences : { type : Map , of : String } , OTP : String , otpExpireTime : Date , invitationCode : String } , { timestamps : true } ) ; /**
 * Password hashing & Signing Url middleware.
 */ userSchema . pre ( "save" , function save ( next ) { const user = this ; if ( user && user . email ) { user . email = user . email . toLowerCase ( ) ; } if ( user && user . avatarUrl ) { const sasAvatarUrl = user . avatarUrl ; user . avatarUrl = sasAvatarUrl . substring ( 0 , sasAvatarUrl . indexOf ( "?" ) ) ; } if ( ! user . isModified ( "password" ) ) { return next ( ) ; } bcrypt . genSalt ( 10 , ( err , salt ) => { if ( err ) { return next ( err ) ; } bcrypt . hash ( user . password as string , salt , null , ( err , hash ) => { if ( err ) { return next ( err ) ; } user . password = hash ; next ( ) ; } ) ; } ) ; } ) ; export const postFind = ( user , next ? ) => { if ( user && user . avatarUrl ) { const avatarFilename = getBlobNameFromUrl ( user . avatarUrl ) ; user . avatarUrl = `${ user . avatarUrl }?${ storage . generateSigningUrlParams ( CONTAINER_AVATAR , avatarFilename ) }` ; } if ( next ) { next ( ) ; } } ; userSchema . post ( "findOne" , postFind ) ; const comparePassword = function ( this , candidatePassword , cb ) { bcrypt . compare ( candidatePassword , this . password , ( err , isMatch ) => { cb ( err , isMatch ) ; } ) ; } ; userSchema . methods . comparePassword = comparePassword ; const UserCollection = mongoose . model ( "User" , userSchema ) ; export default UserCollection ;