Compare commits
No commits in common. "5c26a11023e0b75235d2b21a9546374eeb2f5d98" and "e108be1fb8fc4fcd8cfe936ebc62fc3d4be3353b" have entirely different histories.
5c26a11023
...
e108be1fb8
@ -1,21 +0,0 @@
|
|||||||
const mongoose = require('mongoose');
|
|
||||||
|
|
||||||
|
|
||||||
const UserSchema = mongoose.Schema({
|
|
||||||
// _id: { type: String },
|
|
||||||
name: { type: String, required: true },
|
|
||||||
pwd: { type: String },
|
|
||||||
// hash: { type: String },
|
|
||||||
// salt: { type: String },
|
|
||||||
// type: { type: String },
|
|
||||||
roles: { type: [String], required: true },
|
|
||||||
tags: { type: [String] },
|
|
||||||
// deactivated: { type: Boolean },
|
|
||||||
// participating: { type: [String] },
|
|
||||||
// host: { type: Boolean },
|
|
||||||
bookmarks: { type: [String] },
|
|
||||||
});
|
|
||||||
//tags as index:
|
|
||||||
//UserSchema.index({tags:'text'});
|
|
||||||
|
|
||||||
module.exports = mongoose.model('User', UserSchema);
|
|
@ -58,8 +58,8 @@
|
|||||||
|
|
||||||
<!-- NOTE: Load JQuery, Vue.js, VueRouter, Vuetify -->
|
<!-- NOTE: Load JQuery, Vue.js, VueRouter, Vuetify -->
|
||||||
<script src="lib/jquery-3.3.1.min.js"></script>
|
<script src="lib/jquery-3.3.1.min.js"></script>
|
||||||
<script src="lib/vue-2.6.10.js"></script>
|
<script src="lib/vue.js"></script>
|
||||||
<script src="lib/vue-router-3.0.1.js"></script>
|
<script src="lib/vue-router.js"></script>
|
||||||
|
|
||||||
<!-- Buefy/Vuetify -->
|
<!-- Buefy/Vuetify -->
|
||||||
<script src="lib/buefy-0.7.5.js"></script>
|
<script src="lib/buefy-0.7.5.js"></script>
|
||||||
|
268
server.js
268
server.js
@ -3,162 +3,105 @@
|
|||||||
*
|
*
|
||||||
* Requires express >= 4
|
* Requires express >= 4
|
||||||
*/
|
*/
|
||||||
var common = require ('./server/common'),
|
|
||||||
authorize = require ('./server/authorization');
|
|
||||||
/*
|
/*
|
||||||
|
var common = require ('./server/common'),
|
||||||
|
authorize = require ('./server/authorization'),
|
||||||
dbs = require ('./server/dbs'),
|
dbs = require ('./server/dbs'),
|
||||||
files = require ('./server/files');
|
files = require ('./server/files');
|
||||||
*/
|
*/
|
||||||
const fs = common.fs, // file sync, read certificates
|
var fs = require ('fs'),
|
||||||
http = common.http, // http handler
|
http = require ('http'),
|
||||||
https = require ('https'), // https handler
|
https = require ('https'),
|
||||||
express = require ('express'), // node server framework
|
express = require ('express'),
|
||||||
session = require ('express-session'), // session management (security)
|
session = require ('express-session'), // session management
|
||||||
morgan = require ('morgan'), // logger
|
morgan = require ('morgan'), // logger
|
||||||
//serveFavicon = require ('serve-favicon'),
|
//serveFavicon = require ('serve-favicon'),
|
||||||
bodyParser = require ('body-parser'), // post request bodyparser
|
bodyParser = require ('body-parser');
|
||||||
MongoStore = require ('connect-mongo')(session), // use mongodb as session storage
|
//MongoStore = require ('connect-mongo')(session); // uss mongodb as session storage
|
||||||
Message = require('./database/message.model.js');
|
var Message = require('./message.model.js');
|
||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
|
|
||||||
|
var http_port=8013;
|
||||||
|
https_port=8889;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Init
|
* Init
|
||||||
*/
|
*/
|
||||||
|
/*ll
|
||||||
common .init ();
|
common .init ();
|
||||||
authorize.init (common);
|
authorize.init (common);
|
||||||
//dbs .init (common);
|
dbs .init (common);
|
||||||
//files .init (common);
|
files .init (common);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Security
|
||||||
/*
|
app.disable ('x-powered-by'); // TODO: Disable Header information: Powerd by Express -> Information disclosure
|
||||||
* Security
|
|
||||||
*
|
|
||||||
* TODO: Install helmet
|
|
||||||
* https://expressjs.com/de/advanced/best-practice-security.html
|
|
||||||
*
|
|
||||||
* (Disable Header information: Powerd by Express)
|
|
||||||
* -> Information disclosure
|
|
||||||
*/
|
|
||||||
app.disable ('x-powered-by');
|
|
||||||
|
|
||||||
// Session Management
|
|
||||||
app.set('trust proxy', 1) // trust first proxy, neccessary for cookie secure: true flag
|
|
||||||
app.use (session({
|
|
||||||
secret: 'ahhgylhuvh', // caesar(3) 2 letter surname
|
|
||||||
resave: false,
|
|
||||||
saveUninitialized: false,
|
|
||||||
cookie: {
|
|
||||||
maxAge: 30*24*3600*1000, // TODO: ttl for session as well (Store)
|
|
||||||
secure: true, // true for https only (since our app works only with https)
|
|
||||||
},
|
|
||||||
name: 'om.sid',
|
|
||||||
store: new MongoStore ({mongooseConnection: common.mongoose.connection, ttl: 30*24*3600}), // mongoose + connect-mongo
|
|
||||||
//store: new MemoryStore ({checkPeriod: 24*3600*1000}), // memorystore
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Route Control
|
* Route Control
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Logger
|
||||||
|
app.use (morgan ('dev'));
|
||||||
|
//app.use(express.logger ( { format: 'default', stream: output_stream } ));
|
||||||
|
|
||||||
// Fastpaths
|
// Fastpaths
|
||||||
//app.use (serveFavicon (__dirname + '/public/favicon.ico'));
|
//app.use (serveFavicon (__dirname + '/public/favicon.ico'));
|
||||||
|
|
||||||
|
// Session Management
|
||||||
|
app.use (session({
|
||||||
|
secret: 'adluhohks',
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
cookie: {
|
||||||
|
maxAge: 30*24*3600*1000, // TODO: ttl for session as well (Store)
|
||||||
|
secure: false, // true for https only
|
||||||
|
},
|
||||||
|
name: 'om.sid',
|
||||||
|
//store: new MongoStore ({mongooseConnection: dbs.mongoose.connection, ttl: 30*24*3600}), // mongoose + connect-mongo
|
||||||
|
//store: new MemoryStore ({checkPeriod: 24*3600*1000}), // memorystore
|
||||||
|
}));
|
||||||
|
|
||||||
// Minimal Logging
|
// Args
|
||||||
//app.use (morgan ('dev'));
|
|
||||||
// Advanced Logging
|
|
||||||
morgan.token ('user', function (req, res) { return (req.session && req.session.user) || '-'; });
|
|
||||||
morgan.token ('userColored', function (req, res) {
|
|
||||||
var color = 0;
|
|
||||||
if (req.session && req.session.roles)
|
|
||||||
color = req.session.roles.admin ? 31 // red
|
|
||||||
: req.session.roles.user ? 34 // blue
|
|
||||||
: 0; // no color
|
|
||||||
return '\x1b[' + color + 'm' + ((req.session && req.session.user) || '-') + '\x1b[0m';
|
|
||||||
});
|
|
||||||
morgan.token ('statusColored', function (req, res) {
|
|
||||||
var color = res.statusCode >= 500 ? 31 // red
|
|
||||||
: res.statusCode >= 400 ? 33 // yellow
|
|
||||||
: res.statusCode >= 300 ? 36 // cyan
|
|
||||||
: res.statusCode >= 200 ? 32 // green
|
|
||||||
: 0; // no color
|
|
||||||
return '\x1b[' + color + 'm' + (res.headersSent ? res.statusCode : '-') + '\x1b[0m';
|
|
||||||
});
|
|
||||||
app.use (morgan (':date[iso] :statusColored :method :url :userColored :response-time ms :res[content-length]'));
|
|
||||||
|
|
||||||
// BodyParser
|
|
||||||
// Returns middleware that only parses json bodies.
|
|
||||||
// (https://www.npmjs.com/package/body-parser#bodyparserjsonoptions)
|
|
||||||
app.use (bodyParser.json());
|
app.use (bodyParser.json());
|
||||||
// Returns middleware that only parses urlencoded bodies
|
|
||||||
// with qs library (https://www.npmjs.com/package/qs#readme)
|
|
||||||
app.use (bodyParser.urlencoded({extended: true}));
|
app.use (bodyParser.urlencoded({extended: true}));
|
||||||
|
|
||||||
// API
|
// API
|
||||||
var api_routes = express.Router(); // express app-object routing
|
//var api_routes = express.Router(); // express app-object routing
|
||||||
|
//app.use ('/api', api_routes);
|
||||||
|
|
||||||
app.use ('/api', api_routes);
|
app.use (function (req, res, done) {
|
||||||
|
console.log(req.url);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
//global.__basedir = __dirname;
|
||||||
|
|
||||||
// Static Files
|
// Static Files
|
||||||
// Allow server access to 'public' folder
|
app.use(express.static(__dirname + '/public')); // Allow server access to 'public' folder
|
||||||
app.use(express.static(__dirname + '/public'));
|
|
||||||
|
|
||||||
// Other stuff is NOT authorized unless logged in
|
//app.use(express.static('resources'));
|
||||||
//app.use (authorize.genCheckAuthorized ('user'));
|
|
||||||
|
|
||||||
// Uploaded files
|
|
||||||
//app.use ('/uploads', express.static(__dirname + '/uploads'));
|
|
||||||
|
|
||||||
// Configuring the database
|
// Configuring the database
|
||||||
//var dbConfig = require('./mongodb.config.js');
|
var dbConfig = require('./mongodb.config.js');
|
||||||
|
var mongoose = require('mongoose');
|
||||||
|
|
||||||
common.mongoose.Promise = global.Promise;
|
mongoose.Promise = global.Promise;
|
||||||
|
|
||||||
// Connecting to the database
|
// Connecting to the database
|
||||||
// Local db: common.config.dbLocalConn
|
//mongoose.connect(`mongodb://${server}/${dbConfig.url}`)
|
||||||
// Efi db: common.config.dbConn
|
mongoose.connect(dbConfig.url, {useNewUrlParser: true}).then(() => {
|
||||||
common.mongoose.connect (common.config.dbLocalConn, {useNewUrlParser: true}) .then( () => {
|
|
||||||
console.log("Successfully connected to MongoDB.");
|
console.log("Successfully connected to MongoDB.");
|
||||||
}).catch( err => {
|
}).catch(err => {
|
||||||
console.log('Could not connect to MongoDB.');
|
console.log('Could not connect to MongoDB.');
|
||||||
process.exit();
|
process.exit();
|
||||||
});
|
});
|
||||||
|
|
||||||
// No error so far? Then it's a 404!
|
|
||||||
//app.use (function (req, res, next) { next (common.genError (404, req.url)); });
|
|
||||||
//app.use (routes.errorHandler (true)); /* true: show stack traces */
|
|
||||||
|
|
||||||
|
//require('./app/routes/message.route.js')(app);
|
||||||
/*
|
|
||||||
* API
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
// API allowed for all
|
|
||||||
api_routes.post ('/login', authorize.login); // /api/login
|
|
||||||
|
|
||||||
// Validate all other API calls
|
|
||||||
api_routes.use (authorize.genCheckAuthorized ('user'));
|
|
||||||
api_routes.post ('/logout', authorize.logout);
|
|
||||||
|
|
||||||
function addRoutes (r) {
|
|
||||||
for (var e in r.routes) {
|
|
||||||
var params = r.routes[e].params ? "/" + r.routes[e].params : "";
|
|
||||||
console.log ("Adding routes for /" + e + params + ":" +
|
|
||||||
(r.routes[e].get ? " get":" ") + (r.routes[e].post ? " post":" ") +
|
|
||||||
(r.routes[e].put ? " put":" ") + (r.routes[e].delete ? " delete":" "));
|
|
||||||
if (r.routes[e].get)
|
|
||||||
api_routes.get ('/' + e + params, r.routes[e].get);
|
|
||||||
if (r.routes[e].post)
|
|
||||||
api_routes.post ('/' + e + params, r.routes[e].post);
|
|
||||||
if (r.routes[e].put)
|
|
||||||
api_routes.put ('/' + e + params, r.routes[e].put);
|
|
||||||
if (r.routes[e].delete)
|
|
||||||
api_routes.delete ('/' + e + params, r.routes[e].delete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
app.get ('/api/ids', function (req, res) {
|
app.get ('/api/ids', function (req, res) {
|
||||||
Message.find({},{id: true}) .exec () .then(results => {
|
Message.find({},{id: true}) .exec () .then(results => {
|
||||||
@ -226,17 +169,62 @@ app.post("/api/createMsg", function(req, res){
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Other stuff is NOT authorized unless logged in
|
||||||
|
//app.use (authorize.genCheckAuthorized ('user'));
|
||||||
|
|
||||||
|
// Uploaded files
|
||||||
|
//app.use ('/uploads', expr ess.static(__dirname + '/uploads'));
|
||||||
|
|
||||||
|
// Other stuff is NOT authorized unless logged in
|
||||||
|
//app.use (authorize.genCheckAuthorized ('user'));
|
||||||
|
|
||||||
|
// Uploaded files
|
||||||
|
//app.use ('/uploads', express.static(__dirname + '/uploads'));
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
// No error so far? Then it's a 404!
|
||||||
|
//app.use (function (req, res, next) { next (common.genError (404, req.url)); });
|
||||||
|
//app.use (routes.errorHandler (true)); /* true: show stack traces */ // TODO: Error Handler
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* API
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
// API allowed for all
|
||||||
|
api_routes.post ('/login', authorize.login); // /api/login
|
||||||
|
|
||||||
|
// Validate all other API calls
|
||||||
|
api_routes.use (authorize.genCheckAuthorized ('user'));
|
||||||
|
api_routes.post ('/logout', authorize.logout);
|
||||||
|
|
||||||
|
function addRoutes (r) {
|
||||||
|
for (var e in r.routes) {
|
||||||
|
var params = r.routes[e].params ? "/" + r.routes[e].params : "";
|
||||||
|
console.log ("Adding routes for /" + e + params + ":" +
|
||||||
|
(r.routes[e].get ? " get":" ") + (r.routes[e].post ? " post":" ") +
|
||||||
|
(r.routes[e].put ? " put":" ") + (r.routes[e].delete ? " delete":" "));
|
||||||
|
if (r.routes[e].get)
|
||||||
|
api_routes.get ('/' + e + params, r.routes[e].get);
|
||||||
|
if (r.routes[e].post)
|
||||||
|
api_routes.post ('/' + e + params, r.routes[e].post);
|
||||||
|
if (r.routes[e].put)
|
||||||
|
api_routes.put ('/' + e + params, r.routes[e].put);
|
||||||
|
if (r.routes[e].delete)
|
||||||
|
api_routes.delete ('/' + e + params, r.routes[e].delete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addRoutes (dbs);
|
addRoutes (dbs);
|
||||||
addRoutes (admin);
|
|
||||||
addRoutes (files);
|
addRoutes (files);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Servers
|
* Servers
|
||||||
*/
|
*/
|
||||||
http.createServer (app) .listen (common.config.httpPort, function () {
|
|
||||||
console.log ("Express http server listening on port " + common.config.httpPort);
|
http.createServer (app) .listen (http_port, function () {
|
||||||
|
console.log ("Express http server listening on port " + http_port);
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -250,36 +238,36 @@ http.createServer (app) .listen (common.config.httpPort, function () {
|
|||||||
* openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
|
* openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
|
||||||
* rm certrequest.csr
|
* rm certrequest.csr
|
||||||
*/
|
*/
|
||||||
if (common.config.httpsPort) {
|
|
||||||
var options;
|
var options;
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
// In case it's a real certificate: add CA chain cersts (TODO: use array if required)
|
// In case it's a real certificate: add CA chain cersts (TODO: use array if required)
|
||||||
var ca = fs.readFileSync ('keys/ca_cert.pem');
|
var ca = fs.readFileSync ('keys/ca_cert.pem');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ca = undefined;
|
ca = undefined;
|
||||||
console.log ("Note: Can't read CA bundle: "+e);
|
console.log ("Note: Can't read CA bundle: "+e);
|
||||||
}
|
}
|
||||||
if (ca != undefined) {
|
if (ca != null) {
|
||||||
options = {
|
|
||||||
key: fs.readFileSync ('keys/omkey.pem'),
|
options = {
|
||||||
cert: fs.readFileSync ('keys/certificate.pem'),
|
key: fs.readFileSync ('keys/omkey.pem'),
|
||||||
ca: ca
|
cert: fs.readFileSync ('keys/certificate.pem'),
|
||||||
};
|
ca: ca
|
||||||
https.createServer (options, app) .listen (common.config.httpsPort, function () {
|
};
|
||||||
console.log ("Express https server listening on port " + common.config.httpsPort);
|
https.createServer (options, app) .listen (https_port, function () {
|
||||||
});
|
console.log ("Express https server listening on port " + https_port);
|
||||||
}
|
});
|
||||||
} catch (e) {
|
|
||||||
console.log ("Note: Can't read SSL keys/certs: "+e+"\nDisabling https server");
|
|
||||||
}
|
}
|
||||||
} else {
|
} catch (e) {
|
||||||
console.log("Note: https server disabled by config");
|
console.log ("Note: Can't read SSL keys/certs: "+e+"\nDisabling https server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Uncaught Exceptions
|
* Uncaught Exceptions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
process.on ("uncaughtException", function (err) {
|
process.on ("uncaughtException", function (err) {
|
||||||
console.error ("*** Uncaught Exception:");
|
console.error ("*** Uncaught Exception:");
|
||||||
console.error (err.stack);
|
console.error (err.stack);
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Authorization
|
|
||||||
*/
|
|
||||||
|
|
||||||
var common, User;
|
|
||||||
const ldap = require ('./ldap_ohm');
|
|
||||||
//const crypto = require ("./crypto");
|
|
||||||
|
|
||||||
// deactivated is not used yet
|
|
||||||
const serverVisibleSession = { user: true, name: true, type: true, mail: true, roles: true, deactivated: true, host: true };
|
|
||||||
const clientVisibleSession = { user: true, name: true, type: true, mail: true, roles: true };
|
|
||||||
|
|
||||||
|
|
||||||
// Fill in session object
|
|
||||||
function fillSession (req, user, roles, cb) {
|
|
||||||
if (req.session === undefined)
|
|
||||||
next (common.genError (500, "Error"));
|
|
||||||
req.session.regenerate (function (err) {
|
|
||||||
if (user !== undefined && ! err) {
|
|
||||||
common.shallowCopy (user, serverVisibleSession, {roles: true}, req.session);
|
|
||||||
if (user._id) {
|
|
||||||
req.session.user = user._id;
|
|
||||||
}
|
|
||||||
req.session.roles = roles;
|
|
||||||
}
|
|
||||||
return cb (err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const authorization = {
|
|
||||||
// Generate Error object suitible for throwing or next()ing
|
|
||||||
genCheckAuthorized: function (group) {
|
|
||||||
return function (req, res, next) {
|
|
||||||
if (req.session === undefined || req.session.user === undefined ||
|
|
||||||
req.session.roles === undefined)
|
|
||||||
return next (common.genError (403, "Unauthorized"));
|
|
||||||
if (req.session.roles[group] === undefined)
|
|
||||||
return next (common.genError (403, "Unauthorized"));
|
|
||||||
next ();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Login route: requires .user and .pwd params
|
|
||||||
login: function (req, res, next) {
|
|
||||||
var user = req.body.user || '';
|
|
||||||
var pwd = req.body.pwd || '';
|
|
||||||
|
|
||||||
// Helper: Return valid session Object
|
|
||||||
function returnSession () {
|
|
||||||
// Only export client visible parts of session object
|
|
||||||
var copy = common.shallowCopy (req.session, clientVisibleSession);
|
|
||||||
return res.json (copy);
|
|
||||||
}
|
|
||||||
// Helper: Return error
|
|
||||||
function returnError () {
|
|
||||||
fillSession (req, undefined, undefined, function (err) {
|
|
||||||
next (common.genError (401, "Unauthorized"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Auth: validate session ID
|
|
||||||
// Check whether to just validate current session ID
|
|
||||||
if (user === '' && pwd === '') {
|
|
||||||
console.log ("auth revalidate: " + req.session.user);
|
|
||||||
if (req.session.user === undefined)
|
|
||||||
return returnError();
|
|
||||||
return returnSession ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// check local database
|
|
||||||
User.findById (req.body.user) .exec (function (err, entry) {
|
|
||||||
// If there is a local user AND it has a password associated, test against this, and only this
|
|
||||||
/*
|
|
||||||
if (entry != null && entry.pwd) {
|
|
||||||
if (crypto.checkLocalAuth (entry, req.body.pwd)) {
|
|
||||||
return fillSession (req, entry, common.arrayToHash(entry.roles), returnSession);
|
|
||||||
}
|
|
||||||
return returnError ();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// check ldap
|
|
||||||
ldap.authorize (user.toLowerCase(), pwd, function (found) {
|
|
||||||
console.log ("ldap authorize " + user + " returns " + JSON.stringify (found));
|
|
||||||
// No ldap entry either -> unauthorized
|
|
||||||
if (found == null) {
|
|
||||||
return returnError ();
|
|
||||||
}
|
|
||||||
// If there is an entry w/o password, use it for roles etc.
|
|
||||||
if (entry) {
|
|
||||||
if (! entry.name || entry.name === "")
|
|
||||||
entry.name = found.name;
|
|
||||||
if (! entry.mail || entry.mail === "")
|
|
||||||
entry.mail = found.mail;
|
|
||||||
if (! entry.type || entry.type === "")
|
|
||||||
entry.type = found.type;
|
|
||||||
if (! entry.orclgender || entry.orclgender === "")
|
|
||||||
entry.orclgender = found.orclgender;
|
|
||||||
return fillSession (req, entry, entry.roles.length > 0 ? common.arrayToHash(entry.roles) : {user:true}, returnSession);
|
|
||||||
}
|
|
||||||
// Otherwise create standard user entry
|
|
||||||
return fillSession (req, found, {user:true}, returnSession);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
logout: function (req, res, next) {
|
|
||||||
fillSession (req, undefined, undefined, function (err) {
|
|
||||||
return res.json ({});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
init: function (_common) {
|
|
||||||
common = _common;
|
|
||||||
ldap.init (_common);
|
|
||||||
User = require('../database/user.model.js');;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = authorization;
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Common functions and imports
|
|
||||||
*/
|
|
||||||
|
|
||||||
var common = {
|
|
||||||
fs: require('fs'), // file sync
|
|
||||||
http: require('http'),
|
|
||||||
mongoose: require('mongoose'), // Needed for db connection.
|
|
||||||
//util: require('util'), // Why is it needed here?
|
|
||||||
//fork: require('child_process') .fork, // What does that?
|
|
||||||
|
|
||||||
// Generate Error object suitible for throwing or next()ing
|
|
||||||
// For a better exception handling
|
|
||||||
genError: function (code, message) {
|
|
||||||
var err = new Error (common.http.STATUS_CODES[code] + (message != undefined && message != "" ? ": "+message : ""));
|
|
||||||
err.status = code;
|
|
||||||
// to generally disable stack traces for these manually created error Objects:
|
|
||||||
delete err.stack;
|
|
||||||
return err;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Generate deep copy
|
|
||||||
// Only include properties incl (all if undefined), strip properties excl (associative arrays)
|
|
||||||
deepCopy: function (inp, incl, excl) {
|
|
||||||
// For now, JSON is considered fastest / easiest
|
|
||||||
var obj = JSON.parse (JSON.stringify (inp));
|
|
||||||
if (incl) {
|
|
||||||
for (var k in obj) {
|
|
||||||
if (incl[k] === undefined)
|
|
||||||
delete obj[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (excl) {
|
|
||||||
for (var k in excl) {
|
|
||||||
delete obj[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Create shallow (1 level) copy of object, use obj if already present (merge)
|
|
||||||
// Only include properties incl (all if undefined), strip properties excl (associative arrays)
|
|
||||||
shallowCopy: function (inp, incl, excl, obj) {
|
|
||||||
var keys = inp;
|
|
||||||
if (obj === undefined)
|
|
||||||
obj = {};
|
|
||||||
if (typeof inp == "array")
|
|
||||||
obj = [];
|
|
||||||
if (incl !== undefined)
|
|
||||||
keys = incl;
|
|
||||||
for (var k in keys) {
|
|
||||||
if (inp[k] !== undefined && (excl === undefined || ! excl[k]))
|
|
||||||
obj[k] = inp[k];
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Create hash of 'true' entries for array/mongoose object
|
|
||||||
arrayToHash: function (array) {
|
|
||||||
var hash = {};
|
|
||||||
for (var e=0; e < array.length; e++) {
|
|
||||||
hash[array[e]] = true;
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Log output session cookie
|
|
||||||
debug: function (req) {
|
|
||||||
console.log ("- " + req.headers.cookie + "\n+ " + req.session.id + "\n " + JSON.stringify (req.session));
|
|
||||||
},
|
|
||||||
|
|
||||||
// Init config data
|
|
||||||
init: function () {
|
|
||||||
this.config = JSON.parse (this.fs.readFileSync ("server_config.json"));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = common;
|
|
@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* Valdiate ohm logins with ldap service
|
|
||||||
*/
|
|
||||||
const ldap = require('ldapjs');
|
|
||||||
const ldap_escape = require('ldap-escape');
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: Where do I get the URL from?? A: Is given.
|
|
||||||
var ldap_client = ldap.createClient({
|
|
||||||
//url: 'ldap://gso2.ads1.fh-nuernberg.de/',
|
|
||||||
url: 'ldap://sso.cs.ohm-hochschule.de:389/',
|
|
||||||
//url: 'ldaps://sso.cs.ohm-hochschule.de:636/',
|
|
||||||
reconnect: true,
|
|
||||||
// timeouts don't work reliably
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: Where do I get the 'bindpath' parameters info from? A: Is given.
|
|
||||||
const ldap_config = {
|
|
||||||
bindpath: 'cn=Users,dc=ohm-hochschule,dc=de',
|
|
||||||
timeout: 2000
|
|
||||||
};
|
|
||||||
|
|
||||||
const ldap_ohm = {
|
|
||||||
init: function () {
|
|
||||||
},
|
|
||||||
|
|
||||||
// Authorize user with password
|
|
||||||
// Calls callback with null if unauthorized
|
|
||||||
// Calls callback with object describing user if successful:
|
|
||||||
authorize: function (user, pwd, cb) {
|
|
||||||
if (typeof user != 'string' || typeof pwd != 'string')
|
|
||||||
return cb (null);
|
|
||||||
// Empty passwords *may* bind successfully anonymously
|
|
||||||
if (user.length < 1 || pwd.length < 1)
|
|
||||||
return cb (null);
|
|
||||||
|
|
||||||
/* Same function, different writing style */
|
|
||||||
/* Escape ldap login input */
|
|
||||||
//escaped = ldap_escape.dn`cn=${user},`+ldap_config.bindpath;
|
|
||||||
escaped = ldap_escape.dn (['cn=',','+ldap_config.bindpath], user);
|
|
||||||
|
|
||||||
// Timeout handler: call callback,
|
|
||||||
// make sure later ldap returns don't do anything weird
|
|
||||||
var return_object = {};
|
|
||||||
var timeoutHandle = setTimeout (function () {
|
|
||||||
console.log('ldap timeout');
|
|
||||||
return_object = null;
|
|
||||||
cb (null);
|
|
||||||
}, ldap_config.timeout);
|
|
||||||
|
|
||||||
// Bind ldap to user (authorize)
|
|
||||||
ldap_client.bind (escaped, pwd, function (err, res) {
|
|
||||||
if (return_object === null)
|
|
||||||
return; // Timeout, cb has already been called
|
|
||||||
if (err !== null) {
|
|
||||||
console.log ("ldap bind: failed for user " + user + ": " + err);
|
|
||||||
clearTimeout (timeoutHandle);
|
|
||||||
return cb (null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for user entry of just bound user
|
|
||||||
// There should be only one...
|
|
||||||
ldap_client.search (escaped, { sizeLimit: 1 }, function (err, res) {
|
|
||||||
if (return_object === null)
|
|
||||||
return; // Timeout, cb has already been called
|
|
||||||
if (err !== null) {
|
|
||||||
console.log ("ldap search: search after bind didn't work for user "
|
|
||||||
+ user + ": " + err);
|
|
||||||
clearTimeout (timeoutHandle);
|
|
||||||
return cb (null);
|
|
||||||
}
|
|
||||||
// Populate return with search results
|
|
||||||
res.on('searchEntry', function(entry) {
|
|
||||||
if (return_object === null)
|
|
||||||
return; // Timeout, cb has already been called
|
|
||||||
return_object.user = user;
|
|
||||||
return_object.name = entry.object.displayname;
|
|
||||||
return_object.type = entry.object.employeetype;
|
|
||||||
return_object.mail = entry.object.mail;
|
|
||||||
return_object.gender = entry.object.orclgender;
|
|
||||||
|
|
||||||
// Calling cb here, not in 'end', because of potential bugs with
|
|
||||||
// concurrency failures, and we have our single(!) entry
|
|
||||||
// https://github.com/joyent/node-ldapjs/pull/424
|
|
||||||
clearTimeout (timeoutHandle);
|
|
||||||
if (typeof return_object.mail != 'string' || return_object.mail.length < 1) {
|
|
||||||
console.log("ldap search error after bind for user " + user);
|
|
||||||
return cb (null);
|
|
||||||
}
|
|
||||||
return cb (return_object);
|
|
||||||
});
|
|
||||||
res.on('error', function(err) {
|
|
||||||
console.log('ldap error: ' + err.message);
|
|
||||||
});
|
|
||||||
res.on('end', function(result) {
|
|
||||||
// TODO: Did we forget something?
|
|
||||||
// TODO: analyze result.status?
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = ldap_ohm;
|
|
@ -1,35 +0,0 @@
|
|||||||
// Terminal call: node server/ldap_test.js - needs VPN or eduroam
|
|
||||||
const inquirer = require('inquirer'),
|
|
||||||
ldap = require('./ldap_ohm.js');
|
|
||||||
|
|
||||||
inquirer.prompt([
|
|
||||||
{
|
|
||||||
name: 'username',
|
|
||||||
type: 'input',
|
|
||||||
message: 'Enter your VirtuOhm username:',
|
|
||||||
validate: function( value ) {
|
|
||||||
if (value.length) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return 'Please enter your username.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'password',
|
|
||||||
type: 'password',
|
|
||||||
message: 'Enter your password:',
|
|
||||||
validate: function(value) {
|
|
||||||
if (value.length) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return 'Please enter your password.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}])
|
|
||||||
.then(answers => {
|
|
||||||
ldap.init(null);
|
|
||||||
ldap.authorize(answers.username,answers.password,function(user) {
|
|
||||||
console.log(JSON.stringify(user));
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"dbConn": "mongodb://127.0.0.1:27017/om",
|
|
||||||
"dbLocalConn": "mongodb://localhost:27017/omdb",
|
|
||||||
"dbUser": "om",
|
|
||||||
"dbPwd": "aeg1phuKeDaixese",
|
|
||||||
"initialReservedTime": 120,
|
|
||||||
"httpPort": 8013,
|
|
||||||
"httpsPort": 8889
|
|
||||||
}
|
|
14
user.model.js
Normal file
14
user.model.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
|
|
||||||
|
const UserSchema = mongoose.Schema({
|
||||||
|
name: { type: String, required: true },
|
||||||
|
password: {type: String}, password: {type: String},
|
||||||
|
|
||||||
|
role: {type: String, required: true},
|
||||||
|
tags: [{type: String }],
|
||||||
|
});
|
||||||
|
//tags as index:
|
||||||
|
//UserSchema.index({tags:'text'});
|
||||||
|
|
||||||
|
module.exports = mongoose.model('User', UserSchema);
|
Loading…
x
Reference in New Issue
Block a user