Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

teo.js

Package Overview
Dependencies
Maintainers
1
Versions
71
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

teo.js - npm Package Compare versions

Comparing version 0.1.4 to 0.2.0

.travis.yml

17

config/config.js

@@ -13,3 +13,18 @@ // framework's main config

appDirs: ["models", "controllers"], // app's directories to read and collect files inside, on system start
appFiles: ["app.js"] // app's files to read and cache on system start
appFiles: ["app.js"], // app's files to read and cache on system start
cookie: {
keys: ["signed key"] // default signed key
},
session: {
sessionKeyName: "SID",
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
lifetime: {
session: 60 * 60 * 24 * 10 // in seconds, ten days by default
},
storageType: "memory" // only memory storage type at the moment
},
csrf: {
keyName: "_csrfToken",
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
}
};

4

core/teo.app.cache.js

@@ -7,2 +7,4 @@ /*!

var logger = require("./teo.logger");
exports = module.exports = AppCache;

@@ -27,3 +29,3 @@

} else {
console.error('Cannot add to cache: ' + key + ', val: ' + '\n' + context);
logger.error('Cannot add to cache: ' + key + ', val: ' + '\n' + context);
}

@@ -30,0 +32,0 @@ return context;

@@ -18,2 +18,4 @@ /*!

AppCache = require('./teo.app.cache'),
logger = require("./teo.logger"),
Middleware = require("./teo.middleware"),
http = require("http");

@@ -37,12 +39,14 @@

});
this.cache = new AppCache;
this.compressor = new Compressor();
// TODO: client instance on every call
this.client = new Client({app: this});
this.cache = new AppCache();
this._middleware = new Middleware();
async.series([
this.loadConfig.bind(this), this.collectAppFiles.bind(this)
], function() {
util.extend(this.config, {
});
util.extend(this.config, {});
// ----
this.compressor = new Compressor();
// TODO: client instance on every call
this.client = new Client({app: this});
// ----
process.nextTick(function(){

@@ -139,3 +143,3 @@ this.emit('app:ready', this);

if (err) {
console.error(err.message);
logger.error(err.message);
callback();

@@ -145,3 +149,3 @@ return;

if (typeof script !== 'function') {
console.error('Trying to run not a script');
logger.error('Trying to run not a script');
callback();

@@ -153,3 +157,3 @@ return;

d.on('error', function(err) {
console.error('Domain error', err.stack);
logger.error('Domain error', err.stack);
});

@@ -202,3 +206,3 @@ d.run(function() {

if ( err ) {
console.error( err.message );
logger.error(err.message);
callback( err.message, absPath );

@@ -255,3 +259,3 @@ } else {

if ( err ) {
console.error(err.message);
logger.error(err.message);
next( err );

@@ -301,3 +305,3 @@ return;

if (err) {
console.error(err);
logger.error(err);
next(null, err);

@@ -307,3 +311,3 @@ return;

if (!stat.isFile()) {
console.error('Error: not a file was found!');
logger.error('Error: not a file was found!');
next(null);

@@ -366,3 +370,3 @@ }

this.server.close(function () {
console.log('Connection closed, port: ' + config.get('port') + ' host: ' + config.get('host'));
logger.info('Connection closed, port: ' + config.get('port') + ' host: ' + config.get('host'));
callback && callback();

@@ -385,4 +389,20 @@ });

return function(req, res) {
new this.client.Factory({req: req, res: res});
var client = new this.client.Factory({req: req, res: res});
if (this._middleware.count() > 0) {
this._middleware.run(client.req, client.res, function() {
client.process.apply(client, arguments);
});
}
else {
client.process();
}
}.bind(this);
},
/**
* Middleware wrapper
* @param {Function} func
*/
middleware: function(func) {
this._middleware.add(func);
}

@@ -389,0 +409,0 @@ });

@@ -13,6 +13,5 @@ /*!

// TODO: to config
this.gripKeys = ["signed key"];
this.keys = opts.config.keys;
return new Cookies(opts.req, opts.res, this.gripKeys);
return new Cookies(opts.req, opts.res, this.keys);
};

@@ -20,3 +20,5 @@ /*!

streamer = require("./teo.client.streamer"),
Cookie = require("./teo.client.cookie");
Cookie = require("./teo.client.cookie"),
logger = require("./teo.logger"),
querystring = require("querystring");

@@ -35,3 +37,5 @@ // ---- mime types additional settings

this.routes = new Routes();
this.session = new Session();
this.session = new Session({
config: opts.app.config.get("session")
});

@@ -54,4 +58,2 @@ this.Factory = Base.extend(utils.extend(this.routes, {session: this.session}, {

this.mixinRes();
// ----
this.process();
},

@@ -61,5 +63,10 @@

* Process call
* Could be called with arguments. In this case immediate response with middleware error.
* Usage: .process() || .process(errCode) || process("Err msg") || process(code, err)
* TODO: improve
*/
process: function() {
if (arguments.length > 0) {
this.res.send.apply(this.res, this.parseProcessArgs.apply(this, arguments));
}
if (this.req.method.toLowerCase() === "post") {

@@ -74,15 +81,10 @@ var body = "";

if (contentType === "application/json") {
try {
payload = JSON.parse(body);
this.setReqBody(payload);
} catch(e) {
this.res.send(500, e.message);
return;
}
}
else {
payload = querystring.parse(body);
try {
payload = (contentType === "application/json") ? JSON.parse(body) : querystring.parse(body);
this.setReqBody(payload);
} catch(e) {
this.res.send(500, e.message);
return;
}
// ----

@@ -92,3 +94,2 @@ var csrfToken = payload[this.req.csrf.keyName];

if (csrfToken !== this.req.csrf.getToken()) {
debugger;
this.res.send(403, "Invalid CSRF token!");

@@ -171,3 +172,3 @@ return;

else { // otherwise, render layout
var cached = this.app.cache.get(this.route);
var cached = this.app.cache.get(this.route.path);
if (cached != null) {

@@ -186,3 +187,3 @@ this.res.send(cached);

if (Object.keys(this.req.params).length === 0 && this.app.config.get("cache").response === true) { // TODO AT: make caching for routes with changeable params // TODO AT: make caching for routes with changeable params
this.app.cache.add(this.route, output); // todo: cache pathname!
this.app.cache.add(this.route.path, output);
}

@@ -234,3 +235,3 @@ this.res.send(output);

if (contentType.match(/json/) && !utils.isObject(body)) {
console.warn("Sending not a object as JSON body response:", body);
logger.warn("Sending not a object as JSON body response:", body);
}

@@ -240,7 +241,8 @@

this.res.end(sendJson ?
var response = sendJson ?
this.buildRespObject(code, body) :
(utils.isString(body) ? body : http.STATUS_CODES[code])
);
(utils.isString(body) ? body : http.STATUS_CODES[code]);
this.res.end(response);
}.bind(this);

@@ -250,6 +252,17 @@ },

mixinReq: function() {
// currently, strict order here
this.req.cookie = new Cookie({req: this.req, res: this.res});
this.req.session = this.session.start({req: this.req, res: this.res});
this.req.csrf = new Csrf({req: this.req, res: this.res});
// currently, strict order of mixins here
this.req.cookie = new Cookie({
req: this.req,
res: this.res,
config: this.app.config.get("cookie")
});
this.req.session = this.session.start({
req: this.req,
res: this.res
});
this.req.csrf = new Csrf({
req: this.req,
res: this.res,
config: this.app.config.get("csrf")
});

@@ -277,2 +290,27 @@ if (this.route) { // extracted from route parsed parameters object (e.g /route/:id )

this.req.body = body;
},
/**
* Parse process method arguments
* @returns {Array}
*/
parseProcessArgs: function() {
var err = 500;
var body;
// Only error body is set // e.g. next("My err") || next(400)
if (arguments.length === 1) {
if (!+arguments[0]) {
body = arguments[0].toString();
} else {
err = +arguments[0];
}
}
// e.g. next(500, "Msg")
else {
err = +arguments[0];
body = arguments[1].toString();
}
return [err, body];
}

@@ -279,0 +317,0 @@ }));

@@ -7,17 +7,14 @@ /*!

var Sid = require("./teo.client.sid"),
_ = require("./teo.utils");
var _ = require("./teo.utils"),
crypto = require('crypto'),
Base = require("./teo.base");
/**
* CSRF module
* @extend {Sid}
* @type {*}
*/
exports = module.exports = Sid.extend({
req: null,
res: null,
keyName: "_csrfToken",
// ---- ---- ---- ----
module.exports = Base.extend({
initialize: function(opts) {
_.extend(this, opts);
_.extend(this, {
req: opts.req,
res: opts.res,
keyName: opts.config.keyName,
secret: opts.config.secret
});
this.genToken();

@@ -34,8 +31,12 @@ },

getToken: function() {
return this.req.cookie.get(this.keyName) || this[this.keyName];
return this[this.keyName] || this.req.cookie.get(this.keyName);
},
generateHash: function() { // TODO: separate module for generation of tokens, or move to utils
return crypto.createHmac('sha256', this.secret).update(Math.random().toString() + new Date).digest('hex');
},
setToken: function(token) {
// expires by session
this.req.cookie.set(this.keyName, token);
this[this.keyName] = token;
this.req.session.set("token", token);
this.req.session.set(this.keyName, token);
},

@@ -42,0 +43,0 @@ validate: function(token) {

@@ -8,3 +8,4 @@ /*!

var AppBase = require("./teo.base"),
Sid = require("./teo.client.sid");
Sid = require("./teo.client.sid"),
logger = require("./teo.logger");

@@ -21,7 +22,14 @@ // sessions

var Session = AppBase.extend({
// default storage type
storageType: "memory",
initialize: function(opts) {
// ---- configs
// only memory storage type at the moment
this.storageType = opts.config.storageType;
this.sessionKeyName = opts.config.sessionKeyName;
this.secret = opts.config.secret;
this.lifetime = opts.config.lifetime;
// ----
var Storage = this._loadStorage();
this._setStorage(Storage);
if (Storage) {
this._setStorage(Storage);
}
},

@@ -40,3 +48,3 @@

} catch(e) {
console.error("Error: cannot load session storage with type: " + this.storageType);
logger.error("Error: cannot load session storage with type: " + this.storageType);
}

@@ -67,3 +75,9 @@

start: function(opts) {
return this.constructor.start({req: opts.req, res: opts.res});
return this.constructor.start({
req: opts.req,
res: opts.res,
sessionKeyName: this.sessionKeyName,
secret: this.secret,
lifetime: this.lifetime
});
}

@@ -78,3 +92,3 @@ }, {

start: function(opts) {
var sid = new Sid({req: opts.req, res: opts.res});
var sid = new Sid(opts);
var _sid = sid.getSid();

@@ -81,0 +95,0 @@ var storage = this.storage;

@@ -15,10 +15,2 @@ /*!

var Sid = Base.extend({
req: null,
res: null,
sessionKeyName: "SID",
// TODO: to config
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
lifetime: { // in seconds
session: 60 * 60 * 24 * 10
},
httpOnly: true,

@@ -28,3 +20,8 @@ initialize: function(opts) {

req: opts.req,
res: opts.res
res: opts.res,
sessionKeyName: opts.sessionKeyName,
secret: opts.secret,
lifetime: {
session: opts.lifetime.session
}
});

@@ -31,0 +28,0 @@ this.setSid();

@@ -7,3 +7,4 @@ /*!

var fs = require('fs');
var fs = require("fs"),
logger = require("./teo.logger");

@@ -37,3 +38,3 @@ // Middleware to stream video, audio with support for different formats and device request for chunks

var chunksize = (end - start) + 1;
console.log('RANGE: ' + start + ' - ' + end + ' = ' + chunksize);
logger.log('RANGE: ' + start + ' - ' + end + ' = ' + chunksize);

@@ -53,3 +54,3 @@ file = fs.createReadStream(streamPath, {

} else {
console.log('ALL: ' + total);
logger.log('ALL: ' + total);
file = fs.createReadStream(streamPath);

@@ -65,3 +66,3 @@ res.writeHead(200, {

res.on('close', function() {
console.log('response closed');
logger.log('response closed');
if (res.openedFile) {

@@ -68,0 +69,0 @@ res.openedFile.unpipe(this);

@@ -12,3 +12,4 @@ /*!

App = require('./teo.app'),
Path = require('path');
Path = require('path'),
logger = require("./teo.logger");

@@ -23,3 +24,3 @@ var Core = Base.extend({

this._app = this.mixtureApp({ dir: this.appsDir, confDir: Path.normalize(__dirname + "/../config"), mode: this.mode }); // set flag, that it's core's app
this._app.loadConfigSync(); // (!) load config synchronously TODO: it's not required any more
// this._app.loadConfigSync(); // (!) load config synchronously TODO: it's not required any more
this.prepareApps(function() {

@@ -38,3 +39,3 @@ callback.call(this, this);

if ( err ) {
console.error( err );
logger.error( err );
callback();

@@ -143,9 +144,10 @@ return;

exitHandler: function(options, err) {
if (options.cleanup) {
console.log('cleanup');
if (options.cleanup) { // TODO: cleanup
logger.info('cleanup');
}
if (err) {
console.log(err.stack);
logger.error(err.message);
}
if (options.exit) {
logger.info("Closing Teo.js");
process.exit(err ? 1 : 0);

@@ -152,0 +154,0 @@ }

@@ -22,3 +22,15 @@ module.exports = {

delimiters: '{{ }}',
compressOutput: true
compressOutput: true,
session: {
sessionKeyName: "SID",
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
lifetime: {
session: 60 * 60 * 24 * 10 // in seconds, ten days by default
},
storageType: "memory" // only memory storage type at the moment
},
csrf: {
keyName: "_csrfToken",
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
}
};

@@ -13,3 +13,18 @@ // framework's main config

appDirs: ["models", "controllers"], // app's directories to read and collect files inside, on system start
appFiles: ["app.js"] // app's files to read and cache on system start
appFiles: ["app.js"], // app's files to read and cache on system start
cookie: {
keys: ["signed key"] // default signed key
},
session: {
sessionKeyName: "SID",
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
lifetime: {
session: 60 * 60 * 24 * 10 // in seconds, ten days by default
},
storageType: "memory" // only memory storage type at the moment
},
csrf: {
keyName: "_csrfToken",
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
}
};
{
"name": "teo.js",
"description": "Teo.js is Node.js based web-framework",
"version": "0.1.4",
"version": "0.2.0",
"author": {

@@ -51,3 +51,4 @@ "name": "Andrew Teologov",

"cookies": "~0.5.x",
"commander": "~2.6.x"
"commander": "~2.6.x",
"moment": "~2.9.x"
},

@@ -54,0 +55,0 @@ "devDependencies": {

# Teo.js
[![Travis Build Status](https://travis-ci.org/Antyfive/teo.js.svg)](https://travis-ci.org/Antyfive/teo.js)
Please, meet yet another Node.js based web-framework.

@@ -220,3 +222,20 @@

### req.params
Object of parsed url params
```javascript
client.get('/get/:id', function(req, res) {
cosole.log("My id:" + req.params.id);
});
```
### req.query
Object of parsed GET parameters
`http://localhost:3100/?myParam=1&myParam2=2`
Will parse it to `req.query` object:
```javascript
{
"myParam": "1",
"myParam2": "2"
}
```
To be continued...

@@ -23,3 +23,4 @@ /*!

req,
res;
res,
getTokenStub, generateHashSpy, setTokenSpy;

@@ -33,3 +34,15 @@ beforeEach(function(done) {

res = _res;
csrf = new Csrf({req: req, res: res});
csrf = new Csrf({
req: req,
res: res,
config: {
keyName: "_csrfToken",
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
}
});
getTokenStub = sinon.stub(csrf, "getToken");
generateHashSpy = sinon.spy(csrf, "generateHash");
setTokenSpy = sinon.spy(csrf, "setToken");
done();

@@ -54,2 +67,5 @@ });

app = null;
getTokenStub.restore();
generateHashSpy.restore();
setTokenSpy.restore();
done();

@@ -59,11 +75,61 @@ });

it('Should generate token', function() {
it('Should generate token if it isn`t exists', function() {
getTokenStub.returns(undefined);
var token = csrf.genToken();
assert.isTrue(getTokenStub.calledOnce, "Getter of token should be called");
assert.isTrue(generateHashSpy.calledOnce, "Hash should be generated");
assert.isTrue(setTokenSpy.calledOnce, "Setter of token should be called once");
});
it("Should not generate token if it exists", function() {
generateHashSpy.reset();
getTokenStub.returns("1");
var token = csrf.genToken();
assert.isTrue(getTokenStub.calledOnce, "Getter of token should be called");
assert.isFalse(generateHashSpy.called, "Hash should not be generated");
assert.isFalse(setTokenSpy.called, "Setter of token should be called");
assert.isTrue(typeof token === "string", "Token is not a string");
assert.equal(csrf.getToken(), token, "Tokens are different");
});
it("Should validate token", function() {
assert.isFalse(csrf.validate("test"), "Token not validated correctly");
});
it("Should generate hash string", function() {
assert.isString(csrf.generateHash(), "Hash should be generated");
});
it("Should set token correctly", function() {
var token = "123";
var cookieSetStub = sinon.stub(csrf.req.cookie, "set", function() {});
var sessionSetStub = sinon.stub(csrf.req.session, "set", function() {});
csrf.setToken(token);
assert.isTrue(cookieSetStub.calledOnce, "Cookie setter should be called");
assert.isTrue(sessionSetStub.calledOnce, "Session setter should be called");
assert.deepEqual(cookieSetStub.args[0], [csrf.keyName, token], "Token should be passed to cookie setter");
assert.deepEqual(sessionSetStub.args[0], [csrf.keyName, token], "Token should be passed to session setter");
cookieSetStub.restore();
sessionSetStub.restore();
});
});

@@ -10,3 +10,5 @@ /*!

var App = require(teoBase + '/teo.app'),
http = require("http");
Middleware = require(teoBase + "/teo.middleware"),
http = require("http"),
supertest = require("supertest");

@@ -105,2 +107,101 @@ describe('Testing App', function() {

});
describe("Testing Usage Of Middleware", function() {
var middlewareCountSpy, middlewareRunSpy, middlewareAddSpy,
clientProcessSpy, agent;
beforeEach(function(done) {
middlewareCountSpy = sinon.spy(Middleware.prototype, "count");
middlewareRunSpy = sinon.spy(Middleware.prototype, "run");
middlewareAddSpy = sinon.spy(Middleware.prototype, "add");
clientProcessSpy = sinon.spy(app.client.Factory.prototype, "process");
app.initServer();
app.server.on("listening", function() {
app.client.routes.get("/test/route", function(req, res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.end("okay");
});
agent = supertest.agent(app.server);
done();
});
app.listenServer();
});
afterEach(function(done) {
middlewareCountSpy.restore();
middlewareRunSpy.restore();
middlewareAddSpy.restore();
clientProcessSpy.restore();
app.stop(done);
});
it("Should not run middleware chain if it's empty", function(done) {
agent
.get('/test/route')
.expect('Content-Type', "text/plain")
.expect(200)
.end(function(err, res) {
assert.isTrue(middlewareCountSpy.calledOnce, "Middleware count should be called once");
assert.isFalse(middlewareRunSpy.called, "Middleware should not be called with if no functions were assigned");
assert.isTrue(clientProcessSpy.calledOnce, "Client request process should be called");
done(err);
});
});
it("Should add middleware", function() {
app.middleware(function(req, res, next) {
next();
});
assert.isTrue(middlewareAddSpy.calledOnce, "Middleware should be called");
assert.isFunction(middlewareAddSpy.args[0][0], "Middleware add should be called with correct arguments");
});
it("Should run middleware chain on request", function(done) {
app.middleware(function(req, res, next) {
next();
});
agent
.get('/test/route')
.expect('Content-Type', "text/plain")
.expect(200)
.end(function(err, res) {
assert.isTrue(middlewareCountSpy.calledOnce, "Middleware count should be called once");
assert.isTrue(middlewareRunSpy.calledOnce, "Middleware should not be called with if no functions were assigned");
assert.isTrue(clientProcessSpy.calledOnce, "Client request process should be called");
assert.deepEqual(clientProcessSpy.args[0], [], "Client process method should be called with correct arguments");
done(err);
});
});
});
});

@@ -168,2 +168,45 @@ /*!

});
describe("Testing Client 'process' method on request middleware", function() {
it("Should end request with passed code", function(done) {
app.middleware(function(req, res, next) {
next(403);
});
agent
.get('/test/route')
.expect(403)
.end(done);
});
it("Should end request with passed body and default middleware code", function(done) {
app.middleware(function(req, res, next) {
next("Message");
});
agent
.get('/test/route')
.expect(500, "Message")
.end(done);
});
it("Should end request with passed code and body message", function(done) {
app.middleware(function(req, res, next) {
next(404, "My message");
});
agent
.get('/test/route')
.expect(404, "My message")
.end(done);
});
});
});

@@ -21,4 +21,6 @@ /*!

beforeEach(function() {
core = new Core(params);
beforeEach(function(done) {
core = new Core(params, function() {
done();
});
});

@@ -25,0 +27,0 @@ afterEach(function() {

@@ -33,3 +33,14 @@ /* global define, describe, beforeEach, afterEach, it, assert, sinon */

res = _res;
session = new Session({req: req, res: res});
session = new Session({
req: req,
res: res,
config: {
sessionKeyName: "SID",
secret: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
lifetime: {
session: 60 * 60 * 24 * 10 // in seconds, ten days by default
},
storageType: "memory" // only memory storage type at the moment
}
});
done();

@@ -36,0 +47,0 @@ });

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc