nooljs
Version:
Full stack JavaScript framework created top of Nodejs, express, and Socket-io, and Angularjs
565 lines (471 loc) • 16.7 kB
JavaScript
// noolServer.js 0.1.0
// Copyright (c) 2016 Chandru Krishnar <chandru0507@gmail.com>
// MIT
module.exports = function () {
var $config = {};
var $connection = {};
var _serverF = {};
var _dbAdapter = {};
var $permission = {};
var _Q = {};
var _fs = {};
var _layoutParser = {};
var _noolApi = {};
var $users = {};
var $serverMethods = [];
var path = require("path");
var requireDirectory = require('require-directory');
var dbConnection = requireDirectory (module, "../db");
_monitorServerMethodsTimeout = 60000; // 60 sec
readFile = function (fileName) {
var deferred = _Q.defer();
try
{
_fs.readFile(fileName, function (err, data) {
if (!err)
deferred.resolve(data);
else
deferred.reject(err);
});
}
catch(err)
{
deferred.reject(err);
}
return deferred.promise;
};
getConnection = function (name) {
for (var i in $connection) {
if ($connection[i].name == name)
return $connection[i];
}
return null;
};
clearServerMethod=function(fileName)
{
for( var i in $serverMethods)
{
if($serverMethods[i].name==fileName)
{
$serverMethods.splice(i,1);
return;
}
}
};
getServerMethod= function(fileName)
{
for( var i in $serverMethods)
{
//console.log( "getServerMethod %s current name : %s, filename : %s",i, $serverMethods[i].name, fileName);
if($serverMethods[i].name==fileName)
{
// console.log(" getServerMethod %s selected current name : %s, filename : %s",i, $serverMethods[i].name, fileName);
return $serverMethods[i];
}
}
}
executeServerMethod =function(fileName, methodName, args, callback, user)
{
var result = {};
var serverMethod = getServerMethod(fileName);
if(serverMethod && serverMethod.fun, serverMethod.fun[methodName] && serverMethod.fun[methodName].method)
{
serverMethod = serverMethod.fun[methodName];
// validate the permission
if(serverMethod.permission)
{
// we have permission name
//validate it
if(!validatePermission(serverMethod.permission, user, $config, $permission))
{
result.error= {code:"INVALID_PERMISSION", message:"Server method " + fileName + "." + methodName + " does not have permission."};
if(callback)
callback(result);
return;
}
console.log("executeServerMethod starting ... serverMethod %s has valid permission %s",serverMethod , serverMethod.permission);
}
try
{
console.log("executeServerMethod executing ... serverMethod %s , args:%s",serverMethod, JSON.stringify(args)) ;
var obj = {
$user:user,
$config:$config,
$connection:$connection
};
// args.push(callback);
result.data = serverMethod.method.apply(obj, JSON.parse(args));
console.log("executeServerMethod ... serverMethod %s executed. result: %s",serverMethod , result.data);
}
catch(err)
{
console.log("executeServerMethod executing ... serverMethod %s has error %s",serverMethod , err);
result.error = {code:"SERVER_ERROR", message:JSON.stringify(err)};
//if(callback)
// callback(result.error, null);
}
}
else{
result.error= {code:"INVALID_METHOD", message:"Server method " + fileName + "." + methodName + " is not fond."};
console.log("executeServerMethod error :%s",result.error);
}
if(callback)
{
console.log("executeServerMethod callback error :%s, data:%s",result.error, result.data);
callback(result);
}
};
monitorServerMethods =function()
{
loadAllServerMethods(_fs, "SereverMethods");
}
loadAllServerMethods =function(fs, directoryName){
fs.readdir(directoryName, function(err, filenames)
{
if(err)
return;
filenames.forEach(function(fileName){loadServerMethods( fs, fileName.substr(0, fileName.lastIndexOf('.')) , directoryName)});
});
};
loadServerMethods = function(fs, fileName, directoryName){
console.log("loadServerMethods readFile :%s" , (directoryName + "/" + fileName + ".js" ) );
var path = directoryName + "/" + fileName + ".js";
var fileStat = fs.statSync(path);
var serverMethod = getServerMethod(fileName);
if(serverMethod)
{
if(serverMethod.stat < fileStat)
{
//clear existing queries for this file
clearServerMethod(fileName);
}
else
return; // file upto date.. no need to re-parser it
}
return readFile( path)
.then(function (data)
{
data = data.toString();
var obj = eval("x="+ data);
$serverMethods.push({name:fileName,fun:obj, stat:fileStat});
})
.catch(function (err){
console.log("loadServerMethods file name :%s err :",fileName, err);
});
};
nlServerLogout = function (methodName, typeName, template, data, $scope, serverF, callback, _userKey_) {
//first remove user from user list
if (_userKey_)
$users.removeUser(_userKey_);
$scope.data = {};
$scope.data.url =$config.logout;
if(callback)
{
callback($scope);
}
};
nlDbLogin = function (methodName, typeName, template, data, $scope, serverF, callback, _userKey_) {
_Q.spawn(function * () {
var query = _layoutParser.getQuery(methodName);
var conn = getConnection($config.defaultConnection);
var result ={};
try{
result = yield dbConnection[conn.type].execute(conn.config, query.queryString, data);
}
catch(error)
{
$scope.error = {code:"SERVER_ERROR", message:error};
callback($scope);
return;
}
if (Array.isArray(result) && result.length == 1)
result = result[0];
if ($config.userid && result && result[$config.userid] && result[$config.userid] > 0) {
// login successfully
var user = result;
var userKey = $users.createSession(user);
$scope.data._userKey_ = userKey;
$scope.data.user = user;
bSessionCreated = true;
} else {
$scope.error = {
code : ((result && result.errorcode) ? result.errorcode : "INVALID_LOGIN"),
message : (((result && result.errormessage) ? result.errormessage : " login username/password"))
};
}
callback($scope);
});
};
nlDbClick = function (methodName, typeName, template, data, $scope, serverF, callback, _userKey_) {
_Q.spawn(function * () {
//first remove user from user list
try
{
var query = _layoutParser.getQuery(methodName);
var conn = getConnection($config.defaultConnection);
$scope.data = yield dbConnection[conn.type].execute(conn.config, query.queryString, data);
}
catch(err)
{
console.log('nlDbClick catch error : %s', JSON.stringify(err));
$scope.error = {code:"SERVER_ERROR", message:JSON.stringify(err)};
}
callback($scope);
});
};
nlDbData = function (methodName, typeName, template, data, $scope, serverF,callback, _userKey_) {
_Q.spawn(function * () {
//first remove user from user list
try{
var query = _layoutParser.getQuery(methodName);
var conn = getConnection($config.defaultConnection);
if (query.queryString.endsWith(".json")) {
//this is jon file
conn = getConnection("jsonFile");
}
$scope.data = yield dbConnection[conn.type].execute(conn.config, query.queryString, data);
}
catch(err)
{
console.log('nlDbData catch error : %s', JSON.stringify(err));
$scope.error = {code:"SERVER_ERROR", message:JSON.stringify(err)};
}
callback($scope);
});
};
nlServerClick = function (methodName, typeName, template, data, $scope, serverF, callback, _userKey_) {
return nlServerProcess(methodName, typeName, template, data, $scope, serverF, callback, _userKey_);
};
nlServerData = function (methodName, typeName, template, data, $scope, serverF, callback, _userKey_) {
return nlServerProcess(methodName, typeName, template, data, $scope, serverF, callback, _userKey_);
};
nlServerLogin = function (methodName, typeName, template, data, $scope, serverF, callback, _userKey_) {
return nlServerProcess(methodName, typeName, template, data, $scope, serverF, callback, _userKey_);
};
nlServerProcess = function (methodName, typeName, template, data, $scope, serverF, callback , _userKey_) {
_Q.spawn(function * () {
var error, result2;
try{
var bSessionCreated = false;
$scope = nameValueToObj(data);
if (!$scope)
$scope = {};
//get the server object
var serverFunObj = _layoutParser.getServerFunction(template, methodName);
serverFun = serverFunObj.fun;
// execure server function if available
if (typeof serverFun.server == "function") {
// we have server function execute it
var result = serverFun.server($scope);
//check whether it is login process
if (typeName == 'nlServerLogin' && $scope.user && $config.userid && $scope.user[$config.userid] && $scope.user[$config.userid] > 0 && !bSessionCreated) {
// login sucecssfull
var user = $scope.user;
var userKey = $users.createSession(user);
$scope._userKey_ = userKey;
bSessionCreated = true;
}
// if the server function return false then exist
if (result == false)
{
result2 = {data:$scope};
if($scope && $scope._error) {
// remove error objerct from scope
var error = $scope._error;
$scope._error = undefined;
result2 = {data:$scope,error:error};
}
callback(result2);
return;
}
}
if (serverFun.db && serverFun.db.query)
{
//$scope[serverFunObj.model] = yield serverF.sqlserver['dbData'](serverFun.db.query, layoutParser.objToNameValue($scope));
var conn = getConnection(((serverFun.db.connection) ? serverFun.db.connection : $config.defaultConnection));
var result = yield dbConnection[conn.type].execute(conn.config, serverFun.db.query, _layoutParser.objToNameValue($scope));
$scope[serverFunObj.model] = result ; //yield serverF[conn.type].execute(conn.config, serverFun.db.query, _layoutParser.objToNameValue($scope));
if (serverFun.db.resultType && serverFun.db.resultType == 'single') {
// get only first row of the result set
if ($scope[serverFunObj.model] && Array.isArray($scope[serverFunObj.model]) == true && $scope[serverFunObj.model].length > 0)
$scope[serverFunObj.model] = $scope[serverFunObj.model][0];
}
//check whether it is login process
if (typeName == 'nlServerLogin' && $scope.user && $config.userid && $scope.user[$config.userid] && $scope.user[$config.userid] > 0 && !bSessionCreated) {
// login sucecssfull
var user = $scope.user;
var userKey = $users.createSession(user);
$scope._userKey_ = userKey;
bSessionCreated = true;
}
}
if (typeof serverFun.post == "function")
{
// we have post server function execute it
serverFun.post($scope, _noolApi);
//check whether it is login process
if (typeName == 'nlServerLogin' && $scope.user && $config.userid && $scope.data.user[$config.userid] && $scope.user[$config.userid] > 0 && !bSessionCreated) {
// login successfully
var user = $scope.user;
var userKey = $users.createSession(user);
$scope._userKey_ = userKey;
bSessionCreated = true;
}
}
if($scope && $scope._error){
// remove error objerct from scope
error = $scope._error;
$scope._error = undefined;
}
}
catch(err)
{
console.log('nServerProcess catch error : %s',(typeof(err) == 'object' ? JSON.stringify(err) : err));
error = { code: "SERVER_ERROR", message: (typeof (err) == 'object' ? JSON.stringify(err) : err)};
}
callback({data:$scope,error:error});
});
};
validatePermission = function (permissionName, user, $config, $permission) {
// if permission name is empty need not be validate
if (!permissionName)
return true;
var bValidated = false;
if(!user )
{
console.log("validatePermission empty user");
return false;
}
for (var i in $permission) {
var p = $permission[i];
if (user[p.userKey] == p.userValue) {
// we found matching object
if (p.permission == "*") {
// for * all the permissions are allowed
return true;
}
//check whether permission exists in the array
for (var j in p.permission) {
// we have found matching permission. return true.
if (p.permission[j] == permissionName)
return true;
}
}
}
return bValidated;
};
init = function (Q, fs, serverF, layoutParser, monitorTimeout) {
_Q = Q;
_fs = fs;
_serverF = serverF;
_layoutParser = layoutParser;
//initialize layout parser
_layoutParser.init(fs, monitorTimeout);
_noolApi = serverF.noolApi();
_noolApi.init(_layoutParser);
var configFile = "config/config.json";
var connectionFile = "config/connection.json";
//load all server methods
loadAllServerMethods(fs, "ServerMethods");
setInterval(monitorServerMethods, _monitorServerMethodsTimeout);
// read the config file
readFile(configFile)
.then(function (data) {
if (!data) {
console.log("can't read config file");
return;
}
$config = JSON.parse(data);
//create user session
$users = _serverF.nlUsers(($config.sessionTimeoutMinutes) ? $config.sessionTimeoutMinutes : 60);
// load connection data
return readFile(connectionFile);
})
.then(function (data) {
if (!data) {
return;
}
$connection = JSON.parse(data);
if ($config.permission) {
var conn = getConnection($config.permission.connection);
return dbConnection[conn.type].execute(conn.config, $config.permission.query);
}
})
.then(function (result) {
$permission = result;
})
.catch (function (err) {
console.log("server Init error :" + err);
});
};
return {
execServerMethod: function(methodName, args, callback, _userKey_) {
try{
var obj = $users.getUser(_userKey_);
var user = obj.user;
//methodname should be filename.methodname
var methods = methodName.split(".");
executeServerMethod(methods[0], methods[1], args, callback, user);
}
catch(err)
{
console.log("execServerMethod : %s, err : %s",methodName, JSON.stringify(err));
if(callback)
callback( {code:"SERVER_ERROR", message:JSON.stringify(err)});
}
},
serverFunctions : function (methodName, typeName, template, data, $scope, serverF, callback, _userKey_) {
var bSessionCreated = false;
var obj = $users.getUser(_userKey_);
var user = obj.user;
_layoutParser.getFileData(_fs, template, "layout")
.then(function (result) {
var permissionName = result.permission;
if (!validatePermission(permissionName, user, $config, $permission)) {
// invalid permission
$scope.error = {
code : "NOPermission",
message : $config.permission.errorMessage
};
return;
}
this[typeName](methodName, typeName, template, data, $scope, serverF, callback, _userKey_);
})
.catch (function (err) {
console.log("server process error :" + err);
});
//return $scope;
},
init : init,
getLayout : function (layoutName, _userKey_) {
return _layoutParser.getFileData(_fs, layoutName, "layout")
.then(function (result) {
var data = {};
if (!result) {
// the layout table file not found
data.error = {
code : "NoLayout",
message : "layout is not found for " + layoutName
};
}
else {
// we have layout object
//get the user object
var user = $users.getUser(_userKey_).user;
var permissionName = result.permission;
if (!validatePermission(permissionName, user, $config, $permission)) {
console.log("validation failure for permission :%s, user: %s" , permissionName, user );
// invalid permission
data.error = {
code : "NOPermission",
message : $config.permission.errorMessage
};
} else {
data.layout = result.data;
}
}
return data;
});
}
}
}