Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modulator improvements #10

Merged
merged 19 commits into from
Dec 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions Galleon.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var outbound = require('./fleet/outgoing/outbound');
var queue = require('./fleet/outgoing/queue');

var Database = require('./fleet/connection');
var modulator = require('./bin/modulator/master');
var Modulator = require('./bin/modulator');
// -------------------------------------------

// Query
Expand All @@ -26,7 +26,7 @@ var GalleonQuery = {
unlinkattachment: require('./query/unlink.attachment'),
clean: require('./query/clean.js'),
restore: require('./query/restore.js')
}
};

// Essential
var eventEmmiter = require('events').EventEmitter;
Expand Down Expand Up @@ -72,7 +72,7 @@ var Galleon = function(env, callback){
env = undefined;
}
if((!callback) || (typeof(callback) !== 'function')) {
callback = new Function;
callback = function() {};
}

if((typeof(env) !== 'object') || (!env.connections)) {
Expand All @@ -96,12 +96,12 @@ var Galleon = function(env, callback){
_this.environment = environment;

// Assign module environment
_this.environment.modulator = modulator;
_this.environment.modulator = new Modulator();
// Assign modules -> IF Environment is set to Safe Mode Ignore All Modules
if(_this.environment.safemode === true) {
_this.environment.modules = {}
_this.environment.modules = {};
}else{
_this.environment.modules = _this.environment.modulator.load(_this.environment.modules);
_this.environment.modules = _this.environment.modulator.load();
}

Database(_this.environment.connections, function(error, connection){
Expand Down Expand Up @@ -133,23 +133,23 @@ var Galleon = function(env, callback){
}
});
}else _this.emit('ready');
})
});

// Load front-end modules
_this.environment.modulator.launch(_this.environment.modules['frontend'], osenv.tmpdir(), function(){
if(environment.verbose) console.log("FRONTEND MODULES LAUNCHED".green, arguments)
})
_this.environment.modulator.launch('frontend', osenv.tmpdir(), function(){
if(environment.verbose) console.log("FRONTEND MODULES LAUNCHED".green, arguments);
});

eventEmmiter.call(this);
}
};

var InternalMethods = {
checkPorts: function(ports, callback){
var check = pass;

// There should be a better way to do this
ports.forEach(function(port, index, array){
var finalCallback = undefined;
var finalCallback;

if(array.length-1 <= index) finalCallback = callback;
InternalMethods.checkPort(port, function(test) {
Expand All @@ -175,9 +175,9 @@ var InternalMethods = {
else if (status == 'closed') callback(null, pass);
}

})
});
}
}
};

util.inherits(Galleon, eventEmmiter);

Expand All @@ -194,7 +194,7 @@ Galleon.prototype.dock = function(callback){

// ERROR | INCOMING | OUTGOING //
callback(undefined, INCOMING);
}
};

Galleon.prototype.server = function(callback) {
var Server = require('./api/server');
Expand All @@ -204,15 +204,15 @@ Galleon.prototype.server = function(callback) {

Server(this.environment, this.environment.ports.server, this.connection, this);
callback(undefined, true);
}
};
/* - --------------- - */

/* - DISPATCH METHOD - */
Galleon.prototype.dispatch = function(mail, callback, connection){
connection = connection || this.connection;
var QUEUE = new queue(this.environment);
QUEUE.add(connection, mail, this.environment, callback);
}
};
/* - ---------------- - */

/* - USER MANAGEMENT - */
Expand Down Expand Up @@ -249,7 +249,7 @@ Galleon.prototype.createUser = function(user, callback) {
return callback(new Error("Invalid password"));

bcrypt.hash(user.password, 10, function(error, hash) {
if(error) return callback(error)
if(error) return callback(error);

_this.connection.collections.users.create({
email: user.email,
Expand All @@ -259,9 +259,9 @@ Galleon.prototype.createUser = function(user, callback) {
},function(error, user){
if(error) return callback(error);
callback(null, user);
})
});
});
}
};

Galleon.prototype.listUsers = function(options, callback) {
// Internal
Expand All @@ -272,7 +272,7 @@ Galleon.prototype.listUsers = function(options, callback) {
if(!callback) callback = function(){};

this.connection.collections.users.find().limit(options.limit || 50).exec(callback);
}
};

Galleon.prototype.removeUser = function(query, callback) {
// Internal
Expand All @@ -282,7 +282,7 @@ Galleon.prototype.removeUser = function(query, callback) {

if(query) this.connection.collections.users.destroy(query).exec(callback);
else callback(new Error("NO QUERY"));
}
};

Galleon.prototype.changePassword = function(user, newPassword, oldPassword, callback, forceChange) {
var self = this;
Expand Down Expand Up @@ -311,18 +311,18 @@ Galleon.prototype.changePassword = function(user, newPassword, oldPassword, call
});
else
return callback(new Error("INCORRECT PASSWORD"));
})
})
})
});
});
});
}else{
bcrypt.hash(newPassword, 10, function(error, hash) {
if(hash)
self.connection.collections.users.update({ email: user }, { password: hash }).exec(callback);
else
return callback(new Error("INCORRECT PASSWORD"));
})
});
}
}
};
/* - --------------- - */

/* - EMAIL MANAGEMENT - */
Expand All @@ -336,7 +336,7 @@ Galleon.prototype.query = function(method, query, callback) {

// Execute Query
GalleonQuery[method.toLowerCase()](this, query, callback);
}
};
/* - ---------------- - */

module.exports = Galleon;
31 changes: 21 additions & 10 deletions bin/environment.js → bin/configFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ var defaultPath = path.resolve(osenv.home(), '.galleon/galleon.conf');
createDirectoryIfNotFound(path.resolve(osenv.home(), '.galleon'));

var env = {
watch: function(callback) {
// Listens to config file
// and calls callback when changed
fs.watchFile(defaultPath, function (curr, prev) {
if(curr.mtime > prev.mtime) {
env.get(function(error, data){
callback(error, data, curr, prev);
});
}
});
},
get: function(callback) {
fs.exists(defaultPath, function (exists) {
if(!exists) return callback("CONFIG FILE NOT FOUND!");
Expand Down Expand Up @@ -42,13 +53,13 @@ var env = {
},
setModules: function(modules, callback) {
var self = this;
var modules = _.toArray(modules);
modules = _.toArray(modules);
self.get(function(error, data) {
if(error) return callback(error);

data.modules = modules;
self.set(data, callback);
})
});
},
updateModuleConfig: function(Module, Config, callback) {
var self = this;
Expand All @@ -58,33 +69,33 @@ var env = {
MODULE.config = _.merge(MODULE.config, Config);
if(typeof(callback) === 'function') self.set(data, callback);
else self.setSync(data);
})
});
},
addModules: function(modules, callback) {
var self = this;
var modules = _.toArray(modules);
modules = _.toArray(modules);
self.get(function(error, data) {
if(error) return callback(error);
_.each(modules, function(MODULE) {
if(!data.modules) data.modules = [];
_.remove(data.modules, { name: MODULE.name });
data.modules.push(MODULE);
})
});
self.set(data, callback);
})
});
},
removeModules: function(modules, callback) {
var self = this;
var modules = _.toArray(modules);
modules = _.toArray(modules);
self.get(function(error, data) {
if(error) return callback(error);

_.each(modules, function(MODULE) {
_.pull(data.modules, MODULE);
})
});
self.set(data, callback);
})
});
},
}
};

module.exports = env;
115 changes: 115 additions & 0 deletions bin/modulator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
var shell = require('shelljs');
var _ = require('lodash');
var async = require('async');
var herb = require('herb');
var colors = require('colors');
var configFile = require('./configFile');

var Modulator = function() {
this.env = configFile;
this.modules = this.env.getModulesSync();
this.container = {};
};

Modulator.prototype._getModules = function() {
this.modules = this.env.getModulesSync();
};

Modulator.prototype._add = function (MODULE) {
var m = require(MODULE);
this.env.addModules([{
reference: MODULE,
name: m.name,
extends: m.extends,
config: m.defaults
}]);
};

Modulator.prototype.load = function(modules) {
var context = this;
// Modules are likely required to be loaded on start thus will be loaded Synchronously
_.each(modules || context.modules, function(MODULE) {
// Fill context.modules according to 'extends' attribute

// Assign array if key is undefined
if(!context.container[MODULE.extends]) context.container[MODULE.extends] = {};
// Push current Module to the respective key
context.container[MODULE.extends][MODULE.reference] = MODULE;
});
return context.container;
};

Modulator.prototype.launch = function() {
var context = this;
var args = _.toArray(arguments);
var cat = args.shift();
var callback = args.pop();
var functions = [];

if((!context.container) || (!_.isPlainObject(context.container)) || (!context.container[cat])) return callback();

// Populate functions
_.each(context.container[cat], function(MODULE) {
functions.push(function(callback){
/* Slows down module execution but prevents unintended crashes */
// Prevents a bad module from corrupting the entire eco-system
try {
context.container[cat][MODULE.reference].__gcopy = require(MODULE.reference);
context.container[cat][MODULE.reference].__gcopy.exec.apply(MODULE, args);
}catch(error){
callback(error);
}
});
});

// Watch for config changes
configFile.watch(function() {
if (!context.container) return;
context._getModules();
_.each(context.container[cat], function (MODULE, NAME) {
try {
if (!_.isEqual(_.findWhere(context.modules, { name: NAME }).config, MODULE.config)) {
if (typeof MODULE.__gcopy.update === 'function') { MODULE.__gcopy.update(_.findWhere(context.modules, { name: NAME }).config); }
}
} catch (e) { }
});
context._getModules();
});

// Ignore if no modules are registered for the current task
if(functions.length <= 0) return callback();

async.series(functions, callback);
};

Modulator.prototype.install = function(moduleName) {
var context = this;
moduleName = moduleName.toLowerCase();
moduleName = (moduleName.substring(0,8) !== 'galleon-')?'galleon-'+moduleName:moduleName;
shell.exec('npm install -g ' + moduleName, function(code, output) {
if(code === 0) {
context._add(moduleName);
herb.log(moduleName.toUpperCase().magenta, "SUCCESSFULLY INSTALLED!".green);
herb.warn("Changes will only take affect after restart!");
}else{
herb.log("INSTALLATION FAILED!".red, "\nCODE:", code);
}
});
};

Modulator.prototype.update = function(name, config) {
var context = this;
var MatchFound = false;
// Modules are likely required to be loaded on start thus will be loaded Synchronously
_.each(this.modules, function(MODULE) {
// If Current Module Matches name
if((MODULE.name.toLowerCase() === name) || (MODULE.reference.toLowerCase() === name)) {
// Update Config
context.env.updateModuleConfig(MODULE, config);
MatchFound = true;
}
});
return MatchFound;
};

module.exports = Modulator;
Loading