commit d360f27ff61b1351441034c174a2241d9b3dfb92 Author: brettlangdon Date: Sat Aug 31 19:02:44 2013 -0400 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..87ae97a --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +test: + @echo "No Tests" + +.PHONY: test diff --git a/README.md b/README.md new file mode 100644 index 0000000..89bed6b --- /dev/null +++ b/README.md @@ -0,0 +1,112 @@ +YAPS Sessions +============ + +Session manager for [YAPS](https://github.com/brettlangdon/yaps.git). + +## Install +### Via NPM +```bash +npm install [-g] yaps-sessions +``` + +### Via Git +```bash +git clone git://github.com/brettlangdon/yaps-sessions.git +cd ./yaps-sessions.git +npm install +``` + +## Usage +```javascript +var yaps = require("yaps"); +var yaps_sessions = require("yaps-sessions"); + +var app = new yaps.server(); +app.registerPlugin(yaps_sessions); + +var my_plugin = function(){ + this.GET("/", function(request, server, respond){ + // this is the cookie value being set + request.session_token + // this is the raw data stored in the session, DO NOT edit this manully + // you MUST use request.sessionSet in order to trigger the data being saved + request.session + + // save a new session value + request.sessionSet("my-key", "some special value"); + // get the value back from the session this is the same as request.session.my-key + request.sessionGet("my-key"); + + respond(200, "your session data: " + JSON.stringify(request.session)); + }); +}; +app.registerPlugin(my_plugin); + +app.start(); +``` + +## Settings +```javascript +var yaps = require("yaps"); +var yaps_sessions = require("yaps-sessions"); + +var app = new yaps.server({ + // this has to be an already initalized instance with the following methods + // defaults to a built in `memory_store`, hint: do not use the built in store + // it is good enough for testing, but does not provide any method of session + // cleanup, meaning the session data for each user could potentially stay in memory + // for EVER (until the server is restarted) + // + // set: function(session_token, session_value, session_ttl) + // session_token: this is the session cookie value to store data for + // session_value: this is the raw session, e.g. {"my-key": "some session data"} + // session_ttl: number of seconds until this data is out of date + // get: function(session_token) + // session_token: the cookie value of the session to lookup + // returns: the raw session data as a js object, e.g. {"my-key": "some session data"} + // delete: function(session_token) + // session_token: this is the cookie value of the session to remove + sessionStore: my_custom_store, + + // whether or not to regenerate a users session token on each request, default is false + regenerateTokens: true, + + // method to use for generating user session tokens, default is uuid.v4() + generateToken: function(){ + return "some super secret key"; + }, + + // number of seconds until the session data should expire, default is 0 (keep forever) + // the ttl is updated every time the session is set (for every call to request.sessionSet) + sessionTTL: 3600, + + // the cookie to use to store the session token client side, default "sid" + sessionCookie: "session_id", +}); +app.start(); +``` + +## License +``` +The MIT License (MIT) + +Copyright (c) 2013 Brett Langdon (http://www.brett.is) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +``` diff --git a/index.js b/index.js new file mode 100644 index 0000000..e91801b --- /dev/null +++ b/index.js @@ -0,0 +1,62 @@ +var cookie = require("cookie"); +var uuid = require("uuid"); + +var memory_store = require("./memory_store.js"); + +var sessions = function(options){ + this.settings = options || {}; + this.settings.sessionCookie = this.settings.sessionCookie || "sid"; + this.settings.regenerateTokens = this.settings.regenerateTokens || false; + this.settings.sessionTTL = this.settings.sessionTTL || 0; + this.generateToken = this.settings.generateToken || uuid.v4; + this.sessions = options.sessionStore || new memory_store(); + + this.on("setup", this.on_setup); +}; + +sessions.prototype.on_setup = function(request, server, done){ + var self = this; + request.session_token = this.getSessionToken(request); + request.session = this.getSession(request.session_token); + + // regenerate the user session token per request + if(this.settings.regenerateTokens){ + var old_token = request.session_token; + request.session_token = this.generateToken(); + this.sessions.delete(old_token); + this.sessions.set(request.session_token, request.session, this.settings.sessionTTL); + } + + request.sessionGet = function(key){ + request.session = request.session || {}; + return request.session[key]; + }; + + request.sessionSet = function(key, value){ + request.session = request.session || {}; + request.session[key] = value; + self.sessions.set(request.session_token, request.session, self.settings.sessionTTL); + }; + + request.addHeader("Set-Cookie", cookie.serialize( + this.settings.sessionCookie, + request.session_token + )); + done(); +}; + +sessions.prototype.getSessionToken = function(request){ + var cookies = request.cookies || cookie.parse(request.headers.cookie || ""); + request.session_token = cookies[this.settings.sessionCookie]; + if(!request.session_token){ + request.session_token = this.generateToken(); + this.sessions.set(request.session_token, {}, this.settings.sessionTTL); + } + return request.session_token; +}; + +sessions.prototype.getSession = function(token){ + return this.sessions.get(token); +}; + +module.exports = sessions; diff --git a/memory_store.js b/memory_store.js new file mode 100644 index 0000000..07c1b34 --- /dev/null +++ b/memory_store.js @@ -0,0 +1,37 @@ +var memory_store = function(){ + this.sessions = {}; +}; + +memory_store.prototype.get = function(token){ + var session = this.sessions[token]; + var now = new Date().getTime(); + if(!session){ + return undefined; + } + if(session.expire && now > session.expire){ + this.sessions[token] = undefined; + return undefined; + } + return session.value; +}; + +memory_store.prototype.set = function(token, value, ttl){ + if(!token){ + return; + } + var expire = 0; + if(ttl){ + expire = new Date().getTime() + ttl; + } + var session = { + expire: expire, + value: value, + }; + this.sessions[token] = session; +}; + +memory_store.prototype.delete = function(token){ + this.sessions[token] = undefined; +}; + +module.exports = memory_store; diff --git a/package.json b/package.json new file mode 100644 index 0000000..ed0514d --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "author": "Brett Langdon (http://brett.is)", + "bugs": { + "url": "https://github.com/brettlangdon/yaps-sessions/issues" + }, + "dependencies": { + "cookie": "~0.1.0", + "uuid": "~1.4.1" + }, + "description": "Session management plugin for YAPS", + "keywords": [ + "session", + "yaps", + "http", + "server" + ], + "license": "MIT", + "main": "index.js", + "name": "yaps-sessions", + "repository": { + "type": "git", + "url": "git://github.com/brettlangdon/yaps-sessions.git" + }, + "scripts": { + "test": "make test" + }, + "version": "0.1.0" +}