UNPKG

ckn.systems.backend

Version:

CKN Systems Package for Backend

256 lines (238 loc) 10.5 kB
const fs = require('fs'); const http = require('http'); const https = require('https'); const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); const ejs = require('ejs'); const ckn = require("ckn.systems"); var CryptoJS = require("crypto-js"); ckn.initialBackend(exports); exports.getTheme = (themeName) => { return require("./themes/" + themeName); } exports.server = express(); exports.configuration = require("./ckn.systems.backend.configuration"); exports.models = {}; exports.views = [path.join(exports.configuration.themeFolder + "/templates")]; exports.apps = []; exports.themes = []; const checkParameters = () => { exports.CKN_ENVIRIONMENT_PRODUCTION = "CKN.ENVIRONMENT.PRODUCTION"; exports.CKN_ENVIRIONMENT_DEVELOPMENT = "CKN.ENVIRONMENT.DEVELOPMENT"; exports.mode = exports.CKN_ENVIRIONMENT_PRODUCTION; process.argv.forEach(arg => { if (arg.toLocaleLowerCase() == "dev") { exports.mode = exports.CKN_ENVIRIONMENT_DEVELOPMENT; } }); if (exports.mode == exports.CKN_ENVIRIONMENT_PRODUCTION) { exports.log.info("Mode is Production."); } else { exports.log.info("Mode is Developement."); } } const intialApps = () => { exports.log.info("Start to intial applications."); exports.server.use("/", express.static("public")); exports.apps.forEach(app => { var appName = app.name; exports.models[appName] = {}; exports.log.info("Intial \"" + appName + "\" application."); app.physicalPath = exports.configuration.appFolder + "/" + appName + "/"; app.startups = require(app.physicalPath + "startup.js"); app.startups.initial(app); if (app.url == null) { app.url = ""; app.rootURL = ""; } if (app.url != "") { app.url = app.url + "/"; app.rootURL = "../"; } // Setup application properties // Initial Static Public Folder const publicFolder = app.physicalPath + "public"; exports.server.use("/" + appName, express.static(publicFolder)); // Initial Models const modelFolder = path.join(app.physicalPath + "models"); fs.readdir(modelFolder, (err, files) => { files.forEach(modelFile => { exports.log.info("Loading models"); var model = require(modelFolder + "/" + modelFile); exports.mergeObject(model, exports.models[appName]); }); }); // Initial Views const viewFolder = path.join(app.physicalPath + "views"); exports.views.push(viewFolder); if (app.views != null) app.views.forEach(v => { var _viewFolder = path.join(app.physicalPath + "views/" + v); exports.views.push(_viewFolder); }); // Initial Controllers const controllers = ["controllers", "apis"]; controllers.forEach(controller => { const controllerFolder = path.join(app.physicalPath + controller); fs.readdir(controllerFolder, (err, files) => { files.forEach(controllerFile => { var controller = require(controllerFolder + "/" + controllerFile); var controllerFileNameNoJS = controllerFile.slice(0, controllerFile.length - 3).toLocaleLowerCase(); // Remove .js exports.log.info("Loading controllers from " + controllerFileNameNoJS); // Set Default values for controller if (controller.url == null) controller.url = (controllerFileNameNoJS == "default" ? "" : "" + controllerFileNameNoJS); if (controller.method == null) controller.method = "GET"; // Setup controller properties controller.physicalPath = controllerFolder + "/" + controllerFile; controller.url = app.url + controller.url; exports.log.info("Controller URL is " + controller.url) function processSession(app, controller, req, res) { var session = {}; session.url = controller.url; session.request = req; session.response = res; session.ckn = exports; session.application = app; session.controller = controller; session.configuration = exports.configuration; session.scripts = []; session.styles = []; session = initialSession(session); controller.process(session); } if (controller.method.toUpperCase() == "GET") { exports.server.get("/" + controller.url, (req, res) => { processSession(app, controller, req, res); }); } else if (controller.method.toUpperCase() == "POST") { exports.server.post("/" + controller.url, (req, res) => { processSession(app, controller, req, res); }); } else if (controller.method.toUpperCase() == "PUT") { exports.server.put("/" + controller.url, (req, res) => { processSession(app, controller, req, res); }); } }); }); }); }); } const initialSession = (_session) => { _session.send = (data) => { _session.response.send(data); }; _session.render = (theme) => { theme.prepare(_session); _session.rootPath = ""; var n = (_session.url.match(/\//g) || []).length; exports.loop(n, i => { _session.rootPath += "../"; }); _session.response.render(theme.template, _session); }; _session.cookies = { set: (key, value) => { const oneDayToSeconds = 24 * 60 * 60; _session.response.cookie(key, value, { maxAge: oneDayToSeconds, // You can't access these tokens in the client's javascript httpOnly: true, // Forces to use https in production secure: process.env.NODE_ENV === 'production' ? true : false } ); }, get: (key) => { // We extract the raw cookies from the request headers var rawCookies = _session.request.headers.cookie; if (rawCookies != null) { rawCookies = rawCookies.split('; '); // rawCookies = ['myapp=secretcookie, 'analytics_cookie=beacon;'] const parsedCookies = {}; rawCookies.forEach(rawCookie => { const parsedCookie = rawCookie.split('='); // parsedCookie = ['myapp', 'secretcookie'], ['analytics_cookie', 'beacon'] parsedCookies[parsedCookie[0]] = parsedCookie[1]; }); return parsedCookies[key]; } return null; } } _session.authenticated = (authURL) => { var auth = _session.cookies.get("CKN.AUTHENTICATION.TOKEN") != null; if (!auth) { if (authURL != null) { _session.response.redirect(authURL); } } if (auth) return _session.cookies.get("CKN.AUTHENTICATION.TOKEN"); else return null; } _session.authenticate = (info) => { var key = ''; var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var charactersLength = characters.length; for (var i = 0; i < 125; i++) { key += characters.charAt(Math.floor(Math.random() * charactersLength)); } var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(info), key + "CKN").toString(); _session.cookies.set("CKN.AUTHENTICATION", ciphertext); _session.cookies.set("CKN.AUTHENTICATION.TOKEN", key); return key; } _session.authenticatedInfo = () => { if (_session.cookies.get("CKN.AUTHENTICATION.TOKEN") == null) return null; var key = _session.cookies.get("CKN.AUTHENTICATION.TOKEN").toString(); var ciphertext = _session.cookies.get("CKN.AUTHENTICATION").toString(); ciphertext = decodeURIComponent(ciphertext); var originalText = CryptoJS.AES.decrypt(ciphertext, key + "CKN"); originalText = originalText.toString(CryptoJS.enc.Utf8); return JSON.parse(originalText); }; return _session; } const InitialBackendServer = () => { // Configure server to support JSON exports.server.use(bodyParser.json()); // Configure EJS View Engine exports.server.set('view engine', 'ejs'); // Configure EJS View Folders exports.server.set('views', exports.views); // Start to listen exports.server.listen(exports.configuration.server.port, () => { exports.log.info('Listening at http://127.0.0.1:' + exports.configuration.server.port); }); } exports.start = () => { // Load Themes const themeFolder = path.join(exports.configuration.themeFolder); fs.readdir(themeFolder, (err, files) => { files.forEach(file => { if (file.toLowerCase().endsWith(".js")) { var theme = require(themeFolder + "/" + file); theme.initial(); exports.themes[theme.name] = theme; } }); }); const appFolder = path.join(exports.configuration.appFolder); fs.readdir(appFolder, (err, files) => { files.forEach(file => { if (!file.toLowerCase().includes(".")) { exports.log.info("Load App " + file); exports.apps.push({ name: file }); } }); /* Check Evironment */ checkParameters(); /* Intial Applications */ intialApps(); /* Intial Backend Server */ InitialBackendServer(); }); }