From 91d6f83de47916e913dda95fcb042a95b2d52f00 Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Tue, 3 Dec 2013 13:36:44 -0500 Subject: [PATCH] more mongo work --- app.js | 5 +- package.json | 2 + src/database/mongo.js | 184 +++++++++++-- src/plugins.js | 588 ++++++++++++++++++++++-------------------- src/user.js | 2 +- 5 files changed, 470 insertions(+), 311 deletions(-) diff --git a/app.js b/app.js index b1e27a6c9b..1c9e30e979 100644 --- a/app.js +++ b/app.js @@ -89,14 +89,15 @@ webserver = require('./src/webserver'), SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket'], 'browser client minification': true}), websockets = require('./src/websockets'), - plugins = require('./src/plugins'), // Don't remove this - plugins initializes itself + plugins = require('./src/plugins'), notifications = require('./src/notifications'), upgrade = require('./src/upgrade'); upgrade.check(function(schema_ok) { if (schema_ok || nconf.get('check-schema') === false) { websockets.init(SocketIO); - + console.log('calling plugins init'); + plugins.init(); global.templates = {}; global.translator = translator; diff --git a/package.json b/package.json index 4710b9daa0..af257f5775 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,13 @@ "dependencies": { "socket.io": "~0.9.16", "redis": "0.8.3", + "mongodb": "1.3.20", "express": "3.2.0", "express-namespace": "~0.1.1", "emailjs": "0.3.4", "cookie": "0.0.6", "connect-redis": "1.4.5", + "connect-mongo": "0.4.0", "passport": "0.1.17", "passport-local": "0.1.6", "passport-twitter": "0.1.5", diff --git a/src/database/mongo.js b/src/database/mongo.js index 2864d91395..6d3b4f6e5c 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -2,74 +2,212 @@ (function(module) { 'use strict'; - var mongodb = require('mongodb') - mongoClient = mongodb.MongoClient, + var Db = require('mongodb').Db, + mongoClient = require('mongodb').MongoClient, + Server = require('mongodb').Server, winston = require('winston'), nconf = require('nconf'), express = require('express'), - mongoStore = require('connect-mongo')(express); - mongoHost = nconf.get('mongo:host'); + mongoStore = require('connect-mongo')(express), + mongoHost = nconf.get('mongo:host'), + db; - // mongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) { - mongoClient.connect('mongodb://' + mongoHost + ':' + nconf.get('mongo:port') + '/' + nconf.get('mongo:database'), function(err, db) { + var db = new Db(nconf.get('mongo:database'), new Server(mongoHost, nconf.get('mongo:port')), {w:1}); + //console.log(db.collection); + + db.open(function(err, _db) { + //mongoClient.connect('mongodb://'+ mongoHost + ':' + nconf.get('mongo:port') + '/' + nconf.get('mongo:database'), function(err, _db) { + console.log('WE ARE CONNECTED'); if(err) { - winston.error("NodeBB could not connect to your Mongo database. Mongo returned the following error: " + error.message); + winston.error("NodeBB could not connect to your Mongo database. Mongo returned the following error: " + err.message); process.exit(); } + + // TODO: fill out settings.db + module.sessionStore = new mongoStore({ + db: db + }); + + db.collection('objects').findOne({_key:'config'}, {timeout:true}, function(err, item) { + console.log('fail'); + console.log(item); + callback(err, item); + }); + + }); + + db.createCollection('objects', function(err, collection) { + console.log('collection created', err, collection); + }); + + db.createCollection('sets', function(err, collection) { + }); + // look up how its done in mongo /*if (nconf.get('mongo:password')) { redisClient.auth(nconf.get('mongo:password')); } */ - // TODO: fill out settings.db - module.sessionStore = new mongoStore({ - db: settings.db - }); - - // // Exported functions // module.getFileName = function(callback) { - // TODO : get mongodb filename + throw new Error('not-implemented'); + } + + module.info = function(callback) { + throw new Error('not-implemented'); + } + + // key + + module.exists = function(key, callback) { + throw new Error('not-implemented'); + } + + module.delete = function(key, callback) { + throw new Error('not-implemented'); + } + + module.get = function(key, callback) { + throw new Error('not-implemented'); + } + + module.set = function(key, callback) { + throw new Error('not-implemented'); } + //hashes module.setObject = function(key, data, callback) { - // TODO : implement in mongo + data['_key'] = key; + db.collection('objects').insert(data, {w:1}, function(err, result) { + callback(err, result); + }); } - module.setObjectField = function(key, field, callback) { - // TODO : implement in mongo + module.setObjectField = function(key, field, value, callback) { + db.collection('objects').update(); } module.getObject = function(key, callback) { - // TODO : implement in mongo + console.log('calling findOne'); + db.collection('objects').findOne({_key:key}, {timeout:true},function(err, item) { + console.log(item); + callback(err, item); + }); } module.getObjectField = function(key, field, callback) { - // TODO : implement in mongo + throw new Error('not-implemented'); } module.getObjectFields = function(key, fields, callback) { - // TODO : implement in mongo + throw new Error('not-implemented'); + } + + module.getObjectValues = function(key, callback) { + throw new Error('not-implemented'); + } + + module.isObjectField = function(key, field, callback) { + throw new Error('not-implemented'); } module.deleteObjectField = function(key, field, callback) { - // TODO : implement in mongo + throw new Error('not-implemented'); + } + + module.incrObjectField = function(key, field, callback) { + throw new Error('not-implemented'); + } + + module.decrObjectField = function(key, field, callback) { + throw new Error('not-implemented'); } - module.incrObjectField = function(key, field, value, callback) { - // TODO : implement in mongo + module.incrObjectFieldBy = function(key, field, value, callback) { + throw new Error('not-implemented'); } + // sets + module.setAdd = function(key, value, callback) { + throw new Error('not-implemented'); + } + + module.setRemove = function(key, value, callback) { + throw new Error('not-implemented'); + } + + module.isSetMember = function(key, value, callback) { + throw new Error('not-implemented'); + } + + module.isMemberOfSets = function(sets, value, callback) { + throw new Error('not-implemented'); + } + + module.getSetMembers = function(key, callback) { + console.log('getting set members'); + db.collection('sets').findOne({_key:key}, function(err, data) { + console.log('derp', err, data); + callback(err, data); + }); + } + + module.setCount = function(key, callback) { + throw new Error('not-implemented'); + } + + module.setRemoveRandom = function(key, callback) { + throw new Error('not-implemented'); + } + + // sorted sets + + module.sortedSetAdd = function(key, score, value, callback) { + throw new Error('not-implemented'); + } + + module.sortedSetRemove = function(key, value, callback) { + throw new Error('not-implemented'); + } + + module.getSortedSetRange = function(key, start, stop, callback) { + throw new Error('not-implemented'); + } + + module.getSortedSetRevRange = function(key, start, stop, callback) { + throw new Error('not-implemented'); + } + + module.getSortedSetRevRangeByScore = function(args, callback) { + throw new Error('not-implemented'); + } + + module.sortedSetCount = function(key, min, max, callback) { + throw new Error('not-implemented'); + } + + // lists + module.listPrepend = function(key, value, callback) { + throw new Error('not-implemented'); + } + + module.listAppend = function(key, value, callback) { + throw new Error('not-implemented'); + } + + module.getListRange = function(key, start, stop, callback) { + throw new Error('not-implemented'); + } }(exports)); diff --git a/src/plugins.js b/src/plugins.js index 7dbc0a6bdd..38f4db2d93 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -3,325 +3,343 @@ var fs = require('fs'), async = require('async'), winston = require('winston'), eventEmitter = require('events').EventEmitter, - db = require('./database'), + db = require('./database'); - plugins = { - libraries: {}, - loadedHooks: {}, - staticDirs: {}, - cssFiles: [], +(function(Plugins) { - // Events - readyEvent: new eventEmitter, + Plugins.libraries = {}; + Plugins.loadedHooks = {}; + Plugins.staticDirs = {}; + Plugins.cssFiles = []; - init: function() { - if (this.initialized) return; - if (global.env === 'development') winston.info('[plugins] Initializing plugins system'); + Plugins.initialized = false; - this.reload(function(err) { - if (err) { - if (global.env === 'development') winston.info('[plugins] NodeBB encountered a problem while loading plugins', err.message); - return; + // Events + Plugins.readyEvent = new eventEmitter; + + Plugins.init = function() { + console.log('plugins init called'); + if (Plugins.initialized) { + return; + } + + if (global.env === 'development') { + winston.info('[plugins] Initializing plugins system'); + } + + Plugins.reload(function(err) { + if (err) { + if (global.env === 'development') { + winston.info('[plugins] NodeBB encountered a problem while loading plugins', err.message); } + return; + } - if (global.env === 'development') winston.info('[plugins] Plugins OK'); + if (global.env === 'development') { + winston.info('[plugins] Plugins OK'); + } + Plugins.initialized = true; + plugins.readyEvent.emit('ready'); + }); + }; + + Plugins.ready = function(callback) { + if (!Plugins.initialized) { + Plugins.readyEvent.once('ready', callback); + } else { + callback(); + } + }; + + Plugins.reload = function(callback) { + // Resetting all local plugin data + Plugins.loadedHooks = {}; + Plugins.staticDirs = {}; + Plugins.cssFiles.length = 0; + + // Read the list of activated plugins and require their libraries + async.waterfall([ + function(next) { + db.getSetMembers('plugins:active', next); + }, + function(plugins, next) { + if (plugins && Array.isArray(plugins) && plugins.length > 0) { + async.each(plugins, function(plugin, next) { + var modulePath = path.join(__dirname, '../node_modules/', plugin); + if (fs.existsSync(modulePath)) { + Plugins.loadPlugin(modulePath, next); + } else { + if (global.env === 'development') { + winston.warn('[plugins] Plugin \'' + plugin + '\' not found'); + } + next(); // Ignore this plugin silently + } + }, next); + } else next(); + }, + function(next) { + if (global.env === 'development') winston.info('[plugins] Sorting hooks to fire in priority sequence'); + Object.keys(Plugins.loadedHooks).forEach(function(hook) { + var hooks = Plugins.loadedHooks[hook]; + hooks = hooks.sort(function(a, b) { + return a.priority - b.priority; + }); + }); - plugins.initialized = true; - plugins.readyEvent.emit('ready'); - }); - }, - ready: function(callback) { - if (!this.initialized) this.readyEvent.once('ready', callback); - else callback(); - }, - initialized: false, - reload: function(callback) { - var _self = this; - - // Resetting all local plugin data - this.loadedHooks = {}; - this.staticDirs = {}; - this.cssFiles.length = 0; - - // Read the list of activated plugins and require their libraries - async.waterfall([ + next(); + } + ], callback); + }; + + Plugins.loadPlugin = function(pluginPath, callback) { + fs.readFile(path.join(pluginPath, 'plugin.json'), function(err, data) { + if (err) { + return callback(err); + } + + var pluginData = JSON.parse(data), + libraryPath, staticDir; + + async.parallel([ function(next) { - db.getSetMembers('plugins:active', next); - }, - function(plugins, next) { - if (plugins && Array.isArray(plugins) && plugins.length > 0) { - async.each(plugins, function(plugin, next) { - var modulePath = path.join(__dirname, '../node_modules/', plugin); - if (fs.existsSync(modulePath)) _self.loadPlugin(modulePath, next); - else { - if (global.env === 'development') winston.warn('[plugins] Plugin \'' + plugin + '\' not found'); - next(); // Ignore this plugin silently + if (pluginData.library) { + libraryPath = path.join(pluginPath, pluginData.library); + + fs.exists(libraryPath, function(exists) { + if (exists) { + if (!Plugins.libraries[pluginData.id]) { + Plugins.libraries[pluginData.id] = require(libraryPath); + } + + // Register hooks for this plugin + if (pluginData.hooks && Array.isArray(pluginData.hooks) && pluginData.hooks.length > 0) { + async.each(pluginData.hooks, function(hook, next) { + Plugins.registerHook(pluginData.id, hook, next); + }, next); + } else { + next(null); + } + } else { + winston.warn('[plugins.reload] Library not found for plugin: ' + pluginData.id); + next(); } - }, next); - } else next(); + }); + } else { + winston.warn('[plugins.reload] Library not found for plugin: ' + pluginData.id); + next(); + } }, function(next) { - if (global.env === 'development') winston.info('[plugins] Sorting hooks to fire in priority sequence'); - Object.keys(_self.loadedHooks).forEach(function(hook) { - var hooks = _self.loadedHooks[hook]; - hooks = hooks.sort(function(a, b) { - return a.priority - b.priority; + // Static Directories for Plugins + if (pluginData.staticDir) { + staticDir = path.join(pluginPath, pluginData.staticDir); + + fs.exists(staticDir, function(exists) { + if (exists) { + Plugins.staticDirs[pluginData.id] = staticDir; + next(); + } else next(); }); - }); - - next(); - } - ], callback); - }, - loadPlugin: function(pluginPath, callback) { - var _self = this; - - fs.readFile(path.join(pluginPath, 'plugin.json'), function(err, data) { - if (err) return callback(err); - - var pluginData = JSON.parse(data), - libraryPath, staticDir; - - async.parallel([ - function(next) { - if (pluginData.library) { - libraryPath = path.join(pluginPath, pluginData.library); - - fs.exists(libraryPath, function(exists) { - if (exists) { - if (!_self.libraries[pluginData.id]) { - _self.libraries[pluginData.id] = require(libraryPath); - } - - // Register hooks for this plugin - if (pluginData.hooks && Array.isArray(pluginData.hooks) && pluginData.hooks.length > 0) { - async.each(pluginData.hooks, function(hook, next) { - _self.registerHook(pluginData.id, hook, next); - }, next); - } else { - next(null); - } - } else { - winston.warn('[plugins.reload] Library not found for plugin: ' + pluginData.id); - next(); - } - }); - } else { - winston.warn('[plugins.reload] Library not found for plugin: ' + pluginData.id); - next(); + } else next(); + }, + function(next) { + // CSS Files for plugins + if (pluginData.css && pluginData.css instanceof Array) { + if (global.env === 'development') { + winston.info('[plugins] Found ' + pluginData.css.length + ' CSS file(s) for plugin ' + pluginData.id); } - }, - function(next) { - // Static Directories for Plugins - if (pluginData.staticDir) { - staticDir = path.join(pluginPath, pluginData.staticDir); - - fs.exists(staticDir, function(exists) { - if (exists) { - _self.staticDirs[pluginData.id] = staticDir; - next(); - } else next(); - }); - } else next(); - }, - function(next) { - // CSS Files for plugins - if (pluginData.css && pluginData.css instanceof Array) { - if (global.env === 'development') { - winston.info('[plugins] Found ' + pluginData.css.length + ' CSS file(s) for plugin ' + pluginData.id); - } - _self.cssFiles = _self.cssFiles.concat(pluginData.css.map(function(file) { - return path.join('/plugins', pluginData.id, file); - })); + Plugins.cssFiles = Plugins.cssFiles.concat(pluginData.css.map(function(file) { + return path.join('/plugins', pluginData.id, file); + })); - next(); - } else next(); - } - ], function(err) { - if (!err) { - if (global.env === 'development') winston.info('[plugins] Loaded plugin: ' + pluginData.id); - callback(); - } else callback(new Error('Could not load plugin system')) - }); + next(); + } else next(); + } + ], function(err) { + if (!err) { + if (global.env === 'development') winston.info('[plugins] Loaded plugin: ' + pluginData.id); + callback(); + } else callback(new Error('Could not load plugin system')) }); - }, - registerHook: function(id, data, callback) { - /* - `data` is an object consisting of (* is required): - `data.hook`*, the name of the NodeBB hook - `data.method`*, the method called in that plugin - `data.callbacked`, whether or not the hook expects a callback (true), or a return (false). Only used for filters. (Default: false) - `data.priority`, the relative priority of the method when it is eventually called (default: 10) - */ - var _self = this; - - if (data.hook && data.method) { - data.id = id; - if (!data.priority) data.priority = 10; - data.method = data.method.split('.').reduce(function(memo, prop) { - if (memo[prop]) { - return memo[prop]; - } else { - // Couldn't find method by path, assuming property with periods in it (evil!) - _self.libraries[data.id][data.method]; - } - }, _self.libraries[data.id]); - - _self.loadedHooks[data.hook] = _self.loadedHooks[data.hook] || []; - _self.loadedHooks[data.hook].push(data); - - if (global.env === 'development') winston.info('[plugins] Hook registered: ' + data.hook + ' will call ' + id); - callback(); - } else return; - }, - fireHook: function(hook, args, callback) { - var _self = this - hookList = this.loadedHooks[hook]; - - if (hookList && Array.isArray(hookList)) { - //if (global.env === 'development') winston.info('[plugins] Firing hook: \'' + hook + '\''); - var hookType = hook.split(':')[0]; - switch (hookType) { - case 'filter': - async.reduce(hookList, args, function(value, hookObj, next) { - if (hookObj.method) { - if (hookObj.callbacked) { // If a callback is present (asynchronous method) - hookObj.method.call(_self.libraries[hookObj.id], value, next); - } else { // Synchronous method - value = hookObj.method.call(_self.libraries[hookObj.id], value); - next(null, value); - } - } else { - if (global.env === 'development') winston.info('[plugins] Expected method \'' + hookObj.method + '\' in plugin \'' + hookObj.id + '\' not found, skipping.'); + }); + }; + + Plugins.registerHook = function(id, data, callback) { + /* + `data` is an object consisting of (* is required): + `data.hook`*, the name of the NodeBB hook + `data.method`*, the method called in that plugin + `data.callbacked`, whether or not the hook expects a callback (true), or a return (false). Only used for filters. (Default: false) + `data.priority`, the relative priority of the method when it is eventually called (default: 10) + */ + + if (data.hook && data.method) { + data.id = id; + if (!data.priority) data.priority = 10; + data.method = data.method.split('.').reduce(function(memo, prop) { + if (memo[prop]) { + return memo[prop]; + } else { + // Couldn't find method by path, assuming property with periods in it (evil!) + Plugins.libraries[data.id][data.method]; + } + }, Plugins.libraries[data.id]); + + Plugins.loadedHooks[data.hook] = Plugins.loadedHooks[data.hook] || []; + Plugins.loadedHooks[data.hook].push(data); + + if (global.env === 'development') { + winston.info('[plugins] Hook registered: ' + data.hook + ' will call ' + id); + } + callback(); + } else return; + }; + + Plugins.fireHook = function(hook, args, callback) { + hookList = Plugins.loadedHooks[hook]; + + if (hookList && Array.isArray(hookList)) { + //if (global.env === 'development') winston.info('[plugins] Firing hook: \'' + hook + '\''); + var hookType = hook.split(':')[0]; + switch (hookType) { + case 'filter': + async.reduce(hookList, args, function(value, hookObj, next) { + if (hookObj.method) { + if (hookObj.callbacked) { // If a callback is present (asynchronous method) + hookObj.method.call(Plugins.libraries[hookObj.id], value, next); + } else { // Synchronous method + value = hookObj.method.call(Plugins.libraries[hookObj.id], value); next(null, value); } - }, function(err, value) { - if (err) { - if (global.env === 'development') { - winston.info('[plugins] Problem executing hook: ' + hook); - } + } else { + if (global.env === 'development') winston.info('[plugins] Expected method \'' + hookObj.method + '\' in plugin \'' + hookObj.id + '\' not found, skipping.'); + next(null, value); + } + }, function(err, value) { + if (err) { + if (global.env === 'development') { + winston.info('[plugins] Problem executing hook: ' + hook); } + } - callback.apply(plugins, arguments); - }); - break; - case 'action': - async.each(hookList, function(hookObj) { - if (hookObj.method) { - hookObj.method.call(_self.libraries[hookObj.id], args); - } else { - if (global.env === 'development') { - winston.info('[plugins] Expected method \'' + hookObj.method + '\' in plugin \'' + hookObj.id + '\' not found, skipping.'); - } + callback.apply(plugins, arguments); + }); + break; + case 'action': + async.each(hookList, function(hookObj) { + if (hookObj.method) { + hookObj.method.call(Plugins.libraries[hookObj.id], args); + } else { + if (global.env === 'development') { + winston.info('[plugins] Expected method \'' + hookObj.method + '\' in plugin \'' + hookObj.id + '\' not found, skipping.'); } - }); - break; - default: - // Do nothing... - break; - } - } else { - // Otherwise, this hook contains no methods - var returnVal = args; - if (callback) { - callback(null, returnVal); - } + } + }); + break; + default: + // Do nothing... + break; + } + } else { + // Otherwise, this hook contains no methods + var returnVal = args; + if (callback) { + callback(null, returnVal); } - }, - isActive: function(id, callback) { - db.isSetMember('plugins:active', id, callback); - }, - toggleActive: function(id, callback) { - this.isActive(id, function(err, active) { + } + }; + + Plugins.isActive = function(id, callback) { + db.isSetMember('plugins:active', id, callback); + }; + + Plugins.toggleActive = function(id, callback) { + Plugins.isActive(id, function(err, active) { + if (err) { + if (global.env === 'development') winston.info('[plugins] Could not toggle active state on plugin \'' + id + '\''); + return; + } + + db[(active ? 'setRemove' : 'setAdd')]('plugins:active', id, function(err, success) { if (err) { if (global.env === 'development') winston.info('[plugins] Could not toggle active state on plugin \'' + id + '\''); return; } - db[(active ? 'setRemove' : 'setAdd')]('plugins:active', id, function(err, success) { - if (err) { - if (global.env === 'development') winston.info('[plugins] Could not toggle active state on plugin \'' + id + '\''); - return; - } + // Reload meta data + plugins.reload(function() { + // (De)activation Hooks + plugins.fireHook('action:plugin.' + (active ? 'de' : '') + 'activate', id); - // Reload meta data - plugins.reload(function() { - // (De)activation Hooks - plugins.fireHook('action:plugin.' + (active ? 'de' : '') + 'activate', id); - - if (callback) { - callback({ - id: id, - active: !active - }); - } - }); + if (callback) { + callback({ + id: id, + active: !active + }); + } }); }); - }, - showInstalled: function(callback) { - var _self = this; - npmPluginPath = path.join(__dirname, '../node_modules'); - - async.waterfall([ - function(next) { - fs.readdir(npmPluginPath, function(err, dirs) { - dirs = dirs.map(function(file) { - return path.join(npmPluginPath, file); - }).filter(function(file) { - var stats = fs.statSync(file); - if (stats.isDirectory() && file.substr(npmPluginPath.length + 1, 14) === 'nodebb-plugin-') return true; - else return false; - }); + }); + } - next(err, dirs); + Plugins.showInstalled = function(callback) { + npmPluginPath = path.join(__dirname, '../node_modules'); + + async.waterfall([ + function(next) { + fs.readdir(npmPluginPath, function(err, dirs) { + dirs = dirs.map(function(file) { + return path.join(npmPluginPath, file); + }).filter(function(file) { + var stats = fs.statSync(file); + if (stats.isDirectory() && file.substr(npmPluginPath.length + 1, 14) === 'nodebb-plugin-') return true; + else return false; }); - }, - function(files, next) { - var plugins = []; - - async.each(files, function(file, next) { - var configPath; - - async.waterfall([ - function(next) { - fs.readFile(path.join(file, 'plugin.json'), next); - }, - function(configJSON, next) { - try { - var config = JSON.parse(configJSON); - } catch (err) { - winston.warn("Plugin: " + file + " is corrupted or invalid. Please check plugin.json for errors.") - return next(err, null); - } - - _self.isActive(config.id, function(err, active) { - if (err) next(new Error('no-active-state')); - delete config.library; - delete config.hooks; - config.active = active; - config.activeText = ' ' + (active ? 'Dea' : 'A') + 'ctivate'; - next(null, config); - }); + next(err, dirs); + }); + }, + function(files, next) { + var plugins = []; + + async.each(files, function(file, next) { + var configPath; + + async.waterfall([ + function(next) { + fs.readFile(path.join(file, 'plugin.json'), next); + }, + function(configJSON, next) { + try { + var config = JSON.parse(configJSON); + } catch (err) { + winston.warn("Plugin: " + file + " is corrupted or invalid. Please check plugin.json for errors.") + return next(err, null); } - ], function(err, config) { - if (err) return next(); // Silently fail - plugins.push(config); - next(); - }); - }, function(err) { - next(null, plugins); - }); - } - ], function(err, plugins) { - callback(err, plugins); - }); - } - } + Plugins.isActive(config.id, function(err, active) { + if (err) next(new Error('no-active-state')); -plugins.init(); + delete config.library; + delete config.hooks; + config.active = active; + config.activeText = ' ' + (active ? 'Dea' : 'A') + 'ctivate'; + next(null, config); + }); + } + ], function(err, config) { + if (err) return next(); // Silently fail -module.exports = plugins; \ No newline at end of file + plugins.push(config); + next(); + }); + }, function(err) { + next(null, plugins); + }); + } + ], function(err, plugins) { + callback(err, plugins); + }); + } +}(exports)); diff --git a/src/user.js b/src/user.js index 00557d2e31..686b8e39c3 100644 --- a/src/user.js +++ b/src/user.js @@ -103,7 +103,7 @@ var bcrypt = require('bcrypt'), if (email !== undefined) { db.setObjectField('email:uid', email, uid); - //User.sendConfirmationEmail(email); + User.sendConfirmationEmail(email); } plugins.fireHook('action:user.create', {uid: uid, username: username, email: email, picture: gravatar, timestamp: timestamp});