@ -13,28 +13,40 @@ var sanitize = require('mongo-sanitize');
var crypto = require ( 'crypto' ) ;
var methods = { } ;
// connect
mongoose . connect ( global [ 'gds' ] . cfg . mongoose . uri , {
useNewUrlParser : true
} ) ;
mongoose . set ( 'useFindAndModify' , false ) ;
global [ 'gds' ] . db = mongoose . connection ;
var log = require ( global [ '__dirname' ] + '/bin/logs/module' ) ;
var cfg = require ( global [ '__dirname' ] + '/bin/config' ) ;
var db ;
var mdls = require ( './models.js' ) ;
var models = mdls ( global [ 'gds' ] . db ) ;
var models ;
( async function ( ) {
global [ 'gds' ] . db = await global [ 'gds' ] . db . useDb ( global [ 'gds' ] . cfg . mongoose . db ) ;
/ * *
* connects to db
* @ author Ruben Meyer
* @ async
* /
methods . connect = async ( ) => {
if ( typeof db !== "undefined" ) return ;
// connect
mongoose . connect ( cfg . mongoose . uri , {
useNewUrlParser : true ,
useUnifiedTopology : true ,
useFindAndModify : false
} ) ;
models = mdls ( global [ 'gds' ] . db ) ;
} ) ( ) ;
// connection error handling
global [ 'gds' ] . db . on ( 'error' , ( data ) => {
global [ 'modules' ] . logs . error ( 'MongoDB connection error:\n' , data ) ;
process . exit ( ) ; // exit on connection error
} ) ;
db = mongoose . connection ;
db = await db . useDb ( cfg . mongoose . db ) ;
models = mdls ( db ) ;
// connection error handling
db . on ( 'error' , ( data ) => {
log . error ( 'MongoDB connection error:\n' , data ) ;
process . exit ( ) ; // exit on connection error
} ) ;
}
// // // //////// //////// ///////
// // // // // // //
@ -47,19 +59,19 @@ global['gds'].db.on('error', (data) => {
/ * *
* Adds User to Database
* @ author Ruben Meyer
* @ param { String } nick nickname
* @ param { String } email email
* @ param { String } passhash hashed password
* @ param { Number } group Group id ( normally 0 - > user )
* @ param { Function } callback Callback function ( error , reply )
* @ author Ruben Meyer
* @ async
* @ param { String } nick nickname
* @ param { String } email email
* @ param { String } passhash hashed password
* @ param { Number } group Group id ( normally 0 - > user )
* @ return { Array } async ( reply , err )
* /
methods . addUser = ( nick , email , passhash , group , callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
if ( typeof nick !== 'string' ) return callback ( new TypeError ( 'nick is not a string::database.addUser(' + nick + ',' + email + ',' + passhash + ',' + group + ',callback)' , module . filename ) ) ;
if ( typeof email !== 'string' ) return callback ( new TypeError ( 'email is not a string::database.addUser(' + nick + ',' + email + ',' + passhash + ',' + group + ',callback)' , module . filename ) ) ;
if ( typeof passhash !== 'string' ) return callback ( new TypeError ( 'passhash is not a string::database.addUser(' + nick + ',' + email + ',' + passhash + ',' + group + ',callback)' , module . filename ) ) ;
if ( isNaN ( group ) ) return callback ( new TypeError ( 'group is not a number::database.addUser(' + nick + ',' + email + ',' + passhash + ',' + group + ',callback)' , module . filename ) ) ;
methods . addUser = async ( nick , email , passhash , group ) => {
if ( typeof nick !== 'string' ) return { err : new TypeError ( 'nick is not a string::database.addUser(' + nick + ',' + email + ',' + passhash + ',' + group + ')' , module . filename ) } ;
if ( typeof email !== 'string' ) return { err : new TypeError ( 'email is not a string::database.addUser(' + nick + ',' + email + ',' + passhash + ',' + group + ')' , module . filename ) } ;
if ( typeof passhash !== 'string' ) return { err : new TypeError ( 'passhash is not a string::database.addUser(' + nick + ',' + email + ',' + passhash + ',' + group + ')' , module . filename ) } ;
if ( isNaN ( group ) ) return { err : new TypeError ( 'group is not a number::database.addUser(' + nick + ',' + email + ',' + passhash + ',' + group + ')' , module . filename ) } ;
let userModel = models . user ;
@ -69,70 +81,70 @@ methods.addUser = (nick, email, passhash, group, callback) => {
user . passhash = sanitize ( passhash ) ;
user . group = sanitize ( group ) ;
user . save ( ( err ) => {
if ( ! err ) callback ( null , 1 ) ;
else callback ( err ) ;
} ) ;
try {
reply = await user . save ( ) ;
return { reply : 1 } ;
} catch ( err ) {
return { err : err } ;
}
} ;
/ * *
* Deletes User from D atabase
* deletes user identified by haystack from d atabase
* @ author Ruben Meyer
* @ TODO
* @ async
* @ TODO add functionality
* @ param { String } haystack email or nick
* @ param { Function } callback Callback function ( error , reply )
* @ return { Array } async ( reply , err )
* /
methods . delUser = ( haystack , callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
if ( typeof haystack !== 'string' ) return callback ( new TypeError ( 'haystack is not a string::database.delUser(' + haystack + ',callback)' , module . filename ) ) ;
methods . delUser = async ( haystack ) => {
if ( typeof haystack !== 'string' ) return { err : new TypeError ( 'haystack is not a string::database.delUser(' + haystack + ')' , module . filename ) } ;
let userModel = models . user ;
// sanitize input
haystack = sanitize ( haystack ) ;
userModel . findOneAndDelete ( ) . or ( [ { nickname : haystack } , { email : haystack } ] )
. then ( ( rep ) => {
// TODO delete user
global [ 'logs' ] . debug ( 'deleted user: ' + haystack ) ;
callback ( null , 1 ) ;
} ) . catch ( ( err ) => {
callback ( err ) ;
} ) ;
try {
reply = await userModel . findOneAndDelete ( ) . or ( [ { nickname : haystack } , { email : haystack } ] ) . exec ( ) ;
log . debug ( 'deleted user: ' + haystack ) ;
return { reply : 1 } ;
} catch ( err ) {
return { err : err } ;
}
} ;
/ * *
* get all users
* @ author Ruben Meyer
* @ param { Function } callback Callback function ( reply - > Array users )
* @ async
* @ return { Array } async ( reply , err )
* /
methods . getUsers = ( callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
methods . getUsers = async ( ) => {
let userModel = models . user ;
userModel . find ( { } )
. then ( ( users ) => {
try {
users = await userModel . find ( { } ) . exec ( ) ;
if ( users . length > 0 )
return callback ( null , users ) ;
return { reply : users } ;
else
return callback ( null , false ) ;
} ) . catch ( ( err ) => {
return callback ( err ) ;
} ) ;
return { reply : false } ;
} catch ( err ) {
return { err : err } ;
}
} ;
/ * *
* query users by email , nickname or rememberme token
* query users by UUID , email , nickname or rememberme token
* @ author Ruben Meyer
* @ async
* @ param { String | String [ ] } haystack email or nick
* @ param { Function } callback Callback function ( reply - > Array users )
* @ return async ( reply , err )
* /
methods . getUser = ( haystack , callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
if ( typeof haystack !== 'string' && typeof haystack !== 'object' ) return callback ( new TypeError ( 'email or nickname is not a string|object::database.getUser(' + haystack + ',callback)' , module . filename ) ) ;
methods . getUser = async ( haystack ) => {
if ( typeof haystack !== 'string' && typeof haystack !== 'object' ) return { err : new TypeError ( 'email or nickname is not a string|object::database.getUser(' + haystack + ')' , module . filename ) } ;
let userModel = models . user ;
@ -154,35 +166,39 @@ methods.getUser = (haystack, callback) => {
}
}
userModel . find ( ) . or ( or )
. then ( ( users ) => {
try {
users = await userModel . find ( ) . or ( or ) . exec ( ) ;
if ( users . length > 0 )
return callback ( null , users ) ;
return { reply : users } ;
else
return callback ( null , false ) ;
} ) . catch ( ( err ) => {
return callback ( err ) ;
} ) ;
return { reply : false } ;
} catch ( err ) {
return { err : err } ;
}
} ;
/ * *
* updates obj keys in user entry
* @ author Ruben Meyer
* @ async
* @ param { Number } id User ID
* @ param { Object } obj data
* @ param { Function } callback Callback function
* @ return { Array } async ( reply , err )
* /
methods . updateUser = ( id , obj , callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
if ( typeof id !== 'string' ) return callback ( new TypeError ( 'id is not a string::database.updateUser(' + id + ',' + JSON . stringify ( obj ) + ',callback)' , module . filename ) ) ;
if ( typeof obj !== 'object' ) return callback ( new TypeError ( 'obj is not an object::database.updateUser(' + id + ',' + JSON . stringify ( obj ) + ',callback)' , module . filename ) ) ;
methods . updateUser = async ( id , obj ) => {
if ( typeof id !== 'string' ) return { err : new TypeError ( 'id is not a string::database.updateUser(' + id + ',' + JSON . stringify ( obj ) + ')' , module . filename ) } ;
if ( typeof obj !== 'object' ) return { err : new TypeError ( 'obj is not an object::database.updateUser(' + id + ',' + JSON . stringify ( obj ) + ')' , module . filename ) } ;
let userModel = models . user ;
userModel . findByIdAndUpdate ( id , obj , ( err , data ) => {
if ( err ) callback ( err ) ;
else callback ( null , data ) ;
} ) ;
try {
data = await userModel . findByIdAndUpdate ( id , obj ) . exec ( ) ;
return { data : data } ;
} catch ( err ) {
return { err : err } ;
}
} ;
@ -190,43 +206,49 @@ methods.updateUser = (id, obj, callback) => {
/ * *
* updates data based on login
* @ author Ruben Meyer
* @ async
* @ TODO UPDATE METHOD ; PROBABLY OUTDATED
* @ param { Number } id User ID
* @ param { Object } data data JSON - > remember
* @ param { Function } callback Callback function ( date => 'Login Date' , token => 'RememberMe Cookie Token' )
* @ return { Array } async ( { date => 'Login Date' , token => 'RememberMe Cookie Token' } , err )
* /
methods . addActivity = ( id , data , callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
if ( typeof id !== 'string' ) return callback ( new TypeError ( 'id is not a string::database.updateNewAction(' + id + ',' + JSON . stringify ( options ) + ',callback)' , module . filename ) ) ;
if ( typeof options !== 'object' && options !== null ) return callback ( new TypeError ( 'obj is not an object::database.updateUserProfile(' + id + ',' + JSON . stringify ( obj ) + ',callback)' , module . filename ) ) ;
methods . addActivity = async ( id , data ) => {
if ( typeof id !== 'string' ) return { err : new TypeError ( 'id is not a string::database.updateNewAction(' + id + ',' + JSON . stringify ( options ) + ')' , module . filename ) } ;
if ( typeof options !== 'object' && options !== null ) return { err : new TypeError ( 'obj is not an object::database.updateUserProfile(' + id + ',' + JSON . stringify ( obj ) + ')' , module . filename ) } ;
let date = new Date ( ) . toISOString ( ) ;
let timestamp = new Date ( date ) . getTime ( ) ;
functions . updateUserProfile ( id , {
last_action : date
} , ( err , rep ) => {
if ( err ) return callback ( err ) ;
try {
reply = await methods . updateUser ( id , {
last_action : date
} ) ;
if ( options . rememberme && options . new_token !== false ) {
var token = ( [ 1e7 ] + - 1e3 + - 4e3 + - 8e3 + - 1e11 ) . replace ( /[018]/g , ( c ) => ( c ^ crypto . randomBytes ( new Uint8Array ( 1 ) . length ) [ 0 ] & 15 >> c / 4 ) . toString ( 16 ) ) ;
var Remember = models . remember ;
Remember . findOneAndUpdate ( { userId : id } , { token : token , timestamp : Date . now ( ) } , { upsert : true } , ( err1 , data ) => {
if ( err1 ) callback ( err1 ) ;
return callback ( null , {
try {
data = await Remember . findOneAndUpdate ( { userId : id } , { token : token , timestamp : Date . now ( ) } , { upsert : true } ) . exec ( ) ;
return { reply : {
date : date ,
timestamp : timestamp ,
token : token
} ) ;
} ) ;
} } ;
}
catch ( err ) {
return { err : err } ;
}
} else {
callback ( null , {
return { reply : {
date : date ,
timestamp : timestamp ,
token : options . old_token
} ) ;
} } ;
}
} ) ;
} catch ( err ) {
return { err : err } ;
}
} ;
@ -241,27 +263,28 @@ methods.addActivity = (id, data, callback) => {
/ * *
* get Applications
* @ author Ruben Meyer
* @ param { Function } callback Callback function ( err , apps )
* @ async
* @ return { Array } async ( apps , err )
* /
methods . getApps = ( callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
methods . getApps = async ( ) => {
var Application = models . application ;
Application . find ( { } , ( err , apps ) => {
if ( err ) callback ( err ) ;
else callback ( null , apps ) ;
} ) ;
try {
apps = await Application . find ( { } ) . exec ( ) ;
return { reply : apps } ;
} catch ( err ) {
return { err : err } ;
}
} ;
/ * *
* return auth obj
* @ author Ruben Meyer
* @ async
* @ param { Object } obj data obj ( aId , uId )
* @ param { Function } callback Callback function ( err , obj ) obj - > ( aId , uId , token )
* @ return { Array } async ( { timestamp , token } , err )
* /
methods . setAuthCode = ( obj , callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
if ( typeof obj !== 'object' ) return callback ( new TypeError ( 'obj is not an object::database.setAuthCode(' + JSON . stringify ( obj ) + ',callback)' , module . filename ) ) ;
methods . setAuthCode = async ( obj ) => {
if ( typeof obj !== 'object' ) return { err : new TypeError ( 'obj is not an object::database.setAuthCode(' + JSON . stringify ( obj ) + ')' , module . filename ) } ;
var AuthCode = models . authCode ;
@ -275,74 +298,80 @@ methods.setAuthCode = (obj, callback) => {
timestamp : Date . now ( )
} ;
AuthCode . findOneAndUpdate ( query , change , { upsert : true } , ( err1 , data ) => {
if ( err1 ) callback ( err1 ) ;
return callback ( null , {
try {
data = await AuthCode . findOneAndUpdate ( query , change , { upsert : true } ) . exec ( ) ;
return { reply : {
timestamp : change . timestamp ,
token : change . token
} ) ;
} ) ;
} } ;
} catch ( err ) {
return { err : err } ;
}
} ;
/ * *
* return auth obj
* @ author Ruben Meyer
* @ async
* @ param { Object } obj data obj ( aId , aSecret , uId , token )
* @ param { Function } callback Callback function ( err , bool )
* @ return { Array } async ( bool , err )
* /
methods . getAuth = ( obj , callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
if ( typeof obj !== 'object' ) return callback ( new TypeError ( 'obj is not an object::database.getAuthCode(' + JSON . stringify ( obj ) + ',callback)' , module . filename ) ) ;
methods . getAuth = async ( obj ) => {
if ( typeof obj !== 'object' ) return { err : new TypeError ( 'obj is not an object::database.getAuthCode(' + JSON . stringify ( obj ) + ')' , module . filename ) } ;
var AuthCode = models . authCode ;
AuthCode . findOne ( {
$and : [
{ applicationId : mongoose . Types . ObjectId ( obj . aId ) } ,
{ userId : mongoose . Types . ObjectId ( obj . uId ) } ,
{ token : obj . token }
]
} , ( err , data ) => {
if ( err ) callback ( err ) ;
else {
if ( typeof data === "object" ) {
if ( data === null || data === [ ] ) return callback ( null , false ) ;
var Application = models . application ;
Application . findOne ( {
try {
data = await AuthCode . findOne ( {
$and : [
{ applicationId : mongoose . Types . ObjectId ( obj . aId ) } ,
{ userId : mongoose . Types . ObjectId ( obj . uId ) } ,
{ token : obj . token }
]
} ) . exec ( ) ;
if ( typeof data === "object" ) {
if ( data === null || data === [ ] ) return { reply : false } ;
var Application = models . application ;
try {
data1 = await Application . findOne ( {
$and : [
{ _ id : mongoose . Types . ObjectId ( obj . aId ) } ,
{ secret : obj . aSecret }
]
} , ( err1 , data1 ) => {
if ( err1 ) callback ( err1 ) ;
else {
if ( obj . token == data . token
&& obj . aId == String ( data . applicationId )
&& obj . uId == String ( data . userId )
&& obj . aSecret == data1 . secret ) {
callback ( null , true ) ;
//functions.setAuthCode({
// aId: obj.aId,
// uId: obj.uId
//}, () => {});
}
else callback ( null , false ) ;
}
} ) ;
} else callback ( null , false ) ;
}
} ) ;
} ) . exec ( ) ;
if ( obj . token == data . token
&& obj . aId == String ( data . applicationId )
&& obj . uId == String ( data . userId )
&& obj . aSecret == data1 . secret ) {
return { reply : true } ;
//methods.setAuthCode({
// aId: obj.aId,
// uId: obj.uId
//});
}
else return { reply : false } ;
} catch ( err ) {
return { err : err } ;
}
} else return { reply : false } ;
} catch ( err ) {
return { err : err } ;
}
} ;
/ * *
* return if app is permitted to do access call
* @ author Ruben Meyer
* @ async
* @ param { Object } obj data obj ( aId , redirectUrl )
* @ param { Function } callback Callback function ( err , bool )
* @ return { Array } async ( bool , err )
* /
methods . verifyAppCall = ( obj , callback ) => {
methods . verifyAppCall = async ( obj ) => {
return { } ;
} ;
// //////// //////// //////// //////// ////////
@ -354,17 +383,20 @@ methods.verifyAppCall = (obj, callback) => {
////////////////////////////////////////////////////////
/ * *
* callback with user count
* returns user count
* @ author Ruben Meyer
* @ param { Function } callback Callback function ( reply - > int )
* @ async
* @ return { Array } async ( int , err )
* /
methods . userCount = ( callback ) => {
if ( typeof callback !== 'function' ) callback = function ( ) { } ;
methods . userCount = async ( ) => {
let userModel = models . user ;
userModel . countDocuments ( { } , ( err , count ) => {
callback ( ( err ) ? err : count ) ;
} ) ;
try {
count = await userModel . countDocuments ( { } ) . exec ( ) ;
return { reply : count } ;
} catch ( err ) {
return { err : err } ;
}
} ;