import * as bcrypt from 'bcryptjs' ; import { AggregationCursor , ObjectID } from 'mongodb' ; import { CollectionFactory , Document , IDocument } from 'document-ts' ; import { v4 as uuid } from 'uuid' ; export interface IUser extends IDocument { email ? : string ; firstName ? : string ; lastName ? : string ; role ? : string ; } swagger export class User extends Document < IUser > implements IUser { static collectionName = 'users' ; private password = '' ; constructor ( public email = '' , public firstName = '' , public lastName = '' , public role = '' ) { super ( User . collectionName , { email , firstName , lastName , role , } as IUser ) ; } public static Builder ( user ) { if ( ! user ) { return new User ( ) ; } return new User ( user . email , user . firstName , user . lastName , user . role ) ; } getCalculatedPropertiesToInclude ( ) { return [ 'fullName' ] ; } getPropertiesToExclude ( ) { return [ 'password' ] ; } public get fullName ( ) : string { return `${ this . firstName } ${ this . lastName }` ; } async create ( firstName , lastName , email , role , password ? ) { this . firstName = firstName ; this . lastName = lastName ; this . email = email ; this . role = role ; if ( ! password ) { password = uuid ( ) ; } this . password = await this . setPassword ( password ) ; await this . save ( ) ; } async resetPassword ( newPassword ) { this . password = await this . setPassword ( newPassword ) ; await this . save ( ) ; } private setPassword ( newPassword ) { return new Promise < string > ( function ( resolve , reject ) { bcrypt . genSalt ( 10 , function ( err , salt ) { if ( err ) { return reject ( err ) ; } bcrypt . hash ( newPassword , salt , function ( err , hash ) { if ( err ) { return reject ( err ) ; } resolve ( hash ) ; } ) ; } ) ; } ) ; } comparePassword ( password ) { let user = this ; return new Promise ( function ( resolve , reject ) { bcrypt . compare ( password , user . password , function ( err , isMatch ) { if ( err ) { return reject ( err ) ; } resolve ( isMatch ) ; } ) ; } ) ; } hasSameId ( id ) { return this . _id . toHexString ( ) === id . toHexString ( ) ; } } class UserCollectionFactory extends CollectionFactory < User > { constructor ( docType ) { super ( User . collectionName , docType , [ 'firstName' , 'lastName' , 'email' ] ) ; } async createIndexes ( ) { await this . collection ( ) . createIndexes ( [ { key : { email : 1 , } , unique : true , } , { key : { firstName : 'text' , lastName : 'text' , email : 'text' , } , weights : { lastName : 4 , firstName : 2 , email : 1 , } , name : 'TextIndex' , } , ] ) ; } userSearchQuery ( searchText ) { let aggregateQuery = [ { $match : { $text : { $search : searchText } , } , } , { $project : { email : 1 , } , } , ] ; if ( searchText === undefined || searchText === '' ) { delete ( aggregateQuery [ 0 ] as any ) . $match . $text ; } return this . collection ( ) . aggregate ( aggregateQuery ) ; } } export let UserCollection = new UserCollectionFactory ( User ) ;