import { IAuthDoc , authSchema } from './auth.model' ; import { Mongoose , Model } from 'mongoose' ; import * as bcrypt from 'bcryptjs' ; import * as mongoose from 'mongoose' ; import { getToken } from './utils' ; param _id return export const toObjectId = ( _id ) : mongoose . Types . ObjectId | null => { return ( mongoose . Types . ObjectId . isValid ( _id ) ) ? ( typeof _id === 'string' ) ? mongoose . Types . ObjectId . createFromHexString ( _id ) : _id : null ; } ; export class AuthRepo { private _model : Model < IAuthDoc > ; private _connected = true ; private _db : Mongoose ; private _serverConfig ; public get model ( ) { return this . _model ; } public get serverConfig ( ) { return this . _serverConfig ; } init ( db , serverConfig ) { if ( ! db ) return Promise . reject ( '{AuthRepo} DB not available!' ) ; if ( db . connection . readyState !== 1 ) return Promise . reject ( '{AuthRepo} DB not connected!' ) ; if ( ! serverConfig ) return Promise . reject ( '{AuthRepo} Auth repository must be started with server configuration' ) ; this . _serverConfig = serverConfig ; db . connection . once ( 'disconnect' , ( ) => { this . _connected = false ; } ) ; this . _db = db ; this . _model = this . _db . model < IAuthDoc > ( 'auths' , authSchema ) ; return Promise . resolve ( this ) ; } private _comparePassword ( docPassword , password ) { if ( ! docPassword ) { return false ; } return bcrypt . compareSync ( password , docPassword ) ; } public getToken ( doc ) { return getToken ( this . _serverConfig . secretTokent , + this . _serverConfig . jwtExpire , doc ) ; } async isAuth ( id ) { if ( ! this . _connected ) { return Promise . reject ( '{AuthRepo} DB not connected' ) ; } const auth = await this . _model . findById ( toObjectId ( id ) ) ; if ( ! auth || auth instanceof Error ) return Promise . reject ( `{AuthRepo} isAuth failed. User don't exist.` ) ; delete auth . password ; return { auth } ; } async auth ( email , password ) { if ( ! this . _connected ) { return Promise . reject ( '{AuthRepo} DB not connected' ) ; } const auth = await this . _model . findOne ( { email } ) ; if ( ! auth ) return Promise . reject ( `{AuthRepo} Authentication failed. User ${ email } not found.` ) ; if ( auth instanceof Error ) return Promise . reject ( `{AuthRepo} An error occured fetching a data with email: ${ email }` ) ; if ( ! this . _comparePassword ( auth . password , password ) ) { return Promise . reject ( '{AuthRepo} Authentication failed. Error with compare password.' ) ; } const token = this . getToken ( auth ) ; return { auth , token } ; } async create ( data ) { if ( ! this . _connected ) { return Promise . reject ( '{AuthRepo} DB not connected' ) ; } const { email , password } = data ; if ( ! email || ! password ) { return Promise . reject ( '{AuthRepo} AuthUser creation failed. Form fiels error' ) ; } let auth = await this . _model . findOne ( { email } ) ; if ( auth instanceof Error ) return Promise . reject ( '{AuthRepo} AuthUser creation error' ) ; if ( auth ) return Promise . reject ( '{AuthRepo} User email already exists' ) ; let hash = '' ; try { hash = bcrypt . hashSync ( password , 10 ) ; } catch ( err ) { return Promise . reject ( '{AuthRepo} Error with bcrypt hash password' ) ; } auth = await new this . _model ( { email , password : hash } ) . save ( ) ; if ( auth instanceof Error ) return Promise . reject ( '{AuthRepo} Error with save AuthUser into Auth.Collection' ) ; return { auth } ; } async signin ( reqBody ) { if ( ! this . _connected ) { return Promise . reject ( '{AuthRepo} DB not connected' ) ; } const { email , password } = reqBody ; if ( ! email || ! password ) { return Promise . reject ( '{AuthRepo} Signin failed. Form fiels error' ) ; } let auth = await this . _model . findOne ( { email } ) . catch ( err => err ) ; if ( auth instanceof Error ) return Promise . reject ( { code : 400 , message : '{AuthRepo} Sign in error' } ) ; if ( auth ) { console . log ( '--->' , auth ) ; return Promise . reject ( { code : 400 , message : '{AuthRepo} User email already exists' } ) ; } let hash = '' ; try { hash = bcrypt . hashSync ( password , 10 ) ; } catch ( err ) { return Promise . reject ( { code : 400 , message : '{AuthRepo} Error with bcrypt hash password' } ) ; } auth = await new this . _model ( { email , password : hash } ) . save ( ) ; if ( auth instanceof Error ) return Promise . reject ( { code : 400 , message : '{AuthRepo} Error with save AuthUser into Auth.Collection' } ) ; const token = this . getToken ( auth ) ; return { auth , token } ; } async update ( id , data ) { if ( ! this . _connected ) { return Promise . reject ( { code : 400 , message : '{AuthRepo} DB not connected' } ) ; } if ( ! id ) { return Promise . reject ( { code : 400 , message : '{AuthRepo} Object id not provided' } ) ; } if ( data ) { delete data . created ; delete data . _id ; delete data . __v ; } if ( ! data || Object . keys ( data ) . length === 0 ) { return Promise . reject ( { code : 400 , message : '{AuthRepo} Values to update not provided' } ) ; } if ( data . password ) { try { data . password = bcrypt . hashSync ( data . password , 10 ) ; } catch ( err ) { return Promise . reject ( { code : 400 , message : '{AuthRepo} Error with bcrypt hash password' } ) ; } } else { delete data . password ; } const auth = await this . _model . findOneAndUpdate ( { _id : toObjectId ( id ) } , data , { new : true } ) ; if ( auth instanceof Error ) return Promise . reject ( { code : 400 , message : '{AuthRepo} Error with update AuthUser' } ) ; return { auth } ; } async delete ( id ) { if ( ! this . _connected ) { return Promise . reject ( { code : 400 , message : '{AuthRepo} DB not connected' } ) ; } if ( ! id ) { return Promise . reject ( { code : 400 , message : '{AuthRepo} Object id not provided' } ) ; } const auth = await this . _model . findOneAndRemove ( { _id : toObjectId ( id ) } ) ; if ( auth instanceof Error ) return Promise . reject ( { code : 400 , message : '{AuthRepo} Unable to delete AuthUser' } ) ; return { auth } ; } }