From 7f709ec31b88d8ccb529bd23552bf789a2a43e54 Mon Sep 17 00:00:00 2001 From: Ciaran Duffy Date: Sat, 28 Jan 2017 12:19:57 +0000 Subject: [PATCH 001/296] adding skip navigation switch (#1492) --- plugins/content/config/model.schema | 9 +++++++++ plugins/content/course/model.schema | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/plugins/content/config/model.schema b/plugins/content/config/model.schema index fd89874df0..379cb91ce0 100644 --- a/plugins/content/config/model.schema +++ b/plugins/content/config/model.schema @@ -80,6 +80,15 @@ "validators": [], "title": "Enable text reader support?", "help": "If set to 'true' the course will add focusing to assist text reader software" + }, + "_isSkipNavigationEnabled": { + "type": "bool", + "default": "true", + "isSetting": false, + "inputType": {"type": "Boolean", "options": [true, false]}, + "validators": [], + "title": "Skip Navigation", + "help": "If set to 'true' a 'Skip Navigation' link will appear allowing users to jump to content" } } }, diff --git a/plugins/content/course/model.schema b/plugins/content/course/model.schema index 98491112c2..17822391fb 100644 --- a/plugins/content/course/model.schema +++ b/plugins/content/course/model.schema @@ -158,6 +158,17 @@ "required" ] }, + "skipNavigationText": { + "type": "string", + "title": "Skip navigation label", + "translatable": true, + "default": "Skip navigation", + "inputType": "Text", + "required": true, + "validators": [ + "required" + ] + }, "_accessibilityInstructions": { "type": "object", "title": "Accessibility instructions", @@ -205,6 +216,14 @@ "inputType": "Text", "required": true }, + "skipNavigation": { + "type": "string", + "translatable": true, + "title": "", + "default": "Skip navigation", + "inputType": "Text", + "required": true + }, "menuLoaded": { "type": "string", "title": "", From b0491ea461aa0001506efce611fa355e39a780b4 Mon Sep 17 00:00:00 2001 From: Himanshu Rajotia Date: Tue, 21 Feb 2017 21:34:40 +0530 Subject: [PATCH 002/296] added missing `app` context (#1399) --- install.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install.js b/install.js index ff8e1a05b6..21108518cf 100644 --- a/install.js +++ b/install.js @@ -295,9 +295,9 @@ var steps = [ masterTenant = tenant; console.log("Tenant " + tenant.name + " was created. Now saving configuration, please wait ..."); // save master tenant name to config - configuration.setConfig('masterTenantName', tenant.name); - configuration.setConfig('masterTenantID', tenant._id); - saveConfig(configuration.getConfig(), cb); + app.configuration.setConfig('masterTenantName', tenant.name); + app.configuration.setConfig('masterTenantID', tenant._id); + saveConfig(app.configuration.getConfig(), cb); } ); }; From 025b20d3c9d12217ecd2648aca0fbe011eeea646 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 24 Feb 2017 15:58:10 +0000 Subject: [PATCH 003/296] Add confirmation for super user password during install --- install.js | 9 +++++++++ plugins/auth/local/index.js | 8 ++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/install.js b/install.js index 21108518cf..c460600760 100644 --- a/install.js +++ b/install.js @@ -190,6 +190,13 @@ userConfig = [ description: "Password", hidden: true, required: true + }, + { + name: 'retypePassword', + type: 'string', + description: "Retype Password", + hidden: true, + required: true } ]; @@ -376,6 +383,7 @@ var steps = [ var userEmail = result.email; var userPassword = result.password; + var userRetypePassword = result.retypePassword; // ruthlessly remove any existing users (we're already nuclear if we've deleted the existing tenant) app.usermanager.deleteUser({ email: userEmail }, function (err, userRec) { if (err) { @@ -387,6 +395,7 @@ var steps = [ new localAuth().internalRegisterUser({ email: userEmail, password: userPassword, + retypePassword: userRetypePassword, _tenantId: masterTenant._id }, function (err, user) { if (err) { diff --git a/plugins/auth/local/index.js b/plugins/auth/local/index.js index 4a465ebb51..6a82505c31 100644 --- a/plugins/auth/local/index.js +++ b/plugins/auth/local/index.js @@ -195,8 +195,12 @@ LocalAuth.prototype.registerUser = function (req, res, next) { }; LocalAuth.prototype.internalRegisterUser = function (user, cb) { - if (!user.email || !user.password) { - return cb(new auth.errors.UserRegistrationError('email and password are required!')); + if (!user.email || !user.password || !user.retypePassword) { + return cb(new auth.errors.UserRegistrationError('email, password and retyped password are required!')); + } + + if (user.password !== user.retypePassword) { + return cb(new auth.errors.UserRegistrationError('password and retyped password must match!')) } // create user with hashed password From d0ac4cc73039c82915e34e8dba05f15dff9f3cf5 Mon Sep 17 00:00:00 2001 From: Tom Taylor Date: Mon, 27 Feb 2017 17:02:39 +0000 Subject: [PATCH 004/296] Refactor FFMPEG code --- plugins/filestorage/localfs/index.js | 103 +++++++++++++-------------- 1 file changed, 49 insertions(+), 54 deletions(-) diff --git a/plugins/filestorage/localfs/index.js b/plugins/filestorage/localfs/index.js index 1c5e822fbf..8454644dbc 100644 --- a/plugins/filestorage/localfs/index.js +++ b/plugins/filestorage/localfs/index.js @@ -352,70 +352,65 @@ LocalFileStorage.prototype.copyAsset = function(asset, sourceTenantName, destina */ LocalFileStorage.prototype.createThumbnail = function (filePath, fileType, options, next) { - var imgThumbPath; // early return if we can't create thumbnails if (!configuration.getConfig('useffmpeg')) { return next(null, false); } - - var self = this; var fileFormat = fileType.split('/')[1]; - var additionalOptions = []; fileType = fileType.split('/')[0]; - if ('image' === fileType) { - if ('gif' === fileFormat){ - // pixel format for gif required - additionalOptions.push('-pix_fmt rgb24'); - // number of frames - additionalOptions.push('-frames 1'); - } - imgThumbPath = path.join(path.dirname(filePath), path.basename(filePath) + '_thumb' + path.extname(filePath)); - return new FFMpeg({ source: filePath }) - .addOptions(additionalOptions) - .withSize(options.width + 'x' + options.height) - .keepPixelAspect(true) - .on('error', function (err) { - logger.log('error', 'Failed to create image thumbnail: ' + err.message); - return next(err, false); - }) - .on('end', function () { - return next(null, self.getRelativePath(imgThumbPath)); - }) - .saveToFile(imgThumbPath); - - } else if ('video' === fileType) { - - imgThumbPath = path.join(path.dirname(filePath), path.basename(filePath) + '_thumb.gif'); + // also check fileType is supported + if(!isThumbnailTypeSupported(fileType)) { + return next(null, false); + } + var self = this; + var thumbExt = ('image' === fileType) ? path.extname(filePath) : '.gif'; + var imgThumbPath = path.join(path.dirname(filePath), path.basename(filePath)) + '_thumb' + thumbExt; + + var ff = new FFMpeg({ source: filePath }).output(imgThumbPath); + + if ('video' === fileType) { // pixel format for gifs (only needed with ffmpeg older versions eg 1.2) - additionalOptions.push('-pix_fmt rgb24'); + ff.outputOptions('-pix_fmt rgb24'); + // limit file size to ~300kb + ff.outputOptions('-fs 300000'); // start position 1sec in case of black screen - additionalOptions.push('-ss 00:00:01'); - // frequency of snaps one every five seconds - additionalOptions.push('-vf fps=fps=1/5'); - // number of frames - additionalOptions.push('-frames 7'); - // frame rate - additionalOptions.push('-r 7'); - // set the limit file size in bytes - additionalOptions.push('-fs 300000'); - var pathToDir = path.dirname(filePath); - return new FFMpeg({ source : filePath }) - .addOptions(additionalOptions) - .withSize(options.width + 'x' + options.height) - .on('error', function (err) { - logger.log('error', 'Failed to create video thumbnail: ' + err.message); - return next(null, false); - }) - .on('end', function () { - return next(null, self.getRelativePath(imgThumbPath)); - }) - .saveToFile(imgThumbPath); - } - - // can't do thumb - return next(null, false); + ff.seekInput('00:00:01'); + // setting speed to ~x20 gives a good overview + ff.videoFilters('setpts=0.05*PTS'); + // set output framerate + ff.fps(1.5); + } + else if ('gif' === fileFormat) { + // pixel format for gifs (only needed with ffmpeg older versions eg 1.2) + ff.outputOptions('-pix_fmt rgb24'); + // only want 1 output image + ff.frames(1); + } + // use size from options + ff.size(options.width + 'x' + options.height); + // event handling + ff.on('error', function(err) { + logger.log('error', 'Failed to create ' + fileType + ' thumbnail: ' + err.message); + return next(err, false); + }); + ff.on('end', function() { + return next(null, self.getRelativePath(imgThumbPath)); + }); + + return ff.run(); }; +function isThumbnailTypeSupported(type) { + switch(fileType) { + case 'video': + case 'image': + return true; + break; + default: + return false; + } +} + /** * inspects a file using ffprobe and sets metadata * From c216b853cbba8c9213afec2a2f6f70e437410eac Mon Sep 17 00:00:00 2001 From: Tom Taylor Date: Mon, 27 Feb 2017 17:02:53 +0000 Subject: [PATCH 005/296] Sort imports --- plugins/filestorage/localfs/index.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/plugins/filestorage/localfs/index.js b/plugins/filestorage/localfs/index.js index 8454644dbc..6eb3b2e049 100644 --- a/plugins/filestorage/localfs/index.js +++ b/plugins/filestorage/localfs/index.js @@ -3,18 +3,19 @@ * Local LocalFileStorage module */ -var FileStorage = require('../../../lib/filestorage').FileStorage, - configuration = require('../../../lib/configuration'), - usermanager = require('../../../lib/usermanager'), - util = require('util'), - fs = require('fs'), - path = require('path'), - mkdirp = require('mkdirp'), - async = require('async'), - probe = require('node-ffprobe'), - logger = require('../../../lib/logger'), - ncp = require('ncp').ncp, - FFMpeg = require('fluent-ffmpeg'); +var async = require('async'); +var util = require('util'); +var FFMpeg = require('fluent-ffmpeg'); +var fs = require('fs'); +var mkdirp = require('mkdirp'); +var ncp = require('ncp').ncp; +var path = require('path'); +var probe = require('node-ffprobe'); + +var configuration = require('../../../lib/configuration'); +var FileStorage = require('../../../lib/filestorage').FileStorage; +var logger = require('../../../lib/logger'); +var usermanager = require('../../../lib/usermanager'); function LocalFileStorage() { this.dataRoot = path.join(configuration.serverRoot, configuration.getConfig('dataRoot')); From 21bd21606f46d6d18cfd7fa93e12fbe5e6e89ffe Mon Sep 17 00:00:00 2001 From: Tom Taylor Date: Mon, 27 Feb 2017 17:08:34 +0000 Subject: [PATCH 006/296] Make var lowercase --- plugins/filestorage/localfs/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/filestorage/localfs/index.js b/plugins/filestorage/localfs/index.js index 6eb3b2e049..98f3676827 100644 --- a/plugins/filestorage/localfs/index.js +++ b/plugins/filestorage/localfs/index.js @@ -5,7 +5,7 @@ var async = require('async'); var util = require('util'); -var FFMpeg = require('fluent-ffmpeg'); +var ffmpeg = require('fluent-ffmpeg'); var fs = require('fs'); var mkdirp = require('mkdirp'); var ncp = require('ncp').ncp; @@ -367,7 +367,7 @@ LocalFileStorage.prototype.createThumbnail = function (filePath, fileType, optio var thumbExt = ('image' === fileType) ? path.extname(filePath) : '.gif'; var imgThumbPath = path.join(path.dirname(filePath), path.basename(filePath)) + '_thumb' + thumbExt; - var ff = new FFMpeg({ source: filePath }).output(imgThumbPath); + var ff = new ffmpeg({ source: filePath }).output(imgThumbPath); if ('video' === fileType) { // pixel format for gifs (only needed with ffmpeg older versions eg 1.2) From 6a13ec4601500e540aba4670051c2d6c7460f3cc Mon Sep 17 00:00:00 2001 From: nicola Date: Tue, 28 Feb 2017 13:14:02 +0000 Subject: [PATCH 007/296] Fixes to tests --- plugins/auth/local/index.js | 5 +++-- test/lib.auth.js | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/auth/local/index.js b/plugins/auth/local/index.js index 6a82505c31..517e6c29ca 100644 --- a/plugins/auth/local/index.js +++ b/plugins/auth/local/index.js @@ -175,10 +175,11 @@ LocalAuth.prototype.disavow = function (req, res, next) { }; LocalAuth.prototype.registerUser = function (req, res, next) { - // presently, all we need is email and password + // presently, all we need is email, password and retyped password var user = { email: req.body.email, - password: req.body.password + password: req.body.password, + retypePassword: req.body.retypePassword }; this.internalRegisterUser(user, function (error, user) { diff --git a/test/lib.auth.js b/test/lib.auth.js index ca6be90c96..c539d20fc9 100644 --- a/test/lib.auth.js +++ b/test/lib.auth.js @@ -8,6 +8,7 @@ describe('auth', function() { var app = origin(); var helper = { passwordPlain: 'this is my password', + passwordRetypePlain: 'this is my password', passwordCipher: '', email: 'auth@foo.bar', userId: '', @@ -76,7 +77,8 @@ describe('auth', function() { .set('Accept', 'application/json') .send({ 'email': helper.email, - 'password': helper.passwordPlain + 'password': helper.passwordPlain, + 'retypePassword': helper.passwordRetypePlain }) .expect(200) .expect('Content-Type', /json/) From 2ced960ec82091fb1b724bb06598e40a3c0e7df6 Mon Sep 17 00:00:00 2001 From: Tom Taylor Date: Mon, 13 Mar 2017 10:03:33 +0000 Subject: [PATCH 008/296] Fix (some) whitespace (#1545) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix whitespace * Remove AdaptBuilder references * Fix whitespace * Fix origin whitepace * Fix router whitespace * Fix originView whitespace * Fix helpers whitespace Some minor refactoring * Fix bowermanager whitespace * Fix helpers whitespace * Fix auth whitespace * Fix sidebarFieldsetFilterView whitespace * Fix scaffoldTextArea whitespace * Fix sharedProjectView whitespace * Fix projectModel whitespace * Fix navigationView whitespace * Fix modal whitespace * Fix location whitespace * Fix editorPage whitespace * Fix editorComponentModel whitespace * Fix editorBlockModel whitespace * Fix editorArticleModel whitespace * Fix editorMenuSettingsEditSidebar whitespace * Fix editorMenuLayerView whitespace * Fix editorModel whitespace * Fix dashboardSidebarView whitespace Also some minor refactoring, including removing redundant code from updateUI. * Fix dashboardSidebar whitespace * Fix dashboard whitespace * Fix assetModel whitespace * Fix localfs whitespace * Fix menu whitespace * Fix extension whitespace * Fix stray tab * Fix missing whitespace from feedback * Switch “ for ‘ * Replace " * Add space * Add spaces --- frontend/src/core/app/origin.js | 29 +- frontend/src/core/app/router.js | 28 +- frontend/src/core/app/views/originView.js | 43 +-- .../core/assetManagement/models/assetModel.js | 8 +- frontend/src/core/dashboard/dashboard.js | 37 +- .../dashboard/templates/dashboardSidebar.hbs | 64 ++-- .../dashboard/views/dashboardSidebarView.js | 328 ++++++++---------- .../core/editor/global/models/editorModel.js | 229 ++++++------ .../editor/menu/views/editorMenuLayerView.js | 71 +--- .../editorMenuSettingsEditSidebar.hbs | 9 +- .../editor/page/models/editorArticleModel.js | 22 +- .../editor/page/models/editorBlockModel.js | 61 ++-- .../page/models/editorComponentModel.js | 47 ++- .../core/editor/page/templates/editorPage.hbs | 39 +-- frontend/src/core/location/location.js | 14 +- frontend/src/core/modal/modal.js | 5 +- .../core/navigation/views/navigationView.js | 7 +- .../src/core/project/models/projectModel.js | 16 +- .../core/project/views/sharedProjectView.js | 31 +- .../scaffold/views/scaffoldTextAreaView.js | 51 ++- .../views/sidebarFieldsetFilterView.js | 3 - lib/auth.js | 69 ++-- lib/bowermanager.js | 104 +++--- lib/helpers.js | 81 ++--- lib/outputmanager.js | 16 +- plugins/auth/local/index.js | 64 ++-- plugins/content/extension/index.js | 141 ++++---- plugins/content/menu/index.js | 48 +-- plugins/filestorage/localfs/index.js | 49 +-- 29 files changed, 776 insertions(+), 938 deletions(-) diff --git a/frontend/src/core/app/origin.js b/frontend/src/core/app/origin.js index db5e588cff..48d00c9300 100644 --- a/frontend/src/core/app/origin.js +++ b/frontend/src/core/app/origin.js @@ -1,19 +1,23 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require){ - var _ = require('underscore'); var Backbone = require('backbone'); - var Origin = {}; + var Origin = { + location: {}, + editor: { + data: {} + } + }; + + var pluginTaps = []; _.extend(Origin, Backbone.Events); Origin.initialize = _.once(function() { - Origin.tap('initialize', function() { initialize(); }); - }); function initialize() { @@ -30,34 +34,22 @@ define(function(require){ if (currentLocationPluginsLength === 0) { callback(); } else { - var count = 0; - // Goes through each plugin registered using Origin.registerPluginTap + // Goes through each plugin registered using Origin.registerPluginTap // and that have the same location function callPlugin() { currentLocationPlugins[count].pluginMethod.call(null, function() { - count ++; - if (count === currentLocationPluginsLength) { + if (++count === currentLocationPluginsLength) { callback(); } else { callPlugin(); } }); } - callPlugin(); - } } - Origin.editor = {}; - - Origin.editor.data = {}; - - Origin.location = {}; - - var pluginTaps = []; - // Register a plugin to tap into a certain location before the location loads Origin.registerPluginTap = function(location, pluginMethod) { var pluginTap = { @@ -85,5 +77,4 @@ define(function(require){ }); return Origin; - }); diff --git a/frontend/src/core/app/router.js b/frontend/src/core/app/router.js index 44a758cfa3..281259af99 100644 --- a/frontend/src/core/app/router.js +++ b/frontend/src/core/app/router.js @@ -1,16 +1,14 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { - var Backbone = require('backbone'); var Origin = require('coreJS/app/origin'); var PermissionsView = require('coreJS/app/views/permissionsView'); var Router = Backbone.Router.extend({ - routes: { - "" : "handleIndex", - "_=_" : "handleIndex", - ":module(/*route1)(/*route2)(/*route3)(/*route4)" : "handleRoute" + '': 'handleIndex', + '_=_': 'handleIndex', + ':module(/*route1)(/*route2)(/*route3)(/*route4)': 'handleRoute' }, initialize: function() { @@ -28,11 +26,10 @@ define(function(require) { }, redirectToLogin: function() { - this.navigate('#/user/login', {trigger: true}); + this.navigate('#/user/login', { trigger: true }); }, createView: function(View, viewOptions, settings) { - var viewOptions = (viewOptions || {}); var settings = (settings || {}); var currentView; @@ -46,17 +43,15 @@ define(function(require) { return this.redirectToLogin(); } } - $('.app-inner').append(currentView.$el); - }, handleIndex: function() { // Show loading on any route this.showLoading(); - // console.log('in handleIndex'); + if (this.isUserAuthenticated()) { - this.navigate('#/dashboard', {trigger: true}); + this.navigate('#/dashboard', { trigger: true }); } else { return this.redirectToLogin(); } @@ -65,11 +60,9 @@ define(function(require) { // Persist any dashboard routing for 'Back to courses' link evaluateDashboardRoute: function() { if (Origin.location && Origin.location.module == 'dashboard') { - var suffix = Origin.location.route1 ? '/' + Origin.location.route1 : ''; - Origin.dashboardRoute = '/#/dashboard' + suffix; } }, @@ -79,14 +72,12 @@ define(function(require) { this.showLoading(); // Remove views this.removeViews(); - // Check this user has permissions if (!Origin.permissions.checkRoute(Backbone.history.fragment)) { Origin.trigger('sidebar:sidebarContainer:hide'); Origin.trigger('location:title:hide'); return $('.app-inner').append(new PermissionsView().$el); } - // Verify the user is authenticated if (!this.isUserAuthenticated() && (module !== 'user' && route1 !== 'login')) { Origin.Notify.alert({ @@ -97,17 +88,14 @@ define(function(require) { } var routeArguments = arguments; - // Set previous location object Origin.previousLocation = Origin.location; this.evaluateDashboardRoute(); - // Set location object Origin.location = {}; _.each(this.locationKeys, function(locationKey, index) { Origin.location[locationKey] = routeArguments[index]; }); - // Trigger location change Origin.trigger('location:change', Origin.location); @@ -116,7 +104,6 @@ define(function(require) { locationClass += ' location-' + Origin.location.route1 } $('body').removeClass().addClass(locationClass); - // Trigger router event Origin.trigger('router:' + module, route1, route2, route3, route4); }, @@ -139,11 +126,8 @@ define(function(require) { _.delay(_.bind(function() { this.$loading.addClass('display-none').removeClass('cover-top-bar'); }, this), 300); - } - }); return Router; - }); diff --git a/frontend/src/core/app/views/originView.js b/frontend/src/core/app/views/originView.js index 89934e9fce..7ea9b49be8 100644 --- a/frontend/src/core/app/views/originView.js +++ b/frontend/src/core/app/views/originView.js @@ -1,16 +1,9 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE -/* -* BuilderView - base class for all views -* License - http://github.com/adaptlearning/adapt_authoring/LICENSE -* Maintainers - Brian Quinn -*/ define(function(require){ - var Backbone = require('backbone'); var Origin = require('coreJS/app/origin'); var OriginView = Backbone.View.extend({ - settings: { autoRender: true, preferencesKey: '' @@ -27,7 +20,9 @@ define(function(require){ this.listenTo(Origin, 'remove:views', this.remove); }, - preRender: function() {}, + preRender: function() { + + }, render: function() { var data = this.model ? this.model.toJSON() : null; @@ -43,9 +38,13 @@ define(function(require){ return this; }, - postRender: function() {}, + postRender: function() { - onReady: function() {}, + }, + + onReady: function() { + + }, setViewToReady: function() { Origin.trigger('router:hideLoading'); @@ -53,13 +52,11 @@ define(function(require){ setUserPreference: function(key, value) { if (this.settings.preferencesKey && typeof(Storage) !== "undefined") { - // Get preferences for this view var preferences = (Origin.sessionModel.get(this.settings.preferencesKey) || {}); - // Set key and value + // persist data preferences[key] = value; - // Store in localStorage Origin.sessionModel.set(this.settings.preferencesKey, preferences); - + } }, @@ -83,34 +80,24 @@ define(function(require){ }, remove: function() { - - - // If a view has a form - remove it when removing parent view if (this.form) { - // remove ckeditor instances this.form.$( "textarea" ).each(function () { var editor = CKEDITOR.instances[this.id]; try { // check editor is still in the dom (otherwise throws exception) - if (editor && editor.window.getFrame()){ + if (editor && editor.window.getFrame()) { editor.destroy(true); - } + } } catch (e) { + // do nothing } }); - this.form.remove(); - } - // Call original remove + } Backbone.View.prototype.remove.apply(this, arguments); - - - } - }); return OriginView; - }); diff --git a/frontend/src/core/assetManagement/models/assetModel.js b/frontend/src/core/assetManagement/models/assetModel.js index e1bed1ab73..2e668be6ac 100644 --- a/frontend/src/core/assetManagement/models/assetModel.js +++ b/frontend/src/core/assetManagement/models/assetModel.js @@ -1,17 +1,11 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { - var Backbone = require('backbone'); - var Origin = require('coreJS/app/origin'); var AssetModel = Backbone.Model.extend({ - idAttribute: '_id', - urlRoot: '/api/asset' - }); return AssetModel; - -}); \ No newline at end of file +}); diff --git a/frontend/src/core/dashboard/dashboard.js b/frontend/src/core/dashboard/dashboard.js index b0877bb6a6..7be1ac3a5e 100644 --- a/frontend/src/core/dashboard/dashboard.js +++ b/frontend/src/core/dashboard/dashboard.js @@ -1,6 +1,5 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { - var Origin = require('coreJS/app/origin'); var DashboardView = require('coreJS/dashboard/views/dashboardView'); var DashboardSidebarView = require('coreJS/dashboard/views/dashboardSidebarView'); @@ -11,7 +10,6 @@ define(function(require) { Origin.on('router:dashboard', function(location, subLocation, action) { Origin.tap('dashboard', function() { - Origin.editor = {}; Origin.editor.data = {}; @@ -23,7 +21,8 @@ define(function(require) { callbackEvent: 'dashboard:layout:grid', value: 'grid', group: 'layout', - }, { + }, + { title: window.polyglot.t('app.list'), icon: 'list', callbackEvent: 'dashboard:layout:list', @@ -36,13 +35,15 @@ define(function(require) { callbackEvent: 'dashboard:sort:asc', value: 'asc', group: 'sort' - }, { + }, + { title: window.polyglot.t('app.descending'), icon: 'sort-alpha-desc', callbackEvent: 'dashboard:sort:desc', value: 'desc', group: 'sort' - }, { + }, + { title: window.polyglot.t('app.recent'), icon: 'edit', callbackEvent: 'dashboard:sort:updated', @@ -55,7 +56,7 @@ define(function(require) { tagsCollection.fetch({ success: function() { - Origin.sidebar.addView(new DashboardSidebarView({collection:tagsCollection}).$el); + Origin.sidebar.addView(new DashboardSidebarView({ collection: tagsCollection }).$el); var dashboardType = location || 'all'; Origin.trigger('dashboard:loaded', { type: dashboardType }); }, @@ -63,11 +64,8 @@ define(function(require) { console.log('Error occured getting the tags collection - try refreshing your page'); } }); - }); - }); - Origin.on('dashboard:loaded', function (options) { switch (options.type) { case 'shared': @@ -83,21 +81,16 @@ define(function(require) { }); Origin.on('globalMenu:dashboard:open', function() { - - Origin.router.navigate('#/dashboard', {trigger: true}); - + Origin.router.navigate('#/dashboard', { trigger: true }); }); - var globalMenuObject = { - "location": "global", - "text": "Dashboard", - "icon": "fa-home", - "callbackEvent": "dashboard:open", - "sortOrder": 1 - }; - Origin.on('app:dataReady login:changed', function() { - Origin.globalMenu.addItem(globalMenuObject); + Origin.globalMenu.addItem({ + "location": "global", + "text": window.polyglot.t('app.dashboard'), + "icon": "fa-home", + "callbackEvent": "dashboard:open", + "sortOrder": 1 + }); }); - }); diff --git a/frontend/src/core/dashboard/templates/dashboardSidebar.hbs b/frontend/src/core/dashboard/templates/dashboardSidebar.hbs index 1ae122dba6..66ee12139f 100644 --- a/frontend/src/core/dashboard/templates/dashboardSidebar.hbs +++ b/frontend/src/core/dashboard/templates/dashboardSidebar.hbs @@ -1,54 +1,40 @@ diff --git a/frontend/src/core/editor/page/models/editorArticleModel.js b/frontend/src/core/editor/page/models/editorArticleModel.js index 50af86edd0..dafb5820fc 100644 --- a/frontend/src/core/editor/page/models/editorArticleModel.js +++ b/frontend/src/core/editor/page/models/editorArticleModel.js @@ -1,17 +1,17 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { + var EditorModel = require('editorGlobal/models/editorModel'); - var EditorModel = require('editorGlobal/models/editorModel'); + var EditorArticleModel = EditorModel.extend({ + urlRoot: '/api/content/article', + _parent: 'contentObjects', + _siblings: 'articles', + _children: 'blocks', - var EditorArticleModel = EditorModel.extend({ - - urlRoot: '/api/content/article', - initialize: function() {}, - _parent:'contentObjects', - _siblings:'articles', - _children: 'blocks' - }); - - return EditorArticleModel; + initialize: function(options) { + // TODO intentional override? + } + }); + return EditorArticleModel; }); diff --git a/frontend/src/core/editor/page/models/editorBlockModel.js b/frontend/src/core/editor/page/models/editorBlockModel.js index e1fe810825..f34d7edaf2 100644 --- a/frontend/src/core/editor/page/models/editorBlockModel.js +++ b/frontend/src/core/editor/page/models/editorBlockModel.js @@ -1,29 +1,38 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { - - var EditorModel = require('editorGlobal/models/editorModel'); - - var EditorBlockModel = EditorModel.extend({ - - urlRoot: '/api/content/block', - - initialize: function() {}, - - _parent: 'articles', - _siblings:'blocks', - _children: 'components', - - // Block specific properties - layoutOptions: null, - dragLayoutOptions: null, - - // These are the only attributes which should be permitted on a save - whitelistAttributes: ['_id', '_courseId', '_parentId', '_layoutOptions', - '_type', '_sortOrder', '_classes', '_isOptional', '_isAvailable', 'body', 'displayTitle', - 'title', '_extensions'] - - }); - - return EditorBlockModel; - + var EditorModel = require('editorGlobal/models/editorModel'); + + var EditorBlockModel = EditorModel.extend({ + urlRoot: '/api/content/block', + _parent: 'articles', + _siblings: 'blocks', + _children: 'components', + // Block specific properties + layoutOptions: null, + dragLayoutOptions: null, + // These are the only attributes which should be permitted on a save + // TODO look into this... + whitelistAttributes: [ + '_id', + '_courseId', + '_parentId', + '_layoutOptions', + '_type', + '_sortOrder', + '_classes', + '_isOptional', + '_isAvailable', + 'body', + 'displayTitle', + 'title', + '_extensions', + 'themeSettings' + ], + + initialize: function() { + // TODO interntional override? + } + }); + + return EditorBlockModel; }); diff --git a/frontend/src/core/editor/page/models/editorComponentModel.js b/frontend/src/core/editor/page/models/editorComponentModel.js index 940a664dbd..8703b4643e 100644 --- a/frontend/src/core/editor/page/models/editorComponentModel.js +++ b/frontend/src/core/editor/page/models/editorComponentModel.js @@ -1,21 +1,38 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { + var EditorModel = require('editorGlobal/models/editorModel'); - var EditorModel = require('editorGlobal/models/editorModel'); + var EditorComponentModel = EditorModel.extend({ + urlRoot: '/api/content/component', + _parent: 'blocks', + _siblings: 'components', + _children: false, + // These are the only attributes which should be permitted on a save + // TODO look into this... + whitelistAttributes: [ + '_id', + '_componentType', + '_courseId', + '_layout', + '_parentId', + '_type', + 'properties', + '_component', + '_extensions', + '_classes', + '_isOptional', + '_isAvailable', + 'body', + 'displayTitle', + 'title', + 'version', + 'themeSettings' + ], - var EditorComponentModel = EditorModel.extend({ - urlRoot: '/api/content/component', - initialize: function() {}, - - _parent: 'blocks', - _siblings:'components', - _children: false, - // These are the only attributes which should be permitted on a save - whitelistAttributes: ['_id', '_componentType', '_courseId', '_layout', '_parentId', - '_type', 'properties', '_component', '_extensions', '_classes', '_isOptional', '_isAvailable', 'body', 'displayTitle', - 'title', 'version'] - }); - - return EditorComponentModel; + initialize: function() { + // TODO intentional override? + } + }); + return EditorComponentModel; }); diff --git a/frontend/src/core/editor/page/templates/editorPage.hbs b/frontend/src/core/editor/page/templates/editorPage.hbs index 2eef01bf9d..76848b65fc 100644 --- a/frontend/src/core/editor/page/templates/editorPage.hbs +++ b/frontend/src/core/editor/page/templates/editorPage.hbs @@ -1,26 +1,21 @@
+
+

+ + + + {{#if displayTitle}} + {{displayTitle}} + {{else}} + {{title}} + {{/if}} +

+
{{body}}
+
-
- -

- - - - {{#if displayTitle}} - {{{displayTitle}}} - {{else}} - {{title}} - {{/if}} -

- -
{{{body}}}
- -
- -
- - +
+
diff --git a/frontend/src/core/location/location.js b/frontend/src/core/location/location.js index c2a0ccb4d1..baab0cbaab 100644 --- a/frontend/src/core/location/location.js +++ b/frontend/src/core/location/location.js @@ -1,11 +1,9 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { + var Origin = require('coreJS/app/origin'); + var LocationTitleView = require('coreJS/location/views/locationTitleView'); - var Origin = require('coreJS/app/origin'); - var LocationTitleView = require('coreJS/location/views/locationTitleView'); - - Origin.once('app:dataReady', function() { - $('.location-title').html(new LocationTitleView().$el); - }); - -}) \ No newline at end of file + Origin.once('app:dataReady', function() { + $('.location-title').html(new LocationTitleView().$el); + }); +}) diff --git a/frontend/src/core/modal/modal.js b/frontend/src/core/modal/modal.js index 5d3fca8961..00e4671255 100644 --- a/frontend/src/core/modal/modal.js +++ b/frontend/src/core/modal/modal.js @@ -1,9 +1,7 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { - var Origin = require('coreJS/app/origin'); var ModalView = require('coreJS/modal/views/modalView'); - var ModalModel = require('coreJS/modal/models/modalModel'); Origin.on('modal:open', function(view, options, context) { new ModalView({ @@ -12,5 +10,4 @@ define(function(require) { context: context }); }); - -}); \ No newline at end of file +}); diff --git a/frontend/src/core/navigation/views/navigationView.js b/frontend/src/core/navigation/views/navigationView.js index 59e4d42ced..7e9ee1c9f6 100644 --- a/frontend/src/core/navigation/views/navigationView.js +++ b/frontend/src/core/navigation/views/navigationView.js @@ -1,13 +1,10 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require){ - var OriginView = require('coreJS/app/views/originView'); var Origin = require('coreJS/app/origin'); var NavigationView = OriginView.extend({ - tagName: 'nav', - className: 'navigation', initialize: function() { @@ -38,7 +35,7 @@ define(function(require){ $.ajax({ method: 'post', url: '/api/loginas', - data: {email: _revertLogin.email}, + data: { email: _revertLogin.email }, success: function (jqXHR, textStatus, errorThrown) { sessionModel.set('_canRevert', false); sessionModel.set('id', jqXHR.id); @@ -65,11 +62,9 @@ define(function(require){ event.stopPropagation(); Origin.trigger('navigation:' + $(event.currentTarget).attr('data-event')); } - }, { template: 'navigation' }); return NavigationView; - }); diff --git a/frontend/src/core/project/models/projectModel.js b/frontend/src/core/project/models/projectModel.js index 90220eaa22..8abe9a7989 100644 --- a/frontend/src/core/project/models/projectModel.js +++ b/frontend/src/core/project/models/projectModel.js @@ -1,21 +1,16 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { - - var Backbone = require('backbone'); - var Origin = require('coreJS/app/origin'); - var Helpers = require('coreJS/app/helpers'); var EditorModel = require('editorGlobal/models/editorModel'); + var Helpers = require('coreJS/app/helpers'); + var Origin = require('coreJS/app/origin'); var ProjectModel = EditorModel.extend({ - idAttribute: '_id', - urlRoot: '/api/content/course', - defaults: { - 'tags': [], - _type: 'course', - customStyle: '' + 'tags': [], + _type: 'course', + customStyle: '' }, initialize : function(options) { @@ -40,5 +35,4 @@ define(function(require) { }); return ProjectModel; - }); diff --git a/frontend/src/core/project/views/sharedProjectView.js b/frontend/src/core/project/views/sharedProjectView.js index 8f97b20cb3..d44f9440c4 100644 --- a/frontend/src/core/project/views/sharedProjectView.js +++ b/frontend/src/core/project/views/sharedProjectView.js @@ -1,21 +1,16 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require){ - - var Backbone = require('backbone'); - var Handlebars = require('handlebars'); var OriginView = require('coreJS/app/views/originView'); var Origin = require('coreJS/app/origin'); var SharedProjectView = OriginView.extend({ - tagName: 'li', - className: 'shared-project-list-item', events: { - 'dblclick' : 'promptDuplicateProject', - 'click' : 'selectProject', - 'click a.open-context-course' : 'openContextMenu' + 'dblclick': 'promptDuplicateProject', + 'click': 'selectProject', + 'click a.open-context-course': 'openContextMenu' }, preRender: function() { @@ -30,28 +25,25 @@ define(function(require){ this.model.set('heroImageURI', this.model.getHeroImageURI()); }, - openContextMenu: function (e) { - e.stopPropagation(); - e.preventDefault(); - + openContextMenu: function(e) { + e && e.stopPropagation() && e.preventDefault(); Origin.trigger('contextMenu:open', this, e); }, - selectProject: function(event) { - event && event.preventDefault(); - + selectProject: function(e) { + e && e.preventDefault(); this.selectItem(); }, selectItem: function() { Origin.trigger('dashboard:projectView:itemSelected'); this.$el.addClass('selected'); - this.model.set({_isSelected:true}); + this.model.set({ _isSelected: true }); }, deselectItem: function() { this.$el.removeClass('selected'); - this.model.set({_isSelected:false}); + this.model.set({ _isSelected: false }); }, preview: function() { @@ -63,7 +55,6 @@ define(function(require){ promptDuplicateProject: function() { var self = this; - Origin.Notify.confirm({ text: window.polyglot.t('app.confirmduplicate'), callback: function(confirmed) { @@ -79,7 +70,7 @@ define(function(require){ url: this.model.getDuplicateURI(), type: 'GET', success: function (data) { - Origin.router.navigate('/editor/' + data.newCourseId + '/settings', {trigger: true}); + Origin.router.navigate('/editor/' + data.newCourseId + '/settings', { trigger: true }); }, error: function() { Origin.Notify.alert({ @@ -89,11 +80,9 @@ define(function(require){ } }); } - }, { template: 'sharedProject' }); return SharedProjectView; - }); diff --git a/frontend/src/core/scaffold/views/scaffoldTextAreaView.js b/frontend/src/core/scaffold/views/scaffoldTextAreaView.js index 758c5c375b..db9db1438a 100644 --- a/frontend/src/core/scaffold/views/scaffoldTextAreaView.js +++ b/frontend/src/core/scaffold/views/scaffoldTextAreaView.js @@ -1,30 +1,25 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { - - var Backbone = require('backbone'); - var BackboneForms = require('backboneForms'); - var Origin = require('coreJS/app/origin'); - - var TextAreaBlankView = Backbone.Form.editors.TextArea.extend({ - - render: function() { - // Place value - this.setValue(this.value); - return this; - }, - - getValue: function() { - return this.$el.val(); - } - - }); - - Origin.on('app:dataReady', function() { - // Add Image editor to the list of editors - Origin.scaffold.addCustomField('TextArea:blank', TextAreaBlankView); - }) - - - return TextAreaBlankView; - -}) \ No newline at end of file + var Backbone = require('backbone'); + var BackboneForms = require('backboneForms'); + var Origin = require('coreJS/app/origin'); + + var TextAreaBlankView = Backbone.Form.editors.TextArea.extend({ + render: function() { + // Place value + this.setValue(this.value); + return this; + }, + + getValue: function() { + return this.$el.val(); + } + }); + + Origin.on('app:dataReady', function() { + // Add Image editor to the list of editors + Origin.scaffold.addCustomField('TextArea:blank', TextAreaBlankView); + }); + + return TextAreaBlankView; +}); diff --git a/frontend/src/core/sidebar/views/sidebarFieldsetFilterView.js b/frontend/src/core/sidebar/views/sidebarFieldsetFilterView.js index e770a1e559..b4048366c6 100644 --- a/frontend/src/core/sidebar/views/sidebarFieldsetFilterView.js +++ b/frontend/src/core/sidebar/views/sidebarFieldsetFilterView.js @@ -1,13 +1,10 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE define(function(require) { - var Origin = require('coreJS/app/origin'); var Backbone = require('backbone'); var SidebarFieldsetFilterView = Backbone.View.extend({ - className: 'sidebar-row', - events: { 'click button': 'onFilterClicked' }, diff --git a/lib/auth.js b/lib/auth.js index b760d67fec..d1e316cc7c 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -4,21 +4,22 @@ * */ -var path = require('path'), - fs = require('fs'), - async = require('async'), - junk = require('junk'), - util = require('util'), - bcrypt = require('bcrypt-nodejs'), - passport = require('passport'), - database = require('./database'), - configuration = require('./configuration'), - logger = require('./logger'), - rest = require('./rest'), - pluginmanager = require('./pluginmanager'), - permissions = require('./permissions'), - tenantmanager = require('./tenantmanager'), - usermanager = require('./usermanager'); +var async = require('async'); +var bcrypt = require('bcrypt-nodejs'); +var fs = require('fs'); +var junk = require('junk'); +var path = require('path'); +var util = require('util'); +var passport = require('passport'); + +var configuration = require('./configuration'); +var database = require('./database'); +var logger = require('./logger'); +var rest = require('./rest'); +var permissions = require('./permissions'); +var pluginmanager = require('./pluginmanager'); +var tenantmanager = require('./tenantmanager'); +var usermanager = require('./usermanager'); // private hash for memoizing auth plugins var _authPlugins = Object.create(null); @@ -27,8 +28,8 @@ var _otherLoginLinks = []; /* * CONSTANTS */ -var MODNAME = 'authentication', - WAITFOR = 'pluginmanager'; +var MODNAME = 'authentication'; +var WAITFOR = 'pluginmanager'; // custom errors function UserRegistrationError (message) { @@ -63,7 +64,7 @@ AuthPlugin.prototype.authenticate = function (req, res, next) { }; AuthPlugin.prototype.getLoginHtml = function() { - return ''; + return ''; }; AuthPlugin.prototype.disavow = function (req, res, next) { @@ -107,7 +108,7 @@ AuthPlugin.prototype.isTenantEnabled = function (user, cb) { exports = module.exports = { errors: { - 'UserRegistrationError' : UserRegistrationError, + 'UserRegistrationError': UserRegistrationError, 'UserResetPasswordError': UserResetPasswordError, 'UserGenerateTokenError': UserGenerateTokenError }, @@ -179,7 +180,7 @@ exports = module.exports = { * @return {object} preloader - an AdaptBuilder ModulePreloader */ preload: function (app) { - var preloader = new app.ModulePreloader(app, MODNAME, {events:preloadHandle(app,this)}); + var preloader = new app.ModulePreloader(app, MODNAME, { events: preloadHandle(app,this) }); return preloader; }, @@ -209,38 +210,38 @@ exports = module.exports = { if (err) { return cb(err); } - + var loginHtml = _authPlugins[name].getLoginHtml(); - + if (loginHtml.length !== 0) { - _otherLoginLinks.push(loginHtml) + _otherLoginLinks.push(loginHtml) } - return cb(null, _authPlugins[name]); + return cb(null, _authPlugins[name]); }); - + } catch (err) { return cb(err); } }); }, - + /** * reads the auth plugin directory and returns the names * of available plugins - * + * * @return array */ - + getAvailableAuthPluginsSync: function () { return fs.readdirSync(path.join(configuration.serverRoot, 'plugins', 'auth')).filter(junk.not); }, - + loadAuthPlugins: function(next) { // Load all auth plugins here - logger.log('info', 'Supporting the following authentication types:') + logger.log('info', 'Supporting the following authentication types:') var self = this; - + async.eachSeries( self.getAvailableAuthPluginsSync(), function (pluginName, nextPlugin) { @@ -301,7 +302,7 @@ function preloadHandle(app, instance){ // user exists var user = results[0]; } - + // Store the login details req.logIn(user, function(error) { if (error) { @@ -386,7 +387,7 @@ function preloadHandle(app, instance){ res.statusCode = 200; return res.json(result); }); - + }); rest.post('/userpasswordreset/:token', function (req, res, next) { @@ -411,7 +412,7 @@ function preloadHandle(app, instance){ instance.loadAuthPlugins(function() { preloader.emit('preloadChange', MODNAME, app.preloadConstants.COMPLETE); - }); + }); } } }; diff --git a/lib/bowermanager.js b/lib/bowermanager.js index a119e212d1..608a9acb12 100644 --- a/lib/bowermanager.js +++ b/lib/bowermanager.js @@ -1,14 +1,18 @@ -var bower = require('bower'); +var _ = require('underscore'); var async = require('async'); +var bower = require('bower'); +var fs = require('fs-extra'); +var mkdirp = require('mkdirp'); +var ncp = require('ncp').ncp; +var path = require('path'); var rimraf = require('rimraf'); var semver = require('semver'); -var logger = require('./logger'); + +var Constants = require('./outputmanager').Constants; var database = require('./database'); -var ncp = require('ncp').ncp; -var mkdirp = require('mkdirp'); -var fs = require('fs-extra'); -var path = require('path'); -var _ = require('underscore'); +var logger = require('./logger'); +var origin = require('./application')(); + var bowerOptions = require('../plugins/content/bower/defaults.json'); /* @@ -16,9 +20,9 @@ var bowerOptions = require('../plugins/content/bower/defaults.json'); */ var MODNAME = 'bowermanager', WAITFOR = 'contentmanager'; - + var BowerManager = function() { - + } BowerManager.prototype.extractPackageInfo = function(plugin, pkgMeta, schema) { @@ -38,9 +42,9 @@ BowerManager.prototype.extractPackageInfo = function(plugin, pkgMeta, schema) { // The targetAttribute property is optional. if (pkgMeta.targetAttribute) { - info.targetAttribute = pkgMeta.targetAttribute; + info.targetAttribute = pkgMeta.targetAttribute; } - + // The assetFields property is optional too. if (pkgMeta.assetFields) { info.assetFields = pkgMeta.assetFields; @@ -67,41 +71,41 @@ BowerManager.prototype.extractPackageInfo = function(plugin, pkgMeta, schema) { */ BowerManager.prototype.installPlugin = function(pluginName, pluginVersion, callback) { var self = this; - + // Formulate the package name. var packageName = (pluginVersion == '*') ? pluginName : pluginName + '#' + pluginVersion; - + // Interrogate the version.json file on installation as we cannot rely on including it via a 'require' call. fs.readFile(path.join(app.configuration.getConfig('root'), 'version.json'), 'utf8', function(err, version) { - // Ensure the JSON is parsed. + // Ensure the JSON is parsed. version = JSON.parse(version); - + if (err) { logger.log('error', err); return callback(err); } - + // Clear the bower cache for this plugin. rimraf(path.join(bowerOptions.directory, pluginName), function (err) { if (err) { logger.log('error', err); return callback(err); } - + // Query bower to verify that the specified plugin exists. bower.commands.search(pluginName, bowerOptions) .on('error', callback) - .on('end', function (results) { + .on('end', function (results) { if (!results || results.length == 0) { logger.log('warn', 'Plugin ' + packageName + ' not found!'); return callback('Plugin ' + packageName + ' not found!'); } - - // The plugin exists -- remove any fuzzy matches, e.g. adapt-contrib-assessment would + + // The plugin exists -- remove any fuzzy matches, e.g. adapt-contrib-assessment would // also bring in adapt-contrib-assessmentResults, etc. - var bowerPackage = _.findWhere(results, {name: pluginName}); + var bowerPackage = _.findWhere(results, { name: pluginName }); // Install the plugin from bower. bower.commands.install([packageName], { save: true }, bowerOptions) @@ -109,24 +113,24 @@ BowerManager.prototype.installPlugin = function(pluginName, pluginVersion, callb logger.log('error', err); return callback(err); }) - .on('end', function (packageInfo) { + .on('end', function (packageInfo) { // Unfortunately this is required as the only way to identify the type - // of a plugin is to check for the presence of the property which + // of a plugin is to check for the presence of the property which // actually indicates its type. :-/ - var pluginType = packageInfo[pluginName].pkgMeta.hasOwnProperty('component') + var pluginType = packageInfo[pluginName].pkgMeta.hasOwnProperty('component') ? 'component' : packageInfo[pluginName].pkgMeta.hasOwnProperty('extension') ? 'extension' : packageInfo[pluginName].pkgMeta.hasOwnProperty('menu') ? 'menu' - : packageInfo[pluginName].pkgMeta.hasOwnProperty('theme') + : packageInfo[pluginName].pkgMeta.hasOwnProperty('theme') ? 'theme' : '' - + if (pluginType == '') { logger.log('error', 'Unable to identify pluginType for ' + packageName); return callback('Unable to identify pluginType for ' + packageName); } - + app.contentmanager.getContentPlugin(pluginType, function(err, plugin) { if (err) { return callback(err); @@ -141,12 +145,12 @@ BowerManager.prototype.installPlugin = function(pluginName, pluginVersion, callb return callback('Unable to install ' + packageInfo[pluginName].pkgMeta.name + ' as it is not supported in the current version of of the Adapt framework'); } } else { - self.importPackage(plugin, packageInfo[pluginName], bowerOptions, callback); + self.importPackage(plugin, packageInfo[pluginName], bowerOptions, callback); } }); }); }); - }); + }); }); } @@ -215,12 +219,12 @@ BowerManager.prototype.importPackage = function (plugin, packageInfo, options, c options = { strict: false }; - } + } var self = this; var pkgMeta = packageInfo.pkgMeta; var schemaPath = path.join(packageInfo.canonicalDir, options._adaptSchemaFile); - + fs.exists(schemaPath, function (exists) { if (!exists) { if (options.strict) { @@ -252,10 +256,10 @@ BowerManager.prototype.importPackage = function (plugin, packageInfo, options, c logger.log('error', 'failed to parse schema for ' + pkgMeta.name, e); return callback(null); } - + // Build a path to the destination working folder. var destination = path.join(app.configuration.getConfig('root').toString(), 'temp', app.configuration.getConfig('masterTenantID').toString(), 'adapt_framework', 'src', plugin.bowerConfig.srcLocation, pkgMeta.name); - + // Remove whatever version of the plugin is there already. rimraf(destination, function(err) { if (err) { @@ -268,7 +272,7 @@ BowerManager.prototype.importPackage = function (plugin, packageInfo, options, c return logger.log('error', err); } - // Move from the bower cache to the working directory. + // Move from the bower cache to the working directory. ncp(packageInfo.canonicalDir, destination, function (err) { if (err) { // Don't double call callback. @@ -282,60 +286,60 @@ BowerManager.prototype.importPackage = function (plugin, packageInfo, options, c } logger.log('info', 'Successfully copied ' + pkgMeta.name + ' to ' + destination); - + // Build the package information. var package = self.extractPackageInfo(plugin, pkgMeta, schema); var db = app.db; var pluginString = package.name + ' (v' + package.version + ')'; - // Add the package to the collection. + // Add the package to the collection. // Check if a plugin with this name and version already exists. db.retrieve(plugin.getPluginType(), { name: package.name, version: package.version }, function (err, results) { if (err) { logger.log('error', err); return callback(err); } - + if (results && results.length !== 0) { // Don't add a duplicate. if (options.strict) { return callback("Can't add " + pluginString + ": verion already exists"); } - + return callback(null); } - + // Add the new plugin. db.create(plugin.getPluginType(), package, function (err, newPlugin) { - if (err) { + if (err) { logger.log('error', err); - + if (options.strict) { return callback(err); } - + logger.log('error', 'Failed to add package: ' + pluginString, err); return callback(null); } - + logger.log('info', 'Added package: ' + pluginString); - + // Retrieve any older versions of the plugin. db.retrieve(plugin.getPluginType(), { name: package.name, version: { $ne: newPlugin.version } }, function (err, results) { if (err) { // strictness doesn't matter at this point logger.log('error', 'Failed to retrieve previous packages: ' + err.message, err); } - + // Remove older versions of this plugin. - db.destroy(plugin.getPluginType(), { name: package.name, version: { $ne: newPlugin.version } }, function (err) { + db.destroy(plugin.getPluginType(), { name: package.name, version: { $ne: newPlugin.version } }, function (err) { if (err) { logger.log('error', err); return callback(err); } - + logger.log('info', 'Successfully removed versions of ' + package.name + ' (' + plugin.getPluginType() + ') older than ' + newPlugin.version); - + return callback(null, newPlugin); }); // Remove older versions of the plugin. }); // Retrieve older versions of the plugin. @@ -357,8 +361,8 @@ exports = module.exports = { /** * preload function * - * @param {object} app - AdaptBuilder instance - * @return {object} preloader - an AdaptBuilder ModulePreloader + * @param {object} app - Origin instance + * @return {object} preloader - a ModulePreloader */ preload : function (app) { var preloader = new app.ModulePreloader(app, MODNAME, { events: this.preloadHandle(app, new BowerManager()) }); diff --git a/lib/helpers.js b/lib/helpers.js index 10e46c3c13..d1352202fe 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -1,8 +1,8 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE -var rolemanager = require('./rolemanager'); +var configuration = require('./configuration'); var database = require('./database'); var logger = require('./logger'); -var configuration = require('./configuration'); +var rolemanager = require('./rolemanager'); /** * function generates an object from json schema - could not find a lib to do this for me :-\ @@ -14,7 +14,6 @@ function schemaToObject (schema, id, version, location) { if (!this.memo) { this.memo = Object.create(null); } - // check if we have already built this object var identifier = id + '#' + version + '/' + location; if (this.memo[identifier]) { @@ -42,7 +41,6 @@ function schemaToObject (schema, id, version, location) { break; case "object": var nestedProps = prop.properties; - child[key] = nestedProps ? walkObject(nestedProps) : prop.default || {}; break; default: @@ -76,35 +74,31 @@ function grantSuperPermissions (userId, next) { if (!userId) { return next(new Error("Failed to grant super user permissions, invalid userId: " + userId)); } - + var _assignSuperRole = function (userId, cb) { // verify the Super Admin role is installed rolemanager.retrieveRole({ name: "Super Admin" }, function (err, role) { if (err) { return cb(err); } - if (role) { return rolemanager.assignRole(role._id, userId, cb); } - // role does not exist, bah! return cb(new Error('Role not found')); }); }; - + _assignSuperRole(userId, function (err) { if (!err) { // no problem, role was assigned return next(null); } - // otherwise we need to install default roles rolemanager.installDefaultRoles(function (err) { if (err) { return next(err); } - // the second attempt passes control back to the first callback _assignSuperRole(userId, next); }); @@ -118,7 +112,7 @@ function isMasterPreviewAccessible(courseId, userId, next) { return err; } - db.retrieve('course', { _id: courseId }, {jsonOnly: true}, function (err, results) { + db.retrieve('course', { _id: courseId }, { jsonOnly: true }, function (err, results) { if (err) { logger.log('error', err); return next(err); @@ -130,10 +124,10 @@ function isMasterPreviewAccessible(courseId, userId, next) { if (course._isShared || course.createdBy == userId) { // Shared courses on the same tenant are open to users on the same tenant return next(null, true); - } - + } + return next(null, false); - + } else { return next(new Error('Course ' + courseId + ' not found')); } @@ -143,46 +137,43 @@ function isMasterPreviewAccessible(courseId, userId, next) { function hasCoursePermission (action, userId, tenantId, contentItem, next) { // Check that the contentItem has something resembling a courseId - if (contentItem.hasOwnProperty('_id') || contentItem.hasOwnProperty('_courseId')) { - var courseId = contentItem && contentItem._courseId - ? contentItem._courseId.toString() - : contentItem._id.toString(); + if (!contentItem.hasOwnProperty('_id') && !contentItem.hasOwnProperty('_courseId')) { + // Course permission cannot be verified + return next(null, false); + } - database.getDatabase(function(err, db) { + var courseId = contentItem && contentItem._courseId + ? contentItem._courseId.toString() + : contentItem._id.toString(); + + database.getDatabase(function(err, db) { + if (err) { + logger.log('error', err); + return err; + } + + db.retrieve('course', { _id: courseId }, { jsonOnly: true }, function (err, results) { if (err) { logger.log('error', err); - return err; + return next(err); + } + if (!results || results.length !== 1) { + return next(new Error('Course ' + courseId + ' not found')); } - db.retrieve('course', { _id: courseId }, {jsonOnly: true}, function (err, results) { - if (err) { - logger.log('error', err); - return next(err); - } - - if (results && results.length == 1) { - var course = results[0]; + var course = results[0]; - if ((course._isShared || course.createdBy == userId) && course._tenantId.toString() == tenantId) { - // Shared courses on the same tenant are open to users on the same tenant - return next(null, true); - } - - return next(null, false); - - } else { - return next(new Error('Course ' + courseId + ' not found')); - } - }); - }); - } else { - // Course permission cannot be verified - return next(null, false); - } + if ((course._isShared || course.createdBy == userId) && course._tenantId.toString() == tenantId) { + // Shared courses on the same tenant are open to users on the same tenant + return next(null, true); + } + return next(null, false); + }); + }); } /** - * Replaces ALL insstances of the search parameter in a given string with a replacement + * Replaces ALL instances of the search parameter in a given string with a replacement * @param {string} str * @param {string} search * @param {string} replacement diff --git a/lib/outputmanager.js b/lib/outputmanager.js index 75388e986e..c59eb87c8c 100644 --- a/lib/outputmanager.js +++ b/lib/outputmanager.js @@ -112,8 +112,8 @@ OutputPlugin.prototype.getCourseJSON = function(tenantId, courseId, next) { async.each(Object.keys(Constants.CourseCollections), function(collectionType, callback) { // Set the courseId correctly var criteria = collectionType === 'course' - ? {_id: courseId} - : {_courseId: courseId}; + ? { _id: courseId } + : { _courseId: courseId }; if (collectionType == 'config') { @@ -365,9 +365,9 @@ OutputPlugin.prototype.buildFlagExists = function(pathToBuildFlag, next) { logger.log('error', err); } } - + var exists = typeof stats == 'object'; - + return next(null, exists); }); }; @@ -925,11 +925,11 @@ OutputPlugin.prototype.slugify = function(s) { * @return {string} */ OutputPlugin.prototype.escapeQuotes = function(s) { - + if (typeof s !== 'string') { return ''; } - + s = s.replace(/"/g,'\\"'); s = s.replace(/'/g, "\\'"); @@ -1048,8 +1048,8 @@ exports = module.exports = { /** * preload function * - * @param {object} app - AdaptBuilder instance - * @return {object} preloader - an AdaptBuilder ModulePreloader + * @param {object} app - Origin instance + * @return {object} preloader - a ModulePreloader */ preload : function (app) { var preloader = new app.ModulePreloader(app, MODNAME, { events: this.preloadHandle(app, new OutputManager()) }); diff --git a/plugins/auth/local/index.js b/plugins/auth/local/index.js index 4a465ebb51..e9a69e4aba 100644 --- a/plugins/auth/local/index.js +++ b/plugins/auth/local/index.js @@ -48,8 +48,10 @@ LocalAuth.prototype.verifyUser = function (email, password, done) { } if (!user) { - return done(null, false, {message: MESSAGES.INVALID_USERNAME_OR_PASSWORD, - errorCode: ERROR_CODES.INVALID_USERNAME_OR_PASSWORD}); + return done(null, false, { + message: MESSAGES.INVALID_USERNAME_OR_PASSWORD, + errorCode: ERROR_CODES.INVALID_USERNAME_OR_PASSWORD + }); } if (user.failedLoginCount < MAX_LOGIN_ATTEMPTS) { @@ -63,23 +65,25 @@ LocalAuth.prototype.verifyUser = function (email, password, done) { if (!valid) { // Increment the count of failed attempts var failedCount = user.failedLoginCount ? user.failedLoginCount : 0; - + failedCount++; var delta = { failedLoginCount: failedCount }; - usermanager.updateUser({email: user.email}, delta, function(error) { + usermanager.updateUser({ email: user.email }, delta, function(error) { if (error) { return done(error); } - - return done(null, false, {message: MESSAGES.INVALID_USERNAME_OR_PASSWORD, - errorCode: ERROR_CODES.INVALID_USERNAME_OR_PASSWORD}); + + return done(null, false, { + message: MESSAGES.INVALID_USERNAME_OR_PASSWORD, + errorCode: ERROR_CODES.INVALID_USERNAME_OR_PASSWORD + }); }); } else { - usermanager.updateUser({email: user.email}, {failedLoginCount: 0}, function(error) { + usermanager.updateUser({ email: user.email }, { failedLoginCount: 0 }, function(error) { if (error) { return done(error); } @@ -90,7 +94,10 @@ LocalAuth.prototype.verifyUser = function (email, password, done) { }); } else { // Indicate that the account is locked out - return done(null, false, {message: MESSAGES.ACCOUNT_LOCKED, errorCode: ERROR_CODES.ACCOUNT_LOCKED}); + return done(null, false, { + message: MESSAGES.ACCOUNT_LOCKED, + errorCode: ERROR_CODES.ACCOUNT_LOCKED + }); } }); }; @@ -126,20 +133,20 @@ LocalAuth.prototype.authenticate = function (req, res, next) { if (error) { return next(error); } - + usermanager.logAccess(user, function(error) { if (error) { return next(error); } - - + + //Used to get the users permissions permissions.getUserPermissions(user._id, function(error, userPermissions) { if (error) { return next(error); } res.statusCode = 200; - + if (req.body.shouldPersist && req.body.shouldPersist == 'true') { // Session is persisted for 2 weeks if the user has set 'Remember me' req.session.cookie.maxAge = 14 * 24 * 3600000; @@ -148,7 +155,7 @@ LocalAuth.prototype.authenticate = function (req, res, next) { } var userSession = req.session.passport.user; - + return res.json({ success: true, id: user._id, @@ -157,14 +164,12 @@ LocalAuth.prototype.authenticate = function (req, res, next) { tenantName: userSession.tenant.name, permissions: userPermissions }); - }); - }); }); }); } - + })(req, res, next); }; @@ -229,12 +234,12 @@ LocalAuth.prototype.resetPassword = function (req, res, next) { if (error) { logger.log('error', error); res.statusCode = 200; - return res.json({success: false}); + return res.json({ success: false }); // return next(error); } res.statusCode = 200; - return res.json({success: true}); + return res.json({ success: true }); }); }; @@ -250,12 +255,12 @@ LocalAuth.prototype.internalResetPassword = function (user, next) { } // Update user details with hashed password - usermanager.updateUser({_id: user.id}, {password: hash, failedLoginCount: 0}, function(err) { + usermanager.updateUser({ _id: user.id }, { password: hash, failedLoginCount: 0 }, function(err) { if (error) { return next(error) } - usermanager.deleteUserPasswordReset({user: user.id}, function (error, user) { + usermanager.deleteUserPasswordReset({ user: user.id }, function (error, user) { if (error) { return next(error); } @@ -270,13 +275,13 @@ LocalAuth.prototype.internalResetPassword = function (user, next) { LocalAuth.prototype.generateResetToken = function (req, res, next) { var self = this; - usermanager.retrieveUser({email: req.body.email, auth: 'local'}, function (error, userRecord) { + usermanager.retrieveUser({ email: req.body.email, auth: 'local' }, function (error, userRecord) { if (error) { logger.log('error', error); res.statusCode = 400; - return res.json({success: false}); + return res.json({ success: false }); } - + if (userRecord) { var user = { email: req.body.email, @@ -292,9 +297,9 @@ LocalAuth.prototype.generateResetToken = function (req, res, next) { if (!userToken) { return next(new auth.errors.UserGenerateTokenError('In generateResetToken and user object is not set!')); } - + var subject = app.polyglot.t('app.emailforgottenpasswordsubject'); - var body = app.polyglot.t('app.emailforgottenpasswordbody', {rootUrl: configuration.getConfig('rootUrl'), data: userToken.token}); + var body = app.polyglot.t('app.emailforgottenpasswordbody', { rootUrl: configuration.getConfig('rootUrl'), data: userToken.token }); var templateData = { name: 'passwordReset', user: user, @@ -310,14 +315,13 @@ LocalAuth.prototype.generateResetToken = function (req, res, next) { } logger.log('info', 'Password reset for ' + user.email + ' from ' + user.ipAddress); - return res.status(200).json({success: true}); + return res.status(200).json({ success: true }); }); }); } else { - // Indicate that all is ok even if the user does not exist - // This is to prevent hacking attempts + // Return 200 even if user doesn't exist to prevent brute force hacking res.statusCode = 200; - return res.json({success: true}); + return res.json({ success: true }); } }); }; diff --git a/plugins/content/extension/index.js b/plugins/content/extension/index.js index 6066f80e52..d636fe41e3 100644 --- a/plugins/content/extension/index.js +++ b/plugins/content/extension/index.js @@ -3,28 +3,30 @@ * Extension content plugin * */ - -var origin = require('../../../'), - contentmanager = require('../../../lib/contentmanager'), - usermanager = require('../../../lib/usermanager'), - rest = require('../../../lib/rest'), - BowerPlugin = require('../bower'), - ContentPlugin = contentmanager.ContentPlugin, - ContentTypeError = contentmanager.errors.ContentTypeError, - configuration = require('../../../lib/configuration'), - database = require('../../../lib/database'), - helpers = require('../../../lib/helpers'), - logger = require('../../../lib/logger'), - defaultOptions = require('./defaults.json'), - bower = require('bower'), - rimraf = require('rimraf'), - async = require('async'), - fs = require('fs'), - ncp = require('ncp').ncp, - mkdirp = require('mkdirp'), - _ = require('underscore'), - util = require('util'), - path = require('path'); +var _ = require('underscore'); +var async = require('async'); +var bower = require('bower'); +var fs = require('fs'); +var mkdirp = require('mkdirp'); +var ncp = require('ncp').ncp; +var path = require('path'); +var rimraf = require('rimraf'); +var util = require('util'); + +var BowerPlugin = require('../bower'); +var database = require('../../../lib/database'); +var configuration = require('../../../lib/configuration'); +var contentmanager = require('../../../lib/contentmanager'); +var helpers = require('../../../lib/helpers'); +var logger = require('../../../lib/logger'); +var origin = require('../../../'); +var rest = require('../../../lib/rest'); +var usermanager = require('../../../lib/usermanager'); + +var ContentPlugin = contentmanager.ContentPlugin; +var ContentTypeError = contentmanager.errors.ContentTypeError; + +var defaultOptions = require('./defaults.json'); var bowerConfig = { type: 'extensiontype', @@ -57,14 +59,12 @@ var bowerConfig = { enabledExtensions[key].version = newPlugin.version; } }); - // run the update db.update('config', { _id: doc._id }, { _enabledExtensions: enabledExtensions }, nextItem); }, function (err) { if (err) { logger.log('error', 'Failed to update old documents: ' + err.message, err); } - return next(null); }); }); @@ -152,7 +152,7 @@ function getEnabledExtensions(courseId, cb) { function contentDeletionHook(contentType, data, cb) { var contentData = data[0]; - + if (!contentData._id) { return cb(null, data); } @@ -184,51 +184,51 @@ function contentCreationHook (contentType, data, cb) { if (error) { return callback(error); } - + db.retrieve('componenttype', {component: contentData._component}, function(err, results) { if (err) { return callback(err); } - + if (!results || results.length == 0) { return callback('Unexpected number of componentType records'); } - + var componentType = results[0]._doc; - + if (componentType.globals) { // The component has globals. database.getDatabase(function(error, tenantDb) { // Add the globals to the course. - tenantDb.retrieve('course', {_id: contentData._courseId}, function(err, results) { + tenantDb.retrieve('course', { _id: contentData._courseId }, function(err, results) { if (err) { return callback(err); } - + var key = '_' + componentType.component; var courseDoc = results[0]._doc; var courseGlobals = courseDoc._globals ? courseDoc._globals : {}; - + // Create the _components global object. if (!courseGlobals._components) { courseGlobals._components = {}; } - + if (!courseGlobals._components[key]) { // The global JSON does not exist for this component so set the defaults. var componentGlobals = {}; - + for (var prop in componentType.globals) { if (componentType.globals.hasOwnProperty(prop)) { componentGlobals[prop] = componentType.globals[prop].default; } } - + courseGlobals._components[key] = componentGlobals; - - tenantDb.update('course', {_id: contentData._courseId}, {_globals: courseGlobals}, function(err, doc) { + + tenantDb.update('course', { _id: contentData._courseId }, { _globals: courseGlobals }, function(err, doc) { if (err) { return callback(err); } else { @@ -238,8 +238,8 @@ function contentCreationHook (contentType, data, cb) { } else { return callback(null); } - }); - }); + }); + }); } else { return callback(null) } @@ -250,23 +250,24 @@ function contentCreationHook (contentType, data, cb) { } }, function(callback) { - getEnabledExtensions(contentData._courseId, function (error, extensions) { + getEnabledExtensions(contentData._courseId, function(error, extensions) { if (error) { // permit content creation to continue, but log error logger.log('error', 'could not load extensions: ' + error.message); return callback(null); } - - // _extensions is undefined at this point - contentData._extensions = {}; - extensions.forEach(function (extensionItem) { + + // create _extensions if we need it + if(!contentData._extensions) contentData._extensions = {}; + extensions.forEach(function(extensionItem) { if (extensionItem.properties.hasOwnProperty('pluginLocations') && extensionItem.properties.pluginLocations.properties[contentType]) { var schema = extensionItem.properties.pluginLocations.properties[contentType].properties; // yeesh var generatedObject = helpers.schemaToObject(schema, extensionItem.name, extensionItem.version, contentType); - contentData._extensions = _.extend(contentData._extensions, generatedObject); - } + // keep any existing values in place + contentData._extensions = _.defaults(contentData._extensions, generatedObject); + } }); - + // assign back to passed args data[0] = contentData; callback(null); @@ -278,7 +279,7 @@ function contentCreationHook (contentType, data, cb) { logger.log('error', err); return cb(err); } - + return cb(null, data); }); } @@ -302,7 +303,7 @@ function toggleExtensions (courseId, action, extensions, cb) { if (user && user.tenant && user.tenant._id) { // Changes to extensions warrants a full course rebuild app.emit('rebuildCourse', user.tenant._id, courseId); - } + } database.getDatabase(function (err, db) { if (err) { @@ -335,9 +336,9 @@ function toggleExtensions (courseId, action, extensions, cb) { targetAttribute: targetAttribute }; } - + if (generatedObject) { - updatedExtensions = _.extend(updatedExtensions, generatedObject); + updatedExtensions = _.extend(updatedExtensions, generatedObject); } } else { // remove from list of enabled extensions in config object @@ -353,7 +354,7 @@ function toggleExtensions (courseId, action, extensions, cb) { if (isConfig) { delta._enabledExtensions = enabledExtensions; } - + tenantDb.update(componentType, { _id: component._id }, delta, next); }, nextComponent); }); @@ -370,11 +371,11 @@ function toggleExtensions (courseId, action, extensions, cb) { logger.log('error', err); return cb(err); } - + // Iterate over all the extensions async.eachSeries(results, function (extensionItem, nextItem) { var locations = extensionItem.properties.pluginLocations.properties; - + // Ensure that the 'config' key always exists, as this is required // to presist the list of enabled extensions. if (!_.has(locations, 'config')) { @@ -382,34 +383,34 @@ function toggleExtensions (courseId, action, extensions, cb) { } if (extensionItem.globals) { - tenantDb.retrieve('course', {_id: courseId}, function (err, results) { + tenantDb.retrieve('course', { _id: courseId }, function (err, results) { if (err) { return cb(err); } - + var courseDoc = results[0]._doc; var key = '_' + extensionItem.extension; // Extract the global defaults var courseGlobals = courseDoc._globals ? courseDoc._globals : {}; - - if (action == 'enable') { + + if (action == 'enable') { // Add default value and if (!courseGlobals._extensions) { courseGlobals._extensions = {}; } - + if (!courseGlobals._extensions[key]) { // The global JSON does not exist for this extension so set the defaults var extensionGlobals = {}; - + for (var prop in extensionItem.globals) { if (extensionItem.globals.hasOwnProperty(prop)) { extensionGlobals[prop] = extensionItem.globals[prop].default; } } - + courseGlobals._extensions[key] = extensionGlobals; } } else { @@ -418,19 +419,19 @@ function toggleExtensions (courseId, action, extensions, cb) { delete courseGlobals._extensions[key]; } } - - tenantDb.update('course', {_id: courseId}, {_globals: courseGlobals}, function(err, doc) { + + tenantDb.update('course', { _id: courseId }, { _globals: courseGlobals }, function(err, doc) { if (!err) { async.eachSeries(Object.keys(locations), function (key, nextLocation) { updateComponentItems(tenantDb, key, locations[key].properties, extensionItem, nextLocation); - }, nextItem); + }, nextItem); } }); - }); + }); } else { async.eachSeries(Object.keys(locations), function (key, nextLocation) { updateComponentItems(tenantDb, key, locations[key].properties, extensionItem, nextLocation); - }, nextItem); + }, nextItem); } }, function(err) { if (err) { @@ -441,12 +442,12 @@ function toggleExtensions (courseId, action, extensions, cb) { // Trigger an event to indicate that the extension has been enabled/disabled. app.emit(`extension:${action}`, results[0].name, user.tenant._id, courseId, user._id); } - + cb(); } - }); + }); }); - + }); }, configuration.getConfig('dbName')); } @@ -514,7 +515,7 @@ function initialize () { ['contentobject', 'article', 'block', 'component'].forEach(function (contentType) { app.contentmanager.addContentHook('create', contentType, contentCreationHook.bind(null, contentType)); }); - + ['component'].forEach(function(contentType) { app.contentmanager.addContentHook('destroy', contentType, contentDeletionHook.bind(null, contentType)); }); diff --git a/plugins/content/menu/index.js b/plugins/content/menu/index.js index 209021dcec..44874b6f67 100644 --- a/plugins/content/menu/index.js +++ b/plugins/content/menu/index.js @@ -3,27 +3,29 @@ * Menu content plugin * */ - -var origin = require('../../../'), - contentmanager = require('../../../lib/contentmanager'), - rest = require('../../../lib/rest'), - BowerPlugin = require('../bower'), - ContentPlugin = contentmanager.ContentPlugin, - ContentTypeError = contentmanager.errors.ContentTypeError, - configuration = require('../../../lib/configuration'), - usermanager = require('../../../lib/usermanager'), - database = require('../../../lib/database'), - logger = require('../../../lib/logger'), - defaultOptions = require('./defaults.json'), - bower = require('bower'), - rimraf = require('rimraf'), - async = require('async'), - fs = require('fs'), - ncp = require('ncp').ncp, - mkdirp = require('mkdirp'), - _ = require('underscore'), - util = require('util'), - path = require('path'); +var _ = require('underscore'); +var async = require('async'); +var bower = require('bower'); +var fs = require('fs'); +var mkdirp = require('mkdirp'); +var ncp = require('ncp').ncp; +var path = require('path'); +var rimraf = require('rimraf'); +var util = require('util'); + +var BowerPlugin = require('../bower'); +var configuration = require('../../../lib/configuration'); +var contentmanager = require('../../../lib/contentmanager'); +var database = require('../../../lib/database'); +var logger = require('../../../lib/logger'); +var origin = require('../../../'); +var rest = require('../../../lib/rest'); +var usermanager = require('../../../lib/usermanager'); + +var ContentPlugin = contentmanager.ContentPlugin; +var ContentTypeError = contentmanager.errors.ContentTypeError; + +var defaultOptions = require('./defaults.json'); var bowerConfig = { type: 'menutype', @@ -141,10 +143,10 @@ BowerPlugin.prototype.initialize.call(new Menu(), bowerConfig); app.emit('rebuildCourse', tenantId, courseId); res.statusCode = 200; - return res.json({success: true}); + return res.json({ success: true }); }); }); - }, configuration.getConfig('dbName')); + }, configuration.getConfig('dbName')); }); }); }); diff --git a/plugins/filestorage/localfs/index.js b/plugins/filestorage/localfs/index.js index 1c5e822fbf..119b1f5a54 100644 --- a/plugins/filestorage/localfs/index.js +++ b/plugins/filestorage/localfs/index.js @@ -3,18 +3,19 @@ * Local LocalFileStorage module */ -var FileStorage = require('../../../lib/filestorage').FileStorage, - configuration = require('../../../lib/configuration'), - usermanager = require('../../../lib/usermanager'), - util = require('util'), - fs = require('fs'), - path = require('path'), - mkdirp = require('mkdirp'), - async = require('async'), - probe = require('node-ffprobe'), - logger = require('../../../lib/logger'), - ncp = require('ncp').ncp, - FFMpeg = require('fluent-ffmpeg'); +var async = require('async'); +var util = require('util'); +var FFMpeg = require('fluent-ffmpeg'); +var fs = require('fs'); +var mkdirp = require('mkdirp'); +var ncp = require('ncp').ncp; +var path = require('path'); +var probe = require('node-ffprobe'); + +var configuration = require('../../../lib/configuration'); +var FileStorage = require('../../../lib/filestorage').FileStorage; +var logger = require('../../../lib/logger'); +var usermanager = require('../../../lib/usermanager'); function LocalFileStorage() { this.dataRoot = path.join(configuration.serverRoot, configuration.getConfig('dataRoot')); @@ -37,7 +38,7 @@ LocalFileStorage.prototype.resolvePath = function (relativePath, forceMaster) { if (!forceMaster) { tenantName = user.tenant ? user.tenant.name : configuration.getConfig('masterTenantName'); } else { - tenantName = configuration.getConfig('masterTenantName'); + tenantName = configuration.getConfig('masterTenantName'); } // check that the path isn't already absolute @@ -45,7 +46,7 @@ LocalFileStorage.prototype.resolvePath = function (relativePath, forceMaster) { if (0 === relativePath.indexOf(prefix)) { return relativePath; } - + return path.join(prefix, relativePath); } @@ -73,7 +74,7 @@ LocalFileStorage.prototype.getRelativePath = function (fullPath) { return fullPath.substr(prefix.length); } } - + return fullPath; }; @@ -133,7 +134,7 @@ LocalFileStorage.prototype.createReadStream = function (filePath, options, callb callback = options; options = {}; } - + var forceMaster = (options && options.forceMaster) ? true : false; @@ -185,7 +186,7 @@ LocalFileStorage.prototype.processFileUpload = function (file, newPath, options, newPath = this.resolvePath(newPath); var relativePath = this.getRelativePath(newPath); var self = this; - + // shuffle params if ('function' === typeof options) { cb = options; @@ -211,7 +212,7 @@ LocalFileStorage.prototype.processFileUpload = function (file, newPath, options, mimeType: file.type, size: file.size }; - + // create thumbnail? async.series([ function (nextFunc) { @@ -222,8 +223,8 @@ LocalFileStorage.prototype.processFileUpload = function (file, newPath, options, } nextFunc(); }); - } - + } + return nextFunc(); }, function (nextFunc) { @@ -234,8 +235,8 @@ LocalFileStorage.prototype.processFileUpload = function (file, newPath, options, } nextFunc(); }); - } - + } + return nextFunc(); }, function (nextFunc) { @@ -292,7 +293,7 @@ LocalFileStorage.prototype.getFileStats = function (filePath, callback) { /** * Copies an asset from one tenant to another. - * + * * @param {object} asset - A valid 'asset' record * @param {string} sourceTenantName - Source tenant.name * @param {string} destinationTenantName - Destination tenant.name @@ -410,7 +411,7 @@ LocalFileStorage.prototype.createThumbnail = function (filePath, fileType, optio return next(null, self.getRelativePath(imgThumbPath)); }) .saveToFile(imgThumbPath); - } + } // can't do thumb return next(null, false); From eba495d67fbc06df819abc88af69519e656e1aa4 Mon Sep 17 00:00:00 2001 From: Tom Taylor Date: Mon, 13 Mar 2017 10:04:55 +0000 Subject: [PATCH 009/296] Update version.json and package.json (#1520) * Update version.json * Update package.json * Add TB to contributors * Move dependencies together * Add TG to contributors * Bump framework to 2.0.17 * Remove level of indentation --- package.json | 38 +++++++++++++++++++++++--------------- version.json | 4 ++-- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index c775ee49cd..24a7992885 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "adapt-origin", - "version": "0.2.1", + "name": "adapt_authoring", + "version": "0.3.1", "license": "GPL-3.0", - "description": "Adapt framework authoring tool core application", + "description": "A server-based user interface for authoring eLearning courses using the Adapt Framework.", "keywords": [ "adapt", "authoring", @@ -29,14 +29,14 @@ "name": "Dan Gray", "email": "dan@sinensis.co.uk" }, - { - "name": "Daryl Hedley", - "email": "darylhedley@hotmail.com" - }, { "name": "Dennis Heaney", "email": "dennis@learningpool.com" }, + { + "name": "Daryl Hedley", + "email": "darylhedley@hotmail.com" + }, { "name": "Ryan Lafferty", "email": "ryanl@learningpool.com" @@ -57,15 +57,30 @@ "name": "Brian Quinn", "email": "brian@learningpool.com" }, + { + "name": "Thomas Berger", + "email": "thomas.berger@learnchamp.com" + }, + { + "name": "Tom Greenfield", + "email": "tom.greenfield@kineo.com" + }, { "name": "Thomas Taylor", - "email": "hello@taylortom.co.uk" + "email": "hello@tomtaylor.name" } ], "repository": { "type": "git", "url": "https://github.com/adaptlearning/adapt_authoring.git" }, + "main": "index", + "engines": { + "node": "4.x" + }, + "scripts": { + "test": "make test" + }, "dependencies": { "archiver": "~0.16.0", "async": "0.2.5", @@ -132,13 +147,6 @@ "validator": "4.2.1", "winston": "1.0.2" }, - "main": "index", - "engines": { - "node": "4.x" - }, - "scripts": { - "test": "make test" - }, "devDependencies": { "mocha": "~1.13.0", "phantom": "^0.6.5", diff --git a/version.json b/version.json index 9a69547e41..c4a102800e 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "adapt_authoring": "v0.2.2", - "adapt_framework": "v2.0.7" + "adapt_authoring": "v0.3.1", + "adapt_framework": "v2.0.17" } From 988146e4691fea6335aa86532fd5d84b6d38dd11 Mon Sep 17 00:00:00 2001 From: Tom Taylor Date: Mon, 13 Mar 2017 16:32:27 +0000 Subject: [PATCH 010/296] Only attempt to load routes that are directories (#1535) * Only attempt to load routes that are directories Fixes #1534 * Add message for other errors * Remove duplication --- lib/router.js | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/router.js b/lib/router.js index 02243f1d94..c7bc8f2213 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1,14 +1,11 @@ // LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE -/** - * Module used to set up routes - * - * @module lib/routes - */ - +var _ = require('underscore'); +var async = require('async'); var fs = require('fs'); var path = require('path'); + var configuration = require('./configuration'); -var _ = require('underscore'); +var logger = require('./logger'); /* * CONSTANTS @@ -28,11 +25,25 @@ function Router (options) { Router.prototype.init = function (app) { var basePath = this.options.path; - var routes = fs.readdirSync(basePath); var server = app.server; - routes.forEach (function (routePath) { - var route = require(path.join(basePath, routePath)); - server.use(route); + fs.readdir(basePath, function(error, contents) { + if(error) { + logger.log('error', error); + return; + } + async.each(contents, function(item, cb) { + var itemPath = path.join(basePath, item); + if(!fs.statSync(itemPath).isDirectory()) { + return; + } + try { + var route = require(itemPath); + server.use(route); + } catch(e) { + var detail = (e.code === 'MODULE_NOT_FOUND') ? ', no index.js found' : ` (${e})`; + logger.log('error', `Cannot load routes/${item}${detail}`); + } + }); }); }; From 605ca61cb62eae38037622da2a74f2ebde17add5 Mon Sep 17 00:00:00 2001 From: tomgreenfield Date: Mon, 13 Mar 2017 16:33:14 +0000 Subject: [PATCH 011/296] Clean up language strings (#1574) * Clean up language strings * Remove italics --- .../core/assetManagement/assetManagement.js | 16 +- .../templates/assetManagement.hbs | 4 +- .../assetManagementModalAutofill.hbs | 2 +- .../templates/assetManagementModalFilters.hbs | 4 +- .../assetManagementModalNewAsset.hbs | 4 +- .../templates/assetManagementNewAsset.hbs | 2 +- .../templates/assetManagementSidebar.hbs | 6 +- .../assetManagement/templates/assetPicker.hbs | 6 +- frontend/src/core/modal/templates/modal.hbs | 4 +- .../core/navigation/templates/navigation.hbs | 4 +- .../templates/pluginManagement.hbs | 14 +- .../templates/pluginManagementSidebar.hbs | 10 +- .../templates/pluginManagementUpload.hbs | 2 +- .../pluginManagement/templates/pluginType.hbs | 2 +- .../src/core/project/templates/project.hbs | 4 +- frontend/src/core/scaffold/scaffold.js | 8 +- .../core/sidebar/templates/sidebarFilter.hbs | 4 +- .../src/core/user/templates/userProfile.hbs | 2 +- .../src/core/user/views/userProfileView.js | 2 +- frontend/src/plugins/userManagement/index.js | 2 +- routes/lang/en-application.json | 159 +++++------------- 21 files changed, 92 insertions(+), 169 deletions(-) diff --git a/frontend/src/core/assetManagement/assetManagement.js b/frontend/src/core/assetManagement/assetManagement.js index 2386a9b461..459a58030c 100644 --- a/frontend/src/core/assetManagement/assetManagement.js +++ b/frontend/src/core/assetManagement/assetManagement.js @@ -52,15 +52,13 @@ define(function(require) { Origin.router.navigate('#/assetManagement', {trigger: true}); }); - var globalMenuObject = { - "location": "global", - "text": "Asset Management", - "icon": "fa-file-image-o", - "callbackEvent": "assetManagement:open", - "sortOrder": 2 - }; - Origin.on('app:dataReady login:changed', function() { - Origin.globalMenu.addItem(globalMenuObject); + Origin.globalMenu.addItem({ + "location": "global", + "text": window.polyglot.t('app.assetmanagement'), + "icon": "fa-file-image-o", + "callbackEvent": "assetManagement:open", + "sortOrder": 2 + }); }); }); diff --git a/frontend/src/core/assetManagement/templates/assetManagement.hbs b/frontend/src/core/assetManagement/templates/assetManagement.hbs index 1895932de3..712226e37a 100644 --- a/frontend/src/core/assetManagement/templates/assetManagement.hbs +++ b/frontend/src/core/assetManagement/templates/assetManagement.hbs @@ -1,11 +1,11 @@
- +
-
Select an asset to see a preview here
+
{{t 'app.assetpreviewinstruction'}}
diff --git a/frontend/src/core/assetManagement/templates/assetManagementModalAutofill.hbs b/frontend/src/core/assetManagement/templates/assetManagementModalAutofill.hbs index 74c682d94d..07639f6f00 100644 --- a/frontend/src/core/assetManagement/templates/assetManagementModalAutofill.hbs +++ b/frontend/src/core/assetManagement/templates/assetManagementModalAutofill.hbs @@ -1 +1 @@ -Autofill \ No newline at end of file +{{t 'app.autofill'}} \ No newline at end of file diff --git a/frontend/src/core/assetManagement/templates/assetManagementModalFilters.hbs b/frontend/src/core/assetManagement/templates/assetManagementModalFilters.hbs index 98ad56119f..4e4fe6f289 100644 --- a/frontend/src/core/assetManagement/templates/assetManagementModalFilters.hbs +++ b/frontend/src/core/assetManagement/templates/assetManagementModalFilters.hbs @@ -1,6 +1,6 @@ @@ -11,6 +11,6 @@ \ No newline at end of file diff --git a/frontend/src/core/assetManagement/templates/assetManagementModalNewAsset.hbs b/frontend/src/core/assetManagement/templates/assetManagementModalNewAsset.hbs index 75062289f1..fc249c0a59 100644 --- a/frontend/src/core/assetManagement/templates/assetManagementModalNewAsset.hbs +++ b/frontend/src/core/assetManagement/templates/assetManagementModalNewAsset.hbs @@ -11,7 +11,7 @@ {{#if path}}
- File has been uploaded + {{t 'app.fileuploaded'}}
{{else}} @@ -44,7 +44,7 @@
- +
diff --git a/frontend/src/core/assetManagement/templates/assetManagementNewAsset.hbs b/frontend/src/core/assetManagement/templates/assetManagementNewAsset.hbs index bd4108ab53..537fa29b4b 100644 --- a/frontend/src/core/assetManagement/templates/assetManagementNewAsset.hbs +++ b/frontend/src/core/assetManagement/templates/assetManagementNewAsset.hbs @@ -8,7 +8,7 @@ {{#if path}}
- File has been uploaded + {{t 'app.fileuploaded'}}
{{else}} diff --git a/frontend/src/core/assetManagement/templates/assetManagementSidebar.hbs b/frontend/src/core/assetManagement/templates/assetManagementSidebar.hbs index 575d79cfbb..f3ef27183f 100644 --- a/frontend/src/core/assetManagement/templates/assetManagementSidebar.hbs +++ b/frontend/src/core/assetManagement/templates/assetManagementSidebar.hbs @@ -10,7 +10,7 @@ @@ -20,7 +20,7 @@ @@ -80,7 +80,7 @@ diff --git a/frontend/src/core/assetManagement/templates/assetPicker.hbs b/frontend/src/core/assetManagement/templates/assetPicker.hbs index a30cdf05e4..1de21468e7 100644 --- a/frontend/src/core/assetManagement/templates/assetPicker.hbs +++ b/frontend/src/core/assetManagement/templates/assetPicker.hbs @@ -1,6 +1,6 @@
{{!-- inline search field with close button --}} - + {{/if}} {{#if _shouldShowCancelButton}} {{/if}}
diff --git a/frontend/src/core/navigation/templates/navigation.hbs b/frontend/src/core/navigation/templates/navigation.hbs index 4240002782..a59d879957 100644 --- a/frontend/src/core/navigation/templates/navigation.hbs +++ b/frontend/src/core/navigation/templates/navigation.hbs @@ -21,13 +21,13 @@ {{else}} diff --git a/frontend/src/core/pluginManagement/templates/pluginManagementSidebar.hbs b/frontend/src/core/pluginManagement/templates/pluginManagementSidebar.hbs index fc57b38dd9..5aaaa0b538 100644 --- a/frontend/src/core/pluginManagement/templates/pluginManagementSidebar.hbs +++ b/frontend/src/core/pluginManagement/templates/pluginManagementSidebar.hbs @@ -14,34 +14,34 @@ diff --git a/frontend/src/core/pluginManagement/templates/pluginManagementUpload.hbs b/frontend/src/core/pluginManagement/templates/pluginManagementUpload.hbs index 96ce3c9713..54b3dac649 100644 --- a/frontend/src/core/pluginManagement/templates/pluginManagementUpload.hbs +++ b/frontend/src/core/pluginManagement/templates/pluginManagementUpload.hbs @@ -4,7 +4,7 @@
diff --git a/frontend/src/core/pluginManagement/templates/pluginType.hbs b/frontend/src/core/pluginManagement/templates/pluginType.hbs index 8645c56438..9a32830150 100644 --- a/frontend/src/core/pluginManagement/templates/pluginType.hbs +++ b/frontend/src/core/pluginManagement/templates/pluginType.hbs @@ -22,7 +22,7 @@ {{#if isLocalPackage}} ({{t 'app.uploadedbyuser'}}) {{else}} - + {{/if}} diff --git a/frontend/src/core/project/templates/project.hbs b/frontend/src/core/project/templates/project.hbs index fd97f5ada8..f131d3adac 100644 --- a/frontend/src/core/project/templates/project.hbs +++ b/frontend/src/core/project/templates/project.hbs @@ -35,7 +35,7 @@ {{#if tags.length}}
- +
    @@ -45,7 +45,7 @@ {{/each}}
- +
{{/if}} diff --git a/frontend/src/core/scaffold/scaffold.js b/frontend/src/core/scaffold/scaffold.js index dbf7e8318b..b6b431f92b 100644 --- a/frontend/src/core/scaffold/scaffold.js +++ b/frontend/src/core/scaffold/scaffold.js @@ -209,21 +209,21 @@ define(function(require) { // Setup default fieldsets var fieldsets = { general: { - legend: 'General', + legend: window.polyglot.t('app.general'), fields: [] }, // ::TODO // I want to remove this please properties: { - legend: 'Properties', + legend: window.polyglot.t('app.properties'), fields: [] }, settings :{ - legend: 'Settings', + legend: window.polyglot.t('app.settings'), fields: [] }, extensions: { - legend: 'Extensions', + legend: window.polyglot.t('app.extensions'), fields: ['_extensions'] } }; diff --git a/frontend/src/core/sidebar/templates/sidebarFilter.hbs b/frontend/src/core/sidebar/templates/sidebarFilter.hbs index d8baefcd80..c1a93502b2 100644 --- a/frontend/src/core/sidebar/templates/sidebarFilter.hbs +++ b/frontend/src/core/sidebar/templates/sidebarFilter.hbs @@ -2,10 +2,10 @@