diff --git a/server/app_cfg.js b/server/app_cfg.js index 308be93..a5e96ab 100644 --- a/server/app_cfg.js +++ b/server/app_cfg.js @@ -9,6 +9,7 @@ app_cfg.global = { defaultuser: 'me', defaultpass: '123', saltRounds: 10, + sessionsecret: '0987654321abcdef#xyz', // TODO: eindeutige ID/Version für Anwendung hinterlegen // TODO: Karten-URL für Client festlegen app_id: process.pid diff --git a/server/auth.js b/server/auth.js index f7ed5d5..93c6eb0 100644 --- a/server/auth.js +++ b/server/auth.js @@ -1,27 +1,46 @@ -module.exports = function(app_cfg, db, bcrypt, passport, LocalStrategy) { +module.exports = function (app, app_cfg, db, bcrypt, passport, LocalStrategy) { - // setting up user authentication + var session = require('express-session'); + var SQLiteStore = require('connect-sqlite3')(session); + var LocalStrategy = require('passport-local').Strategy; + + app.use(session({ + store: new SQLiteStore({ + db: app_cfg.global.database, + concurrentDB: true + }), + secret: app_cfg.global.sessionsecret, + resave: false, + saveUninitialized: true, + cookie: { + maxAge: 60 * 60 * 1000 + } // 1 Stunde + })); + + app.use(passport.initialize()); + app.use(passport.session()); + + // Benutzerauthentifizierung passport.use(new LocalStrategy({ usernameField: 'user' - }, function(user, password, done) { - db.get('SELECT password FROM waip_users WHERE user = ?', user, function(err, row) { + }, function (user, password, done) { + db.get('SELECT password FROM waip_users WHERE user = ?', user, function (err, row) { if (!row) return done(null, false); - bcrypt.compare(password, row.password, function(err, res) { + bcrypt.compare(password, row.password, function (err, res) { if (!res) return done(null, false); - db.get('SELECT user, id FROM waip_users WHERE user = ?', user, function(err, row) { - //console.log('got user: '+row+' err: '+ err); + db.get('SELECT user, id FROM waip_users WHERE user = ?', user, function (err, row) { return done(null, row); }); }); }); })); - passport.serializeUser(function(user, done) { + passport.serializeUser(function (user, done) { return done(null, user.id); }); - passport.deserializeUser(function(id, done) { - db.get('SELECT id, user, permissions FROM waip_users WHERE id = ?', id, function(err, row) { + passport.deserializeUser(function (id, done) { + db.get('SELECT id, user, permissions FROM waip_users WHERE id = ?', id, function (err, row) { if (!row) { return done(null, false); } @@ -29,4 +48,17 @@ module.exports = function(app_cfg, db, bcrypt, passport, LocalStrategy) { }); }); -}; + // Funktion die prueft ob der Benutzer angemeldet ist + function ensureAuthenticated(req, res, next) { + if (req.isAuthenticated()) { + // req.user is available for use here + return next(); } + + // denied. redirect to login + res.redirect('/login') + } + + return{ + ensureAuthenticated: ensureAuthenticated + }; +}; \ No newline at end of file diff --git a/server/routing.js b/server/routing.js index 5639816..8c4f610 100644 --- a/server/routing.js +++ b/server/routing.js @@ -1,12 +1,12 @@ -module.exports = function(app, sql, app_cfg, passport) { +module.exports = function (app, sql, app_cfg, passport, auth) { // get index - app.get('/', function(req, res) { - sql.db_list_wachen(function(data) { + app.get('/', function (req, res) { + sql.db_list_wachen(function (data) { var data_wachen = data - sql.db_list_traeger(function(data) { + sql.db_list_traeger(function (data) { var data_traeger = data - sql.db_list_kreis(function(data) { + sql.db_list_kreis(function (data) { var data_kreis = data res.render('home', { title: 'Startseite', @@ -21,15 +21,15 @@ module.exports = function(app, sql, app_cfg, passport) { }); // get /waip - app.get('/waip', function(req, res) { + app.get('/waip', function (req, res) { res.redirect('/waip/0'); }); // get /waip/ // TODO: Abstruz bei unbekannter/falscher Wachennummer - app.get('/waip/:wachen_id', function(req, res, next) { + app.get('/waip/:wachen_id', function (req, res, next) { var parmeter_id = req.params.wachen_id; - sql.db_wache_vorhanden(parmeter_id, function(result) { + sql.db_wache_vorhanden(parmeter_id, function (result) { if (result) { res.render('waip', { title: 'Alarmmonitor', @@ -48,7 +48,7 @@ module.exports = function(app, sql, app_cfg, passport) { // get /ueber - app.get('/ueber', function(req, res) { + app.get('/ueber', function (req, res) { res.render('ueber', { title: 'Über', user: req.user @@ -56,7 +56,7 @@ module.exports = function(app, sql, app_cfg, passport) { }); // get /uhr - app.get('/test_clock', function(req, res) { + app.get('/test_clock', function (req, res) { res.render('test_clock', { title: 'Test Uhr', user: req.user @@ -64,15 +64,26 @@ module.exports = function(app, sql, app_cfg, passport) { }); // get /test_tableau - app.get('/test_tableau', function(req, res) { + app.get('/test_tableau', function (req, res) { res.render('test_wachalarm', { title: 'Test Wachalarm', user: req.user }); }); + // get /show_log + app.get('/show_log', auth.ensureAuthenticated, function (req, res) { + sql.db_get_log(function (data) { + res.render('show_log', { + title: 'Log-Datei', + user: req.user, + dataSet: data + }); + }); + }); + // get /login - app.get('/login', function(req, res) { + app.get('/login', function (req, res) { res.render('login', { title: 'Login', user: req.user @@ -81,25 +92,25 @@ module.exports = function(app, sql, app_cfg, passport) { app.post('/login', passport.authenticate('local', { failureRedirect: '/login' - }), function(req, res) { + }), function (req, res) { res.redirect('/'); }); - app.post('/logout', function(req, res) { - req.session.destroy(function(err) { + app.post('/logout', function (req, res) { + req.session.destroy(function (err) { res.redirect('/'); }) }); // catch 404 and forward to error handler - app.use(function(req, res, next) { + app.use(function (req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handler - app.use(function(err, req, res, next) { + app.use(function (err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; @@ -108,4 +119,4 @@ module.exports = function(app, sql, app_cfg, passport) { res.render('error'); }); -}; +}; \ No newline at end of file diff --git a/server/sql_cfg.js b/server/sql_cfg.js index cb15807..609e30d 100644 --- a/server/sql_cfg.js +++ b/server/sql_cfg.js @@ -1,4 +1,4 @@ -module.exports = function(bcrypt, app_cfg) { +module.exports = function (bcrypt, app_cfg) { // TODO: gegen better-sqlite3 ersetzen @@ -18,7 +18,7 @@ module.exports = function(bcrypt, app_cfg) { // Datenbank bei Neustart bereinigen, oder Datenbank befuellen if (dbExists) { - db.serialize(function() { + db.serialize(function () { // alte Clients (Sockets) bei neustart des Servers entfernen db.run(`DELETE FROM waip_clients`); }); @@ -26,7 +26,7 @@ module.exports = function(bcrypt, app_cfg) { // Datenbankdatei erstellen fs.openSync(dbFile, 'w'); // leere Datenbank befuellen - db.serialize(function() { + db.serialize(function () { // Einsatz-Tabelle erstellen db.run(`CREATE TABLE waip_einsaetze ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, @@ -84,6 +84,11 @@ module.exports = function(bcrypt, app_cfg) { id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, einsatzmittel_typ TEXT, einsatzmittel_rufname TEXT)`); + db.run(`CREATE TABLE waip_log ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, + log_time DATETIME DEFAULT CURRENT_TIMESTAMP, + log_typ TEXT, + log_text TEXT)`); // Default-Wachen speichern db.run(`INSERT OR REPLACE INTO waip_wachen ( nr_wache, nr_traeger, nr_kreis, name_wache, name_traeger, name_kreis) @@ -790,10 +795,10 @@ module.exports = function(bcrypt, app_cfg) { (\'85\',\'KTW\'), (\'88\',\'Rettungsboot\')`); // Benutzer-Tabelle mit Standard-Admin befuellen - bcrypt.hash(app_cfg.global.defaultpass, app_cfg.global.saltRounds, function(err, hash) { - db.run(`INSERT INTO waip_users ( user, password, permissions ) VALUES( ?, ?, 'admin' )`, app_cfg.global.defaultuser, hash, function(err) { + bcrypt.hash(app_cfg.global.defaultpass, app_cfg.global.saltRounds, function (err, hash) { + db.run(`INSERT INTO waip_users ( user, password, permissions ) VALUES( ?, ?, 'admin' )`, app_cfg.global.defaultuser, hash, function (err) { if (err) { - console.log(err); + console.error(err.message); }; }); }); @@ -802,4 +807,4 @@ module.exports = function(bcrypt, app_cfg) { return db; -}; +}; \ No newline at end of file diff --git a/server/sql_qry.js b/server/sql_qry.js index c06bcff..806f610 100644 --- a/server/sql_qry.js +++ b/server/sql_qry.js @@ -338,6 +338,24 @@ module.exports = function(db) { }); }; + function db_log(typ, text) { + db.run(`INSERT INTO waip_log (log_typ, log_text) + VALUES ( + \'` + typ + `\', + \'` + text + `\')`); + //TODO: Log auf 20.000 Datensätze begrenzen + }; + + function db_get_log(callback) { + db.all('select * from waip_log order by log_time DESC', function(err, rows) { + if (err == null && rows) { + callback && callback(rows); + } else { + callback && callback(null); + }; + }); + }; + return { db_einsatz_speichern: db_einsatz_speichern, db_einsatz_laden: db_einsatz_laden, @@ -358,7 +376,9 @@ module.exports = function(db) { db_tts_einsatzmittel: db_tts_einsatzmittel, db_get_socket_by_id: db_get_socket_by_id, db_update_client_status: db_update_client_status, - db_check_client_waipid: db_check_client_waipid + db_check_client_waipid: db_check_client_waipid, + db_log: db_log, + db_get_log: db_get_log }; }; diff --git a/server/udp.js b/server/udp.js index 0ce5728..bf6e8fd 100644 --- a/server/udp.js +++ b/server/udp.js @@ -1,4 +1,4 @@ -module.exports = function(app_cfg, waip_io){ +module.exports = function(app_cfg, waip_io, sql){ // Module laden var dgram = require('dgram'); @@ -18,16 +18,16 @@ module.exports = function(app_cfg, waip_io){ udp_server.bind(app_cfg.global.udpport); udp_server.on('listening', function() { var address = udp_server.address(); - console.log('UDP Server auf ' + address.address + ':' + address.port + ' gestartet.'); + sql.db_log('Anwendung', 'UDP Server auf ' + address.address + ':' + address.port + ' gestartet.'); }); // Warten auf Einsatzdaten udp_server.on('message', function(message, remote) { if (isValidJSON(message)) { - console.log('Neuer Einsatz von ' + remote.address + ':' + remote.port + ': ' + message); + sql.db_log('WAIP','Neuer Einsatz von ' + remote.address + ':' + remote.port + ': ' + message); waip_io.einsatz_speichern(message); } else { - console.log('Fehler: Einsatz von ' + remote.address + ':' + remote.port + ' Fehlerhaft: ' + message); + sql.db_log('Fehler-WAIP', 'Fehler: Einsatz von ' + remote.address + ':' + remote.port + ' Fehlerhaft: ' + message); } }); }; diff --git a/server/waip_io.js b/server/waip_io.js index 934aef8..4ffe09c 100644 --- a/server/waip_io.js +++ b/server/waip_io.js @@ -1,34 +1,34 @@ -module.exports = function(io, sql, async, app_cfg) { +module.exports = function (io, sql, async, app_cfg) { // Socket.IO - io.on('connection', function(socket) { - console.log('Anwendung von ' + socket.request.connection.remoteAddress + ' (' + socket.id + ') geoeffnet'); + io.on('connection', function (socket) { + sql.db_log('WAIP', 'Anwendung von ' + socket.request.connection.remoteAddress + ' (' + socket.id + ') geoeffnet'); io.sockets.to(socket.id).emit('io.version', app_cfg.global.app_id); // disconnect - socket.on('disconnect', function() { - console.log('Alarmmonitor von ' + socket.request.connection.remoteAddress + ' (' + socket.id + ') geschlossen'); + socket.on('disconnect', function () { + sql.db_log('WAIP', 'Alarmmonitor von ' + socket.request.connection.remoteAddress + ' (' + socket.id + ') geschlossen'); sql.db_client_delete(socket.id); }); // Aufruf des Alarmmonitors einer bestimmten Wache verarbeiten - socket.on('wachen_id', function(wachen_id) { - console.log('Alarmmonitor Nr. ' + wachen_id + ' von ' + socket.request.connection.remoteAddress + ' (' + socket.id + ') aufgerufen'); + socket.on('wachen_id', function (wachen_id) { + sql.db_log('WAIP', 'Alarmmonitor Nr. ' + wachen_id + ' von ' + socket.request.connection.remoteAddress + ' (' + socket.id + ') aufgerufen'); // prüfen ob Wachenummer in der Datenbank hinterlegt ist - sql.db_wache_vorhanden(wachen_id, function(result) { + sql.db_wache_vorhanden(wachen_id, function (result) { // wenn die Wachennummer vorhanden/plausibel dann weiter if (result) { // Socket-Room beitreiten - socket.join(wachen_id, function() { + socket.join(wachen_id, function () { // Socket-ID und Client-IP in der Datenbank speichern sql.db_client_save(socket.id, socket.request.connection.remoteAddress, wachen_id); // prüfen ob für diese Wache ein Einsatz vorhanden ist - sql.db_einsatz_vorhanden(wachen_id, function(result_einsatz) { + sql.db_einsatz_vorhanden(wachen_id, function (result_einsatz) { if (result_einsatz) { - console.log('Einsatz ' + result_einsatz[0].waip_einsaetze_ID + ' fuer Wache ' + wachen_id + ' vorhanden'); + sql.db_log('WAIP', 'Einsatz ' + result_einsatz[0].waip_einsaetze_ID + ' fuer Wache ' + wachen_id + ' vorhanden'); //letzten Einsatz verteilen einsatz_verteilen(result_einsatz[0].waip_einsaetze_ID, socket.id, wachen_id); sql.db_update_client_status(socket.id, result_einsatz[0].waip_einsaetze_ID); } else { - console.log('Kein Einsatz fuer Wache ' + wachen_id + ' vorhanden, Standby'); + sql.db_log('WAIP', 'Kein Einsatz fuer Wache ' + wachen_id + ' vorhanden, Standby'); //oder falls kein Einsatz vorhanden ist, dann io.sockets.to(socket.id).emit('io.standby', null); sql.db_update_client_status(socket.id, 'standby'); @@ -36,7 +36,7 @@ module.exports = function(io, sql, async, app_cfg) { }); }); } else { - console.log('Fehler: Wachnnummer ' + wachen_id + 'nicht vorhanden'); + sql.db_log('Fehler-WAIP', 'Fehler: Wachnnummer ' + wachen_id + 'nicht vorhanden'); io.sockets.to(socket.id).emit('io.error', 'Fehler: Wachnnummer \'' + wachen_id + '\' nicht vorhanden!'); }; }); @@ -47,23 +47,23 @@ module.exports = function(io, sql, async, app_cfg) { // Einsatzmeldung in Datenbank speichern function einsatz_speichern(message) { // Einsatzmeldung (JSON) speichern - sql.db_einsatz_speichern(JSON.parse(message), function(waip_id) { + sql.db_einsatz_speichern(JSON.parse(message), function (waip_id) { // nach dem Speichern anhand der waip_id die beteiligten Wachennummern zum Einsatz ermitteln - console.log('DEBUG: ' + waip_id); - sql.db_get_einsatzwachen(waip_id, function(data) { + sql.db_log('WAIP', 'DEBUG: ' + waip_id); + sql.db_get_einsatzwachen(waip_id, function (data) { if (data) { - data.forEach(function(row) { + data.forEach(function (row) { // fuer jede Wache(row.room) die verbundenen Sockets(Clients) ermitteln und Einsatz verteilen var room_stockets = io.sockets.adapter.rooms[row.room]; if (typeof room_stockets !== 'undefined') { - Object.keys(room_stockets.sockets).forEach(function(socketId) { + Object.keys(room_stockets.sockets).forEach(function (socketId) { einsatz_verteilen(waip_id, socketId, row.room); - console.log('Einsatz ' + waip_id + ' wird an ' + socketId + ' (' + row.room + ') gesendet'); + sql.db_log('WAIP', 'Einsatz ' + waip_id + ' wird an ' + socketId + ' (' + row.room + ') gesendet'); }); }; }); } else { - console.log('Fehler: Wache für waip_id ' + waip_id + ' nicht vorhanden!'); + sql.db_log('Fehler-WAIP', 'Fehler: Wache für waip_id ' + waip_id + ' nicht vorhanden!'); }; }); }); @@ -72,22 +72,22 @@ module.exports = function(io, sql, async, app_cfg) { // Einsatz an Client verteilen function einsatz_verteilen(waip_id, socket_id, wachen_nr) { // Einsatzdaten für eine Wache aus Datenbank laden - sql.db_get_einsatzdaten(waip_id, wachen_nr, function(einsatzdaten) { + sql.db_get_einsatzdaten(waip_id, wachen_nr, function (einsatzdaten) { if (einsatzdaten) { // Einsatz senden - console.log('Einsatz ' + waip_id + ' fuer Wache ' + wachen_nr + ' an Socket ' + socket_id + ' gesendet'); + sql.db_log('WAIP', 'Einsatz ' + waip_id + ' fuer Wache ' + wachen_nr + ' an Socket ' + socket_id + ' gesendet'); io.sockets.to(socket_id).emit('io.neuerEinsatz', einsatzdaten); sql.db_update_client_status(socket_id, waip_id); // Sound erstellen - tts_erstellen(app_cfg, socket_id, einsatzdaten, function(tts) { + tts_erstellen(app_cfg, socket_id, einsatzdaten, function (tts) { // Sound senden - console.log('ttsfile: ' + tts); + sql.db_log('WAIP', 'ttsfile: ' + tts); io.sockets.to(socket_id).emit('io.playtts', tts); }); } else { // Standby senden io.sockets.to(socket_id).emit('io.standby', null); - console.log('Kein Einsatz fuer Wache ' + wachen_nr + ' vorhanden, Standby an Socket ' + socket_id + ' gesendet..'); + sql.db_log('WAIP', 'Kein Einsatz fuer Wache ' + wachen_nr + ' vorhanden, Standby an Socket ' + socket_id + ' gesendet..'); sql.db_update_client_status(socket_id, 'standby'); }; }); @@ -108,7 +108,7 @@ module.exports = function(io, sql, async, app_cfg) { var mp3_bell = process.cwd() + app_cfg.global.soundpath + 'bell_short.mp3'; }; // Zusammensetzen der Sprachansage - async.map(JSON.parse(einsatzdaten.em_alarmiert), sql.db_tts_einsatzmittel, function(err, einsatzmittel) { + async.map(JSON.parse(einsatzdaten.em_alarmiert), sql.db_tts_einsatzmittel, function (err, einsatzmittel) { // Grunddaten var tts_text = einsatzdaten.einsatzart + ', ' + einsatzdaten.stichwort; if (einsatzdaten.objekt) { @@ -116,7 +116,6 @@ module.exports = function(io, sql, async, app_cfg) { } else { var tts_text = tts_text + '. ' + einsatzdaten.ort + ', ' + einsatzdaten.ortsteil; }; - //console.log('DEBUG: '+ tts_text); // Einsatzmittel tts_text = tts_text + '. Für ' + einsatzmittel.join(", "); // Unterscheidung nach Sondersignal @@ -152,42 +151,42 @@ module.exports = function(io, sql, async, app_cfg) { var childD = proc.spawn('powershell', commands); childD.stdin.setEncoding('ascii'); childD.stderr.setEncoding('ascii'); - childD.stderr.on('data', function(data) { - console.log(new Error(data)); + childD.stderr.on('data', function (data) { + sql.db_log('Fehler-TTS', data); callback && callback(null); }); - childD.on('exit', function() { + childD.on('exit', function () { callback && callback(mp3_url); }); childD.stdin.end(); } else { - console.log(new Error('OS ist nicht Windows')); + sql.db_log('Fehler-TTS', 'OS ist nicht Windows'); callback && callback(null); }; }); }; // Aufräumen (alle 10 Sekunden) - setInterval(function() { + setInterval(function () { // Nach alten Einsaetzen suchen und diese ggf. loeschen - sql.db_get_alte_einsaetze('5', function(waip_id) { + sql.db_get_alte_einsaetze('5', function (waip_id) { if (waip_id) { - console.log('Einsatz mit der ID ' + waip_id + ' ist veraltet und kann gelöscht werden.') + sql.db_log('WAIP', 'Einsatz mit der ID ' + waip_id + ' ist veraltet und kann gelöscht werden.') //beteiligte Wachen ermitteln - sql.db_get_einsatzwachen(waip_id, function(data) { + sql.db_get_einsatzwachen(waip_id, function (data) { if (data) { - data.forEach(function(row) { + data.forEach(function (row) { // fuer jede Wache(row.room) die verbundenen Sockets(Clients) ermitteln und Standby senden var room_stockets = io.sockets.adapter.rooms[row.room]; if (typeof room_stockets !== 'undefined') { - Object.keys(room_stockets.sockets).forEach(function(socketId) { + Object.keys(room_stockets.sockets).forEach(function (socketId) { // Standby senden // TODO: Standby nur senden, wenn kein anderer (als der zu löschende) Einsatz angezeigt wird - sql.db_check_client_waipid(socketId, waip_id, function(same_id){ + sql.db_check_client_waipid(socketId, waip_id, function (same_id) { if (same_id) { io.sockets.to(socketId).emit('io.standby', null); io.sockets.to(socketId).emit('io.stopaudio', null); - console.log('Standby an Socket ' + socketId + ' gesendet'); + sql.db_log('WAIP', 'Standby an Socket ' + socketId + ' gesendet'); sql.db_update_client_status(socketId, 'standby'); }; }); @@ -196,7 +195,7 @@ module.exports = function(io, sql, async, app_cfg) { }); }; // Einsatz löschen - console.log('Einsatz ' + waip_id + ' wird gelöscht'); + sql.db_log('WAIP', 'Einsatz ' + waip_id + ' wird gelöscht'); sql.db_einsatz_loeschen(waip_id); }); }; @@ -207,12 +206,12 @@ module.exports = function(io, sql, async, app_cfg) { const fs = require('fs'); fs.readdirSync(process.cwd() + app_cfg.global.soundpath).forEach(file => { // nur die mp3s von alten clients loeschen - if ( file.substring(0,4) != 'bell' && file.substring(file.length - 3) == 'mp3' && file.substring(file.length - 8) != '_tmp.mp3') { - sql.db_get_socket_by_id(file.substring(0, file.length - 4), function(data) { + if (file.substring(0, 4) != 'bell' && file.substring(file.length - 3) == 'mp3' && file.substring(file.length - 8) != '_tmp.mp3') { + sql.db_get_socket_by_id(file.substring(0, file.length - 4), function (data) { if (!data) { - fs.unlink(process.cwd() + app_cfg.global.soundpath + file ,function(err){ - if(err) return console.log(err); - console.log(file + ' wurde erfolgreich geloescht'); + fs.unlink(process.cwd() + app_cfg.global.soundpath + file, function (err) { + if (err) return sql.db_log('Fehler-WAIP', err); + sql.db_log('WAIP', file + ' wurde erfolgreich geloescht'); }); }; }); @@ -225,4 +224,4 @@ module.exports = function(io, sql, async, app_cfg) { return { einsatz_speichern: einsatz_speichern }; -}; +}; \ No newline at end of file