1
0
Fork 0

Compare commits

...

7 Commits

10 changed files with 106 additions and 144 deletions

24
app.js
View File

@ -1,22 +1,15 @@
// GDS: Global Data System global['debug'] = (process.env.NODE_ENV === 'debug') ? true : false;
global['gds'] = {
debug: (process.env.NODE_ENV === 'debug') ? true : false,
db: null,
cache: {},
cfg: require(__dirname+'/bin/config')
};
global['modules'] = {};
global['__dirname'] = __dirname; global['__dirname'] = __dirname;
/** /**
* load modules * load modules
*/ */
let load = (name) => { const load = (name) => {
return require(__dirname+'/bin/'+name+'/module'); return require(__dirname+'/bin/'+name+'/module');
}; };
// environment variable check // environment variable check
let env_vars = ["APP_ID", "APP_SECRET"]; const env_vars = ["APP_ID", "APP_SECRET"];
let env_missing = false; let env_missing = false;
env_vars.forEach((el) => { env_vars.forEach((el) => {
if(typeof process.env[el] == 'undefined') { if(typeof process.env[el] == 'undefined') {
@ -26,14 +19,9 @@ env_vars.forEach((el) => {
}); });
if(env_missing) process.exit(); if(env_missing) process.exit();
global['modules'].logs = load('logs'); // log handler global['logs'] = load('logs'); // log handler
global['logs'] = global['modules'].logs; // alias
global['modules'].web = load('web'); // web server
global['modules'].sso = load('sso'); // sso service
// custom modules
const webServer = load('web'); // web server
// start web server // start web server
global['modules'].web.start(); webServer.start();

View File

@ -9,17 +9,18 @@ module.exports = {
}, },
web: { web: {
host: "*", host: "*",
port: 8080, port: 8081,
poweredBy: 'baseApp', poweredBy: 'baseApp',
rootUrl: '/', // '/', '/SSObaseApp' rootUrl: '/', // '/', '/SSObaseApp/'
doubleSlashCheck: true, // replacing // with / doubleSlashCheck: true, // replacing // with /
sessionKey: require('crypto').randomBytes(32).toString('hex'), sessionKey: require('crypto').randomBytes(32).toString('hex'),
cookieKey: require('crypto').randomBytes(32).toString('hex'), cookieKey: require('crypto').randomBytes(32).toString('hex'),
rememberMeMaxAge: 1000*60*60 // two weeks (milliseconds*seconds*minutes) rememberMeMaxAge: 1000*60*60 // two weeks (milliseconds*seconds*minutes)
}, },
sso: { sso: {
authenticator: "http://localhost:8080/api/authenticate", // redirect back to this url; authenticator: "http://localhost:8081/api/authenticate", // redirect back to this url;
provider: "https://auth.rxbn.de/authenticate", // sso service providerApi: "http://localhost:8080/api/authenticate", // sso service api
providerUI: "http://localhost:8080/authenticate", // sso service
appId: process.env.APP_ID, // app id appId: process.env.APP_ID, // app id
appSecret: process.env.APP_SECRET // random token appSecret: process.env.APP_SECRET // random token
}, },

View File

@ -2,12 +2,13 @@ var methods = {};
let fs = require('fs'); let fs = require('fs');
let util = require('util'); let util = require('util');
var cfg = require(global['__dirname']+'/bin/config');
// save new line to file // save new line to file
newLine = (prefix, obj) => { newLine = (prefix, obj) => {
let date = new Date(); // current date let date = new Date(); // current date
let filename = global['gds'].cfg.log.filename(); // filename let filename = cfg.log.filename(); // filename
let dir = global['gds'].cfg.log.directory(); // directory let dir = cfg.log.directory(); // directory
let path = dir + filename; // filepath let path = dir + filename; // filepath
let fs_options = { // fs options for encoding, file mode and file flag let fs_options = { // fs options for encoding, file mode and file flag
encoding: "utf8", encoding: "utf8",
@ -46,7 +47,7 @@ newLine = (prefix, obj) => {
} }
}; };
fallback = (fn, ...data) => { log = (fn, ...data) => {
if(data.length == 1) data = data[0]; if(data.length == 1) data = data[0];
fn.apply(null, data); fn.apply(null, data);
@ -55,8 +56,7 @@ fallback = (fn, ...data) => {
// LOG | INFO // LOG | INFO
methods.log = (...data) => { methods.log = (...data) => {
if(global['modules'].cli) global['modules'].cli.log.apply(global['modules'].cli, data); log(console.log, data);
else fallback(console.log, data);
if(data.length == 1) data = data[0]; if(data.length == 1) data = data[0];
newLine(" [LOG]", data); newLine(" [LOG]", data);
@ -65,8 +65,7 @@ methods.info = methods.log;
// WARNING // WARNING
methods.warn = (...data) => { methods.warn = (...data) => {
if(global['modules'].cli) global['modules'].cli.log.apply(global['modules'].cli, data); log(console.warn, data);
else fallback(console.warn, data);
if(data.length == 1) data = data[0]; if(data.length == 1) data = data[0];
newLine(" [WARN]", data); newLine(" [WARN]", data);
@ -74,8 +73,7 @@ methods.warn = (...data) => {
// ERROR // ERROR
methods.error = (...data) => { methods.error = (...data) => {
if(global['modules'].cli) global['modules'].cli.log.apply(global['modules'].cli, data); log(console.error, data);
else fallback(console.error, data);
if(data.length == 1) data = data[0]; if(data.length == 1) data = data[0];
newLine("[ERROR]", data); newLine("[ERROR]", data);
@ -84,9 +82,8 @@ methods.err = methods.error;
// DEBUG // DEBUG
methods.debug = (...data) => { methods.debug = (...data) => {
if(global['gds'].debug) { if(global['debug'] === true) {
if(global['modules'].cli) global['modules'].cli.log.apply(global['modules'].cli, data); log(console.log, data);
else fallback(console.log, data);
if(data.length == 1) data = data[0]; if(data.length == 1) data = data[0];
newLine("[DEBUG]", data); newLine("[DEBUG]", data);

View File

@ -6,42 +6,38 @@
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
var functions = {}; const methods = {};
var request = require('request'); const bent = require('bent');
var querystring = require('querystring'); const querystring = require('querystring');
const cfg = require(global['__dirname']+'/bin/config');
/** /**
* authenticate user * authenticate user
* @author Ruben Meyer * @author Ruben Meyer
* @param {Object} obj obj (userId, userToken, appId, appSecret) * @async
* @param {Function} callback obj (err, access => true, false) * @param {Object} obj obj (userId, token, appId, appSecret)
* @return {Object} callback obj (err, access => {true, false})
*/ */
functions.authenticateUser = (obj, callback) => { methods.authenticateUser = async (obj, callback) => {
if(typeof callback !== 'function') callback = function() {}; let request = bent(cfg.sso.providerApi, 'POST', 'json', 200);
request({ try {
method: 'POST', let post = await request('', {
uri: global['gds'].cfg.sso.provider,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
applicationId: obj.appId, applicationId: obj.appId,
applicationSecret: obj.appSecret, applicationSecret: obj.appSecret,
userId: obj.userId, userId: obj.userId,
token: obj.userToken token: obj.token
}) });
}, (err, res, body) => {
console.log('error:', err); // Print the error if one occurred if(post.status == 200 && post.message == "msg.auth.authentication.successful")
console.log('statusCode:', res && res.statusCode); // Print the response status code if a response was received return true;
console.log('body:', body); // Print the HTML } catch(err) {
try { // something went wrong
if(typeof body !== "object") body = JSON.parse(body); console.log(err);
return callback(err, body.access); return false;
} catch(e) { }
callback(new Error("Body is misformed"));
}
});
}; };
/** /**
@ -51,12 +47,12 @@ functions.authenticateUser = (obj, callback) => {
* @param {Object} obj obj(url, appId) * @param {Object} obj obj(url, appId)
* @param {Function} callback string(url) * @param {Function} callback string(url)
*/ */
functions.createAuthentication = (obj) => { methods.createAuthentication = (obj) => {
let nUrl = { let nUrl = {
redirectUrl: obj.url, redirectUrl: obj.url,
appId: obj.appId appId: obj.appId
}; };
return global['gds'].cfg.sso.provider+"?"+querystring.stringify(nUrl); return cfg.sso.providerUI+"?"+querystring.stringify(nUrl);
}; };
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -1,19 +1,27 @@
var express = require('express'); var express = require('express');
var route = express.Router(); var route = express.Router();
const cfg = require(global['__dirname']+'/bin/config');
route.use((req, res, next) => { route.use((req, res, next) => {
if(!req.session || !req.session.user) { if(!req.session || !req.session.user) {
if(!req.path.startsWith('/api')) { if(!req.path.startsWith('/api')) {
let path = (global['gds'].cfg.web.rootUrl+'/auth'); let path = (cfg.web.rootUrl+'/auth');
if(global['gds'].cfg.web.doubleSlashCheck) path = path.replace(/\/+/g, "/"); if(cfg.web.doubleSlashCheck) path = path.replace(/\/+/g, "/");
res.redirect(path); res.redirect(path);
} else { } else {
res.redirect('/auth'+req.path); res.redirect('/auth'+req.path);
} }
} else next(); } else {
// initialize User
if(req.session.user.initializeUser) {
// do it
req.session.user.initializeUser = false;
}
next();
}
}); });
route.get('/', (req, res) => { route.get('/', (req, res) => {

View File

@ -1,18 +1,35 @@
var express = require('express'); var express = require('express');
var route = express.Router(); var route = express.Router();
const cfg = require(global['__dirname']+'/bin/config');
const sso = require(global['__dirname']+'/bin/sso/module');
route.get('/login', (req, res) => { route.get('/login', (req, res) => {
// TODO: login // TODO: login
let a = global['modules'].sso.createAuthentication({ let a = sso.createAuthentication({
url: global['gds'].cfg.sso.authenticator, url: cfg.sso.authenticator,
appId: global['gds'].cfg.sso.appId appId: cfg.sso.appId
}); });
res.redirect(a); res.redirect(a);
}); });
route.get('/authenticate', (req, res) => { route.get('/authenticate', async (req, res) => {
// TODO: authenticate if(req.query && req.query.uid && req.query.token) {
res.end(); let auth = await sso.authenticateUser({
userId: req.query.uid,
token: req.query.token,
appId: cfg.sso.appId,
appSecret: cfg.sso.appSecret
});
if(auth) {
req.session.user = {
ssoId: req.query.uid,
initializeUser: true
};
return res.redirect(cfg.web.rootUrl);
}
else return res.redirect(cfg.web.rootUrl + 'auth/login');
}
}); });
route.get('/logout', (req, res) => { route.get('/logout', (req, res) => {
@ -31,7 +48,7 @@ route.get('/logout', (req, res) => {
} }
}); });
if(global['gds'].debug) { if(global['debug']) {
// DEBUG info // DEBUG info
route.get('/info', (req, res) => { route.get('/info', (req, res) => {
let obj = {}; let obj = {};

View File

@ -1,6 +1,7 @@
var express = require('express'); var express = require('express');
var route = express.Router(); var route = express.Router();
const cfg = require(global['__dirname']+'/bin/config');
route.all('/', function(req, res, next) { route.all('/', function(req, res, next) {
// TODO: show login page or dashboard // TODO: show login page or dashboard
@ -17,7 +18,9 @@ route.all('/*', (req, res, next) => {
// TODO: role-based authorization // TODO: role-based authorization
// TODO: show login page or page // TODO: show login page or page
res.end('500 - LEL'); res.render('auth/views/index', {
appName: cfg.app.name
});
}); });
module.exports = route; module.exports = route;

View File

@ -1,5 +1,5 @@
//- variables //- variables
- var appName = global['gds'].cfg.app.name || "SSObaseApp"; - var appName = appName || "SSObaseApp";
- var title = "Dashboard"; - var title = "Dashboard";
mixin navItem(name, id, symbol, href) mixin navItem(name, id, symbol, href)

View File

@ -1,5 +1,7 @@
// init // init
var methods = {}; const methods = {};
const cfg = require(global['__dirname']+'/bin/config');
/** /**
* start web server * start web server
@ -27,7 +29,7 @@ methods.start = () => {
// Access Control Headers // Access Control Headers
app.use( (req, res, next) => { app.use( (req, res, next) => {
res.set({ res.set({
'X-Powered-By': global['gds'].cfg 'X-Powered-By': cfg.web.poweredBy
}); });
res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
@ -39,14 +41,14 @@ methods.start = () => {
app.use(bp.urlencoded({ app.use(bp.urlencoded({
extended: true extended: true
})); }));
app.use(cp(global['gds'].cfg.web.cookieKey)); app.use(cp(cfg.web.cookieKey));
// Pretty print // Pretty print
app.locals.pretty = true; app.locals.pretty = true;
// Sessions // Sessions
session_options = { session_options = {
secret: global['gds'].cfg.web.sessionKey, secret: cfg.web.sessionKey,
resave: false, resave: false,
saveUninitialized: false, cookie: {}}; saveUninitialized: false, cookie: {}};
if(app.get('env') === 'production') { if(app.get('env') === 'production') {
@ -56,8 +58,6 @@ methods.start = () => {
//static files //static files
app.use('/res', (req, res, next) => { app.use('/res', (req, res, next) => {
if(typeof global['gds'].cache.web == 'undefined') global['gds'].cache.web = {};
let dir = global['__dirname'] + '/res/web'; let dir = global['__dirname'] + '/res/web';
@ -65,29 +65,16 @@ methods.start = () => {
else dir += '/app'; else dir += '/app';
let joined_path = path.join(dir, /^[^?]+/.exec(req.url)[0]); let joined_path = path.join(dir, /^[^?]+/.exec(req.url)[0]);
fs.exists(joined_path, (exists) => {
if(exists) {
let contentType = mime.contentType(path.extname(joined_path));
res.setHeader('Content-Type', contentType);
// path already cached; not exist fs.createReadStream(joined_path).pipe(res);
if(global['gds'].cache.web[joined_path] == false) { } else {
res.status(404).end(); res.status(404).end();
// path already cached; exist }
} else if(global['gds'].cache.web[joined_path] == true){ });
let contentType = mime.contentType(path.extname(joined_path));
res.setHeader('Content-Type', contentType);
fs.createReadStream(joined_path).pipe(res);
// check path
} else {
fs.exists(joined_path, (exists) => {
global['gds'].cache.web[joined_path] = exists;
if(exists) {
let contentType = mime.contentType(path.extname(joined_path));
res.setHeader('Content-Type', contentType);
fs.createReadStream(joined_path).pipe(res);
} else {
res.status(404).end();
}
});
}
}); });
// web routes // web routes
@ -95,44 +82,9 @@ methods.start = () => {
app.use('/', require(global['__dirname']+'/bin/web/app/routes/main')); app.use('/', require(global['__dirname']+'/bin/web/app/routes/main'));
// start server // start server
app.listen(global['gds'].cfg.web.port, () => { app.listen(cfg.web.port, () => {
global['modules'].logs.log("Server is listening on port: "+global['gds'].cfg.web.port); global['logs'].log("Server is listening on port: "+cfg.web.port);
}); });
// DEBUG OUTPUT: list all routes with HTTP method
setTimeout(function () {
function print (path, layer) {
if (layer.route) {
layer.route.stack.forEach(print.bind(null, path.concat(split(layer.route.path))))
} else if (layer.name === 'router' && layer.handle.stack) {
layer.handle.stack.forEach(print.bind(null, path.concat(split(layer.regexp))))
} else if (layer.method) {
console.log('%s /%s',
layer.method.toUpperCase(),
path.concat(split(layer.regexp)).filter(Boolean).join('/')
);
}
}
function split (thing) {
if (typeof thing === 'string') {
return thing.split('/')
} else if (thing.fast_slash) {
return ''
} else {
var match = thing.toString()
.replace('\\/?', '')
.replace('(?=\\/|$)', '$')
.match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//)
return match
? match[1].replace(/\\(.)/g, '$1').split('/')
: '<complex:' + thing.toString() + '>'
}
}
app._router.stack.forEach(print.bind(null, []))
}, 1500);
}; };
module.exports = methods; module.exports = methods;

View File

@ -6,11 +6,11 @@
"author": "rxbn_", "author": "rxbn_",
"license": "", "license": "",
"dependencies": { "dependencies": {
"bent": "^7.3.10",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"cookie-parser": "^1.4.4", "cookie-parser": "^1.4.5",
"express": "^4.17.1", "express": "^4.17.1",
"express-session": "^1.16.2", "express-session": "^1.17.1",
"pug": "^2.0.4", "pug": "^3.0.0"
"request": "^2.88.0"
} }
} }