diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..acbc92a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "env": { + "node": true + }, + "parserOptions": { + "ecmaVersion": 8 + }, + "rules": { + "no-const-assign": "warn", + "no-this-before-super": "warn", + "no-undef": "warn", + "no-unreachable": "warn", + "no-unused-vars": "warn", + "constructor-super": "warn", + "valid-typeof": "warn", + "semi": "warn", + "keyword-spacing": "warn", + "space-before-function-paren": "warn", + "space-before-blocks": "warn", + "indent": ["warn", 4], + "no-trailing-spaces": "warn", + "comma-style": ["error", "last"], + "eol-last": ["error", "always"] + } +} \ No newline at end of file diff --git a/README.md b/README.md index b68990d..a858eac 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,36 @@ -Emergence -========= +# Emergence [![Join the chat at https://gitter.im/JarvusInnovations/Emergence](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/JarvusInnovations/Emergence?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Emergence is a NodeJS-powered server that provides a web interface for configuring and launching the services that power your website or application. It provides virtualized storage containers for your code and assets that are accessible via WebDAV and API. Each storage container maintains complete version history for all files and can be linked over the web to a parent container that files will be inherited from just-in-time. +## Features -Features ---------- -* Rich web interface provides for all setup and management -* Plugin-based support for system services to be configured and run - * Plugins included for nginx and mysql -* Versioned storage containers - * Inherit remote containers over http - * Copy-on-write - * Accessible remotely via WebDAV and locally via API -* PHP development framework - * Classes automatically loaded from storage container - * Lightweight MVC classes optimized for serial inheritance across sites - * Extendable templating system powered by Dwoo +- Rich web interface provides for all setup and management +- Plugin-based support for system services to be configured and run + - Plugins included for nginx and mysql +- Versioned storage containers + - Inherit remote containers over http + - Copy-on-write + - Accessible remotely via WebDAV and locally via API +- PHP development framework + - Classes automatically loaded from storage container + - Lightweight MVC classes optimized for serial inheritance across sites + - Extendable templating system powered by Dwoo +## Requirements -Requirements -------------- -* NodeJS -* npm - * underscore - * node-static -* mysql -* nginx -* php-fpm - * php 5.3+ - * apc - * mysqli +- NodeJS +- npm +- mysql +- nginx +- php-fpm + - php 5.6+ + - apcu + - mysqli +## Installation -Installation --------------- -See http://emr.ge/docs +See [http://emr.ge/docs](http://emr.ge/docs) - - -Visit http://serverhost:9083 in your browser +Visit [http://serverhost:9083](http://serverhost:9083) in your browser diff --git a/bin/kernel b/bin/kernel index 97bd81d..f4eea7b 100755 --- a/bin/kernel +++ b/bin/kernel @@ -1,19 +1,12 @@ #!/usr/bin/env node +var fs = require('fs'), + sitesLib = require('../kernel-lib/sites.js'), -// requirements -var _ = require('underscore'), - util = require('util'), - url = require('url'), - path = require('path'), - fs = require('fs'), - sitesLib = require('../kernel-lib/sites.js'); + CONFIG; -var CONFIG; - if (fs.existsSync('/emergence/config.json')) { // try to load existing kernel config - CONFIG = JSON.parse(fs.readFileSync('/emergence/config.json', 'ascii')); } else { // try to smart-init a new kernel config @@ -53,8 +46,6 @@ if (fs.existsSync('/emergence/config.json')) { }; - - // detect nginx if (fs.existsSync('/usr/sbin/nginx')) { CONFIG.services.plugins.web = { @@ -138,11 +129,13 @@ if (fs.existsSync('/emergence/config.json')) { }; } + fs.writeFileSync('/emergence/config.json', JSON.stringify(CONFIG, null, 4)); fs.chmodSync('/emergence/config.json', '600'); console.log('Generated and wrote initial config: /emergence/config.json'); } + // create default admin user if (!fs.existsSync('/emergence/admins.htpasswd')) { console.log('Creating default administrative user: admin/admin'); @@ -155,6 +148,7 @@ if (!fs.existsSync('/emergence/admins.htpasswd')) { var eSites = sitesLib.createSites(CONFIG); var eServices = require('../kernel-lib/services.js').createServices(eSites, CONFIG); + // instantiate management server var eManagementServer = require('../kernel-lib/server.js').createServer({ sites: eSites, @@ -163,4 +157,4 @@ var eManagementServer = require('../kernel-lib/server.js').createServer({ // start server -eManagementServer.start(); \ No newline at end of file +eManagementServer.start(); diff --git a/kernel-lib/server.js b/kernel-lib/server.js index 820f386..1d715a8 100644 --- a/kernel-lib/server.js +++ b/kernel-lib/server.js @@ -3,14 +3,19 @@ var http = require('http'), util = require('util'), fs = require('fs'), path = require('path'), - _ = require('underscore'), util = require('util'), url = require('url'), static = require('node-static'), events = require('events'), nodeCleanup = require('node-cleanup'); -exports.Server = function(paths, config) { + +exports.createServer = function (paths, options) { + return new Server(paths, options); +}; + + +function Server (paths, config) { var me = this, options = config.server; @@ -31,10 +36,10 @@ exports.Server = function(paths, config) { nodeCleanup(this.close.bind(this)); }; -util.inherits(exports.Server, events.EventEmitter); +util.inherits(Server, events.EventEmitter); -exports.Server.prototype.start = function() { +Server.prototype.start = function () { // create authenticator this.httpAuth = require('http-auth')({ authRealm: 'Emergence Node Management', @@ -67,30 +72,25 @@ exports.Server.prototype.start = function() { console.log('Management server listening on '+this.webProtocol+'://'+this.options.host+':'+this.options.port); }; -exports.createServer = function(paths, options) { - return new exports.Server(paths, options); -}; - - -exports.Server.prototype.handleWebRequest = function(request, response) { +Server.prototype.handleWebRequest = function (request, response) { var me = this; - me.httpAuth.apply(request, response, function(username) { + me.httpAuth.apply(request, response, function () { me.handleRequest(request, response); }); }; -exports.Server.prototype.handleRequest = function(request, response) { +Server.prototype.handleRequest = function (request, response) { var me = this; request.content = ''; - request.addListener('data', function(chunk) { + request.addListener('data', function (chunk) { request.content += chunk; }); - request.addListener('end', function() { - request.urlInfo = url.parse(request.url) + request.addListener('end', function () { + request.urlInfo = url.parse(request.url); request.path = request.urlInfo.pathname.substr(1).split('/'); console.log(request.method+' '+request.url); @@ -122,7 +122,7 @@ exports.Server.prototype.handleRequest = function(request, response) { }); }; -exports.Server.prototype.close = function(options, error) { +Server.prototype.close = function () { console.log('Shutting down management server...'); if (this.webServer) { @@ -132,4 +132,4 @@ exports.Server.prototype.close = function(options, error) { if (this.socketServer) { this.socketServer.close(); } -}; \ No newline at end of file +}; diff --git a/kernel-lib/services.js b/kernel-lib/services.js index 0853748..db269b3 100644 --- a/kernel-lib/services.js +++ b/kernel-lib/services.js @@ -1,12 +1,17 @@ var _ = require('underscore'), util = require('util'), fs = require('fs'), - path = require('path'), events = require('events'); -exports.ServicesController = function(sites, config) { + +exports.createServices = function (sites, config) { + return new ServicesController(sites, config); +}; + + +function ServicesController (sites, config) { var me = this, - options = config.services; + options = config.services; me.sites = sites; @@ -47,7 +52,7 @@ exports.ServicesController = function(sites, config) { // load service plugins me.services = {}; - _.each(me.options.plugins, function(plugin, name) { + _.each(me.options.plugins, function (plugin, name) { console.log('Loading service: '+name); if (_.isString(plugin)) { @@ -60,7 +65,7 @@ exports.ServicesController = function(sites, config) { }); // auto-start service plugins - _.each(me.services, function(service, name) { + _.each(me.services, function (service, name) { if (service.options.autoStart) { console.log('Autostarting service: '+name); service.start(); @@ -68,10 +73,10 @@ exports.ServicesController = function(sites, config) { }); }; -util.inherits(exports.ServicesController, events.EventEmitter); +util.inherits(ServicesController, events.EventEmitter); -exports.ServicesController.prototype.handleRequest = function(request, response, server) { +ServicesController.prototype.handleRequest = function (request) { var me = this; if (request.path[1]) { @@ -83,7 +88,7 @@ exports.ServicesController.prototype.handleRequest = function(request, response, services: [] }; - _.each(me.services, function(service, name) { + _.each(me.services, function (service) { statusData.services.push(service.getStatus()); }); @@ -93,7 +98,7 @@ exports.ServicesController.prototype.handleRequest = function(request, response, return false; }; -exports.ServicesController.prototype.handleServiceRequest = function(request, response, server) { +ServicesController.prototype.handleServiceRequest = function (request) { var me = this, service = me.services[request.path[1]]; @@ -124,7 +129,3 @@ exports.ServicesController.prototype.handleServiceRequest = function(request, re return false; }; - -exports.createServices = function(sites, config) { - return new exports.ServicesController(sites, config); -}; \ No newline at end of file diff --git a/kernel-lib/services/abstract.js b/kernel-lib/services/abstract.js index e9e3071..5be0a77 100644 --- a/kernel-lib/services/abstract.js +++ b/kernel-lib/services/abstract.js @@ -1,13 +1,12 @@ -var _ = require('underscore') - ,util = require('util') - ,events = require('events'); +var util = require('util'), + events = require('events'); -exports.AbstractService = function(name, controller, options) { +function AbstractService (name, controller, options) { var me = this; // call events constructor - exports.AbstractService.super_.apply(me, arguments); + AbstractService.super_.apply(me, arguments); // initialize options and apply defaults me.name = name; @@ -19,28 +18,30 @@ exports.AbstractService = function(name, controller, options) { me.status = 'offline'; }; -util.inherits(exports.AbstractService, events.EventEmitter); +util.inherits(AbstractService, events.EventEmitter); +module.exports = AbstractService; -exports.AbstractService.prototype.getStatus = function() { + +AbstractService.prototype.getStatus = function () { return { - name: this.name - ,status: this.status + name: this.name, + status: this.status }; -} +}; -exports.AbstractService.prototype.start = function() { +AbstractService.prototype.start = function () { throw new Error('start() not implemented in '+this.name); }; -exports.AbstractService.prototype.stop = function() { +AbstractService.prototype.stop = function () { throw new Error('start() not implemented in '+this.name); }; -exports.AbstractService.prototype.restart = function() { +AbstractService.prototype.restart = function () { if (this.stop()) { return this.start(); } else { return false; } -}; \ No newline at end of file +}; diff --git a/kernel-lib/services/mysql.js b/kernel-lib/services/mysql.js index 7e9bba2..f835738 100644 --- a/kernel-lib/services/mysql.js +++ b/kernel-lib/services/mysql.js @@ -1,6 +1,5 @@ var _ = require('underscore'), fs = require('fs'), - path = require('path'), util = require('util'), spawn = require('child_process').spawn, exec = require('child_process').exec, @@ -8,16 +7,18 @@ var _ = require('underscore'), semver = require('semver'), mysql = require('mysql2'); -exports.createService = function(name, controller, options) { - return new exports.MysqlService(name, controller, options); + +exports.createService = function (name, controller, options) { + return new MysqlService(name, controller, options); }; -exports.MysqlService = function(name, controller, options) { + +function MysqlService (name, controller) { var me = this, versionMatch; // call parent constructor - exports.MysqlService.super_.apply(me, arguments); + MysqlService.super_.apply(me, arguments); // default options me.options.configPath = me.options.configPath || controller.options.configDir + '/my.cnf'; @@ -67,11 +68,10 @@ exports.MysqlService = function(name, controller, options) { controller.sites.on('siteCreated', _.bind(me.onSiteCreated, me)); }; -util.inherits(exports.MysqlService, require('./abstract.js').AbstractService); - +util.inherits(MysqlService, require('./abstract.js')); -exports.MysqlService.prototype.start = function(firstRun) { +MysqlService.prototype.start = function (firstRun) { var me = this; if (me.pid) { @@ -104,11 +104,11 @@ exports.MysqlService.prototype.start = function(firstRun) { exec('chown -R mysql:mysql '+me.options.dataDir); if (semver.lt(me.mysqldVersion, '5.7.6') || me.mysqldIsMaria) { - exec('mysql_install_db --defaults-file='+me.options.configPath, function(error, stdout, stderr) { + exec('mysql_install_db --defaults-file='+me.options.configPath, function () { me.start(true); }); } else { - exec('mysqld --initialize-insecure --user=mysql --datadir='+me.options.dataDir, function(error, stdout, stderr) { + exec('mysqld --initialize-insecure --user=mysql --datadir='+me.options.dataDir, function () { me.start(true); }); } @@ -155,8 +155,7 @@ exports.MysqlService.prototype.start = function(firstRun) { return true; }; - -exports.MysqlService.prototype.stop = function() { +MysqlService.prototype.stop = function () { var me = this; if (!me.pid) { @@ -176,7 +175,7 @@ exports.MysqlService.prototype.stop = function() { return true; }; -exports.MysqlService.prototype.restart = function() { +MysqlService.prototype.restart = function () { var me = this, now; @@ -200,11 +199,11 @@ exports.MysqlService.prototype.restart = function() { return me.start(); }; -exports.MysqlService.prototype.writeConfig = function() { +MysqlService.prototype.writeConfig = function () { fs.writeFileSync(this.options.configPath, this.makeConfig()); }; -exports.MysqlService.prototype.makeConfig = function() { +MysqlService.prototype.makeConfig = function () { var me = this, config = []; @@ -215,7 +214,7 @@ exports.MysqlService.prototype.makeConfig = function() { 'port = 3306', 'socket = '+me.options.socketPath, 'pid-file = '+me.options.pidPath, -// 'log-error = '+me.options.errorLogPath, // disabled due to http://bugs.mysql.com/bug.php?id=65592 -- errors output to STDIN will usually go into emergence-kernel's log + // 'log-error = '+me.options.errorLogPath, // disabled due to http://bugs.mysql.com/bug.php?id=65592 -- errors output to STDIN will usually go into emergence-kernel's log 'basedir = /usr', 'datadir = '+me.options.dataDir, 'skip-external-locking', @@ -226,7 +225,7 @@ exports.MysqlService.prototype.makeConfig = function() { 'read_buffer_size = 256K', 'read_rnd_buffer_size = 512K', 'myisam_sort_buffer_size = 8M', -// 'lc-messages-dir = /usr/local/share/mysql', + // 'lc-messages-dir = /usr/local/share/mysql', 'log-bin = mysqld-bin', 'expire_logs_days = 2', @@ -265,7 +264,7 @@ exports.MysqlService.prototype.makeConfig = function() { return config.join('\n'); }; -exports.MysqlService.prototype.secureInstallation = function() { +MysqlService.prototype.secureInstallation = function () { var me = this, sql = ''; @@ -299,7 +298,7 @@ exports.MysqlService.prototype.secureInstallation = function() { multipleStatements: true }); - connection.query(sql, function(error) { + connection.query(sql, function (error) { connection.end(); if (error) { @@ -310,8 +309,7 @@ exports.MysqlService.prototype.secureInstallation = function() { }); }; - -exports.MysqlService.prototype.onSiteCreated = function(siteData, requestData, callbacks) { +MysqlService.prototype.onSiteCreated = function (siteData, requestData, callbacks) { var me = this, sql = '', dbConfig = { @@ -328,7 +326,7 @@ exports.MysqlService.prototype.onSiteCreated = function(siteData, requestData, c sql += 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, LOCK TABLES ON `'+siteData.handle+'`.* TO \''+siteData.handle+'\'@\'localhost\';'; sql += 'FLUSH PRIVILEGES;'; - me.executeSQL(sql, function(error, results) { + me.executeSQL(sql, function (error) { if (error) { console.log(me.name+': failed to setup database `'+siteData.handle+'`: '+error); return; @@ -340,7 +338,7 @@ exports.MysqlService.prototype.onSiteCreated = function(siteData, requestData, c }); // populate tables - me.createSkeletonTables(siteData, function() { + me.createSkeletonTables(siteData, function () { if (callbacks.databaseReady) { callbacks.databaseReady(dbConfig, siteData, requestData); } @@ -348,9 +346,7 @@ exports.MysqlService.prototype.onSiteCreated = function(siteData, requestData, c }); }; - - -exports.MysqlService.prototype.createSkeletonTables = function(siteData, callback) { +MysqlService.prototype.createSkeletonTables = function (siteData, callback) { var me = this, sql = ''; @@ -389,7 +385,7 @@ exports.MysqlService.prototype.createSkeletonTables = function(siteData, callbac sql += ') ENGINE=MyISAM DEFAULT CHARSET=utf8;'; // run tables - me.executeSQL(sql, function(error, results) { + me.executeSQL(sql, function (error) { if (error) { console.log(me.name+': failed to setup skeleton tables on `'+siteData.handle+'`: '+error); return; @@ -401,9 +397,7 @@ exports.MysqlService.prototype.createSkeletonTables = function(siteData, callbac }); }; - - -exports.MysqlService.prototype.executeSQL = function(sql, callback) { +MysqlService.prototype.executeSQL = function (sql, callback) { var connection = mysql.createConnection({ socketPath: this.options.socketPath, user: this.options.managerUser, @@ -411,9 +405,9 @@ exports.MysqlService.prototype.executeSQL = function(sql, callback) { multipleStatements: true }); - connection.query(sql, function(err, results) { + connection.query(sql, function (err, results) { connection.end(); callback(err, results); }); -}; \ No newline at end of file +}; diff --git a/kernel-lib/services/nginx.js b/kernel-lib/services/nginx.js index 5e5d8a5..1428769 100644 --- a/kernel-lib/services/nginx.js +++ b/kernel-lib/services/nginx.js @@ -1,18 +1,19 @@ var _ = require('underscore'), fs = require('fs'), - path = require('path'), util = require('util'), spawn = require('child_process').spawn; -exports.createService = function(name, controller, options) { - return new exports.NginxService(name, controller, options); + +exports.createService = function (name, controller, options) { + return new NginxService(name, controller, options); }; -exports.NginxService = function(name, controller, options) { + +function NginxService (name, controller) { var me = this; // call parent constructor - exports.NginxService.super_.apply(me, arguments); + NginxService.super_.apply(me, arguments); // default options me.options.configPath = me.options.configPath || controller.options.configDir + '/nginx.conf'; @@ -50,11 +51,10 @@ exports.NginxService = function(name, controller, options) { controller.sites.on('siteUpdated', _.bind(me.onSiteCreated, me)); }; -util.inherits(exports.NginxService, require('./abstract.js').AbstractService); +util.inherits(NginxService, require('./abstract.js')); - -exports.NginxService.prototype.start = function() { +NginxService.prototype.start = function () { var me = this; console.log(me.name+': spawning daemon: '+me.options.execPath); @@ -83,7 +83,7 @@ exports.NginxService.prototype.start = function() { me.status = 'online'; } else { console.log(me.name+': failed to find pid after launching, waiting 1000ms and trying again...'); - setTimeout(function() { + setTimeout(function () { if (fs.existsSync(me.options.pidPath)) { me.pid = parseInt(fs.readFileSync(me.options.pidPath, 'ascii')); @@ -115,8 +115,7 @@ exports.NginxService.prototype.start = function() { return true; }; - -exports.NginxService.prototype.stop = function() { +NginxService.prototype.stop = function () { var me = this; if (!me.pid) { @@ -135,8 +134,7 @@ exports.NginxService.prototype.stop = function() { return true; }; - -exports.NginxService.prototype.restart = function() { +NginxService.prototype.restart = function () { var me = this; if (!me.pid) { @@ -157,12 +155,11 @@ exports.NginxService.prototype.restart = function() { return true; }; - -exports.NginxService.prototype.writeConfig = function() { +NginxService.prototype.writeConfig = function () { fs.writeFileSync(this.options.configPath, this.makeConfig()); }; -exports.NginxService.prototype.makeConfig = function() { +NginxService.prototype.makeConfig = function () { var me = this, phpSocketPath = me.controller.services['php'].options.socketPath, phpBootstrapDir = me.controller.services['php'].options.bootstrapDir, @@ -245,7 +242,7 @@ exports.NginxService.prototype.makeConfig = function() { ' fastcgi_buffers 32 64k;', ' server_tokens off;' -/* + /* ' server {', ' server_name _;', @@ -255,7 +252,7 @@ exports.NginxService.prototype.makeConfig = function() { */ ); - _.each(me.controller.sites.sites, function(site, handle) { + _.each(me.controller.sites.sites, function (site, handle) { var hostnames = site.hostnames.slice(), siteDir = me.controller.sites.options.sitesDir+'/'+handle, logsDir = siteDir+'/logs', @@ -309,7 +306,7 @@ exports.NginxService.prototype.makeConfig = function() { sslHostnames = {}; sslHostnames[site.primary_hostname] = site.ssl; - site.hostnames.forEach(function(hostname) { + site.hostnames.forEach(function (hostname) { sslHostnames[hostname] = site.ssl; }); } @@ -341,7 +338,6 @@ exports.NginxService.prototype.makeConfig = function() { return config.join('\n'); }; - -exports.NginxService.prototype.onSiteCreated = function(siteData) { +NginxService.prototype.onSiteCreated = function () { this.restart(); }; diff --git a/kernel-lib/services/php-fpm.js b/kernel-lib/services/php-fpm.js index 9cde0fd..a590552 100644 --- a/kernel-lib/services/php-fpm.js +++ b/kernel-lib/services/php-fpm.js @@ -5,15 +5,17 @@ var _ = require('underscore'), spawn = require('child_process').spawn, phpfpm = require('node-phpfpm'); -exports.createService = function(name, controller, options) { - return new exports.PhpFpmService(name, controller, options); + +exports.createService = function (name, controller, options) { + return new PhpFpmService(name, controller, options); }; -exports.PhpFpmService = function(name, controller, options) { + +function PhpFpmService (name, controller) { var me = this; // call parent constructor - exports.PhpFpmService.super_.apply(me, arguments); + PhpFpmService.super_.apply(me, arguments); // default options me.options.bootstrapDir = me.options.bootstrapDir || path.resolve(__dirname, '../../php-bootstrap'); @@ -48,11 +50,10 @@ exports.PhpFpmService = function(name, controller, options) { controller.sites.on('siteUpdated', _.bind(me.onSiteUpdated, me)); }; -util.inherits(exports.PhpFpmService, require('./abstract.js').AbstractService); +util.inherits(PhpFpmService, require('./abstract.js')); - -exports.PhpFpmService.prototype.start = function() { +PhpFpmService.prototype.start = function () { var me = this; console.log(me.name+': spawning daemon: '+me.options.execPath); @@ -101,10 +102,10 @@ exports.PhpFpmService.prototype.start = function() { this.status = 'online'; return true; -} +}; -exports.PhpFpmService.prototype.stop = function() { +PhpFpmService.prototype.stop = function () { var me = this; if (!me.pid) { @@ -124,7 +125,7 @@ exports.PhpFpmService.prototype.stop = function() { }; -exports.PhpFpmService.prototype.restart = function() { +PhpFpmService.prototype.restart = function () { var me = this; if (!me.pid) { @@ -146,11 +147,11 @@ exports.PhpFpmService.prototype.restart = function() { }; -exports.PhpFpmService.prototype.writeConfig = function() { +PhpFpmService.prototype.writeConfig = function () { fs.writeFileSync(this.options.configPath, this.makeConfig()); }; -exports.PhpFpmService.prototype.makeConfig = function() { +PhpFpmService.prototype.makeConfig = function () { var me = this, config = []; @@ -197,7 +198,7 @@ exports.PhpFpmService.prototype.makeConfig = function() { return config.join('\n'); }; -exports.PhpFpmService.prototype.onSiteUpdated = function(siteData) { +PhpFpmService.prototype.onSiteUpdated = function (siteData) { var me = this, siteRoot = me.controller.sites.options.sitesDir + '/' + siteData.handle, phpClient; @@ -216,7 +217,7 @@ exports.PhpFpmService.prototype.onSiteUpdated = function(siteData) { json: [ { action: 'delete', key: siteRoot } ] - }, function(err, output, phpErrors) { + }, function (err, output, phpErrors) { if (err == 99) console.error('PHPFPM server error'); console.log(output); if (phpErrors) console.error(phpErrors); diff --git a/kernel-lib/sites.js b/kernel-lib/sites.js index 60e2458..57b0810 100644 --- a/kernel-lib/sites.js +++ b/kernel-lib/sites.js @@ -10,13 +10,14 @@ var _ = require('underscore'), phpShellScript = path.resolve(__dirname, '../bin/shell'); -exports.createSites = function(config) { - return new exports.Sites(config); +exports.createSites = function (config) { + return new Sites(config); }; -exports.Sites = function(config) { + +function Sites (config) { var me = this, - options = config.sites; + options = config.sites; // call events constructor events.EventEmitter.call(me); @@ -38,7 +39,7 @@ exports.Sites = function(config) { console.log('Loading sites from '+me.options.sitesDir+'...'); me.sites = {}; - _.each(fs.readdirSync(me.options.sitesDir), function(handle) { + _.each(fs.readdirSync(me.options.sitesDir), function (handle) { try { me.sites[handle] = JSON.parse(fs.readFileSync(me.options.sitesDir+'/'+handle+'/site.json', 'ascii')); me.sites[handle].handle = handle; @@ -50,10 +51,10 @@ exports.Sites = function(config) { }; -util.inherits(exports.Sites, events.EventEmitter); +util.inherits(Sites, events.EventEmitter); -exports.Sites.prototype.handleRequest = function(request, response, server) { +Sites.prototype.handleRequest = function (request, response) { var me = this; if (request.method == 'GET') { @@ -149,11 +150,11 @@ exports.Sites.prototype.handleRequest = function(request, response, server) { phpProc = spawn(phpShellScript, [request.path[1]]); phpProcInitialized = false; - phpProc.stderr.on('data', function(data) { + phpProc.stderr.on('data', function (data) { console.log('php-cli stderr: ' + data); }); - phpProc.stdout.on('data', function(data) { + phpProc.stdout.on('data', function (data) { console.log('php-cli stdout: ' + data); // skip first chunk from PHP process @@ -181,11 +182,11 @@ exports.Sites.prototype.handleRequest = function(request, response, server) { phpProc = spawn(phpShellScript, [request.path[1], '--stdin']); - phpProc.stdout.on('data', function(data) { + phpProc.stdout.on('data', function (data) { console.log('php-cli stdout: ' + data); response.write(data); }); - phpProc.stderr.on('data', function(data) { console.log('php-cli stderr: ' + data); }); + phpProc.stderr.on('data', function (data) { console.log('php-cli stderr: ' + data); }); requestData.AccountLevel = 'Developer'; @@ -229,15 +230,15 @@ exports.Sites.prototype.handleRequest = function(request, response, server) { // notify plugins me.emit('siteCreated', cfgResult.site, requestData, { - databaseReady: function() { + databaseReady: function () { // execute onSiteCreated within site's container console.log('Executing Site::onSiteCreated() via php-cli'); phpProc = spawn(phpShellScript, [cfgResult.site.handle]); - phpProc.stdout.on('data', function(data) { console.log('php-cli stdout: ' + data); }); - phpProc.stderr.on('data', function(data) { console.log('php-cli stderr: ' + data); }); + phpProc.stdout.on('data', function (data) { console.log('php-cli stdout: ' + data); }); + phpProc.stderr.on('data', function (data) { console.log('php-cli stderr: ' + data); }); - function _phpExec(code) { + function _phpExec (code) { //console.log('php> '+code); phpProc.stdin.write(code+'\n'); } @@ -271,8 +272,7 @@ exports.Sites.prototype.handleRequest = function(request, response, server) { return false; }; - -exports.Sites.prototype.writeSiteConfig = function(requestData) { +Sites.prototype.writeSiteConfig = function (requestData) { var me = this, siteData = _.clone(requestData); @@ -342,7 +342,7 @@ exports.Sites.prototype.writeSiteConfig = function(requestData) { return {site: siteData, isNew: isNew}; }; -exports.Sites.prototype.updateSiteConfig = function(handle, changes) { +Sites.prototype.updateSiteConfig = function (handle, changes) { var me = this, siteDir = me.options.sitesDir+'/'+handle, filename = siteDir+'/site.json', @@ -361,8 +361,7 @@ exports.Sites.prototype.updateSiteConfig = function(handle, changes) { } }; - -exports.generatePassword = exports.Sites.prototype.generatePassword = function(length) { +Sites.prototype.generatePassword = function (length) { length = length || 16; var pass = '', @@ -374,3 +373,6 @@ exports.generatePassword = exports.Sites.prototype.generatePassword = function(l return pass; }; + + +exports.generatePassword = Sites.prototype.generatePassword; diff --git a/kernel-www/.eslintrc.json b/kernel-www/.eslintrc.json new file mode 100644 index 0000000..8e49afa --- /dev/null +++ b/kernel-www/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "env": { + "browser": true + }, + "globals": { + "Ext": true, + "eMan": true + } +} \ No newline at end of file diff --git a/kernel-www/app.js b/kernel-www/app.js index f6323d6..5777386 100644 --- a/kernel-www/app.js +++ b/kernel-www/app.js @@ -1,36 +1,36 @@ // enable and configure loader Ext.Loader.setConfig({ - enabled:true - ,paths:{ - Ext: '//extjs.cachefly.net/ext/gpl/5.0.0/src' - } + enabled:true, + paths:{ + Ext: '//extjs.cachefly.net/ext/gpl/5.0.0/src' + } }); Ext.application({ - name: 'eMan' - ,appFolder: 'app' - - ,controllers: ['Viewport', 'Services', 'Sites', 'Log'] - - ,autoCreateViewport: false - - ,launch: function() { - eMan.app = this; - eMan.log = Ext.bind(eMan.app.log, eMan.app); - this.viewport = Ext.create('eMan.view.Viewport'); - this.viewport.setLoading(true); - Ext.Ajax.request({ - url: '/server-config' - ,success: function(response) { - var r = Ext.decode(response.responseText); - eMan.app.serverConfig = r; - eMan.app.viewport.setLoading(false); - } - }); - this.fireEvent('log', 'Emergence Manager ready.'); - } - - ,log: function(message) { - this.fireEvent('log', message); - } + name: 'eMan', + appFolder: 'app', + + controllers: ['Viewport', 'Services', 'Sites', 'Log'], + + autoCreateViewport: false, + + launch: function () { + eMan.app = this; + eMan.log = Ext.bind(eMan.app.log, eMan.app); + this.viewport = Ext.create('eMan.view.Viewport'); + this.viewport.setLoading(true); + Ext.Ajax.request({ + url: '/server-config', + success: function (response) { + var r = Ext.decode(response.responseText); + eMan.app.serverConfig = r; + eMan.app.viewport.setLoading(false); + } + }); + this.fireEvent('log', 'Emergence Manager ready.'); + }, + + log: function (message) { + this.fireEvent('log', message); + } }); diff --git a/kernel-www/app/controller/Log.js b/kernel-www/app/controller/Log.js index 4e2c2c7..c0cb88a 100644 --- a/kernel-www/app/controller/Log.js +++ b/kernel-www/app/controller/Log.js @@ -1,24 +1,23 @@ Ext.define('eMan.controller.Log', { - extend: 'Ext.app.Controller' + extend: 'Ext.app.Controller', - ,views: ['log.Grid'] - ,stores: ['Log'] - ,models: ['LogEntry'] + views: ['log.Grid'], + stores: ['Log'], + models: ['LogEntry'], - ,init: function() { - this.control({ - 'loggrid': { - afterrender: function(grid) { - eMan.app.on('log', function(message, type) { - this.getLogStore().insert(0, { - timestamp: new Date() - ,message: message - }); - }, this); - } - ,scope: this - } - }); - } - -}); \ No newline at end of file + init: function () { + this.control({ + 'loggrid': { + afterrender: function () { + eMan.app.on('log', function (message) { + this.getLogStore().insert(0, { + timestamp: new Date(), + message: message + }); + }, this); + }, + scope: this + } + }); + } +}); diff --git a/kernel-www/app/controller/Services.js b/kernel-www/app/controller/Services.js index 3e57841..672474a 100644 --- a/kernel-www/app/controller/Services.js +++ b/kernel-www/app/controller/Services.js @@ -1,138 +1,138 @@ Ext.define('eMan.controller.Services', { - extend: 'Ext.app.Controller' - - ,views: ['services.Grid'] - ,stores: ['Services'] - ,models: ['Service'] - - ,init: function() { - - this.startServiceBtn = new Ext.create('Ext.menu.Item', { - text: 'Start Service' - ,scope: this - ,handler: this.onStartPress - }); - - this.restartServiceBtn = new Ext.create('Ext.menu.Item', { - text: 'Restart Service' - ,scope: this - ,handler: this.onRestartPress - }); - - this.stopServiceBtn = new Ext.create('Ext.menu.Item', { - text: 'Stop Service' - ,scope: this - ,handler: this.onStopPress - }); - - this.servicesContextMenu = Ext.create('Ext.menu.Menu', { - items: [this.startServiceBtn, this.restartServiceBtn, this.stopServiceBtn] - }); - - this.control({ - 'servicesgrid gridview': { - scope: this - ,cellclick: function(view, cellEl, colIndex, record, rowEl, rowIndex, ev) { - if(colIndex == 1) - this.showServiceMenu(view, cellEl, record); + extend: 'Ext.app.Controller', + + views: ['services.Grid'], + stores: ['Services'], + models: ['Service'], + + init: function () { + + this.startServiceBtn = new Ext.create('Ext.menu.Item', { + text: 'Start Service', + scope: this, + handler: this.onStartPress + }); + + this.restartServiceBtn = new Ext.create('Ext.menu.Item', { + text: 'Restart Service', + scope: this, + handler: this.onRestartPress + }); + + this.stopServiceBtn = new Ext.create('Ext.menu.Item', { + text: 'Stop Service', + scope: this, + handler: this.onStopPress + }); + + this.servicesContextMenu = Ext.create('Ext.menu.Menu', { + items: [this.startServiceBtn, this.restartServiceBtn, this.stopServiceBtn] + }); + + this.control({ + 'servicesgrid gridview': { + scope: this, + cellclick: function (view, cellEl, colIndex, record) { + if (colIndex == 1) + this.showServiceMenu(view, cellEl, record); } - } - ,'servicesgrid tool[type=refresh]': { - scope: this - ,click: function() { - this.getServicesStore().load(); - } - } - }); - } - - ,showServiceMenu: function(view, cellEl, service) { - if(service.get('status') == 'offline') - { - this.startServiceBtn.show(); - this.restartServiceBtn.hide(); - this.stopServiceBtn.hide(); - } - else - { - this.startServiceBtn.hide(); - this.restartServiceBtn.show(); - this.stopServiceBtn.show(); - } - - this.servicesContextMenu.contextRecord = service; - this.servicesContextMenu.showBy(cellEl); - } - - ,onStartPress: function(btn, ev) { - var service = btn.parentMenu.contextRecord; - - eMan.log('Starting service '+service.get('name')+'...'); - service.set('status', 'starting...'); - - Ext.Ajax.request({ - url: '/services/'+service.get('name')+'/!start' - ,method: 'POST' - ,scope: this - ,success: function(response) { - var r = Ext.decode(response.responseText); - - eMan.log((r.success?'Successfully started service ':'Failed to start service')+service.get('name')); - - if(r.status) - { - service.set(r.status); - service.commit(); - } - } - }); - } - - ,onStopPress: function(btn, ev) { - var service = btn.parentMenu.contextRecord; - - eMan.log('Stopping service '+service.get('name')+'...'); - service.set('status', 'stopping...'); - - Ext.Ajax.request({ - url: '/services/'+service.get('name')+'/!stop' - ,method: 'POST' - ,scope: this - ,success: function(response) { - var r = Ext.decode(response.responseText); - - eMan.log((r.success?'Successfully stopped service ':'Failed to stop service ')+service.get('name')); - - if(r.status) - { - service.set(r.status); - service.commit(); - } - } - }); - } - - ,onRestartPress: function(btn, ev) { - var service = btn.parentMenu.contextRecord; - - eMan.log('Restarting service '+service.get('name')+'...'); - service.set('status', 'restarting...'); - - Ext.Ajax.request({ - url: '/services/'+service.get('name')+'/!restart' - ,method: 'POST' - ,scope: this - ,success: function(response) { - var r = Ext.decode(response.responseText); - - eMan.log((r.success?'Successfully restarted service ':'Failed to restart service ')+service.get('name')); - - if(r.status) - { - service.set(r.status); - service.commit(); - } - } - }); - } -}); \ No newline at end of file + }, + 'servicesgrid tool[type=refresh]': { + scope: this, + click: function () { + this.getServicesStore().load(); + } + } + }); + }, + + showServiceMenu: function (view, cellEl, service) { + if (service.get('status') == 'offline') + { + this.startServiceBtn.show(); + this.restartServiceBtn.hide(); + this.stopServiceBtn.hide(); + } + else + { + this.startServiceBtn.hide(); + this.restartServiceBtn.show(); + this.stopServiceBtn.show(); + } + + this.servicesContextMenu.contextRecord = service; + this.servicesContextMenu.showBy(cellEl); + }, + + onStartPress: function (btn) { + var service = btn.parentMenu.contextRecord; + + eMan.log('Starting service '+service.get('name')+'...'); + service.set('status', 'starting...'); + + Ext.Ajax.request({ + url: '/services/'+service.get('name')+'/!start', + method: 'POST', + scope: this, + success: function (response) { + var r = Ext.decode(response.responseText); + + eMan.log((r.success?'Successfully started service ':'Failed to start service')+service.get('name')); + + if (r.status) + { + service.set(r.status); + service.commit(); + } + } + }); + }, + + onStopPress: function (btn) { + var service = btn.parentMenu.contextRecord; + + eMan.log('Stopping service '+service.get('name')+'...'); + service.set('status', 'stopping...'); + + Ext.Ajax.request({ + url: '/services/'+service.get('name')+'/!stop', + method: 'POST', + scope: this, + success: function (response) { + var r = Ext.decode(response.responseText); + + eMan.log((r.success?'Successfully stopped service ':'Failed to stop service ')+service.get('name')); + + if (r.status) + { + service.set(r.status); + service.commit(); + } + } + }); + }, + + onRestartPress: function (btn) { + var service = btn.parentMenu.contextRecord; + + eMan.log('Restarting service '+service.get('name')+'...'); + service.set('status', 'restarting...'); + + Ext.Ajax.request({ + url: '/services/'+service.get('name')+'/!restart', + method: 'POST', + scope: this, + success: function (response) { + var r = Ext.decode(response.responseText); + + eMan.log((r.success?'Successfully restarted service ':'Failed to restart service ')+service.get('name')); + + if (r.status) + { + service.set(r.status); + service.commit(); + } + } + }); + } +}); diff --git a/kernel-www/app/controller/Sites.js b/kernel-www/app/controller/Sites.js index c8206c6..f7c30a5 100644 --- a/kernel-www/app/controller/Sites.js +++ b/kernel-www/app/controller/Sites.js @@ -1,69 +1,69 @@ Ext.define('eMan.controller.Sites', { - extend: 'Ext.app.Controller' - ,requires: ['Ext.Ajax', 'Ext.window.Window'] - - ,views: ['site.Grid', 'site.CreateForm', 'site.DeveloperForm', 'site.Menu'] - ,stores: ['Sites','Skeletons'] - ,models: ['Site'] - - ,refs: [{ - ref: 'siteMenu' - ,selector: 'sitemenu' - ,autoCreate: true - ,xtype: 'sitemenu' - },{ - ref: 'createForm' - ,selector: 'sitecreate' - ,autoCreate: true - ,xtype: 'sitecreate' - },{ - ref: 'developerWindow' - ,selector: 'window#developer-create' - ,autoCreate: true - - ,xtype: 'window' - ,itemId: 'developer' - ,title: 'Create developer user' - ,width: 400 - ,modal: true - ,items: { - xtype: 'developerform' - } - }] - - ,init: function() { - var me = this - ,skeletonsStore = me.getSkeletonsStore(); - - this.control({ - 'sitegrid': { - itemcontextmenu: me.onSiteContextMenu - } - ,'sitegrid button[action=create]': { - click: me.onCreateClick - } - ,'sitemenu menuitem[action=create-inheriting]': { + extend: 'Ext.app.Controller', + requires: ['Ext.Ajax', 'Ext.window.Window'], + + views: ['site.Grid', 'site.CreateForm', 'site.DeveloperForm', 'site.Menu'], + stores: ['Sites','Skeletons'], + models: ['Site'], + + refs: [{ + ref: 'siteMenu', + selector: 'sitemenu', + autoCreate: true, + xtype: 'sitemenu' + },{ + ref: 'createForm', + selector: 'sitecreate', + autoCreate: true, + xtype: 'sitecreate' + },{ + ref: 'developerWindow', + selector: 'window#developer-create', + autoCreate: true, + + xtype: 'window', + itemId: 'developer', + title: 'Create developer user', + width: 400, + modal: true, + items: { + xtype: 'developerform' + } + }], + + init: function () { + var me = this, + skeletonsStore = me.getSkeletonsStore(); + + this.control({ + 'sitegrid': { + itemcontextmenu: me.onSiteContextMenu + }, + 'sitegrid button[action=create]': { + click: me.onCreateClick + }, + 'sitemenu menuitem[action=create-inheriting]': { click: me.onCreateInheritingClick - } - ,'sitemenu menuitem[action=create-developer]': { + }, + 'sitemenu menuitem[action=create-developer]': { click: me.onCreateDeveloperClick + }, + 'sitecreate button[action=save]': { + click: me.createSite + }, + 'sitecreate button[action=cancel]': { + click: me.cancelCreateSite + }, + 'developerform button[action=save]': { + click: 'onDeveloperSaveClick' + }, + 'developerform button[action=cancel]': { + click: 'onDeveloperCancelClick' } - ,'sitecreate button[action=save]': { - click: me.createSite - } - ,'sitecreate button[action=cancel]': { - click: me.cancelCreateSite - } - ,'developerform button[action=save]': { - click: 'onDeveloperSaveClick' - } - ,'developerform button[action=cancel]': { - click: 'onDeveloperCancelClick' - } - }); - - // load and check that at least skeleton-v1 is in the store - skeletonsStore.load(function(records) { + }); + + // load and check that at least skeleton-v1 is in the store + skeletonsStore.load(function (records) { if (!records.length) { skeletonsStore.add({hostname: 'skeleton.emr.ge', key: '8U6kydil36bl3vlJ'}); skeletonsStore.sync(); @@ -71,9 +71,9 @@ Ext.define('eMan.controller.Sites', { // download latest Ext.Ajax.request({ - method: 'GET' - ,url: 'http://emr.ge/skeletons.json' - ,success: function(response) { + method: 'GET', + url: 'http://emr.ge/skeletons.json', + success: function (response) { var data = Ext.decode(response.responseText, true); if (data) { skeletonsStore.loadData(data); @@ -81,142 +81,142 @@ Ext.define('eMan.controller.Sites', { } } }); - }); - } - - ,showCreateForm: function(siteRecord, animateTarget) { - - this.editingSite = siteRecord; - - this.getCreateForm().loadRecord(this.editingSite); - - this.createWindow = Ext.create('Ext.window.Window', { - title: 'Create a new site' - ,width: 400 - ,modal: true - ,layout: 'fit' - ,items: this.getCreateForm() - ,listeners: { - scope: this - ,show: { - fn: function() { - this.getCreateForm().getForm().findField('label').focus(); - } - ,delay: 500 - } - } - }); - - this.createWindow.show(animateTarget); - } - - - ,createSite: function() { - var data = this.getCreateForm().getValues(); - - if(data.user_username || data.user_password || data.user_email || data.user_first || data.user_last) - { - if(!(data.user_username && data.user_password && data.user_email && data.user_first && data.user_last)) - { - Ext.Msg.alert('Incomplete user', 'Please fill out all fields for a first user'); - return false; - } - - data.create_user = { - Username: data.user_username - ,Password: data.user_password - ,Email: data.user_email - ,FirstName: data.user_first - ,LastName: data.user_last - }; - - delete data.user_email; - delete data.user_password; - delete data.user_email; - delete data.user_first; - delete data.user_last; - } - - this.editingSite.set(data); - this.getSitesStore().add(this.editingSite); - this.createWindow.close(); - } - - ,cancelCreateSite: function() { - this.createWindow.close(); - } - - ,onSiteContextMenu: function(tree, record, item, index, ev) { + }); + }, + + showCreateForm: function (siteRecord, animateTarget) { + + this.editingSite = siteRecord; + + this.getCreateForm().loadRecord(this.editingSite); + + this.createWindow = Ext.create('Ext.window.Window', { + title: 'Create a new site', + width: 400, + modal: true, + layout: 'fit', + items: this.getCreateForm(), + listeners: { + scope: this, + show: { + fn: function () { + this.getCreateForm().getForm().findField('label').focus(); + }, + delay: 500 + } + } + }); + + this.createWindow.show(animateTarget); + }, + + + createSite: function () { + var data = this.getCreateForm().getValues(); + + if (data.user_username || data.user_password || data.user_email || data.user_first || data.user_last) + { + if (!(data.user_username && data.user_password && data.user_email && data.user_first && data.user_last)) + { + Ext.Msg.alert('Incomplete user', 'Please fill out all fields for a first user'); + return false; + } + + data.create_user = { + Username: data.user_username, + Password: data.user_password, + Email: data.user_email, + FirstName: data.user_first, + LastName: data.user_last + }; + + delete data.user_email; + delete data.user_password; + delete data.user_email; + delete data.user_first; + delete data.user_last; + } + + this.editingSite.set(data); + this.getSitesStore().add(this.editingSite); + this.createWindow.close(); + }, + + cancelCreateSite: function () { + this.createWindow.close(); + }, + + onSiteContextMenu: function (tree, record, item, index, ev) { ev.stopEvent(); var menu = this.getSiteMenu(); menu.siteRecord = record; menu.showAt(ev.getXY()); - } + }, - ,onCreateClick: function(btn) { - var siteRecord = Ext.create('eMan.model.Site'); - this.showCreateForm(siteRecord, btn.el) - } + onCreateClick: function (btn) { + var siteRecord = Ext.create('eMan.model.Site'); + this.showCreateForm(siteRecord, btn.el); + }, - ,onCreateInheritingClick: function(menuItem) { + onCreateInheritingClick: function (menuItem) { var parentSite = menuItem.parentMenu.siteRecord; - var siteRecord = Ext.create('eMan.model.Site', { - parent_hostname: parentSite.get('primary_hostname') - ,parent_key: parentSite.get('inheritance_key') - }); + var siteRecord = Ext.create('eMan.model.Site', { + parent_hostname: parentSite.get('primary_hostname'), + parent_key: parentSite.get('inheritance_key') + }); - this.showCreateForm(siteRecord, menuItem.el); - } + this.showCreateForm(siteRecord, menuItem.el); + }, - ,onCreateDeveloperClick: function(menuItem) { + onCreateDeveloperClick: function (menuItem) { var developerWindow = this.getDeveloperWindow(), - developerForm = developerWindow.down('developerform'), - site = menuItem.parentMenu.siteRecord; + developerForm = developerWindow.down('developerform'), + site = menuItem.parentMenu.siteRecord; - developerForm.setSite(site); - developerWindow.setTitle(developerWindow.getInitialConfig('title') + ' for ' + site.get('handle')); - developerWindow.show(); - developerForm.getForm().findField('Email').focus(); - } + developerForm.setSite(site); + developerWindow.setTitle(developerWindow.getInitialConfig('title') + ' for ' + site.get('handle')); + developerWindow.show(); + developerForm.getForm().findField('Email').focus(); + }, - ,onDeveloperCancelClick: function() { - var developerWindow = this.getDeveloperWindow(); + onDeveloperCancelClick: function () { + var developerWindow = this.getDeveloperWindow(); - developerWindow.down('developerform').reset(); - developerWindow.close(); - } + developerWindow.down('developerform').reset(); + developerWindow.close(); + }, - ,onDeveloperSaveClick: function() { + onDeveloperSaveClick: function () { var developerWindow = this.getDeveloperWindow(), - developerForm = developerWindow.down('developerform'); - - developerWindow.setLoading('Creating developer…'); - Ext.Ajax.request({ - method: 'POST', - url: '/sites/'+developerForm.getSite().get('handle')+'/developers', - jsonData: developerForm.getValues(), - callback: function(operation, success, response) { - var responseData = success && Ext.decode(response.responseText), - errorMessage = 'Failed to create developer'; - - developerWindow.setLoading(false); - - if (!success || !responseData || !responseData.success || !responseData.data.ID) { - if (responseData.errors) { - errorMessage += ':'; - } - - Ext.Msg.alert('Developer not created', errorMessage); - } else { - Ext.Msg.alert('Developer created', 'Created user #'+responseData.data.ID); - developerForm.reset(); - developerWindow.close(); - } - } - }) - } -}); \ No newline at end of file + developerForm = developerWindow.down('developerform'); + + developerWindow.setLoading('Creating developer…'); + Ext.Ajax.request({ + method: 'POST', + url: '/sites/'+developerForm.getSite().get('handle')+'/developers', + jsonData: developerForm.getValues(), + callback: function (operation, success, response) { + var responseData = success && Ext.decode(response.responseText), + errorMessage = 'Failed to create developer'; + + developerWindow.setLoading(false); + + if (!success || !responseData || !responseData.success || !responseData.data.ID) { + if (responseData.errors) { + errorMessage += ':'; + } + + Ext.Msg.alert('Developer not created', errorMessage); + } else { + Ext.Msg.alert('Developer created', 'Created user #'+responseData.data.ID); + developerForm.reset(); + developerWindow.close(); + } + } + }); + } +}); diff --git a/kernel-www/app/controller/Viewport.js b/kernel-www/app/controller/Viewport.js index cb6d3a1..6805d89 100644 --- a/kernel-www/app/controller/Viewport.js +++ b/kernel-www/app/controller/Viewport.js @@ -1,6 +1,6 @@ Ext.define('eMan.controller.Viewport', { - extend: 'Ext.app.Controller' + extend: 'Ext.app.Controller', - ,views: ['Viewport'] + views: ['Viewport'] -}); \ No newline at end of file +}); diff --git a/kernel-www/app/model/LogEntry.js b/kernel-www/app/model/LogEntry.js index ed66335..2296954 100644 --- a/kernel-www/app/model/LogEntry.js +++ b/kernel-www/app/model/LogEntry.js @@ -1,12 +1,11 @@ Ext.define('eMan.model.LogEntry', { - extend: 'Ext.data.Model' + extend: 'Ext.data.Model', - ,fields: [{ - name: 'timestamp' - ,type: 'date' - },{ - name: 'message' - ,type: 'string' - }] - -}); \ No newline at end of file + fields: [{ + name: 'timestamp', + type: 'date' + },{ + name: 'message', + type: 'string' + }] +}); diff --git a/kernel-www/app/model/Service.js b/kernel-www/app/model/Service.js index d88e7c0..2c58818 100644 --- a/kernel-www/app/model/Service.js +++ b/kernel-www/app/model/Service.js @@ -1,15 +1,14 @@ Ext.define('eMan.model.Service', { - extend: 'Ext.data.Model' + extend: 'Ext.data.Model', - ,fields: ['name','status'] - ,idProperty: 'name' - ,proxy: { - type: 'rest' - ,url: '/services' - ,reader: { - type: 'json' - ,root: 'services' - } - } - -}); \ No newline at end of file + fields: ['name','status'], + idProperty: 'name', + proxy: { + type: 'rest', + url: '/services', + reader: { + type: 'json', + root: 'services' + } + } +}); diff --git a/kernel-www/app/model/Site.js b/kernel-www/app/model/Site.js index 71dfad1..ee4cfef 100644 --- a/kernel-www/app/model/Site.js +++ b/kernel-www/app/model/Site.js @@ -1,27 +1,26 @@ Ext.define('eMan.model.Site', { - extend: 'Ext.data.Model' - - ,fields: [ - {name: 'id', persist: false} - ,{name: 'handle', type: 'string'} - ,{name: 'primary_hostname', type: 'string'} - ,{name: 'hostnames'} - ,{name: 'label', type: 'string', useNull: true} - ,{name: 'parent_hostname', type: 'string', useNull: true} - ,{name: 'parent_key', type: 'string', useNull: true} - ,{name: 'inheritance_key', type: 'string'} - ,{name: 'create_user', useNull: true} - ] - ,proxy: { - type: 'rest' - ,url: '/sites' - ,reader: { - type: 'json' - ,root: 'data' - } - ,writer: { - type: 'json' - } - } + extend: 'Ext.data.Model', + fields: [ + {name: 'id', persist: false}, + {name: 'handle', type: 'string'}, + {name: 'primary_hostname', type: 'string'}, + {name: 'hostnames'}, + {name: 'label', type: 'string', useNull: true}, + {name: 'parent_hostname', type: 'string', useNull: true}, + {name: 'parent_key', type: 'string', useNull: true}, + {name: 'inheritance_key', type: 'string'}, + {name: 'create_user', useNull: true} + ], + proxy: { + type: 'rest', + url: '/sites', + reader: { + type: 'json', + root: 'data' + }, + writer: { + type: 'json' + } + } }); diff --git a/kernel-www/app/model/Skeleton.js b/kernel-www/app/model/Skeleton.js index d2a7777..5023d85 100644 --- a/kernel-www/app/model/Skeleton.js +++ b/kernel-www/app/model/Skeleton.js @@ -1,8 +1,8 @@ Ext.define('eMan.model.Skeleton', { - extend: 'Ext.data.Model' + extend: 'Ext.data.Model', - ,fields: [ - {name: 'hostname', type: 'string'} - ,{name: 'key', type: 'string'} - ] + fields: [ + {name: 'hostname', type: 'string'}, + {name: 'key', type: 'string'} + ] }); diff --git a/kernel-www/app/store/Log.js b/kernel-www/app/store/Log.js index 4cdca0a..a0f7a95 100644 --- a/kernel-www/app/store/Log.js +++ b/kernel-www/app/store/Log.js @@ -1,6 +1,5 @@ Ext.define('eMan.store.Log', { - extend: 'Ext.data.Store' + extend: 'Ext.data.Store', - ,model: 'eMan.model.LogEntry' - -}); \ No newline at end of file + model: 'eMan.model.LogEntry' +}); diff --git a/kernel-www/app/store/Services.js b/kernel-www/app/store/Services.js index 568ce06..e94580c 100644 --- a/kernel-www/app/store/Services.js +++ b/kernel-www/app/store/Services.js @@ -1,7 +1,6 @@ Ext.define('eMan.store.Services', { - extend: 'Ext.data.Store' + extend: 'Ext.data.Store', - ,model: 'eMan.model.Service' - ,autoLoad: true - -}); \ No newline at end of file + model: 'eMan.model.Service', + autoLoad: true +}); diff --git a/kernel-www/app/store/Sites.js b/kernel-www/app/store/Sites.js index 2b6ccb5..02f7264 100644 --- a/kernel-www/app/store/Sites.js +++ b/kernel-www/app/store/Sites.js @@ -1,7 +1,7 @@ Ext.define('eMan.store.Sites', { - extend: 'Ext.data.Store' + extend: 'Ext.data.Store', - ,model: 'eMan.model.Site' - ,autoSync: true - ,autoLoad: true + model: 'eMan.model.Site', + autoSync: true, + autoLoad: true }); diff --git a/kernel-www/app/store/Skeletons.js b/kernel-www/app/store/Skeletons.js index 93171a8..c107571 100644 --- a/kernel-www/app/store/Skeletons.js +++ b/kernel-www/app/store/Skeletons.js @@ -1,14 +1,14 @@ Ext.define('eMan.store.Skeletons', { - extend: 'Ext.data.Store' - ,requires: [ - 'eMan.model.Skeleton' - ,'Ext.data.proxy.LocalStorage' - ] + extend: 'Ext.data.Store', + requires: [ + 'eMan.model.Skeleton', + 'Ext.data.proxy.LocalStorage' + ], - ,model: 'eMan.model.Skeleton' + model: 'eMan.model.Skeleton', - ,proxy: { - type: 'localstorage' - ,id: 'emergence-skeletons' - } + proxy: { + type: 'localstorage', + id: 'emergence-skeletons' + } }); diff --git a/kernel-www/app/view/Viewport.js b/kernel-www/app/view/Viewport.js index af56963..880baa3 100644 --- a/kernel-www/app/view/Viewport.js +++ b/kernel-www/app/view/Viewport.js @@ -1,34 +1,31 @@ Ext.define('eMan.view.Viewport', { - extend: 'Ext.container.Viewport' + extend: 'Ext.container.Viewport', - ,layout: 'border' - - ,initComponent: function() { - - this.tbar = ['Create a new site']; - - this.items = [{ - region: 'north' - ,layout: { - type: 'hbox' - ,align: 'stretch' - } - ,height: 200 - ,items: [{ - xtype: 'servicesgrid' - ,width: 300 - },{ - xtype: 'loggrid' - ,flex: 1 - }] - },{ - region: 'center' - ,xtype: 'sitegrid' - }]; - - this.callParent(arguments); - } - + layout: 'border', + initComponent: function () { + this.tbar = ['Create a new site']; + + this.items = [{ + region: 'north', + layout: { + type: 'hbox', + align: 'stretch' + }, + height: 200, + items: [{ + xtype: 'servicesgrid', + width: 300 + },{ + xtype: 'loggrid', + flex: 1 + }] + },{ + region: 'center', + xtype: 'sitegrid' + }]; + + this.callParent(arguments); + } }); diff --git a/kernel-www/app/view/log/Grid.js b/kernel-www/app/view/log/Grid.js index 2561bcd..f27aa90 100644 --- a/kernel-www/app/view/log/Grid.js +++ b/kernel-www/app/view/log/Grid.js @@ -1,29 +1,27 @@ Ext.define('eMan.view.log.Grid', { - extend: 'Ext.grid.Panel' - ,alias: 'widget.loggrid' + extend: 'Ext.grid.Panel', + alias: 'widget.loggrid', - ,title: 'System Log' - ,store: 'Log' - ,viewConfig: { - emptyText: 'No activity' - } - - ,initComponent: function() { - - this.columns = [{ - xtype: 'datecolumn' - ,text: 'Timestamp' - ,dataIndex: 'timestamp' - ,format: 'Y-m-d h:i:s' - ,width: 120 - },{ - text: 'Message' - ,dataIndex: 'message' - ,flex: 1 - }]; + title: 'System Log', + store: 'Log', + viewConfig: { + emptyText: 'No activity' + }, - this.callParent(arguments); - } - + initComponent: function () { -}); \ No newline at end of file + this.columns = [{ + xtype: 'datecolumn', + text: 'Timestamp', + dataIndex: 'timestamp', + format: 'Y-m-d h:i:s', + width: 120 + },{ + text: 'Message', + dataIndex: 'message', + flex: 1 + }]; + + this.callParent(arguments); + } +}); diff --git a/kernel-www/app/view/services/Grid.js b/kernel-www/app/view/services/Grid.js index 9fadfe2..16912f3 100644 --- a/kernel-www/app/view/services/Grid.js +++ b/kernel-www/app/view/services/Grid.js @@ -1,32 +1,30 @@ Ext.define('eMan.view.services.Grid', { - extend: 'Ext.grid.Panel' - ,alias: 'widget.servicesgrid' + extend: 'Ext.grid.Panel', + alias: 'widget.servicesgrid', - ,title: 'System Services' - ,store: 'Services' - ,viewConfig: { - emptyText: 'No sites loaded' - } - - ,initComponent: function() { - - this.tools = [{ - type: 'refresh' - ,tooltip: 'Refresh services status' - }]; - - this.columns = [{ - text: 'Name' - ,dataIndex: 'name' - ,flex: 1 - },{ - text: 'Status' - ,dataIndex: 'status' - ,width: 100 - }]; + title: 'System Services', + store: 'Services', + viewConfig: { + emptyText: 'No sites loaded' + }, - this.callParent(arguments); - } - + initComponent: function () { -}); \ No newline at end of file + this.tools = [{ + type: 'refresh', + tooltip: 'Refresh services status' + }]; + + this.columns = [{ + text: 'Name', + dataIndex: 'name', + flex: 1 + },{ + text: 'Status', + dataIndex: 'status', + width: 100 + }]; + + this.callParent(arguments); + } +}); diff --git a/kernel-www/app/view/site/CreateForm.js b/kernel-www/app/view/site/CreateForm.js index da181e1..dae5fb5 100644 --- a/kernel-www/app/view/site/CreateForm.js +++ b/kernel-www/app/view/site/CreateForm.js @@ -1,87 +1,87 @@ Ext.define('eMan.view.site.CreateForm', { - extend: 'Ext.form.Panel' - ,alias: 'widget.sitecreate' + extend: 'Ext.form.Panel', + alias: 'widget.sitecreate', - ,bodyPadding: 15 - ,autoScroll: true - ,border: false - ,defaultType: 'textfield' - ,fieldDefaults: { - anchor: '100%' - ,labelAlign: 'right' - ,labelWidth: 110 - } + bodyPadding: 15, + autoScroll: true, + border: false, + defaultType: 'textfield', + fieldDefaults: { + anchor: '100%', + labelAlign: 'right', + labelWidth: 110 + }, - ,initComponent: function() { + initComponent: function () { - this.buttons = [{ - xtype: 'button' - ,text: 'Cancel' - ,action: 'cancel' - },{ - xtype: 'button' - ,text: 'Save Site »' - ,formBind: true - //,disabled: true - ,action: 'save' - }]; + this.buttons = [{ + xtype: 'button', + text: 'Cancel', + action: 'cancel' + },{ + xtype: 'button', + text: 'Save Site »', + formBind: true, + //,disabled: true + action: 'save' + }]; - this.items = [{ - fieldLabel: 'Site Label' - ,name: 'label' - ,allowBlank: false - ,listeners: { - scope: this - ,blur: function(labelfield) { + this.items = [{ + fieldLabel: 'Site Label', + name: 'label', + allowBlank: false, + listeners: { + scope: this, + blur: function (labelfield) { var handleField = this.getForm().findField('handle'); - if(!handleField.getValue() && labelfield.getValue()) + if (!handleField.getValue() && labelfield.getValue()) { handleField.setValue(labelfield.getValue().toLowerCase().replace(/\s+/g,'-').replace(/[^a-z0-9\-]/g,'')); } } } },{ - fieldLabel: 'Handle' - ,name: 'handle' - ,allowBlank: false - ,maxLength: 16 + fieldLabel: 'Handle', + name: 'handle', + allowBlank: false, + maxLength: 16 },{ - fieldLabel: 'Primary Hostname' - ,name: 'primary_hostname' - ,allowBlank: false - ,listeners: { - scope: this - ,focus: function(priField) { - var handleField = this.getForm().findField('handle') - ,defaultSuffix = eMan.app.serverConfig.defaultSuffix;; + fieldLabel: 'Primary Hostname', + name: 'primary_hostname', + allowBlank: false, + listeners: { + scope: this, + focus: function (priField) { + var handleField = this.getForm().findField('handle'), + defaultSuffix = eMan.app.serverConfig.defaultSuffix;; - if(!priField.getValue() && handleField.getValue() && defaultSuffix) + if (!priField.getValue() && handleField.getValue() && defaultSuffix) { priField.setValue(handleField.getValue() + '.' + defaultSuffix); } - } - ,blur: function(priField) { + }, + blur: function (priField) { var secField = this.getForm().findField('hostnames'); - if(!secField.getValue() && priField.getValue()) + if (!secField.getValue() && priField.getValue()) { - if(priField.getValue().substr(0,4) == 'www.') + if (priField.getValue().substr(0,4) == 'www.') priField.setValue(priField.getValue().substr(4)); - if(priField.getValue().split('.').length == 2) + if (priField.getValue().split('.').length == 2) secField.setValue('www.'+priField.getValue()); } } } },{ - fieldLabel: 'Alt. Hostnames' - ,name: 'hostnames' - ,listeners: { - scope: this - ,focus: function(secField) { - var handleField = this.getForm().findField('handle') - ,defaultSuffix = eMan.app.serverConfig.defaultSuffix - ,defaultHostname = defaultSuffix && (handleField.getValue() + '.' + defaultSuffix) - ,altHostnames = Ext.Array.clean(secField.getValue().split(/\s*,\s*/)); + fieldLabel: 'Alt. Hostnames', + name: 'hostnames', + listeners: { + scope: this, + focus: function (secField) { + var handleField = this.getForm().findField('handle'), + defaultSuffix = eMan.app.serverConfig.defaultSuffix, + defaultHostname = defaultSuffix && (handleField.getValue() + '.' + defaultSuffix), + altHostnames = Ext.Array.clean(secField.getValue().split(/\s*,\s*/)); if (defaultHostname && !secField.defaultAdded && !Ext.Array.contains(altHostnames, defaultHostname)) { altHostnames.push(defaultHostname); @@ -91,25 +91,25 @@ Ext.define('eMan.view.site.CreateForm', { } } },{ - fieldLabel: 'Parent Site' - ,xtype: 'combo' - ,name: 'parent_hostname' - ,autoSelect: false - ,emptyText: 'Select or enter hostname' - ,displayField: 'hostname' - ,valueField: 'hostname' - ,store: 'Skeletons' - ,queryMode: 'local' - ,listeners: { - scope: this - ,select: function(hostField) { + fieldLabel: 'Parent Site', + xtype: 'combo', + name: 'parent_hostname', + autoSelect: false, + emptyText: 'Select or enter hostname', + displayField: 'hostname', + valueField: 'hostname', + store: 'Skeletons', + queryMode: 'local', + listeners: { + scope: this, + select: function (hostField) { var keyField = this.getForm().findField('parent_key'); - if(hostField.getValue()) + if (hostField.getValue()) { var hostRecord = hostField.findRecordByValue(hostField.getValue()); - if(hostRecord && hostRecord.get('key')) + if (hostRecord && hostRecord.get('key')) keyField.setValue(hostRecord.get('key')); else keyField.focus(); @@ -121,46 +121,46 @@ Ext.define('eMan.view.site.CreateForm', { } } },{ - fieldLabel: 'Parent Access Key' - ,name: 'parent_key' + fieldLabel: 'Parent Access Key', + name: 'parent_key' },{ - xtype: 'fieldset' - ,title: 'First User' - ,defaultType: 'textfield' - ,fieldDefaults: { + xtype: 'fieldset', + title: 'First User', + defaultType: 'textfield', + fieldDefaults: { anchor: '100%' - } - ,items: [{ - fieldLabel: 'Email' - ,name: 'user_email' - ,listeners: { - scope: this - ,blur: function(emailField) { - var userField = this.getForm().findField('user_username') - ,email = emailField.getValue(); + }, + items: [{ + fieldLabel: 'Email', + name: 'user_email', + listeners: { + scope: this, + blur: function (emailField) { + var userField = this.getForm().findField('user_username'), + email = emailField.getValue(); - if(!userField.getValue() && email) + if (!userField.getValue() && email) { userField.setValue(email.substr(0, email.indexOf('@'))); } } } },{ - fieldLabel: 'Username' - ,name: 'user_username' + fieldLabel: 'Username', + name: 'user_username' },{ - fieldLabel: 'Password' - ,inputType: 'password' - ,name: 'user_password' + fieldLabel: 'Password', + inputType: 'password', + name: 'user_password' },{ - fieldLabel: 'First name' - ,name: 'user_first' + fieldLabel: 'First name', + name: 'user_first' },{ - fieldLabel: 'Last name' - ,name: 'user_last' + fieldLabel: 'Last name', + name: 'user_last' }] }]; - this.callParent(arguments); - } + this.callParent(arguments); + } }); diff --git a/kernel-www/app/view/site/DeveloperForm.js b/kernel-www/app/view/site/DeveloperForm.js index bc7e8af..dba70cd 100644 --- a/kernel-www/app/view/site/DeveloperForm.js +++ b/kernel-www/app/view/site/DeveloperForm.js @@ -32,7 +32,7 @@ Ext.define('eMan.view.site.DeveloperForm', { fieldLabel: 'Email', name: 'Email', listeners: { - blur: function(emailField) { + blur: function (emailField) { var userField = this.next('field[name=Username]'), email = emailField.getValue(); @@ -55,4 +55,4 @@ Ext.define('eMan.view.site.DeveloperForm', { fieldLabel: 'Last name', name: 'LastName' }] -}); \ No newline at end of file +}); diff --git a/kernel-www/app/view/site/Grid.js b/kernel-www/app/view/site/Grid.js index 4323128..a59b15f 100644 --- a/kernel-www/app/view/site/Grid.js +++ b/kernel-www/app/view/site/Grid.js @@ -1,79 +1,74 @@ Ext.define('eMan.view.site.Grid', { - extend: 'Ext.grid.Panel' - ,alias: 'widget.sitegrid' + extend: 'Ext.grid.Panel', + alias: 'widget.sitegrid', - ,title: 'Sites' - ,store: 'Sites' - ,viewConfig: { - emptyText: 'No sites loaded' - } - - ,initComponent: function() { - - this.dockedItems = [{ - xtype: 'toolbar' - ,dock: 'top' - ,items: [{ - xtype: 'button' - ,action: 'create' - ,text: 'Create Site' - ,scope: this - ,handler: this.onCreateSitePress - }] - }]; - - this.columns = [{ - text: 'Label' - ,dataIndex: 'label' - ,width: 200 - ,renderer: function(v, metaData) { - if(v) - return v; - - metaData.tdCls = 'x-cell-empty'; - return 'Unlabeled Site'; - } - },{ - text: 'Handle' - ,dataIndex: 'handle' - ,width: 150 - },{ - text: 'Primary Hostname' - ,dataIndex: 'primary_hostname' - ,width: 150 - ,renderer: function(v, metaData) { - if(v) - return ''+v+''; - } - },{ - text: 'Hostnames' - ,dataIndex: 'hostnames' - ,flex: 1 - ,renderer: function(v) { - return typeof v == 'string' ? v : v.join(', '); - } - },{ - text: 'Parent Hostname' - ,dataIndex: 'parent_hostname' - ,width: 150 - ,renderer: function(v, metaData) { - if(v) - return v; - - metaData.tdCls = 'x-cell-empty'; - return 'None'; - } - },{ - text: 'Inheritance Key' - ,dataIndex: 'inheritance_key' - ,width: 150 - }]; + title: 'Sites', + store: 'Sites', + viewConfig: { + emptyText: 'No sites loaded' + }, - this.callParent(arguments); - } - - - + initComponent: function () { + this.dockedItems = [{ + xtype: 'toolbar', + dock: 'top', + items: [{ + xtype: 'button', + action: 'create', + text: 'Create Site', + scope: this, + handler: this.onCreateSitePress + }] + }]; -}); \ No newline at end of file + this.columns = [{ + text: 'Label', + dataIndex: 'label', + width: 200, + renderer: function (v, metaData) { + if (v) + return v; + + metaData.tdCls = 'x-cell-empty'; + return 'Unlabeled Site'; + } + },{ + text: 'Handle', + dataIndex: 'handle', + width: 150 + },{ + text: 'Primary Hostname', + dataIndex: 'primary_hostname', + width: 150, + renderer: function (v) { + if (v) + return ''+v+''; + } + },{ + text: 'Hostnames', + dataIndex: 'hostnames', + flex: 1, + renderer: function (v) { + return typeof v == 'string' ? v : v.join(', '); + } + },{ + text: 'Parent Hostname', + dataIndex: 'parent_hostname', + width: 150, + renderer: function (v, metaData) { + if (v) + return v; + + metaData.tdCls = 'x-cell-empty'; + return 'None'; + } + },{ + text: 'Inheritance Key', + dataIndex: 'inheritance_key', + width: 150 + }]; + + this.callParent(arguments); + } +}); diff --git a/kernel-www/app/view/site/Menu.js b/kernel-www/app/view/site/Menu.js index 8f80c14..d197ec5 100644 --- a/kernel-www/app/view/site/Menu.js +++ b/kernel-www/app/view/site/Menu.js @@ -1,13 +1,13 @@ Ext.define('eMan.view.site.Menu', { - extend: 'Ext.menu.Menu' - ,alias: 'widget.sitemenu' + extend: 'Ext.menu.Menu', + alias: 'widget.sitemenu', - ,items: [{ - text: 'Create inheriting site' - ,action: 'create-inheriting' + items: [{ + text: 'Create inheriting site', + action: 'create-inheriting' //,icon: '/img/icons/fugue/blue-document.png' },{ - text: 'Create developer user' - ,action: 'create-developer' + text: 'Create developer user', + action: 'create-developer' }] }); diff --git a/package.json b/package.json index 2b06aea..9685bb2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "emergence", "preferGlobal": true, - "version": "1.0.2", + "version": "1.0.3", "license": "MIT", "dependencies": { "hostile": "^1.0.2", diff --git a/php-bootstrap/bootstrap.inc.php b/php-bootstrap/bootstrap.inc.php index e174a44..aba6a82 100644 --- a/php-bootstrap/bootstrap.inc.php +++ b/php-bootstrap/bootstrap.inc.php @@ -3,14 +3,14 @@ define('EMERGENCE_BOOTSTRAP_DIR', dirname(__FILE__)); // load core libraries -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/CacheIterator.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/Cache.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/Emergence.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/Emergence_FS.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/Debug.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/DB.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/File.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/Site.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/SiteCollection.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/SiteFile.class.php'); -require(EMERGENCE_BOOTSTRAP_DIR . '/lib/HttpProxy.class.php'); \ No newline at end of file +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/CacheIterator.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/Cache.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/Emergence.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/Emergence_FS.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/Debug.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/DB.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/File.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/Site.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/SiteCollection.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/SiteFile.class.php'); +require(EMERGENCE_BOOTSTRAP_DIR.'/lib/HttpProxy.class.php'); \ No newline at end of file diff --git a/php-bootstrap/lib/Cache.class.php b/php-bootstrap/lib/Cache.class.php index cfdc7c6..f839ab7 100644 --- a/php-bootstrap/lib/Cache.class.php +++ b/php-bootstrap/lib/Cache.class.php @@ -47,7 +47,7 @@ public static function fetch($key) return static::rawFetch(static::localizeKey($key)); } - public static function store($key, $value, $ttl = 0) + public static function store($key, $value, $ttl = 0) { return static::rawStore(static::localizeKey($key), $value, $ttl); } diff --git a/php-bootstrap/lib/CacheIterator.class.php b/php-bootstrap/lib/CacheIterator.class.php index 112c29d..795afbf 100644 --- a/php-bootstrap/lib/CacheIterator.class.php +++ b/php-bootstrap/lib/CacheIterator.class.php @@ -1,6 +1,6 @@ [^\']+)\' for key \'(?[^\']+)\'/', $message, $matches)) { $this->duplicateKey = $matches['key']; $this->duplicateValue = $matches['value']; diff --git a/php-bootstrap/lib/Emergence.class.php b/php-bootstrap/lib/Emergence.class.php index 55ac296..1f305fa 100644 --- a/php-bootstrap/lib/Emergence.class.php +++ b/php-bootstrap/lib/Emergence.class.php @@ -84,7 +84,7 @@ public static function handleTreeRequest($rootNode = null) // set minimum id if (!empty($_REQUEST['minId'])) { - $fileConditions[] = 'ID > ' . intval($_REQUEST['minId']); + $fileConditions[] = 'ID > '.intval($_REQUEST['minId']); } // get files @@ -104,8 +104,8 @@ public static function buildUrl($path = array(), $params = array()) $params['accessKey'] = Site::getConfig('parent_key'); $url = 'http://'.Site::getConfig('parent_hostname').'/emergence'; - $url .= '/' . implode('/', $path); - $url .= '?' . http_build_query($params); + $url .= '/'.implode('/', $path); + $url .= '?'.http_build_query($params); return $url; } diff --git a/php-bootstrap/lib/Emergence_FS.class.php b/php-bootstrap/lib/Emergence_FS.class.php index 752275d..194d641 100644 --- a/php-bootstrap/lib/Emergence_FS.class.php +++ b/php-bootstrap/lib/Emergence_FS.class.php @@ -10,7 +10,7 @@ public static function cacheTree($path, $force = false) } // check if this tree has already been cached - $cacheKey = 'cacheTree:' . implode('/', $path); + $cacheKey = 'cacheTree:'.implode('/', $path); if (!Site::$autoPull || (!$force && Cache::fetch($cacheKey))) { return 0; } @@ -51,7 +51,7 @@ public static function getTree($path = null, $localOnly = false, $includeDeleted if ($path) { $collections = static::getCollectionLayers($path, $localOnly); - if(empty($collections['local']) && empty($collections['remote'])) { + if (empty($collections['local']) && empty($collections['remote'])) { return array(); } @@ -79,7 +79,7 @@ public static function getTree($path = null, $localOnly = false, $includeDeleted } // append to tree conditions - $conditions[] = '(' . join(') OR (', $positionConditions) . ')'; + $conditions[] = '('.join(') OR (', $positionConditions).')'; } elseif ($localOnly) { $conditions['Site'] = 'Local'; } @@ -115,7 +115,7 @@ public static function getTree($path = null, $localOnly = false, $includeDeleted // map conditions $mappedConditions = array(); - foreach($conditions AS $key => $value) { + foreach ($conditions AS $key => $value) { if (is_string($key)) { $mappedConditions[] = sprintf('`%s` = "%s"', $key, DB::escape($value)); } else { @@ -139,12 +139,13 @@ public static function getTree($path = null, $localOnly = false, $includeDeleted return $tree; } - public static function getTreeFiles($path = null, $localOnly = false, $fileConditions = array(), $collectionConditions = array()) { + public static function getTreeFiles($path = null, $localOnly = false, $fileConditions = array(), $collectionConditions = array()) + { return static::getTreeFilesFromTree(static::getTree($path, $localOnly, false, $collectionConditions), $fileConditions); } - public static function getTreeFilesFromTree($tree, $conditions = array()) { - + public static function getTreeFilesFromTree($tree, $conditions = array()) + { $conditions['Status'] = 'Normal'; // map conditions @@ -163,7 +164,7 @@ public static function getTreeFilesFromTree($tree, $conditions = array()) { $remoteCollections = array(); foreach ($tree AS &$collectionInfo) { - if($collectionInfo['Site'] == 'Local') { + if ($collectionInfo['Site'] == 'Local') { $localCollections[] = $collectionInfo['ID']; } else { $remoteCollections[] = $collectionInfo['ID']; @@ -305,9 +306,8 @@ public static function exportTree($sourcePath, $destinationPath, $options = arra $tree = static::getTree($sourcePath, $options['localOnly']); foreach ($tree AS $collectionID => &$node) { - if ($node['ParentID'] && !empty($tree[$node['ParentID']])) { - $node['_path'] = $tree[$node['ParentID']]['_path'] . '/' . $node['Handle']; + $node['_path'] = $tree[$node['ParentID']]['_path'].'/'.$node['Handle']; } else { $node['_path'] = $destinationPath; } @@ -365,7 +365,7 @@ public static function exportTree($sourcePath, $destinationPath, $options = arra } if ($fileRow['Status'] == 'Normal' && $tree[$fileRow['CollectionID']]['Status'] != 'Deleted' && ($tree[$fileRow['CollectionID']]['Site'] == 'Local' || !in_array($dst, $filesWritten))) { - copy(Site::$rootPath . '/' . SiteFile::$dataPath . '/' . $fileRow['ID'], $dst); + copy(Site::$rootPath.'/'.SiteFile::$dataPath.'/'.$fileRow['ID'], $dst); touch($dst, strtotime($fileRow['Timestamp'])); $filesWritten[] = $dst; } @@ -398,7 +398,7 @@ public static function importFile($sourcePath, $destinationPath) $sha1 = sha1_file($sourcePath); // skip if existing local or remote file matches hash - if(!$existingNode || $existingNode->SHA1 != $sha1) { + if (!$existingNode || $existingNode->SHA1 != $sha1) { // use lower level create methods to supply already-calculated hash $fileRecord = SiteFile::createFromPath($destinationPath, null, $existingNode ? $existingNode->ID : null); return SiteFile::saveRecordData($fileRecord, fopen($sourcePath, 'r'), $sha1); @@ -464,7 +464,7 @@ public static function importTree($sourcePath, $destinationPath, $options = arra } if ($collectionInfo['ParentID'] && isset($destinationCollectionsTree[$collectionInfo['ParentID']])) { - $collectionInfo['_path'] = $destinationCollectionsTree[$collectionInfo['ParentID']]['_path'] . '/' . $collectionInfo['Handle']; + $collectionInfo['_path'] = $destinationCollectionsTree[$collectionInfo['ParentID']]['_path'].'/'.$collectionInfo['Handle']; $localDestinationCollectionsMap[$collectionInfo['_path']] = &$collectionInfo; } elseif (!$collectionInfo['ParentID']) { $collectionInfo['_path'] = $collectionInfo['Handle']; @@ -490,7 +490,7 @@ public static function importTree($sourcePath, $destinationPath, $options = arra // iterate through all source files foreach ($iterator AS $tmpPath => $node) { $relPath = substr($tmpPath, $prefixLen); - $path = $destinationPath ? $destinationPath . $relPath : ltrim($relPath, '/'); + $path = $destinationPath ? $destinationPath.$relPath : ltrim($relPath, '/'); if ($options['debug']) { Debug::dump(array('tmpPath' => $tmpPath, 'destPath' => $path), false, 'iterating node'); @@ -636,7 +636,7 @@ public static function getCollectionLayers($path, $localOnly = false) } while ($handle = array_shift($path)) { - if ($localCollection){ + if ($localCollection) { $localCollection = SiteCollection::getByHandle($handle, $localCollection->ID, false); } @@ -662,7 +662,7 @@ public static function findFiles($filename, $useRegexp = false, $scope = null, $ foreach (static::getCollectionLayers($scopeItem, $localOnly) AS $collection) { $collections[] = $collection; } - } elseif(is_a($scopeItem, 'SiteCollection')) { + } elseif (is_a($scopeItem, 'SiteCollection')) { $collections[] = $scopeItem; } } diff --git a/php-bootstrap/lib/Emergence_Stream_Wrapper.class.php b/php-bootstrap/lib/Emergence_Stream_Wrapper.class.php index 3b922f6..9699a66 100644 --- a/php-bootstrap/lib/Emergence_Stream_Wrapper.class.php +++ b/php-bootstrap/lib/Emergence_Stream_Wrapper.class.php @@ -46,7 +46,7 @@ public static function getByEmergenceVFS($path) return $templateNode; } - public function stream_open( $path , $mode , $options , &$opened_path ) + public function stream_open($path , $mode , $options , &$opened_path) { $this->position = 0; $this->fp = false; diff --git a/php-bootstrap/lib/HttpProxy.class.php b/php-bootstrap/lib/HttpProxy.class.php index 81baa4e..65e6a45 100644 --- a/php-bootstrap/lib/HttpProxy.class.php +++ b/php-bootstrap/lib/HttpProxy.class.php @@ -58,7 +58,7 @@ public static function relayRequest($options) // build URL $baseUrl = $options['url']; if (!empty(Site::$pathStack) && (!isset($options['autoAppend']) || $options['autoAppend'] != false)) { - $options['url'] .= '/' . implode('/', Site::$pathStack); + $options['url'] .= '/'.implode('/', Site::$pathStack); } // get cookies @@ -68,15 +68,15 @@ public static function relayRequest($options) // add query string if (!empty($_SERVER['QUERY_STRING']) && (!isset($options['autoQuery']) || $options['autoQuery'] != false)) { - $options['url'] .= '?' . $_SERVER['QUERY_STRING']; + $options['url'] .= '?'.$_SERVER['QUERY_STRING']; } // build headers foreach ($options['forwardHeaders'] AS $header) { - $headerKey = 'HTTP_' . str_replace('-', '_', strtoupper($header)); + $headerKey = 'HTTP_'.str_replace('-', '_', strtoupper($header)); if (!empty($_SERVER[$headerKey])) { - $options['headers'][] = $header . ': ' . $_SERVER[$headerKey]; + $options['headers'][] = $header.': '.$_SERVER[$headerKey]; } } @@ -113,7 +113,7 @@ public static function relayRequest($options) } else { $responseHeaders = array(); curl_setopt($ch, CURLOPT_HEADER, false); - curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $header) use($options, &$responseHeaders) { + curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $header) use ($options, &$responseHeaders) { $headerLength = strlen($header); @list($headerKey, $headerValue) = preg_split('/:\s*/', $header, 2); if ($headerKey && $headerValue) { @@ -133,7 +133,7 @@ public static function relayRequest($options) if (!empty($options['debug'])) { print("

Response Header: $header

"); - } elseif(empty($options['returnResponse'])) { + } elseif (empty($options['returnResponse'])) { header($header); } @@ -183,7 +183,7 @@ public static function relayRequest($options) if (!empty($options['debug'])) { print('

Response Info

');
             print_r(curl_getinfo($ch));
-                        print('
'); + print(''); print('

cURL error

'.var_export(curl_error($ch), true).'
'); print('

Response Length

'.strlen($responseBody)); print('

Response Body

');
diff --git a/php-bootstrap/lib/Site.class.php b/php-bootstrap/lib/Site.class.php
index a6c4b29..1f0ccc1 100644
--- a/php-bootstrap/lib/Site.class.php
+++ b/php-bootstrap/lib/Site.class.php
@@ -93,7 +93,7 @@ public static function initialize($rootPath, $hostname = null)
 
         // set useful transaction name and metadata for newrelic
         if (extension_loaded('newrelic')) {
-            newrelic_name_transaction(static::getConfig('handle') . '/' . implode('/', site::$requestPath));
+            newrelic_name_transaction(static::getConfig('handle').'/'.implode('/', site::$requestPath));
 
             if (isset($_SERVER['QUERY_STRING'])) {
                 newrelic_add_custom_parameter('request.query', $_SERVER['QUERY_STRING']);
@@ -167,7 +167,7 @@ public static function handleRequest()
         if (isset($_SERVER['HTTP_ORIGIN'])) {
             $hostname = strtolower(parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST));
             if ($hostname == strtolower(static::$hostname) || static::$permittedOrigins == '*' || in_array($hostname, static::$permittedOrigins)) {
-                header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
+                header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
                 header('Access-Control-Allow-Credentials: true');
                 //header('Access-Control-Max-Age: 86400')
             } else {
@@ -177,10 +177,10 @@ public static function handleRequest()
         }
 
         if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
-            header('Access-Control-Allow-Methods: ' . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']);
+            header('Access-Control-Allow-Methods: '.$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']);
 
             if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
-                header('Access-Control-Allow-Headers: ' . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
+                header('Access-Control-Allow-Headers: '.$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
             }
 
             exit();
@@ -317,7 +317,7 @@ public static function getRequestPathResult($path)
 
             // if path component doesn't already end in .php, check for a .php match first
             if (substr($handle, -4) != '.php') {
-                array_push($searchPath, $handle . '.php');
+                array_push($searchPath, $handle.'.php');
                 $foundNode = static::resolvePath($searchPath);
                 // printf("\t\t%s\t%s\n", $foundNode ? 'matched' : 'missed', implode('/', $searchPath));
                 array_pop($searchPath);
@@ -456,7 +456,7 @@ class_exists($className, false)
             if ($lastNsPos = strrpos($className, '\\')) {
                 $namespace = substr($className, 0, $lastNsPos);
                 $className = substr($className, $lastNsPos + 1);
-                $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
+                $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;
             } else {
                 $fileName = '';
             }
@@ -497,7 +497,7 @@ class_exists($className, false)
 
     public static function loadConfig($className)
     {
-        $cacheKey = 'class-config:' . $className;
+        $cacheKey = 'class-config:'.$className;
 
 
         if (!$configFileIds = Cache::fetch($cacheKey)) {
@@ -508,7 +508,7 @@ public static function loadConfig($className)
             if ($lastNsPos = strrpos($className, '\\')) {
                 $namespace = substr($className, 0, $lastNsPos);
                 $className = substr($className, $lastNsPos + 1);
-                $path  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
+                $path  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;
             } else {
                 $path = '';
             }
@@ -716,18 +716,18 @@ public static function redirect($path, $get = false, $hash = false)
         if (preg_match('/^https?:\/\//i', $path)) {
             $url = $path;
         } else {
-            $url = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . static::$hostname . '/' . ltrim($path, '/');
+            $url = ($_SERVER['HTTPS'] ? 'https' : 'http').'://'.static::$hostname.'/'.ltrim($path, '/');
         }
 
         if ($get) {
-            $url .= '?' . (is_array($get) ? http_build_query($get) : $get);
+            $url .= '?'.(is_array($get) ? http_build_query($get) : $get);
         }
 
         if ($hash) {
-            $url .= '#' . $hash;
+            $url .= '#'.$hash;
         }
 
-        header('Location: ' . $url);
+        header('Location: '.$url);
         exit();
     }
 
@@ -780,12 +780,12 @@ public static function getVersionedRootUrl($path)
 
         $fsPath = $path;
         array_unshift($fsPath, 'site-root');
-        $url = '/' . implode('/', $path);
+        $url = '/'.implode('/', $path);
 
         $Node = static::resolvePath($fsPath);
 
         if ($Node) {
-            return $url . '?_sha1=' . $Node->SHA1;
+            return $url.'?_sha1='.$Node->SHA1;
         } else {
             return $url;
         }
diff --git a/php-bootstrap/lib/SiteCollection.class.php b/php-bootstrap/lib/SiteCollection.class.php
index 157713a..7dfb4fe 100644
--- a/php-bootstrap/lib/SiteCollection.class.php
+++ b/php-bootstrap/lib/SiteCollection.class.php
@@ -25,10 +25,9 @@ public function __construct($handle, $record = null)
             if (static::$autoCreate) {
                 $this->_record = static::createRecord($handle);
             } else {
-                throw new Exception('Collection with name ' . $handle . ' could not be located');
+                throw new Exception('Collection with name '.$handle.' could not be located');
             }
         }
-
     }
 
     public function __get($name)
@@ -73,12 +72,12 @@ public static function getCacheKey($handle, $parentID = null, $remote = false)
             $cacheKey .= sprintf('/%s/', $remote ? 'remote' : 'local');
         }
 
-        return $cacheKey . $handle;
+        return $cacheKey.$handle;
     }
 
     public static function getByID($collectionID)
     {
-        $cacheKey = 'efs:col:' . $collectionID;
+        $cacheKey = 'efs:col:'.$collectionID;
 
         if (false === ($record = Cache::fetch($cacheKey))) {
             $record = DB::oneRecord(
diff --git a/php-bootstrap/lib/SiteFile.class.php b/php-bootstrap/lib/SiteFile.class.php
index ab14eac..65dac10 100644
--- a/php-bootstrap/lib/SiteFile.class.php
+++ b/php-bootstrap/lib/SiteFile.class.php
@@ -106,7 +106,7 @@ public static function getCacheKey($collectionID, $handle)
 
     public static function getByID($fileID)
     {
-        $cacheKey = 'efs:file:' . $fileID;
+        $cacheKey = 'efs:file:'.$fileID;
 
         if (false === ($record = Cache::fetch($cacheKey))) {
             $record = DB::oneRecord(
@@ -211,7 +211,7 @@ public function getFullPath($root = null, $prependParent = true)
 
     public static function getRealPathByID($ID)
     {
-        return Site::$rootPath . '/' . static::$dataPath . '/' . $ID;
+        return Site::$rootPath.'/'.static::$dataPath.'/'.$ID;
     }
 
     public function getName()
@@ -273,7 +273,7 @@ public static function create($collectionID, $handle, $data = null, $ancestorID
         return $record;
     }
 
-    function put($data, $ancestorID = null)
+    public function put($data, $ancestorID = null)
     {
         $record = null;
         $tempPath = tempnam(static::getRealPathByID(''), 'uploading');
@@ -512,7 +512,7 @@ public function outputAsResponse($includeAuthor = false)
         if (!empty($_GET['_sha1']) && $_GET['_sha1'] == $this->SHA1) {
             $expires = 60*60*24*365;
             header('Cache-Control: public, max-age='.$expires);
-            header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()+$expires));
+            header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time()+$expires));
             header('Pragma: public');
         }
 
@@ -530,7 +530,7 @@ public function outputAsResponse($includeAuthor = false)
         header('Last-Modified: '.gmdate('D, d M Y H:i:s \G\M\T', $this->Timestamp));
 
         if ($includeAuthor && $this->Author) {
-          header('Author: '.$this->Author->EmailRecipient);
+            header('Author: '.$this->Author->EmailRecipient);
         }
 
         readfile($this->RealPath);
diff --git a/php-bootstrap/mail.php b/php-bootstrap/mail.php
index 92cffbe..caa76f4 100644
--- a/php-bootstrap/mail.php
+++ b/php-bootstrap/mail.php
@@ -1,7 +1,7 @@