1 /*jshint node:true, indent:2, curly:false, eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
2 regexp:true, undef:true, strict:true, trailing:true, white:true */
3 /*global X:true, SYS:true, XT:true, _:true */
5 var async = require("async"),
6 path = require("path"),
7 routes = require("./routes");
13 // Get the most recent version of the core code
14 // XXX: we'll need to sometimes give older versions
15 // @param {String} language Can be "js" or "css".
17 var getCoreUuid = function (language, organization, callback) {
18 var coll = new SYS.ClientCodeRelationCollection();
20 username: X.options.databaseServer.user,
21 database: organization,
24 { attribute: "language", value: language },
25 { attribute: "extension", value: null, includeNull: true }
28 success: function (coll, res) {
29 var sortedModels = _.sortBy(coll.models, function (model) {
30 return -1 * getVersionSize(model.get("version"));
32 callback(null, sortedModels[0].get("uuid"));
38 Just get a sense of how recent a version is without the dots.
39 Higher version number string inputs will result in higher int outputs.
40 Works with three or four dot-separated numbers.
42 var getVersionSize = function (version) {
43 var versionSplit = version.split('.'), // e.g. "4.5.0-beta2".
44 versionSize = 1000000 * versionSplit[0] + // Get "4" from "4.5.0-beta2".
45 10000 * versionSplit[1] + // Get "5" from "4.5.0-beta2".
46 100 * versionSplit[2].match(/^[0-9]+/g, '')[0], // Get "0" from "0-beta2".
47 prerelease = versionSplit[2].replace(/^[0-9]+/g, ''), // Get "-beta2" from "0-beta2".
48 preRegEx = /([a-zA-Z]+)([0-9]*)/g, // Capture pre-release as ["beta2", "beta", "2"].
49 preMatch = preRegEx.exec(prerelease),
53 if (versionSplit.length > 3) {
54 versionSize += versionSplit[3];
57 if (preMatch && preMatch.length && preMatch[0] !== '') {
58 if (preMatch[1] !== '') {
59 preVersion = preMatch[1].match(/[a-zA-Z]+/g); // Get ["beta"] from ["beta2", "beta", "2"].
61 // Decrease versionSize for pre-releasees.
62 switch (preVersion[0].toLowerCase()) {
64 versionSize = versionSize - 50;
67 versionSize = versionSize - 40;
70 versionSize = versionSize - 20;
73 X.err("Cannot get pre-release version number.");
77 // Add pre-release version to versionSize.
78 if (preMatch[2] !== '') {
79 preNum = preMatch[2].match(/[0-9]+/g); // Get ["2"] from ["beta2", "beta", "2"].
80 versionSize = versionSize + parseInt(preNum);
89 Figures out what extensions the user is entitled to. Queries to determine
90 client code UUIDs for core and those extensions. Sends on to the app view
93 var serveApp = exports.serveApp = function (req, res) {
94 if (!req.session.passport.user) {
95 routes.logout(req, res);
99 var user = new SYS.User(),
100 fetchError = function (err) {
101 X.log("Extension fetch error", err);
102 res.send({isError: true, message: "Error fetching extensions"});
104 fetchSuccess = function (model, result) {
105 var sendExtensions = function (res, extensions) {
106 extensions.sort(function (ext1, ext2) {
107 if (ext1.loadOrder !== ext2.loadOrder) {
108 return ext1.loadOrder - ext2.loadOrder;
110 return ext1.name > ext2.name ? 1 : -1;
113 var getLatestUuid = function (extensions, language) {
114 var uuids = _.map(extensions, function (ext) {
115 var jsModels = _.filter(ext.codeInfo, function (codeInfo) {
116 return codeInfo.language === language;
118 var sortedModels = _.sortBy(jsModels, function (codeInfo) {
119 return -1 * getVersionSize(codeInfo.version);
121 if (sortedModels[0]) {
122 return sortedModels[0].uuid;
124 X.log("Could not find js uuid for extension " + ext.description);
128 return _.compact(uuids); // eliminate any null values
130 var extJsUuids = getLatestUuid(extensions, "js");
131 var extCssUuids = getLatestUuid(extensions, "css");
132 var extensionPaths = _.compact(_.map(extensions, function (ext) {
133 var locationName = ext.location.indexOf("/") === 0 ?
134 path.join(ext.location, "source") :
136 return path.join(locationName, ext.name);
138 getCoreUuid('js', req.session.passport.user.organization, function (err, jsUuid) {
140 res.send({isError: true, error: err});
143 getCoreUuid('css', req.session.passport.user.organization, function (err, cssUuid) {
145 res.send({isError: true, error: err});
148 res.render(req.viewName || 'app', {
149 org: req.session.passport.user.organization,
152 extensionJsArray: extJsUuids,
153 extensionCssArray: extCssUuids,
154 extensionPaths: extensionPaths
159 var getExtensionFromRole = function (role, callback) {
160 var id = role.userAccountRole,
161 roleModel = new SYS.UserAccountRole();
163 roleModel.fetch({id: id,
164 username: X.options.databaseServer.user,
165 database: req.session.passport.user.organization,
166 success: function (model, result) {
167 var extensions = _.map(model.get("grantedExtensions"), function (ext) {
168 return ext.extension;
170 callback(null, extensions);
172 error: function (err) {
177 var extensions = _.map(user.get("grantedExtensions"), function (ext) {
178 return ext.extension;
180 // Add the extensions that the user gets from his roles
181 var userAccountRoles = user.get("grantedUserAccountRoles");
182 if (userAccountRoles.length > 0) {
183 // we're going to have to do more async calls to get all the
184 // extensions related to these roles.
185 async.map(userAccountRoles, getExtensionFromRole, function (err, results) {
187 res.send({isError: true, message: "error in extension route"});
190 // add all role-granted extensions that are not already there
191 _.each(results, function (result) {
192 _.each(result, function (newExt) {
193 var preExistingExt = _.find(extensions, function (currentExt) {
194 return currentExt.id === newExt.id;
196 if (!preExistingExt) {
197 extensions.push(newExt);
201 sendExtensions(res, extensions);
205 // no second async call necessary
206 sendExtensions(res, extensions);
211 id: req.session.passport.user.username,
212 success: fetchSuccess,
214 username: X.options.databaseServer.user,
215 database: req.session.passport.user.organization
219 exports.serveDebug = function (req, res) {
220 req.viewName = "debug";