diff --git a/README.md b/README.md index cd30711..1411ca0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ Usage is very easy after you have setup the server at local network. The viewer 1. npm install 2. copy `config-default.js` to `config.js` 3. check config settings and if you don't need local rtmp media server, set `mediaServer` to `false` -4. (edit `/data/meta.json`, add, remove or rename the displays you need or use the defaults) 5. npm start # Default usage diff --git a/app.js b/app.js index 51e9784..8257721 100644 --- a/app.js +++ b/app.js @@ -1,9 +1,10 @@ let express = require('express'); let createError = require('http-errors'); -let path = require('path'); let cookieParser = require('cookie-parser'); let logger = require('morgan'); let lessMiddleware = require('less-middleware'); +let path = require('path'); + const EventEmitter = require('events'); let config = require("./config.js"); @@ -19,6 +20,29 @@ let i18next = require("i18next"); let FilesystemBackend = require("i18next-node-fs-backend"); let i18nextMiddleware = require("i18next-express-middleware"); +let passport = require('passport'); +let LocalStrategy = require('passport-local').Strategy; +let User = require("./modules/db.js"); + +passport.use(new LocalStrategy( + { + + }, + function (username, password, cb) { + User.findByUsername(username, function (err, user) { + if (err) { + return cb(err); + } + if (!user) { + return cb(null, false); + } + if (user.password != password) { + return cb(null, false); + } + return cb(null, user); + }); + })); + if (config.mediaServer) { const {NodeMediaServer} = require('node-media-server'); @@ -40,6 +64,18 @@ if (config.mediaServer) { nms.run(); } +passport.serializeUser(function(user, cb) { + cb(null, user.id); +}); + +passport.deserializeUser(function(id, cb) { + User.findById(id, function (err, user) { + if (err) { return cb(err); } + cb(null, user); + }); +}); + + i18next .use(FilesystemBackend) .use(i18nextMiddleware.LanguageDetector) @@ -50,7 +86,27 @@ i18next }, fallbackLng: config.defaultLocale, preload: ['en', 'fi'], - saveMissing: true + saveMissing: true, + detection: { + // order and from where user language should be detected + order: [/*'path', 'session', */ 'querystring', 'cookie', 'header'], + + // keys or params to lookup language from + lookupQuerystring: 'lng', + lookupCookie: 'i18next', + lookupHeader: 'accept-language', + lookupSession: 'lng', + lookupPath: 'lng', + lookupFromPathIndex: 0, + + // cache user language + caches: false, // ['cookie'] + + // optional expire and domain for set cookie + // cookieExpirationDate: new Date(), + // cookieDomain: 'myDomain', + // cookieSecure: true // if need secure cookie + } }); // view engine setup @@ -63,16 +119,23 @@ app.use(express.json()); app.use(express.urlencoded({extended: false})); app.use(cookieParser()); app.use(lessMiddleware(path.join(__dirname, 'public'))); - app.use(express.static(path.join(__dirname, 'public'))); +app.use(require('express-session')({ secret: config.sessionKey, resave: false, saveUninitialized: true })); + +// Initialize Passport and restore authentication state, if any, from the +// session. +app.use(passport.initialize()); +app.use(passport.session()); let websocket = require("./modules/websocket")(server, app, io, eventDispatcher); let indexRouter = require('./routes/index.js')(websocket, eventDispatcher); let adminRouter = require('./routes/admin.js')(websocket, eventDispatcher); +let authRouter = require('./routes/auth.js')(websocket, eventDispatcher); -app.use('/', indexRouter); +app.use('/', authRouter); app.use('/admin', adminRouter); +app.use('/', indexRouter); // catch 404 and forward to error handler app.use(function (req, res, next) { diff --git a/config-default.js b/config-default.js index d256154..1079d91 100644 --- a/config-default.js +++ b/config-default.js @@ -1,14 +1,76 @@ module.exports = { "serverListenPort": process.env.PORT || 8000, - "serverHost": process.env.HOST || "localhost", - "serverUrl": "http://" + (process.env.HOST || "localhost"), + "serverHost": process.env.HOST || "127.0.0.1", + "serverUrl": "http://" + (process.env.HOST || "127.0.0.1"), // used for web client + "sessionKey": "generateRandomStringForSecret", + "secureViews": false, // set true to use password also for viewing info screen content + "useLocalAssets": false, // used to load javascript libraries locally from /public/assets + "mediaServer": false, // local streaming server for rtmp, see docs how to use + "defaultLocale": "en", + + /* + * Administrators + */ + "admins": [ { - "name": process.env.ADMIN_USER || "admin", - "pass": process.env.ADMIN_PASS || "admin" + "id": 1, + "displayName": "Administrator", + "username": "admin", + "password": "admin", + "permissions": { + "isAdmin": true, + "dashboard": { + "addBundle": true, + "addSlides": true, + "addWebPage": true, + } + } + }, + { + "id": 2, + "displayName": "Display Operator", + "username": "operator", + "password": "operator", + "permissions": { + "isAdmin": true, + "dashboard": { + "addBundle": false, + "addSlides": true, + "addWebPage": false, + } + } + }, + { + "id": 3, + "displayName": "Display Viewer", + "username": "view", + "password": "view", + "permissions": { + "isAdmin": false, + } } ], - "mediaServer": false, - "useLocalAssets": false, - "defaultLocale": "en" + /* + * Displays + * If needed, define more screens + */ + + "displays": [ + { + "id": 1, + "name": "Big Screen", + "bundle": "default" + }, + { + "id": 2, + "name": "Secondary Screen", + "bundle": "set1" + }, + { + "id": 3, + "name": "Kiosk", + "bundle": "default" + } + ] }; diff --git a/data/default/bundle.json b/data/default/bundle.json index 6666645..b1d262d 100644 --- a/data/default/bundle.json +++ b/data/default/bundle.json @@ -1,7 +1,7 @@ { "displayName": "default", "background": "bg.jpg", - "duration": 0, + "duration": 30, "transition": "tiles3d", "useWebFonts": false, "displayTime": true, diff --git a/data/meta.json b/data/meta.json deleted file mode 100644 index 160cebb..0000000 --- a/data/meta.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "bundleNames": [ - { - "dir": "default", - "name": "default" - } - ], - "displays": [ - { - "name": "main screen", - "bundle": "default" - }, - { - "name": "2nd screen", - "bundle": "set1" - }, - { - "name": "3rd screen", - "bundle": "default" - }, - { - "name": "4th screen", - "bundle": "set1" - }, - { - "name": "5th screen", - "bundle": "default" - } - ] -} \ No newline at end of file diff --git a/locales/en/translation.json b/locales/en/translation.json index e6be4d8..c21026e 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -1,5 +1,11 @@ { "infoscreen": "InfoScreen3", + "auth": { + "userName": "Username", + "password": "Password", + "login": "Login", + "logout": "Logout" + }, "actions": { "upload": "Upload", "uploadScale": "Upload and scale 16:9", diff --git a/locales/fi/translation.json b/locales/fi/translation.json index 78781ba..e9d98e8 100644 --- a/locales/fi/translation.json +++ b/locales/fi/translation.json @@ -1,5 +1,11 @@ { "infoscreen": "InfoScreen3", + "auth": { + "userName": "Käyttäjätunnus", + "password": "Salasana", + "login": "Kirjaudu", + "logout": "Kirjaudu ulos" + }, "actions": { "upload": "Lataa", "uploadScale": "Lataa ja skaalaa 16:9", diff --git a/modules/admin.js b/modules/admin.js index a729c39..0deea15 100644 --- a/modules/admin.js +++ b/modules/admin.js @@ -540,13 +540,13 @@ class admin { previewInstances.push({adminId: socket.id, preview: {}, currentView: {}}); let serverOptions = getView(displayId).serverOptions; let bundleDirs = self.bundleManager.getBundleInfos(); - let meta = JSON.parse(fs.readFileSync("./data/meta.json").toString()); + socket.emit("callback.dashboard.sync", { displayId: displayId, bundleDirs: bundleDirs, serverOptions: serverOptions, - displays: meta.displays + displays: config.displays }); } diff --git a/modules/auth.js b/modules/auth.js index be973a3..e69de29 100644 --- a/modules/auth.js +++ b/modules/auth.js @@ -1,28 +0,0 @@ - -let basicAuth = require("basic-auth"); -let config = require("../config.js"); - -module.exports = function (req, res, next) { - function unauthorized(res) { - res.set("WWW-Authenticate", "Basic realm=Authorization Required"); - return res.sendStatus(401); - } - - let user = basicAuth(req); - - if (!user || !user.name || !user.pass) { - return unauthorized(res); - } - - for (let i in config.admins) { - let admin = config.admins[i]; - if (user.name === admin.name && user.pass === admin.pass) { - return next('route'); - } - } - - return unauthorized(res); -}; - - - diff --git a/modules/db.js b/modules/db.js new file mode 100644 index 0000000..be8d84a --- /dev/null +++ b/modules/db.js @@ -0,0 +1,27 @@ +var records = require("../config.js").admins; +module.exports = { + + findById: function(id, cb) { + process.nextTick(function () { + var idx = id - 1; + if (records[idx]) { + cb(null, records[idx]); + } else { + cb(new Error('User ' + id + ' does not exist')); + } + }); + }, + + findByUsername: function(username, cb) { + process.nextTick(function () { + for (var i = 0, len = records.length; i < len; i++) { + var record = records[i]; + if (record.username === username) { + return cb(null, record); + } + } + return cb(null, null); + }); + } + +}; diff --git a/modules/display.js b/modules/display.js index 29e5041..5c526b8 100644 --- a/modules/display.js +++ b/modules/display.js @@ -5,19 +5,19 @@ let bundleManager = require('./bundleManager.js'); /** * handles one display instance - * @module infoscreen3/display + * @module infoscreen/display */ class display { /** * @param {object} sharedIO - socketIO * @param {object} dispatcher - dispatcher - * @param {object} meta - reads from ./data/meta.json --> as display[displayId] + * @param {object} meta - reads from config.displays * @param {number} displayId - this display instances id * @param {object} bundleManager */ constructor(sharedIO, dispatcher, meta, displayId, bundleManager) { - cli.info("Starting display" + displayId + ": " + meta.name + "..."); + cli.info("Starting display with id " + displayId + " ..."); /** @property {Array} timeoutId - holds setTimeout id's for mainLoop */ this.timeoutId = []; @@ -104,7 +104,7 @@ class display { }); // io this.init(meta); - cli.info("done."); + cli.success(meta.name + " started with '" + meta.bundle + "'"); } // display @@ -236,4 +236,5 @@ class display { } } +/** @exports display */ module.exports = display; \ No newline at end of file diff --git a/modules/websocket.js b/modules/websocket.js index 185ab4f..35a60f0 100644 --- a/modules/websocket.js +++ b/modules/websocket.js @@ -1,4 +1,4 @@ -let meta = require("../data/meta.json"); +let availableDisplays = require("../config.js").displays; let display = require("./display.js"); let admin = require("./admin.js"); let cli = require('./cli.js'); @@ -8,12 +8,12 @@ let fs = require('fs'); /** * - * @type {module:infoscreen3/display[]} + * @type {display[]} */ let screenView = []; /** - * @exports infoscreen3/websocket + * @exports websocket */ module.exports = function (server, app, io, dispatcher) { console.log(chalk.green(">> ") + "InfoScreen3" + chalk.green("<<")); @@ -53,7 +53,7 @@ module.exports = function (server, app, io, dispatcher) { cli.info("Starting websocket backends..."); let screenId = 0; - for (let metadata of meta.displays) { + for (let metadata of availableDisplays) { screenView.push(new display(io, dispatcher, metadata, screenId, bundleManager)); screenId += 1; } @@ -80,7 +80,7 @@ module.exports = function (server, app, io, dispatcher) { previewImages.push("/img/nopreview.png"); } } - socket.emit("callback.displays", {displays: meta.displays, previewImages: previewImages}); + socket.emit("callback.displays", {displays: availableDisplays, previewImages: previewImages}); }); }); diff --git a/package-lock.json b/package-lock.json index 00534e6..1d79b63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -82,8 +82,7 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "optional": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "async-limiter": { "version": "1.0.0", @@ -253,7 +252,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "optional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -286,6 +284,11 @@ "busboy": "*" } }, + "connect-ensure-login": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-ensure-login/-/connect-ensure-login-0.1.1.tgz", + "integrity": "sha1-F03MUSQ7nqwj+NmCFa62aU4uihI=" + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -363,8 +366,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "optional": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "depd": { "version": "1.1.2", @@ -541,6 +543,33 @@ } } }, + "express-session": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.1.tgz", + "integrity": "sha512-pWvUL8Tl5jUy1MLH7DhgUlpoKeVPUTe+y6WQD9YhcN0C5qAhsh4a8feVjiUXo3TFhIy191YGZ4tewW9edbl2xQ==", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.2", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -550,8 +579,7 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "optional": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "2.0.1", @@ -790,8 +818,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-schema": { "version": "0.2.3", @@ -920,7 +947,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -1038,11 +1065,38 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, + "passport": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", + "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + } + }, + "passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -1090,6 +1144,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -1153,8 +1212,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safer-buffer": { "version": "2.1.2", @@ -1372,8 +1430,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "twig": { "version": "0.10.3", @@ -1394,6 +1451,14 @@ "mime-types": "~2.1.18" } }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 0367f3c..addd321 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,12 @@ "basic-auth": "^2.0.1", "chalk": "^2.4.2", "connect-busboy": "0.0.2", + "connect-ensure-login": "^0.1.1", "cookie-parser": "^1.4.4", "cors": "^2.8.5", "debug": "~2.6.9", "express": "^4.16.4", + "express-session": "^1.16.1", "http-errors": "~1.6.2", "i18next": "^15.1.0", "i18next-express-middleware": "^1.8.0", @@ -21,6 +23,8 @@ "morgan": "~1.9.0", "node-media-server": "^1.4.15", "node.extend": ">=2.0.1", + "passport": "^0.4.0", + "passport-local": "^1.0.0", "socket.io": "^2.2.0", "twig": "~0.10.3" } diff --git a/public/js/display.js b/public/js/display.js index 353606b..32d0e9e 100644 --- a/public/js/display.js +++ b/public/js/display.js @@ -447,7 +447,10 @@ function getWebLayer(offset) { function clearIFrame(elementId) { var frame = document.getElementById(elementId); - frame.contentWindow.location.href = "/empty"; + + if (frame.contentWindow.location.href !== document.location.origin + "/empty") { + frame.contentWindow.location.href = "/empty"; + } } diff --git a/routes/admin.js b/routes/admin.js index 7c50ca4..b0f7a02 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -1,5 +1,4 @@ let express = require('express'); -let authMiddleWare = require('../modules/auth.js'); let router = express.Router(); let cli = require("../modules/cli.js"); let fs = require('fs'); @@ -7,14 +6,28 @@ let path = require('path'); let config = require("../config.js"); let busboy = require("connect-busboy"); +function ensureIsAdmin(req, res, next) { + + if (!req.isAuthenticated || !req.isAuthenticated()) { + req.session.location = "/admin"; + return res.redirect("/login"); + } else { + if (!req.user.permissions.isAdmin) { + cli.error(req.user.displayName + " has tried to access admin!", "permission error"); + return res.redirect("/login"); + } + } + next(); +} + module.exports = function (websocket, dispatcher) { var bundleManager = websocket.bundleManager; - router.use(authMiddleWare); + router.use(ensureIsAdmin); router.use(busboy({immediate: true})); router.get('/', function (req, res, next) { - res.render('admin/dashboard', {config: config}); + res.render('admin/dashboard', {config: config, permission: req.user.permissions}); }); router.get('/preview', function (req, res, next) { @@ -100,14 +113,12 @@ module.exports = function (websocket, dispatcher) { router.get('/edit/bundleSlides', function (req, res, next) { - // let bundles = getDirectories("./data"); var bundle = {}; try { bundle = bundleManager.getBundle(req.query['bundle']); } catch (err) { - + cli.error(err, "can't find bundle"); } - console.log(bundle); res.render('admin/editBundleSlides', {config: config, bundle: bundle}); }); @@ -129,11 +140,5 @@ module.exports = function (websocket, dispatcher) { res.render('ajax/bundleImageList', {bundleImages: output}); }); - function getDirectories(path) { - return fs.readdirSync(path).filter(function (file) { - return fs.statSync(path + '/' + file).isDirectory(); - }); - } - return router; }; diff --git a/routes/auth.js b/routes/auth.js new file mode 100644 index 0000000..0a302fd --- /dev/null +++ b/routes/auth.js @@ -0,0 +1,32 @@ +let router = require('express').Router(); +let passport = require("passport"); + +module.exports = function (websocket, dispatcher) { + + router.get('/login', function (req, res, next) { + console.log(req.session); + + res.render('auth/login'); + }); + + router.post('/login', + passport.authenticate('local', {failureRedirect: '/login'}), + function (req, res) { + if (req.session.location) { + return res.redirect(req.session.location); + } + return res.redirect("/"); + }); + + router.get('/logout', + function (req, res) { + req.logout(); + res.redirect('/'); + }); + + router.get('/empty', function (req, res, next) { + res.render('empty'); + }); + + return router; +}; \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index bad0869..44ae80c 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,34 +1,38 @@ let express = require('express'); -let authMiddleWare = require('../modules/auth.js'); let router = express.Router(); let fs = require("fs"); let config = require("../config.js"); -let displayMeta = require("../data/meta.json"); +let availableDisplays = config.displays; const cli = require('../modules/cli.js'); +function ensureIsAdmin(req, res, next) { + if (!req.isAuthenticated || !req.isAuthenticated()) { + req.session.location = "/"; + console.log(req.session); + return res.redirect("/login"); + } + return next(); +} + module.exports = function (websocket, dispatcher) { - - router.use(authMiddleWare); - + if (config.secureViews) { + router.use(ensureIsAdmin); + } router.get('/', function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.render('index', {config: config}); }); - router.get('/empty', function (req, res, next) { - res.render('empty'); - }); - router.get('/display/:id/lite', function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); let idx = parseInt(req.params.id); - res.render('liteDisplay', {config: config, display: displayMeta.displays[idx], displayId: idx}); + res.render('liteDisplay', {config: config, display: availableDisplays[idx], displayId: idx}); }); router.get('/display/:id', function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); let idx = parseInt(req.params.id); - res.render('display', {config: config, display: displayMeta.displays[idx], displayId: idx}); + res.render('display', {config: config, display: availableDisplays[idx], displayId: idx}); }); router.get('/images/:dir/:name', function (req, res, next) { @@ -77,7 +81,7 @@ module.exports = function (websocket, dispatcher) { } }; - res.sendFile("display_"+req.params.displayId+".png", options, function (err) { + res.sendFile("display_" + req.params.displayId + ".png", options, function (err) { if (err) { cli.error(err); res.end(); diff --git a/views/admin/dashboard.twig b/views/admin/dashboard.twig index 4e60d1a..4dd3bc9 100644 --- a/views/admin/dashboard.twig +++ b/views/admin/dashboard.twig @@ -45,7 +45,9 @@
@@ -57,9 +59,10 @@