UNPKG

17.8 kBJavaScriptView Raw
1
2/**
3 * Plugin loader middleware for `simpleportal.Server`
4 *
5 * @property pluginloader
6 * @for simpleportal
7 * @type {pluginloader}
8 * @static
9 */
10
11/**
12 * Plugin loader middleware for `simpleportal.Server`
13 *
14 * @class pluginloader
15 * @module middleware
16 * @static
17 */
18var PluginLoader = module.exports = {};
19
20var path = require('path');
21var fs = require('fs');
22var util = require('./util');
23
24var simpleportal = require('./simpleportal');
25
26var logger = require("./logger");
27var router = require('./router');
28
29PluginLoader.services={};
30PluginLoader.services.service={};
31
32PluginLoader.plugindirs = [];
33
34PluginLoader.plugindir = 'resources/plugin';
35PluginLoader.pluginUrl='/plugin';
36
37/**
38 * To get the details of a plugin
39 *
40 * @method getPluginDetails
41 *
42 * @param {string} pluginid id of the plugin
43 *
44 * @return {object} plugindetails object of the plugin setting
45 */
46PluginLoader.getPluginDetails = function(pluginid){
47 var plugindetails;
48
49 return plugindetails;
50}
51
52/**
53 * To load plugin from a specific plugin settings
54 *
55 * @method __loadPlugin
56 *
57 * @param {} pluginsetting
58 * @param {} configuration
59 * @param {} dbInstance
60 * @param {callback} callback The callback to excecute when complete
61 * @private
62 */
63__loadPlugin = function(pluginsetting, configuration, dbInstance, callback){
64 logger.getInstance().info('Simple Portal : pluginloader', '__loadPlugin -- ' + pluginsetting.id);
65
66 if(pluginsetting.plugintype == 'webapp'){
67 if(!pluginsetting['public'] || pluginsetting['public']+'' != 'true'){
68 if(PluginLoader.configuration.webapps)
69 PluginLoader.configuration.webapps.push(pluginsetting.id);
70 else
71 PluginLoader.configuration.webapps = [pluginsetting.id];
72
73 if(PluginLoader.configuration.webappuris)
74 PluginLoader.configuration.webappuris.push(pluginsetting.webappuri||'/'+pluginsetting.id);
75 else
76 PluginLoader.configuration.webappuris = [pluginsetting.webappuri||'/'+pluginsetting.id];
77 }
78
79 if(!pluginsetting.disabled&&pluginsetting.installed && fs.existsSync(pluginsetting.installeddir + '/startup'))
80 simpleportal.startuploader.loadStartups({configuration:pluginsetting, startupdir:pluginsetting.installeddir + '/startup'}, function(){
81 console.log('Loading startups for plugin - '+ pluginsetting.id)
82 });
83 }else {
84 logger.getInstance().info('Simple Portal : pluginloader', '__loadPlugin -- ' + pluginsetting.id +' -- is -- ' + pluginsetting.plugintype);
85 }
86
87 if(!pluginsetting.disabled&&pluginsetting.installed)
88 if(PluginLoader.plugins[pluginsetting.plugintype])
89 PluginLoader.plugins[pluginsetting.plugintype].push(pluginsetting);
90
91 if(pluginsetting.viewdir){
92 console.log('CHECKING VIEW DIR -- '+ pluginsetting.installeddir + '/' + pluginsetting.viewdir +" <<<>>>"+ fs.existsSync(pluginsetting.installeddir + '/' + pluginsetting.viewdir));
93 if(fs.existsSync(pluginsetting.installeddir + '/' + pluginsetting.viewdir)){
94 var viewconfig_ = {};
95 if(pluginsetting.configuration && pluginsetting.configuration.views)
96 viewconfig_ = pluginsetting.configuration.views;
97
98 simpleportal.viewloader.loadViews({viewdir:pluginsetting.installeddir + '/' + pluginsetting.viewdir, views:viewconfig_}, function(){
99 console.log('Finsihed view callbacks');
100 });
101 }
102 }
103
104 if(!pluginsetting.disabled&&pluginsetting.installed && pluginsetting.servicedir){
105 if(fs.existsSync(pluginsetting.installeddir + '/' + pluginsetting.servicedir)){
106 var services_ = {};
107 if(pluginsetting.configuration && pluginsetting.configuration.services)
108 services_ = pluginsetting.configuration.services;
109
110 simpleportal.serviceloader.loadServices({servicedir:pluginsetting.installeddir + '/' + pluginsetting.servicedir, services:services_}, callback);
111 }else
112 callback();
113 } else if(!pluginsetting.disabled){
114 logger.getInstance().info('Simple Portal : pluginloader', '__loadPlugin -- ' + pluginsetting.id +' -- is -- ' + pluginsetting.installeddir + ' -- '+ pluginsetting.installed);
115 callback();
116 } else
117 callback();
118}
119
120/**
121 * To register a plugin within a directory
122 *
123 * @method registerPlugin
124 * @param {} file plugin directory path
125 * @param {} configuration
126 * @param {} dbInstance OPtional db instance if not mentioned will use the default instance
127 * @param {callback} callback The callback to excecute when complete
128 * @private
129 * @deprecated
130 */
131PluginLoader.registerPlugin = function(file, configuration, dbInstance, callback){
132 logger.getInstance().info('Simple Portal : pluginloader', 'registerPlugin -- ' + file);
133
134 if( fs.existsSync(file) && !/\.$/.test(file)){
135 var path = fs.realpathSync(file);
136 var startindex=0;
137 if(file.lastIndexOf('/') >= 0)
138 startindex=file.lastIndexOf('/')+1;
139 var plugin = file.substring(startindex);
140 var pluginsetting = {id:plugin};
141
142 PluginLoader.readPluginSetting(pluginsetting);
143
144 if(pluginsetting.plugintype == 'webapp'){
145 if( !pluginsetting['public'] || pluginsetting['public']+'' != 'true' ){
146 if(PluginLoader.configuration.webapps)
147 PluginLoader.configuration.webapps.push(pluginsetting.id);
148 else
149 PluginLoader.configuration.webapps = [pluginsetting.id];
150
151 if(PluginLoader.configuration.webappuris)
152 PluginLoader.configuration.webappuris.push(pluginsetting.webappuri||'/'+pluginsetting.id);
153 else
154 PluginLoader.configuration.webappuris = [pluginsetting.webappuri||'/'+pluginsetting.id];
155 }
156 }else {
157 logger.getInstance().info('Simple Portal : pluginloader', 'registerPlugin -- ' + pluginsetting.id +' -- is -- ' + pluginsetting.plugintype);
158 }
159
160 if(!pluginsetting.disabled&&pluginsetting.installed && pluginsetting.servicedir){
161 if(PluginLoader.plugins[pluginsetting.plugintype])
162 PluginLoader.plugins[pluginsetting.plugintype].push(pluginsetting);
163
164 if(fs.existsSync(pluginsetting.installeddir + '/' + pluginsetting.servicedir)){
165 simpleportal.serviceloader.registerServices(pluginsetting.installeddir + '/' + pluginsetting.servicedir, pluginsetting.configuration, function(error){
166 callback(error);
167 });
168 }else
169 callback();
170 } else if(!pluginsetting.disabled){
171 logger.getInstance().info('Simple Portal : pluginloader', 'registerPlugin -- ' + pluginsetting.id +' -- is -- ' + pluginsetting.installeddir);
172 callback();
173 }else
174 callback();
175 }else
176 callback('No such plugin found - ' + file);
177}
178
179/**
180 * To get all the plugins registered
181 *
182 * @method getPlugins
183 * @param {string} type plugin type if not mentioned complete plugins will be send
184 *
185 * @return object or array accoring to the plugin type
186 */
187PluginLoader.getPlugins = function(type){
188 if(!PluginLoader.plugins)
189 return [];
190
191 if(type && PluginLoader.plugins[type])
192 return PluginLoader.plugins[type];
193 else
194 return PluginLoader.plugins;
195}
196
197/**
198 * To load plugin froma list
199 *
200 * @method loadPluginFromList
201 *
202 * @param {} pluginsettinglist
203 * @param {} configuration
204 * @param {callback} callback The callback to excecute when complete
205 *
206 * @private
207 */
208loadPluginFromList=function(pluginsettinglist, configuration, callback){
209 var __registerPlugins_count = pluginsettinglist.length,
210 __registerPlugins_count_fincount=0,
211 errors;
212
213 for(var i in pluginsettinglist){
214 var pluginsetting = pluginsettinglist[i];
215
216 __loadPlugin(pluginsetting, configuration, PluginLoader.dbInstance, function(error){
217 if(error){
218 errors=errors||[];
219 errors.push(error);
220 }
221
222 if(__registerPlugins_count_fincount++ == __registerPlugins_count-1)
223 callback(errors);
224 });
225 }
226}
227
228/**
229 * To unload plugins from a directory
230 *
231 * @method unLoadPluginFromDirectory
232 *
233 * @param {} plugindir
234 * @param {} configuration
235 * @param {callback} callback The callback to excecute when complete
236 */
237PluginLoader.unLoadPluginFromDirectory=function(plugindir, configuration, callback){
238 logger.getInstance().info('Simple Portal : PluginLoader : unLoadPluginFromDirectory', plugindir);
239
240 if(!fs.existsSync(plugindir))
241 callback();
242 else{
243 var pluginlist = [];
244 var pluginsettinglist = [];
245
246 fs.readdirSync(plugindir).forEach(function(filename){
247 if(!/\.$/.test(filename)){
248 pluginlist.push({installeddir:plugindir+ '/' + filename, id:filename});
249 }
250 });
251
252 for(var i in pluginlist){
253 var pluginsetting = pluginlist[i];
254
255 pluginsetting = PluginLoader.readPluginSetting(pluginsetting, plugindir);
256
257 if(pluginsetting&&!pluginsetting.disabled&&pluginsetting.installed)
258 pluginsettinglist.push(pluginsetting);
259 }
260
261 loadPluginFromList(pluginsettinglist, configuration, callback);
262 }
263};
264
265/**
266 * To get all the plugins in the folder, deep search
267 *
268 * @method getPluginFolders
269 * @param plugindir Directory where plugins will be searched for
270 *
271 * @return array of plugin folders
272 */
273PluginLoader.getPluginFolders=function(plugindir, deepindex, cndeepindex){
274 var pluginlist = [],
275 cndeepindex=cndeepindex||0;
276
277 if (fs.existsSync(plugindir)){
278 var subfolders = fs.readdirSync(plugindir).filter(function(v){
279 return !/^\./.test(v) && fs.statSync(path.join(plugindir, v)).isDirectory();
280 });
281
282 subfolders.forEach(function(filename) {
283 var file = plugindir + '/' + filename;
284 if (fs.existsSync(file + '/plugin.json')){
285 pluginlist.push({installeddir:file, id:filename})
286 //pluginlist.push(file);
287 } else if (!simpleportal.util.jsonarraycontains(pluginlist, 'installeddir', file) && deepindex > cndeepindex){
288 //pluginlist = pluginlist.concat(PluginLoader.getPluginFolders(file, 1));
289 pluginlist= pluginlist.concat(PluginLoader.getPluginFolders(file, cndeepindex++));
290 }
291 });
292 }
293
294 return pluginlist;
295};
296
297/**
298 * To load plugin from a directory
299 *
300 * @method loadPluginFromDirectory
301 * @param {} plugindir Plugin directory
302 * @param {} configuration
303 * @param {callback} callback The callback to excecute when complete
304 * @return
305 */
306PluginLoader.loadPluginFromDirectory=function(plugindir, configuration, callback){
307 if(!PluginLoader.plugins)
308 PluginLoader.plugins={util:[], webapp:[], theme:[]};
309
310 if(!fs.existsSync(plugindir))
311 callback();
312 else{
313 logger.getInstance().info('Simple Portal : PluginLoader : loadPluginFromDirectory', plugindir);
314
315 var pluginlist = PluginLoader.getPluginFolders(plugindir, 3),
316 pluginsettinglist = [];
317
318 for(var i in pluginlist){
319 var pluginsetting = pluginlist[i];
320
321 pluginsetting = PluginLoader.readPluginSetting(pluginsetting, plugindir);
322
323 if(!pluginsetting.installeddir)
324 pluginsetting.installeddir = plugindir + '/' + pluginsetting.id;
325
326 if(pluginsetting&&!pluginsetting.disabled&&pluginsetting.installed)
327 pluginsettinglist.push(pluginsetting);
328 }
329
330 pluginsettinglist = pluginsettinglist.sort(function(a, b){
331 return (a.priority||0) > (b.priority||0);
332 });
333
334 if(pluginsettinglist&&pluginsettinglist.length >0){
335 if(!simpleportal.util.arraycontains(PluginLoader.plugindirs, plugindir) && plugindir != PluginLoader.plugindir){
336 PluginLoader.plugindirs.push(plugindir);
337 }
338
339 loadPluginFromList(pluginsettinglist, configuration, callback);
340 }else
341 callback();
342 }
343};
344
345/**
346 * To update the configuration of the `simpleportal.pluginloader`
347 *
348 * @method updateConfiguration
349 * @param {} configuration Configuration you want to update
350 */
351PluginLoader.updateConfiguration=function(configuration){
352 PluginLoader.configuration=configuration;
353}
354
355/**
356 * To read plugin settings from the plugin.json file
357 *
358 * @method readPluginSetting
359 *
360 * @param {} pluginsettings plugin details
361 * @param {} plugindir Directry where plugin will be searched for
362 *
363 * @return {object} pluginsettings parsed json data from the plugin.json file
364 */
365PluginLoader.readPluginSetting = function(pluginsettings, plugindir, skipalt){
366 var deployedroot = simpleportal.util.getServerPath(plugindir||PluginLoader.plugindir);
367
368 if(pluginsettings['public']&&pluginsettings.publicappdir)
369 deployedroot = simpleportal.util.getServerPath(pluginsettings.publicappdir);
370
371 if(pluginsettings['public']&&pluginsettings.plugintype=='theme')
372 deployedroot = deployedroot + '/themes';
373
374 var deployedpath = deployedroot + '/' + pluginsettings.id;
375
376 if(!fs.existsSync(deployedpath) &&pluginsettings.installeddir && pluginsettings.installeddir.indexOf(plugindir) != -1) {
377 deployedpath = simpleportal.util.getServerPath(pluginsettings.installeddir);
378 }
379
380 logger.getInstance().info('Simple Portal : PluginLoader : readPluginSetting', 'reading plugin settings -' + deployedpath);
381
382 if(fs.existsSync(deployedpath)){
383 pluginsettings.installeddir=deployedpath;
384
385 if(fs.existsSync(deployedpath + '/plugin.json')){
386 var exisitingpluginsetting = simpleportal.util.readJSONFile(deployedpath + '/plugin.json');
387
388 if(exisitingpluginsetting&&exisitingpluginsetting.version)
389 pluginsettings.curversion=exisitingpluginsetting.version;
390
391 pluginsettings.installed=true;
392 pluginsettings = simpleportal.util.extendJSON(pluginsettings, exisitingpluginsetting);
393 }
394
395 if(pluginsettings.dependencies&&pluginsettings.dependencies.length > 0){
396 pluginsettings.missingdependencies=[];
397
398 for(var index in pluginsettings.dependencies){
399 if(pluginsettings.dependencies[index] != pluginsettings.id){ // infinite loop in case self dependancy
400 var dependappid = pluginsettings.dependencies[index],
401 missing = true;
402
403 var setting_ = PluginLoader.readPluginSetting({id:dependappid}); // check this dependency is missing!!
404 missing = !setting_.installed;
405
406 if(missing){
407 for(var i in PluginLoader.plugindirs){
408 if(missing){
409 var plugindir_ = PluginLoader.plugindirs[i];
410 var setting_ = PluginLoader.readPluginSetting({id:dependappid}, plugindir_); // check this dependency in alternate directories
411
412 missing = !setting_.installed;
413 }
414 }
415 }
416
417 if(missing)
418 pluginsettings.missingdependencies.push(setting_.id);
419 }
420 }
421 }
422 }else{
423 pluginsettings.installed=false;
424
425 delete pluginsettings.installeddir;
426 delete pluginsettings.missingdependencies;
427 }
428
429 return pluginsettings;
430}
431
432/**
433 * To load a plugin based on the pluginsettings provided
434 *
435 * @method loadPlugin
436 *
437 * @param {} pluginsetting plugin settings
438 * @param {callback} callback The callback to excecute when complete
439 */
440PluginLoader.loadPlugin = function(pluginsetting, callback){
441 var instance = this;
442
443 logger.getInstance().debug('Simple Portal : loadPlugin', 'Loading plugins --' + pluginsetting.installeddir);
444
445 simpleportal.pluginloader.readPluginSetting(pluginsetting);
446
447 __loadPlugin(pluginsetting, pluginsetting.configuration, PluginLoader.dbInstance, callback);
448}
449
450PluginLoader.services.service['GET /:id'] = function(request, response, callback){
451 if(request.user.role&&request.user.role=='superadmin')
452 callback(null, getServiceDetails(request.pathGroup))
453 else
454 callback('Permission denied');
455}
456
457PluginLoader.services.service['GET /'] = function(request, response, callback){
458 if(request.user.role&&request.user.role=='superadmin'){
459 var result =[];
460 for(var subModule in PluginLoader){
461 var details = PluginLoader.getPluginDetails(subModule);
462 if(details)
463 result.push(details);
464 }
465 callback(null, result);
466 } else
467 callback('Permission denied');
468};
469
470/**
471 * To unload a plugin from the `simpleportal.Server`
472 *
473 * @method unLoadPlugins
474 * @param {} configuration plugin configuration
475 * @param {callback} callback The callback to excecute when complete
476 */
477PluginLoader.unLoadPlugins = function(configuration, callback){
478 var plugindir = configuration&&configuration.plugindir ? configuration.plugindir : PluginLoader.plugindir;
479 logger.getInstance().info('Simple Portal : pluginloader', 'unLoadPlugins -- ' + plugindir);
480
481 var errors = [];
482 if(!fs.existsSync(plugindir))
483 callback();
484 else{
485 var stats = fs.lstatSync(plugindir);
486
487 if (stats.isDirectory()) {
488 PluginLoader.__unLoadPlugins(plugindir, {}, function(error){
489 if(error)
490 errors.push(error);
491
492 if(callback)
493 callback(errors);
494 });
495 }else if(callback)
496 callback();
497 }
498}
499
500/**
501 * To load plugins based ona plugin directory confoguration
502 *
503 * @method loadPlugins
504 *
505 * @param {} configuration Configuration for the plugin directory
506 * @param {callback} callback The callback to excecute when complete
507 */
508PluginLoader.loadPlugins = function(configuration, callback){
509 var plugindir = configuration&&configuration.plugindir ? configuration.plugindir : PluginLoader.plugindir;
510
511 logger.getInstance().info('Simple Portal : pluginloader', 'loadPlugins -- ' + plugindir);
512
513 if(!PluginLoader.plugins)
514 PluginLoader.plugins={util:[], webapp:[], theme:[]};
515
516 var errors;
517 if(!fs.existsSync(plugindir))
518 callback();
519 else{
520 var stats = fs.lstatSync(plugindir);
521
522 if (stats.isDirectory()) {
523 PluginLoader.loadPluginFromDirectory(plugindir, {}, function(error){
524 if(error){
525 errors=errors||[];
526 errors.push(error);
527 }
528
529 if(callback)
530 callback(errors);
531 });
532 }else if(callback)
533 callback();
534 }
535};
536
537/**
538 * To initialize the router required for the `simpleportal.Server`
539 *
540 * @method initRouter
541 * @param {} router router object where the oauth handlers will be registered
542 * @param {callback} callback The callback to excecute when complete
543 */
544PluginLoader.initRouter = function(router, callback){
545 logger.getInstance().info('Simple Portal - PluginLoader : initRouter', 'Initializing plugin routers');
546
547 router.dispatch.addServiceHandlers(PluginLoader, PluginLoader.pluginUrl, simpleportal.serviceloader.call);
548 router.dispatch.addServiceGlobalHandlers(PluginLoader, PluginLoader.pluginUrl, simpleportal.serviceloader.call);
549
550 if(callback)
551 callback();
552}
553
554new simpleportal.CRUDService({name:'pluginloader', service:PluginLoader, modify:true, collection:'pluginloader', userrole:'superadmin'});
\No newline at end of file